From 67c8678346055e8455ac062cbc18ab5b693c40a1 Mon Sep 17 00:00:00 2001 From: Michael Liebert Date: Wed, 15 Dec 2021 16:14:28 +0100 Subject: [PATCH 01/15] arm: mach-k3: am642_init: Unlock MCU PADCFG regs Currently only the PADCFG registers of the main domain are unlocked. Also unlock PADCFG registers of MCU domain, so MCU pin muxing can be configured by u-boot or Linux. Signed-off-by: Michael Liebert Tested-by: Christian Gmeiner Acked-by: Nishanth Menon --- arch/arm/mach-k3/am642_init.c | 3 +++ arch/arm/mach-k3/include/mach/am64_hardware.h | 2 ++ 2 files changed, 5 insertions(+) diff --git a/arch/arm/mach-k3/am642_init.c b/arch/arm/mach-k3/am642_init.c index 533905daeb..958fa05af4 100644 --- a/arch/arm/mach-k3/am642_init.c +++ b/arch/arm/mach-k3/am642_init.c @@ -37,6 +37,9 @@ static void ctrl_mmr_unlock(void) mmr_unlock(CTRL_MMR0_BASE, 3); mmr_unlock(CTRL_MMR0_BASE, 5); mmr_unlock(CTRL_MMR0_BASE, 6); + + /* Unlock all MCU_PADCFG_MMR1 module registers */ + mmr_unlock(MCU_PADCFG_MMR1_BASE, 1); } /* diff --git a/arch/arm/mach-k3/include/mach/am64_hardware.h b/arch/arm/mach-k3/include/mach/am64_hardware.h index 96383437d5..e06e1f9532 100644 --- a/arch/arm/mach-k3/include/mach/am64_hardware.h +++ b/arch/arm/mach-k3/include/mach/am64_hardware.h @@ -12,6 +12,8 @@ #define PADCFG_MMR1_BASE 0xf0000 +#define MCU_PADCFG_MMR1_BASE 0x04080000 + #define MAIN_DEVSTAT_PRIMARY_BOOTMODE_MASK 0x00000078 #define MAIN_DEVSTAT_PRIMARY_BOOTMODE_SHIFT 3 From 584216315dee17d3a104379ff087ff57d2bbda48 Mon Sep 17 00:00:00 2001 From: Vignesh Raghavendra Date: Thu, 23 Dec 2021 19:26:03 +0530 Subject: [PATCH 02/15] ARM: mach-k3: sysfw-loader: Copy sysfw.itb to OCRAM in OSPI/SPI bootmode In case of xSPI bootmode OSPI flash is in DDR mode and needs to be accessed in multiple of 16bit accesses Hence we cannot parse sysfw.itb FIT image directly on OSPI flash via MMIO window. So, copy the image to internal on-chip RAM before parsing the image. Moreover, board cfg data maybe modified by ROM/TIFS in case of HS platform and thus cannot reside in OSPI/xSPI and needs to be copied over to internal OCRAM. This unblocks OSPI/xSPI boot on HS platforms Signed-off-by: Vignesh Raghavendra Reviewed-by: Dave Gerlach Tested-by: Keerthy Acked-by: Pratyush Yadav --- arch/arm/mach-k3/sysfw-loader.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-k3/sysfw-loader.c b/arch/arm/mach-k3/sysfw-loader.c index 9ce576186c..5e48c36ccd 100644 --- a/arch/arm/mach-k3/sysfw-loader.c +++ b/arch/arm/mach-k3/sysfw-loader.c @@ -22,6 +22,7 @@ #include #include +#include #include #include "common.h" @@ -335,6 +336,14 @@ static void *k3_sysfw_get_spi_addr(void) return (void *)(addr + CONFIG_K3_SYSFW_IMAGE_SPI_OFFS); } + +static void k3_sysfw_spi_copy(u32 *dst, u32 *src, size_t len) +{ + size_t i; + + for (i = 0; i < len / sizeof(*dst); i++) + *dst++ = *src++; +} #endif void k3_sysfw_loader(bool rom_loaded_sysfw, @@ -344,6 +353,9 @@ void k3_sysfw_loader(bool rom_loaded_sysfw, struct spl_image_info spl_image = { 0 }; struct spl_boot_device bootdev = { 0 }; struct ti_sci_handle *ti_sci; +#if CONFIG_IS_ENABLED(SPI_LOAD) + void *sysfw_spi_base; +#endif int ret = 0; if (rom_loaded_sysfw) { @@ -394,9 +406,11 @@ void k3_sysfw_loader(bool rom_loaded_sysfw, #endif #if CONFIG_IS_ENABLED(SPI_LOAD) case BOOT_DEVICE_SPI: - sysfw_load_address = k3_sysfw_get_spi_addr(); - if (!sysfw_load_address) + sysfw_spi_base = k3_sysfw_get_spi_addr(); + if (!sysfw_spi_base) ret = -ENODEV; + k3_sysfw_spi_copy(sysfw_load_address, sysfw_spi_base, + CONFIG_K3_SYSFW_IMAGE_SIZE_MAX); break; #endif #if CONFIG_IS_ENABLED(YMODEM_SUPPORT) From 4af5e5f6fdf53c3d1827a72daf886350b2e29e1c Mon Sep 17 00:00:00 2001 From: Vignesh Raghavendra Date: Thu, 23 Dec 2021 19:27:30 +0530 Subject: [PATCH 03/15] dma: ti: k3-udma: Fix rflow reservation for PKTDMA Driver has a bug in that it uses rflow_in_use bitmap when setting up free rflow range from TISCI but use rflow_map for reservation in __udma_reserve_rflow() Fix this by dropping rflow_in_use bitmap array and use rflow_map for PKTDMA. BCDMA does not need rflow_in_use either. This fixes CPSW3g not able to get DMA channels at R5 SPL on AM64x Signed-off-by: Vignesh Raghavendra --- drivers/dma/ti/k3-udma.c | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/drivers/dma/ti/k3-udma.c b/drivers/dma/ti/k3-udma.c index 411edef3a7..86603d43f1 100644 --- a/drivers/dma/ti/k3-udma.c +++ b/drivers/dma/ti/k3-udma.c @@ -165,7 +165,6 @@ struct udma_dev { unsigned long *rchan_map; unsigned long *rflow_map; unsigned long *rflow_map_reserved; - unsigned long *rflow_in_use; unsigned long *tflow_map; struct udma_bchan *bchans; @@ -1448,15 +1447,11 @@ static int bcdma_setup_resources(struct udma_dev *ud) sizeof(unsigned long), GFP_KERNEL); ud->rchans = devm_kcalloc(dev, ud->rchan_cnt, sizeof(*ud->rchans), GFP_KERNEL); - /* BCDMA do not really have flows, but the driver expect it */ - ud->rflow_in_use = devm_kcalloc(dev, BITS_TO_LONGS(ud->rchan_cnt), - sizeof(unsigned long), - GFP_KERNEL); ud->rflows = devm_kcalloc(dev, ud->rchan_cnt, sizeof(*ud->rflows), GFP_KERNEL); if (!ud->bchan_map || !ud->tchan_map || !ud->rchan_map || - !ud->rflow_in_use || !ud->bchans || !ud->tchans || !ud->rchans || + !ud->bchans || !ud->tchans || !ud->rchans || !ud->rflows) return -ENOMEM; @@ -1535,16 +1530,16 @@ static int pktdma_setup_resources(struct udma_dev *ud) sizeof(unsigned long), GFP_KERNEL); ud->rchans = devm_kcalloc(dev, ud->rchan_cnt, sizeof(*ud->rchans), GFP_KERNEL); - ud->rflow_in_use = devm_kcalloc(dev, BITS_TO_LONGS(ud->rflow_cnt), - sizeof(unsigned long), - GFP_KERNEL); + ud->rflow_map = devm_kcalloc(dev, BITS_TO_LONGS(ud->rflow_cnt), + sizeof(unsigned long), + GFP_KERNEL); ud->rflows = devm_kcalloc(dev, ud->rflow_cnt, sizeof(*ud->rflows), GFP_KERNEL); ud->tflow_map = devm_kmalloc_array(dev, BITS_TO_LONGS(ud->tflow_cnt), sizeof(unsigned long), GFP_KERNEL); if (!ud->tchan_map || !ud->rchan_map || !ud->tflow_map || !ud->tchans || - !ud->rchans || !ud->rflows || !ud->rflow_in_use) + !ud->rchans || !ud->rflows || !ud->rflow_map) return -ENOMEM; /* Get resource ranges from tisci */ @@ -1592,12 +1587,12 @@ static int pktdma_setup_resources(struct udma_dev *ud) rm_res = tisci_rm->rm_ranges[RM_RANGE_RFLOW]; if (IS_ERR(rm_res)) { /* all rflows are assigned exclusively to Linux */ - bitmap_zero(ud->rflow_in_use, ud->rflow_cnt); + bitmap_zero(ud->rflow_map, ud->rflow_cnt); } else { - bitmap_fill(ud->rflow_in_use, ud->rflow_cnt); + bitmap_fill(ud->rflow_map, ud->rflow_cnt); for (i = 0; i < rm_res->sets; i++) { rm_desc = &rm_res->desc[i]; - bitmap_clear(ud->rflow_in_use, rm_desc->start, + bitmap_clear(ud->rflow_map, rm_desc->start, rm_desc->num); dev_dbg(dev, "ti-sci-res: rflow: %d:%d\n", rm_desc->start, rm_desc->num); From e58d9284850fa78d364d264087fe744717963675 Mon Sep 17 00:00:00 2001 From: Vignesh Raghavendra Date: Fri, 24 Dec 2021 12:55:29 +0530 Subject: [PATCH 04/15] mach-k3: common: Instantiate AM65 CPSW NUSS wrapper Probe toplevel AM65 CPSW NUSS driver from misc_init_r() when driver is enabled. Since driver is modeled as UCLASS_MISC, we need to explicitly probe the driver. Use common misc_init_r() that entire K3 family of SoCs. Signed-off-by: Vignesh Raghavendra --- arch/arm/mach-k3/common.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/arch/arm/mach-k3/common.c b/arch/arm/mach-k3/common.c index 2666cd2d7b..39d00270b7 100644 --- a/arch/arm/mach-k3/common.c +++ b/arch/arm/mach-k3/common.c @@ -549,3 +549,19 @@ void spl_board_prepare_for_linux(void) dcache_disable(); } #endif + +int misc_init_r(void) +{ + if (IS_ENABLED(CONFIG_TI_AM65_CPSW_NUSS)) { + struct udevice *dev; + int ret; + + ret = uclass_get_device_by_driver(UCLASS_MISC, + DM_DRIVER_GET(am65_cpsw_nuss), + &dev); + if (ret) + printf("Failed to probe am65_cpsw_nuss driver\n"); + } + + return 0; +} From 38922b1f4acc0ae80c58a3baae9134b02defece7 Mon Sep 17 00:00:00 2001 From: Vignesh Raghavendra Date: Fri, 24 Dec 2021 12:55:30 +0530 Subject: [PATCH 05/15] net: ti: am65-cpsw: Add support for multi port independent MAC mode On certain TI SoC, like AM64x there is a CPSW3G which supports 2 external independent MAC ports for single CPSW instance. It is not possible for Ethernet driver to register more than one port for given instance. This patch modifies top level CPSW NUSS as UCLASS_MISC and binds UCLASS_ETH to individual ports so as to support bring up more than one Ethernet interface in U-Boot. Note that there is no isolation in the since, CPSW NUSS is in promisc mode and forwards all packets to host. Since top level driver is now UCLASS_MISC, board files would need to instantiate this driver explicitly. Signed-off-by: Vignesh Raghavendra --- drivers/net/ti/Kconfig | 2 + drivers/net/ti/am65-cpsw-nuss.c | 77 +++++++++++++++++++++------------ 2 files changed, 52 insertions(+), 27 deletions(-) diff --git a/drivers/net/ti/Kconfig b/drivers/net/ti/Kconfig index f2dbbd0128..59c96d862d 100644 --- a/drivers/net/ti/Kconfig +++ b/drivers/net/ti/Kconfig @@ -28,6 +28,8 @@ config DRIVER_TI_KEYSTONE_NET config TI_AM65_CPSW_NUSS bool "TI K3 AM65x MCU CPSW Nuss Ethernet controller driver" depends on ARCH_K3 + imply MISC_INIT_R + imply MISC select PHYLIB help This driver supports TI K3 MCU CPSW Nuss Ethernet controller diff --git a/drivers/net/ti/am65-cpsw-nuss.c b/drivers/net/ti/am65-cpsw-nuss.c index 3ab6a30828..6ae69b51c7 100644 --- a/drivers/net/ti/am65-cpsw-nuss.c +++ b/drivers/net/ti/am65-cpsw-nuss.c @@ -597,7 +597,7 @@ static int am65_cpsw_phy_init(struct udevice *dev) return ret; } -static int am65_cpsw_ofdata_parse_phy(struct udevice *dev, ofnode port_np) +static int am65_cpsw_ofdata_parse_phy(struct udevice *dev) { struct eth_pdata *pdata = dev_get_plat(dev); struct am65_cpsw_priv *priv = dev_get_priv(dev); @@ -605,7 +605,9 @@ static int am65_cpsw_ofdata_parse_phy(struct udevice *dev, ofnode port_np) const char *phy_mode; int ret = 0; - phy_mode = ofnode_read_string(port_np, "phy-mode"); + dev_read_u32(dev, "reg", &priv->port_id); + + phy_mode = dev_read_string(dev, "phy-mode"); if (phy_mode) { pdata->phy_interface = phy_get_interface_by_name(phy_mode); @@ -617,13 +619,13 @@ static int am65_cpsw_ofdata_parse_phy(struct udevice *dev, ofnode port_np) } } - ofnode_read_u32(port_np, "max-speed", (u32 *)&pdata->max_speed); + dev_read_u32(dev, "max-speed", (u32 *)&pdata->max_speed); if (pdata->max_speed) dev_err(dev, "Port %u speed froced to %uMbit\n", priv->port_id, pdata->max_speed); priv->has_phy = true; - ret = ofnode_parse_phandle_with_args(port_np, "phy-handle", + ret = ofnode_parse_phandle_with_args(dev_ofnode(dev), "phy-handle", NULL, 0, 0, &out_args); if (ret) { dev_err(dev, "can't parse phy-handle port %u (%d)\n", @@ -646,21 +648,46 @@ out: return ret; } -static int am65_cpsw_probe_cpsw(struct udevice *dev) +static int am65_cpsw_port_probe(struct udevice *dev) { struct am65_cpsw_priv *priv = dev_get_priv(dev); struct eth_pdata *pdata = dev_get_plat(dev); struct am65_cpsw_common *cpsw_common; - ofnode ports_np, node; - int ret, i; + char portname[15]; + int ret; priv->dev = dev; - cpsw_common = calloc(1, sizeof(*priv->cpsw_common)); - if (!cpsw_common) - return -ENOMEM; + cpsw_common = dev_get_priv(dev->parent); priv->cpsw_common = cpsw_common; + sprintf(portname, "%s%s", dev->parent->name, dev->name); + device_set_name(dev, portname); + + ret = am65_cpsw_ofdata_parse_phy(dev); + if (ret) + goto out; + + am65_cpsw_gmii_sel_k3(priv, pdata->phy_interface, priv->port_id); + + ret = am65_cpsw_mdio_init(dev); + if (ret) + goto out; + + ret = am65_cpsw_phy_init(dev); + if (ret) + goto out; +out: + return ret; +} + +static int am65_cpsw_probe_nuss(struct udevice *dev) +{ + struct am65_cpsw_common *cpsw_common = dev_get_priv(dev); + ofnode ports_np, node; + int ret, i; + struct udevice *port_dev; + cpsw_common->dev = dev; cpsw_common->ss_base = dev_read_addr(dev); if (cpsw_common->ss_base == FDT_ADDR_T_NONE) @@ -723,10 +750,9 @@ static int am65_cpsw_probe_cpsw(struct udevice *dev) if (disabled) continue; - priv->port_id = port_id; - ret = am65_cpsw_ofdata_parse_phy(dev, node); + ret = device_bind_driver_to_node(dev, "am65_cpsw_nuss_port", ofnode_get_name(node), node, &port_dev); if (ret) - goto out; + printf("SCREEEM\n"); } for (i = 0; i < AM65_CPSW_CPSWNU_MAX_PORTS; i++) { @@ -756,16 +782,6 @@ static int am65_cpsw_probe_cpsw(struct udevice *dev) dev_read_u32_default(dev, "bus_freq", AM65_CPSW_MDIO_BUS_FREQ_DEF); - am65_cpsw_gmii_sel_k3(priv, pdata->phy_interface, priv->port_id); - - ret = am65_cpsw_mdio_init(dev); - if (ret) - goto out; - - ret = am65_cpsw_phy_init(dev); - if (ret) - goto out; - dev_info(dev, "K3 CPSW: nuss_ver: 0x%08X cpsw_ver: 0x%08X ale_ver: 0x%08X Ports:%u mdio_freq:%u\n", readl(cpsw_common->ss_base), readl(cpsw_common->cpsw_base), @@ -786,11 +802,18 @@ static const struct udevice_id am65_cpsw_nuss_ids[] = { { } }; -U_BOOT_DRIVER(am65_cpsw_nuss_slave) = { - .name = "am65_cpsw_nuss_slave", - .id = UCLASS_ETH, +U_BOOT_DRIVER(am65_cpsw_nuss) = { + .name = "am65_cpsw_nuss", + .id = UCLASS_MISC, .of_match = am65_cpsw_nuss_ids, - .probe = am65_cpsw_probe_cpsw, + .probe = am65_cpsw_probe_nuss, + .priv_auto = sizeof(struct am65_cpsw_common), +}; + +U_BOOT_DRIVER(am65_cpsw_nuss_port) = { + .name = "am65_cpsw_nuss_port", + .id = UCLASS_ETH, + .probe = am65_cpsw_port_probe, .ops = &am65_cpsw_ops, .priv_auto = sizeof(struct am65_cpsw_priv), .plat_auto = sizeof(struct eth_pdata), From 70bcd249f4726358e412216edfc5fd72165e2c48 Mon Sep 17 00:00:00 2001 From: Vignesh Raghavendra Date: Fri, 24 Dec 2021 12:55:31 +0530 Subject: [PATCH 06/15] board: ti: am64x: Init DRAM size in R5/A53 SPL Call dram_init_banksize() from spl_board_init() otherwise TFTP download fails due to lmb_get_free_size() not able to find unreserved region due to lack of DRAM size info. Required to support Ethernet boot on AM64x. Signed-off-by: Vignesh Raghavendra --- board/ti/am64x/evm.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/board/ti/am64x/evm.c b/board/ti/am64x/evm.c index 1a9f69c6cf..8373c768f1 100644 --- a/board/ti/am64x/evm.c +++ b/board/ti/am64x/evm.c @@ -196,5 +196,8 @@ void spl_board_init(void) val = readl(CTRLMMR_USB0_PHY_CTRL); val &= ~(CORE_VOLTAGE); writel(val, CTRLMMR_USB0_PHY_CTRL); + + /* Init DRAM size for R5/A53 SPL */ + dram_init_banksize(); } #endif From 93c43a8365fae0f188ac091d129542470ddaf62d Mon Sep 17 00:00:00 2001 From: Vignesh Raghavendra Date: Fri, 24 Dec 2021 12:55:32 +0530 Subject: [PATCH 07/15] mach-k3: am642_init: Probe AM65 CPSW NUSS for R5/A53 SPL In order to support Ethernet boot on AM64x, probe AM65 CPSW NUSS. Signed-off-by: Vignesh Raghavendra --- arch/arm/mach-k3/am642_init.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/arm/mach-k3/am642_init.c b/arch/arm/mach-k3/am642_init.c index 958fa05af4..543dea02bc 100644 --- a/arch/arm/mach-k3/am642_init.c +++ b/arch/arm/mach-k3/am642_init.c @@ -199,6 +199,13 @@ void board_init_f(ulong dummy) if (ret) panic("DRAM init failed: %d\n", ret); #endif + if (IS_ENABLED(CONFIG_SPL_ETH) && IS_ENABLED(CONFIG_TI_AM65_CPSW_NUSS) && + spl_boot_device() == BOOT_DEVICE_ETHERNET) { + struct udevice *cpswdev; + + if (uclass_get_device_by_driver(UCLASS_MISC, DM_DRIVER_GET(am65_cpsw_nuss), &cpswdev)) + printf("Failed to probe am65_cpsw_nuss driver\n"); + } } u32 spl_mmc_boot_mode(const u32 boot_device) From 07252f5c7149d3d41cf9acfb28b24e243f32ec35 Mon Sep 17 00:00:00 2001 From: Vignesh Raghavendra Date: Fri, 24 Dec 2021 12:55:33 +0530 Subject: [PATCH 08/15] mach-k3: am64_spl: Alias Ethernet RGMII boot to CPGMAC This is required to enables spl_net boot on AM64x Signed-off-by: Vignesh Raghavendra --- arch/arm/mach-k3/include/mach/am64_spl.h | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/mach-k3/include/mach/am64_spl.h b/arch/arm/mach-k3/include/mach/am64_spl.h index 607b09c2e5..b4f396b2c0 100644 --- a/arch/arm/mach-k3/include/mach/am64_spl.h +++ b/arch/arm/mach-k3/include/mach/am64_spl.h @@ -12,6 +12,7 @@ #define BOOT_DEVICE_QSPI 0x02 #define BOOT_DEVICE_SPI 0x03 #define BOOT_DEVICE_ETHERNET 0x04 +#define BOOT_DEVICE_CPGMAC 0x04 #define BOOT_DEVICE_ETHERNET_RGMII 0x04 #define BOOT_DEVICE_ETHERNET_RMII 0x05 #define BOOT_DEVICE_I2C 0x06 From ef7be5a07b8c31add141da1f2e9a6788357772de Mon Sep 17 00:00:00 2001 From: Vignesh Raghavendra Date: Fri, 24 Dec 2021 12:55:35 +0530 Subject: [PATCH 09/15] ARM: dts: K3-am642-r5-sk: Enable Second CPSW port in R5/A53 SPL Enable Second Ethernet port on which ROM support Ethboot. Signed-off-by: Vignesh Raghavendra --- arch/arm/dts/k3-am642-r5-sk.dts | 73 ++++++++++++++++++++++++++++ arch/arm/dts/k3-am642-sk-u-boot.dtsi | 40 ++++++++++++++- 2 files changed, 112 insertions(+), 1 deletion(-) diff --git a/arch/arm/dts/k3-am642-r5-sk.dts b/arch/arm/dts/k3-am642-r5-sk.dts index 71fcf61ff9..3a17448ca0 100644 --- a/arch/arm/dts/k3-am642-r5-sk.dts +++ b/arch/arm/dts/k3-am642-r5-sk.dts @@ -7,6 +7,7 @@ #include #include +#include #include "k3-am642.dtsi" #include "k3-am64-sk-lp4-1333MTs.dtsi" #include "k3-am64-ddr.dtsi" @@ -116,6 +117,47 @@ AM64X_IOPAD(0x02a8, PIN_OUTPUT, 0) /* (E19) USB0_DRVVBUS */ >; }; + + mdio1_pins_default: mdio1-pins-default { + pinctrl-single,pins = < + AM64X_IOPAD(0x01fc, PIN_OUTPUT, 4) /* (R2) PRG0_PRU1_GPO19.MDIO0_MDC */ + AM64X_IOPAD(0x01f8, PIN_INPUT, 4) /* (P5) PRG0_PRU1_GPO18.MDIO0_MDIO */ + >; + }; + + rgmii1_pins_default: rgmii1-pins-default { + pinctrl-single,pins = < + AM64X_IOPAD(0x011c, PIN_INPUT, 4) /* (AA13) PRG1_PRU1_GPO5.RGMII1_RD0 */ + AM64X_IOPAD(0x0128, PIN_INPUT, 4) /* (U12) PRG1_PRU1_GPO8.RGMII1_RD1 */ + AM64X_IOPAD(0x0150, PIN_INPUT, 4) /* (Y13) PRG1_PRU1_GPO18.RGMII1_RD2 */ + AM64X_IOPAD(0x0154, PIN_INPUT, 4) /* (V12) PRG1_PRU1_GPO19.RGMII1_RD3 */ + AM64X_IOPAD(0x00d8, PIN_INPUT, 4) /* (W13) PRG1_PRU0_GPO8.RGMII1_RXC */ + AM64X_IOPAD(0x00cc, PIN_INPUT, 4) /* (V13) PRG1_PRU0_GPO5.RGMII1_RX_CTL */ + AM64X_IOPAD(0x0124, PIN_OUTPUT, 4) /* (V15) PRG1_PRU1_GPO7.RGMII1_TD0 */ + AM64X_IOPAD(0x012c, PIN_OUTPUT, 4) /* (V14) PRG1_PRU1_GPO9.RGMII1_TD1 */ + AM64X_IOPAD(0x0130, PIN_OUTPUT, 4) /* (W14) PRG1_PRU1_GPO10.RGMII1_TD2 */ + AM64X_IOPAD(0x014c, PIN_OUTPUT, 4) /* (AA14) PRG1_PRU1_GPO17.RGMII1_TD3 */ + AM64X_IOPAD(0x00e0, PIN_OUTPUT, 4) /* (U14) PRG1_PRU0_GPO10.RGMII1_TXC */ + AM64X_IOPAD(0x00dc, PIN_OUTPUT, 4) /* (U15) PRG1_PRU0_GPO9.RGMII1_TX_CTL */ + >; + }; + + rgmii2_pins_default: rgmii2-pins-default { + pinctrl-single,pins = < + AM64X_IOPAD(0x0108, PIN_INPUT, 4) /* (W11) PRG1_PRU1_GPO0.RGMII2_RD0 */ + AM64X_IOPAD(0x010c, PIN_INPUT, 4) /* (V11) PRG1_PRU1_GPO1.RGMII2_RD1 */ + AM64X_IOPAD(0x0110, PIN_INPUT, 4) /* (AA12) PRG1_PRU1_GPO2.RGMII2_RD2 */ + AM64X_IOPAD(0x0114, PIN_INPUT, 4) /* (Y12) PRG1_PRU1_GPO3.RGMII2_RD3 */ + AM64X_IOPAD(0x0120, PIN_INPUT, 4) /* (U11) PRG1_PRU1_GPO6.RGMII2_RXC */ + AM64X_IOPAD(0x0118, PIN_INPUT, 4) /* (W12) PRG1_PRU1_GPO4.RGMII2_RX_CTL */ + AM64X_IOPAD(0x0134, PIN_OUTPUT, 4) /* (AA10) PRG1_PRU1_GPO11.RGMII2_TD0 */ + AM64X_IOPAD(0x0138, PIN_OUTPUT, 4) /* (V10) PRG1_PRU1_GPO12.RGMII2_TD1 */ + AM64X_IOPAD(0x013c, PIN_OUTPUT, 4) /* (U10) PRG1_PRU1_GPO13.RGMII2_TD2 */ + AM64X_IOPAD(0x0140, PIN_OUTPUT, 4) /* (AA11) PRG1_PRU1_GPO14.RGMII2_TD3 */ + AM64X_IOPAD(0x0148, PIN_OUTPUT, 4) /* (Y10) PRG1_PRU1_GPO16.RGMII2_TXC */ + AM64X_IOPAD(0x0144, PIN_OUTPUT, 4) /* (Y11) PRG1_PRU1_GPO15.RGMII2_TX_CTL */ + >; + }; }; &dmsc { @@ -182,4 +224,35 @@ phy-names = "cdns3,usb3-phy"; }; +&cpsw3g { + pinctrl-names = "default"; + pinctrl-0 = <&mdio1_pins_default + &rgmii1_pins_default + &rgmii2_pins_default>; +}; + +&cpsw_port1 { + phy-mode = "rgmii-rxid"; + phy-handle = <&cpsw3g_phy0>; +}; + +&cpsw_port2 { + phy-mode = "rgmii-rxid"; + phy-handle = <&cpsw3g_phy1>; +}; + +&cpsw3g_mdio { + cpsw3g_phy0: ethernet-phy@0 { + reg = <0>; + ti,rx-internal-delay = ; + ti,fifo-depth = ; + }; + + cpsw3g_phy1: ethernet-phy@1 { + reg = <1>; + ti,rx-internal-delay = ; + ti,fifo-depth = ; + }; +}; + #include "k3-am642-sk-u-boot.dtsi" diff --git a/arch/arm/dts/k3-am642-sk-u-boot.dtsi b/arch/arm/dts/k3-am642-sk-u-boot.dtsi index 95cf52c37f..2f5cfaa04f 100644 --- a/arch/arm/dts/k3-am642-sk-u-boot.dtsi +++ b/arch/arm/dts/k3-am642-sk-u-boot.dtsi @@ -100,15 +100,53 @@ <0x0 0x43000200 0x0 0x8>; reg-names = "cpsw_nuss", "mac_efuse"; /delete-property/ ranges; + u-boot,dm-spl; cpsw-phy-sel@04044 { compatible = "ti,am64-phy-gmii-sel"; reg = <0x0 0x43004044 0x0 0x8>; + u-boot,dm-spl; + }; + + ethernet-ports { + u-boot,dm-spl; }; }; &cpsw_port2 { - status = "disabled"; + u-boot,dm-spl; +}; + +&cpsw_port1 { + u-boot,dm-spl; +}; + +&main_bcdma { + u-boot,dm-spl; +}; + +&main_pktdma { + u-boot,dm-spl; +}; + +&rgmii1_pins_default { + u-boot,dm-spl; +}; + +&rgmii2_pins_default { + u-boot,dm-spl; +}; + +&mdio1_pins_default { + u-boot,dm-spl; +}; + +&cpsw3g_phy0 { + u-boot,dm-spl; +}; + +&cpsw3g_phy1 { + u-boot,dm-spl; }; &main_usb0_pins_default { From b6e59617c8d876876e99e1516ed2d991f25c3fe6 Mon Sep 17 00:00:00 2001 From: chao zeng Date: Fri, 7 Jan 2022 11:26:24 +0800 Subject: [PATCH 10/15] gpio: da8xx_gpio: Fix gpio name with address The GPIO bank numbers do not appear in the device tree, so make the gpio name based on the address (ie gpio@42110000_25 vs 25) Signed-off-by: chao zeng --- drivers/gpio/da8xx_gpio.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/gpio/da8xx_gpio.c b/drivers/gpio/da8xx_gpio.c index d106e9846d..b310f2dbf6 100644 --- a/drivers/gpio/da8xx_gpio.c +++ b/drivers/gpio/da8xx_gpio.c @@ -545,12 +545,20 @@ static int davinci_gpio_of_to_plat(struct udevice *dev) { struct davinci_gpio_plat *plat = dev_get_plat(dev); fdt_addr_t addr; + char name[18], *str; addr = dev_read_addr(dev); if (addr == FDT_ADDR_T_NONE) return -EINVAL; plat->base = addr; + + sprintf(name, "gpio@%4x_", (unsigned int)plat->base); + str = strdup(name); + if (!str) + return -ENOMEM; + plat->port_name = str; + return 0; } From e660cfad5339719721a96257090ae47bbc2abee6 Mon Sep 17 00:00:00 2001 From: Christian Gmeiner Date: Thu, 16 Dec 2021 10:57:29 +0100 Subject: [PATCH 11/15] omap: timer: implement timer_get_boot_us To make the OMAP DM timer driver useful for the timing of bootstages, we need to implement timer_get_boot_us(..). Signed-off-by: Christian Gmeiner --- drivers/timer/omap-timer.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/drivers/timer/omap-timer.c b/drivers/timer/omap-timer.c index 721e385fd1..25a6108fef 100644 --- a/drivers/timer/omap-timer.c +++ b/drivers/timer/omap-timer.c @@ -83,6 +83,27 @@ static int omap_timer_of_to_plat(struct udevice *dev) return 0; } +#if CONFIG_IS_ENABLED(BOOTSTAGE) +ulong timer_get_boot_us(void) +{ + u64 ticks = 0; + u32 rate = 1; + u64 us; + int ret; + + ret = dm_timer_init(); + if (!ret) { + /* The timer is available */ + rate = timer_get_rate(gd->timer); + timer_get_count(gd->timer, &ticks); + } else { + return 0; + } + + us = (ticks * 1000) / rate; + return us; +} +#endif static const struct timer_ops omap_timer_ops = { .get_count = omap_timer_get_count, From 5ce7df1078a506f01d63d821b6531fac86e079b9 Mon Sep 17 00:00:00 2001 From: Amjad Ouled-Ameur Date: Mon, 6 Dec 2021 18:22:00 +0100 Subject: [PATCH 12/15] configs: am43xx_hs_evm: Add SPL_USB_STORAGE Support Enable CONFIG_SPL_USB_STORAGE to support UBS MSC boot support. Signed-off-by: Faiz Abbas Signed-off-by: Amjad Ouled-Ameur --- configs/am43xx_hs_evm_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/configs/am43xx_hs_evm_defconfig b/configs/am43xx_hs_evm_defconfig index 3ff2e5b622..d4bebd2c01 100644 --- a/configs/am43xx_hs_evm_defconfig +++ b/configs/am43xx_hs_evm_defconfig @@ -33,6 +33,7 @@ CONFIG_SPL_NAND_BASE=y CONFIG_SPL_NET=y CONFIG_SPL_NET_VCI_STRING="AM43xx U-Boot SPL" CONFIG_SPL_USB_HOST=y +CONFIG_SPL_USB_STORAGE=y CONFIG_SPL_USB_GADGET=y CONFIG_SPL_USB_ETHER=y CONFIG_SYS_I2C_EEPROM_ADDR_LEN=2 From a6e562fe36b2bae780589a81a11fceb6e1b4a9f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20M=C3=A4tje?= Date: Tue, 30 Nov 2021 01:06:56 +0100 Subject: [PATCH 13/15] Fix wrong QSPI clock calculation for AM4372 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On AM4372 the SPI_GCLK input gets its clock from the PRCM module which divides the PER_CLKOUTM2 frequency (192MHz) by a fixed factor of 4. See AM437x Reference Manual in section 27 QSPI >> 27.2 Integration. The QSPI_FCLK therefore needs to take this factor into account and becomes (192000000 / 4). Signed-off-by: Stefan Mätje --- drivers/spi/ti_qspi.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/spi/ti_qspi.c b/drivers/spi/ti_qspi.c index c542f40c7d..99acb10882 100644 --- a/drivers/spi/ti_qspi.c +++ b/drivers/spi/ti_qspi.c @@ -30,7 +30,8 @@ DECLARE_GLOBAL_DATA_PTR; /* ti qpsi register bit masks */ #define QSPI_TIMEOUT 2000000 -#define QSPI_FCLK 192000000 +/* AM4372: QSPI gets SPI_GCLK from PRCM unit as PER_CLKOUTM2 divided by 4. */ +#define QSPI_FCLK (192000000 / 4) #define QSPI_DRA7XX_FCLK 76800000 #define QSPI_WLEN_MAX_BITS 128 #define QSPI_WLEN_MAX_BYTES (QSPI_WLEN_MAX_BITS >> 3) From f44bcb9f0d73c13738b8f3e437bda75fda642ad7 Mon Sep 17 00:00:00 2001 From: David Rivshin Date: Thu, 18 Nov 2021 13:25:24 -0500 Subject: [PATCH 14/15] nand: gpmc: Handle bitflips in erased pages when using BCH ECC engine In the case of an erased (sub)page both the data and ECC are all 0xFF bytes. This fails the normal ECC verification, as the computed ECC of all-0xFF is not also 0xFF. The GPMC NAND driver attempted to detect erased pages by checking that the ECC bytes are all-0xFF, but this had two problems: 1) bitflips in the data were not corrected, so the data looked not-erased 2) bitflips in the ECC bytes were reported as uncorrectable ECC errors The equivalent Linux driver [1] correctly handles this by counting the number of 0-bits in the combination of data and ECC bytes. If the number of 0-bits is less than the amount of bits correctable by the selected ECC algorithm, then it is treated as an erased page with correctable bitflips. Implement similar, though simplified, logic in omap_correct_data_bch(). [1] see omap_elm_correct_data() in omap2.c Signed-off-by: David Rivshin --- drivers/mtd/nand/raw/omap_gpmc.c | 45 +++++++++++++++++++++++++------- 1 file changed, 36 insertions(+), 9 deletions(-) diff --git a/drivers/mtd/nand/raw/omap_gpmc.c b/drivers/mtd/nand/raw/omap_gpmc.c index 530574898c..107447f9df 100644 --- a/drivers/mtd/nand/raw/omap_gpmc.c +++ b/drivers/mtd/nand/raw/omap_gpmc.c @@ -507,19 +507,45 @@ static int omap_correct_data_bch(struct mtd_info *mtd, uint8_t *dat, /* check calculated ecc */ for (i = 0; i < ecc->bytes && !ecc_flag; i++) { if (calc_ecc[i] != 0x00) - ecc_flag = 1; + goto not_ecc_match; } - if (!ecc_flag) - return 0; + return 0; +not_ecc_match: - /* check for whether its a erased-page */ - ecc_flag = 0; - for (i = 0; i < ecc->bytes && !ecc_flag; i++) { + /* check for whether it's an erased-page */ + for (i = 0; i < ecc->bytes; i++) { if (read_ecc[i] != 0xff) - ecc_flag = 1; + goto not_erased; + } + for (i = 0; i < SECTOR_BYTES; i++) { + if (dat[i] != 0xff) + goto not_erased; + } + return 0; +not_erased: + + /* + * Check for whether it's an erased page with a correctable + * number of bitflips. Erased pages have all 1's in the data, + * so we just compute the number of 0 bits in the data and + * see if it's under the correction threshold. + * + * NOTE: The check for a perfect erased page above is faster for + * the more common case, even though it's logically redundant. + */ + for (i = 0; i < ecc->bytes; i++) + error_count += hweight8(~read_ecc[i]); + + for (i = 0; i < SECTOR_BYTES; i++) + error_count += hweight8(~dat[i]); + + if (error_count <= ecc->strength) { + memset(read_ecc, 0xFF, ecc->bytes); + memset(dat, 0xFF, SECTOR_BYTES); + debug("nand: %u bit-flip(s) corrected in erased page\n", + error_count); + return error_count; } - if (!ecc_flag) - return 0; /* * while reading ECC result we read it in big endian. @@ -539,6 +565,7 @@ static int omap_correct_data_bch(struct mtd_info *mtd, uint8_t *dat, } /* use elm module to check for errors */ elm_config(bch_type); + error_count = 0; err = elm_check_error(calc_ecc, bch_type, &error_count, error_loc); if (err) return err; From 609983e981a0a7f053ee6f9f6cd2772226a33000 Mon Sep 17 00:00:00 2001 From: Amjad Ouled-Ameur Date: Fri, 29 Oct 2021 16:08:17 +0200 Subject: [PATCH 15/15] board: ti: am335x: Choose CPSW or PRUSS configuration based on jumper setting The am335x-ice-v2 board's Ethernet ports can be configured in 'MII' or 'RMII' mode to be connected to 'PRUSS' or 'CPSW' Ethernet subsystems. This patch sets the environment variable 'ice_mii' to 'mii' or 'rmii' accordingly. Based on that we choose the appropriate board devicetree i.e. 'am335x-ice-v2.dtb' or 'am335x-ice-v2-prueth.dtb'. Since there are 2 Ethernet ports with 2 modes, there can be 4 configurations but for now we consider both ports in different modes to be an invalid configuration and prevent boot in that case. Signed-off-by: Roger Quadros [Amjad: use overlay instead of using new am335x-ice-v2-prueth.dtb] Signed-off-by: Amjad Ouled-Ameur Reviewed-by: Tom Rini [trini: Make prueth_is_mii be marked __maybe_unused] Signed-off-by: Tom Rini --- board/ti/am335x/board.c | 18 ++++++++++++++++++ include/configs/am335x_evm.h | 5 ++++- include/configs/ti_armv7_common.h | 1 + 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/board/ti/am335x/board.c b/board/ti/am335x/board.c index e8555de9c9..9b7067040a 100644 --- a/board/ti/am335x/board.c +++ b/board/ti/am335x/board.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -38,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -691,6 +693,8 @@ done: } #endif +static bool __maybe_unused prueth_is_mii = true; + /* * Basic board specific setup. Pinmux has been handled already. */ @@ -710,6 +714,8 @@ int board_init(void) if (board_is_icev2()) { int rv; u32 reg; + bool eth0_is_mii = true; + bool eth1_is_mii = true; REQUEST_AND_SET_GPIO(GPIO_PR1_MII_CTRL); /* Make J19 status available on GPIO1_26 */ @@ -740,6 +746,7 @@ int board_init(void) writel(reg, GPIO0_IRQSTATUS1); /* clear irq */ /* RMII mode */ printf("ETH0, CPSW\n"); + eth0_is_mii = false; } else { /* MII mode */ printf("ETH0, PRU\n"); @@ -752,12 +759,21 @@ int board_init(void) /* RMII mode */ printf("ETH1, CPSW\n"); gpio_set_value(GPIO_MUX_MII_CTRL, 1); + eth1_is_mii = false; } else { /* MII mode */ printf("ETH1, PRU\n"); cdce913_data.pdiv2 = 4; /* 25MHz PHY clk */ } + if (eth0_is_mii != eth1_is_mii) { + printf("Unsupported Ethernet port configuration\n"); + printf("Both ports must be set as RMII or MII\n"); + hang(); + } + + prueth_is_mii = eth0_is_mii; + /* disable rising edge IRQs */ reg = readl(GPIO0_RISINGDETECT) & ~BIT(11); writel(reg, GPIO0_RISINGDETECT); @@ -852,6 +868,8 @@ int board_late_init(void) if (is_valid_ethaddr(mac_addr)) eth_env_set_enetaddr("eth1addr", mac_addr); } + + env_set("ice_mii", prueth_is_mii ? "mii" : "rmii"); #endif if (!env_get("serial#")) { diff --git a/include/configs/am335x_evm.h b/include/configs/am335x_evm.h index 7fb1b3a3e3..0f340806ef 100644 --- a/include/configs/am335x_evm.h +++ b/include/configs/am335x_evm.h @@ -143,7 +143,10 @@ "if test $board_name = A335X_SK; then " \ "setenv fdtfile am335x-evmsk.dtb; fi; " \ "if test $board_name = A335_ICE; then " \ - "setenv fdtfile am335x-icev2.dtb; fi; " \ + "setenv fdtfile am335x-icev2.dtb; " \ + "if test $ice_mii = mii; then " \ + "setenv pxe_label_override Pruss; fi;" \ + "fi; " \ "if test $fdtfile = undefined; then " \ "echo WARNING: Could not determine device tree to use; fi; \0" \ "init_console=" \ diff --git a/include/configs/ti_armv7_common.h b/include/configs/ti_armv7_common.h index fa48cd2818..797e121198 100644 --- a/include/configs/ti_armv7_common.h +++ b/include/configs/ti_armv7_common.h @@ -37,6 +37,7 @@ "fdtaddr=0x88000000\0" \ "dtboaddr=0x89000000\0" \ "fdt_addr_r=0x88000000\0" \ + "fdtoverlay_addr_r=0x89000000\0" \ "rdaddr=0x88080000\0" \ "ramdisk_addr_r=0x88080000\0" \ "scriptaddr=0x80000000\0" \