diff options
author | Tom Rini <trini@konsulko.com> | 2020-08-25 10:24:40 -0400 |
---|---|---|
committer | Tom Rini <trini@konsulko.com> | 2020-08-25 13:38:29 -0400 |
commit | 9f9ecd3e4d7839e24c182fb7b24937e19b670f1b (patch) | |
tree | 4250ad58dba47ae6127d4129b9a19dc648fd064d /board | |
parent | ec54217ddc6f52f3b7dad7a3fd6d8a3abd64ab7e (diff) | |
parent | 6944937f9c4d21f39dd257bce7b677a0f6849cea (diff) |
Merge https://gitlab.denx.de/u-boot/custodians/u-boot-marvell
- Add basic Marvell/Cavium OcteonTX/TX2 support (Suneel)
- Infrastructure changes to PCI uclass to support these SoC's (Suneel)
- Add PCI, MMC & watchdog driver drivers for OcteonTX/TX2 (Suneel)
- Increase CONFIG_SYS_MALLOC_F_LEN for qemu-x86 (Stefan)
Diffstat (limited to 'board')
-rw-r--r-- | board/Marvell/octeontx/Kconfig | 14 | ||||
-rw-r--r-- | board/Marvell/octeontx/MAINTAINERS | 8 | ||||
-rw-r--r-- | board/Marvell/octeontx/Makefile | 9 | ||||
-rw-r--r-- | board/Marvell/octeontx/board-fdt.c | 311 | ||||
-rw-r--r-- | board/Marvell/octeontx/board.c | 152 | ||||
-rw-r--r-- | board/Marvell/octeontx/smc.c | 25 | ||||
-rw-r--r-- | board/Marvell/octeontx/soc-utils.c | 50 | ||||
-rw-r--r-- | board/Marvell/octeontx2/Kconfig | 14 | ||||
-rw-r--r-- | board/Marvell/octeontx2/MAINTAINERS | 8 | ||||
-rw-r--r-- | board/Marvell/octeontx2/Makefile | 9 | ||||
-rw-r--r-- | board/Marvell/octeontx2/board-fdt.c | 221 | ||||
-rw-r--r-- | board/Marvell/octeontx2/board.c | 247 | ||||
-rw-r--r-- | board/Marvell/octeontx2/smc.c | 58 | ||||
-rw-r--r-- | board/Marvell/octeontx2/soc-utils.c | 49 | ||||
-rw-r--r-- | board/renesas/rcar-common/common.c | 47 |
15 files changed, 1175 insertions, 47 deletions
diff --git a/board/Marvell/octeontx/Kconfig b/board/Marvell/octeontx/Kconfig new file mode 100644 index 0000000000..45d115916c --- /dev/null +++ b/board/Marvell/octeontx/Kconfig @@ -0,0 +1,14 @@ +if TARGET_OCTEONTX_81XX || TARGET_OCTEONTX_83XX + +config SYS_VENDOR + string + default "Marvell" + +config SYS_BOARD + string + default "octeontx" + +config SYS_CONFIG_NAME + default "octeontx_common" + +endif diff --git a/board/Marvell/octeontx/MAINTAINERS b/board/Marvell/octeontx/MAINTAINERS new file mode 100644 index 0000000000..1f3b12b1ab --- /dev/null +++ b/board/Marvell/octeontx/MAINTAINERS @@ -0,0 +1,8 @@ +OCTEONTX BOARD +M: Aaron Williams <awilliams@marvell.com> +S: Maintained +F: board/Marvell/octeontx/ +F: include/configs/octeontx_81xx.h +F: include/configs/octeontx_83xx.h +F: configs/octeontx_81xx_defconfig +F: configs/octeontx_83xx_defconfig diff --git a/board/Marvell/octeontx/Makefile b/board/Marvell/octeontx/Makefile new file mode 100644 index 0000000000..fbe32ae003 --- /dev/null +++ b/board/Marvell/octeontx/Makefile @@ -0,0 +1,9 @@ +#/* +# * Copyright (C) 2018 Marvell International Ltd. +# * +# * SPDX-License-Identifier: GPL-2.0 +# * 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/octeontx/board-fdt.c b/board/Marvell/octeontx/board-fdt.c new file mode 100644 index 0000000000..0b05ef11e9 --- /dev/null +++ b/board/Marvell/octeontx/board-fdt.c @@ -0,0 +1,311 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * https://spdx.org/licenses + */ + +#include <errno.h> +#include <env.h> +#include <log.h> +#include <net.h> +#include <asm/io.h> +#include <linux/compiler.h> +#include <linux/libfdt.h> +#include <fdtdec.h> +#include <fdt_support.h> +#include <asm/arch/board.h> +#include <asm/global_data.h> + +DECLARE_GLOBAL_DATA_PTR; + +static int fdt_get_mdio_bus(const void *fdt, int phy_offset) +{ + int node, bus = -1; + const u64 *reg; + u64 addr; + + if (phy_offset < 0) + return -1; + /* obtain mdio node and get the reg prop */ + node = fdt_parent_offset(fdt, phy_offset); + if (node < 0) + return -1; + + reg = fdt_getprop(fdt, node, "reg", NULL); + addr = fdt64_to_cpu(*reg); + bus = (addr & (1 << 7)) ? 1 : 0; + return bus; +} + +static int fdt_get_phy_addr(const void *fdt, int phy_offset) +{ + const u32 *reg; + int addr = -1; + + if (phy_offset < 0) + return -1; + reg = fdt_getprop(fdt, phy_offset, "reg", NULL); + addr = fdt32_to_cpu(*reg); + return addr; +} + +void fdt_parse_phy_info(void) +{ + const void *fdt = gd->fdt_blob; + int offset = 0, node, bgx_id = 0, lmacid = 0; + const u32 *val; + char bgxname[24]; + int len, rgx_id = 0, eth_id = 0; + int phandle, phy_offset; + int subnode, i; + int bdknode; + + bdknode = fdt_path_offset(fdt, "/cavium,bdk"); + if (bdknode < 0) { + printf("%s: bdk node is missing from device tree: %s\n", + __func__, fdt_strerror(bdknode)); + } + + offset = fdt_node_offset_by_compatible(fdt, -1, "pci-bridge"); + if (offset < 1) + return; + + for (bgx_id = 0; bgx_id < MAX_BGX_PER_NODE; bgx_id++) { + int phy_addr[LMAC_CNT] = {[0 ... LMAC_CNT - 1] = -1}; + bool autoneg_dis[LMAC_CNT] = {[0 ... LMAC_CNT - 1] = 0}; + int mdio_bus[LMAC_CNT] = {[0 ... LMAC_CNT - 1] = -1}; + bool lmac_reg[LMAC_CNT] = {[0 ... LMAC_CNT - 1] = 0}; + bool lmac_enable[LMAC_CNT] = {[0 ... LMAC_CNT - 1] = 0}; + + snprintf(bgxname, sizeof(bgxname), "bgx%d", bgx_id); + node = fdt_subnode_offset(fdt, offset, bgxname); + if (node < 0) { + /* check if it is rgx node */ + snprintf(bgxname, sizeof(bgxname), "rgx%d", rgx_id); + node = fdt_subnode_offset(fdt, offset, bgxname); + if (node < 0) { + debug("bgx%d/rgx0 node not found\n", bgx_id); + return; + } + } + debug("bgx%d node found\n", bgx_id); + + /* + * loop through each of the bgx/rgx nodes + * to find PHY nodes + */ + fdt_for_each_subnode(subnode, fdt, node) { + /* Check for reg property */ + val = fdt_getprop(fdt, subnode, "reg", &len); + if (val) { + debug("lmacid = %d\n", lmacid); + lmac_reg[lmacid] = 1; + } + /* check for phy-handle property */ + val = fdt_getprop(fdt, subnode, "phy-handle", &len); + if (val) { + phandle = fdt32_to_cpu(*val); + if (!phandle) { + debug("phandle not valid %d\n", lmacid); + } else { + phy_offset = fdt_node_offset_by_phandle + (fdt, phandle); + phy_addr[lmacid] = fdt_get_phy_addr + (fdt, phy_offset); + mdio_bus[lmacid] = fdt_get_mdio_bus + (fdt, phy_offset); + } + } else { + debug("phy-handle prop not found %d\n", + lmacid); + } + /* check for autonegotiation property */ + val = fdt_getprop(fdt, subnode, + "cavium,disable-autonegotiation", + &len); + if (val) + autoneg_dis[lmacid] = 1; + + eth_id++; + lmacid++; + } + + for (i = 0; i < MAX_LMAC_PER_BGX; i++) { + const char *str; + + snprintf(bgxname, sizeof(bgxname), + "BGX-ENABLE.N0.BGX%d.P%d", bgx_id, i); + if (bdknode >= 0) { + str = fdt_getprop(fdt, bdknode, + bgxname, &len); + if (str) + lmac_enable[i] = + simple_strtol(str, NULL, + 10); + } + } + + lmacid = 0; + bgx_set_board_info(bgx_id, mdio_bus, phy_addr, + autoneg_dis, lmac_reg, lmac_enable); + } +} + +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; +} + +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) +{ + const void *fdt = gd->fdt_blob; + int node, len = 16; + const char *str = NULL; + + 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; +} + +void fdt_board_get_ethaddr(int bgx, int lmac, unsigned char *eth) +{ + const void *fdt = gd->fdt_blob; + const char *mac = NULL; + int offset = 0, node, len; + int subnode, i = 0; + char bgxname[24]; + + offset = fdt_node_offset_by_compatible(fdt, -1, "pci-bridge"); + if (offset < 0) { + printf("%s couldn't find mrml bridge node in fdt\n", + __func__); + return; + } + if (bgx == 2 && otx_is_soc(CN81XX)) { + snprintf(bgxname, sizeof(bgxname), "rgx%d", 0); + lmac = 0; + } else { + snprintf(bgxname, sizeof(bgxname), "bgx%d", bgx); + } + + node = fdt_subnode_offset(fdt, offset, bgxname); + + fdt_for_each_subnode(subnode, fdt, node) { + if (i++ != lmac) + continue; + /* check for local-mac-address */ + mac = fdt_getprop(fdt, subnode, "local-mac-address", &len); + if (mac) { + debug("%s mac %pM\n", __func__, mac); + memcpy(eth, mac, ARP_HLEN); + } else { + memset(eth, 0, ARP_HLEN); + } + debug("%s eth %pM\n", __func__, eth); + return; + } +} + +int arch_fixup_memory_node(void *blob) +{ + return 0; +} + +int ft_board_setup(void *blob, struct bd_info *bd) +{ + /* remove "cavium, bdk" node from DT */ + int ret = 0, offset; + + ret = fdt_check_header(blob); + if (ret < 0) { + printf("ERROR: %s\n", fdt_strerror(ret)); + return ret; + } + + if (blob) { + offset = fdt_path_offset(blob, "/cavium,bdk"); + if (offset < 0) { + printf("ERROR: FDT BDK node not found\n"); + return offset; + } + + /* delete node */ + ret = fdt_del_node(blob, offset); + if (ret < 0) { + printf("WARNING : could not remove bdk node\n"); + return ret; + } + + debug("%s deleted bdk node\n", __func__); + } + + 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/octeontx/board.c b/board/Marvell/octeontx/board.c new file mode 100644 index 0000000000..940faacbe3 --- /dev/null +++ b/board/Marvell/octeontx/board.c @@ -0,0 +1,152 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * https://spdx.org/licenses + */ + +#include <dm.h> +#include <malloc.h> +#include <errno.h> +#include <env.h> +#include <init.h> +#include <log.h> +#include <netdev.h> +#include <pci_ids.h> +#include <asm/io.h> +#include <linux/compiler.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 octeontx_cleanup_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); + } +} + +int octeontx_board_has_pmp(void) +{ + return (otx_is_board("sff8104") || otx_is_board("nas8104")); +} + +int board_early_init_r(void) +{ + pci_init(); + return 0; +} + +int board_init(void) +{ + if (IS_ENABLED(CONFIG_NET_OCTEONTX)) + fdt_parse_phy_info(); + + 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, bgx_cnt, i; + + /* Probe MAC(BGX) and NIC PF devices before Network stack init */ + bgx_cnt = otx_is_soc(CN81XX) ? 2 : 4; + for (i = 0; i < bgx_cnt; i++) { + err = dm_pci_find_device(PCI_VENDOR_ID_CAVIUM, + PCI_DEVICE_ID_CAVIUM_BGX, i, &dev); + if (err) + debug("%s BGX%d device not found\n", __func__, i); + } + if (otx_is_soc(CN81XX)) { + err = dm_pci_find_device(PCI_VENDOR_ID_CAVIUM, + PCI_DEVICE_ID_CAVIUM_RGX, 0, &dev); + if (err) + debug("%s RGX device not found\n", __func__); + } + err = dm_pci_find_device(PCI_VENDOR_ID_CAVIUM, + PCI_DEVICE_ID_CAVIUM_NIC, 0, &dev); + if (err) + debug("NIC PF device not found\n"); +} + +/** + * Board late initialization routine. + */ +int board_late_init(void) +{ + char boardname[32]; + char boardserial[150], boardrev[150]; + bool save_env = false; + const char *str; + + /* + * Try to cleanup ethaddr env variables, this is needed + * as with each boot, configuration of network interfaces can change. + */ + octeontx_cleanup_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); + } + + if (IS_ENABLED(CONFIG_NET_OCTEONTX)) + 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; +} diff --git a/board/Marvell/octeontx/smc.c b/board/Marvell/octeontx/smc.c new file mode 100644 index 0000000000..5eeba2358b --- /dev/null +++ b/board/Marvell/octeontx/smc.c @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * https://spdx.org/licenses + */ + +#include <asm/global_data.h> +#include <asm/ptrace.h> +#include <asm/system.h> +#include <asm/arch/smc.h> + +DECLARE_GLOBAL_DATA_PTR; + +ssize_t smc_dram_size(unsigned int node) +{ + struct pt_regs regs; + + regs.regs[0] = OCTEONTX_DRAM_SIZE; + regs.regs[1] = node; + smc_call(®s); + + return regs.regs[0]; +} + diff --git a/board/Marvell/octeontx/soc-utils.c b/board/Marvell/octeontx/soc-utils.c new file mode 100644 index 0000000000..5fd5afd48d --- /dev/null +++ b/board/Marvell/octeontx/soc-utils.c @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2019 Marvell International Ltd. + * + * https://spdx.org/licenses + */ + +#include <dm.h> +#include <dm/util.h> +#include <errno.h> +#include <malloc.h> +#include <asm/io.h> +#include <asm/arch/soc.h> +#include <asm/arch/board.h> + +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(); +} + +bool read_alt_pkg(void) +{ + return false; +} 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 <awilliams@marvell.com> +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 <errno.h> +#include <fdtdec.h> +#include <fdt_support.h> +#include <log.h> + +#include <linux/compiler.h> +#include <linux/libfdt.h> + +#include <asm/arch/board.h> +#include <asm/arch/smc.h> +#include <asm/global_data.h> +#include <asm/io.h> + +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 <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)", + ""); 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 <asm/global_data.h> +#include <asm/io.h> +#include <asm/psci.h> +#include <asm/ptrace.h> +#include <asm/system.h> +#include <asm/arch/smc.h> + +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 <common.h> +#include <dm.h> +#include <malloc.h> +#include <errno.h> +#include <asm/io.h> +#include <linux/compiler.h> +#include <asm/arch/soc.h> +#include <asm/arch/board.h> +#include <dm/util.h> + +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(); +} + diff --git a/board/renesas/rcar-common/common.c b/board/renesas/rcar-common/common.c index 83dd288847..9762fb2638 100644 --- a/board/renesas/rcar-common/common.c +++ b/board/renesas/rcar-common/common.c @@ -42,51 +42,4 @@ int dram_init_banksize(void) return 0; } - -#if CONFIG_IS_ENABLED(OF_BOARD_SETUP) && CONFIG_IS_ENABLED(PCI) -int ft_board_setup(void *blob, struct bd_info *bd) -{ - struct udevice *dev; - struct uclass *uc; - fdt_addr_t regs_addr; - int i, off, ret; - - ret = uclass_get(UCLASS_PCI, &uc); - if (ret) - return ret; - - uclass_foreach_dev(dev, uc) { - struct pci_controller hose = { 0 }; - - for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { - if (hose.region_count == MAX_PCI_REGIONS) { - printf("maximum number of regions parsed, aborting\n"); - break; - } - - if (bd->bi_dram[i].size) { - pci_set_region(&hose.regions[hose.region_count++], - bd->bi_dram[i].start, - bd->bi_dram[i].start, - bd->bi_dram[i].size, - PCI_REGION_MEM | - PCI_REGION_PREFETCH | - PCI_REGION_SYS_MEMORY); - } - } - - regs_addr = devfdt_get_addr_index(dev, 0); - off = fdt_node_offset_by_compat_reg(blob, - "renesas,pcie-rcar-gen3", regs_addr); - if (off < 0) { - printf("Failed to find PCIe node@%llx\n", regs_addr); - return off; - } - - fdt_pci_dma_ranges(blob, off, &hose); - } - - return 0; -} -#endif #endif |