[U-Boot] [PATCH v2 00/18] Add EEPROM-based board detect support for TI K3 SoCs

This series adds the pieces needed to fully configure the TI AM654x EVM and its associated (optional) daughtercards using a GPIO-based card presence detection scheme.
Changes since initial submission: - Re-based onto latest 'master' branch - Collected all review tags - Re-tested
Andreas Dannenberg (16): arm: dts: k3-am65: Move pinctrl nodes out of U-Boot specific dtsi arm: dts: k3-am65: Add I2C nodes arm: dts: k3-am654-base-board: Enable wkup_i2c0 across all boot stages configs: am65x_evm_defconfig: Enable I2C support configs: am65x_hs_evm_defconfig: Enable I2C support arm64: dts: k3-am654-base-board: Add I2C GPIO expander @ 0x38 configs: am65x_evm_a53: Enable PCA953X-type GPIO driver configs: am65x_hs_evm_a53: Enable PCA953X-type GPIO driver configs: am65x_evm_a53: Increase malloc pool before relocation configs: am65x_hs_evm_a53: Increase malloc pool before relocation arm: K3: am654: Map common EEPROM data into SRAM scratch space ti: common: am6: Add support for board description EEPROM ti: common: am6: Add support for setting MAC addresses board: ti: am654: Use EEPROM-based board detection configs: am65x_evm: Add support for applying overlays configs: am65x_hs_evm: Add support for applying overlays
Vignesh R (2): i2c: omap24xx_i2c: Adapt driver to support K3 devices arm: omap_i2c: Remove unwanted header file inclusion
arch/arm/dts/k3-am65-main.dtsi | 60 +++++ arch/arm/dts/k3-am65-mcu.dtsi | 11 + arch/arm/dts/k3-am65-wakeup.dtsi | 19 ++ arch/arm/dts/k3-am65.dtsi | 7 + arch/arm/dts/k3-am654-base-board-u-boot.dtsi | 35 +-- arch/arm/dts/k3-am654-base-board.dts | 22 ++ arch/arm/dts/k3-am654-r5-base-board.dts | 13 + arch/arm/include/asm/omap_i2c.h | 2 - arch/arm/mach-k3/am6_init.c | 4 + arch/arm/mach-k3/include/mach/am6_hardware.h | 3 + arch/arm/mach-k3/include/mach/sys_proto.h | 2 + board/ti/am65x/Kconfig | 7 + board/ti/am65x/evm.c | 241 ++++++++++++++++++ board/ti/common/board_detect.c | 246 +++++++++++++++++++ board/ti/common/board_detect.h | 206 ++++++++++++++++ configs/am65x_evm_a53_defconfig | 11 +- configs/am65x_evm_r5_defconfig | 4 + configs/am65x_hs_evm_a53_defconfig | 11 +- configs/am65x_hs_evm_r5_defconfig | 4 + drivers/i2c/Kconfig | 2 +- include/configs/am65x_evm.h | 18 +- 21 files changed, 892 insertions(+), 36 deletions(-)

From: Vignesh R vigneshr@ti.com
K3 devices have I2C IP that is same as OMAP2+ family. Allow driver to be compiled for ARCH_K3.
Signed-off-by: Vignesh R vigneshr@ti.com Signed-off-by: Andreas Dannenberg dannenberg@ti.com Reviewed-by: Heiko Schocher hs@denx.de Reviewed-by: Lokesh Vutla lokeshvutla@ti.com --- drivers/i2c/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig index 095a9bc6a4..4772db3837 100644 --- a/drivers/i2c/Kconfig +++ b/drivers/i2c/Kconfig @@ -330,7 +330,7 @@ endif
config SYS_I2C_OMAP24XX bool "TI OMAP2+ I2C driver" - depends on ARCH_OMAP2PLUS + depends on ARCH_OMAP2PLUS || ARCH_K3 help Add support for the OMAP2+ I2C driver.

From: Vignesh R vigneshr@ti.com
There is no need for to include this header here, so drop it.
Signed-off-by: Vignesh R vigneshr@ti.com Reviewed-by: Heiko Schocher hs@denx.de Reviewed-by: Lokesh Vutla lokeshvutla@ti.com --- arch/arm/include/asm/omap_i2c.h | 2 -- 1 file changed, 2 deletions(-)
diff --git a/arch/arm/include/asm/omap_i2c.h b/arch/arm/include/asm/omap_i2c.h index c1695cbbee..a6975401da 100644 --- a/arch/arm/include/asm/omap_i2c.h +++ b/arch/arm/include/asm/omap_i2c.h @@ -3,8 +3,6 @@ #ifndef _OMAP_I2C_H #define _OMAP_I2C_H
-#include <asm/arch/cpu.h> - #ifdef CONFIG_DM_I2C
/* Information about a GPIO bank */

