From b80ca8176dc0e78d3fb22b2389c847a5d96ee583 Mon Sep 17 00:00:00 2001 From: Marek Behún Date: Wed, 8 Apr 2020 12:02:03 +0200 Subject: arm: mvebu: turris_mox: Fix early SPI communication MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The SPI clock signal changes value when the SPI configuration register is configured. This can sometimes lead to the device misinterpreting the enablement of the SPI controller as actual clock tick. This can be solved by first setting the SPI CS1 pin from GPIO to SPI mode, and only after that writing the SPI configuration register. Signed-off-by: Marek Behún Reviewed-by: Stefan Roese --- board/CZ.NIC/turris_mox/turris_mox.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'board/CZ.NIC') diff --git a/board/CZ.NIC/turris_mox/turris_mox.c b/board/CZ.NIC/turris_mox/turris_mox.c index 377191baef..0b13d1d190 100644 --- a/board/CZ.NIC/turris_mox/turris_mox.c +++ b/board/CZ.NIC/turris_mox/turris_mox.c @@ -67,9 +67,11 @@ int board_fix_fdt(void *blob) * to read SPI by reading/writing SPI registers directly */ - writel(0x563fa, ARMADA_37XX_NB_GPIO_SEL); writel(0x10df, ARMADA_37XX_SPI_CFG); - writel(0x2005b, ARMADA_37XX_SPI_CTRL); + /* put pin from GPIO to SPI mode */ + clrbits_le32(ARMADA_37XX_NB_GPIO_SEL, BIT(12)); + /* enable SPI CS1 */ + setbits_le32(ARMADA_37XX_SPI_CTRL, BIT(17)); while (!(readl(ARMADA_37XX_SPI_CTRL) & 0x2)) udelay(1); @@ -89,7 +91,8 @@ int board_fix_fdt(void *blob) size = i; - writel(0x5b, ARMADA_37XX_SPI_CTRL); + /* disable SPI CS1 */ + clrbits_le32(ARMADA_37XX_SPI_CTRL, BIT(17)); if (size > 1 && (topology[1] == MOX_MODULE_PCI || topology[1] == MOX_MODULE_USB3 || -- cgit From 2b3f2dd1ce90410d2edcd67bbef686c3361133c0 Mon Sep 17 00:00:00 2001 From: Marek Behún Date: Wed, 8 Apr 2020 12:02:05 +0200 Subject: arm: mvebu: turris_mox: Setup Linux's device tree before boot MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Patch Linux's device tree according to which Mox modules are connected. Linux's device tree has all possible Mox module nodes preprogrammed, but in disabled state. If MOX B, MOX F or MOX G module is present, this code enables the PCI node. For the network modules (MOX C, MOX D and MOX E) are present, the code enables corresponding ethernet and swtich nodes and DSA connections. For the SFP cage the SFP GPIO controller node and SFP node are also enabled. Signed-off-by: Marek Behún Reviewed-by: Stefan Roese --- board/CZ.NIC/turris_mox/turris_mox.c | 295 ++++++++++++++++++++++++++++++++--- 1 file changed, 277 insertions(+), 18 deletions(-) (limited to 'board/CZ.NIC') diff --git a/board/CZ.NIC/turris_mox/turris_mox.c b/board/CZ.NIC/turris_mox/turris_mox.c index 0b13d1d190..6e937826d0 100644 --- a/board/CZ.NIC/turris_mox/turris_mox.c +++ b/board/CZ.NIC/turris_mox/turris_mox.c @@ -34,7 +34,11 @@ #define ARMADA_37XX_SPI_DOUT 0xd0010608 #define ARMADA_37XX_SPI_DIN 0xd001060c +#define ETH1_PATH "/soc/internal-regs@d0000000/ethernet@40000" +#define MDIO_PATH "/soc/internal-regs@d0000000/mdio@32004" +#define SFP_GPIO_PATH "/soc/internal-regs@d0000000/spi@10600/moxtet@1/gpio@0" #define PCIE_PATH "/soc/pcie@d0070000" +#define SFP_PATH "/sfp" DECLARE_GLOBAL_DATA_PTR; @@ -459,24 +463,22 @@ int last_stage_init(void) } break; case MOX_MODULE_PCI: - if (pci) { + if (pci) printf("Error: Only one Mini-PCIe module is supported!\n"); - } else if (usb) { + else if (usb) printf("Error: Mini-PCIe module cannot come after USB 3.0 module!\n"); - } else if (i && (i != 1 || !passpci)) { + else if (i && (i != 1 || !passpci)) printf("Error: Mini-PCIe module should be the first connected module or come right after Passthrough Mini-PCIe module!\n"); - } else { + else ++pci; - } break; case MOX_MODULE_TOPAZ: - if (topaz) { + if (topaz) printf("Error: Only one Topaz module is supported!\n"); - } else if (peridot >= 3) { + else if (peridot >= 3) printf("Error: At most two Peridot modules can come before Topaz module!\n"); - } else { + else ++topaz; - } break; case MOX_MODULE_PERIDOT: if (sfp || topaz) { @@ -489,24 +491,22 @@ int last_stage_init(void) } break; case MOX_MODULE_USB3: - if (pci) { + if (pci) printf("Error: USB 3.0 module cannot come after Mini-PCIe module!\n"); - } else if (usb) { + else if (usb) printf("Error: Only one USB 3.0 module is supported!\n"); - } else if (i && (i != 1 || !passpci)) { + else if (i && (i != 1 || !passpci)) printf("Error: USB 3.0 module should be the first connected module or come right after Passthrough Mini-PCIe module!\n"); - } else { + else ++usb; - } break; case MOX_MODULE_PASSPCI: - if (passpci) { + if (passpci) printf("Error: Only one Passthrough Mini-PCIe module is supported!\n"); - } else if (i != 0) { + else if (i != 0) printf("Error: Passthrough Mini-PCIe module should be the first connected module!\n"); - } else { + else ++passpci; - } } } @@ -551,3 +551,262 @@ int last_stage_init(void) return 0; } + +#if defined(CONFIG_OF_BOARD_SETUP) + +static int vnode_by_path(void *blob, const char *fmt, va_list ap) +{ + char path[128]; + + vsnprintf(path, 128, fmt, ap); + return fdt_path_offset(blob, path); +} + +static int node_by_path(void *blob, const char *fmt, ...) +{ + va_list ap; + int res; + + va_start(ap, fmt); + res = vnode_by_path(blob, fmt, ap); + va_end(ap); + + return res; +} + +static int phandle_by_path(void *blob, const char *fmt, ...) +{ + va_list ap; + int node, phandle, res; + + va_start(ap, fmt); + node = vnode_by_path(blob, fmt, ap); + va_end(ap); + + if (node < 0) + return node; + + phandle = fdt_get_phandle(blob, node); + if (phandle > 0) + return phandle; + + phandle = fdt_get_max_phandle(blob); + if (phandle < 0) + return phandle; + + phandle += 1; + + res = fdt_setprop_u32(blob, node, "linux,phandle", phandle); + if (res < 0) + return res; + + res = fdt_setprop_u32(blob, node, "phandle", phandle); + if (res < 0) + return res; + + return phandle; +} + +static int enable_by_path(void *blob, const char *fmt, ...) +{ + va_list ap; + int node; + + va_start(ap, fmt); + node = vnode_by_path(blob, fmt, ap); + va_end(ap); + + if (node < 0) + return node; + + return fdt_setprop_string(blob, node, "status", "okay"); +} + +static bool is_topaz(int id) +{ + return topaz && id == peridot + topaz - 1; +} + +static int switch_addr(int id) +{ + return is_topaz(id) ? 0x2 : 0x10 + id; +} + +static int setup_switch(void *blob, int id) +{ + int res, addr, i, node, phandle; + + addr = switch_addr(id); + + /* first enable the switch by setting status = "okay" */ + res = enable_by_path(blob, MDIO_PATH "/switch%i@%x", id, addr); + if (res < 0) + return res; + + /* + * now if there are more switches or a SFP module coming after, + * enable corresponding ports + */ + if (id < peridot + topaz - 1) { + res = enable_by_path(blob, + MDIO_PATH "/switch%i@%x/ports/port@a", + id, addr); + } else if (id == peridot - 1 && !topaz && sfp) { + res = enable_by_path(blob, + MDIO_PATH "/switch%i@%x/ports/port-sfp@a", + id, addr); + } else { + res = 0; + } + if (res < 0) + return res; + + if (id >= peridot + topaz - 1) + return 0; + + /* finally change link property if needed */ + node = node_by_path(blob, MDIO_PATH "/switch%i@%x/ports/port@a", id, + addr); + if (node < 0) + return node; + + for (i = id + 1; i < peridot + topaz; ++i) { + phandle = phandle_by_path(blob, + MDIO_PATH "/switch%i@%x/ports/port@%x", + i, switch_addr(i), + is_topaz(i) ? 5 : 9); + if (phandle < 0) + return phandle; + + if (i == id + 1) + res = fdt_setprop_u32(blob, node, "link", phandle); + else + res = fdt_appendprop_u32(blob, node, "link", phandle); + if (res < 0) + return res; + } + + return 0; +} + +static int remove_disabled_nodes(void *blob) +{ + while (1) { + int res, offset; + + offset = fdt_node_offset_by_prop_value(blob, -1, "status", + "disabled", 9); + if (offset < 0) + break; + + res = fdt_del_node(blob, offset); + if (res < 0) + return res; + } + + return 0; +} + +int ft_board_setup(void *blob, bd_t *bd) +{ + int node, phandle, res; + + /* + * If MOX B (PCI), MOX F (USB) or MOX G (Passthrough PCI) modules are + * connected, enable the PCIe node. + */ + if (pci || usb || passpci) { + node = fdt_path_offset(blob, PCIE_PATH); + if (node < 0) + return node; + + res = fdt_setprop_string(blob, node, "status", "okay"); + if (res < 0) + return res; + } + + /* + * If MOX C (Topaz switch) and/or MOX E (Peridot switch) are connected, + * enable the eth1 node and setup the switches. + */ + if (peridot || topaz) { + int i; + + res = enable_by_path(blob, ETH1_PATH); + if (res < 0) + return res; + + for (i = 0; i < peridot + topaz; ++i) { + res = setup_switch(blob, i); + if (res < 0) + return res; + } + } + + /* + * If MOX D (SFP cage module) is connected, enable the SFP node and eth1 + * node. If there is no Peridot switch between MOX A and MOX D, add link + * to the SFP node to eth1 node. + * Also enable and configure SFP GPIO controller node. + */ + if (sfp) { + res = enable_by_path(blob, SFP_PATH); + if (res < 0) + return res; + + res = enable_by_path(blob, ETH1_PATH); + if (res < 0) + return res; + + if (!peridot) { + phandle = phandle_by_path(blob, SFP_PATH); + if (phandle < 0) + return res; + + node = node_by_path(blob, ETH1_PATH); + if (node < 0) + return node; + + res = fdt_setprop_u32(blob, node, "sfp", phandle); + if (res < 0) + return res; + + res = fdt_setprop_string(blob, node, "phy-mode", + "sgmii"); + if (res < 0) + return res; + } + + res = enable_by_path(blob, SFP_GPIO_PATH); + if (res < 0) + return res; + + if (sfp_pos) { + char newname[16]; + + /* moxtet-sfp is on non-zero position, change default */ + node = node_by_path(blob, SFP_GPIO_PATH); + if (node < 0) + return node; + + res = fdt_setprop_u32(blob, node, "reg", sfp_pos); + if (res < 0) + return res; + + sprintf(newname, "gpio@%x", sfp_pos); + + res = fdt_set_name(blob, node, newname); + if (res < 0) + return res; + } + } + + fdt_fixup_ethernet(blob); + + /* Finally remove disabled nodes, as per Rob Herring's request. */ + remove_disabled_nodes(blob); + + return 0; +} + +#endif -- cgit From 9657841010cae49b1f903adf198ec334cfc92f11 Mon Sep 17 00:00:00 2001 From: Marek Behún Date: Wed, 8 Apr 2020 12:02:07 +0200 Subject: arm: mvebu: turris_mox: don't use hardcoded addresses MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use macro MVEBU_REGISTER to access register addresses instead of hardcoded addresses. Signed-off-by: Marek Behún Reviewed-by: Stefan Roese --- board/CZ.NIC/turris_mox/mox_sp.c | 14 ++++++++------ board/CZ.NIC/turris_mox/turris_mox.c | 11 ++++++----- 2 files changed, 14 insertions(+), 11 deletions(-) (limited to 'board/CZ.NIC') diff --git a/board/CZ.NIC/turris_mox/mox_sp.c b/board/CZ.NIC/turris_mox/mox_sp.c index 0b29ffcc67..3c23471e65 100644 --- a/board/CZ.NIC/turris_mox/mox_sp.c +++ b/board/CZ.NIC/turris_mox/mox_sp.c @@ -4,15 +4,17 @@ */ #include +#include #include -#define RWTM_CMD_PARAM(i) (size_t)(0xd00b0000 + (i) * 4) -#define RWTM_CMD 0xd00b0040 -#define RWTM_CMD_RETSTATUS 0xd00b0080 -#define RWTM_CMD_STATUS(i) (size_t)(0xd00b0084 + (i) * 4) +#define RWTM_BASE (MVEBU_REGISTER(0xb0000)) +#define RWTM_CMD_PARAM(i) (size_t)(RWTM_BASE + (i) * 4) +#define RWTM_CMD (RWTM_BASE + 0x40) +#define RWTM_CMD_RETSTATUS (RWTM_BASE + 0x80) +#define RWTM_CMD_STATUS(i) (size_t)(RWTM_BASE + 0x84 + (i) * 4) -#define RWTM_HOST_INT_RESET 0xd00b00c8 -#define RWTM_HOST_INT_MASK 0xd00b00cc +#define RWTM_HOST_INT_RESET (RWTM_BASE + 0xc8) +#define RWTM_HOST_INT_MASK (RWTM_BASE + 0xcc) #define SP_CMD_COMPLETE BIT(0) #define MBOX_STS_SUCCESS (0x0 << 30) diff --git a/board/CZ.NIC/turris_mox/turris_mox.c b/board/CZ.NIC/turris_mox/turris_mox.c index 6e937826d0..cd39b1c01f 100644 --- a/board/CZ.NIC/turris_mox/turris_mox.c +++ b/board/CZ.NIC/turris_mox/turris_mox.c @@ -5,6 +5,7 @@ #include #include +#include #include #include #include @@ -28,11 +29,11 @@ #define MOX_MODULE_USB3 0x5 #define MOX_MODULE_PASSPCI 0x6 -#define ARMADA_37XX_NB_GPIO_SEL 0xd0013830 -#define ARMADA_37XX_SPI_CTRL 0xd0010600 -#define ARMADA_37XX_SPI_CFG 0xd0010604 -#define ARMADA_37XX_SPI_DOUT 0xd0010608 -#define ARMADA_37XX_SPI_DIN 0xd001060c +#define ARMADA_37XX_NB_GPIO_SEL (MVEBU_REGISTER(0x13830)) +#define ARMADA_37XX_SPI_CTRL (MVEBU_REGISTER(0x10600)) +#define ARMADA_37XX_SPI_CFG (MVEBU_REGISTER(0x10604)) +#define ARMADA_37XX_SPI_DOUT (MVEBU_REGISTER(0x10608)) +#define ARMADA_37XX_SPI_DIN (MVEBU_REGISTER(0x1060c)) #define ETH1_PATH "/soc/internal-regs@d0000000/ethernet@40000" #define MDIO_PATH "/soc/internal-regs@d0000000/mdio@32004" -- cgit From c8a185a823d7aa8fc02df0c064d47e5713eaebc6 Mon Sep 17 00:00:00 2001 From: Marek Behún Date: Wed, 8 Apr 2020 12:02:08 +0200 Subject: arm: mvebu: turris_mox: sort headers alphabetically MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sort #includes alphabetically, the only exception is common.h, which is included first in most parts of U-Boot. Signed-off-by: Marek Behún Reviewed-by: Stefan Roese --- board/CZ.NIC/turris_mox/turris_mox.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'board/CZ.NIC') diff --git a/board/CZ.NIC/turris_mox/turris_mox.c b/board/CZ.NIC/turris_mox/turris_mox.c index cd39b1c01f..5bb53b1260 100644 --- a/board/CZ.NIC/turris_mox/turris_mox.c +++ b/board/CZ.NIC/turris_mox/turris_mox.c @@ -4,19 +4,19 @@ */ #include -#include #include -#include #include -#include +#include #include +#include #include -#include -#include -#include -#include -#include #include +#include +#include +#include +#include +#include +#include #include "mox_sp.h" -- cgit From 4e9eb04c8d258521f2ec80ad857179f5e362f7fa Mon Sep 17 00:00:00 2001 From: Marek Behún Date: Wed, 8 Apr 2020 19:25:20 +0200 Subject: arm: mvebu: turris_mox: support devices with RAM > 1 GB MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In order to support MOX boards with 2 GB or 4 GB RAM, we use the new Armada-3700 generic code for memory information structures. This is done by removing dram_init and dram_init_banksize from turris_mox.c, in order for the generic, weak definitions to be used. Also for boards with 4 GB RAM it is needed to increase CONFIG_NR_DRAM_BANKS to 2 in turris_mox_defconfig. Signed-off-by: Marek Behún Reviewed-by: Stefan Roese --- board/CZ.NIC/turris_mox/turris_mox.c | 16 ---------------- 1 file changed, 16 deletions(-) (limited to 'board/CZ.NIC') diff --git a/board/CZ.NIC/turris_mox/turris_mox.c b/board/CZ.NIC/turris_mox/turris_mox.c index 5bb53b1260..8e4c023103 100644 --- a/board/CZ.NIC/turris_mox/turris_mox.c +++ b/board/CZ.NIC/turris_mox/turris_mox.c @@ -43,22 +43,6 @@ DECLARE_GLOBAL_DATA_PTR; -int dram_init(void) -{ - gd->ram_base = 0; - gd->ram_size = (phys_size_t)get_ram_size(0, 0x40000000); - - return 0; -} - -int dram_init_banksize(void) -{ - gd->bd->bi_dram[0].start = (phys_addr_t)0; - gd->bd->bi_dram[0].size = gd->ram_size; - - return 0; -} - #if defined(CONFIG_OF_BOARD_FIXUP) int board_fix_fdt(void *blob) { -- cgit From c64ac3b3185aeb3846297ad7391fc6df8ecd73bf Mon Sep 17 00:00:00 2001 From: Marek Behún Date: Wed, 8 Apr 2020 19:25:22 +0200 Subject: arm: mvebu: turris_mox: fix PCIe ranges in device tree MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use the new a3700_fdt_fix_pcie_regions function in turris_mox.c so that MOX boards with 4 GB RAM are fully supported. Signed-off-by: Marek Behún Reviewed-by: Stefan Roese --- board/CZ.NIC/turris_mox/turris_mox.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'board/CZ.NIC') diff --git a/board/CZ.NIC/turris_mox/turris_mox.c b/board/CZ.NIC/turris_mox/turris_mox.c index 8e4c023103..470ea32f9c 100644 --- a/board/CZ.NIC/turris_mox/turris_mox.c +++ b/board/CZ.NIC/turris_mox/turris_mox.c @@ -4,6 +4,7 @@ */ #include +#include #include #include #include @@ -104,6 +105,11 @@ int board_fix_fdt(void *blob) return 0; } + if (a3700_fdt_fix_pcie_regions(blob) < 0) { + printf("Cannot fix PCIe regions in U-Boot's device tree!\n"); + return 0; + } + return 0; } #endif @@ -708,6 +714,11 @@ int ft_board_setup(void *blob, bd_t *bd) res = fdt_setprop_string(blob, node, "status", "okay"); if (res < 0) return res; + + /* Fix PCIe regions for devices with 4 GB RAM */ + res = a3700_fdt_fix_pcie_regions(blob); + if (res < 0) + return res; } /* -- cgit