From 0a668f6d38a2a631eb872f4f1107399db46b1c15 Mon Sep 17 00:00:00 2001 From: Suneel Garapati Date: Sat, 19 Oct 2019 18:47:37 -0700 Subject: arm: octeontx2: Add support for OcteonTX2 SoC platforms This patch adds support for all OcteonTX2 96xx/95xx boards from Marvell. For 96xx boards, use octeontx_96xx_defconfig and for 95xx boards, use octeontx_95xx_defconfig. Signed-off-by: Suneel Garapati --- board/Marvell/octeontx2/Kconfig | 14 ++ board/Marvell/octeontx2/MAINTAINERS | 8 ++ board/Marvell/octeontx2/Makefile | 9 ++ board/Marvell/octeontx2/board-fdt.c | 221 ++++++++++++++++++++++++++++++++ board/Marvell/octeontx2/board.c | 247 ++++++++++++++++++++++++++++++++++++ board/Marvell/octeontx2/smc.c | 58 +++++++++ board/Marvell/octeontx2/soc-utils.c | 49 +++++++ 7 files changed, 606 insertions(+) create mode 100644 board/Marvell/octeontx2/Kconfig create mode 100644 board/Marvell/octeontx2/MAINTAINERS create mode 100644 board/Marvell/octeontx2/Makefile create mode 100644 board/Marvell/octeontx2/board-fdt.c create mode 100644 board/Marvell/octeontx2/board.c create mode 100644 board/Marvell/octeontx2/smc.c create mode 100644 board/Marvell/octeontx2/soc-utils.c (limited to 'board') diff --git a/board/Marvell/octeontx2/Kconfig b/board/Marvell/octeontx2/Kconfig new file mode 100644 index 0000000000..99291d795b --- /dev/null +++ b/board/Marvell/octeontx2/Kconfig @@ -0,0 +1,14 @@ +if TARGET_OCTEONTX2_95XX || TARGET_OCTEONTX2_96XX + +config SYS_VENDOR + string + default "Marvell" + +config SYS_BOARD + string + default "octeontx2" + +config SYS_CONFIG_NAME + default "octeontx2_common" + +endif diff --git a/board/Marvell/octeontx2/MAINTAINERS b/board/Marvell/octeontx2/MAINTAINERS new file mode 100644 index 0000000000..eec1d77dd1 --- /dev/null +++ b/board/Marvell/octeontx2/MAINTAINERS @@ -0,0 +1,8 @@ +OCTEONTX2 BOARD +M: Aaron Williams +S: Maintained +F: board/Marvell/octeontx2/ +F: include/configs/octeontx2_96xx.h +F: include/configs/octeontx2_95xx.h +F: configs/octeontx2_96xx_defconfig +F: configs/octeontx2_95xx_defconfig diff --git a/board/Marvell/octeontx2/Makefile b/board/Marvell/octeontx2/Makefile new file mode 100644 index 0000000000..1f763b197b --- /dev/null +++ b/board/Marvell/octeontx2/Makefile @@ -0,0 +1,9 @@ +#/* SPDX-License-Identifier: GPL-2.0 +# * +# * Copyright (C) 2018 Marvell International Ltd. +# * +# * https://spdx.org/licenses +# */ + +obj-y := board.o smc.o soc-utils.o +obj-$(CONFIG_OF_LIBFDT) += board-fdt.o diff --git a/board/Marvell/octeontx2/board-fdt.c b/board/Marvell/octeontx2/board-fdt.c new file mode 100644 index 0000000000..a4771af4c1 --- /dev/null +++ b/board/Marvell/octeontx2/board-fdt.c @@ -0,0 +1,221 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * https://spdx.org/licenses + */ + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +static int fdt_get_bdk_node(void) +{ + int node, ret; + const void *fdt = gd->fdt_blob; + + if (!fdt) { + printf("ERROR: %s: no valid device tree found\n", __func__); + return 0; + } + + ret = fdt_check_header(fdt); + if (ret < 0) { + printf("fdt: %s\n", fdt_strerror(ret)); + return 0; + } + + node = fdt_path_offset(fdt, "/cavium,bdk"); + if (node < 0) { + printf("%s: /cavium,bdk is missing from device tree: %s\n", + __func__, fdt_strerror(node)); + return 0; + } + return node; +} + +u64 fdt_get_board_mac_addr(void) +{ + int node, len = 16; + const char *str = NULL; + const void *fdt = gd->fdt_blob; + u64 mac_addr = 0; + + node = fdt_get_bdk_node(); + if (!node) + return mac_addr; + str = fdt_getprop(fdt, node, "BOARD-MAC-ADDRESS", &len); + if (str) + mac_addr = simple_strtol(str, NULL, 16); + return mac_addr; +} + +int fdt_get_board_mac_cnt(void) +{ + int node, len = 16; + const char *str = NULL; + const void *fdt = gd->fdt_blob; + int mac_count = 0; + + node = fdt_get_bdk_node(); + if (!node) + return mac_count; + str = fdt_getprop(fdt, node, "BOARD-MAC-ADDRESS-NUM", &len); + if (str) { + mac_count = simple_strtol(str, NULL, 10); + if (!mac_count) + mac_count = simple_strtol(str, NULL, 16); + debug("fdt: MAC_NUM %d\n", mac_count); + } else { + printf("Error: cannot retrieve mac count prop from fdt\n"); + } + str = fdt_getprop(gd->fdt_blob, node, "BOARD-MAC-ADDRESS-NUM-OVERRIDE", + &len); + if (str) { + if (simple_strtol(str, NULL, 10) >= 0) + mac_count = simple_strtol(str, NULL, 10); + debug("fdt: MAC_NUM %d\n", mac_count); + } else { + printf("Error: cannot retrieve mac num override prop\n"); + } + return mac_count; +} + +const char *fdt_get_board_serial(void) +{ + const void *fdt = gd->fdt_blob; + int node, len = 64; + const char *str = NULL; + + node = fdt_get_bdk_node(); + if (!node) + return NULL; + + str = fdt_getprop(fdt, node, "BOARD-SERIAL", &len); + if (!str) + printf("Error: cannot retrieve board serial from fdt\n"); + return str; +} + +const char *fdt_get_board_revision(void) +{ + const void *fdt = gd->fdt_blob; + int node, len = 64; + const char *str = NULL; + + node = fdt_get_bdk_node(); + if (!node) + return NULL; + + str = fdt_getprop(fdt, node, "BOARD-REVISION", &len); + if (!str) + printf("Error: cannot retrieve board revision from fdt\n"); + return str; +} + +const char *fdt_get_board_model(void) +{ + int node, len = 16; + const char *str = NULL; + const void *fdt = gd->fdt_blob; + + node = fdt_get_bdk_node(); + if (!node) + return NULL; + str = fdt_getprop(fdt, node, "BOARD-MODEL", &len); + if (!str) + printf("Error: cannot retrieve board model from fdt\n"); + return str; +} + +int arch_fixup_memory_node(void *blob) +{ + return 0; +} + +int ft_board_setup(void *blob, struct bd_info *bd) +{ + int nodeoff, node, ret, i; + const char *temp; + + static const char * const + octeontx_brd_nodes[] = {"BOARD-MODEL", + "BOARD-SERIAL", + "BOARD-MAC-ADDRESS", + "BOARD-REVISION", + "BOARD-MAC-ADDRESS-NUM" + }; + char nodes[ARRAY_SIZE(octeontx_brd_nodes)][32]; + + ret = fdt_check_header(blob); + if (ret < 0) { + printf("ERROR: %s\n", fdt_strerror(ret)); + return ret; + } + + if (blob) { + nodeoff = fdt_path_offset(blob, "/cavium,bdk"); + if (nodeoff < 0) { + printf("ERROR: FDT BDK node not found\n"); + return nodeoff; + } + + /* Read properties in temporary variables */ + for (i = 0; i < ARRAY_SIZE(octeontx_brd_nodes); i++) { + temp = fdt_getprop(blob, nodeoff, + octeontx_brd_nodes[i], NULL); + strncpy(nodes[i], temp, sizeof(nodes[i])); + } + + /* Delete cavium,bdk node */ + ret = fdt_del_node(blob, nodeoff); + if (ret < 0) { + printf("WARNING : could not remove cavium, bdk node\n"); + return ret; + } + debug("%s deleted 'cavium,bdk' node\n", __func__); + /* + * Add a new node at root level which would have + * necessary info + */ + node = fdt_add_subnode(blob, 0, "octeontx_brd"); + if (node < 0) { + printf("Cannot create node octeontx_brd: %s\n", + fdt_strerror(node)); + return -EIO; + } + + /* Populate properties in node */ + for (i = 0; i < ARRAY_SIZE(octeontx_brd_nodes); i++) { + if (fdt_setprop_string(blob, node, + octeontx_brd_nodes[i], + nodes[i])) { + printf("Can't set %s\n", nodes[i]); + return -EIO; + } + } + } + + return 0; +} + +/** + * Return the FDT base address that was passed by ATF + * + * @return FDT base address received from ATF in x1 register + */ +void *board_fdt_blob_setup(void) +{ + return (void *)fdt_base_addr; +} diff --git a/board/Marvell/octeontx2/board.c b/board/Marvell/octeontx2/board.c new file mode 100644 index 0000000000..50e903d9aa --- /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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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)", + ""); diff --git a/board/Marvell/octeontx2/smc.c b/board/Marvell/octeontx2/smc.c new file mode 100644 index 0000000000..9e3169576c --- /dev/null +++ b/board/Marvell/octeontx2/smc.c @@ -0,0 +1,58 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * https://spdx.org/licenses + */ + +#include +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +ssize_t smc_dram_size(unsigned int node) +{ + struct pt_regs regs; + + regs.regs[0] = OCTEONTX2_DRAM_SIZE; + regs.regs[1] = node; + smc_call(®s); + + return regs.regs[0]; +} + +ssize_t smc_disable_rvu_lfs(unsigned int node) +{ + struct pt_regs regs; + + regs.regs[0] = OCTEONTX2_DISABLE_RVU_LFS; + regs.regs[1] = node; + smc_call(®s); + + return regs.regs[0]; +} + +ssize_t smc_configure_ooo(unsigned int val) +{ + struct pt_regs regs; + + regs.regs[0] = OCTEONTX2_CONFIG_OOO; + regs.regs[1] = val; + smc_call(®s); + + return regs.regs[0]; +} + +ssize_t smc_flsf_fw_booted(void) +{ + struct pt_regs regs; + + regs.regs[0] = OCTEONTX2_FSAFE_PR_BOOT_SUCCESS; + smc_call(®s); + + return regs.regs[0]; +} diff --git a/board/Marvell/octeontx2/soc-utils.c b/board/Marvell/octeontx2/soc-utils.c new file mode 100644 index 0000000000..1cba7fb596 --- /dev/null +++ b/board/Marvell/octeontx2/soc-utils.c @@ -0,0 +1,49 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2019 Marvell International Ltd. + * + * https://spdx.org/licenses + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int read_platform(void) +{ + int plat = PLATFORM_HW; + + const char *model = fdt_get_board_model(); + + if (model && !strncmp(model, "ASIM-", 5)) + plat = PLATFORM_ASIM; + if (model && !strncmp(model, "EMUL-", 5)) + plat = PLATFORM_EMULATOR; + + return plat; +} + +static inline u64 read_midr(void) +{ + u64 result; + + asm ("mrs %[rd],MIDR_EL1" : [rd] "=r" (result)); + return result; +} + +u8 read_partnum(void) +{ + return ((read_midr() >> 4) & 0xFF); +} + +const char *read_board_name(void) +{ + return fdt_get_board_model(); +} + -- cgit