Only U-Boot specifc DT properties or overrides, must be in -u-boot.dtsi. Pinctrl nodes does not belong here. Now that pinctrl nodes are in kernel DT, there is no reason to be keep these in -u-boot.dtsi. Move them to proper places so that it would ease copying DT entries from kernel DT.
Signed-off-by: Vignesh R vigneshr@ti.com Reviewed-by: Lokesh Vutla lokeshvutla@ti.com --- arch/arm/dts/k3-am65-main.dtsi | 16 ++++++++++++++ arch/arm/dts/k3-am65-wakeup.dtsi | 8 +++++++ arch/arm/dts/k3-am654-base-board-u-boot.dtsi | 23 -------------------- 3 files changed, 24 insertions(+), 23 deletions(-)
diff --git a/arch/arm/dts/k3-am65-main.dtsi b/arch/arm/dts/k3-am65-main.dtsi index adcd6341e4..f7c2a60d5c 100644 --- a/arch/arm/dts/k3-am65-main.dtsi +++ b/arch/arm/dts/k3-am65-main.dtsi @@ -69,4 +69,20 @@ clock-frequency = <48000000>; current-speed = <115200>; }; + + main_pmx0: pinmux@11c000 { + compatible = "pinctrl-single"; + reg = <0x0 0x11c000 0x0 0x2e4>; + #pinctrl-cells = <1>; + pinctrl-single,register-width = <32>; + pinctrl-single,function-mask = <0xffffffff>; + }; + + main_pmx1: pinmux@11c2e8 { + compatible = "pinctrl-single"; + reg = <0x0 0x11c2e8 0x0 0x24>; + #pinctrl-cells = <1>; + pinctrl-single,register-width = <32>; + pinctrl-single,function-mask = <0xffffffff>; + }; }; diff --git a/arch/arm/dts/k3-am65-wakeup.dtsi b/arch/arm/dts/k3-am65-wakeup.dtsi index 1f591ef8bb..1b67747dfe 100644 --- a/arch/arm/dts/k3-am65-wakeup.dtsi +++ b/arch/arm/dts/k3-am65-wakeup.dtsi @@ -34,6 +34,14 @@ }; };
+ wkup_pmx0: pinmux@4301c000 { + compatible = "pinctrl-single"; + reg = <0x4301c000 0x118>; + #pinctrl-cells = <1>; + pinctrl-single,register-width = <32>; + pinctrl-single,function-mask = <0xffffffff>; + }; + wkup_uart0: serial@42300000 { compatible = "ti,am654-uart"; reg = <0x42300000 0x100>; diff --git a/arch/arm/dts/k3-am654-base-board-u-boot.dtsi b/arch/arm/dts/k3-am654-base-board-u-boot.dtsi index f5c8253831..c802f0b2b7 100644 --- a/arch/arm/dts/k3-am654-base-board-u-boot.dtsi +++ b/arch/arm/dts/k3-am654-base-board-u-boot.dtsi @@ -19,22 +19,6 @@ &cbass_main{ u-boot,dm-spl;
- main_pmx0: pinmux@11c000 { - compatible = "pinctrl-single"; - reg = <0x0 0x11c000 0x0 0x2e4>; - #pinctrl-cells = <1>; - pinctrl-single,register-width = <32>; - pinctrl-single,function-mask = <0xffffffff>; - }; - - main_pmx1: pinmux@11c2e8 { - compatible = "pinctrl-single"; - reg = <0x0 0x11c2e8 0x0 0x24>; - #pinctrl-cells = <1>; - pinctrl-single,register-width = <32>; - pinctrl-single,function-mask = <0xffffffff>; - }; - sdhci0: sdhci@04F80000 { compatible = "arasan,sdhci-5.1"; reg = <0x0 0x4F80000 0x0 0x1000>, @@ -57,13 +41,6 @@
&cbass_mcu { u-boot,dm-spl; - wkup_pmx0: pinmux@4301c000 { - compatible = "pinctrl-single"; - reg = <0x0 0x4301c000 0x0 0x118>; - #pinctrl-cells = <1>; - pinctrl-single,register-width = <32>; - pinctrl-single,function-mask = <0xffffffff>; - };
navss_mcu: navss-mcu { compatible = "simple-bus";

Add I2C DT nodes
Signed-off-by: Vignesh R vigneshr@ti.com Reviewed-by: Lokesh Vutla lokeshvutla@ti.com --- arch/arm/dts/k3-am65-main.dtsi | 44 ++++++++++++++++++++++++++++++++ arch/arm/dts/k3-am65-mcu.dtsi | 11 ++++++++ arch/arm/dts/k3-am65-wakeup.dtsi | 11 ++++++++ arch/arm/dts/k3-am65.dtsi | 6 +++++ 4 files changed, 72 insertions(+)
diff --git a/arch/arm/dts/k3-am65-main.dtsi b/arch/arm/dts/k3-am65-main.dtsi index f7c2a60d5c..9164348396 100644 --- a/arch/arm/dts/k3-am65-main.dtsi +++ b/arch/arm/dts/k3-am65-main.dtsi @@ -85,4 +85,48 @@ pinctrl-single,register-width = <32>; pinctrl-single,function-mask = <0xffffffff>; }; + + main_i2c0: i2c@2000000 { + compatible = "ti,am654-i2c", "ti,omap4-i2c"; + reg = <0x0 0x2000000 0x0 0x100>; + interrupts = <GIC_SPI 200 IRQ_TYPE_LEVEL_HIGH>; + #address-cells = <1>; + #size-cells = <0>; + clock-names = "fck"; + clocks = <&k3_clks 110 1>; + power-domains = <&k3_pds 110>; + }; + + main_i2c1: i2c@2010000 { + compatible = "ti,am654-i2c", "ti,omap4-i2c"; + reg = <0x0 0x2010000 0x0 0x100>; + interrupts = <GIC_SPI 201 IRQ_TYPE_LEVEL_HIGH>; + #address-cells = <1>; + #size-cells = <0>; + clock-names = "fck"; + clocks = <&k3_clks 111 1>; + power-domains = <&k3_pds 111>; + }; + + main_i2c2: i2c@2020000 { + compatible = "ti,am654-i2c", "ti,omap4-i2c"; + reg = <0x0 0x2020000 0x0 0x100>; + interrupts = <GIC_SPI 202 IRQ_TYPE_LEVEL_HIGH>; + #address-cells = <1>; + #size-cells = <0>; + clock-names = "fck"; + clocks = <&k3_clks 112 1>; + power-domains = <&k3_pds 112>; + }; + + main_i2c3: i2c@2030000 { + compatible = "ti,am654-i2c", "ti,omap4-i2c"; + reg = <0x0 0x2030000 0x0 0x100>; + interrupts = <GIC_SPI 203 IRQ_TYPE_LEVEL_HIGH>; + #address-cells = <1>; + #size-cells = <0>; + clock-names = "fck"; + clocks = <&k3_clks 113 1>; + power-domains = <&k3_pds 113>; + }; }; diff --git a/arch/arm/dts/k3-am65-mcu.dtsi b/arch/arm/dts/k3-am65-mcu.dtsi index 8c611d16df..1fd027748e 100644 --- a/arch/arm/dts/k3-am65-mcu.dtsi +++ b/arch/arm/dts/k3-am65-mcu.dtsi @@ -15,4 +15,15 @@ clock-frequency = <96000000>; current-speed = <115200>; }; + + mcu_i2c0: i2c@40b00000 { + compatible = "ti,am654-i2c", "ti,omap4-i2c"; + reg = <0x0 0x40b00000 0x0 0x100>; + interrupts = <GIC_SPI 564 IRQ_TYPE_LEVEL_HIGH>; + #address-cells = <1>; + #size-cells = <0>; + clock-names = "fck"; + clocks = <&k3_clks 114 1>; + power-domains = <&k3_pds 114>; + }; }; diff --git a/arch/arm/dts/k3-am65-wakeup.dtsi b/arch/arm/dts/k3-am65-wakeup.dtsi index 1b67747dfe..1f85006f55 100644 --- a/arch/arm/dts/k3-am65-wakeup.dtsi +++ b/arch/arm/dts/k3-am65-wakeup.dtsi @@ -51,4 +51,15 @@ clock-frequency = <48000000>; current-speed = <115200>; }; + + wkup_i2c0: i2c@42120000 { + compatible = "ti,am654-i2c", "ti,omap4-i2c"; + reg = <0x42120000 0x100>; + interrupts = <GIC_SPI 696 IRQ_TYPE_LEVEL_HIGH>; + #address-cells = <1>; + #size-cells = <0>; + clock-names = "fck"; + clocks = <&k3_clks 115 1>; + power-domains = <&k3_pds 115>; + }; }; diff --git a/arch/arm/dts/k3-am65.dtsi b/arch/arm/dts/k3-am65.dtsi index 3d4bf369d0..5bcf6e0693 100644 --- a/arch/arm/dts/k3-am65.dtsi +++ b/arch/arm/dts/k3-am65.dtsi @@ -22,6 +22,12 @@ serial2 = &main_uart0; serial3 = &main_uart1; serial4 = &main_uart2; + i2c0 = &wkup_i2c0; + i2c1 = &mcu_i2c0; + i2c2 = &main_i2c0; + i2c3 = &main_i2c1; + i2c4 = &main_i2c2; + i2c5 = &main_i2c3; };
chosen { };

To enable the use of an EEPROM-based board detection scheme we need to be able to access the I2C bus associated with the EEPROMs across all 3 stages of U-Boot: R5 SPL, A53 SPL, and A53 U-Boot (proper). So go ahead and add/update the wkup_i2c0 peripheral module DTS definitions and its associated pinmux node accordingly.
Signed-off-by: Andreas Dannenberg dannenberg@ti.com Reviewed-by: Lokesh Vutla lokeshvutla@ti.com --- arch/arm/dts/k3-am65.dtsi | 1 + arch/arm/dts/k3-am654-base-board-u-boot.dtsi | 12 ++++++++++++ arch/arm/dts/k3-am654-base-board.dts | 15 +++++++++++++++ arch/arm/dts/k3-am654-r5-base-board.dts | 13 +++++++++++++ 4 files changed, 41 insertions(+)
diff --git a/arch/arm/dts/k3-am65.dtsi b/arch/arm/dts/k3-am65.dtsi index 5bcf6e0693..50f4be2047 100644 --- a/arch/arm/dts/k3-am65.dtsi +++ b/arch/arm/dts/k3-am65.dtsi @@ -8,6 +8,7 @@ #include <dt-bindings/gpio/gpio.h> #include <dt-bindings/interrupt-controller/irq.h> #include <dt-bindings/interrupt-controller/arm-gic.h> +#include <dt-bindings/pinctrl/k3.h>
/ { model = "Texas Instruments K3 AM654 SoC"; diff --git a/arch/arm/dts/k3-am654-base-board-u-boot.dtsi b/arch/arm/dts/k3-am654-base-board-u-boot.dtsi index c802f0b2b7..eb057e7a96 100644 --- a/arch/arm/dts/k3-am654-base-board-u-boot.dtsi +++ b/arch/arm/dts/k3-am654-base-board-u-boot.dtsi @@ -117,6 +117,14 @@ u-boot,dm-spl; };
+&wkup_pmx0 { + u-boot,dm-spl; + + wkup_i2c0_pins_default { + u-boot,dm-spl; + }; +}; + &main_pmx0 { u-boot,dm-spl; main_uart0_pins_default: main_uart0_pins_default { @@ -189,3 +197,7 @@ pinctrl-0 = <&main_mmc1_pins_default>; sdhci-caps-mask = <0x7 0x0>; }; + +&wkup_i2c0 { + u-boot,dm-spl; +}; diff --git a/arch/arm/dts/k3-am654-base-board.dts b/arch/arm/dts/k3-am654-base-board.dts index af6956fdc1..e31411e39d 100644 --- a/arch/arm/dts/k3-am654-base-board.dts +++ b/arch/arm/dts/k3-am654-base-board.dts @@ -34,3 +34,18 @@ }; }; }; + +&wkup_pmx0 { + wkup_i2c0_pins_default: wkup-i2c0-pins-default { + pinctrl-single,pins = < + AM65X_WKUP_IOPAD(0x00e0, PIN_INPUT, 0) /* (AC7) WKUP_I2C0_SCL */ + AM65X_WKUP_IOPAD(0x00e4, PIN_INPUT, 0) /* (AD6) WKUP_I2C0_SDA */ + >; + }; +}; + +&wkup_i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&wkup_i2c0_pins_default>; + clock-frequency = <400000>; +}; diff --git a/arch/arm/dts/k3-am654-r5-base-board.dts b/arch/arm/dts/k3-am654-r5-base-board.dts index a07038be70..1ef525ea69 100644 --- a/arch/arm/dts/k3-am654-r5-base-board.dts +++ b/arch/arm/dts/k3-am654-r5-base-board.dts @@ -130,6 +130,13 @@ >; u-boot,dm-spl; }; + + wkup_i2c0_pins_default: wkup-i2c0-pins-default { + pinctrl-single,pins = < + AM65X_WKUP_IOPAD(0x00e0, PIN_INPUT, 0) /* (AC7) WKUP_I2C0_SCL */ + AM65X_WKUP_IOPAD(0x00e4, PIN_INPUT, 0) /* (AD6) WKUP_I2C0_SDA */ + >; + }; };
&memorycontroller { @@ -137,3 +144,9 @@ pinctrl-names = "default"; pinctrl-0 = <&wkup_vtt_pins_default>; }; + +&wkup_i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&wkup_i2c0_pins_default>; + clock-frequency = <400000>; +};

