From 4987bc2a1aea7e444a606ad887826f355486174a Mon Sep 17 00:00:00 2001 From: Anatolij Gustschin Date: Wed, 10 Jul 2019 19:44:15 +0200 Subject: [PATCH 01/20] board: siemens: adapt factoryset reading for DM_I2C enabled boards For new boards we always enable DM_I2C. Extend factoryset functions to support EEPROM reading on these boards. Signed-off-by: Anatolij Gustschin --- board/siemens/common/factoryset.c | 45 +++++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/board/siemens/common/factoryset.c b/board/siemens/common/factoryset.c index 96615424f6..1dda897f18 100644 --- a/board/siemens/common/factoryset.c +++ b/board/siemens/common/factoryset.c @@ -8,6 +8,7 @@ #if !defined(CONFIG_SPL_BUILD) #include +#include #include #include #include @@ -143,16 +144,39 @@ int factoryset_read_eeprom(int i2c_addr) int i, pages = 0, size = 0; unsigned char eeprom_buf[0x3c00], hdr[4], buf[MAX_STRING_LENGTH]; unsigned char *cp, *cp1; +#if CONFIG_IS_ENABLED(DM_I2C) + struct udevice *bus, *dev; + int ret; +#endif #if defined(CONFIG_DFU_OVER_USB) factory_dat.usb_vendor_id = CONFIG_USB_GADGET_VENDOR_NUM; factory_dat.usb_product_id = CONFIG_USB_GADGET_PRODUCT_NUM; #endif + +#if CONFIG_IS_ENABLED(DM_I2C) + ret = uclass_get_device_by_seq(UCLASS_I2C, EEPROM_I2C_BUS, &bus); + if (ret) + goto err; + + ret = dm_i2c_probe(bus, i2c_addr, 0, &dev); + if (ret) + goto err; + + ret = i2c_set_chip_offset_len(dev, 2); + if (ret) + goto err; + + ret = dm_i2c_read(dev, EEPROM_FATORYSET_OFFSET, hdr, sizeof(hdr)); + if (ret) + goto err; +#else if (i2c_probe(i2c_addr)) goto err; if (i2c_read(i2c_addr, EEPROM_FATORYSET_OFFSET, 2, hdr, sizeof(hdr))) goto err; +#endif if ((hdr[0] != 0x99) || (hdr[1] != 0x80)) { printf("FactorySet is not right in eeprom.\n"); @@ -173,16 +197,33 @@ int factoryset_read_eeprom(int i2c_addr) * data after every time we got a record from eeprom */ debug("Read eeprom page :\n"); - for (i = 0; i < pages; i++) + for (i = 0; i < pages; i++) { +#if CONFIG_IS_ENABLED(DM_I2C) + ret = dm_i2c_read(dev, (OFF_PG + i) * EEPR_PG_SZ, + eeprom_buf + (i * EEPR_PG_SZ), EEPR_PG_SZ); + if (ret) + goto err; +#else if (i2c_read(i2c_addr, (OFF_PG + i) * EEPR_PG_SZ, 2, eeprom_buf + (i * EEPR_PG_SZ), EEPR_PG_SZ)) goto err; +#endif + } - if (size % EEPR_PG_SZ) + if (size % EEPR_PG_SZ) { +#if CONFIG_IS_ENABLED(DM_I2C) + ret = dm_i2c_read(dev, (OFF_PG + pages) * EEPR_PG_SZ, + eeprom_buf + (pages * EEPR_PG_SZ), + size % EEPR_PG_SZ); + if (ret) + goto err; +#else if (i2c_read(i2c_addr, (OFF_PG + pages) * EEPR_PG_SZ, 2, eeprom_buf + (pages * EEPR_PG_SZ), (size % EEPR_PG_SZ))) goto err; +#endif + } /* we do below just for eeprom align */ for (i = 0; i < size; i++) From 490e6d68597dc41d6d2a767927652470b19c2bd9 Mon Sep 17 00:00:00 2001 From: Anatolij Gustschin Date: Wed, 10 Jul 2019 19:44:16 +0200 Subject: [PATCH 02/20] board: siemens: extend factoryset reading for giedi and deneb boards giedi and deneb are i.MX8X based and have additional data with WLAN MAC in factoryset container. Enable building for these boards and adapt factoryset functions to set WLAN MAC and dtb name in environment. Signed-off-by: Anatolij Gustschin --- board/siemens/common/factoryset.c | 78 +++++++++++++++++++++++++------ board/siemens/common/factoryset.h | 3 ++ 2 files changed, 66 insertions(+), 15 deletions(-) diff --git a/board/siemens/common/factoryset.c b/board/siemens/common/factoryset.c index 1dda897f18..40456a5392 100644 --- a/board/siemens/common/factoryset.c +++ b/board/siemens/common/factoryset.c @@ -243,6 +243,20 @@ int factoryset_read_eeprom(int i2c_addr) cp1 += 3; } +#if CONFIG_IS_ENABLED(TARGET_GIEDI) || CONFIG_IS_ENABLED(TARGET_DENEB) + /* get mac address for WLAN */ + ret = get_factory_record_val(cp, size, (uchar *)"WLAN1", (uchar *)"mac", + buf, MAX_STRING_LENGTH); + if (ret > 0) { + cp1 = buf; + for (i = 0; i < 6; i++) { + factory_dat.mac_wlan[i] = simple_strtoul((char *)cp1, + NULL, 16); + cp1 += 3; + } + } +#endif + #if defined(CONFIG_DFU_OVER_USB) /* read vid and pid for dfu mode */ if (0 <= get_factory_record_val(cp, size, (uchar *)"USBD1", @@ -305,42 +319,76 @@ err: return 1; } -static struct ctrl_dev *cdev = (struct ctrl_dev *)CTRL_DEVICE_BASE; +static int get_mac_from_efuse(uint8_t mac[6]) +{ +#ifdef CONFIG_AM33XX + struct ctrl_dev *cdev = (struct ctrl_dev *)CTRL_DEVICE_BASE; + uint32_t mac_hi, mac_lo; + + mac_lo = readl(&cdev->macid0l); + mac_hi = readl(&cdev->macid0h); + + mac[0] = mac_hi & 0xFF; + mac[1] = (mac_hi & 0xFF00) >> 8; + mac[2] = (mac_hi & 0xFF0000) >> 16; + mac[3] = (mac_hi & 0xFF000000) >> 24; + mac[4] = mac_lo & 0xFF; + mac[5] = (mac_lo & 0xFF00) >> 8; +#else + /* unhandled */ + memset(mac, 0, 6); +#endif + if (!is_valid_ethaddr(mac)) { + puts("Warning: ethaddr not set by FactorySet or E-fuse. "); + puts("Set variable to overcome this.\n"); + return -1; + } + return 0; +} static int factoryset_mac_env_set(void) { uint8_t mac_addr[6]; + /* Set mac from factoryset or try reading E-fuse */ debug("FactorySet: Set mac address\n"); if (is_valid_ethaddr(factory_dat.mac)) { memcpy(mac_addr, factory_dat.mac, 6); } else { - uint32_t mac_hi, mac_lo; - debug("Warning: FactorySet: not set. Fallback to E-fuse\n"); - mac_lo = readl(&cdev->macid0l); - mac_hi = readl(&cdev->macid0h); - - mac_addr[0] = mac_hi & 0xFF; - mac_addr[1] = (mac_hi & 0xFF00) >> 8; - mac_addr[2] = (mac_hi & 0xFF0000) >> 16; - mac_addr[3] = (mac_hi & 0xFF000000) >> 24; - mac_addr[4] = mac_lo & 0xFF; - mac_addr[5] = (mac_lo & 0xFF00) >> 8; - if (!is_valid_ethaddr(mac_addr)) { - printf("Warning: ethaddr not set by FactorySet or E-fuse. Set variable to overcome this.\n"); + if (get_mac_from_efuse(mac_addr) < 0) return -1; - } } eth_env_set_enetaddr("ethaddr", mac_addr); + +#if CONFIG_IS_ENABLED(TARGET_GIEDI) || CONFIG_IS_ENABLED(TARGET_DENEB) + eth_env_set_enetaddr("eth1addr", mac_addr); + + /* wlan mac */ + if (is_valid_ethaddr(factory_dat.mac_wlan)) + eth_env_set_enetaddr("eth2addr", factory_dat.mac_wlan); +#endif return 0; } +static void factoryset_dtb_env_set(void) +{ + /* Set ASN in environment*/ + if (factory_dat.asn[0] != 0) { + env_set("dtb_name", (char *)factory_dat.asn); + } else { + /* dtb suffix gets added in load script */ + env_set("dtb_name", "default"); + } +} + int factoryset_env_set(void) { int ret = 0; + factoryset_dtb_env_set(); + if (factoryset_mac_env_set() < 0) ret = -1; diff --git a/board/siemens/common/factoryset.h b/board/siemens/common/factoryset.h index d4e8353249..261a217687 100644 --- a/board/siemens/common/factoryset.h +++ b/board/siemens/common/factoryset.h @@ -11,6 +11,9 @@ struct factorysetcontainer { uchar mac[6]; +#if CONFIG_IS_ENABLED(TARGET_GIEDI) || CONFIG_IS_ENABLED(TARGET_DENEB) + uchar mac_wlan[6]; +#endif int usb_vendor_id; int usb_product_id; int pxm50; From 2800bb155b57b5e6a25e4bbc1e30e9032a03f197 Mon Sep 17 00:00:00 2001 From: Anselm Busse Date: Wed, 31 Jul 2019 17:30:28 +0200 Subject: [PATCH 03/20] ARM: omap3: overo: Fix MMC init for SPL The SPL for the Overo board does not initialise the MMC. Hence, it cannot load the main boot loader from the SD card susequently. This patch moves the initialisation code for the MMC so it gets included in the SPL. [trini: Add missing header] Signed-off-by: Tom Rini --- board/overo/common.c | 26 ++++++++++++++++++++++++++ board/overo/overo.c | 14 -------------- 2 files changed, 26 insertions(+), 14 deletions(-) diff --git a/board/overo/common.c b/board/overo/common.c index fc02d66d53..2c4f412e5d 100644 --- a/board/overo/common.c +++ b/board/overo/common.c @@ -17,6 +17,7 @@ #include #include #include +#include #include DECLARE_GLOBAL_DATA_PTR; @@ -38,6 +39,31 @@ int board_init(void) return 0; } +#if defined(CONFIG_MMC) +int board_mmc_init(bd_t *bis) +{ + return omap_mmc_init(0, 0, 0, -1, -1); +} +#endif + +#if defined(CONFIG_MMC) +void board_mmc_power_init(void) +{ + twl4030_power_mmc_init(0); +} +#endif + +#if defined(CONFIG_SPL_OS_BOOT) +int spl_start_uboot(void) +{ + /* break into full u-boot on 'c' */ + if (serial_tstc() && serial_getc() == 'c') + return 1; + + return 0; +} +#endif /* CONFIG_SPL_OS_BOOT */ + #define MUX_OVERO() \ /*SDRC*/\ MUX_VAL(CP(SDRC_D0), (IEN | PTD | DIS | M0)) /*SDRC_D0*/\ diff --git a/board/overo/overo.c b/board/overo/overo.c index 8fa41f8155..3d57f945f4 100644 --- a/board/overo/overo.c +++ b/board/overo/overo.c @@ -376,20 +376,6 @@ int board_eth_init(bd_t *bis) } #endif -#if defined(CONFIG_MMC) -int board_mmc_init(bd_t *bis) -{ - return omap_mmc_init(0, 0, 0, -1, -1); -} -#endif - -#if defined(CONFIG_MMC) -void board_mmc_power_init(void) -{ - twl4030_power_mmc_init(0); -} -#endif - #if defined(CONFIG_USB_EHCI_HCD) static struct omap_usbhs_board_data usbhs_bdata = { .port_mode[0] = OMAP_USBHS_PORT_MODE_UNUSED, From 7659ea32a6e99c4880ee38df90522876490788ad Mon Sep 17 00:00:00 2001 From: Suniel Mahesh Date: Wed, 31 Jul 2019 21:54:06 +0530 Subject: [PATCH 04/20] watchdog: omap_wdt: Convert watchdog driver to use DT and DM This patch adds device tree and driver model watchdog support, converts the legacy omap watchdog driver to driver model for TI AM335x chipsets. The following compile warning is removed: ===================== WARNING ====================== This board does not use CONFIG_WDT (DM watchdog support). Please update the board to use CONFIG_WDT before the v2019.10 release. Failure to update by the deadline may result in board removal. See doc/driver-model/MIGRATION.txt for more info. ==================================================== CONFIG_HW_WATCHDOG is no more a default option for AM33XX devices after DT/DM conversion, adjusted kconfig accordingly. DM watchdog support is enabled by default in SPL. The SPL image doesn't fit into SRAM because of size constraints and build breaks with an overflow. For this reason DM watchdog support should be disabled in SPL, driver code should be adjusted accordingly to serve this purpose. Built and tested on AM335x device (BeagleboneBlack), compile tested for all other AM33xx based boards. Signed-off-by: Suniel Mahesh --- arch/arm/include/asm/ti-common/omap_wdt.h | 5 + configs/am335x_evm_defconfig | 2 + drivers/watchdog/Kconfig | 9 +- drivers/watchdog/Makefile | 1 + drivers/watchdog/omap_wdt.c | 114 ++++++++++++++++++++++ 5 files changed, 130 insertions(+), 1 deletion(-) diff --git a/arch/arm/include/asm/ti-common/omap_wdt.h b/arch/arm/include/asm/ti-common/omap_wdt.h index 7d72e3af02..fbc421b630 100644 --- a/arch/arm/include/asm/ti-common/omap_wdt.h +++ b/arch/arm/include/asm/ti-common/omap_wdt.h @@ -56,4 +56,9 @@ struct wd_timer { unsigned int wdt_unfr; /* offset 0x100 */ }; +struct omap3_wdt_priv { + struct wd_timer *regs; + unsigned int wdt_trgr_pattern; +}; + #endif /* __OMAP_WDT_H__ */ diff --git a/configs/am335x_evm_defconfig b/configs/am335x_evm_defconfig index ff96f192e0..fa6b03060a 100644 --- a/configs/am335x_evm_defconfig +++ b/configs/am335x_evm_defconfig @@ -58,6 +58,8 @@ CONFIG_DM_SPI=y CONFIG_OMAP3_SPI=y CONFIG_TIMER=y CONFIG_OMAP_TIMER=y +CONFIG_WDT=y +CONFIG_WDT_OMAP3=y CONFIG_USB=y CONFIG_DM_USB=y CONFIG_DM_USB_GADGET=y diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 1e5d14c4ff..a66a9bcbe2 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -28,7 +28,6 @@ config OMAP_WATCHDOG bool "TI OMAP watchdog driver" depends on ARCH_OMAP2PLUS select HW_WATCHDOG - default y if AM33XX help Say Y here to enable the OMAP3+ watchdog driver. @@ -113,6 +112,14 @@ config WDT_MTK The watchdog timer is stopped when initialized. It performs full SoC reset. +config WDT_OMAP3 + bool "TI OMAP watchdog timer support" + depends on WDT && ARCH_OMAP2PLUS + default y if AM33XX + help + This enables OMAP3+ watchdog timer driver, which can be + found on some TI chipsets and inline with driver model. + config WDT_ORION bool "Orion watchdog timer support" depends on WDT diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index 414ba2430a..955caef815 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -25,6 +25,7 @@ obj-$(CONFIG_WDT_CDNS) += cdns_wdt.o obj-$(CONFIG_WDT_MPC8xx) += mpc8xx_wdt.o obj-$(CONFIG_WDT_MT7621) += mt7621_wdt.o obj-$(CONFIG_WDT_MTK) += mtk_wdt.o +obj-$(CONFIG_WDT_OMAP3) += omap_wdt.o obj-$(CONFIG_WDT_SP805) += sp805_wdt.o obj-$(CONFIG_WDT_STM32MP) += stm32mp_wdt.o obj-$(CONFIG_WDT_TANGIER) += tangier_wdt.o diff --git a/drivers/watchdog/omap_wdt.c b/drivers/watchdog/omap_wdt.c index 343adb00c7..86f7cf1aaf 100644 --- a/drivers/watchdog/omap_wdt.c +++ b/drivers/watchdog/omap_wdt.c @@ -42,10 +42,14 @@ #include #include #include +#include +#include +#include /* Hardware timeout in seconds */ #define WDT_HW_TIMEOUT 60 +#if !CONFIG_IS_ENABLED(WDT) static unsigned int wdt_trgr_pattern = 0x1234; void hw_watchdog_reset(void) @@ -134,3 +138,113 @@ void hw_watchdog_init(void) while ((readl(&wdt->wdtwwps)) & WDT_WWPS_PEND_WSPR) ; } +#else +static int omap3_wdt_reset(struct udevice *dev) +{ + struct omap3_wdt_priv *priv = dev_get_priv(dev); + + priv->wdt_trgr_pattern = 0x1234; +/* + * Somebody just triggered watchdog reset and write to WTGR register + * is in progress. It is resetting right now, no need to trigger it + * again + */ + if ((readl(&priv->regs->wdtwwps)) & WDT_WWPS_PEND_WTGR) + return 0; + + priv->wdt_trgr_pattern = ~(priv->wdt_trgr_pattern); + writel(priv->wdt_trgr_pattern, &priv->regs->wdtwtgr); +/* + * Don't wait for posted write to complete, i.e. don't check + * WDT_WWPS_PEND_WTGR bit in WWPS register. There is no writes to + * WTGR register outside of this func, and if entering it + * we see WDT_WWPS_PEND_WTGR bit set, it means watchdog reset + * was just triggered. This prevents us from wasting time in busy + * polling of WDT_WWPS_PEND_WTGR bit. + */ + return 0; +} + +static int omap3_wdt_stop(struct udevice *dev) +{ + struct omap3_wdt_priv *priv = dev_get_priv(dev); + +/* disable watchdog */ + writel(0xAAAA, &priv->regs->wdtwspr); + while (readl(&priv->regs->wdtwwps) != 0x0) + ; + writel(0x5555, &priv->regs->wdtwspr); + while (readl(&priv->regs->wdtwwps) != 0x0) + ; + return 0; +} + +static int omap3_wdt_start(struct udevice *dev, u64 timeout_ms, ulong flags) +{ + struct omap3_wdt_priv *priv = dev_get_priv(dev); + u32 pre_margin = GET_WLDR_VAL(timeout_ms); +/* + * Make sure the watchdog is disabled. This is unfortunately required + * because writing to various registers with the watchdog running has no + * effect. + */ + omap3_wdt_stop(dev); + +/* initialize prescaler */ + while (readl(&priv->regs->wdtwwps) & WDT_WWPS_PEND_WCLR) + ; + + writel(WDT_WCLR_PRE | (PTV << WDT_WCLR_PTV_OFF), &priv->regs->wdtwclr); + while (readl(&priv->regs->wdtwwps) & WDT_WWPS_PEND_WCLR) + ; +/* just count up at 32 KHz */ + while (readl(&priv->regs->wdtwwps) & WDT_WWPS_PEND_WLDR) + ; + + writel(pre_margin, &priv->regs->wdtwldr); + while (readl(&priv->regs->wdtwwps) & WDT_WWPS_PEND_WLDR) + ; +/* Sequence to enable the watchdog */ + writel(0xBBBB, &priv->regs->wdtwspr); + while ((readl(&priv->regs->wdtwwps)) & WDT_WWPS_PEND_WSPR) + ; + + writel(0x4444, &priv->regs->wdtwspr); + while ((readl(&priv->regs->wdtwwps)) & WDT_WWPS_PEND_WSPR) + ; + + return 0; +} + +static int omap3_wdt_probe(struct udevice *dev) +{ + struct omap3_wdt_priv *priv = dev_get_priv(dev); + + priv->regs = (struct wd_timer *)devfdt_get_addr(dev); + if (!priv->regs) + return -EINVAL; + + debug("%s: Probing wdt%u\n", __func__, dev->seq); + return 0; +} + +static const struct wdt_ops omap3_wdt_ops = { + .start = omap3_wdt_start, + .stop = omap3_wdt_stop, + .reset = omap3_wdt_reset, +}; + +static const struct udevice_id omap3_wdt_ids[] = { + { .compatible = "ti,omap3-wdt" }, + { } +}; + +U_BOOT_DRIVER(omap3_wdt) = { + .name = "omap3_wdt", + .id = UCLASS_WDT, + .of_match = omap3_wdt_ids, + .ops = &omap3_wdt_ops, + .probe = omap3_wdt_probe, + .priv_auto_alloc_size = sizeof(struct omap3_wdt_priv), +}; +#endif /* !CONFIG_IS_ENABLED(WDT) */ From 6912f2a8ae9d98203cb2470c472d3f2fde78357b Mon Sep 17 00:00:00 2001 From: Suniel Mahesh Date: Wed, 31 Jul 2019 21:54:07 +0530 Subject: [PATCH 05/20] watchdog: omap_wdt: Disable DM watchdog support in SPL This patch disables DM watchdog support for SPL builds and uses the legacy omap watchdog driver on TI AM335x chipsets. The following build error is reported if DM watchdog support was enabled in SPL: CC spl/drivers/usb/gadget/rndis.o LD spl/drivers/usb/gadget/built-in.o LD spl/drivers/usb/musb-new/built-in.o LD spl/drivers/built-in.o LD spl/u-boot-spl arm-linux-ld.bfd: u-boot-spl section .u_boot_list will not fit in region .sram arm-linux-ld.bfd: region .sram overflowed by 440 bytes make[1]: *** [spl/u-boot-spl] Error 1 make: *** [spl/u-boot-spl] Error 2 Adjusted WATCHDOG_RESET macro accordingly. Earlier it was pointing to hw_watchdog_reset. Since CONFIG_WATCHDOG replaces CONFIG_HW_WATCHDOG, now WATCHDOG_RESET macro points to watchdog_reset. This watchdog_reset is not defined anywhere for am33xx/omap2 and needs to be defined. Fixed this by simply calling hw_watchdog_reset in watchdog_reset. Built and tested on AM335x device (BeagleboneBlack), compile tested for all other AM33xx/omap2 based boards. Signed-off-by: Suniel Mahesh [trini: Fix watchdog.h logic] Signed-off-by: Tom Rini --- arch/arm/mach-omap2/boot-common.c | 2 +- configs/am335x_evm_defconfig | 1 + drivers/watchdog/omap_wdt.c | 7 +++++++ include/watchdog.h | 2 +- 4 files changed, 10 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-omap2/boot-common.c b/arch/arm/mach-omap2/boot-common.c index c8b8ac657f..c9549aafb9 100644 --- a/arch/arm/mach-omap2/boot-common.c +++ b/arch/arm/mach-omap2/boot-common.c @@ -208,7 +208,7 @@ void spl_board_init(void) #if defined(CONFIG_AM33XX) && defined(CONFIG_SPL_MUSB_NEW_SUPPORT) arch_misc_init(); #endif -#if defined(CONFIG_HW_WATCHDOG) +#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) hw_watchdog_init(); #endif #ifdef CONFIG_AM33XX diff --git a/configs/am335x_evm_defconfig b/configs/am335x_evm_defconfig index fa6b03060a..c0f7cccd8b 100644 --- a/configs/am335x_evm_defconfig +++ b/configs/am335x_evm_defconfig @@ -60,6 +60,7 @@ CONFIG_TIMER=y CONFIG_OMAP_TIMER=y CONFIG_WDT=y CONFIG_WDT_OMAP3=y +# CONFIG_SPL_WDT is not set CONFIG_USB=y CONFIG_DM_USB=y CONFIG_DM_USB_GADGET=y diff --git a/drivers/watchdog/omap_wdt.c b/drivers/watchdog/omap_wdt.c index 86f7cf1aaf..d5857be867 100644 --- a/drivers/watchdog/omap_wdt.c +++ b/drivers/watchdog/omap_wdt.c @@ -138,7 +138,14 @@ void hw_watchdog_init(void) while ((readl(&wdt->wdtwwps)) & WDT_WWPS_PEND_WSPR) ; } + +void watchdog_reset(void) +{ + hw_watchdog_reset(); +} + #else + static int omap3_wdt_reset(struct udevice *dev) { struct omap3_wdt_priv *priv = dev_get_priv(dev); diff --git a/include/watchdog.h b/include/watchdog.h index 3a357de903..a4a4e8e614 100644 --- a/include/watchdog.h +++ b/include/watchdog.h @@ -77,7 +77,7 @@ int init_func_watchdog_reset(void); * Prototypes from $(CPU)/cpu.c. */ -#if defined(CONFIG_HW_WATCHDOG) && !defined(__ASSEMBLY__) +#if (defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)) && !defined(__ASSEMBLY__) void hw_watchdog_init(void); #endif From 60df809f626016d9992a7e894799a675c61d4d4b Mon Sep 17 00:00:00 2001 From: Hannes Schmelzer Date: Thu, 1 Aug 2019 07:04:46 +0200 Subject: [PATCH 06/20] board/BuR/brsmarc1: initial commit This commit adds support for the B&R brsmarc1 SoM. The SoM is based on TI's AM335x SoC. Mainly vxWorks 6.9.4.x is running on the board, doing some PLC stuff on various carrier boards. Signed-off-by: Hannes Schmelzer --- arch/arm/dts/Makefile | 1 + arch/arm/dts/am335x-brsmarc1.dts | 416 +++++++++++++++++++++++++++++ arch/arm/mach-omap2/Kconfig | 1 + arch/arm/mach-omap2/am33xx/Kconfig | 4 + board/BuR/brsmarc1/Kconfig | 15 ++ board/BuR/brsmarc1/MAINTAINERS | 6 + board/BuR/brsmarc1/Makefile | 10 + board/BuR/brsmarc1/board.c | 168 ++++++++++++ board/BuR/brsmarc1/config.mk | 33 +++ board/BuR/brsmarc1/mux.c | 266 ++++++++++++++++++ configs/brsmarc1_defconfig | 109 ++++++++ include/configs/brsmarc1.h | 83 ++++++ 12 files changed, 1112 insertions(+) create mode 100644 arch/arm/dts/am335x-brsmarc1.dts create mode 100644 board/BuR/brsmarc1/Kconfig create mode 100644 board/BuR/brsmarc1/MAINTAINERS create mode 100644 board/BuR/brsmarc1/Makefile create mode 100644 board/BuR/brsmarc1/board.c create mode 100644 board/BuR/brsmarc1/config.mk create mode 100644 board/BuR/brsmarc1/mux.c create mode 100644 configs/brsmarc1_defconfig create mode 100644 include/configs/brsmarc1.h diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile index 9e7d6d6490..bac0350982 100644 --- a/arch/arm/dts/Makefile +++ b/arch/arm/dts/Makefile @@ -281,6 +281,7 @@ dtb-$(CONFIG_AM33XX) += \ am335x-brppt1-nand.dtb \ am335x-brppt1-spi.dtb \ am335x-brxre1.dtb \ + am335x-brsmarc1.dtb \ am335x-draco.dtb \ am335x-evm.dtb \ am335x-evmsk.dtb \ diff --git a/arch/arm/dts/am335x-brsmarc1.dts b/arch/arm/dts/am335x-brsmarc1.dts new file mode 100644 index 0000000000..1a7f9a5365 --- /dev/null +++ b/arch/arm/dts/am335x-brsmarc1.dts @@ -0,0 +1,416 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2017 B&R Industrial Automation GmbH + * http://www.br-automation.com + * + */ +/dts-v1/; + +#include "am33xx.dtsi" +#include "dt-bindings/thermal/thermal.h" + +/ { + model = "BRSMARC1 SoM"; + compatible = "ti,am33xx"; + + fset: factory-settings { + bl-version = " "; + order-no = " "; + cpu-order-no = " "; + hw-revision = " "; + serial-no = <0>; + device-id = <0x0>; + parent-id = <0x0>; + hw-variant = <0x0>; + hw-platform = <0x7>; + fram-offset = <0x100>; + fram-size = <0x1F00>; + cache-disable = <0x0>; + cpu-clock = <0x0>; + }; + + chosen { + bootargs = "console=ttyO0,115200 earlyprintk"; + stdout-path = &uart0; + }; + + aliases { + fset = &fset; + mmc = &mmc2; + spi0 = &spi0; + spi1 = &spi1; + touch0 = &burtouch0; + screen0 = &lcdscreen0; + }; + + memory { + device_type = "memory"; + reg = <0x80000000 0x10000000>; /* 256 MB */ + }; + + vmmcsd_fixed: fixedregulator@0 { + compatible = "regulator-fixed"; + regulator-name = "vmmcsd_fixed"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + lcdscreen0: lcdscreen@0 { + /*backlight = <&tps_bl>; */ + compatible = "ti,tilcdc,panel"; + status = "okay"; + + panel-info { + ac-bias = <255>; + ac-bias-intrpt = <0>; + dma-burst-sz = <16>; + bpp = <32>; + fdd = <0x80>; + sync-edge = <0>; + sync-ctrl = <1>; + raster-order = <0>; + fifo-th = <0>; + rotation = <0>; + pupdelay = <0>; + pondelay = <0>; + pwrpin = <0x000000B1>; + brightdrv = <0>; + brightfdim = <100>; + brightdef = <50>; + }; + + display-timings { + default { + clock-frequency = <0>; + hactive = <0>; + vactive = <0>; + hfront-porch = <0>; + hback-porch = <0>; + hsync-len = <0>; + vfront-porch = <0>; + vback-porch = <0>; + vsync-len = <0>; + hsync-active = <0>; + vsync-active = <0>; + pupdelay = <10>; + pondelay = <10>; + }; + }; + }; + + board_thermal: board-thermal { + polling-delay-passive = <1000>; /* milliseconds */ + polling-delay = <2500>; /* milliseconds */ + + thermal-sensors = <&cputemp>; + + trips { + crit_trip: crit-trip { + temperature = <95000>; /* millicelsius */ + hysteresis = <5000>; /* millicelsius */ + type = "critical"; + }; + }; + cooling-maps { + map0 { + trip = <&crit_trip>; + cooling-device = + <&resetc THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; + }; +}; + +&uart0 { /* console uart */ + u-boot,dm-spl; + status = "okay"; +}; + +&uart2 { /* X2X - P2P */ + status = "okay"; +}; + +&uart3 { /* RS485 */ + status = "okay"; +}; + +&uart4 { /* RS232 */ + status = "okay"; +}; + +&i2c0 { + u-boot,dm-spl; + status = "okay"; + clock-frequency = <100000>; + + tps: tps@24 { /* PMIC controller */ + u-boot,dm-spl; + reg = <0x24>; + compatible = "ti,tps65217"; + }; + + cputemp: temperature-sensor@48 { /* cpu temperature */ + #thermal-sensor-cells = <0>; + compatible = "nxp,pct2075"; + reg = <0x48>; + }; + + basetemp: temperature-sensor@49 { /* baseboard temperature */ + #thermal-sensor-cells = <0>; + compatible = "nxp,pct2075"; + reg = <0x49>; + }; + extrtc: rtc@51 { /* realtime clock */ + compatible = "epson,rx8571"; + reg = <0x51>; + }; + + resetc: reset-controller@60 { + compatible = "bur,rststm"; + reg = <0x60>; + + cooling-min-state = <0>; + cooling-max-state = <1>; /* reset gets fired */ + #cooling-cells = <2>; /* min followed by max */ + }; +}; + +&i2c1 { + u-boot,dm-spl; + status = "okay"; +}; + +&spi0 { + u-boot,dm-spl; + status = "okay"; + + cs-gpios = <&gpio0 5 GPIO_ACTIVE_HIGH>, + <&gpio0 6 GPIO_ACTIVE_HIGH>, + <0>, + <0>; + + spi-max-frequency = <24000000>; + + spi_flash: spiflash@0 { + u-boot,dm-spl; + u-boot,dm-pre-reloc; + compatible = "spidev", "spi-flash"; + spi-max-frequency = <24000000>; + reg = <0>; + }; +}; + +&spi1 { + u-boot,dm-spl; + status = "okay"; + cs-gpios = <&gpio3 17 GPIO_ACTIVE_HIGH>, + <&gpio0 19 GPIO_ACTIVE_HIGH>, + <0>, + <0>; + + spi-max-frequency = <24000000>; +}; + +&edma { + status = "okay"; +}; + +&cppi41dma { + status = "okay"; +}; + +&usb { + status = "okay"; +}; + +&usb_ctrl_mod { + status = "okay"; +}; + +&usb0_phy { + status = "okay"; +}; + +&usb1_phy { + status = "okay"; +}; + +&usb0 { + status = "okay"; + dr_mode = "host"; +}; + +&usb1 { + status = "okay"; + dr_mode = "host"; +}; + +&davinci_mdio { + status = "okay"; +}; + +&mac { + status = "okay"; +}; + +&phy_sel { + rmii-clock-ext; +}; + +&cpsw_emac0 { + phy_id = <&davinci_mdio>, <1>; + phy-mode = "rmii"; + ti,ledcr = <0x0480>; +}; + +&cpsw_emac1 { + phy_id = <&davinci_mdio>, <3>; + phy-mode = "rmii"; + ti,ledcr = <0x0480>; +}; + +&mmc1 { + vmmc-supply = <&vmmcsd_fixed>; + bus-width = <0x4>; + ti,non-removable; + ti,needs-special-hs-handling; + ti,vcc-aux-disable-is-sleep; + status = "okay"; +}; + +&mmc2 { + vmmc-supply = <&vmmcsd_fixed>; + bus-width = <0x8>; + ti,non-removable; + ti,needs-special-hs-handling; + ti,vcc-aux-disable-is-sleep; + status = "okay"; +}; + +&lcdc { + status = "okay"; + ti,no-reset-on-init; + ti,no-idle-on-init; +}; + +&elm { + status = "okay"; +}; + +&sham { + status = "okay"; +}; + +&aes { + status = "okay"; +}; + +&gpio0 { + u-boot,dm-spl; + ti,no-reset-on-init; +}; + +&gpio1 { + u-boot,dm-spl; + ti,no-reset-on-init; +}; + +&gpio2 { + u-boot,dm-spl; + ti,no-reset-on-init; +}; + +&gpio3 { + u-boot,dm-spl; + ti,no-reset-on-init; +}; + +&timer1 { /* today unused */ + status = "okay"; + ti,no-reset-on-init; + ti,no-idle-on-init; +}; + +&timer2 { /* used for vxworks primary timer device */ + status = "okay"; + ti,no-reset-on-init; + ti,no-idle-on-init; +}; + +&timer3 { /* used sysdelay and hal tsc counter*/ + status = "okay"; + ti,no-reset-on-init; + ti,no-idle-on-init; +}; + +&timer4 { /* used for PWM beeper */ + status = "okay"; + ti,no-reset-on-init; + ti,no-idle-on-init; +}; + +&timer5 { /* used for PWM backlight */ + status = "okay"; + ti,no-reset-on-init; + ti,no-idle-on-init; +}; + +&timer6 { /* used for cpsw end device */ + status = "okay"; + ti,no-reset-on-init; + ti,no-idle-on-init; +}; + +&timer7 { /* used for cpsw end device */ + status = "okay"; + ti,no-reset-on-init; + ti,no-idle-on-init; +}; + +&wdt2 { + status = "okay"; + ti,no-reset-on-init; + ti,no-idle-on-init; +}; + +&epwmss0 { + status = "okay"; +}; + +&tscadc { + status = "okay"; + + tsc { + burtouch0: burtouch@0 { + status = "okay"; + compatible = "bur,DdVxSfTouchXXX"; + bur,hwtree = "IF7"; + bur,KX0 = <0x0>; + bur,KX1 = <0x0>; + bur,KX2 = <0x0>; + bur,KY0 = <0x0>; + bur,KY1 = <0x0>; + bur,KY2 = <0x0>; + }; + }; +}; + +&dcan0 { + status = "okay"; +}; + +&dcan1 { + status = "okay"; +}; + +&sham { + status = "disabled"; +}; + +&aes { + status = "disabled"; +}; + +&rng { + status = "disabled"; +}; diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig index efe89eed0b..ed8056e871 100644 --- a/arch/arm/mach-omap2/Kconfig +++ b/arch/arm/mach-omap2/Kconfig @@ -176,6 +176,7 @@ source "arch/arm/mach-omap2/omap5/Kconfig" source "arch/arm/mach-omap2/am33xx/Kconfig" source "board/BuR/brxre1/Kconfig" +source "board/BuR/brsmarc1/Kconfig" source "board/BuR/brppt1/Kconfig" source "board/siemens/draco/Kconfig" source "board/siemens/pxm2/Kconfig" diff --git a/arch/arm/mach-omap2/am33xx/Kconfig b/arch/arm/mach-omap2/am33xx/Kconfig index 9da2a16a99..7f6b344c82 100644 --- a/arch/arm/mach-omap2/am33xx/Kconfig +++ b/arch/arm/mach-omap2/am33xx/Kconfig @@ -121,6 +121,10 @@ config TARGET_BRXRE1 bool "Support BRXRE1" select BOARD_LATE_INIT +config TARGET_BRSMARC1 + bool "Support BRSMARC1" + select BOARD_LATE_INIT + config TARGET_BRPPT1 bool "Support BRPPT1" select BOARD_LATE_INIT diff --git a/board/BuR/brsmarc1/Kconfig b/board/BuR/brsmarc1/Kconfig new file mode 100644 index 0000000000..6d3d7a2a26 --- /dev/null +++ b/board/BuR/brsmarc1/Kconfig @@ -0,0 +1,15 @@ +if TARGET_BRSMARC1 + +config SYS_BOARD + default "brsmarc1" + +config SYS_VENDOR + default "BuR" + +config SYS_SOC + default "am33xx" + +config SYS_CONFIG_NAME + default "brsmarc1" + +endif diff --git a/board/BuR/brsmarc1/MAINTAINERS b/board/BuR/brsmarc1/MAINTAINERS new file mode 100644 index 0000000000..c6dfc20f4d --- /dev/null +++ b/board/BuR/brsmarc1/MAINTAINERS @@ -0,0 +1,6 @@ +BRSMARC1 BOARD +M: Hannes Schmelzer +S: Maintained +F: board/BuR/brsmarc1/ +F: include/configs/brsmarc1.h +F: configs/brsmarc1_defconfig diff --git a/board/BuR/brsmarc1/Makefile b/board/BuR/brsmarc1/Makefile new file mode 100644 index 0000000000..1c3f64dea4 --- /dev/null +++ b/board/BuR/brsmarc1/Makefile @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright (C) 2019 Hannes Schmelzer - +# B&R Industrial Automation GmbH - http://www.br-automation.com/ +# + +obj-$(CONFIG_SPL_BUILD) += mux.o +obj-y += ../common/br_resetc.o +obj-y += ../common/common.o +obj-y += board.o diff --git a/board/BuR/brsmarc1/board.c b/board/BuR/brsmarc1/board.c new file mode 100644 index 0000000000..4c70346148 --- /dev/null +++ b/board/BuR/brsmarc1/board.c @@ -0,0 +1,168 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * board.c + * + * Board functions for B&R BRSMARC1 Board + * + * Copyright (C) 2017 Hannes Schmelzer + * B&R Industrial Automation GmbH - http://www.br-automation.com + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../common/bur_common.h" +#include "../common/br_resetc.h" + +/* -------------------------------------------------------------------------*/ +/* -- defines for used GPIO Hardware -- */ +#define PER_RESET (2 * 32 + 0) + +DECLARE_GLOBAL_DATA_PTR; + +#if defined(CONFIG_SPL_BUILD) +static const struct ddr_data ddr3_data = { + .datardsratio0 = MT41K256M16HA125E_RD_DQS, + .datawdsratio0 = MT41K256M16HA125E_WR_DQS, + .datafwsratio0 = MT41K256M16HA125E_PHY_FIFO_WE, + .datawrsratio0 = MT41K256M16HA125E_PHY_WR_DATA, +}; + +static const struct cmd_control ddr3_cmd_ctrl_data = { + .cmd0csratio = MT41K256M16HA125E_RATIO, + .cmd0iclkout = MT41K256M16HA125E_INVERT_CLKOUT, + + .cmd1csratio = MT41K256M16HA125E_RATIO, + .cmd1iclkout = MT41K256M16HA125E_INVERT_CLKOUT, + + .cmd2csratio = MT41K256M16HA125E_RATIO, + .cmd2iclkout = MT41K256M16HA125E_INVERT_CLKOUT, +}; + +static struct emif_regs ddr3_emif_reg_data = { + .sdram_config = MT41K256M16HA125E_EMIF_SDCFG, + .ref_ctrl = MT41K256M16HA125E_EMIF_SDREF, + .sdram_tim1 = MT41K256M16HA125E_EMIF_TIM1, + .sdram_tim2 = MT41K256M16HA125E_EMIF_TIM2, + .sdram_tim3 = MT41K256M16HA125E_EMIF_TIM3, + .zq_config = MT41K256M16HA125E_ZQ_CFG, + .emif_ddr_phy_ctlr_1 = MT41K256M16HA125E_EMIF_READ_LATENCY, +}; + +static const struct ctrl_ioregs ddr3_ioregs = { + .cm0ioctl = MT41K256M16HA125E_IOCTRL_VALUE, + .cm1ioctl = MT41K256M16HA125E_IOCTRL_VALUE, + .cm2ioctl = MT41K256M16HA125E_IOCTRL_VALUE, + .dt0ioctl = MT41K256M16HA125E_IOCTRL_VALUE, + .dt1ioctl = MT41K256M16HA125E_IOCTRL_VALUE, +}; + +#define OSC (V_OSCK / 1000000) +const struct dpll_params dpll_ddr3 = { 400, OSC - 1, 1, -1, -1, -1, -1}; + +void am33xx_spl_board_init(void) +{ + struct cm_perpll *const cmper = (struct cm_perpll *)CM_PER; + struct cm_wkuppll *const cmwkup = (struct cm_wkuppll *)CM_WKUP; + + int rc; + /* + * enable additional clocks of modules which are accessed later from + * VxWorks OS + */ + u32 *const clk_domains[] = { 0 }; + u32 *const clk_modules_specific[] = { + &cmwkup->wkup_adctscctrl, + &cmper->spi1clkctrl, + &cmper->dcan0clkctrl, + &cmper->dcan1clkctrl, + &cmper->timer4clkctrl, + &cmper->timer5clkctrl, + &cmper->lcdclkctrl, + &cmper->lcdcclkstctrl, + 0 + }; + do_enable_clocks(clk_domains, clk_modules_specific, 1); + + /* setup I2C */ + enable_i2c_pin_mux(); + + /* peripheral reset */ + rc = gpio_request(PER_RESET, "PER_RESET"); + if (rc != 0) + printf("cannot request PER_RESET GPIO!\n"); + + rc = gpio_direction_output(PER_RESET, 0); + if (rc != 0) + printf("cannot set PER_RESET GPIO!\n"); + + /* setup pmic */ + pmicsetup(0, 0); +} + +const struct dpll_params *get_dpll_ddr_params(void) +{ + return &dpll_ddr3; +} + +void sdram_init(void) +{ + config_ddr(400, &ddr3_ioregs, + &ddr3_data, + &ddr3_cmd_ctrl_data, + &ddr3_emif_reg_data, 0); +} +#endif /* CONFIG_SPL_BUILD */ +#if !defined(CONFIG_SPL_BUILD) + +/* decision if backlight is switched on or not on powerup */ +int board_backlightstate(void) +{ + u8 bklmask, rstcause; + int rc = 0; + + rc |= br_resetc_regget(RSTCTRL_SCRATCHREG1, &bklmask); + rc |= br_resetc_regget(RSTCTRL_ERSTCAUSE, &rstcause); + + if (rc != 0) { + printf("%s: read rstctrl failed!\n", __func__); + return 1; + } + + if ((rstcause & bklmask) != 0) + return 0; + + return 1; +} + +/* Basic board specific setup. run quite after relocation */ +int board_init(void) +{ + if (power_tps65217_init(0)) + printf("WARN: cannot setup PMIC 0x24 @ bus #0, not found!.\n"); + + return 0; +} + +#if defined(CONFIG_BOARD_LATE_INIT) + +int board_late_init(void) +{ + br_resetc_bmode(); + + return 0; +} + +#endif /* CONFIG_BOARD_LATE_INIT */ +#endif /* !CONFIG_SPL_BUILD */ diff --git a/board/BuR/brsmarc1/config.mk b/board/BuR/brsmarc1/config.mk new file mode 100644 index 0000000000..0692988507 --- /dev/null +++ b/board/BuR/brsmarc1/config.mk @@ -0,0 +1,33 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright (C) 2019 Hannes Schmelzer - +# B&R Industrial Automation GmbH - http://www.br-automation.com +# + +hw-platform-y :=$(shell echo $(CONFIG_DEFAULT_DEVICE_TREE) | sed -e 's/am335x-//') + +payload_off :=$(shell printf "%d" $(CONFIG_SYS_SPI_U_BOOT_OFFS)) + +quiet_cmd_prodbin = PRODBIN $@ $(payload_off) +cmd_prodbin = \ + dd if=/dev/zero ibs=1M count=2 2>/dev/null | tr "\000" "\377" >$@ && \ + dd conv=notrunc bs=1 if=MLO.byteswap of=$@ seek=0 2>/dev/null && \ + dd bs=1 if=u-boot-dtb.img of=$@ seek=$(payload_off) 2>/dev/null + +quiet_cmd_prodzip = SAPZIP $@ +cmd_prodzip = \ + test -d misc && rm -r misc; \ + mkdir misc && \ + cp MLO.byteswap misc/ && \ + cp spl/u-boot-spl.bin misc/ && \ + cp u-boot-dtb.img misc/ && \ + zip -9 -r $@ misc/* >/dev/null $< + +ALL-y += $(hw-platform-y)_prog.bin +ALL-y += $(hw-platform-y)_prod.zip + +$(hw-platform-y)_prog.bin: u-boot-dtb.img spl/u-boot-spl.bin + $(call if_changed,prodbin) + +$(hw-platform-y)_prod.zip: $(hw-platform-y)_prog.bin + $(call if_changed,prodzip) \ No newline at end of file diff --git a/board/BuR/brsmarc1/mux.c b/board/BuR/brsmarc1/mux.c new file mode 100644 index 0000000000..33c214d6b2 --- /dev/null +++ b/board/BuR/brsmarc1/mux.c @@ -0,0 +1,266 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * mux.c + * + * Pinmux Setting for B&R BRSMARC1 Board (HW-Rev. 1) + * + * Copyright (C) 2017 Hannes Schmelzer + * B&R Industrial Automation GmbH - http://www.br-automation.com + * + */ + +#include +#include +#include +#include +#include +#include + +static struct module_pin_mux spi0_pin_mux[] = { + /* SPI0_SCLK */ + {OFFSET(spi0_sclk), MODE(0) | PULLUDEN | RXACTIVE}, + /* SPI0_D0 */ + {OFFSET(spi0_d0), MODE(0) | PULLUDEN | RXACTIVE}, + /* SPI0_D1 */ + {OFFSET(spi0_d1), MODE(0) | PULLUDEN | RXACTIVE}, + /* SPI0_CS0 */ + {OFFSET(spi0_cs0), MODE(7) | PULLUDEN | PULLUP_EN | RXACTIVE}, + /* SPI0_CS1 */ + {OFFSET(spi0_cs1), MODE(7) | PULLUDEN | PULLUP_EN | RXACTIVE}, + {-1}, +}; + +static struct module_pin_mux spi1_pin_mux[] = { + /* SPI1_SCLK */ + {OFFSET(mcasp0_aclkx), MODE(3) | PULLUDEN | RXACTIVE}, + /* SPI1_D0 */ + {OFFSET(mcasp0_fsx), MODE(3) | PULLUDEN | RXACTIVE}, + /* SPI1_D1 */ + {OFFSET(mcasp0_axr0), MODE(3) | PULLUDEN | RXACTIVE}, + /* SPI1_CS0 */ + {OFFSET(mcasp0_ahclkr), MODE(7) | PULLUDEN | PULLUP_EN | RXACTIVE}, + /* SPI1_CS1 */ + {OFFSET(xdma_event_intr0), MODE(7) | PULLUDEN | PULLUP_EN | RXACTIVE}, + {-1}, +}; + +static struct module_pin_mux dcan0_pin_mux[] = { + /* DCAN0 TX */ + {OFFSET(uart1_ctsn), MODE(2) | PULLUDEN | PULLUP_EN}, + /* DCAN0 RX */ + {OFFSET(uart1_rtsn), MODE(2) | RXACTIVE}, + {-1}, +}; + +static struct module_pin_mux dcan1_pin_mux[] = { + /* DCAN1 TX */ + {OFFSET(uart0_ctsn), MODE(2) | PULLUDEN | PULLUP_EN}, + /* DCAN1 RX */ + {OFFSET(uart0_rtsn), MODE(2) | RXACTIVE}, + {-1}, +}; + +static struct module_pin_mux gpios[] = { + /* GPIO0_7 - LVDS_EN */ + {OFFSET(ecap0_in_pwm0_out), (MODE(7) | PULLUDDIS | PULLDOWN_EN)}, + /* GPIO0_20 - BKLT_PWM (timer7) */ + {OFFSET(xdma_event_intr1), (MODE(4) | PULLUDDIS | PULLDOWN_EN)}, + /* GPIO2_4 - DISON */ + {OFFSET(gpmc_wen), (MODE(7) | PULLUDDIS | PULLDOWN_EN)}, + /* GPIO1_24 - RGB_EN */ + {OFFSET(gpmc_a8), (MODE(7) | PULLUDDIS | PULLDOWN_EN)}, + /* GPIO1_28 - nPD */ + {OFFSET(gpmc_be1n), (MODE(7) | PULLUDEN | PULLUP_EN)}, + /* GPIO2_5 - Watchdog */ + {OFFSET(gpmc_be0n_cle), (MODE(7) | PULLUDDIS | PULLDOWN_EN)}, + /* GPIO2_0 - ResetOut */ + {OFFSET(gpmc_csn3), (MODE(7) | PULLUDEN | PULLUP_EN)}, + /* GPIO2_2 - BKLT_EN */ + {OFFSET(gpmc_advn_ale), (MODE(7) | PULLUDDIS | PULLDOWN_EN)}, + /* GPIO1_17 - GPIO0 */ + {OFFSET(gpmc_a1), (MODE(7) | PULLUDDIS | RXACTIVE)}, + /* GPIO1_18 - GPIO1 */ + {OFFSET(gpmc_a2), (MODE(7) | PULLUDDIS | RXACTIVE)}, + /* GPIO1_19 - GPIO2 */ + {OFFSET(gpmc_a3), (MODE(7) | PULLUDDIS | RXACTIVE)}, + /* GPIO1_22 - GPIO3 */ + {OFFSET(gpmc_a6), (MODE(7) | PULLUDDIS | RXACTIVE)}, + /* GPIO1_23 - GPIO4 */ + {OFFSET(gpmc_a7), (MODE(7) | PULLUDDIS | RXACTIVE)}, + /* GPIO1_25 - GPIO5 */ + {OFFSET(gpmc_a9), (MODE(7) | PULLUDDIS | RXACTIVE)}, + /* GPIO3_7 - GPIO6 */ + {OFFSET(emu0), (MODE(7) | PULLUDDIS | RXACTIVE)}, + /* GPIO3_8 - GPIO7 */ + {OFFSET(emu1), (MODE(7) | PULLUDDIS | RXACTIVE)}, + /* GPIO3_18 - GPIO8 */ + {OFFSET(mcasp0_aclkr), (MODE(7) | PULLUDDIS | RXACTIVE)}, + /* GPIO3_19 - GPIO9 */ + {OFFSET(mcasp0_fsr), (MODE(7) | PULLUDDIS | RXACTIVE)}, + /* GPIO3_20 - GPIO10 */ + {OFFSET(mcasp0_axr1), (MODE(7) | PULLUDDIS | RXACTIVE)}, + /* GPIO3_21 - GPIO11 */ + {OFFSET(mcasp0_ahclkx), (MODE(7) | PULLUDDIS | RXACTIVE)}, + /* GPIO2_28 - DRAM-strapping */ + {OFFSET(mmc0_dat1), (MODE(7) | PULLUDEN | PULLUP_EN)}, + /* GPIO2_4 - not routed (Pin U6) */ + {OFFSET(gpmc_wen), (MODE(7) | PULLUDEN | PULLUP_EN | RXACTIVE)}, + /* GPIO2_5 - not routed (Pin T6) */ + {OFFSET(gpmc_be0n_cle), (MODE(7) | PULLUDEN | PULLUP_EN | RXACTIVE)}, + /* GPIO2_28 - not routed (Pin G15) */ + {OFFSET(mmc0_dat1), (MODE(7) | PULLUDEN | PULLUP_EN | RXACTIVE)}, + /* GPIO3_18 - not routed (Pin B12) */ + {OFFSET(mcasp0_aclkr), (MODE(7) | PULLUDEN | PULLUP_EN | RXACTIVE)}, + {-1}, +}; + +static struct module_pin_mux uart0_pin_mux[] = { + /* UART0_RXD */ + {OFFSET(uart0_rxd), (MODE(0) | PULLUDEN | PULLUP_EN | RXACTIVE)}, + /* UART0_TXD */ + {OFFSET(uart0_txd), (MODE(0) | PULLUDEN)}, + {-1}, +}; + +static struct module_pin_mux uart234_pin_mux[] = { + /* UART2_RXD */ + {OFFSET(mii1_txclk), (MODE(1) | PULLUDEN | PULLUP_EN | RXACTIVE)}, + /* UART2_TXD */ + {OFFSET(mii1_rxclk), (MODE(1) | PULLUDEN)}, + + /* UART3_RXD */ + {OFFSET(mii1_rxd3), (MODE(1) | PULLUDEN | PULLUP_EN | RXACTIVE)}, + /* UART3_TXD */ + {OFFSET(mmc0_dat0), (MODE(3) | PULLUDEN)}, + /* UART3_RTS */ + {OFFSET(mmc0_cmd), (MODE(2) | PULLUDEN)}, + /* UART3_CTS */ + {OFFSET(mmc0_clk), (MODE(2) | PULLUDEN | PULLUP_EN | RXACTIVE)}, + + /* UART4_RXD */ + {OFFSET(mii1_txd3), (MODE(3) | PULLUDEN | PULLUP_EN | RXACTIVE)}, + /* UART4_TXD */ + {OFFSET(mii1_txd2), (MODE(3) | PULLUDEN)}, + /* UART4_RTS */ + {OFFSET(mmc0_dat2), (MODE(3) | PULLUDEN)}, + /* UART4_CTS */ + {OFFSET(mmc0_dat3), (MODE(3) | PULLUDEN | PULLUP_EN | RXACTIVE)}, + + {-1}, +}; + +static struct module_pin_mux i2c_pin_mux[] = { + /* I2C0_DATA */ + {OFFSET(i2c0_sda), (MODE(0) | RXACTIVE | PULLUDEN | SLEWCTRL)}, + /* I2C0_SCLK */ + {OFFSET(i2c0_scl), (MODE(0) | RXACTIVE | PULLUDEN | SLEWCTRL)}, + /* I2C1_DATA */ + {OFFSET(uart1_rxd), (MODE(3) | RXACTIVE | PULLUDEN | SLEWCTRL)}, + /* I2C1_SCLK */ + {OFFSET(uart1_txd), (MODE(3) | RXACTIVE | PULLUDEN | SLEWCTRL)}, + {-1}, +}; + +static struct module_pin_mux eth_pin_mux[] = { + /* ETH1 */ + {OFFSET(rmii1_refclk), MODE(0) | RXACTIVE}, /* ETH1_REFCLK */ + {OFFSET(mii1_crs), MODE(1) | RXACTIVE}, /* RMII1_CRSDV */ + {OFFSET(mii1_rxerr), MODE(1) | RXACTIVE}, /* RMII1_RXER */ + {OFFSET(mii1_txen), MODE(1)}, /* RMII1_TXEN */ + {OFFSET(mii1_rxd0), MODE(1) | RXACTIVE}, /* RMII1_RXD0 */ + {OFFSET(mii1_rxd1), MODE(1) | RXACTIVE}, /* RMII1_RXD1 */ + {OFFSET(mii1_txd0), MODE(1)}, /* RMII1_TXD0 */ + {OFFSET(mii1_txd1), MODE(1)}, /* RMII1_TXD1 */ + + /* ETH2 */ + {OFFSET(mii1_col), MODE(1) | RXACTIVE}, /* ETH2_REFCLK */ + {OFFSET(gpmc_wait0), MODE(3) | RXACTIVE}, /* RMII2_CRSDV */ + {OFFSET(gpmc_wpn), MODE(3) | RXACTIVE}, /* RMII2_RXER */ + {OFFSET(gpmc_a0), MODE(3)}, /* RMII2_TXEN */ + {OFFSET(gpmc_a11), MODE(3) | RXACTIVE}, /* RMII2_RXD0 */ + {OFFSET(gpmc_a10), MODE(3) | RXACTIVE}, /* RMII2_RXD1 */ + {OFFSET(gpmc_a5), MODE(3)}, /* RMII2_TXD0 */ + {OFFSET(gpmc_a4), MODE(3)}, /* RMII2_TXD1 */ + + /* gpio2_19, gpio 3_4, not connected on board */ + {OFFSET(mii1_rxd2), MODE(7) | PULLUDEN | PULLUP_EN | RXACTIVE}, + {OFFSET(mii1_rxdv), MODE(7) | PULLUDEN | PULLUP_EN | RXACTIVE}, + + /* ETH Management */ + {OFFSET(mdio_data), MODE(0) | RXACTIVE | PULLUP_EN}, /* MDIO_DATA */ + {OFFSET(mdio_clk), MODE(0) | PULLUP_EN}, /* MDIO_CLK */ + + {-1}, +}; + +static struct module_pin_mux mmc1_pin_mux[] = { + {OFFSET(gpmc_ad7), (MODE(1) | RXACTIVE | PULLUP_EN)}, /* MMC1_DAT7 */ + {OFFSET(gpmc_ad6), (MODE(1) | RXACTIVE | PULLUP_EN)}, /* MMC1_DAT6 */ + {OFFSET(gpmc_ad5), (MODE(1) | RXACTIVE | PULLUP_EN)}, /* MMC1_DAT5 */ + {OFFSET(gpmc_ad4), (MODE(1) | RXACTIVE | PULLUP_EN)}, /* MMC1_DAT4 */ + {OFFSET(gpmc_ad3), (MODE(1) | RXACTIVE | PULLUP_EN)}, /* MMC1_DAT3 */ + {OFFSET(gpmc_ad2), (MODE(1) | RXACTIVE | PULLUP_EN)}, /* MMC1_DAT2 */ + {OFFSET(gpmc_ad1), (MODE(1) | RXACTIVE | PULLUP_EN)}, /* MMC1_DAT1 */ + {OFFSET(gpmc_ad0), (MODE(1) | RXACTIVE | PULLUP_EN)}, /* MMC1_DAT0 */ + {OFFSET(gpmc_csn1), (MODE(2) | RXACTIVE | PULLUP_EN)}, /* MMC1_CLK */ + {OFFSET(gpmc_csn2), (MODE(2) | RXACTIVE | PULLUP_EN)}, /* MMC1_CMD */ + {-1}, +}; + +static struct module_pin_mux lcd_pin_mux[] = { + {OFFSET(lcd_data0), (MODE(0) | PULLUDDIS)}, /* LCD-Data(0) */ + {OFFSET(lcd_data1), (MODE(0) | PULLUDDIS)}, /* LCD-Data(1) */ + {OFFSET(lcd_data2), (MODE(0) | PULLUDDIS)}, /* LCD-Data(2) */ + {OFFSET(lcd_data3), (MODE(0) | PULLUDDIS)}, /* LCD-Data(3) */ + {OFFSET(lcd_data4), (MODE(0) | PULLUDDIS)}, /* LCD-Data(4) */ + {OFFSET(lcd_data5), (MODE(0) | PULLUDDIS)}, /* LCD-Data(5) */ + {OFFSET(lcd_data6), (MODE(0) | PULLUDDIS)}, /* LCD-Data(6) */ + {OFFSET(lcd_data7), (MODE(0) | PULLUDDIS)}, /* LCD-Data(7) */ + {OFFSET(lcd_data8), (MODE(0) | PULLUDDIS)}, /* LCD-Data(8) */ + {OFFSET(lcd_data9), (MODE(0) | PULLUDDIS)}, /* LCD-Data(9) */ + {OFFSET(lcd_data10), (MODE(0) | PULLUDDIS)}, /* LCD-Data(10) */ + {OFFSET(lcd_data11), (MODE(0) | PULLUDDIS)}, /* LCD-Data(11) */ + {OFFSET(lcd_data12), (MODE(0) | PULLUDDIS)}, /* LCD-Data(12) */ + {OFFSET(lcd_data13), (MODE(0) | PULLUDDIS)}, /* LCD-Data(13) */ + {OFFSET(lcd_data14), (MODE(0) | PULLUDDIS)}, /* LCD-Data(14) */ + {OFFSET(lcd_data15), (MODE(0) | PULLUDDIS)}, /* LCD-Data(15) */ + + {OFFSET(gpmc_ad8), (MODE(1) | PULLUDDIS)}, /* LCD-Data(16) */ + {OFFSET(gpmc_ad9), (MODE(1) | PULLUDDIS)}, /* LCD-Data(17) */ + {OFFSET(gpmc_ad10), (MODE(1) | PULLUDDIS)}, /* LCD-Data(18) */ + {OFFSET(gpmc_ad11), (MODE(1) | PULLUDDIS)}, /* LCD-Data(19) */ + {OFFSET(gpmc_ad12), (MODE(1) | PULLUDDIS)}, /* LCD-Data(20) */ + {OFFSET(gpmc_ad13), (MODE(1) | PULLUDDIS)}, /* LCD-Data(21) */ + {OFFSET(gpmc_ad14), (MODE(1) | PULLUDDIS)}, /* LCD-Data(22) */ + {OFFSET(gpmc_ad15), (MODE(1) | PULLUDDIS)}, /* LCD-Data(23) */ + + {OFFSET(lcd_vsync), (MODE(0) | PULLUDDIS)}, /* LCD-VSync */ + {OFFSET(lcd_hsync), (MODE(0) | PULLUDDIS)}, /* LCD-HSync */ + {OFFSET(lcd_ac_bias_en), (MODE(0) | PULLUDDIS)},/* LCD-DE */ + {OFFSET(lcd_pclk), (MODE(0) | PULLUDDIS)}, /* LCD-CLK */ + + {-1}, +}; + +void enable_uart0_pin_mux(void) +{ + configure_module_pin_mux(uart0_pin_mux); +} + +void enable_i2c_pin_mux(void) +{ + configure_module_pin_mux(i2c_pin_mux); +} + +void enable_board_pin_mux(void) +{ + configure_module_pin_mux(eth_pin_mux); + configure_module_pin_mux(spi0_pin_mux); + configure_module_pin_mux(spi1_pin_mux); + configure_module_pin_mux(dcan0_pin_mux); + configure_module_pin_mux(dcan1_pin_mux); + configure_module_pin_mux(uart234_pin_mux); + configure_module_pin_mux(mmc1_pin_mux); + configure_module_pin_mux(lcd_pin_mux); + configure_module_pin_mux(gpios); +} diff --git a/configs/brsmarc1_defconfig b/configs/brsmarc1_defconfig new file mode 100644 index 0000000000..9066b1ca8a --- /dev/null +++ b/configs/brsmarc1_defconfig @@ -0,0 +1,109 @@ +CONFIG_ARM=y +CONFIG_ARCH_OMAP2PLUS=y +CONFIG_SPL_GPIO_SUPPORT=y +CONFIG_SPL_LIBCOMMON_SUPPORT=y +CONFIG_SPL_LIBGENERIC_SUPPORT=y +CONFIG_SYS_MALLOC_F_LEN=0x2000 +CONFIG_AM33XX=y +CONFIG_SYS_MPUCLK=600 +CONFIG_TARGET_BRSMARC1=y +CONFIG_SPL_SERIAL_SUPPORT=y +CONFIG_ENV_SIZE=0x10000 +CONFIG_ENV_OFFSET=0x20000 +CONFIG_SPL_SYS_MALLOC_F_LEN=0x4000 +CONFIG_SPL=y +CONFIG_ENV_SECT_SIZE=0x10000 +CONFIG_SPL_SPI_FLASH_SUPPORT=y +CONFIG_SPL_SPI_SUPPORT=y +CONFIG_TPL_SYS_MALLOC_F_LEN=0x0 +# CONFIG_EXPERT is not set +# CONFIG_FIT is not set +CONFIG_OF_BOARD_SETUP=y +CONFIG_BOOTDELAY=0 +CONFIG_USE_BOOTCOMMAND=y +CONFIG_BOOTCOMMAND="run b_default" +CONFIG_SYS_CONSOLE_IS_IN_ENV=y +CONFIG_SYS_CONSOLE_OVERWRITE_ROUTINE=y +CONFIG_SYS_CONSOLE_INFO_QUIET=y +CONFIG_VERSION_VARIABLE=y +# CONFIG_DISPLAY_CPUINFO is not set +# CONFIG_DISPLAY_BOARDINFO is not set +CONFIG_ARCH_MISC_INIT=y +# CONFIG_SPL_RAW_IMAGE_SUPPORT is not set +CONFIG_SPL_SYS_MALLOC_SIMPLE=y +CONFIG_SPL_SEPARATE_BSS=y +# CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR is not set +CONFIG_SPL_I2C_SUPPORT=y +# CONFIG_SPL_NAND_SUPPORT is not set +CONFIG_SPL_POWER_SUPPORT=y +CONFIG_SPL_SPI_LOAD=y +CONFIG_SPL_YMODEM_SUPPORT=y +CONFIG_HUSH_PARSER=y +# CONFIG_CMD_BOOTD is not set +CONFIG_CMD_BOOTZ=y +# CONFIG_CMD_IMI is not set +# CONFIG_CMD_XIMG is not set +# CONFIG_CMD_EDITENV is not set +# CONFIG_CMD_CRC32 is not set +CONFIG_CMD_CLK=y +# CONFIG_CMD_FLASH is not set +CONFIG_CMD_GPIO=y +CONFIG_CMD_I2C=y +# CONFIG_CMD_LOADS is not set +CONFIG_CMD_MMC=y +CONFIG_CMD_SF=y +CONFIG_CMD_SPI=y +CONFIG_CMD_USB=y +# CONFIG_CMD_ITEST is not set +CONFIG_CMD_DHCP=y +# CONFIG_CMD_NFS is not set +CONFIG_CMD_MII=y +CONFIG_CMD_PING=y +CONFIG_CMD_TIME=y +CONFIG_CMD_EXT4=y +CONFIG_CMD_EXT4_WRITE=y +CONFIG_CMD_FAT=y +CONFIG_CMD_FS_GENERIC=y +# CONFIG_SPL_DOS_PARTITION is not set +CONFIG_OF_CONTROL=y +CONFIG_SPL_OF_CONTROL=y +CONFIG_DEFAULT_DEVICE_TREE="am335x-brsmarc1" +CONFIG_ENV_IS_IN_SPI_FLASH=y +CONFIG_NET_RANDOM_ETHADDR=y +CONFIG_NETCONSOLE=y +CONFIG_DM=y +CONFIG_SPL_DM=y +CONFIG_SPL_DM_SEQ_ALIAS=y +# CONFIG_OF_TRANSLATE is not set +# CONFIG_SPL_BLK is not set +CONFIG_DM_GPIO=y +CONFIG_DM_I2C=y +CONFIG_MISC=y +CONFIG_DM_MMC=y +CONFIG_MMC_OMAP_HS=y +CONFIG_DM_SPI_FLASH=y +CONFIG_SPI_FLASH=y +CONFIG_SF_DEFAULT_SPEED=24000000 +CONFIG_SPI_FLASH_SPANSION=y +CONFIG_SPI_FLASH_STMICRO=y +CONFIG_SPI_FLASH_WINBOND=y +# CONFIG_SPI_FLASH_USE_4K_SECTORS is not set +CONFIG_PHY_NATSEMI=y +CONFIG_DM_ETH=y +CONFIG_DRIVER_TI_CPSW=y +CONFIG_DM_SERIAL=y +CONFIG_SPI=y +CONFIG_DM_SPI=y +CONFIG_OMAP3_SPI=y +CONFIG_USB=y +CONFIG_DM_USB=y +CONFIG_USB_MUSB_HOST=y +CONFIG_USB_MUSB_GADGET=y +CONFIG_USB_MUSB_TI=y +CONFIG_USB_STORAGE=y +CONFIG_USB_GADGET=y +# CONFIG_OMAP_WATCHDOG is not set +CONFIG_SPL_TINY_MEMSET=y +CONFIG_SHA1=y +CONFIG_SHA256=y +# CONFIG_EFI_LOADER is not set diff --git a/include/configs/brsmarc1.h b/include/configs/brsmarc1.h new file mode 100644 index 0000000000..c18445816e --- /dev/null +++ b/include/configs/brsmarc1.h @@ -0,0 +1,83 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * brsmarc1.h + * + * specific parts for B&R BRSMARC1 Motherboard + * + * Copyright (C) 2017 Hannes Schmelzer - + * B&R Industrial Automation GmbH - http://www.br-automation.com + * + */ + +#ifndef __CONFIG_BRSMARC1_H__ +#define __CONFIG_BRSMARC1_H__ + +#include +#include +/* ------------------------------------------------------------------------- */ +#define CONFIG_BOARD_TYPES + +/* memory */ +#define CONFIG_SYS_MALLOC_LEN (5 * 1024 * 1024) +#define CONFIG_SYS_BOOTM_LEN (32 * 1024 * 1024) + +/* Clock Defines */ +#define V_OSCK 26000000 /* Clock output from T2 */ +#define V_SCLK (V_OSCK) + +#define CONFIG_MACH_TYPE 3589 + +#ifndef CONFIG_SPL_BUILD + +/* Default environment */ +#define CONFIG_EXTRA_ENV_SETTINGS \ +BUR_COMMON_ENV \ +"autoload=0\0" \ +"scradr=" __stringify(CONFIG_SYS_LOAD_ADDR) "\0" \ +"cfgscr=mw ${dtbaddr} 0;" \ +" sf probe && sf read ${scradr} 0xC0000 0x10000 && source ${scradr};" \ +" fdt addr ${dtbaddr} || cp ${fdtcontroladdr} ${dtbaddr} 4000\0" \ +"dtbaddr=0x84000000\0" \ +"loadaddr=0x82000000\0" \ +"b_break=0\0" \ +"b_tgts_std=mmc0 mmc1 def net usb0\0" \ +"b_tgts_rcy=def net usb0\0" \ +"b_tgts_pme=net usb0 mmc0 mmc1\0" \ +"b_deftgts=if test ${b_mode} = 12; then setenv b_tgts ${b_tgts_pme};" \ +" elif test ${b_mode} = 0; then setenv b_tgts ${b_tgts_rcy};" \ +" else setenv b_tgts ${b_tgts_std}; fi\0" \ +"b_mmc0=load mmc 1 ${scradr} bootscr.img && source ${scradr}\0" \ +"b_mmc1=load mmc 1 ${loadaddr} arimg.ugz && run startsys\0" \ +"b_def=sf read ${loadaddr} 100000 700000; run startsys\0" \ +"b_net=tftp ${scradr} netscript.img && source ${scradr}\0" \ +"b_usb0=usb start && load usb 0 ${scradr} bootscr.img && source ${scradr}\0" \ +"b_default=run b_deftgts; for target in ${b_tgts};"\ +" do run b_${target}; if test ${b_break} = 1; then; exit; fi; done\0" \ +"vxargs=setenv bootargs cpsw(0,0)host:vxWorks h=${serverip}" \ +" e=${ipaddr}:${netmask} g=${gatewayip} u=vxWorksFTP pw=vxWorks\0" \ +"vxfdt=fdt addr ${dtbaddr}; fdt resize 0x8000;" \ +" fdt boardsetup\0" \ +"startsys=run vxargs && mw 0x80001100 0 && run vxfdt &&" \ +" bootm ${loadaddr} - ${dtbaddr}\0" +#endif /* !CONFIG_SPL_BUILD*/ + +/* undefine command which we not need here */ +#undef CONFIG_BOOTM_NETBSD +#undef CONFIG_BOOTM_PLAN9 +#undef CONFIG_BOOTM_RTEMS + +/* Support both device trees and ATAGs. */ +#define CONFIG_CMDLINE_TAG +#define CONFIG_SETUP_MEMORY_TAGS +#define CONFIG_INITRD_TAG + +/* SPI Flash */ +#define CONFIG_SYS_SPI_U_BOOT_OFFS 0x40000 + +/* Environment */ +#define CONFIG_SYS_REDUNDAND_ENVIRONMENT +#define CONFIG_ENV_OFFSET_REDUND (CONFIG_ENV_OFFSET + \ + CONFIG_ENV_SECT_SIZE) + +#define CONFIG_CONS_INDEX 1 +#endif /* __CONFIG_BRSMARC1_H__ */ From 71cd80af863945e81f468c22e5e1afb06eba75cd Mon Sep 17 00:00:00 2001 From: Nishanth Menon Date: Thu, 1 Aug 2019 19:08:24 +0530 Subject: [PATCH 07/20] power: domain: ti-sci-power-domain: Add device ID info to get/set_device failure Failure log for ti_sci_power_domain_on/off is as below: "ti_sci_power_domain_on: get/set_device failed (-19)" The above information is useless for debug without information on what specific device access failed. So add that information as well. Signed-off-by: Nishanth Menon Signed-off-by: Lokesh Vutla --- drivers/power/domain/ti-sci-power-domain.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/power/domain/ti-sci-power-domain.c b/drivers/power/domain/ti-sci-power-domain.c index b9cd37b612..4c4351d2d9 100644 --- a/drivers/power/domain/ti-sci-power-domain.c +++ b/drivers/power/domain/ti-sci-power-domain.c @@ -68,8 +68,8 @@ static int ti_sci_power_domain_on(struct power_domain *pd) ret = dops->get_device(sci, pd->id); if (ret) - dev_err(power_domain->dev, "%s: get_device failed (%d)\n", - __func__, ret); + dev_err(pd->dev, "%s: get_device(%lu) failed (%d)\n", + __func__, pd->id, ret); return ret; } @@ -85,8 +85,8 @@ static int ti_sci_power_domain_off(struct power_domain *pd) ret = dops->put_device(sci, pd->id); if (ret) - dev_err(power_domain->dev, "%s: put_device failed (%d)\n", - __func__, ret); + dev_err(pd->dev, "%s: put_device(%lu) failed (%d)\n", + __func__, pd->id, ret); return ret; } From acbb7cd4d34caec36ff6d044a8f55325fa27459f Mon Sep 17 00:00:00 2001 From: Sekhar Nori Date: Thu, 1 Aug 2019 19:12:55 +0530 Subject: [PATCH 08/20] clk: add support for clk_is_match() Add support for clk_is_match() which is required to know if two clock pointers point to the same exact physical clock. Also add a unit test for the new API. Reviewed-by: Lokesh Vutla Signed-off-by: Sekhar Nori --- drivers/clk/clk-uclass.c | 13 +++++++++++++ include/clk.h | 12 ++++++++++++ test/dm/clk.c | 1 + 3 files changed, 26 insertions(+) diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c index cee4d912b0..c66b6f3c4e 100644 --- a/drivers/clk/clk-uclass.c +++ b/drivers/clk/clk-uclass.c @@ -518,6 +518,19 @@ int clk_get_by_id(ulong id, struct clk **clkp) return -ENOENT; } +bool clk_is_match(const struct clk *p, const struct clk *q) +{ + /* trivial case: identical struct clk's or both NULL */ + if (p == q) + return true; + + /* same device, id and data */ + if (p->dev == q->dev && p->id == q->id && p->data == q->data) + return true; + + return false; +} + UCLASS_DRIVER(clk) = { .id = UCLASS_CLK, .name = "clk", diff --git a/include/clk.h b/include/clk.h index 2ebc905e04..3ca2796b57 100644 --- a/include/clk.h +++ b/include/clk.h @@ -333,6 +333,18 @@ int clk_disable(struct clk *clk); */ int clk_disable_bulk(struct clk_bulk *bulk); +/** + * clk_is_match - check if two clk's point to the same hardware clock + * @p: clk compared against q + * @q: clk compared against p + * + * Returns true if the two struct clk pointers both point to the same hardware + * clock node. + * + * Returns false otherwise. Note that two NULL clks are treated as matching. + */ +bool clk_is_match(const struct clk *p, const struct clk *q); + int soc_clk_dump(void); /** diff --git a/test/dm/clk.c b/test/dm/clk.c index f301ecbb45..676ef217f0 100644 --- a/test/dm/clk.c +++ b/test/dm/clk.c @@ -24,6 +24,7 @@ static int dm_test_clk_base(struct unit_test_state *uts) /* Get the same clk port in 2 different ways and compare */ ut_assertok(clk_get_by_index(dev, 1, &clk_method1)); ut_assertok(clk_get_by_index_nodev(dev_ofnode(dev), 1, &clk_method2)); + ut_asserteq(clk_is_match(&clk_method1, &clk_method2), true); ut_asserteq(clk_method1.id, clk_method2.id); return 0; From f5b904796fa876bbfdf6eb9d2b311f9d01d80f5a Mon Sep 17 00:00:00 2001 From: Sekhar Nori Date: Thu, 1 Aug 2019 19:12:56 +0530 Subject: [PATCH 09/20] dm: core: add support for getting register address and size Current dev_read_*() API lacks support to get address and size of a "reg" property by name or index. Add support for the same. Livetree support has been added but not tested on real hardware. The existing unit tests testing reading address from device-tree have been updated to test address as well as size. Reviewed-by: Lokesh Vutla Signed-off-by: Sekhar Nori --- drivers/core/fdtaddr.c | 17 +++++++++++++++++ drivers/core/read.c | 20 ++++++++++++++++++++ include/dm/fdtaddr.h | 18 ++++++++++++++++++ include/dm/read.h | 41 +++++++++++++++++++++++++++++++++++++++++ test/dm/test-fdt.c | 16 ++++++++++++---- 5 files changed, 108 insertions(+), 4 deletions(-) diff --git a/drivers/core/fdtaddr.c b/drivers/core/fdtaddr.c index c2873861da..6850003a28 100644 --- a/drivers/core/fdtaddr.c +++ b/drivers/core/fdtaddr.c @@ -129,6 +129,23 @@ fdt_addr_t devfdt_get_addr_name(struct udevice *dev, const char *name) #endif } +fdt_addr_t devfdt_get_addr_size_name(struct udevice *dev, const char *name, + fdt_size_t *size) +{ +#if CONFIG_IS_ENABLED(OF_CONTROL) + int index; + + index = fdt_stringlist_search(gd->fdt_blob, dev_of_offset(dev), + "reg-names", name); + if (index < 0) + return index; + + return devfdt_get_addr_size_index(dev, index, size); +#else + return FDT_ADDR_T_NONE; +#endif +} + fdt_addr_t devfdt_get_addr(struct udevice *dev) { return devfdt_get_addr_index(dev, 0); diff --git a/drivers/core/read.c b/drivers/core/read.c index 1a044b05e8..8b5502de11 100644 --- a/drivers/core/read.c +++ b/drivers/core/read.c @@ -82,6 +82,15 @@ fdt_addr_t dev_read_addr_index(struct udevice *dev, int index) return devfdt_get_addr_index(dev, index); } +fdt_addr_t dev_read_addr_size_index(struct udevice *dev, int index, + fdt_size_t *size) +{ + if (ofnode_is_np(dev_ofnode(dev))) + return ofnode_get_addr_size_index(dev_ofnode(dev), index, size); + else + return devfdt_get_addr_size_index(dev, index, size); +} + void *dev_remap_addr_index(struct udevice *dev, int index) { fdt_addr_t addr = dev_read_addr_index(dev, index); @@ -102,6 +111,17 @@ fdt_addr_t dev_read_addr_name(struct udevice *dev, const char *name) return dev_read_addr_index(dev, index); } +fdt_addr_t dev_read_addr_size_name(struct udevice *dev, const char *name, + fdt_size_t *size) +{ + int index = dev_read_stringlist_search(dev, "reg-names", name); + + if (index < 0) + return FDT_ADDR_T_NONE; + else + return dev_read_addr_size_index(dev, index, size); +} + void *dev_remap_addr_name(struct udevice *dev, const char *name) { fdt_addr_t addr = dev_read_addr_name(dev, name); diff --git a/include/dm/fdtaddr.h b/include/dm/fdtaddr.h index 3bc2599b6c..57b326cb33 100644 --- a/include/dm/fdtaddr.h +++ b/include/dm/fdtaddr.h @@ -120,4 +120,22 @@ fdt_addr_t devfdt_get_addr_size_index(struct udevice *dev, int index, */ fdt_addr_t devfdt_get_addr_name(struct udevice *dev, const char *name); +/** + * devfdt_get_addr_size_name() - Get the reg property and its size for a device, + * indexed by name + * + * Returns the address and size specified in the 'reg' property of a device. + * + * @dev: Pointer to a device + * @name: the 'reg' property can hold a list of pairs, with the + * 'reg-names' property providing named-based identification. @index + * indicates the value to search for in 'reg-names'. + * @size: Pointer to size variable - this function returns the size + * specified in the 'reg' property here + * + * @return addr + */ +fdt_addr_t devfdt_get_addr_size_name(struct udevice *dev, const char *name, + fdt_size_t *size); + #endif diff --git a/include/dm/read.h b/include/dm/read.h index 6ecd062e20..0c62d62f11 100644 --- a/include/dm/read.h +++ b/include/dm/read.h @@ -144,6 +144,19 @@ int dev_read_size(struct udevice *dev, const char *propname); */ fdt_addr_t dev_read_addr_index(struct udevice *dev, int index); +/** + * dev_read_addr_size_index() - Get the indexed reg property of a device + * + * @dev: Device to read from + * @index: the 'reg' property can hold a list of pairs + * and @index is used to select which one is required + * @size: place to put size value (on success) + * + * @return address or FDT_ADDR_T_NONE if not found + */ +fdt_addr_t dev_read_addr_size_index(struct udevice *dev, int index, + fdt_size_t *size); + /** * dev_remap_addr_index() - Get the indexed reg property of a device * as a memory-mapped I/O pointer @@ -168,6 +181,20 @@ void *dev_remap_addr_index(struct udevice *dev, int index); */ fdt_addr_t dev_read_addr_name(struct udevice *dev, const char* name); +/** + * dev_read_addr_size_name() - Get the reg property of a device, indexed by name + * + * @dev: Device to read from + * @name: the 'reg' property can hold a list of pairs, with the + * 'reg-names' property providing named-based identification. @index + * indicates the value to search for in 'reg-names'. + * @size: place to put size value (on success) + * + * @return address or FDT_ADDR_T_NONE if not found + */ +fdt_addr_t dev_read_addr_size_name(struct udevice *dev, const char *name, + fdt_size_t *size); + /** * dev_remap_addr_name() - Get the reg property of a device, indexed by name, * as a memory-mapped I/O pointer @@ -601,12 +628,26 @@ static inline fdt_addr_t dev_read_addr_index(struct udevice *dev, int index) return devfdt_get_addr_index(dev, index); } +static inline fdt_addr_t dev_read_addr_size_index(struct udevice *dev, + int index, + fdt_size_t *size) +{ + return devfdt_get_addr_size_index(dev, index, size); +} + static inline fdt_addr_t dev_read_addr_name(struct udevice *dev, const char *name) { return devfdt_get_addr_name(dev, name); } +static inline fdt_addr_t dev_read_addr_size_name(struct udevice *dev, + const char *name, + fdt_size_t *size) +{ + return devfdt_get_addr_size_name(dev, name, size); +} + static inline fdt_addr_t dev_read_addr(struct udevice *dev) { return devfdt_get_addr(dev); diff --git a/test/dm/test-fdt.c b/test/dm/test-fdt.c index ad8591639d..1fb8b5c248 100644 --- a/test/dm/test-fdt.c +++ b/test/dm/test-fdt.c @@ -549,12 +549,14 @@ static int dm_test_fdt_remap_addr_index_flat(struct unit_test_state *uts) { struct udevice *dev; fdt_addr_t addr; + fdt_size_t size; void *paddr; ut_assertok(uclass_find_device_by_seq(UCLASS_TEST_DUMMY, 0, true, &dev)); - addr = devfdt_get_addr_index(dev, 0); + addr = devfdt_get_addr_size_index(dev, 0, &size); ut_asserteq(0x8000, addr); + ut_asserteq(0x1000, size); paddr = map_physmem(addr, 0, MAP_NOCACHE); ut_assertnonnull(paddr); @@ -569,12 +571,14 @@ static int dm_test_fdt_remap_addr_name_flat(struct unit_test_state *uts) { struct udevice *dev; fdt_addr_t addr; + fdt_size_t size; void *paddr; ut_assertok(uclass_find_device_by_seq(UCLASS_TEST_DUMMY, 0, true, &dev)); - addr = devfdt_get_addr_name(dev, "sandbox-dummy-0"); + addr = devfdt_get_addr_size_name(dev, "sandbox-dummy-0", &size); ut_asserteq(0x8000, addr); + ut_asserteq(0x1000, size); paddr = map_physmem(addr, 0, MAP_NOCACHE); ut_assertnonnull(paddr); @@ -609,12 +613,14 @@ static int dm_test_fdt_remap_addr_index_live(struct unit_test_state *uts) { struct udevice *dev; fdt_addr_t addr; + fdt_size_t size; void *paddr; ut_assertok(uclass_find_device_by_seq(UCLASS_TEST_DUMMY, 0, true, &dev)); - addr = dev_read_addr_index(dev, 0); + addr = dev_read_addr_size_index(dev, 0, &size); ut_asserteq(0x8000, addr); + ut_asserteq(0x1000, size); paddr = map_physmem(addr, 0, MAP_NOCACHE); ut_assertnonnull(paddr); @@ -629,12 +635,14 @@ static int dm_test_fdt_remap_addr_name_live(struct unit_test_state *uts) { struct udevice *dev; fdt_addr_t addr; + fdt_size_t size; void *paddr; ut_assertok(uclass_find_device_by_seq(UCLASS_TEST_DUMMY, 0, true, &dev)); - addr = dev_read_addr_name(dev, "sandbox-dummy-0"); + addr = dev_read_addr_size_name(dev, "sandbox-dummy-0", &size); ut_asserteq(0x8000, addr); + ut_asserteq(0x1000, size); paddr = map_physmem(addr, 0, MAP_NOCACHE); ut_assertnonnull(paddr); From 03c396bb5f3e74c74ce164b9b1eef9908e5cfabb Mon Sep 17 00:00:00 2001 From: Sekhar Nori Date: Thu, 1 Aug 2019 19:12:57 +0530 Subject: [PATCH 10/20] pcie: ti: add driver for AM65x PCIe RC Add driver supporting PCIe root-complex available on TI's AM65x SoC. Signed-off-by: Sekhar Nori --- drivers/pci/Kconfig | 6 + drivers/pci/Makefile | 1 + drivers/pci/pcie_dw_ti.c | 725 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 732 insertions(+) create mode 100644 drivers/pci/pcie_dw_ti.c diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig index 3fe38f7315..bdfc0c1796 100644 --- a/drivers/pci/Kconfig +++ b/drivers/pci/Kconfig @@ -145,4 +145,10 @@ config PCI_MVEBU Say Y here if you want to enable PCIe controller support on Armada XP/38x SoCs. +config PCI_KEYSTONE + bool "TI Keystone PCIe controller" + depends on DM_PCI + help + Say Y here if you want to enable PCI controller support on AM654 SoC. + endif diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile index b5ebd50c85..e54a98b8c9 100644 --- a/drivers/pci/Makefile +++ b/drivers/pci/Makefile @@ -38,3 +38,4 @@ obj-$(CONFIG_PCIE_LAYERSCAPE_GEN4) += pcie_layerscape_gen4.o \ pcie_layerscape_gen4_fixup.o obj-$(CONFIG_PCI_XILINX) += pcie_xilinx.o obj-$(CONFIG_PCIE_INTEL_FPGA) += pcie_intel_fpga.o +obj-$(CONFIG_PCI_KEYSTONE) += pcie_dw_ti.o diff --git a/drivers/pci/pcie_dw_ti.c b/drivers/pci/pcie_dw_ti.c new file mode 100644 index 0000000000..b37fc2de7f --- /dev/null +++ b/drivers/pci/pcie_dw_ti.c @@ -0,0 +1,725 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2018 Texas Instruments, Inc + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +#define PCIE_VENDORID_MASK GENMASK(15, 0) +#define PCIE_DEVICEID_SHIFT 16 + +/* PCI DBICS registers */ +#define PCIE_CONFIG_BAR0 0x10 +#define PCIE_LINK_STATUS_REG 0x80 +#define PCIE_LINK_STATUS_SPEED_OFF 16 +#define PCIE_LINK_STATUS_SPEED_MASK (0xf << PCIE_LINK_STATUS_SPEED_OFF) +#define PCIE_LINK_STATUS_WIDTH_OFF 20 +#define PCIE_LINK_STATUS_WIDTH_MASK (0xf << PCIE_LINK_STATUS_WIDTH_OFF) + +#define PCIE_LINK_CAPABILITY 0x7c +#define PCIE_LINK_CTL_2 0xa0 +#define TARGET_LINK_SPEED_MASK 0xf +#define LINK_SPEED_GEN_1 0x1 +#define LINK_SPEED_GEN_2 0x2 +#define LINK_SPEED_GEN_3 0x3 + +#define PCIE_MISC_CONTROL_1_OFF 0x8bc +#define PCIE_DBI_RO_WR_EN BIT(0) + +#define PLR_OFFSET 0x700 +#define PCIE_PORT_DEBUG0 (PLR_OFFSET + 0x28) +#define PORT_LOGIC_LTSSM_STATE_MASK 0x1f +#define PORT_LOGIC_LTSSM_STATE_L0 0x11 + +#define PCIE_LINK_WIDTH_SPEED_CONTROL 0x80c +#define PORT_LOGIC_SPEED_CHANGE (0x1 << 17) + +#define PCIE_LINK_UP_TIMEOUT_MS 100 + +/* + * iATU Unroll-specific register definitions + * From 4.80 core version the address translation will be made by unroll. + * The registers are offset from atu_base + */ +#define PCIE_ATU_UNR_REGION_CTRL1 0x00 +#define PCIE_ATU_UNR_REGION_CTRL2 0x04 +#define PCIE_ATU_UNR_LOWER_BASE 0x08 +#define PCIE_ATU_UNR_UPPER_BASE 0x0c +#define PCIE_ATU_UNR_LIMIT 0x10 +#define PCIE_ATU_UNR_LOWER_TARGET 0x14 +#define PCIE_ATU_UNR_UPPER_TARGET 0x18 + +#define PCIE_ATU_REGION_INDEX1 (0x1 << 0) +#define PCIE_ATU_REGION_INDEX0 (0x0 << 0) +#define PCIE_ATU_TYPE_MEM (0x0 << 0) +#define PCIE_ATU_TYPE_IO (0x2 << 0) +#define PCIE_ATU_TYPE_CFG0 (0x4 << 0) +#define PCIE_ATU_TYPE_CFG1 (0x5 << 0) +#define PCIE_ATU_ENABLE (0x1 << 31) +#define PCIE_ATU_BAR_MODE_ENABLE (0x1 << 30) +#define PCIE_ATU_BUS(x) (((x) & 0xff) << 24) +#define PCIE_ATU_DEV(x) (((x) & 0x1f) << 19) +#define PCIE_ATU_FUNC(x) (((x) & 0x7) << 16) + +/* Register address builder */ +#define PCIE_GET_ATU_OUTB_UNR_REG_OFFSET(region) ((region) << 9) + +/* Offsets from App base */ +#define PCIE_CMD_STATUS 0x04 +#define LTSSM_EN_VAL BIT(0) + +/* Parameters for the waiting for iATU enabled routine */ +#define LINK_WAIT_MAX_IATU_RETRIES 5 +#define LINK_WAIT_IATU 10000 + +#define AM654_PCIE_DEV_TYPE_MASK 0x3 +#define EP 0x0 +#define LEG_EP 0x1 +#define RC 0x2 + +/** + * struct pcie_dw_ti - TI DW PCIe controller state + * + * @app_base: The base address of application register space + * @dbics_base: The base address of dbics register space + * @cfg_base: The base address of configuration space + * @atu_base: The base address of ATU space + * @cfg_size: The size of the configuration space which is needed + * as it gets written into the PCIE_ATU_LIMIT register + * @first_busno: This driver supports multiple PCIe controllers. + * first_busno stores the bus number of the PCIe root-port + * number which may vary depending on the PCIe setup + * (PEX switches etc). + */ +struct pcie_dw_ti { + void *app_base; + void *dbi_base; + void *cfg_base; + void *atu_base; + fdt_size_t cfg_size; + int first_busno; + struct udevice *dev; + + /* IO and MEM PCI regions */ + struct pci_region io; + struct pci_region mem; +}; + +enum dw_pcie_device_mode { + DW_PCIE_UNKNOWN_TYPE, + DW_PCIE_EP_TYPE, + DW_PCIE_LEG_EP_TYPE, + DW_PCIE_RC_TYPE, +}; + +static int pcie_dw_get_link_speed(struct pcie_dw_ti *pci) +{ + return (readl(pci->dbi_base + PCIE_LINK_STATUS_REG) & + PCIE_LINK_STATUS_SPEED_MASK) >> PCIE_LINK_STATUS_SPEED_OFF; +} + +static int pcie_dw_get_link_width(struct pcie_dw_ti *pci) +{ + return (readl(pci->dbi_base + PCIE_LINK_STATUS_REG) & + PCIE_LINK_STATUS_WIDTH_MASK) >> PCIE_LINK_STATUS_WIDTH_OFF; +} + +static void dw_pcie_writel_ob_unroll(struct pcie_dw_ti *pci, u32 index, u32 reg, + u32 val) +{ + u32 offset = PCIE_GET_ATU_OUTB_UNR_REG_OFFSET(index); + void __iomem *base = pci->atu_base; + + writel(val, base + offset + reg); +} + +static u32 dw_pcie_readl_ob_unroll(struct pcie_dw_ti *pci, u32 index, u32 reg) +{ + u32 offset = PCIE_GET_ATU_OUTB_UNR_REG_OFFSET(index); + void __iomem *base = pci->atu_base; + + return readl(base + offset + reg); +} + +/** + * pcie_dw_prog_outbound_atu_unroll() - Configure ATU for outbound accesses + * + * @pcie: Pointer to the PCI controller state + * @index: ATU region index + * @type: ATU accsess type + * @cpu_addr: the physical address for the translation entry + * @pci_addr: the pcie bus address for the translation entry + * @size: the size of the translation entry + */ +static void pcie_dw_prog_outbound_atu_unroll(struct pcie_dw_ti *pci, int index, + int type, u64 cpu_addr, + u64 pci_addr, u32 size) +{ + u32 retries, val; + + debug("ATU programmed with: index: %d, type: %d, cpu addr: %8llx, pci addr: %8llx, size: %8x\n", + index, type, cpu_addr, pci_addr, size); + + dw_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_LOWER_BASE, + lower_32_bits(cpu_addr)); + dw_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_UPPER_BASE, + upper_32_bits(cpu_addr)); + dw_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_LIMIT, + lower_32_bits(cpu_addr + size - 1)); + dw_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_LOWER_TARGET, + lower_32_bits(pci_addr)); + dw_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_UPPER_TARGET, + upper_32_bits(pci_addr)); + dw_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_REGION_CTRL1, + type); + dw_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_REGION_CTRL2, + PCIE_ATU_ENABLE); + + /* + * Make sure ATU enable takes effect before any subsequent config + * and I/O accesses. + */ + for (retries = 0; retries < LINK_WAIT_MAX_IATU_RETRIES; retries++) { + val = dw_pcie_readl_ob_unroll(pci, index, + PCIE_ATU_UNR_REGION_CTRL2); + if (val & PCIE_ATU_ENABLE) + return; + + udelay(LINK_WAIT_IATU); + } + dev_err(pci->dev, "outbound iATU is not being enabled\n"); +} + +/** + * set_cfg_address() - Configure the PCIe controller config space access + * + * @pcie: Pointer to the PCI controller state + * @d: PCI device to access + * @where: Offset in the configuration space + * + * Configures the PCIe controller to access the configuration space of + * a specific PCIe device and returns the address to use for this + * access. + * + * Return: Address that can be used to access the configation space + * of the requested device / offset + */ +static uintptr_t set_cfg_address(struct pcie_dw_ti *pcie, + pci_dev_t d, uint where) +{ + int bus = PCI_BUS(d) - pcie->first_busno; + uintptr_t va_address; + u32 atu_type; + + /* Use dbi_base for own configuration read and write */ + if (!bus) { + va_address = (uintptr_t)pcie->dbi_base; + goto out; + } + + if (bus == 1) + /* For local bus, change TLP Type field to 4. */ + atu_type = PCIE_ATU_TYPE_CFG0; + else + /* Otherwise, change TLP Type field to 5. */ + atu_type = PCIE_ATU_TYPE_CFG1; + + /* + * Not accessing root port configuration space? + * Region #0 is used for Outbound CFG space access. + * Direction = Outbound + * Region Index = 0 + */ + d = PCI_MASK_BUS(d); + d = PCI_ADD_BUS(bus, d); + pcie_dw_prog_outbound_atu_unroll(pcie, PCIE_ATU_REGION_INDEX1, + atu_type, (u64)pcie->cfg_base, + d << 8, pcie->cfg_size); + + va_address = (uintptr_t)pcie->cfg_base; + +out: + va_address += where & ~0x3; + + return va_address; +} + +/** + * pcie_dw_addr_valid() - Check for valid bus address + * + * @d: The PCI device to access + * @first_busno: Bus number of the PCIe controller root complex + * + * Return 1 (true) if the PCI device can be accessed by this controller. + * + * Return: 1 on valid, 0 on invalid + */ +static int pcie_dw_addr_valid(pci_dev_t d, int first_busno) +{ + if ((PCI_BUS(d) == first_busno) && (PCI_DEV(d) > 0)) + return 0; + if ((PCI_BUS(d) == first_busno + 1) && (PCI_DEV(d) > 0)) + return 0; + + return 1; +} + +/** + * pcie_dw_ti_read_config() - Read from configuration space + * + * @bus: Pointer to the PCI bus + * @bdf: Identifies the PCIe device to access + * @offset: The offset into the device's configuration space + * @valuep: A pointer at which to store the read value + * @size: Indicates the size of access to perform + * + * Read a value of size @size from offset @offset within the configuration + * space of the device identified by the bus, device & function numbers in @bdf + * on the PCI bus @bus. + * + * Return: 0 on success + */ +static int pcie_dw_ti_read_config(struct udevice *bus, pci_dev_t bdf, + uint offset, ulong *valuep, + enum pci_size_t size) +{ + struct pcie_dw_ti *pcie = dev_get_priv(bus); + uintptr_t va_address; + ulong value; + + debug("PCIE CFG read: bdf=%2x:%2x:%2x ", + PCI_BUS(bdf), PCI_DEV(bdf), PCI_FUNC(bdf)); + + if (!pcie_dw_addr_valid(bdf, pcie->first_busno)) { + debug("- out of range\n"); + *valuep = pci_get_ff(size); + return 0; + } + + va_address = set_cfg_address(pcie, bdf, offset); + + value = readl(va_address); + + debug("(addr,val)=(0x%04x, 0x%08lx)\n", offset, value); + *valuep = pci_conv_32_to_size(value, offset, size); + + pcie_dw_prog_outbound_atu_unroll(pcie, PCIE_ATU_REGION_INDEX1, + PCIE_ATU_TYPE_IO, pcie->io.phys_start, + pcie->io.bus_start, pcie->io.size); + + return 0; +} + +/** + * pcie_dw_ti_write_config() - Write to configuration space + * + * @bus: Pointer to the PCI bus + * @bdf: Identifies the PCIe device to access + * @offset: The offset into the device's configuration space + * @value: The value to write + * @size: Indicates the size of access to perform + * + * Write the value @value of size @size from offset @offset within the + * configuration space of the device identified by the bus, device & function + * numbers in @bdf on the PCI bus @bus. + * + * Return: 0 on success + */ +static int pcie_dw_ti_write_config(struct udevice *bus, pci_dev_t bdf, + uint offset, ulong value, + enum pci_size_t size) +{ + struct pcie_dw_ti *pcie = dev_get_priv(bus); + uintptr_t va_address; + ulong old; + + debug("PCIE CFG write: (b,d,f)=(%2d,%2d,%2d) ", + PCI_BUS(bdf), PCI_DEV(bdf), PCI_FUNC(bdf)); + debug("(addr,val)=(0x%04x, 0x%08lx)\n", offset, value); + + if (!pcie_dw_addr_valid(bdf, pcie->first_busno)) { + debug("- out of range\n"); + return 0; + } + + va_address = set_cfg_address(pcie, bdf, offset); + + old = readl(va_address); + value = pci_conv_size_to_32(old, value, offset, size); + writel(value, va_address); + + pcie_dw_prog_outbound_atu_unroll(pcie, PCIE_ATU_REGION_INDEX1, + PCIE_ATU_TYPE_IO, pcie->io.phys_start, + pcie->io.bus_start, pcie->io.size); + + return 0; +} + +static inline void dw_pcie_dbi_write_enable(struct pcie_dw_ti *pci, bool en) +{ + u32 val; + + val = readl(pci->dbi_base + PCIE_MISC_CONTROL_1_OFF); + if (en) + val |= PCIE_DBI_RO_WR_EN; + else + val &= ~PCIE_DBI_RO_WR_EN; + writel(val, pci->dbi_base + PCIE_MISC_CONTROL_1_OFF); +} + +/** + * pcie_dw_configure() - Configure link capabilities and speed + * + * @regs_base: A pointer to the PCIe controller registers + * @cap_speed: The capabilities and speed to configure + * + * Configure the link capabilities and speed in the PCIe root complex. + */ +static void pcie_dw_configure(struct pcie_dw_ti *pci, u32 cap_speed) +{ + u32 val; + + dw_pcie_dbi_write_enable(pci, true); + + val = readl(pci->dbi_base + PCIE_LINK_CAPABILITY); + val &= ~TARGET_LINK_SPEED_MASK; + val |= cap_speed; + writel(val, pci->dbi_base + PCIE_LINK_CAPABILITY); + + val = readl(pci->dbi_base + PCIE_LINK_CTL_2); + val &= ~TARGET_LINK_SPEED_MASK; + val |= cap_speed; + writel(val, pci->dbi_base + PCIE_LINK_CTL_2); + + dw_pcie_dbi_write_enable(pci, false); +} + +/** + * is_link_up() - Return the link state + * + * @regs_base: A pointer to the PCIe DBICS registers + * + * Return: 1 (true) for active line and 0 (false) for no link + */ +static int is_link_up(struct pcie_dw_ti *pci) +{ + u32 val; + + val = readl(pci->dbi_base + PCIE_PORT_DEBUG0); + val &= PORT_LOGIC_LTSSM_STATE_MASK; + + return (val == PORT_LOGIC_LTSSM_STATE_L0); +} + +/** + * wait_link_up() - Wait for the link to come up + * + * @regs_base: A pointer to the PCIe controller registers + * + * Return: 1 (true) for active line and 0 (false) for no link (timeout) + */ +static int wait_link_up(struct pcie_dw_ti *pci) +{ + unsigned long timeout; + + timeout = get_timer(0) + PCIE_LINK_UP_TIMEOUT_MS; + while (!is_link_up(pci)) { + if (get_timer(0) > timeout) + return 0; + }; + + return 1; +} + +static int pcie_dw_ti_pcie_link_up(struct pcie_dw_ti *pci, u32 cap_speed) +{ + u32 val; + + if (is_link_up(pci)) { + printf("PCI Link already up before configuration!\n"); + return 1; + } + + /* DW pre link configurations */ + pcie_dw_configure(pci, cap_speed); + + /* Initiate link training */ + val = readl(pci->app_base + PCIE_CMD_STATUS); + val |= LTSSM_EN_VAL; + writel(val, pci->app_base + PCIE_CMD_STATUS); + + /* Check that link was established */ + if (!wait_link_up(pci)) + return 0; + + /* + * Link can be established in Gen 1. still need to wait + * till MAC nagaotiation is completed + */ + udelay(100); + + return 1; +} + +/** + * pcie_dw_setup_host() - Setup the PCIe controller for RC opertaion + * + * @pcie: Pointer to the PCI controller state + * + * Configure the host BARs of the PCIe controller root port so that + * PCI(e) devices may access the system memory. + */ +static void pcie_dw_setup_host(struct pcie_dw_ti *pci) +{ + u32 val; + + /* setup RC BARs */ + writel(PCI_BASE_ADDRESS_MEM_TYPE_64, + pci->dbi_base + PCI_BASE_ADDRESS_0); + writel(0x0, pci->dbi_base + PCI_BASE_ADDRESS_1); + + /* setup interrupt pins */ + dw_pcie_dbi_write_enable(pci, true); + val = readl(pci->dbi_base + PCI_INTERRUPT_LINE); + val &= 0xffff00ff; + val |= 0x00000100; + writel(val, pci->dbi_base + PCI_INTERRUPT_LINE); + dw_pcie_dbi_write_enable(pci, false); + + /* setup bus numbers */ + val = readl(pci->dbi_base + PCI_PRIMARY_BUS); + val &= 0xff000000; + val |= 0x00ff0100; + writel(val, pci->dbi_base + PCI_PRIMARY_BUS); + + /* setup command register */ + val = readl(pci->dbi_base + PCI_COMMAND); + val &= 0xffff0000; + val |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY | + PCI_COMMAND_MASTER | PCI_COMMAND_SERR; + writel(val, pci->dbi_base + PCI_COMMAND); + + /* Enable write permission for the DBI read-only register */ + dw_pcie_dbi_write_enable(pci, true); + /* program correct class for RC */ + writew(PCI_CLASS_BRIDGE_PCI, pci->dbi_base + PCI_CLASS_DEVICE); + /* Better disable write permission right after the update */ + dw_pcie_dbi_write_enable(pci, false); + + val = readl(pci->dbi_base + PCIE_LINK_WIDTH_SPEED_CONTROL); + val |= PORT_LOGIC_SPEED_CHANGE; + writel(val, pci->dbi_base + PCIE_LINK_WIDTH_SPEED_CONTROL); +} + +static int pcie_am654_set_mode(struct pcie_dw_ti *pci, + enum dw_pcie_device_mode mode) +{ + struct regmap *syscon; + u32 val; + u32 mask; + int ret; + + syscon = syscon_regmap_lookup_by_phandle(pci->dev, + "ti,syscon-pcie-mode"); + if (IS_ERR(syscon)) + return 0; + + mask = AM654_PCIE_DEV_TYPE_MASK; + + switch (mode) { + case DW_PCIE_RC_TYPE: + val = RC; + break; + case DW_PCIE_EP_TYPE: + val = EP; + break; + default: + dev_err(pci->dev, "INVALID device type %d\n", mode); + return -EINVAL; + } + + ret = regmap_update_bits(syscon, 0, mask, val); + if (ret) { + dev_err(pci->dev, "failed to set pcie mode\n"); + return ret; + } + + return 0; +} + +static int pcie_dw_init_id(struct pcie_dw_ti *pci) +{ + struct regmap *devctrl_regs; + unsigned int id; + int ret; + + devctrl_regs = syscon_regmap_lookup_by_phandle(pci->dev, + "ti,syscon-pcie-id"); + if (IS_ERR(devctrl_regs)) + return PTR_ERR(devctrl_regs); + + ret = regmap_read(devctrl_regs, 0, &id); + if (ret) + return ret; + + dw_pcie_dbi_write_enable(pci, true); + writew(id & PCIE_VENDORID_MASK, pci->dbi_base + PCI_VENDOR_ID); + writew(id >> PCIE_DEVICEID_SHIFT, pci->dbi_base + PCI_DEVICE_ID); + dw_pcie_dbi_write_enable(pci, false); + + return 0; +} + +/** + * pcie_dw_ti_probe() - Probe the PCIe bus for active link + * + * @dev: A pointer to the device being operated on + * + * Probe for an active link on the PCIe bus and configure the controller + * to enable this port. + * + * Return: 0 on success, else -ENODEV + */ +static int pcie_dw_ti_probe(struct udevice *dev) +{ + struct pcie_dw_ti *pci = dev_get_priv(dev); + struct udevice *ctlr = pci_get_controller(dev); + struct pci_controller *hose = dev_get_uclass_priv(ctlr); + struct power_domain pci_pwrdmn; + struct phy phy0, phy1; + int ret; + + ret = power_domain_get_by_index(dev, &pci_pwrdmn, 0); + if (ret) { + dev_err(dev, "failed to get power domain\n"); + return ret; + } + + ret = power_domain_on(&pci_pwrdmn); + if (ret) { + dev_err(dev, "Power domain on failed\n"); + return ret; + } + + ret = generic_phy_get_by_name(dev, "pcie-phy0", &phy0); + if (ret) { + dev_err(dev, "Unable to get phy0"); + return ret; + } + generic_phy_reset(&phy0); + generic_phy_init(&phy0); + generic_phy_power_on(&phy0); + + ret = generic_phy_get_by_name(dev, "pcie-phy1", &phy1); + if (ret) { + dev_err(dev, "Unable to get phy1"); + return ret; + } + generic_phy_reset(&phy1); + generic_phy_init(&phy1); + generic_phy_power_on(&phy1); + + pci->first_busno = dev->seq; + pci->dev = dev; + + pcie_dw_setup_host(pci); + pcie_dw_init_id(pci); + + if (device_is_compatible(dev, "ti,am654-pcie-rc")) + pcie_am654_set_mode(pci, DW_PCIE_RC_TYPE); + + if (!pcie_dw_ti_pcie_link_up(pci, LINK_SPEED_GEN_2)) { + printf("PCIE-%d: Link down\n", dev->seq); + return -ENODEV; + } + + printf("PCIE-%d: Link up (Gen%d-x%d, Bus%d)\n", dev->seq, + pcie_dw_get_link_speed(pci), + pcie_dw_get_link_width(pci), + hose->first_busno); + + /* Store the IO and MEM windows settings for future use by the ATU */ + pci->io.phys_start = hose->regions[0].phys_start; /* IO base */ + pci->io.bus_start = hose->regions[0].bus_start; /* IO_bus_addr */ + pci->io.size = hose->regions[0].size; /* IO size */ + + pci->mem.phys_start = hose->regions[1].phys_start; /* MEM base */ + pci->mem.bus_start = hose->regions[1].bus_start; /* MEM_bus_addr */ + pci->mem.size = hose->regions[1].size; /* MEM size */ + + pcie_dw_prog_outbound_atu_unroll(pci, PCIE_ATU_REGION_INDEX0, + PCIE_ATU_TYPE_MEM, + pci->mem.phys_start, + pci->mem.bus_start, pci->mem.size); + + return 0; +} + +/** + * pcie_dw_ti_ofdata_to_platdata() - Translate from DT to device state + * + * @dev: A pointer to the device being operated on + * + * Translate relevant data from the device tree pertaining to device @dev into + * state that the driver will later make use of. This state is stored in the + * device's private data structure. + * + * Return: 0 on success, else -EINVAL + */ +static int pcie_dw_ti_ofdata_to_platdata(struct udevice *dev) +{ + struct pcie_dw_ti *pcie = dev_get_priv(dev); + + /* Get the controller base address */ + pcie->dbi_base = (void *)dev_read_addr_name(dev, "dbics"); + if ((fdt_addr_t)pcie->dbi_base == FDT_ADDR_T_NONE) + return -EINVAL; + + /* Get the config space base address and size */ + pcie->cfg_base = (void *)dev_read_addr_size_name(dev, "config", + &pcie->cfg_size); + if ((fdt_addr_t)pcie->cfg_base == FDT_ADDR_T_NONE) + return -EINVAL; + + /* Get the iATU base address and size */ + pcie->atu_base = (void *)dev_read_addr_name(dev, "atu"); + if ((fdt_addr_t)pcie->atu_base == FDT_ADDR_T_NONE) + return -EINVAL; + + /* Get the app base address and size */ + pcie->app_base = (void *)dev_read_addr_name(dev, "app"); + if ((fdt_addr_t)pcie->app_base == FDT_ADDR_T_NONE) + return -EINVAL; + + return 0; +} + +static const struct dm_pci_ops pcie_dw_ti_ops = { + .read_config = pcie_dw_ti_read_config, + .write_config = pcie_dw_ti_write_config, +}; + +static const struct udevice_id pcie_dw_ti_ids[] = { + { .compatible = "ti,am654-pcie-rc" }, + { } +}; + +U_BOOT_DRIVER(pcie_dw_ti) = { + .name = "pcie_dw_ti", + .id = UCLASS_PCI, + .of_match = pcie_dw_ti_ids, + .ops = &pcie_dw_ti_ops, + .ofdata_to_platdata = pcie_dw_ti_ofdata_to_platdata, + .probe = pcie_dw_ti_probe, + .priv_auto_alloc_size = sizeof(struct pcie_dw_ti), +}; From 888e1caeaec2645aee461dfc9e84f21642e050ec Mon Sep 17 00:00:00 2001 From: Sekhar Nori Date: Thu, 1 Aug 2019 19:12:58 +0530 Subject: [PATCH 11/20] phy: add support for AM654x SERDES Add a new SERDES driver for TI's AM654x SoC which configures the SERDES only for PCIe. Support fo USB3 can be added later. SERDES in am654x has three input clocks (left input, external reference clock and right input) and two output clocks (left output and right output) in addition to a PLL mux clock which the SERDES uses for Clock Multiplier Unit (CMU refclock). The PLL mux clock can select from one of the three input clocks. The right output can select between left input and external reference clock while the left output can select between the right input and external reference clock. The driver has support to select PLL mux and left/right output mux as specified in device tree. Signed-off-by: Sekhar Nori --- drivers/phy/Kconfig | 9 + drivers/phy/Makefile | 1 + drivers/phy/phy-ti-am654.c | 411 +++++++++++++++++++++++++++++++++++++ 3 files changed, 421 insertions(+) create mode 100644 drivers/phy/phy-ti-am654.c diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig index 8209ca7323..3942f035eb 100644 --- a/drivers/phy/Kconfig +++ b/drivers/phy/Kconfig @@ -108,6 +108,15 @@ config SPL_PIPE3_PHY This PHY is found on omap devices supporting SATA such as dra7, am57x and omap5 +config AM654_PHY + tristate "TI AM654 SERDES support" + depends on PHY && ARCH_K3 + select REGMAP + select SYSCON + help + This option enables support for TI AM654 SerDes PHY used for + PCIe. + config STI_USB_PHY bool "STMicroelectronics USB2 picoPHY driver for STiH407 family" depends on PHY && ARCH_STI diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile index b9f5195e1c..3157f1b7ee 100644 --- a/drivers/phy/Makefile +++ b/drivers/phy/Makefile @@ -11,6 +11,7 @@ obj-$(CONFIG_BCM6358_USBH_PHY) += bcm6358-usbh-phy.o obj-$(CONFIG_BCM6368_USBH_PHY) += bcm6368-usbh-phy.o obj-$(CONFIG_PHY_SANDBOX) += sandbox-phy.o obj-$(CONFIG_$(SPL_)PIPE3_PHY) += ti-pipe3-phy.o +obj-$(CONFIG_AM654_PHY) += phy-ti-am654.o obj-$(CONFIG_STI_USB_PHY) += sti_usb_phy.o obj-$(CONFIG_PHY_RCAR_GEN2) += phy-rcar-gen2.o obj-$(CONFIG_PHY_RCAR_GEN3) += phy-rcar-gen3.o diff --git a/drivers/phy/phy-ti-am654.c b/drivers/phy/phy-ti-am654.c new file mode 100644 index 0000000000..39490124ea --- /dev/null +++ b/drivers/phy/phy-ti-am654.c @@ -0,0 +1,411 @@ +// SPDX-License-Identifier: GPL-2.0+ +/** + * PCIe SERDES driver for AM654x SoC + * + * Copyright (C) 2018 Texas Instruments + * Author: Kishon Vijay Abraham I + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define CMU_R07C 0x7c +#define CMU_MASTER_CDN_O BIT(24) + +#define COMLANE_R138 0xb38 +#define CONFIG_VERSION_REG_MASK GENMASK(23, 16) +#define CONFIG_VERSION_REG_SHIFT 16 +#define VERSION 0x70 + +#define COMLANE_R190 0xb90 +#define L1_MASTER_CDN_O BIT(9) + +#define COMLANE_R194 0xb94 +#define CMU_OK_I_0 BIT(19) + +#define SERDES_CTRL 0x1fd0 +#define POR_EN BIT(29) + +#define WIZ_LANEXCTL_STS 0x1fe0 +#define TX0_ENABLE_OVL BIT(31) +#define TX0_ENABLE_MASK GENMASK(30, 29) +#define TX0_ENABLE_SHIFT 29 +#define TX0_DISABLE_STATE 0x0 +#define TX0_SLEEP_STATE 0x1 +#define TX0_SNOOZE_STATE 0x2 +#define TX0_ENABLE_STATE 0x3 +#define RX0_ENABLE_OVL BIT(15) +#define RX0_ENABLE_MASK GENMASK(14, 13) +#define RX0_ENABLE_SHIFT 13 +#define RX0_DISABLE_STATE 0x0 +#define RX0_SLEEP_STATE 0x1 +#define RX0_SNOOZE_STATE 0x2 +#define RX0_ENABLE_STATE 0x3 + +#define WIZ_PLL_CTRL 0x1ff4 +#define PLL_ENABLE_OVL BIT(31) +#define PLL_ENABLE_MASK GENMASK(30, 29) +#define PLL_ENABLE_SHIFT 29 +#define PLL_DISABLE_STATE 0x0 +#define PLL_SLEEP_STATE 0x1 +#define PLL_SNOOZE_STATE 0x2 +#define PLL_ENABLE_STATE 0x3 +#define PLL_OK BIT(28) + +#define PLL_LOCK_TIME 1000 /* in milliseconds */ +#define SLEEP_TIME 100 /* in microseconds */ + +#define LANE_USB3 0x0 +#define LANE_PCIE0_LANE0 0x1 + +#define LANE_PCIE1_LANE0 0x0 +#define LANE_PCIE0_LANE1 0x1 + +#define SERDES_NUM_CLOCKS 3 + +/* SERDES control MMR bit offsets */ +#define SERDES_CTL_LANE_FUNC_SEL_SHIFT 0 +#define SERDES_CTL_LANE_FUNC_SEL_MASK GENMASK(1, 0) +#define SERDES_CTL_CLK_SEL_SHIFT 4 +#define SERDES_CTL_CLK_SEL_MASK GENMASK(7, 4) + +/** + * struct serdes_am654_mux_clk_data - clock controller information structure + */ +struct serdes_am654_mux_clk_data { + struct regmap *regmap; + struct clk_bulk parents; +}; + +static int serdes_am654_mux_clk_probe(struct udevice *dev) +{ + struct serdes_am654_mux_clk_data *data = dev_get_priv(dev); + struct udevice *syscon; + struct regmap *regmap; + int ret; + + debug("%s(dev=%s)\n", __func__, dev->name); + + if (!data) + return -ENOMEM; + + ret = uclass_get_device_by_phandle(UCLASS_SYSCON, dev, + "ti,serdes-clk", &syscon); + if (ret) { + dev_err(dev, "unable to find syscon device\n"); + return ret; + } + + regmap = syscon_get_regmap(syscon); + if (IS_ERR(regmap)) { + dev_err(dev, "Fail to get Syscon regmap\n"); + return PTR_ERR(regmap); + } + + data->regmap = regmap; + + ret = clk_get_bulk(dev, &data->parents); + if (ret) { + dev_err(dev, "Failed to obtain parent clocks\n"); + return ret; + } + + return 0; +} + +static int mux_table[SERDES_NUM_CLOCKS][3] = { + /* + * The entries represent values for selecting between + * {left input, external reference clock, right input} + * Only one of Left Output or Right Output should be used since + * both left and right output clock uses the same bits and modifying + * one clock will impact the other. + */ + { BIT(2), 0, BIT(0) }, /* Mux of CMU refclk */ + { -1, BIT(3), BIT(1) }, /* Mux of Left Output */ + { BIT(1), BIT(3) | BIT(1), -1 }, /* Mux of Right Output */ +}; + +static int serdes_am654_mux_clk_set_parent(struct clk *clk, struct clk *parent) +{ + struct serdes_am654_mux_clk_data *data = dev_get_priv(clk->dev); + u32 val; + int i; + + debug("%s(clk=%s, parent=%s)\n", __func__, clk->dev->name, + parent->dev->name); + + /* + * Since we have the same device-tree node represent both the + * clock and serdes device, we have two devices associated with + * the serdes node. assigned-clocks for this node is processed twice, + * once for the clock device and another time for the serdes + * device. When it is processed for the clock device, it is before + * the probe for clock device has been called. We ignore this case + * and rely on assigned-clocks to be processed correctly for the + * serdes case. + */ + if (!data->regmap) + return 0; + + for (i = 0; i < data->parents.count; i++) { + if (clk_is_match(&data->parents.clks[i], parent)) + break; + } + + if (i >= data->parents.count) + return -EINVAL; + + val = mux_table[clk->id][i]; + val <<= SERDES_CTL_CLK_SEL_SHIFT; + + regmap_update_bits(data->regmap, 0, SERDES_CTL_CLK_SEL_MASK, val); + + return 0; +} + +static struct clk_ops serdes_am654_mux_clk_ops = { + .set_parent = serdes_am654_mux_clk_set_parent, +}; + +U_BOOT_DRIVER(serdes_am654_mux_clk) = { + .name = "ti-serdes-am654-mux-clk", + .id = UCLASS_CLK, + .probe = serdes_am654_mux_clk_probe, + .priv_auto_alloc_size = sizeof(struct serdes_am654_mux_clk_data), + .ops = &serdes_am654_mux_clk_ops, +}; + +struct serdes_am654 { + struct regmap *regmap; + struct regmap *serdes_ctl; +}; + +static int serdes_am654_enable_pll(struct serdes_am654 *phy) +{ + u32 mask = PLL_ENABLE_OVL | PLL_ENABLE_MASK; + u32 val = PLL_ENABLE_OVL | (PLL_ENABLE_STATE << PLL_ENABLE_SHIFT); + + regmap_update_bits(phy->regmap, WIZ_PLL_CTRL, mask, val); + + return regmap_read_poll_timeout(phy->regmap, WIZ_PLL_CTRL, val, + val & PLL_OK, 1000, PLL_LOCK_TIME); +} + +static void serdes_am654_disable_pll(struct serdes_am654 *phy) +{ + u32 mask = PLL_ENABLE_OVL | PLL_ENABLE_MASK; + + regmap_update_bits(phy->regmap, WIZ_PLL_CTRL, mask, 0); +} + +static int serdes_am654_enable_txrx(struct serdes_am654 *phy) +{ + u32 mask; + u32 val; + + /* Enable TX */ + mask = TX0_ENABLE_OVL | TX0_ENABLE_MASK; + val = TX0_ENABLE_OVL | (TX0_ENABLE_STATE << TX0_ENABLE_SHIFT); + regmap_update_bits(phy->regmap, WIZ_LANEXCTL_STS, mask, val); + + /* Enable RX */ + mask = RX0_ENABLE_OVL | RX0_ENABLE_MASK; + val = RX0_ENABLE_OVL | (RX0_ENABLE_STATE << RX0_ENABLE_SHIFT); + regmap_update_bits(phy->regmap, WIZ_LANEXCTL_STS, mask, val); + + return 0; +} + +static int serdes_am654_disable_txrx(struct serdes_am654 *phy) +{ + u32 mask; + + /* Disable TX */ + mask = TX0_ENABLE_OVL | TX0_ENABLE_MASK; + regmap_update_bits(phy->regmap, WIZ_LANEXCTL_STS, mask, 0); + + /* Disable RX */ + mask = RX0_ENABLE_OVL | RX0_ENABLE_MASK; + regmap_update_bits(phy->regmap, WIZ_LANEXCTL_STS, mask, 0); + + return 0; +} + +static int serdes_am654_power_on(struct phy *x) +{ + struct serdes_am654 *phy = dev_get_priv(x->dev); + int ret; + u32 val; + + ret = serdes_am654_enable_pll(phy); + if (ret) { + dev_err(x->dev, "Failed to enable PLL\n"); + return ret; + } + + ret = serdes_am654_enable_txrx(phy); + if (ret) { + dev_err(x->dev, "Failed to enable TX RX\n"); + return ret; + } + + return regmap_read_poll_timeout(phy->regmap, COMLANE_R194, val, + val & CMU_OK_I_0, SLEEP_TIME, + PLL_LOCK_TIME); +} + +static int serdes_am654_power_off(struct phy *x) +{ + struct serdes_am654 *phy = dev_get_priv(x->dev); + + serdes_am654_disable_txrx(phy); + serdes_am654_disable_pll(phy); + + return 0; +} + +static int serdes_am654_init(struct phy *x) +{ + struct serdes_am654 *phy = dev_get_priv(x->dev); + u32 mask; + u32 val; + + mask = CONFIG_VERSION_REG_MASK; + val = VERSION << CONFIG_VERSION_REG_SHIFT; + regmap_update_bits(phy->regmap, COMLANE_R138, mask, val); + + val = CMU_MASTER_CDN_O; + regmap_update_bits(phy->regmap, CMU_R07C, val, val); + + val = L1_MASTER_CDN_O; + regmap_update_bits(phy->regmap, COMLANE_R190, val, val); + + return 0; +} + +static int serdes_am654_reset(struct phy *x) +{ + struct serdes_am654 *phy = dev_get_priv(x->dev); + u32 val; + + val = POR_EN; + regmap_update_bits(phy->regmap, SERDES_CTRL, val, val); + mdelay(1); + regmap_update_bits(phy->regmap, SERDES_CTRL, val, 0); + + return 0; +} + +static int serdes_am654_of_xlate(struct phy *x, + struct ofnode_phandle_args *args) +{ + struct serdes_am654 *phy = dev_get_priv(x->dev); + + if (args->args_count != 2) { + dev_err(phy->dev, "Invalid DT PHY argument count: %d\n", + args->args_count); + return -EINVAL; + } + + if (args->args[0] != PHY_TYPE_PCIE) { + dev_err(phy->dev, "Unrecognized PHY type: %d\n", + args->args[0]); + return -EINVAL; + } + + x->id = args->args[0] | (args->args[1] << 16); + + /* Setup mux mode using second argument */ + regmap_update_bits(phy->serdes_ctl, 0, SERDES_CTL_LANE_FUNC_SEL_MASK, + args->args[1]); + + return 0; +} + +static int serdes_am654_bind(struct udevice *dev) +{ + int ret; + + ret = device_bind_driver_to_node(dev->parent, + "ti-serdes-am654-mux-clk", + dev_read_name(dev), dev->node, + NULL); + if (ret) { + dev_err(dev, "%s: not able to bind clock driver\n", __func__); + return ret; + } + + return 0; +} + +static int serdes_am654_probe(struct udevice *dev) +{ + struct serdes_am654 *phy = dev_get_priv(dev); + struct power_domain serdes_pwrdmn; + struct regmap *serdes_ctl; + struct regmap *map; + int ret; + + ret = regmap_init_mem(dev_ofnode(dev), &map); + if (ret) + return ret; + + phy->regmap = map; + + serdes_ctl = syscon_regmap_lookup_by_phandle(dev, "ti,serdes-clk"); + if (IS_ERR(serdes_ctl)) { + dev_err(dev, "unable to find syscon device\n"); + return PTR_ERR(serdes_ctl); + } + + phy->serdes_ctl = serdes_ctl; + + ret = power_domain_get_by_index(dev, &serdes_pwrdmn, 0); + if (ret) { + dev_err(dev, "failed to get power domain\n"); + return ret; + } + + ret = power_domain_on(&serdes_pwrdmn); + if (ret) { + dev_err(dev, "Power domain on failed\n"); + return ret; + } + + return 0; +} + +static const struct udevice_id serdes_am654_phy_ids[] = { + { + .compatible = "ti,phy-am654-serdes", + }, +}; + +static const struct phy_ops serdes_am654_phy_ops = { + .reset = serdes_am654_reset, + .init = serdes_am654_init, + .power_on = serdes_am654_power_on, + .power_off = serdes_am654_power_off, + .of_xlate = serdes_am654_of_xlate, +}; + +U_BOOT_DRIVER(am654_serdes_phy) = { + .name = "am654_serdes_phy", + .id = UCLASS_PHY, + .of_match = serdes_am654_phy_ids, + .bind = serdes_am654_bind, + .ops = &serdes_am654_phy_ops, + .probe = serdes_am654_probe, + .priv_auto_alloc_size = sizeof(struct serdes_am654), +}; From e0598c45842ad989a3c156c8b24127cdba2d6633 Mon Sep 17 00:00:00 2001 From: Sekhar Nori Date: Thu, 1 Aug 2019 19:12:59 +0530 Subject: [PATCH 12/20] configs: am65x_evm_a53: enable PCIe support Enable support for PCIe and related configurations on AM654 EVM platform. Signed-off-by: Sekhar Nori --- configs/am65x_evm_a53_defconfig | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/configs/am65x_evm_a53_defconfig b/configs/am65x_evm_a53_defconfig index d43df6a187..1808e670fd 100644 --- a/configs/am65x_evm_a53_defconfig +++ b/configs/am65x_evm_a53_defconfig @@ -34,6 +34,8 @@ CONFIG_CMD_ASKENV=y CONFIG_CMD_GPT=y CONFIG_CMD_I2C=y CONFIG_CMD_MMC=y +CONFIG_CMD_PCI=y +CONFIG_CMD_REMOTEPROC=y # CONFIG_CMD_SETEXPR is not set CONFIG_CMD_TIME=y # CONFIG_ISO_PARTITION is not set @@ -70,6 +72,10 @@ CONFIG_PHY_FIXED=y CONFIG_DM_ETH=y CONFIG_TI_AM65_CPSW_NUSS=y CONFIG_PHY=y +CONFIG_PCI=y +CONFIG_DM_PCI=y +CONFIG_PCI_KEYSTONE=y +CONFIG_AM654_PHY=y CONFIG_PINCTRL=y # CONFIG_PINCTRL_GENERIC is not set CONFIG_SPL_PINCTRL=y From 476e991452433b72f280147c93435ccd9423639f Mon Sep 17 00:00:00 2001 From: Sekhar Nori Date: Thu, 1 Aug 2019 19:13:00 +0530 Subject: [PATCH 13/20] arm: dts: k3-am65: add support for PCIe and SERDES Add needed device-tree nodes to support PCIe 0 and SERDES on AM65x SoC. The nodes are kept disabled by default. Signed-off-by: Sekhar Nori --- arch/arm/dts/k3-am65-main.dtsi | 108 +++++++++++++++++++++ arch/arm/dts/k3-am65.dtsi | 1 + include/dt-bindings/phy/phy-am654-serdes.h | 13 +++ 3 files changed, 122 insertions(+) create mode 100644 include/dt-bindings/phy/phy-am654-serdes.h diff --git a/arch/arm/dts/k3-am65-main.dtsi b/arch/arm/dts/k3-am65-main.dtsi index 7d03706057..0f5da9a563 100644 --- a/arch/arm/dts/k3-am65-main.dtsi +++ b/arch/arm/dts/k3-am65-main.dtsi @@ -5,6 +5,9 @@ * Copyright (C) 2016-2018 Texas Instruments Incorporated - http://www.ti.com/ */ +#include +#include + &cbass_main { gic500: interrupt-controller@1800000 { compatible = "arm,gic-v3"; @@ -143,4 +146,109 @@ clocks = <&k3_clks 113 1>; power-domains = <&k3_pds 113 TI_SCI_PD_EXCLUSIVE>; }; + + scm_conf: scm_conf@100000 { + compatible = "syscon", "simple-mfd"; + reg = <0 0x00100000 0 0x1c000>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x0 0x00100000 0x1c000>; + + serdes_mux: mux-controller { + compatible = "mmio-mux"; + #mux-control-cells = <1>; + mux-reg-masks = <0x4080 0x3>, /* SERDES0 lane select */ + <0x4090 0x3>; /* SERDES1 lane select */ + }; + + pcie0_mode: pcie-mode@4060 { + compatible = "syscon"; + reg = <0x00004060 0x4>; + }; + + pcie1_mode: pcie-mode@4070 { + compatible = "syscon"; + reg = <0x00004070 0x4>; + }; + + serdes0_clk: serdes_clk@4080 { + compatible = "syscon"; + reg = <0x00004080 0x4>; + }; + + serdes1_clk: serdes_clk@4090 { + compatible = "syscon"; + reg = <0x00004090 0x4>; + }; + + pcie_devid: pcie-devid@210 { + compatible = "syscon"; + reg = <0x00000210 0x4>; + }; + }; + + serdes0: serdes@900000 { + compatible = "ti,phy-am654-serdes"; + reg = <0x0 0x900000 0x0 0x2000>; + reg-names = "serdes"; + #phy-cells = <2>; + power-domains = <&k3_pds 153 TI_SCI_PD_EXCLUSIVE>; + clocks = <&k3_clks 153 4>, <&k3_clks 153 1>, <&serdes1 AM654_SERDES_LO_REFCLK>; + clock-output-names = "serdes0_cmu_refclk", "serdes0_lo_refclk", "serdes0_ro_refclk"; + assigned-clocks = <&k3_clks 153 4>, <&serdes0 AM654_SERDES_CMU_REFCLK>; + assigned-clock-parents = <&k3_clks 153 8>, <&k3_clks 153 4>; + ti,serdes-clk = <&serdes0_clk>; + mux-controls = <&serdes_mux 0>; + #clock-cells = <1>; + }; + + serdes1: serdes@910000 { + compatible = "ti,phy-am654-serdes"; + reg = <0x0 0x910000 0x0 0x2000>; + reg-names = "serdes"; + #phy-cells = <2>; + power-domains = <&k3_pds 154 TI_SCI_PD_EXCLUSIVE>; + clocks = <&serdes0 AM654_SERDES_RO_REFCLK>, <&k3_clks 154 1>, <&k3_clks 154 5>; + clock-output-names = "serdes1_cmu_refclk", "serdes1_lo_refclk", "serdes1_ro_refclk"; + assigned-clocks = <&k3_clks 154 5>, <&serdes1 AM654_SERDES_CMU_REFCLK>; + assigned-clock-parents = <&k3_clks 154 9>, <&k3_clks 154 5>; + ti,serdes-clk = <&serdes1_clk>; + mux-controls = <&serdes_mux 1>; + #clock-cells = <1>; + }; + + pcie0_rc: pcie@5500000 { + compatible = "ti,am654-pcie-rc"; + reg = <0x0 0x5500000 0x0 0x1000>, <0x0 0x5501000 0x0 0x1000>, <0x0 0x10000000 0x0 0x2000>, <0x0 0x5506000 0x0 0x1000>; + reg-names = "app", "dbics", "config", "atu"; + power-domains = <&k3_pds 120 TI_SCI_PD_EXCLUSIVE>; + #address-cells = <3>; + #size-cells = <2>; + ranges = <0x81000000 0 0 0x0 0x10020000 0 0x00010000 + 0x82000000 0 0x10030000 0x0 0x10030000 0 0x07FD0000>; + ti,syscon-pcie-id = <&pcie_devid>; + ti,syscon-pcie-mode = <&pcie0_mode>; + bus-range = <0x0 0xff>; + status = "disabled"; + device_type = "pci"; + num-lanes = <1>; + num-ob-windows = <16>; + num-viewport = <16>; + max-link-speed = <3>; + interrupts = ; + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 0 7>; + interrupt-map = <0 0 0 1 &pcie0_intc 0>, /* INT A */ + <0 0 0 2 &pcie0_intc 0>, /* INT B */ + <0 0 0 3 &pcie0_intc 0>, /* INT C */ + <0 0 0 4 &pcie0_intc 0>; /* INT D */ + msi-map = <0x0 &gic_its 0x0 0x10000>; + + pcie0_intc: legacy-interrupt-controller@1 { + interrupt-controller; + #interrupt-cells = <1>; + interrupt-parent = <&gic500>; + interrupts = ; + }; + }; }; diff --git a/arch/arm/dts/k3-am65.dtsi b/arch/arm/dts/k3-am65.dtsi index a3abd146d1..a1467a4dd4 100644 --- a/arch/arm/dts/k3-am65.dtsi +++ b/arch/arm/dts/k3-am65.dtsi @@ -69,6 +69,7 @@ <0x00 0x00900000 0x00 0x00900000 0x00 0x00012000>, /* serdes */ <0x00 0x01000000 0x00 0x01000000 0x00 0x0af02400>, /* Most peripherals */ <0x00 0x30800000 0x00 0x30800000 0x00 0x0bc00000>, /* MAIN NAVSS */ + <0x00 0x10000000 0x00 0x10000000 0x00 0x10000000>, /* PCIe DAT */ /* MCUSS Range */ <0x00 0x28380000 0x00 0x28380000 0x00 0x03880000>, <0x00 0x40200000 0x00 0x40200000 0x00 0x00900100>, diff --git a/include/dt-bindings/phy/phy-am654-serdes.h b/include/dt-bindings/phy/phy-am654-serdes.h new file mode 100644 index 0000000000..e8d901729e --- /dev/null +++ b/include/dt-bindings/phy/phy-am654-serdes.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * This header provides constants for AM654 SERDES. + */ + +#ifndef _DT_BINDINGS_AM654_SERDES +#define _DT_BINDINGS_AM654_SERDES + +#define AM654_SERDES_CMU_REFCLK 0 +#define AM654_SERDES_LO_REFCLK 1 +#define AM654_SERDES_RO_REFCLK 2 + +#endif /* _DT_BINDINGS_AM654_SERDES */ From 36de3b066842fc681606bc91f9b36a562627e8a9 Mon Sep 17 00:00:00 2001 From: Sekhar Nori Date: Thu, 1 Aug 2019 19:13:01 +0530 Subject: [PATCH 14/20] configs: am65x_evm_a53: enable support for PCIe ethernet cards Enable support for Intel E1000 based PCIe ethernet cards that can be used to test PCIe RC functionality on AM65x EVM. Signed-off-by: Sekhar Nori --- configs/am65x_evm_a53_defconfig | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/configs/am65x_evm_a53_defconfig b/configs/am65x_evm_a53_defconfig index 1808e670fd..7e33e4c9db 100644 --- a/configs/am65x_evm_a53_defconfig +++ b/configs/am65x_evm_a53_defconfig @@ -70,11 +70,13 @@ CONFIG_MMC_SDHCI_AM654=y CONFIG_PHY_TI=y CONFIG_PHY_FIXED=y CONFIG_DM_ETH=y +CONFIG_E1000=y +CONFIG_CMD_E1000=y CONFIG_TI_AM65_CPSW_NUSS=y -CONFIG_PHY=y CONFIG_PCI=y CONFIG_DM_PCI=y CONFIG_PCI_KEYSTONE=y +CONFIG_PHY=y CONFIG_AM654_PHY=y CONFIG_PINCTRL=y # CONFIG_PINCTRL_GENERIC is not set From 66e2637b19ed49ee4038dd9d440ce6357587b38c Mon Sep 17 00:00:00 2001 From: Adam Ford Date: Thu, 1 Aug 2019 08:47:55 -0500 Subject: [PATCH 15/20] ARM: da850-evm: Fix Lowlevel init A previous patch for enabling the NAND config set a flag called CONFIG_SKIP_LOWLEVEL_INIT when it should have been called CONFIG_SKIP_LOWLEVEL_INIT_ONLY. The affect this had was creating a delay on startup for the NOR version which is XIP and doesn't have SPL, so the lowlevel initialization functions need to operate. This delay was not really noticeable at first, but the delays have been getting longer, finally reached the point of nearly seven seconds before the board would appear to start. This patch sets the CONFIG_SKIP_LOWLEVEL_INIT_ONLY instead which means "The normal CP15 init (such as enabling the instruction cache) is still performed" per the README. It doesn't appear to have any adverse behavior on the SPI Flash or the NAND flash boards which use SPL. Fixes: 93f3362762f0 ("ARM: configs: Add da850evm_nand to boot from NAND") Signed-off-by: Adam Ford --- include/configs/da850evm.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/configs/da850evm.h b/include/configs/da850evm.h index ff536131ba..0281dbd7b4 100644 --- a/include/configs/da850evm.h +++ b/include/configs/da850evm.h @@ -26,7 +26,7 @@ #define CONFIG_SYS_OSCIN_FREQ 24000000 #define CONFIG_SYS_TIMERBASE DAVINCI_TIMER0_BASE #define CONFIG_SYS_HZ_CLOCK clk_get(DAVINCI_AUXCLK_CLKID) -#define CONFIG_SKIP_LOWLEVEL_INIT +#define CONFIG_SKIP_LOWLEVEL_INIT_ONLY #ifdef CONFIG_DIRECT_NOR_BOOT #define CONFIG_ARCH_CPU_INIT From d2c30190ee69869164c3bfafaed5143b0c316983 Mon Sep 17 00:00:00 2001 From: Adam Ford Date: Fri, 2 Aug 2019 07:03:39 -0500 Subject: [PATCH 16/20] ARM: da850-evm: Increase environment NOR partition offset The current size allocated to U-Boot is 384k, but U-Boot has grown to 436K which means that saving the environmental variables wipes out part of the U-Boot source and the board ceases to function. Due to the sector and erase size for the NOR part and a desire to not have to change partition sizes often, this patch moves the U-Boot environmental variables to an offset of 1M so saveenv does not brick the board. This patch also sets up MTDIDS and MTDPARTS to clearly show where U-Boot and U-Boot's environmental variables are located. Signed-off-by: Adam Ford --- configs/da850evm_direct_nor_defconfig | 9 +++++++-- include/configs/da850evm.h | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/configs/da850evm_direct_nor_defconfig b/configs/da850evm_direct_nor_defconfig index 2eaa29fb8f..a8ebbd95ec 100644 --- a/configs/da850evm_direct_nor_defconfig +++ b/configs/da850evm_direct_nor_defconfig @@ -21,10 +21,11 @@ CONFIG_SYS_PROMPT="U-Boot > " CONFIG_CMD_IMLS=y CONFIG_CRC32_VERIFY=y CONFIG_CMD_DM=y -# CONFIG_CMD_GPIO is not set # CONFIG_CMD_GPT is not set # CONFIG_CMD_MMC is not set +CONFIG_CMD_MTD=y # CONFIG_CMD_PART is not set +# CONFIG_CMD_SF is not set # CONFIG_CMD_SPI is not set # CONFIG_CMD_SETEXPR is not set # CONFIG_CMD_TIME is not set @@ -32,6 +33,9 @@ CONFIG_CMD_DM=y # CONFIG_CMD_EXT4 is not set # CONFIG_CMD_FAT is not set # CONFIG_CMD_FS_GENERIC is not set +CONFIG_CMD_MTDPARTS=y +CONFIG_MTDIDS_DEFAULT="nor0=physmap-flash.2" +CONFIG_MTDPARTS_DEFAULT="mtdparts=physmap-flash.2:1m(u-boot),128k(u-boot-env),-(spare)" CONFIG_CMD_DIAG=y CONFIG_OF_CONTROL=y CONFIG_DEFAULT_DEVICE_TREE="da850-evm" @@ -45,6 +49,8 @@ CONFIG_SYS_I2C_DAVINCI=y CONFIG_MTD=y CONFIG_MTD_NOR_FLASH=y CONFIG_FLASH_CFI_DRIVER=y +CONFIG_SYS_FLASH_USE_BUFFER_WRITE=y +CONFIG_FLASH_CFI_MTD=y CONFIG_SYS_FLASH_PROTECTION=y CONFIG_SYS_FLASH_CFI=y CONFIG_DM_SPI_FLASH=y @@ -66,7 +72,6 @@ CONFIG_DM_SPI=y CONFIG_DAVINCI_SPI=y CONFIG_USB=y CONFIG_DM_USB=y -# CONFIG_SPL_DM_USB is not set CONFIG_USB_OHCI_HCD=y CONFIG_USB_OHCI_DA8XX=y CONFIG_USB_MUSB_HOST=y diff --git a/include/configs/da850evm.h b/include/configs/da850evm.h index 0281dbd7b4..9bd6da015e 100644 --- a/include/configs/da850evm.h +++ b/include/configs/da850evm.h @@ -192,7 +192,7 @@ #ifdef CONFIG_USE_NOR #define CONFIG_SYS_MAX_FLASH_BANKS 1 /* max number of flash banks */ #define CONFIG_SYS_FLASH_SECT_SZ (128 << 10) /* 128KB */ -#define CONFIG_ENV_OFFSET (CONFIG_SYS_FLASH_SECT_SZ * 3) +#define CONFIG_ENV_OFFSET (SZ_1M) #define CONFIG_ENV_SIZE (10 << 10) /* 10KB */ #define CONFIG_SYS_FLASH_BASE DAVINCI_ASYNC_EMIF_DATA_CE2_BASE #define PHYS_FLASH_SIZE (8 << 20) /* Flash size 8MB */ From 79bb64678c7a3476093df097d9543ca505d2d4e4 Mon Sep 17 00:00:00 2001 From: Adam Ford Date: Fri, 2 Aug 2019 16:21:55 -0500 Subject: [PATCH 17/20] ARM: da850-evm: Enable filesystem commands when booting from NOR The configuration with NOR is mutually exclusive with MMC, and as such, the filesystem commands were disabled. With the USB host enabled, this patch enables the file system command which can be executed on storage devices attached to the USB. Signed-off-by: Adam Ford --- configs/da850evm_direct_nor_defconfig | 4 ---- 1 file changed, 4 deletions(-) diff --git a/configs/da850evm_direct_nor_defconfig b/configs/da850evm_direct_nor_defconfig index a8ebbd95ec..407a30fbbf 100644 --- a/configs/da850evm_direct_nor_defconfig +++ b/configs/da850evm_direct_nor_defconfig @@ -29,10 +29,6 @@ CONFIG_CMD_MTD=y # CONFIG_CMD_SPI is not set # CONFIG_CMD_SETEXPR is not set # CONFIG_CMD_TIME is not set -# CONFIG_CMD_EXT2 is not set -# CONFIG_CMD_EXT4 is not set -# CONFIG_CMD_FAT is not set -# CONFIG_CMD_FS_GENERIC is not set CONFIG_CMD_MTDPARTS=y CONFIG_MTDIDS_DEFAULT="nor0=physmap-flash.2" CONFIG_MTDPARTS_DEFAULT="mtdparts=physmap-flash.2:1m(u-boot),128k(u-boot-env),-(spare)" From 51cd1e2373274dc3167dabba628dcfc25828d36d Mon Sep 17 00:00:00 2001 From: Adam Ford Date: Sat, 3 Aug 2019 07:56:10 -0500 Subject: [PATCH 18/20] ARM: da850-evm: Enable SPI Flash and NAND Flash when booting NOR Historically there have been various boot options, SPI flash, NAND or NOR. The NOR flash is mutually exclusive with MMC, but it isn't mutually exclusive with NAND or SPI Flash, so this patch enables both NAND flash and SPI Flash when booting from NOR. Signed-off-by: Adam Ford --- board/davinci/da8xxevm/da850evm.c | 3 ++- configs/da850evm_direct_nor_defconfig | 8 ++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/board/davinci/da8xxevm/da850evm.c b/board/davinci/da8xxevm/da850evm.c index 2d5710076d..c9c34a0c29 100644 --- a/board/davinci/da8xxevm/da850evm.c +++ b/board/davinci/da8xxevm/da850evm.c @@ -234,7 +234,8 @@ const struct pinmux_resource pinmuxes[] = { PINMUX_ITEM(emifa_pins_cs3), PINMUX_ITEM(emifa_pins_cs4), PINMUX_ITEM(emifa_pins_nand), -#elif defined(CONFIG_USE_NOR) +#endif +#ifdef CONFIG_USE_NOR PINMUX_ITEM(emifa_pins_cs2), PINMUX_ITEM(emifa_pins_nor), #endif diff --git a/configs/da850evm_direct_nor_defconfig b/configs/da850evm_direct_nor_defconfig index 407a30fbbf..e889751b8c 100644 --- a/configs/da850evm_direct_nor_defconfig +++ b/configs/da850evm_direct_nor_defconfig @@ -24,14 +24,15 @@ CONFIG_CMD_DM=y # CONFIG_CMD_GPT is not set # CONFIG_CMD_MMC is not set CONFIG_CMD_MTD=y +CONFIG_CMD_NAND=y # CONFIG_CMD_PART is not set # CONFIG_CMD_SF is not set # CONFIG_CMD_SPI is not set # CONFIG_CMD_SETEXPR is not set # CONFIG_CMD_TIME is not set CONFIG_CMD_MTDPARTS=y -CONFIG_MTDIDS_DEFAULT="nor0=physmap-flash.2" -CONFIG_MTDPARTS_DEFAULT="mtdparts=physmap-flash.2:1m(u-boot),128k(u-boot-env),-(spare)" +CONFIG_MTDIDS_DEFAULT="nor0=physmap-flash.2,nor1=spi1.0,nand0=nand512" +CONFIG_MTDPARTS_DEFAULT="mtdparts=physmap-flash.2:1m(u-boot),128k(u-boot-env),-(spare);spi1.0:32k(SPL),480k(u-boot),64k(u-boot-env),7552k(kernel-spare),64k(MAC-Address);nand512:128k(u-boot env),512k(u-boot),128k(spl-os),8m(kernel),-(rootfs)" CONFIG_CMD_DIAG=y CONFIG_OF_CONTROL=y CONFIG_DEFAULT_DEVICE_TREE="da850-evm" @@ -49,10 +50,13 @@ CONFIG_SYS_FLASH_USE_BUFFER_WRITE=y CONFIG_FLASH_CFI_MTD=y CONFIG_SYS_FLASH_PROTECTION=y CONFIG_SYS_FLASH_CFI=y +CONFIG_NAND=y +CONFIG_NAND_DAVINCI=y CONFIG_DM_SPI_FLASH=y CONFIG_SPI_FLASH=y CONFIG_SPI_FLASH_STMICRO=y CONFIG_SPI_FLASH_WINBOND=y +CONFIG_SPI_FLASH_MTD=y CONFIG_DM_ETH=y CONFIG_MII=y CONFIG_DRIVER_TI_EMAC=y From c659a979ea777b0b1119a46f76de9e9616049374 Mon Sep 17 00:00:00 2001 From: Vignesh Raghavendra Date: Mon, 5 Aug 2019 12:26:44 -0500 Subject: [PATCH 19/20] firmware: ti_sci: Parse all resource ranges even if some is not available Do not fail if any of the requested subtypes are not available, but set the number of resources to 0 and continue parsing the resource ranges. Based on Linux kernel patch by Peter Ujfalusi Signed-off-by: Vignesh Raghavendra Reviewed-by: Lokesh Vutla --- drivers/firmware/ti_sci.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/drivers/firmware/ti_sci.c b/drivers/firmware/ti_sci.c index 1fd29f2cdf..62b1dc2006 100644 --- a/drivers/firmware/ti_sci.c +++ b/drivers/firmware/ti_sci.c @@ -3170,6 +3170,7 @@ devm_ti_sci_get_of_resource(const struct ti_sci_handle *handle, u32 resource_subtype; u16 resource_type; struct ti_sci_resource *res; + bool valid_set = false; int sets, i, ret; u32 *temp; @@ -3209,12 +3210,15 @@ devm_ti_sci_get_of_resource(const struct ti_sci_handle *handle, &res->desc[i].start, &res->desc[i].num); if (ret) { - dev_err(dev, "type %d subtype %d not allocated for host %d\n", + dev_dbg(dev, "type %d subtype %d not allocated for host %d\n", resource_type, resource_subtype, handle_to_ti_sci_info(handle)->host_id); - return ERR_PTR(ret); + res->desc[i].start = 0; + res->desc[i].num = 0; + continue; } + valid_set = true; dev_dbg(dev, "res type = %d, subtype = %d, start = %d, num = %d\n", resource_type, resource_subtype, res->desc[i].start, res->desc[i].num); @@ -3226,7 +3230,10 @@ devm_ti_sci_get_of_resource(const struct ti_sci_handle *handle, return ERR_PTR(-ENOMEM); } - return res; + if (valid_set) + return res; + + return ERR_PTR(-EINVAL); } /* Description for K2G */ From 0805fe151d8c47cfbcfddf71c0891ed4f3c10b56 Mon Sep 17 00:00:00 2001 From: Andreas Dannenberg Date: Mon, 5 Aug 2019 13:46:23 -0500 Subject: [PATCH 20/20] arm: K3: sysfw-loader: Do not require full printf() for version info A previous commit... commit 2a51e16bd57a ("configs: Make USE_TINY_PRINTF depend on SPL||TPL and be default") ...causes the System Firmware version string during SPL boot to no longer getting printed to the console as expected. To fix this issue rework the handling of that string to only use basic printf() syntax rather than for example disabling CONFIG_USE_TINY_PRINTF on affected devices, this way maintaining most of the memory size benefit the initial patch brings when it comes to SPL. Signed-off-by: Andreas Dannenberg Reviewed-by: Tom Rini --- arch/arm/mach-k3/sysfw-loader.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/arch/arm/mach-k3/sysfw-loader.c b/arch/arm/mach-k3/sysfw-loader.c index 2ede82004a..7a482bdc8a 100644 --- a/arch/arm/mach-k3/sysfw-loader.c +++ b/arch/arm/mach-k3/sysfw-loader.c @@ -251,10 +251,21 @@ void k3_sysfw_loader(void (*config_pm_done_callback)(void)) if (config_pm_done_callback) config_pm_done_callback(); - /* Output System Firmware version info */ - printf("SYSFW ABI: %d.%d (firmware rev 0x%04x '%.*s')\n", + /* + * Output System Firmware version info. Note that since the + * 'firmware_description' field is not guaranteed to be zero- + * terminated we manually add a \0 terminator if needed. Further + * note that we intentionally no longer rely on the extended + * printf() formatter '%.*s' to not having to require a more + * full-featured printf() implementation. + */ + char fw_desc[sizeof(ti_sci->version.firmware_description) + 1]; + + strncpy(fw_desc, ti_sci->version.firmware_description, + sizeof(ti_sci->version.firmware_description)); + fw_desc[sizeof(fw_desc) - 1] = '\0'; + + printf("SYSFW ABI: %d.%d (firmware rev 0x%04x '%s')\n", ti_sci->version.abi_major, ti_sci->version.abi_minor, - ti_sci->version.firmware_revision, - sizeof(ti_sci->version.firmware_description), - ti_sci->version.firmware_description); + ti_sci->version.firmware_revision, fw_desc); }