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