Suneel Garapati | d9e7246 | 2019-10-19 18:47:37 -0700 | [diff] [blame] | 1 | // SPDX-License-Identifier: GPL-2.0 |
| 2 | /* |
| 3 | * Copyright (C) 2018 Marvell International Ltd. |
| 4 | * |
| 5 | * https://spdx.org/licenses |
| 6 | */ |
| 7 | |
| 8 | #include <command.h> |
| 9 | #include <console.h> |
| 10 | #include <cpu_func.h> |
| 11 | #include <dm.h> |
Simon Glass | 3ba929a | 2020-10-30 21:38:53 -0600 | [diff] [blame] | 12 | #include <asm/global_data.h> |
Suneel Garapati | d9e7246 | 2019-10-19 18:47:37 -0700 | [diff] [blame] | 13 | #include <dm/uclass-internal.h> |
| 14 | #include <env.h> |
Simon Glass | 1cedca1 | 2023-08-21 21:17:01 -0600 | [diff] [blame] | 15 | #include <event.h> |
Suneel Garapati | d9e7246 | 2019-10-19 18:47:37 -0700 | [diff] [blame] | 16 | #include <init.h> |
| 17 | #include <malloc.h> |
| 18 | #include <net.h> |
| 19 | #include <pci_ids.h> |
| 20 | #include <errno.h> |
| 21 | #include <asm/io.h> |
| 22 | #include <linux/compiler.h> |
| 23 | #include <linux/delay.h> |
| 24 | #include <linux/libfdt.h> |
| 25 | #include <fdt_support.h> |
| 26 | #include <asm/arch/smc.h> |
| 27 | #include <asm/arch/soc.h> |
| 28 | #include <asm/arch/board.h> |
| 29 | #include <dm/util.h> |
| 30 | |
| 31 | DECLARE_GLOBAL_DATA_PTR; |
| 32 | |
| 33 | void cleanup_env_ethaddr(void) |
| 34 | { |
| 35 | char ename[32]; |
| 36 | |
| 37 | for (int i = 0; i < 20; i++) { |
| 38 | sprintf(ename, i ? "eth%daddr" : "ethaddr", i); |
| 39 | if (env_get(ename)) |
| 40 | env_set(ename, NULL); |
| 41 | } |
| 42 | } |
| 43 | |
| 44 | void octeontx2_board_get_mac_addr(u8 index, u8 *mac_addr) |
| 45 | { |
| 46 | u64 tmp_mac, board_mac_addr = fdt_get_board_mac_addr(); |
| 47 | static int board_mac_num; |
| 48 | |
| 49 | board_mac_num = fdt_get_board_mac_cnt(); |
| 50 | if ((!is_zero_ethaddr((u8 *)&board_mac_addr)) && board_mac_num) { |
| 51 | tmp_mac = board_mac_addr; |
| 52 | tmp_mac += index; |
| 53 | tmp_mac = swab64(tmp_mac) >> 16; |
| 54 | memcpy(mac_addr, (u8 *)&tmp_mac, ARP_HLEN); |
| 55 | board_mac_num--; |
| 56 | } else { |
| 57 | memset(mac_addr, 0, ARP_HLEN); |
| 58 | } |
| 59 | debug("%s mac %pM\n", __func__, mac_addr); |
| 60 | } |
| 61 | |
| 62 | void board_quiesce_devices(void) |
| 63 | { |
| 64 | struct uclass *uc_dev; |
| 65 | int ret; |
| 66 | |
| 67 | /* Removes all RVU PF devices */ |
| 68 | ret = uclass_get(UCLASS_ETH, &uc_dev); |
| 69 | if (uc_dev) |
| 70 | ret = uclass_destroy(uc_dev); |
| 71 | if (ret) |
| 72 | printf("couldn't remove rvu pf devices\n"); |
| 73 | |
| 74 | if (IS_ENABLED(CONFIG_OCTEONTX2_CGX_INTF)) { |
| 75 | /* Bring down all cgx lmac links */ |
| 76 | cgx_intf_shutdown(); |
| 77 | } |
| 78 | |
| 79 | /* Removes all CGX and RVU AF devices */ |
| 80 | ret = uclass_get(UCLASS_MISC, &uc_dev); |
| 81 | if (uc_dev) |
| 82 | ret = uclass_destroy(uc_dev); |
| 83 | if (ret) |
| 84 | printf("couldn't remove misc (cgx/rvu_af) devices\n"); |
| 85 | |
| 86 | /* SMC call - removes all LF<->PF mappings */ |
| 87 | smc_disable_rvu_lfs(0); |
| 88 | } |
| 89 | |
| 90 | int board_early_init_r(void) |
| 91 | { |
| 92 | pci_init(); |
| 93 | return 0; |
| 94 | } |
| 95 | |
| 96 | int board_init(void) |
| 97 | { |
| 98 | return 0; |
| 99 | } |
| 100 | |
| 101 | int timer_init(void) |
| 102 | { |
| 103 | return 0; |
| 104 | } |
| 105 | |
| 106 | int dram_init(void) |
| 107 | { |
| 108 | gd->ram_size = smc_dram_size(0); |
Tom Rini | bb4dd96 | 2022-11-16 13:10:37 -0500 | [diff] [blame] | 109 | gd->ram_size -= CFG_SYS_SDRAM_BASE; |
Suneel Garapati | d9e7246 | 2019-10-19 18:47:37 -0700 | [diff] [blame] | 110 | |
| 111 | mem_map_fill(); |
| 112 | |
| 113 | return 0; |
| 114 | } |
| 115 | |
| 116 | void board_late_probe_devices(void) |
| 117 | { |
| 118 | struct udevice *dev; |
| 119 | int err, cgx_cnt = 3, i; |
| 120 | |
| 121 | /* Probe MAC(CGX) and NIC AF devices before Network stack init */ |
| 122 | for (i = 0; i < cgx_cnt; i++) { |
| 123 | err = dm_pci_find_device(PCI_VENDOR_ID_CAVIUM, |
| 124 | PCI_DEVICE_ID_CAVIUM_CGX, i, &dev); |
| 125 | if (err) |
| 126 | debug("%s CGX%d device not found\n", __func__, i); |
| 127 | } |
| 128 | err = dm_pci_find_device(PCI_VENDOR_ID_CAVIUM, |
| 129 | PCI_DEVICE_ID_CAVIUM_RVU_AF, 0, &dev); |
| 130 | if (err) |
| 131 | debug("NIC AF device not found\n"); |
| 132 | } |
| 133 | |
| 134 | /** |
| 135 | * Board late initialization routine. |
| 136 | */ |
| 137 | int board_late_init(void) |
| 138 | { |
| 139 | char boardname[32]; |
| 140 | char boardserial[150], boardrev[150]; |
| 141 | long val; |
| 142 | bool save_env = false; |
| 143 | const char *str; |
| 144 | |
| 145 | debug("%s()\n", __func__); |
| 146 | |
| 147 | /* |
| 148 | * Now that pci_init initializes env device. |
| 149 | * Try to cleanup ethaddr env variables, this is needed |
| 150 | * as with each boot, configuration of QLM can change. |
| 151 | */ |
| 152 | cleanup_env_ethaddr(); |
| 153 | |
| 154 | snprintf(boardname, sizeof(boardname), "%s> ", fdt_get_board_model()); |
| 155 | env_set("prompt", boardname); |
| 156 | set_working_fdt_addr(env_get_hex("fdtcontroladdr", fdt_base_addr)); |
| 157 | |
| 158 | str = fdt_get_board_revision(); |
| 159 | if (str) { |
| 160 | snprintf(boardrev, sizeof(boardrev), "%s", str); |
| 161 | if (env_get("boardrev") && |
| 162 | strcmp(boardrev, env_get("boardrev"))) |
| 163 | save_env = true; |
| 164 | env_set("boardrev", boardrev); |
| 165 | } |
| 166 | |
| 167 | str = fdt_get_board_serial(); |
| 168 | if (str) { |
| 169 | snprintf(boardserial, sizeof(boardserial), "%s", str); |
| 170 | if (env_get("serial#") && |
| 171 | strcmp(boardserial, env_get("serial#"))) |
| 172 | save_env = true; |
| 173 | env_set("serial#", boardserial); |
| 174 | } |
| 175 | |
| 176 | val = env_get_hex("disable_ooo", 0); |
| 177 | smc_configure_ooo(val); |
| 178 | |
| 179 | if (IS_ENABLED(CONFIG_NET_OCTEONTX2)) |
| 180 | board_late_probe_devices(); |
| 181 | |
| 182 | if (save_env) |
| 183 | env_save(); |
| 184 | |
| 185 | return 0; |
| 186 | } |
| 187 | |
| 188 | /* |
| 189 | * Invoked before relocation, so limit to stack variables. |
| 190 | */ |
| 191 | int checkboard(void) |
| 192 | { |
| 193 | printf("Board: %s\n", fdt_get_board_model()); |
| 194 | |
| 195 | return 0; |
| 196 | } |
| 197 | |
| 198 | void board_acquire_flash_arb(bool acquire) |
| 199 | { |
| 200 | union cpc_boot_ownerx ownerx; |
| 201 | |
| 202 | if (!acquire) { |
| 203 | ownerx.u = readl(CPC_BOOT_OWNERX(3)); |
| 204 | ownerx.s.boot_req = 0; |
| 205 | writel(ownerx.u, CPC_BOOT_OWNERX(3)); |
| 206 | } else { |
| 207 | ownerx.u = 0; |
| 208 | ownerx.s.boot_req = 1; |
| 209 | writel(ownerx.u, CPC_BOOT_OWNERX(3)); |
| 210 | udelay(1); |
| 211 | do { |
| 212 | ownerx.u = readl(CPC_BOOT_OWNERX(3)); |
| 213 | } while (ownerx.s.boot_wait); |
| 214 | } |
| 215 | } |
| 216 | |
Simon Glass | 1cedca1 | 2023-08-21 21:17:01 -0600 | [diff] [blame] | 217 | static int last_stage_init(void) |
Suneel Garapati | d9e7246 | 2019-10-19 18:47:37 -0700 | [diff] [blame] | 218 | { |
| 219 | (void)smc_flsf_fw_booted(); |
| 220 | return 0; |
| 221 | } |
Simon Glass | 1cedca1 | 2023-08-21 21:17:01 -0600 | [diff] [blame] | 222 | EVENT_SPY_SIMPLE(EVT_LAST_STAGE_INIT, last_stage_init); |
Suneel Garapati | d9e7246 | 2019-10-19 18:47:37 -0700 | [diff] [blame] | 223 | |
| 224 | static int do_go_uboot(struct cmd_tbl *cmdtp, int flag, int argc, |
| 225 | char *const argv[]) |
| 226 | { |
| 227 | typedef void __noreturn (*uboot_entry_t)(ulong, void *); |
| 228 | uboot_entry_t entry; |
| 229 | ulong addr; |
| 230 | void *fdt; |
Ilias Apalodimas | ab5348a | 2021-10-26 09:12:33 +0300 | [diff] [blame] | 231 | int err; |
Suneel Garapati | d9e7246 | 2019-10-19 18:47:37 -0700 | [diff] [blame] | 232 | |
| 233 | if (argc < 2) |
| 234 | return CMD_RET_USAGE; |
| 235 | |
Simon Glass | 3ff49ec | 2021-07-24 09:03:29 -0600 | [diff] [blame] | 236 | addr = hextoul(argv[1], NULL); |
Ilias Apalodimas | ab5348a | 2021-10-26 09:12:33 +0300 | [diff] [blame] | 237 | fdt = board_fdt_blob_setup(&err); |
Suneel Garapati | d9e7246 | 2019-10-19 18:47:37 -0700 | [diff] [blame] | 238 | entry = (uboot_entry_t)addr; |
| 239 | flush_cache((ulong)addr, 1 << 20); /* 1MiB should be enough */ |
| 240 | dcache_disable(); |
| 241 | |
| 242 | printf("## Starting U-Boot at %p (FDT at %p)...\n", entry, fdt); |
| 243 | |
| 244 | entry(0, fdt); |
| 245 | |
| 246 | return 0; |
| 247 | } |
| 248 | |
| 249 | U_BOOT_CMD(go_uboot, 2, 0, do_go_uboot, |
| 250 | "Start U-Boot from RAM (pass FDT via x1 register)", |
| 251 | ""); |