Enable I2C via driver model as well as the associated set of U-Boot commands to allow us interacting with various I2C slave devices.
Signed-off-by: Andreas Dannenberg dannenberg@ti.com Signed-off-by: Vignesh R vigneshr@ti.com Reviewed-by: Lokesh Vutla lokeshvutla@ti.com --- configs/am65x_evm_a53_defconfig | 4 ++++ configs/am65x_evm_r5_defconfig | 4 ++++ 2 files changed, 8 insertions(+)
diff --git a/configs/am65x_evm_a53_defconfig b/configs/am65x_evm_a53_defconfig index 41cf0100fa..e1c7cbe7dc 100644 --- a/configs/am65x_evm_a53_defconfig +++ b/configs/am65x_evm_a53_defconfig @@ -30,6 +30,7 @@ CONFIG_SPL_REMOTEPROC=y CONFIG_SPL_YMODEM_SUPPORT=y CONFIG_CMD_ASKENV=y # CONFIG_CMD_FLASH is not set +CONFIG_CMD_I2C=y CONFIG_CMD_MMC=y CONFIG_CMD_REMOTEPROC=y # CONFIG_CMD_SETEXPR is not set @@ -53,6 +54,9 @@ CONFIG_CLK_TI_SCI=y CONFIG_DMA_CHANNELS=y CONFIG_TI_K3_NAVSS_UDMA=y CONFIG_TI_SCI_PROTOCOL=y +CONFIG_DM_I2C=y +CONFIG_I2C_SET_DEFAULT_BUS_NUM=y +CONFIG_SYS_I2C_OMAP24XX=y CONFIG_DM_MAILBOX=y CONFIG_K3_SEC_PROXY=y CONFIG_DM_MMC=y diff --git a/configs/am65x_evm_r5_defconfig b/configs/am65x_evm_r5_defconfig index 3814872ec7..f832491fd3 100644 --- a/configs/am65x_evm_r5_defconfig +++ b/configs/am65x_evm_r5_defconfig @@ -35,6 +35,7 @@ CONFIG_CMD_BOOTZ=y CONFIG_CMD_ASKENV=y # CONFIG_CMD_FLASH is not set CONFIG_CMD_GPT=y +CONFIG_CMD_I2C=y CONFIG_CMD_MMC=y CONFIG_CMD_REMOTEPROC=y # CONFIG_CMD_SETEXPR is not set @@ -58,6 +59,9 @@ CONFIG_CLK_TI_SCI=y CONFIG_TI_SCI_PROTOCOL=y CONFIG_DM_GPIO=y CONFIG_DA8XX_GPIO=y +CONFIG_DM_I2C=y +CONFIG_I2C_SET_DEFAULT_BUS_NUM=y +CONFIG_SYS_I2C_OMAP24XX=y CONFIG_DM_MAILBOX=y CONFIG_K3_SEC_PROXY=y CONFIG_MISC=y

Enable I2C via driver model as well as the associated set of U-Boot commands to allow us interacting with various I2C slave devices.
Signed-off-by: Andreas Dannenberg dannenberg@ti.com Reviewed-by: Lokesh Vutla lokeshvutla@ti.com Acked-by: Andrew F. Davis afd@ti.com --- configs/am65x_hs_evm_a53_defconfig | 4 ++++ configs/am65x_hs_evm_r5_defconfig | 4 ++++ 2 files changed, 8 insertions(+)
diff --git a/configs/am65x_hs_evm_a53_defconfig b/configs/am65x_hs_evm_a53_defconfig index 9c55cd37f6..42bd90dec0 100644 --- a/configs/am65x_hs_evm_a53_defconfig +++ b/configs/am65x_hs_evm_a53_defconfig @@ -33,6 +33,7 @@ CONFIG_SPL_REMOTEPROC=y CONFIG_SPL_YMODEM_SUPPORT=y CONFIG_CMD_ASKENV=y # CONFIG_CMD_FLASH is not set +CONFIG_CMD_I2C=y CONFIG_CMD_MMC=y CONFIG_CMD_REMOTEPROC=y # CONFIG_CMD_SETEXPR is not set @@ -56,6 +57,9 @@ CONFIG_CLK_TI_SCI=y CONFIG_DMA_CHANNELS=y CONFIG_TI_K3_NAVSS_UDMA=y CONFIG_TI_SCI_PROTOCOL=y +CONFIG_DM_I2C=y +CONFIG_I2C_SET_DEFAULT_BUS_NUM=y +CONFIG_SYS_I2C_OMAP24XX=y CONFIG_DM_MAILBOX=y CONFIG_K3_SEC_PROXY=y CONFIG_DM_MMC=y diff --git a/configs/am65x_hs_evm_r5_defconfig b/configs/am65x_hs_evm_r5_defconfig index 0b12f15782..9ce7b0a2e7 100644 --- a/configs/am65x_hs_evm_r5_defconfig +++ b/configs/am65x_hs_evm_r5_defconfig @@ -37,6 +37,7 @@ CONFIG_CMD_BOOTZ=y CONFIG_CMD_ASKENV=y # CONFIG_CMD_FLASH is not set CONFIG_CMD_GPT=y +CONFIG_CMD_I2C=y CONFIG_CMD_MMC=y CONFIG_CMD_REMOTEPROC=y # CONFIG_CMD_SETEXPR is not set @@ -60,6 +61,9 @@ CONFIG_CLK_TI_SCI=y CONFIG_TI_SCI_PROTOCOL=y CONFIG_DM_GPIO=y CONFIG_DA8XX_GPIO=y +CONFIG_DM_I2C=y +CONFIG_I2C_SET_DEFAULT_BUS_NUM=y +CONFIG_SYS_I2C_OMAP24XX=y CONFIG_DM_MAILBOX=y CONFIG_K3_SEC_PROXY=y CONFIG_MISC=y

