diff options
Diffstat (limited to 'board/Marvell/octeontx2/board.c')
-rw-r--r-- | board/Marvell/octeontx2/board.c | 247 |
1 files changed, 247 insertions, 0 deletions
diff --git a/board/Marvell/octeontx2/board.c b/board/Marvell/octeontx2/board.c new file mode 100644 index 0000000..50e903d --- /dev/null +++ b/board/Marvell/octeontx2/board.c @@ -0,0 +1,247 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * https://spdx.org/licenses + */ + +#include <command.h> +#include <console.h> +#include <cpu_func.h> +#include <dm.h> +#include <dm/uclass-internal.h> +#include <env.h> +#include <init.h> +#include <malloc.h> +#include <net.h> +#include <pci_ids.h> +#include <errno.h> +#include <asm/io.h> +#include <linux/compiler.h> +#include <linux/delay.h> +#include <linux/libfdt.h> +#include <fdt_support.h> +#include <asm/arch/smc.h> +#include <asm/arch/soc.h> +#include <asm/arch/board.h> +#include <dm/util.h> + +DECLARE_GLOBAL_DATA_PTR; + +void cleanup_env_ethaddr(void) +{ + char ename[32]; + + for (int i = 0; i < 20; i++) { + sprintf(ename, i ? "eth%daddr" : "ethaddr", i); + if (env_get(ename)) + env_set(ename, NULL); + } +} + +void octeontx2_board_get_mac_addr(u8 index, u8 *mac_addr) +{ + u64 tmp_mac, board_mac_addr = fdt_get_board_mac_addr(); + static int board_mac_num; + + board_mac_num = fdt_get_board_mac_cnt(); + if ((!is_zero_ethaddr((u8 *)&board_mac_addr)) && board_mac_num) { + tmp_mac = board_mac_addr; + tmp_mac += index; + tmp_mac = swab64(tmp_mac) >> 16; + memcpy(mac_addr, (u8 *)&tmp_mac, ARP_HLEN); + board_mac_num--; + } else { + memset(mac_addr, 0, ARP_HLEN); + } + debug("%s mac %pM\n", __func__, mac_addr); +} + +void board_quiesce_devices(void) +{ + struct uclass *uc_dev; + int ret; + + /* Removes all RVU PF devices */ + ret = uclass_get(UCLASS_ETH, &uc_dev); + if (uc_dev) + ret = uclass_destroy(uc_dev); + if (ret) + printf("couldn't remove rvu pf devices\n"); + + if (IS_ENABLED(CONFIG_OCTEONTX2_CGX_INTF)) { + /* Bring down all cgx lmac links */ + cgx_intf_shutdown(); + } + + /* Removes all CGX and RVU AF devices */ + ret = uclass_get(UCLASS_MISC, &uc_dev); + if (uc_dev) + ret = uclass_destroy(uc_dev); + if (ret) + printf("couldn't remove misc (cgx/rvu_af) devices\n"); + + /* SMC call - removes all LF<->PF mappings */ + smc_disable_rvu_lfs(0); +} + +int board_early_init_r(void) +{ + pci_init(); + return 0; +} + +int board_init(void) +{ + return 0; +} + +int timer_init(void) +{ + return 0; +} + +int dram_init(void) +{ + gd->ram_size = smc_dram_size(0); + gd->ram_size -= CONFIG_SYS_SDRAM_BASE; + + mem_map_fill(); + + return 0; +} + +void board_late_probe_devices(void) +{ + struct udevice *dev; + int err, cgx_cnt = 3, i; + + /* Probe MAC(CGX) and NIC AF devices before Network stack init */ + for (i = 0; i < cgx_cnt; i++) { + err = dm_pci_find_device(PCI_VENDOR_ID_CAVIUM, + PCI_DEVICE_ID_CAVIUM_CGX, i, &dev); + if (err) + debug("%s CGX%d device not found\n", __func__, i); + } + err = dm_pci_find_device(PCI_VENDOR_ID_CAVIUM, + PCI_DEVICE_ID_CAVIUM_RVU_AF, 0, &dev); + if (err) + debug("NIC AF device not found\n"); +} + +/** + * Board late initialization routine. + */ +int board_late_init(void) +{ + char boardname[32]; + char boardserial[150], boardrev[150]; + long val; + bool save_env = false; + const char *str; + + debug("%s()\n", __func__); + + /* + * Now that pci_init initializes env device. + * Try to cleanup ethaddr env variables, this is needed + * as with each boot, configuration of QLM can change. + */ + cleanup_env_ethaddr(); + + snprintf(boardname, sizeof(boardname), "%s> ", fdt_get_board_model()); + env_set("prompt", boardname); + set_working_fdt_addr(env_get_hex("fdtcontroladdr", fdt_base_addr)); + + str = fdt_get_board_revision(); + if (str) { + snprintf(boardrev, sizeof(boardrev), "%s", str); + if (env_get("boardrev") && + strcmp(boardrev, env_get("boardrev"))) + save_env = true; + env_set("boardrev", boardrev); + } + + str = fdt_get_board_serial(); + if (str) { + snprintf(boardserial, sizeof(boardserial), "%s", str); + if (env_get("serial#") && + strcmp(boardserial, env_get("serial#"))) + save_env = true; + env_set("serial#", boardserial); + } + + val = env_get_hex("disable_ooo", 0); + smc_configure_ooo(val); + + if (IS_ENABLED(CONFIG_NET_OCTEONTX2)) + board_late_probe_devices(); + + if (save_env) + env_save(); + + return 0; +} + +/* + * Invoked before relocation, so limit to stack variables. + */ +int checkboard(void) +{ + printf("Board: %s\n", fdt_get_board_model()); + + return 0; +} + +void board_acquire_flash_arb(bool acquire) +{ + union cpc_boot_ownerx ownerx; + + if (!acquire) { + ownerx.u = readl(CPC_BOOT_OWNERX(3)); + ownerx.s.boot_req = 0; + writel(ownerx.u, CPC_BOOT_OWNERX(3)); + } else { + ownerx.u = 0; + ownerx.s.boot_req = 1; + writel(ownerx.u, CPC_BOOT_OWNERX(3)); + udelay(1); + do { + ownerx.u = readl(CPC_BOOT_OWNERX(3)); + } while (ownerx.s.boot_wait); + } +} + +int last_stage_init(void) +{ + (void)smc_flsf_fw_booted(); + return 0; +} + +static int do_go_uboot(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + typedef void __noreturn (*uboot_entry_t)(ulong, void *); + uboot_entry_t entry; + ulong addr; + void *fdt; + + if (argc < 2) + return CMD_RET_USAGE; + + addr = simple_strtoul(argv[1], NULL, 16); + fdt = board_fdt_blob_setup(); + entry = (uboot_entry_t)addr; + flush_cache((ulong)addr, 1 << 20); /* 1MiB should be enough */ + dcache_disable(); + + printf("## Starting U-Boot at %p (FDT at %p)...\n", entry, fdt); + + entry(0, fdt); + + return 0; +} + +U_BOOT_CMD(go_uboot, 2, 0, do_go_uboot, + "Start U-Boot from RAM (pass FDT via x1 register)", + ""); |