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> 12#include <asm/global_data.h> 13#include <dm/uclass-internal.h> 14#include <env.h> 15#include <event.h> 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 31DECLARE_GLOBAL_DATA_PTR; 32 33void 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 44void 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 62void 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 90int board_early_init_r(void) 91{ 92 pci_init(); 93 return 0; 94} 95 96int board_init(void) 97{ 98 return 0; 99} 100 101int timer_init(void) 102{ 103 return 0; 104} 105 106int dram_init(void) 107{ 108 gd->ram_size = smc_dram_size(0); 109 gd->ram_size -= CFG_SYS_SDRAM_BASE; 110 111 mem_map_fill(); 112 113 return 0; 114} 115 116void 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 */ 137int 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 */ 191int checkboard(void) 192{ 193 printf("Board: %s\n", fdt_get_board_model()); 194 195 return 0; 196} 197 198void 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 217static int last_stage_init(void) 218{ 219 (void)smc_flsf_fw_booted(); 220 return 0; 221} 222EVENT_SPY_SIMPLE(EVT_LAST_STAGE_INIT, last_stage_init); 223 224static 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; 231 int err; 232 233 if (argc < 2) 234 return CMD_RET_USAGE; 235 236 addr = hextoul(argv[1], NULL); 237 fdt = board_fdt_blob_setup(&err); 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 249U_BOOT_CMD(go_uboot, 2, 0, do_go_uboot, 250 "Start U-Boot from RAM (pass FDT via x1 register)", 251 ""); 252