The AM654 base board has a TCA9554/PCA9554-type GPIO expander on the wkup_i2c0 bus at address 0x38 that is used to detect the presence of daughter cards. Add a respective DTS description of this expander to enable its use.
Signed-off-by: Andreas Dannenberg dannenberg@ti.com Reviewed-by: Lokesh Vutla lokeshvutla@ti.com --- arch/arm/dts/k3-am654-base-board.dts | 7 +++++++ 1 file changed, 7 insertions(+)
diff --git a/arch/arm/dts/k3-am654-base-board.dts b/arch/arm/dts/k3-am654-base-board.dts index e31411e39d..c6a595be23 100644 --- a/arch/arm/dts/k3-am654-base-board.dts +++ b/arch/arm/dts/k3-am654-base-board.dts @@ -48,4 +48,11 @@ pinctrl-names = "default"; pinctrl-0 = <&wkup_i2c0_pins_default>; clock-frequency = <400000>; + + tca9554: gpio@38 { + compatible = "nxp,pca9554"; + reg = <0x38>; + gpio-controller; + #gpio-cells = <2>; + }; };

Enable GPIO driver for PCA953X-compatible I2C-based I/O expander which includes support for the TCA9554/PCA9554-type expander found on the AM654 EVM base board.
Signed-off-by: Andreas Dannenberg dannenberg@ti.com Reviewed-by: Lokesh Vutla lokeshvutla@ti.com --- configs/am65x_evm_a53_defconfig | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/configs/am65x_evm_a53_defconfig b/configs/am65x_evm_a53_defconfig index e1c7cbe7dc..3a8166d32d 100644 --- a/configs/am65x_evm_a53_defconfig +++ b/configs/am65x_evm_a53_defconfig @@ -54,6 +54,8 @@ CONFIG_CLK_TI_SCI=y CONFIG_DMA_CHANNELS=y CONFIG_TI_K3_NAVSS_UDMA=y CONFIG_TI_SCI_PROTOCOL=y +CONFIG_DM_GPIO=y +CONFIG_DM_PCA953X=y CONFIG_DM_I2C=y CONFIG_I2C_SET_DEFAULT_BUS_NUM=y CONFIG_SYS_I2C_OMAP24XX=y

Enable GPIO driver for PCA953X-compatible I2C-based I/O expander which includes support for the TCA9554/PCA9554-type expander found on the AM654 EVM base board.
Signed-off-by: Andreas Dannenberg dannenberg@ti.com Reviewed-by: Lokesh Vutla lokeshvutla@ti.com Acked-by: Andrew F. Davis afd@ti.com --- configs/am65x_hs_evm_a53_defconfig | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/configs/am65x_hs_evm_a53_defconfig b/configs/am65x_hs_evm_a53_defconfig index 42bd90dec0..239d5efa29 100644 --- a/configs/am65x_hs_evm_a53_defconfig +++ b/configs/am65x_hs_evm_a53_defconfig @@ -57,6 +57,8 @@ CONFIG_CLK_TI_SCI=y CONFIG_DMA_CHANNELS=y CONFIG_TI_K3_NAVSS_UDMA=y CONFIG_TI_SCI_PROTOCOL=y +CONFIG_DM_GPIO=y +CONFIG_DM_PCA953X=y CONFIG_DM_I2C=y CONFIG_I2C_SET_DEFAULT_BUS_NUM=y CONFIG_SYS_I2C_OMAP24XX=y

The malloc pool used before relocation is getting tight leading to out of memory errors doing certain DM-related calls. Since we are running the A53 SPL out of DDR let's just go ahead and bump its size as used in U-Boot proper as well as SPL (via Kconfig default value) from 8KB to 32KB.
Signed-off-by: Andreas Dannenberg dannenberg@ti.com Reviewed-by: Lokesh Vutla lokeshvutla@ti.com --- configs/am65x_evm_a53_defconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/configs/am65x_evm_a53_defconfig b/configs/am65x_evm_a53_defconfig index 3a8166d32d..2aa54706a0 100644 --- a/configs/am65x_evm_a53_defconfig +++ b/configs/am65x_evm_a53_defconfig @@ -2,7 +2,7 @@ CONFIG_ARM=y CONFIG_ARCH_K3=y CONFIG_SPL_LIBCOMMON_SUPPORT=y CONFIG_SPL_LIBGENERIC_SUPPORT=y -CONFIG_SYS_MALLOC_F_LEN=0x2000 +CONFIG_SYS_MALLOC_F_LEN=0x8000 CONFIG_SOC_K3_AM6=y CONFIG_TARGET_AM654_A53_EVM=y CONFIG_SPL_MMC_SUPPORT=y

The malloc pool used before relocation is getting tight leading to out of memory errors doing certain DM-related calls. Since we are running the A53 SPL out of DDR let's just go ahead and bump its size as used in U-Boot proper as well as SPL (via Kconfig default value) from 8KB to 32KB.
Signed-off-by: Andreas Dannenberg dannenberg@ti.com Reviewed-by: Lokesh Vutla lokeshvutla@ti.com Acked-by: Andrew F. Davis afd@ti.com --- configs/am65x_hs_evm_a53_defconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/configs/am65x_hs_evm_a53_defconfig b/configs/am65x_hs_evm_a53_defconfig index 239d5efa29..e74bd5de08 100644 --- a/configs/am65x_hs_evm_a53_defconfig +++ b/configs/am65x_hs_evm_a53_defconfig @@ -3,7 +3,7 @@ CONFIG_ARCH_K3=y CONFIG_TI_SECURE_DEVICE=y CONFIG_SPL_LIBCOMMON_SUPPORT=y CONFIG_SPL_LIBGENERIC_SUPPORT=y -CONFIG_SYS_MALLOC_F_LEN=0x2000 +CONFIG_SYS_MALLOC_F_LEN=0x8000 CONFIG_SOC_K3_AM6=y CONFIG_TARGET_AM654_A53_EVM=y CONFIG_SPL_MMC_SUPPORT=y

The board detection scheme employed on various TI EVMs makes use of SRAM scratch space to share data read from an on-board EEPROM between the different bootloading stages. Map the associated definition that's used to locate this data into the SRAM scratch space we use on AM654x.
Signed-off-by: Andreas Dannenberg dannenberg@ti.com Reviewed-by: Lokesh Vutla lokeshvutla@ti.com --- arch/arm/mach-k3/include/mach/am6_hardware.h | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/arch/arm/mach-k3/include/mach/am6_hardware.h b/arch/arm/mach-k3/include/mach/am6_hardware.h index 3343233aa3..6df7631545 100644 --- a/arch/arm/mach-k3/include/mach/am6_hardware.h +++ b/arch/arm/mach-k3/include/mach/am6_hardware.h @@ -44,4 +44,7 @@ #define CTRLMMR_LOCK_KICK1 0x0100c #define CTRLMMR_LOCK_KICK1_UNLOCK_VAL 0xd172bc5a
+/* MCU SCRATCHPAD usage */ +#define TI_SRAM_SCRATCH_BOARD_EEPROM_START CONFIG_SYS_K3_MCU_SCRATCHPAD_BASE + #endif /* __ASM_ARCH_AM6_HARDWARE_H */

The AM654x EVM based on the TI K3 family of SoCs have an updated board detection EEPROM structure, now comprising variable-sized TLV-type records, containing a superset of what is already being provided on earlier platforms such as DRA7. Add basic support for parsing the new data structures contained on the base board into the common TI EEPROM structure while also providing infrastructure that can be used later on to parse data from additional EEPROMs such as the ones that are used on daughtercards for this platform.
Signed-off-by: Andreas Dannenberg dannenberg@ti.com Reviewed-by: Lokesh Vutla lokeshvutla@ti.com --- board/ti/common/board_detect.c | 214 +++++++++++++++++++++++++++++++++ board/ti/common/board_detect.h | 194 ++++++++++++++++++++++++++++++ 2 files changed, 408 insertions(+)
diff --git a/board/ti/common/board_detect.c b/board/ti/common/board_detect.c index e258e22f37..fea39f21e8 100644 --- a/board/ti/common/board_detect.c +++ b/board/ti/common/board_detect.c @@ -8,6 +8,7 @@ */
#include <common.h> +#include <asm/arch/hardware.h> #include <asm/omap_common.h> #include <dm/uclass.h> #include <i2c.h> @@ -284,6 +285,191 @@ int __maybe_unused ti_i2c_eeprom_dra7_get(int bus_addr, int dev_addr) return 0; }
+static int ti_i2c_eeprom_am6_parse_record(struct ti_am6_eeprom_record *record, + struct ti_am6_eeprom *ep, + char **mac_addr, + u8 mac_addr_max_cnt, + u8 *mac_addr_cnt) +{ + switch (record->header.id) { + case TI_AM6_EEPROM_RECORD_BOARD_INFO: + if (record->header.len != sizeof(record->data.board_info)) + return -EINVAL; + + if (!ep) + break; + + /* Populate (and clean, if needed) the board name */ + strlcpy(ep->name, record->data.board_info.name, + sizeof(ep->name)); + ti_eeprom_string_cleanup(ep->name); + + /* Populate selected other fields from the board info record */ + strlcpy(ep->version, record->data.board_info.version, + sizeof(ep->version)); + strlcpy(ep->software_revision, + record->data.board_info.software_revision, + sizeof(ep->software_revision)); + strlcpy(ep->serial, record->data.board_info.serial, + sizeof(ep->serial)); + break; + case TI_AM6_EEPROM_RECORD_MAC_INFO: + if (record->header.len != sizeof(record->data.mac_info)) + return -EINVAL; + + if (!mac_addr || !mac_addr_max_cnt) + break; + + *mac_addr_cnt = ((record->data.mac_info.mac_control & + TI_AM6_EEPROM_MAC_ADDR_COUNT_MASK) >> + TI_AM6_EEPROM_MAC_ADDR_COUNT_SHIFT) + 1; + + /* + * The EEPROM can (but may not) hold a very large amount + * of MAC addresses, by far exceeding what we want/can store + * in the common memory array, so only grab what we can fit. + * Note that a value of 0 means 1 MAC address, and so on. + */ + *mac_addr_cnt = min(*mac_addr_cnt, mac_addr_max_cnt); + + memcpy(mac_addr, record->data.mac_info.mac_addr, + *mac_addr_cnt * TI_EEPROM_HDR_ETH_ALEN); + break; + case 0x00: + /* Illegal value... Fall through... */ + case 0xFF: + /* Illegal value... Something went horribly wrong... */ + return -EINVAL; + default: + pr_warn("%s: Ignoring record id %u\n", __func__, + record->header.id); + } + + return 0; +} + +int __maybe_unused ti_i2c_eeprom_am6_get(int bus_addr, int dev_addr, + struct ti_am6_eeprom *ep, + char **mac_addr, + u8 mac_addr_max_cnt, + u8 *mac_addr_cnt) +{ + struct udevice *dev; + struct udevice *bus; + unsigned int eeprom_addr; + struct ti_am6_eeprom_record_board_id board_id; + struct ti_am6_eeprom_record record; + int rc; + + /* Initialize with a known bad marker for i2c fails.. */ + memset(ep, 0, sizeof(*ep)); + ep->header = TI_DEAD_EEPROM_MAGIC; + + /* Read the board ID record which is always the first EEPROM record */ + rc = ti_i2c_eeprom_get(bus_addr, dev_addr, TI_EEPROM_HEADER_MAGIC, + sizeof(board_id), (uint8_t *)&board_id); + if (rc) + return rc; + + if (board_id.header.id != TI_AM6_EEPROM_RECORD_BOARD_ID) { + pr_err("%s: Invalid board ID record!\n", __func__); + return -EINVAL; + } + + /* Establish DM handle to board config EEPROM */ + rc = uclass_get_device_by_seq(UCLASS_I2C, bus_addr, &bus); + if (rc) + return rc; + rc = i2c_get_chip(bus, dev_addr, 1, &dev); + if (rc) + return rc; + + ep->header = TI_EEPROM_HEADER_MAGIC; + + /* Ready to parse TLV structure. Initialize variables... */ + *mac_addr_cnt = 0; + + /* + * After the all-encompassing board ID record all other records follow + * a TLV-type scheme. Point to the first such record and then start + * parsing those one by one. + */ + eeprom_addr = sizeof(board_id); + + while (true) { + rc = dm_i2c_read(dev, eeprom_addr, (uint8_t *)&record.header, + sizeof(record.header)); + if (rc) + return rc; + + /* + * Check for end of list marker. If we reached it don't go + * any further and stop parsing right here. + */ + if (record.header.id == TI_AM6_EEPROM_RECORD_END_LIST) + break; + + eeprom_addr += sizeof(record.header); + + debug("%s: dev_addr=0x%02x header.id=%u header.len=%u\n", + __func__, dev_addr, record.header.id, + record.header.len); + + /* Read record into memory if it fits */ + if (record.header.len <= sizeof(record.data)) { + rc = dm_i2c_read(dev, eeprom_addr, + (uint8_t *)&record.data, + record.header.len); + if (rc) + return rc; + + /* Process record */ + rc = ti_i2c_eeprom_am6_parse_record(&record, ep, + mac_addr, + mac_addr_max_cnt, + mac_addr_cnt); + if (rc) { + pr_err("%s: EEPROM parsing error!\n", __func__); + return rc; + } + } else { + /* + * We may get here in case of larger records which + * are not yet understood. + */ + pr_err("%s: Ignoring record id %u\n", __func__, + record.header.id); + } + + eeprom_addr += record.header.len; + } + + return 0; +} + +int __maybe_unused ti_i2c_eeprom_am6_get_base(int bus_addr, int dev_addr) +{ + struct ti_am6_eeprom *ep = TI_AM6_EEPROM_DATA; + int ret; + + /* + * Always execute EEPROM read by not allowing to bypass it during the + * first invocation of SPL which happens on the R5 core. + */ +#if !(defined(CONFIG_SPL_BUILD) && defined(CONFIG_CPU_V7R)) + if (ep->header == TI_EEPROM_HEADER_MAGIC) { + debug("%s: EEPROM has already been read\n", __func__); + return 0; + } +#endif + + ret = ti_i2c_eeprom_am6_get(bus_addr, dev_addr, ep, + (char **)ep->mac_addr, + AM6_EEPROM_HDR_NO_OF_MAC_ADDR, + &ep->mac_addr_cnt); + return ret; +} + bool __maybe_unused board_ti_is(char *name_tag) { struct ti_common_eeprom *ep = TI_EEPROM_DATA; @@ -391,6 +577,34 @@ void __maybe_unused set_board_info_env(char *name) env_set("board_serial", unknown); }
+void __maybe_unused set_board_info_env_am6(char *name) +{ + char *unknown = "unknown"; + struct ti_am6_eeprom *ep = TI_AM6_EEPROM_DATA; + + if (name) + env_set("board_name", name); + else if (ep->name) + env_set("board_name", ep->name); + else + env_set("board_name", unknown); + + if (ep->version) + env_set("board_rev", ep->version); + else + env_set("board_rev", unknown); + + if (ep->software_revision) + env_set("board_software_revision", ep->software_revision); + else + env_set("board_software_revision", unknown); + + if (ep->serial) + env_set("board_serial", ep->serial); + else + env_set("board_serial", unknown); +} + static u64 mac_to_u64(u8 mac[6]) { int i; diff --git a/board/ti/common/board_detect.h b/board/ti/common/board_detect.h index f8495a7a7c..bf563c84c8 100644 --- a/board/ti/common/board_detect.h +++ b/board/ti/common/board_detect.h @@ -43,6 +43,133 @@ struct ti_am_eeprom { char mac_addr[TI_EEPROM_HDR_NO_OF_MAC_ADDR][TI_EEPROM_HDR_ETH_ALEN]; } __attribute__ ((__packed__));
+/* AM6x TI EVM EEPROM Definitions */ +#define TI_AM6_EEPROM_RECORD_BOARD_ID 0x01 +#define TI_AM6_EEPROM_RECORD_BOARD_INFO 0x10 +#define TI_AM6_EEPROM_RECORD_DDR_INFO 0x11 +#define TI_AM6_EEPROM_RECORD_DDR_SPD 0x12 +#define TI_AM6_EEPROM_RECORD_MAC_INFO 0x13 +#define TI_AM6_EEPROM_RECORD_END_LIST 0xFE + +/* + * Common header for AM6x TI EVM EEPROM records. Used to encapsulate the config + * EEPROM in its entirety as well as for individual records contained within. + */ +struct ti_am6_eeprom_record_header { + u8 id; + u16 len; +} __attribute__ ((__packed__)); + +/* AM6x TI EVM EEPROM board ID structure */ +struct ti_am6_eeprom_record_board_id { + u32 magic_number; + struct ti_am6_eeprom_record_header header; +} __attribute__ ((__packed__)); + +/* AM6x TI EVM EEPROM board info structure */ +#define AM6_EEPROM_HDR_NAME_LEN 16 +#define AM6_EEPROM_HDR_VERSION_LEN 2 +#define AM6_EEPROM_HDR_PROC_NR_LEN 4 +#define AM6_EEPROM_HDR_VARIANT_LEN 2 +#define AM6_EEPROM_HDR_PCB_REV_LEN 2 +#define AM6_EEPROM_HDR_SCH_BOM_REV_LEN 2 +#define AM6_EEPROM_HDR_SW_REV_LEN 2 +#define AM6_EEPROM_HDR_VID_LEN 2 +#define AM6_EEPROM_HDR_BLD_WK_LEN 2 +#define AM6_EEPROM_HDR_BLD_YR_LEN 2 +#define AM6_EEPROM_HDR_4P_NR_LEN 6 +#define AM6_EEPROM_HDR_SERIAL_LEN 4 + +struct ti_am6_eeprom_record_board_info { + char name[AM6_EEPROM_HDR_NAME_LEN]; + char version[AM6_EEPROM_HDR_VERSION_LEN]; + char proc_number[AM6_EEPROM_HDR_PROC_NR_LEN]; + char variant[AM6_EEPROM_HDR_VARIANT_LEN]; + char pcb_revision[AM6_EEPROM_HDR_PCB_REV_LEN]; + char schematic_bom_revision[AM6_EEPROM_HDR_SCH_BOM_REV_LEN]; + char software_revision[AM6_EEPROM_HDR_SW_REV_LEN]; + char vendor_id[AM6_EEPROM_HDR_VID_LEN]; + char build_week[AM6_EEPROM_HDR_BLD_WK_LEN]; + char build_year[AM6_EEPROM_HDR_BLD_YR_LEN]; + char board_4p_number[AM6_EEPROM_HDR_4P_NR_LEN]; + char serial[AM6_EEPROM_HDR_SERIAL_LEN]; +} __attribute__ ((__packed__)); + +/* Memory location to keep a copy of the AM6 board info record */ +#define TI_AM6_EEPROM_BD_INFO_DATA ((struct ti_am6_eeprom_record_board_info *) \ + TI_SRAM_SCRATCH_BOARD_EEPROM_START) + +/* AM6x TI EVM EEPROM DDR info structure */ +#define TI_AM6_EEPROM_DDR_CTRL_INSTANCE_MASK GENMASK(1, 0) +#define TI_AM6_EEPROM_DDR_CTRL_INSTANCE_SHIFT 0 +#define TI_AM6_EEPROM_DDR_CTRL_SPD_DATA_LOC_MASK GENMASK(3, 2) +#define TI_AM6_EEPROM_DDR_CTRL_SPD_DATA_LOC_NA (0 << 2) +#define TI_AM6_EEPROM_DDR_CTRL_SPD_DATA_LOC_BOARDID (2 << 2) +#define TI_AM6_EEPROM_DDR_CTRL_SPD_DATA_LOC_I2C51 (3 << 2) +#define TI_AM6_EEPROM_DDR_CTRL_MEM_TYPE_MASK GENMASK(5, 4) +#define TI_AM6_EEPROM_DDR_CTRL_MEM_TYPE_DDR3 (0 << 4) +#define TI_AM6_EEPROM_DDR_CTRL_MEM_TYPE_DDR4 (1 << 4) +#define TI_AM6_EEPROM_DDR_CTRL_MEM_TYPE_LPDDR4 (2 << 4) +#define TI_AM6_EEPROM_DDR_CTRL_IF_DATA_WIDTH_MASK GENMASK(7, 6) +#define TI_AM6_EEPROM_DDR_CTRL_IF_DATA_WIDTH_16 (0 << 6) +#define TI_AM6_EEPROM_DDR_CTRL_IF_DATA_WIDTH_32 (1 << 6) +#define TI_AM6_EEPROM_DDR_CTRL_IF_DATA_WIDTH_64 (2 << 6) +#define TI_AM6_EEPROM_DDR_CTRL_DEV_DATA_WIDTH_MASK GENMASK(9, 8) +#define TI_AM6_EEPROM_DDR_CTRL_DEV_DATA_WIDTH_8 (0 << 8) +#define TI_AM6_EEPROM_DDR_CTRL_DEV_DATA_WIDTH_16 (1 << 8) +#define TI_AM6_EEPROM_DDR_CTRL_DEV_DATA_WIDTH_32 (2 << 8) +#define TI_AM6_EEPROM_DDR_CTRL_RANKS_2 BIT(10) +#define TI_AM6_EEPROM_DDR_CTRL_DENS_MASK GENMASK(13, 11) +#define TI_AM6_EEPROM_DDR_CTRL_DENS_1GB (0 << 11) +#define TI_AM6_EEPROM_DDR_CTRL_DENS_2GB (1 << 11) +#define TI_AM6_EEPROM_DDR_CTRL_DENS_4GB (2 << 11) +#define TI_AM6_EEPROM_DDR_CTRL_DENS_8GB (3 << 11) +#define TI_AM6_EEPROM_DDR_CTRL_DENS_12GB (4 << 11) +#define TI_AM6_EEPROM_DDR_CTRL_DENS_16GB (5 << 11) +#define TI_AM6_EEPROM_DDR_CTRL_DENS_24GB (6 << 11) +#define TI_AM6_EEPROM_DDR_CTRL_DENS_32GB (7 << 11) +#define TI_AM6_EEPROM_DDR_CTRL_ECC BIT(14) + +struct ti_am6_eeprom_record_ddr_info { + u16 ddr_control; +} __attribute__ ((__packed__)); + +/* AM6x TI EVM EEPROM DDR SPD structure */ +#define TI_AM6_EEPROM_DDR_SPD_INSTANCE_MASK GENMASK(1, 0) +#define TI_AM6_EEPROM_DDR_SPD_INSTANCE_SHIFT 0 +#define TI_AM6_EEPROM_DDR_SPD_MEM_TYPE_MASK GENMASK(4, 3) +#define TI_AM6_EEPROM_DDR_SPD_MEM_TYPE_DDR3 (0 << 3) +#define TI_AM6_EEPROM_DDR_SPD_MEM_TYPE_DDR4 (1 << 3) +#define TI_AM6_EEPROM_DDR_SPD_MEM_TYPE_LPDDR4 (2 << 3) +#define TI_AM6_EEPROM_DDR_SPD_DATA_LEN 512 + +struct ti_am6_eeprom_record_ddr_spd { + u16 spd_control; + u8 data[TI_AM6_EEPROM_DDR_SPD_DATA_LEN]; +} __attribute__ ((__packed__)); + +/* AM6x TI EVM EEPROM MAC info structure */ +#define TI_AM6_EEPROM_MAC_INFO_INSTANCE_MASK GENMASK(2, 0) +#define TI_AM6_EEPROM_MAC_INFO_INSTANCE_SHIFT 0 +#define TI_AM6_EEPROM_MAC_ADDR_COUNT_MASK GENMASK(7, 3) +#define TI_AM6_EEPROM_MAC_ADDR_COUNT_SHIFT 3 +#define TI_AM6_EEPROM_MAC_ADDR_MAX_COUNT 32 + +struct ti_am6_eeprom_record_mac_info { + u16 mac_control; + u8 mac_addr[TI_AM6_EEPROM_MAC_ADDR_MAX_COUNT][TI_EEPROM_HDR_ETH_ALEN]; +} __attribute__ ((__packed__)); + +struct ti_am6_eeprom_record { + struct ti_am6_eeprom_record_header header; + union { + struct ti_am6_eeprom_record_board_info board_info; + struct ti_am6_eeprom_record_ddr_info ddr_info; + struct ti_am6_eeprom_record_ddr_spd ddr_spd; + struct ti_am6_eeprom_record_mac_info mac_info; + } data; +} __attribute__ ((__packed__)); + /* DRA7 EEPROM MAGIC Header identifier */ #define DRA7_EEPROM_HEADER_MAGIC 0xAA5533EE #define DRA7_EEPROM_HDR_NAME_LEN 16 @@ -99,6 +226,37 @@ struct ti_common_eeprom { #define TI_EEPROM_DATA ((struct ti_common_eeprom *)\ TI_SRAM_SCRATCH_BOARD_EEPROM_START)
+/* + * Maximum number of Ethernet MAC addresses extracted from the AM6x on-board + * EEPROM during the initial probe and carried forward in SRAM. + */ +#define AM6_EEPROM_HDR_NO_OF_MAC_ADDR 8 + +/** + * struct ti_am6_eeprom - Null terminated, usable EEPROM contents, as extracted + * from the AM6 on-board EEPROM. Note that we only carry a subset of data + * at this time to be considerate about memory consumption. + * @header: Magic number for data validity indication + * @name: NULL terminated name + * @version: NULL terminated version + * @software_revision: NULL terminated software revision + * @serial: Board serial number + * @mac_addr_cnt: Number of MAC addresses stored in this object + * @mac_addr: MAC addresses + */ +struct ti_am6_eeprom { + u32 header; + char name[AM6_EEPROM_HDR_NAME_LEN + 1]; + char version[AM6_EEPROM_HDR_VERSION_LEN + 1]; + char software_revision[AM6_EEPROM_HDR_SW_REV_LEN + 1]; + char serial[AM6_EEPROM_HDR_SERIAL_LEN + 1]; + u8 mac_addr_cnt; + char mac_addr[AM6_EEPROM_HDR_NO_OF_MAC_ADDR][TI_EEPROM_HDR_ETH_ALEN]; +}; + +#define TI_AM6_EEPROM_DATA ((struct ti_am6_eeprom *) \ + TI_SRAM_SCRATCH_BOARD_EEPROM_START) + /** * ti_i2c_eeprom_am_get() - Consolidated eeprom data collection for AM* TI EVMs * @bus_addr: I2C bus address @@ -116,6 +274,33 @@ int ti_i2c_eeprom_am_get(int bus_addr, int dev_addr); */ int ti_i2c_eeprom_dra7_get(int bus_addr, int dev_addr);
+/** + * ti_i2c_eeprom_am6_get() - Consolidated eeprom data for AM6x TI EVMs and + * associated daughter cards, parsed into user- + * provided data structures + * @bus_addr: I2C bus address + * @dev_addr: I2C slave address + * @ep: Pointer to structure receiving AM6-specific header data + * @mac_addr: Pointer to memory receiving parsed MAC addresses. May be + * NULL to skip MAC parsing. + * @mac_addr_max_cnt: Maximum number of MAC addresses that can be stored into + * mac_addr. May be NULL to skip MAC parsing. + * @mac_addr_cnt: Pointer to a location returning how many MAC addressed got + * actually parsed. + */ +int __maybe_unused ti_i2c_eeprom_am6_get(int bus_addr, int dev_addr, + struct ti_am6_eeprom *ep, + char **mac_addr, + u8 mac_addr_max_cnt, + u8 *mac_addr_cnt); + +/** + * ti_i2c_eeprom_am6_get_base() - Consolidated eeprom data for AM6x TI EVMs + * @bus_addr: I2C bus address + * @dev_addr: I2C slave address + */ +int __maybe_unused ti_i2c_eeprom_am6_get_base(int bus_addr, int dev_addr); + /** * board_ti_is() - Board detection logic for TI EVMs * @name_tag: Tag used in eeprom for the board @@ -192,6 +377,15 @@ u64 board_ti_get_emif2_size(void); */ void set_board_info_env(char *name);
+/** + * set_board_info_env_am6() - Setup commonly used board information environment + * vars for AM6-type boards + * @name: Name of the board + * + * If name is NULL, default_name is used. + */ +void set_board_info_env_am6(char *name); + /** * board_ti_set_ethaddr- Sets the ethaddr environment from EEPROM * @index: The first eth<index>addr environment variable to set

The AM654x EVM based on the TI K3 family of SoCs has an updated board detection EEPROM structure that contains a TLV record of dedicated MAC addresses rather than a range of MAC addresses as it was used on earlier platforms such as DRA7. Add a basic function that allows us setting up Ethernet MAC addresses into the U-Boot environment based on the MAC address record contained in the common TI EEPROM structure.
Signed-off-by: Andreas Dannenberg dannenberg@ti.com Reviewed-by: Lokesh Vutla lokeshvutla@ti.com --- board/ti/common/board_detect.c | 32 ++++++++++++++++++++++++++++++++ board/ti/common/board_detect.h | 12 ++++++++++++ 2 files changed, 44 insertions(+)
diff --git a/board/ti/common/board_detect.c b/board/ti/common/board_detect.c index fea39f21e8..32fa10599e 100644 --- a/board/ti/common/board_detect.c +++ b/board/ti/common/board_detect.c @@ -534,6 +534,25 @@ fail: memset(mac_addr, 0, TI_EEPROM_HDR_ETH_ALEN); }
+void __maybe_unused +board_ti_am6_get_eth_mac_addr(int index, + u8 mac_addr[TI_EEPROM_HDR_ETH_ALEN]) +{ + struct ti_am6_eeprom *ep = TI_AM6_EEPROM_DATA; + + if (ep->header == TI_DEAD_EEPROM_MAGIC) + goto fail; + + if (index < 0 || index >= ep->mac_addr_cnt) + goto fail; + + memcpy(mac_addr, ep->mac_addr[index], TI_EEPROM_HDR_ETH_ALEN); + return; + +fail: + memset(mac_addr, 0, TI_EEPROM_HDR_ETH_ALEN); +} + u64 __maybe_unused board_ti_get_emif1_size(void) { struct ti_common_eeprom *ep = TI_EEPROM_DATA; @@ -667,6 +686,19 @@ void board_ti_set_ethaddr(int index) } }
+void board_ti_am6_set_ethaddr(int index, int count) +{ + u8 mac_addr[6]; + int i; + + for (i = 0; i < count; i++) { + board_ti_am6_get_eth_mac_addr(i, mac_addr); + if (is_valid_ethaddr(mac_addr)) + eth_env_set_enetaddr_by_index("eth", i + index, + mac_addr); + } +} + bool __maybe_unused board_ti_was_eeprom_read(void) { struct ti_common_eeprom *ep = TI_EEPROM_DATA; diff --git a/board/ti/common/board_detect.h b/board/ti/common/board_detect.h index bf563c84c8..a45d8961b9 100644 --- a/board/ti/common/board_detect.h +++ b/board/ti/common/board_detect.h @@ -398,6 +398,18 @@ void set_board_info_env_am6(char *name); */ void board_ti_set_ethaddr(int index);
+/** + * board_ti_am6_set_ethaddr- Sets the ethaddr environment from EEPROM + * @index: The first eth<index>addr environment variable to set + * @count: The number of MAC addresses to process + * + * EEPROM should be already read before calling this function. The EEPROM + * contains n dedicated MAC addresses. This function sets the ethaddr + * environment variable for all the available MAC addresses starting + * from eth<index>addr. + */ +void board_ti_am6_set_ethaddr(int index, int count); + /** * board_ti_was_eeprom_read() - Check to see if the eeprom contents have been read *

The TI AM654x EVM base board and the associated daughtercards have on- board I2C-based EEPROMs containing board configuration data. Use the board detection infrastructure introduced earlier to do the following:
1) Parse the AM654x EVM base board EEPROM and populate items like board name and MAC addresses into the TI common EEPROM data structure residing in SRAM scratch space 2) Check for presence of daughter card(s) by probing the associated presence signals via an I2C-based GPIO expander. Then, if such a card is found, parse the data such as additional Ethernet MAC addresses from its on-board EEPROM and populate into U-Boot accordingly 3) Dynamically create an U-Boot ENV variable called overlay_files containing a list of daugherboard-specific DTB overlays based on daughercards found.
This patch adds support for the AM654x base board ("AM6-COMPROCEVM") as well as for the IDK ("AM6-IDKAPPEVM"), OLDI LCD ("OLDI-LCD1EVM") PCIe/USB3.0 ("SER-PCIEUSBEVM"), 2 Lane PCIe/USB2.0 ("SER-PCIE2LEVM"), and general purpuse ("AM6-GPAPPEVM") daughtercards.
Signed-off-by: Andreas Dannenberg dannenberg@ti.com Reviewed-by: Lokesh Vutla lokeshvutla@ti.com --- arch/arm/mach-k3/am6_init.c | 4 + arch/arm/mach-k3/include/mach/sys_proto.h | 2 + board/ti/am65x/Kconfig | 7 + board/ti/am65x/evm.c | 241 ++++++++++++++++++++++ include/configs/am65x_evm.h | 9 +- 5 files changed, 257 insertions(+), 6 deletions(-)
diff --git a/arch/arm/mach-k3/am6_init.c b/arch/arm/mach-k3/am6_init.c index 60a580305d..72bce7ce43 100644 --- a/arch/arm/mach-k3/am6_init.c +++ b/arch/arm/mach-k3/am6_init.c @@ -10,6 +10,7 @@ #include <asm/io.h> #include <spl.h> #include <asm/arch/hardware.h> +#include <asm/arch/sys_proto.h> #include "common.h" #include <dm.h>
@@ -86,6 +87,9 @@ void board_init_f(ulong dummy) /* Prepare console output */ preloader_console_init();
+ /* Perform EEPROM-based board detection */ + do_board_detect(); + #ifdef CONFIG_K3_AM654_DDRSS ret = uclass_get_device(UCLASS_RAM, 0, &dev); if (ret) diff --git a/arch/arm/mach-k3/include/mach/sys_proto.h b/arch/arm/mach-k3/include/mach/sys_proto.h index 018725b4d1..787a274492 100644 --- a/arch/arm/mach-k3/include/mach/sys_proto.h +++ b/arch/arm/mach-k3/include/mach/sys_proto.h @@ -12,4 +12,6 @@ u32 wait_on_value(u32 read_bit_mask, u32 match_value, void *read_addr, u32 bound); struct ti_sci_handle *get_ti_sci_handle(void); int fdt_fixup_msmc_ram(void *blob, char *parent_path, char *node_name); +int do_board_detect(void); + #endif diff --git a/board/ti/am65x/Kconfig b/board/ti/am65x/Kconfig index 98172c28f5..64d9b8cdae 100644 --- a/board/ti/am65x/Kconfig +++ b/board/ti/am65x/Kconfig @@ -12,6 +12,8 @@ config TARGET_AM654_A53_EVM select ARM64 select SOC_K3_AM6 select SYS_DISABLE_DCACHE_OPS + select BOARD_LATE_INIT + imply TI_I2C_BOARD_DETECT
config TARGET_AM654_R5_EVM bool "TI K3 based AM654 EVM running on R5" @@ -20,6 +22,7 @@ config TARGET_AM654_R5_EVM select SOC_K3_AM6 select K3_AM654_DDRSS imply SYS_K3_SPL_ATF + imply TI_I2C_BOARD_DETECT
endchoice
@@ -34,6 +37,8 @@ config SYS_VENDOR config SYS_CONFIG_NAME default "am65x_evm"
+source "board/ti/common/Kconfig" + endif
if TARGET_AM654_R5_EVM @@ -50,4 +55,6 @@ config SYS_CONFIG_NAME config SPL_LDSCRIPT default "arch/arm/mach-omap2/u-boot-spl.lds"
+source "board/ti/common/Kconfig" + endif diff --git a/board/ti/am65x/evm.c b/board/ti/am65x/evm.c index 52f5d6b11e..7bd8c4fa66 100644 --- a/board/ti/am65x/evm.c +++ b/board/ti/am65x/evm.c @@ -8,10 +8,31 @@ */
#include <common.h> +#include <dm.h> +#include <asm/arch/sys_proto.h> +#include <asm/arch/hardware.h> +#include <asm/gpio.h> #include <asm/io.h> +#include <asm/omap_common.h> #include <spl.h> #include <asm/arch/sys_proto.h>
+#include "../common/board_detect.h" + +#define board_is_am65x_base_board() board_ti_is("AM6-COMPROCEVM") + +/* Daughter card presence detection signals */ +enum { + AM65X_EVM_APP_BRD_DET, + AM65X_EVM_LCD_BRD_DET, + AM65X_EVM_SERDES_BRD_DET, + AM65X_EVM_HDMI_GPMC_BRD_DET, + AM65X_EVM_BRD_DET_COUNT, +}; + +/* Max number of MAC addresses that are parsed/processed per daughter card */ +#define DAUGHTER_CARD_NO_OF_MAC_ADDR 8 + DECLARE_GLOBAL_DATA_PTR;
int board_init(void) @@ -80,3 +101,223 @@ int ft_board_setup(void *blob, bd_t *bd) return ret; } #endif + +int do_board_detect(void) +{ + int ret; + + ret = ti_i2c_eeprom_am6_get_base(CONFIG_EEPROM_BUS_ADDRESS, + CONFIG_EEPROM_CHIP_ADDRESS); + if (ret) + pr_err("Reading on-board EEPROM at 0x%02x failed %d\n", + CONFIG_EEPROM_CHIP_ADDRESS, ret); + + return ret; +} + +static void setup_board_eeprom_env(void) +{ + char *name = "am65x"; + + if (do_board_detect()) + goto invalid_eeprom; + + if (board_is_am65x_base_board()) + name = "am65x"; + else + printf("Unidentified board claims %s in eeprom header\n", + board_ti_get_name()); + +invalid_eeprom: + set_board_info_env_am6(name); +} + +static int init_daughtercard_det_gpio(char *gpio_name, struct gpio_desc *desc) +{ + int ret; + + memset(desc, 0, sizeof(*desc)); + + ret = dm_gpio_lookup_name(gpio_name, desc); + if (ret < 0) + return ret; + + /* Request GPIO, simply re-using the name as label */ + ret = dm_gpio_request(desc, gpio_name); + if (ret < 0) + return ret; + + return dm_gpio_set_dir_flags(desc, GPIOD_IS_IN); +} + +static int probe_daughtercards(void) +{ + struct ti_am6_eeprom ep; + struct gpio_desc board_det_gpios[AM65X_EVM_BRD_DET_COUNT]; + char mac_addr[DAUGHTER_CARD_NO_OF_MAC_ADDR][TI_EEPROM_HDR_ETH_ALEN]; + u8 mac_addr_cnt; + char name_overlays[1024] = { 0 }; + int i, j; + int ret; + + /* + * Daughter card presence detection signal name to GPIO (via I2C I/O + * expander @ address 0x38) name and EEPROM I2C address mapping. + */ + const struct { + char *gpio_name; + u8 i2c_addr; + } slot_map[AM65X_EVM_BRD_DET_COUNT] = { + { "gpio@38_0", 0x52, }, /* AM65X_EVM_APP_BRD_DET */ + { "gpio@38_1", 0x55, }, /* AM65X_EVM_LCD_BRD_DET */ + { "gpio@38_2", 0x54, }, /* AM65X_EVM_SERDES_BRD_DET */ + { "gpio@38_3", 0x53, }, /* AM65X_EVM_HDMI_GPMC_BRD_DET */ + }; + + /* Declaration of daughtercards to probe */ + const struct { + u8 slot_index; /* Slot the card is installed */ + char *card_name; /* EEPROM-programmed card name */ + char *dtbo_name; /* Device tree overlay to apply */ + u8 eth_offset; /* ethXaddr MAC address index offset */ + } cards[] = { + { + AM65X_EVM_APP_BRD_DET, + "AM6-GPAPPEVM", + "k3-am654-gp.dtbo", + 0, + }, + { + AM65X_EVM_APP_BRD_DET, + "AM6-IDKAPPEVM", + "k3-am654-idk.dtbo", + 3, + }, + { + AM65X_EVM_SERDES_BRD_DET, + "SER-PCIE2LEVM", + "k3-am654-pcie-usb2.dtbo", + 0, + }, + { + AM65X_EVM_SERDES_BRD_DET, + "SER-PCIEUSBEVM", + "k3-am654-pcie-usb3.dtbo", + 0, + }, + { + AM65X_EVM_LCD_BRD_DET, + "OLDI-LCD1EVM", + "k3-am654-evm-oldi-lcd1evm.dtbo", + 0, + }, + }; + + /* + * Initialize GPIO used for daughtercard slot presence detection and + * keep the resulting handles in local array for easier access. + */ + for (i = 0; i < AM65X_EVM_BRD_DET_COUNT; i++) { + ret = init_daughtercard_det_gpio(slot_map[i].gpio_name, + &board_det_gpios[i]); + if (ret < 0) + return ret; + } + + for (i = 0; i < ARRAY_SIZE(cards); i++) { + /* Obtain card-specific slot index and associated I2C address */ + u8 slot_index = cards[i].slot_index; + u8 i2c_addr = slot_map[slot_index].i2c_addr; + + /* + * The presence detection signal is active-low, hence skip + * over this card slot if anything other than 0 is returned. + */ + ret = dm_gpio_get_value(&board_det_gpios[slot_index]); + if (ret < 0) + return ret; + else if (ret) + continue; + + /* Get and parse the daughter card EEPROM record */ + ret = ti_i2c_eeprom_am6_get(CONFIG_EEPROM_BUS_ADDRESS, i2c_addr, + &ep, + (char **)mac_addr, + DAUGHTER_CARD_NO_OF_MAC_ADDR, + &mac_addr_cnt); + if (ret) { + pr_err("Reading daughtercard EEPROM at 0x%02x failed %d\n", + i2c_addr, ret); + /* + * Even this is pretty serious let's just skip over + * this particular daughtercard, rather than ending + * the probing process altogether. + */ + continue; + } + + /* Only process the parsed data if we found a match */ + if (strncmp(ep.name, cards[i].card_name, sizeof(ep.name))) + continue; + + printf("detected %s\n", cards[i].card_name); + + /* + * Populate any MAC addresses from daughtercard into the U-Boot + * environment, starting with a card-specific offset so we can + * have multiple cards contribute to the MAC pool in a well- + * defined manner. + */ + for (j = 0; j < mac_addr_cnt; j++) { + if (!is_valid_ethaddr((u8 *)mac_addr[j])) + continue; + + eth_env_set_enetaddr_by_index("eth", + cards[i].eth_offset + j, + (uchar *)mac_addr[j]); + } + + /* Skip if no overlays are to be added */ + if (!strlen(cards[i].dtbo_name)) + continue; + + /* + * Make sure we are not running out of buffer space by checking + * if we can fit the new overlay, a trailing space to be used + * as a separator, plus the terminating zero. + */ + if (strlen(name_overlays) + strlen(cards[i].dtbo_name) + 2 > + sizeof(name_overlays)) + return -ENOMEM; + + /* Append to our list of overlays */ + strcat(name_overlays, cards[i].dtbo_name); + strcat(name_overlays, " "); + } + + /* Apply device tree overlay(s) to the U-Boot environment, if any */ + if (strlen(name_overlays)) + return env_set("name_overlays", name_overlays); + + return 0; +} + +int board_late_init(void) +{ + struct ti_am6_eeprom *ep = TI_AM6_EEPROM_DATA; + + setup_board_eeprom_env(); + + /* + * The first MAC address for ethernet a.k.a. ethernet0 comes from + * efuse populated via the am654 gigabit eth switch subsystem driver. + * All the other ones are populated via EEPROM, hence continue with + * an index of 1. + */ + board_ti_am6_set_ethaddr(1, ep->mac_addr_cnt); + + /* Check for and probe any plugged-in daughtercards */ + probe_daughtercards(); + + return 0; +} diff --git a/include/configs/am65x_evm.h b/include/configs/am65x_evm.h index b043bf886b..7e3d6a3b8f 100644 --- a/include/configs/am65x_evm.h +++ b/include/configs/am65x_evm.h @@ -37,12 +37,9 @@ /* U-Boot general configuration */ #define EXTRA_ENV_AM65X_BOARD_SETTINGS \ "findfdt=" \ - "if test $board_name = am65x; then " \ - "setenv name_fdt k3-am654-base-board.dtb; " \ - "else if test $name_fdt = undefined; then " \ - "echo WARNING: Could not determine device tree to use;"\ - "fi; fi; " \ - "setenv fdtfile ${name_fdt}\0" \ + "setenv name_fdt k3-am654-base-board.dtb;" \ + "setenv fdtfile ${name_fdt};" \ + "setenv overlay_files ${name_overlays}\0" \ "loadaddr=0x80080000\0" \ "fdtaddr=0x82000000\0" \ "name_kern=Image\0" \

This will allow for downloading and applying overlays from an MMC/SD boot media based on the overlay_files ENV variable containing a list of overlay files.
Signed-off-by: Andreas Dannenberg dannenberg@ti.com Reviewed-by: Lokesh Vutla lokeshvutla@ti.com --- configs/am65x_evm_a53_defconfig | 3 ++- include/configs/am65x_evm.h | 9 +++++++++ 2 files changed, 11 insertions(+), 1 deletion(-)
diff --git a/configs/am65x_evm_a53_defconfig b/configs/am65x_evm_a53_defconfig index 2aa54706a0..e9a008d64f 100644 --- a/configs/am65x_evm_a53_defconfig +++ b/configs/am65x_evm_a53_defconfig @@ -16,7 +16,7 @@ CONFIG_DISTRO_DEFAULTS=y # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set CONFIG_SPL_LOAD_FIT=y CONFIG_OF_BOARD_SETUP=y -CONFIG_BOOTCOMMAND="run findfdt; run envboot; run init_${boot}; run get_kern_${boot}; run get_fdt_${boot}; run run_kern" +CONFIG_BOOTCOMMAND="run findfdt; run envboot; run init_${boot}; run get_kern_${boot}; run get_fdt_${boot}; run get_overlay_${boot}; run run_kern" # CONFIG_DISPLAY_CPUINFO is not set CONFIG_SPL_TEXT_BASE=0x80080000 CONFIG_SPL_SYS_MALLOC_SIMPLE=y @@ -80,3 +80,4 @@ CONFIG_SOC_TI=y CONFIG_SYSRESET=y CONFIG_SPL_SYSRESET=y CONFIG_SYSRESET_TI_SCI=y +CONFIG_OF_LIBFDT_OVERLAY=y diff --git a/include/configs/am65x_evm.h b/include/configs/am65x_evm.h index 7e3d6a3b8f..e3dbcce0bf 100644 --- a/include/configs/am65x_evm.h +++ b/include/configs/am65x_evm.h @@ -42,6 +42,7 @@ "setenv overlay_files ${name_overlays}\0" \ "loadaddr=0x80080000\0" \ "fdtaddr=0x82000000\0" \ + "overlayaddr=0x83000000\0" \ "name_kern=Image\0" \ "console=ttyS2,115200n8\0" \ "args_all=setenv optargs earlycon=ns16550a,mmio32,0x02800000\0" \ @@ -56,6 +57,14 @@ "rd_spec=-\0" \ "init_mmc=run args_all args_mmc\0" \ "get_fdt_mmc=load mmc ${bootpart} ${fdtaddr} ${bootdir}/${name_fdt}\0" \ + "get_overlay_mmc=" \ + "fdt address ${fdtaddr};" \ + "fdt resize 0x100000;" \ + "for overlay in $overlay_files;" \ + "do;" \ + "load mmc ${bootpart} ${overlayaddr} ${bootdir}/${overlay};" \ + "fdt apply ${overlayaddr};" \ + "done;\0" \ "get_kern_mmc=load mmc ${bootpart} ${loadaddr} " \ "${bootdir}/${name_kern}\0"

This will allow for downloading and applying overlays from an MMC/SD boot media based on the overlay_files ENV variable containing a list of overlay files.
Signed-off-by: Andreas Dannenberg dannenberg@ti.com Reviewed-by: Lokesh Vutla lokeshvutla@ti.com --- configs/am65x_hs_evm_a53_defconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/configs/am65x_hs_evm_a53_defconfig b/configs/am65x_hs_evm_a53_defconfig index e74bd5de08..270c783916 100644 --- a/configs/am65x_hs_evm_a53_defconfig +++ b/configs/am65x_hs_evm_a53_defconfig @@ -19,7 +19,7 @@ CONFIG_FIT_IMAGE_POST_PROCESS=y CONFIG_SPL_LOAD_FIT=y CONFIG_SPL_FIT_IMAGE_POST_PROCESS=y CONFIG_OF_BOARD_SETUP=y -CONFIG_BOOTCOMMAND="run findfdt; run envboot; run init_${boot}; run get_kern_${boot}; run get_fdt_${boot}; run run_kern" +CONFIG_BOOTCOMMAND="run findfdt; run envboot; run init_${boot}; run get_kern_${boot}; run get_fdt_${boot}; run get_overlay_${boot}; run run_kern" # CONFIG_DISPLAY_CPUINFO is not set CONFIG_SPL_TEXT_BASE=0x80080000 CONFIG_SPL_SYS_MALLOC_SIMPLE=y @@ -83,3 +83,4 @@ CONFIG_SOC_TI=y CONFIG_SYSRESET=y CONFIG_SPL_SYSRESET=y CONFIG_SYSRESET_TI_SCI=y +CONFIG_OF_LIBFDT_OVERLAY=y
participants (1)
-
Andreas Dannenberg