diff options
| author | Tom Rini <[email protected]> | 2026-05-01 08:12:31 -0600 |
|---|---|---|
| committer | Tom Rini <[email protected]> | 2026-05-01 08:12:31 -0600 |
| commit | bb0f3eebb3c196d9b6efbbd1e5aa9b16abbb9ad6 (patch) | |
| tree | d79d178cc3b66267ed0558f53bfc6ca200136826 | |
| parent | 21d842d4e538f93fd9d0e3f8905b26b17256d409 (diff) | |
| parent | 4c8d2a633ed22e90c6b1954b10b0f74fd678cb23 (diff) | |
Apologies for the delay, but please pull those sunxi changes into
v2026.07. Nothing earth shattering, mostly minor improvements like
better SPL power LED support, and fixes to some H616 DRAM setup. Also
some more forward looking enhancement for the SPI code. I also pulled in
Richard's raw NAND flash improvements for the H6/H616 SoC, though this
lacks proper peer testing due to the lack of mainline support for any
board actually employing those chips.
47 files changed, 418 insertions, 113 deletions
diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig index 89f0e77bcdb..ceba96b61a5 100644 --- a/arch/arm/mach-sunxi/Kconfig +++ b/arch/arm/mach-sunxi/Kconfig @@ -151,7 +151,6 @@ config DRAM_SUNXI_TPR3 config DRAM_SUNXI_TPR6 hex "DRAM TPR6 parameter" - default 0x3300c080 help TPR6 value from vendor DRAM settings. @@ -1245,15 +1244,17 @@ config SPL_SUNXI_LED_STATUS if SPL_SUNXI_LED_STATUS -config SPL_SUNXI_LED_STATUS_BIT +config SPL_SUNXI_LED_STATUS_GPIO int "GPIO number for GPIO status LED" help GPIO number for the GPIO controlling the GPIO status LED in SPL. -config SPL_SUNXI_LED_STATUS_STATE - bool "GPIO status LED initial state is on" +config SPL_SUNXI_LED_STATUS_ACTIVE_HIGH + bool "GPIO status LED is active high" + default y help - Whether the initial state of the status LED in SPL must be on or off. + Whether the GPIO of the status LED must be set high or low to turn + the LED on. endif # SPL_SUNXI_LED_STATUS diff --git a/arch/arm/mach-sunxi/dram_sun50i_h616.c b/arch/arm/mach-sunxi/dram_sun50i_h616.c index 3345c9b8e82..42a0550e015 100644 --- a/arch/arm/mach-sunxi/dram_sun50i_h616.c +++ b/arch/arm/mach-sunxi/dram_sun50i_h616.c @@ -975,7 +975,7 @@ static bool mctl_phy_init(const struct dram_para *para, val = para->tpr6 & 0xff; break; case SUNXI_DRAM_TYPE_LPDDR3: - val = para->tpr6 >> 8 & 0xff; + val = para->tpr6 >> 16 & 0xff; break; case SUNXI_DRAM_TYPE_LPDDR4: val = para->tpr6 >> 24 & 0xff; diff --git a/board/sunxi/board.c b/board/sunxi/board.c index d7722d1858a..3d1afec7c66 100644 --- a/board/sunxi/board.c +++ b/board/sunxi/board.c @@ -563,8 +563,8 @@ static void sunxi_spl_store_dram_size(phys_addr_t dram_size) static void status_led_init(void) { #if CONFIG_IS_ENABLED(SUNXI_LED_STATUS) - unsigned int state = CONFIG_SPL_SUNXI_LED_STATUS_STATE; - unsigned int gpio = CONFIG_SPL_SUNXI_LED_STATUS_BIT; + unsigned int state = IS_ENABLED(CONFIG_SPL_SUNXI_LED_STATUS_ACTIVE_HIGH); + unsigned int gpio = CONFIG_SPL_SUNXI_LED_STATUS_GPIO; gpio_request(gpio, "gpio_led"); gpio_direction_output(gpio, state); diff --git a/configs/A13-OLinuXinoM_defconfig b/configs/A13-OLinuXinoM_defconfig index f547635302f..6c5a1b33194 100644 --- a/configs/A13-OLinuXinoM_defconfig +++ b/configs/A13-OLinuXinoM_defconfig @@ -10,6 +10,8 @@ CONFIG_VIDEO_VGA_VIA_LCD=y CONFIG_VIDEO_VGA_VIA_LCD_FORCE_SYNC_ACTIVE_HIGH=y CONFIG_VIDEO_LCD_POWER="PB10" CONFIG_VIDEO_LCD_BL_PWM="PB2" +CONFIG_SPL_SUNXI_LED_STATUS=y +CONFIG_SPL_SUNXI_LED_STATUS_GPIO=201 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set CONFIG_SYS_I2C_MVTWSI=y CONFIG_SYS_I2C_SLAVE=0x7f diff --git a/configs/Bananapi_M2_Ultra_defconfig b/configs/Bananapi_M2_Ultra_defconfig index 375b0063c1a..750868033be 100644 --- a/configs/Bananapi_M2_Ultra_defconfig +++ b/configs/Bananapi_M2_Ultra_defconfig @@ -5,6 +5,8 @@ CONFIG_DRAM_CLK=576 CONFIG_SPL=y CONFIG_MACH_SUN8I_R40=y CONFIG_MMC_SUNXI_SLOT_EXTRA=2 +CONFIG_SPL_SUNXI_LED_STATUS=y +CONFIG_SPL_SUNXI_LED_STATUS_GPIO=244 # CONFIG_HAS_ARMV7_SECURE_BASE is not set CONFIG_AHCI=y # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set diff --git a/configs/Bananapi_m2m_defconfig b/configs/Bananapi_m2m_defconfig index 0c20cce49ea..f75e3e09d03 100644 --- a/configs/Bananapi_m2m_defconfig +++ b/configs/Bananapi_m2m_defconfig @@ -7,6 +7,9 @@ CONFIG_MACH_SUN8I_A33=y CONFIG_DRAM_ZQ=15291 CONFIG_DRAM_ODT_EN=y CONFIG_MMC_SUNXI_SLOT_EXTRA=2 +CONFIG_SPL_SUNXI_LED_STATUS=y +CONFIG_SPL_SUNXI_LED_STATUS_GPIO=355 +# CONFIG_SPL_SUNXI_LED_STATUS_ACTIVE_HIGH is not set # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set CONFIG_FASTBOOT_CMD_OEM_FORMAT=y CONFIG_USB_EHCI_HCD=y diff --git a/configs/Mele_A1000G_quad_defconfig b/configs/Mele_A1000G_quad_defconfig index 1f4739e0005..ee6c902970a 100644 --- a/configs/Mele_A1000G_quad_defconfig +++ b/configs/Mele_A1000G_quad_defconfig @@ -4,6 +4,8 @@ CONFIG_DEFAULT_DEVICE_TREE="sun6i-a31-mele-a1000g-quad" CONFIG_SPL=y CONFIG_MACH_SUN6I=y CONFIG_DRAM_ZQ=120 +CONFIG_SPL_SUNXI_LED_STATUS=y +CONFIG_SPL_SUNXI_LED_STATUS_GPIO=237 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set CONFIG_PHY_REALTEK=y CONFIG_ETH_DESIGNWARE=y diff --git a/configs/Mele_A1000_defconfig b/configs/Mele_A1000_defconfig index 93e73ebe3f1..48679265650 100644 --- a/configs/Mele_A1000_defconfig +++ b/configs/Mele_A1000_defconfig @@ -5,6 +5,8 @@ CONFIG_SPL=y CONFIG_MACH_SUN4I=y CONFIG_VIDEO_VGA=y CONFIG_VIDEO_COMPOSITE=y +CONFIG_SPL_SUNXI_LED_STATUS=y +CONFIG_SPL_SUNXI_LED_STATUS_GPIO=244 CONFIG_AHCI=y # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set CONFIG_SPL_I2C=y diff --git a/configs/Mele_M9_defconfig b/configs/Mele_M9_defconfig index 9b1bb97eedd..293e00db1b0 100644 --- a/configs/Mele_M9_defconfig +++ b/configs/Mele_M9_defconfig @@ -4,6 +4,8 @@ CONFIG_DEFAULT_DEVICE_TREE="sun6i-a31-m9" CONFIG_SPL=y CONFIG_MACH_SUN6I=y CONFIG_DRAM_ZQ=120 +CONFIG_SPL_SUNXI_LED_STATUS=y +CONFIG_SPL_SUNXI_LED_STATUS_GPIO=237 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set CONFIG_PHY_REALTEK=y CONFIG_ETH_DESIGNWARE=y diff --git a/configs/anbernic_rg35xx_h700_defconfig b/configs/anbernic_rg35xx_h700_defconfig index 2fa57cbecce..2abea94e979 100644 --- a/configs/anbernic_rg35xx_h700_defconfig +++ b/configs/anbernic_rg35xx_h700_defconfig @@ -16,6 +16,8 @@ CONFIG_DRAM_SUNXI_PHY_ADDR_MAP_1=y CONFIG_MACH_SUN50I_H616=y CONFIG_SUNXI_DRAM_H616_LPDDR4=y CONFIG_R_I2C_ENABLE=y +CONFIG_SPL_SUNXI_LED_STATUS=y +CONFIG_SPL_SUNXI_LED_STATUS_GPIO=268 CONFIG_SPL_I2C=y CONFIG_SPL_SYS_I2C_LEGACY=y CONFIG_SYS_I2C_MVTWSI=y diff --git a/configs/bananapi_m1_plus_defconfig b/configs/bananapi_m1_plus_defconfig index 22b69aa88cb..14ecaf759b5 100644 --- a/configs/bananapi_m1_plus_defconfig +++ b/configs/bananapi_m1_plus_defconfig @@ -6,6 +6,8 @@ CONFIG_SPL=y CONFIG_MACH_SUN7I=y CONFIG_VIDEO_COMPOSITE=y CONFIG_GMAC_TX_DELAY=3 +CONFIG_SPL_SUNXI_LED_STATUS=y +CONFIG_SPL_SUNXI_LED_STATUS_GPIO=249 CONFIG_AHCI=y # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set CONFIG_SPL_I2C=y diff --git a/configs/bananapi_m2_berry_defconfig b/configs/bananapi_m2_berry_defconfig index b406d519684..b9975211362 100644 --- a/configs/bananapi_m2_berry_defconfig +++ b/configs/bananapi_m2_berry_defconfig @@ -4,6 +4,8 @@ CONFIG_DEFAULT_DEVICE_TREE="sun8i-v40-bananapi-m2-berry" CONFIG_DRAM_CLK=576 CONFIG_SPL=y CONFIG_MACH_SUN8I_R40=y +CONFIG_SPL_SUNXI_LED_STATUS=y +CONFIG_SPL_SUNXI_LED_STATUS_GPIO=244 # CONFIG_HAS_ARMV7_SECURE_BASE is not set CONFIG_AHCI=y # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set diff --git a/configs/bananapi_m2_zero_defconfig b/configs/bananapi_m2_zero_defconfig index 337bafecd47..5041802ea8c 100644 --- a/configs/bananapi_m2_zero_defconfig +++ b/configs/bananapi_m2_zero_defconfig @@ -4,4 +4,7 @@ CONFIG_DEFAULT_DEVICE_TREE="sun8i-h2-plus-bananapi-m2-zero" CONFIG_DRAM_CLK=408 CONFIG_SPL=y CONFIG_MACH_SUN8I_H3=y +CONFIG_SPL_SUNXI_LED_STATUS=y +CONFIG_SPL_SUNXI_LED_STATUS_GPIO=362 +# CONFIG_SPL_SUNXI_LED_STATUS_ACTIVE_HIGH is not set # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set diff --git a/configs/bananapi_m64_defconfig b/configs/bananapi_m64_defconfig index d957071cb13..3d1f5d27e5d 100644 --- a/configs/bananapi_m64_defconfig +++ b/configs/bananapi_m64_defconfig @@ -4,6 +4,8 @@ CONFIG_DEFAULT_DEVICE_TREE="sun50i-a64-bananapi-m64" CONFIG_SPL=y CONFIG_MACH_SUN50I=y CONFIG_MMC_SUNXI_SLOT_EXTRA=2 +CONFIG_SPL_SUNXI_LED_STATUS=y +CONFIG_SPL_SUNXI_LED_STATUS_GPIO=120 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set CONFIG_SUPPORT_EMMC_BOOT=y CONFIG_SUN8I_EMAC=y diff --git a/configs/beelink_gs1_defconfig b/configs/beelink_gs1_defconfig index de46d205453..ebac032915f 100644 --- a/configs/beelink_gs1_defconfig +++ b/configs/beelink_gs1_defconfig @@ -5,6 +5,8 @@ CONFIG_SPL=y CONFIG_MACH_SUN50I_H6=y CONFIG_SUNXI_DRAM_H6_LPDDR3=y CONFIG_MMC_SUNXI_SLOT_EXTRA=2 +CONFIG_SPL_SUNXI_LED_STATUS=y +CONFIG_SPL_SUNXI_LED_STATUS_GPIO=356 # CONFIG_PSCI_RESET is not set # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set CONFIG_LED=y diff --git a/configs/beelink_x2_defconfig b/configs/beelink_x2_defconfig index 3b0be26f063..16a37da521d 100644 --- a/configs/beelink_x2_defconfig +++ b/configs/beelink_x2_defconfig @@ -5,6 +5,8 @@ CONFIG_DRAM_CLK=567 CONFIG_SPL=y CONFIG_MACH_SUN8I_H3=y CONFIG_MMC_SUNXI_SLOT_EXTRA=2 +CONFIG_SPL_SUNXI_LED_STATUS=y +CONFIG_SPL_SUNXI_LED_STATUS_GPIO=362 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set CONFIG_SUN8I_EMAC=y CONFIG_USB_EHCI_HCD=y diff --git a/configs/icnova-a20-adb4006_defconfig b/configs/icnova-a20-adb4006_defconfig index 507e330612e..dcb6457fe71 100644 --- a/configs/icnova-a20-adb4006_defconfig +++ b/configs/icnova-a20-adb4006_defconfig @@ -4,6 +4,8 @@ CONFIG_DEFAULT_DEVICE_TREE="sun7i-a20-icnova-a20-adb4006" CONFIG_DRAM_CLK=384 CONFIG_SPL=y CONFIG_MACH_SUN7I=y +CONFIG_SPL_SUNXI_LED_STATUS=y +CONFIG_SPL_SUNXI_LED_STATUS_GPIO=245 CONFIG_AHCI=y # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set CONFIG_SPL_I2C=y diff --git a/configs/liontron-h-a133l_defconfig b/configs/liontron-h-a133l_defconfig index 831d5b56e3a..836e8d12ff0 100644 --- a/configs/liontron-h-a133l_defconfig +++ b/configs/liontron-h-a133l_defconfig @@ -23,6 +23,9 @@ CONFIG_MACH_SUN50I_A133=y CONFIG_SUNXI_DRAM_A133_LPDDR4=y CONFIG_MMC_SUNXI_SLOT_EXTRA=2 CONFIG_R_I2C_ENABLE=y +CONFIG_SPL_SUNXI_LED_STATUS=y +CONFIG_SPL_SUNXI_LED_STATUS_GPIO=240 +# CONFIG_SPL_SUNXI_LED_STATUS_ACTIVE_HIGH is not set # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set CONFIG_SPL_I2C=y CONFIG_SPL_SYS_I2C_LEGACY=y diff --git a/configs/nanopi_duo2_defconfig b/configs/nanopi_duo2_defconfig index 41b5502d24e..9b0fbecff60 100644 --- a/configs/nanopi_duo2_defconfig +++ b/configs/nanopi_duo2_defconfig @@ -5,6 +5,8 @@ CONFIG_DRAM_CLK=408 CONFIG_SPL=y CONFIG_MACH_SUN8I_H3=y # CONFIG_VIDEO_DE2 is not set +CONFIG_SPL_SUNXI_LED_STATUS=y +CONFIG_SPL_SUNXI_LED_STATUS_GPIO=362 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set CONFIG_CONSOLE_MUX=y CONFIG_USB_EHCI_HCD=y diff --git a/configs/nanopi_neo2_defconfig b/configs/nanopi_neo2_defconfig index 6704a24a880..63fa6bac9ba 100644 --- a/configs/nanopi_neo2_defconfig +++ b/configs/nanopi_neo2_defconfig @@ -6,6 +6,8 @@ CONFIG_SPL=y CONFIG_MACH_SUN50I_H5=y CONFIG_DRAM_ZQ=3881977 # CONFIG_DRAM_ODT_EN is not set +CONFIG_SPL_SUNXI_LED_STATUS=y +CONFIG_SPL_SUNXI_LED_STATUS_GPIO=362 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set CONFIG_SUN8I_EMAC=y CONFIG_USB_EHCI_HCD=y diff --git a/configs/nanopi_neo_air_defconfig b/configs/nanopi_neo_air_defconfig index 3b8cbbfcdba..110bb1e864c 100644 --- a/configs/nanopi_neo_air_defconfig +++ b/configs/nanopi_neo_air_defconfig @@ -5,6 +5,8 @@ CONFIG_DRAM_CLK=408 CONFIG_SPL=y CONFIG_MACH_SUN8I_H3=y # CONFIG_VIDEO_DE2 is not set +CONFIG_SPL_SUNXI_LED_STATUS=y +CONFIG_SPL_SUNXI_LED_STATUS_GPIO=362 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set CONFIG_CONSOLE_MUX=y CONFIG_USB_EHCI_HCD=y diff --git a/configs/nanopi_neo_plus2_defconfig b/configs/nanopi_neo_plus2_defconfig index e80e32a63d4..9d1b783476d 100644 --- a/configs/nanopi_neo_plus2_defconfig +++ b/configs/nanopi_neo_plus2_defconfig @@ -7,6 +7,8 @@ CONFIG_MACH_SUN50I_H5=y CONFIG_DRAM_ZQ=3881977 # CONFIG_DRAM_ODT_EN is not set CONFIG_MMC_SUNXI_SLOT_EXTRA=2 +CONFIG_SPL_SUNXI_LED_STATUS=y +CONFIG_SPL_SUNXI_LED_STATUS_GPIO=362 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set CONFIG_SUN8I_EMAC=y CONFIG_USB_EHCI_HCD=y diff --git a/configs/orangepi_2_defconfig b/configs/orangepi_2_defconfig index 88433808538..43f3ab512f1 100644 --- a/configs/orangepi_2_defconfig +++ b/configs/orangepi_2_defconfig @@ -5,6 +5,8 @@ CONFIG_DEFAULT_DEVICE_TREE="sun8i-h3-orangepi-2" CONFIG_DRAM_CLK=672 CONFIG_SPL=y CONFIG_MACH_SUN8I_H3=y +CONFIG_SPL_SUNXI_LED_STATUS=y +CONFIG_SPL_SUNXI_LED_STATUS_GPIO=362 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set CONFIG_SPL_I2C=y CONFIG_SPL_SYS_I2C_LEGACY=y diff --git a/configs/orangepi_3_defconfig b/configs/orangepi_3_defconfig index 125137bc321..409fa705a06 100644 --- a/configs/orangepi_3_defconfig +++ b/configs/orangepi_3_defconfig @@ -6,6 +6,8 @@ CONFIG_MACH_SUN50I_H6=y CONFIG_SUNXI_DRAM_H6_LPDDR3=y CONFIG_MMC_SUNXI_SLOT_EXTRA=2 CONFIG_BLUETOOTH_DT_DEVICE_FIXUP="brcm,bcm4345c5" +CONFIG_SPL_SUNXI_LED_STATUS=y +CONFIG_SPL_SUNXI_LED_STATUS_GPIO=356 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set CONFIG_PHY_SUN50I_USB3=y CONFIG_USB_XHCI_HCD=y diff --git a/configs/orangepi_lite2_defconfig b/configs/orangepi_lite2_defconfig index 577f7436c15..5d72d34eb9d 100644 --- a/configs/orangepi_lite2_defconfig +++ b/configs/orangepi_lite2_defconfig @@ -4,6 +4,8 @@ CONFIG_DEFAULT_DEVICE_TREE="sun50i-h6-orangepi-lite2" CONFIG_SPL=y CONFIG_MACH_SUN50I_H6=y CONFIG_SUNXI_DRAM_H6_LPDDR3=y +CONFIG_SPL_SUNXI_LED_STATUS=y +CONFIG_SPL_SUNXI_LED_STATUS_GPIO=356 # CONFIG_PSCI_RESET is not set # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set CONFIG_USB_EHCI_HCD=y diff --git a/configs/orangepi_lite_defconfig b/configs/orangepi_lite_defconfig index ea1548f0fcd..499ffd8ace5 100644 --- a/configs/orangepi_lite_defconfig +++ b/configs/orangepi_lite_defconfig @@ -4,6 +4,8 @@ CONFIG_DEFAULT_DEVICE_TREE="sun8i-h3-orangepi-lite" CONFIG_DRAM_CLK=672 CONFIG_SPL=y CONFIG_MACH_SUN8I_H3=y +CONFIG_SPL_SUNXI_LED_STATUS=y +CONFIG_SPL_SUNXI_LED_STATUS_GPIO=362 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set CONFIG_USB_EHCI_HCD=y CONFIG_USB_OHCI_HCD=y diff --git a/configs/orangepi_one_defconfig b/configs/orangepi_one_defconfig index e4de13de26b..637eb41207e 100644 --- a/configs/orangepi_one_defconfig +++ b/configs/orangepi_one_defconfig @@ -4,6 +4,8 @@ CONFIG_DEFAULT_DEVICE_TREE="sun8i-h3-orangepi-one" CONFIG_DRAM_CLK=672 CONFIG_SPL=y CONFIG_MACH_SUN8I_H3=y +CONFIG_SPL_SUNXI_LED_STATUS=y +CONFIG_SPL_SUNXI_LED_STATUS_GPIO=362 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set CONFIG_SUN8I_EMAC=y CONFIG_USB_EHCI_HCD=y diff --git a/configs/orangepi_pc2_defconfig b/configs/orangepi_pc2_defconfig index d856a25814b..464b34f4ec0 100644 --- a/configs/orangepi_pc2_defconfig +++ b/configs/orangepi_pc2_defconfig @@ -6,6 +6,8 @@ CONFIG_SPL=y CONFIG_MACH_SUN50I_H5=y CONFIG_DRAM_ZQ=3881977 CONFIG_SPL_SPI_SUNXI=y +CONFIG_SPL_SUNXI_LED_STATUS=y +CONFIG_SPL_SUNXI_LED_STATUS_GPIO=362 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set CONFIG_SPL_I2C=y CONFIG_SPL_SYS_I2C_LEGACY=y diff --git a/configs/orangepi_pc_defconfig b/configs/orangepi_pc_defconfig index f857d7fa203..01195b68621 100644 --- a/configs/orangepi_pc_defconfig +++ b/configs/orangepi_pc_defconfig @@ -4,6 +4,8 @@ CONFIG_DEFAULT_DEVICE_TREE="sun8i-h3-orangepi-pc" CONFIG_DRAM_CLK=624 CONFIG_SPL=y CONFIG_MACH_SUN8I_H3=y +CONFIG_SPL_SUNXI_LED_STATUS=y +CONFIG_SPL_SUNXI_LED_STATUS_GPIO=362 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set CONFIG_SPL_I2C=y CONFIG_SPL_SYS_I2C_LEGACY=y diff --git a/configs/orangepi_prime_defconfig b/configs/orangepi_prime_defconfig index e93154cc0e9..e5e9009378c 100644 --- a/configs/orangepi_prime_defconfig +++ b/configs/orangepi_prime_defconfig @@ -6,6 +6,8 @@ CONFIG_SPL=y CONFIG_MACH_SUN50I_H5=y CONFIG_DRAM_ZQ=3881977 # CONFIG_DRAM_ODT_EN is not set +CONFIG_SPL_SUNXI_LED_STATUS=y +CONFIG_SPL_SUNXI_LED_STATUS_GPIO=362 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set CONFIG_SUN8I_EMAC=y CONFIG_USB_EHCI_HCD=y diff --git a/configs/orangepi_zero2_defconfig b/configs/orangepi_zero2_defconfig index 831bfe66e25..afd1535052d 100644 --- a/configs/orangepi_zero2_defconfig +++ b/configs/orangepi_zero2_defconfig @@ -5,11 +5,14 @@ CONFIG_SPL=y CONFIG_DRAM_SUNXI_DX_ODT=0x08080808 CONFIG_DRAM_SUNXI_DX_DRI=0x0e0e0e0e CONFIG_DRAM_SUNXI_CA_DRI=0x0e0e +CONFIG_DRAM_SUNXI_TPR6=0x33808080 CONFIG_DRAM_SUNXI_TPR10=0xf83438 CONFIG_MACH_SUN50I_H616=y CONFIG_SUNXI_DRAM_H616_DDR3_1333=y CONFIG_R_I2C_ENABLE=y CONFIG_SPL_SPI_SUNXI=y +CONFIG_SPL_SUNXI_LED_STATUS=y +CONFIG_SPL_SUNXI_LED_STATUS_GPIO=76 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set CONFIG_SPL_I2C=y CONFIG_SPL_SYS_I2C_LEGACY=y diff --git a/configs/orangepi_zero_defconfig b/configs/orangepi_zero_defconfig index e128f5fcdb3..49a1f4d03da 100644 --- a/configs/orangepi_zero_defconfig +++ b/configs/orangepi_zero_defconfig @@ -6,6 +6,8 @@ CONFIG_SPL=y CONFIG_MACH_SUN8I_H3=y # CONFIG_VIDEO_DE2 is not set CONFIG_SPL_SPI_SUNXI=y +CONFIG_SPL_SUNXI_LED_STATUS=y +CONFIG_SPL_SUNXI_LED_STATUS_GPIO=362 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set CONFIG_CONSOLE_MUX=y CONFIG_MTD=y diff --git a/configs/orangepi_zero_plus2_defconfig b/configs/orangepi_zero_plus2_defconfig index c4d9800975c..9758ffd385e 100644 --- a/configs/orangepi_zero_plus2_defconfig +++ b/configs/orangepi_zero_plus2_defconfig @@ -7,6 +7,8 @@ CONFIG_MACH_SUN50I_H5=y CONFIG_DRAM_ZQ=3881977 # CONFIG_DRAM_ODT_EN is not set CONFIG_MMC_SUNXI_SLOT_EXTRA=2 +CONFIG_SPL_SUNXI_LED_STATUS=y +CONFIG_SPL_SUNXI_LED_STATUS_GPIO=362 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set CONFIG_SUN8I_EMAC=y CONFIG_USB_EHCI_HCD=y diff --git a/configs/orangepi_zero_plus2_h3_defconfig b/configs/orangepi_zero_plus2_h3_defconfig index caf515c7026..63335b404da 100644 --- a/configs/orangepi_zero_plus2_h3_defconfig +++ b/configs/orangepi_zero_plus2_h3_defconfig @@ -6,6 +6,8 @@ CONFIG_SPL=y CONFIG_MACH_SUN8I_H3=y # CONFIG_DRAM_ODT_EN is not set CONFIG_MMC_SUNXI_SLOT_EXTRA=2 +CONFIG_SPL_SUNXI_LED_STATUS=y +CONFIG_SPL_SUNXI_LED_STATUS_GPIO=362 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set CONFIG_SUN8I_EMAC=y CONFIG_USB_EHCI_HCD=y diff --git a/configs/orangepi_zero_plus_defconfig b/configs/orangepi_zero_plus_defconfig index 4b6491dc846..bb159428a14 100644 --- a/configs/orangepi_zero_plus_defconfig +++ b/configs/orangepi_zero_plus_defconfig @@ -6,6 +6,8 @@ CONFIG_SPL=y CONFIG_MACH_SUN50I_H5=y CONFIG_DRAM_ZQ=3881977 # CONFIG_DRAM_ODT_EN is not set +CONFIG_SPL_SUNXI_LED_STATUS=y +CONFIG_SPL_SUNXI_LED_STATUS_GPIO=362 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set CONFIG_SUN8I_EMAC=y CONFIG_USB_EHCI_HCD=y diff --git a/configs/pinephone_defconfig b/configs/pinephone_defconfig index ed7dbc1852b..3a4f4ec51cf 100644 --- a/configs/pinephone_defconfig +++ b/configs/pinephone_defconfig @@ -9,8 +9,7 @@ CONFIG_DRAM_ZQ=3881949 CONFIG_MMC_SUNXI_SLOT_EXTRA=2 CONFIG_PINEPHONE_DT_SELECTION=y CONFIG_SPL_SUNXI_LED_STATUS=y -CONFIG_SPL_SUNXI_LED_STATUS_BIT=114 -CONFIG_SPL_SUNXI_LED_STATUS_STATE=y +CONFIG_SPL_SUNXI_LED_STATUS_GPIO=114 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set CONFIG_CMD_PSTORE=y CONFIG_CMD_PSTORE_MEM_ADDR=0x61000000 diff --git a/configs/radxa-cubie-a5e_defconfig b/configs/radxa-cubie-a5e_defconfig index 9d204ef5548..84bc4e3d4a9 100644 --- a/configs/radxa-cubie-a5e_defconfig +++ b/configs/radxa-cubie-a5e_defconfig @@ -15,6 +15,9 @@ CONFIG_DRAM_SUNXI_TPR12=0x3533302f CONFIG_MACH_SUN55I_A523=y CONFIG_MMC_SUNXI_SLOT_EXTRA=2 CONFIG_R_I2C_ENABLE=y +CONFIG_SPL_SUNXI_LED_STATUS=y +CONFIG_SPL_SUNXI_LED_STATUS_GPIO=356 +# CONFIG_SPL_SUNXI_LED_STATUS_ACTIVE_HIGH is not set # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set CONFIG_SPL_I2C=y CONFIG_SPL_SYS_I2C_LEGACY=y diff --git a/configs/tanix_tx1_defconfig b/configs/tanix_tx1_defconfig index 1bd167ce0f6..03b18701859 100644 --- a/configs/tanix_tx1_defconfig +++ b/configs/tanix_tx1_defconfig @@ -14,6 +14,8 @@ CONFIG_MACH_SUN50I_H616=y CONFIG_SUNXI_DRAM_H616_LPDDR3=y CONFIG_MMC_SUNXI_SLOT_EXTRA=2 CONFIG_R_I2C_ENABLE=y +CONFIG_SPL_SUNXI_LED_STATUS=y +CONFIG_SPL_SUNXI_LED_STATUS_GPIO=231 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set CONFIG_SPL_I2C=y CONFIG_SPL_SYS_I2C_LEGACY=y diff --git a/configs/transpeed-8k618-t_defconfig b/configs/transpeed-8k618-t_defconfig index e4bf5e8efd3..e672d8f8df9 100644 --- a/configs/transpeed-8k618-t_defconfig +++ b/configs/transpeed-8k618-t_defconfig @@ -7,6 +7,7 @@ CONFIG_DRAM_SUNXI_DX_ODT=0x03030303 CONFIG_DRAM_SUNXI_DX_DRI=0x0e0e0e0e CONFIG_DRAM_SUNXI_CA_DRI=0x1f12 CONFIG_DRAM_SUNXI_TPR0=0xc0001002 +CONFIG_DRAM_SUNXI_TPR6=0x33808080 CONFIG_DRAM_SUNXI_TPR10=0x2f1107 CONFIG_DRAM_SUNXI_TPR11=0xddddcccc CONFIG_DRAM_SUNXI_TPR12=0xeddc7665 diff --git a/configs/x96_mate_defconfig b/configs/x96_mate_defconfig index c0628370df9..1b7d9338c02 100644 --- a/configs/x96_mate_defconfig +++ b/configs/x96_mate_defconfig @@ -6,6 +6,7 @@ CONFIG_DRAM_SUNXI_DX_ODT=0x03030303 CONFIG_DRAM_SUNXI_DX_DRI=0x0e0e0e0e CONFIG_DRAM_SUNXI_CA_DRI=0x1c12 CONFIG_DRAM_SUNXI_TPR0=0xc0000c05 +CONFIG_DRAM_SUNXI_TPR6=0x33808080 CONFIG_DRAM_SUNXI_TPR10=0x2f0007 CONFIG_DRAM_SUNXI_TPR11=0xffffdddd CONFIG_DRAM_SUNXI_TPR12=0xfedf7557 diff --git a/configs/x96q_defconfig b/configs/x96q_defconfig index 59f01aae4eb..068aee3fd1e 100644 --- a/configs/x96q_defconfig +++ b/configs/x96q_defconfig @@ -8,6 +8,7 @@ CONFIG_DRAM_SUNXI_DX_DRI=0x0e0e0e0e CONFIG_DRAM_SUNXI_CA_DRI=0x1f12 CONFIG_DRAM_SUNXI_TPR0=0xc0001002 CONFIG_DRAM_SUNXI_TPR2=0x00000100 +CONFIG_DRAM_SUNXI_TPR6=0x33808080 CONFIG_DRAM_SUNXI_TPR10=0x002f0107 CONFIG_DRAM_SUNXI_TPR11=0xddddcccc CONFIG_DRAM_SUNXI_TPR12=0xeddc7665 diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c index ef27a4b7a36..49748fddf80 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -114,6 +114,7 @@ struct sunxi_nand_hw_ecc { * @clk_rate: clk_rate required for this NAND chip * @timing_cfg TIMING_CFG register value for this NAND chip * @selected: current active CS + * @user_data_bytes array of user data lengths for all ECC steps * @nsels: number of CS lines required by the NAND chip * @sels: array of CS lines descriptions */ @@ -128,6 +129,7 @@ struct sunxi_nand_chip { u32 addr[2]; int cmd_cycles; u8 cmd[2]; + u8 *user_data_bytes; int nsels; struct sunxi_nand_chip_sel sels[0]; }; @@ -744,20 +746,76 @@ static void sunxi_nfc_set_user_data_len(struct sunxi_nfc *nfc, writel(val, nfc->regs + NFC_REG_USER_DATA_LEN(nfc, step)); } +static u8 sunxi_nfc_user_data_sz(const struct sunxi_nand_chip *sunxi_nand, int step) +{ + if (!sunxi_nand->user_data_bytes) + return USER_DATA_SZ; + + return sunxi_nand->user_data_bytes[step]; +} + +static void sunxi_nfc_hw_ecc_get_prot_oob_bytes(struct nand_chip *nand, u8 *oob, + int step, bool bbm, int page, + unsigned int user_data_sz) +{ + struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); + struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); + u32 user_data; + + if (!nfc->caps->reg_user_data_len) { + /* + * For A10, the user data for step n is in the nth + * REG_USER_DATA + */ + user_data = readl(nfc->regs + NFC_REG_USER_DATA(nfc, step)); + sunxi_nfc_user_data_to_buf(user_data, oob); + + } else { + /* + * For H6 NAND controller, the user data for all steps is + * contained in 32 user data registers, but not at a specific + * offset for each step, they are just concatenated. + */ + unsigned int user_data_off = 0; + unsigned int reg_off; + u8 *ptr = oob; + unsigned int i; + + for (i = 0; i < step; i++) + user_data_off += sunxi_nfc_user_data_sz(sunxi_nand, i); + + user_data_off /= 4; + for (i = 0; i < user_data_sz / 4; i++, ptr += 4) { + reg_off = NFC_REG_USER_DATA(nfc, user_data_off + i); + user_data = readl(nfc->regs + reg_off); + sunxi_nfc_user_data_to_buf(user_data, ptr); + } + } + + /* De-randomize the Bad Block Marker. */ + if (bbm && nand->options & NAND_NEED_SCRAMBLING) + sunxi_nfc_randomize_bbm(&nand->mtd, page, oob); +} + static int sunxi_nfc_hw_ecc_read_chunk(struct mtd_info *mtd, u8 *data, int data_off, u8 *oob, int oob_off, int *cur_off, unsigned int *max_bitflips, - bool bbm, int page) + int step, int page) { struct nand_chip *nand = mtd_to_nand(mtd); struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); + struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); + unsigned int user_data_sz = sunxi_nfc_user_data_sz(sunxi_nand, step); struct nand_ecc_ctrl *ecc = &nand->ecc; int raw_mode = 0; u32 status; u32 pattern_found; + bool bbm = !step; int ret; + /* From the controller point of view, we are at step 0 */ + const int nfc_step = 0; if (*cur_off != data_off) nand->cmdfunc(mtd, NAND_CMD_RNDOUT, data_off, -1); @@ -771,8 +829,7 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct mtd_info *mtd, if (ret) return ret; - sunxi_nfc_reset_user_data_len(nfc); - sunxi_nfc_set_user_data_len(nfc, 4, 0); + sunxi_nfc_set_user_data_len(nfc, user_data_sz, nfc_step); sunxi_nfc_randomizer_enable(mtd); writel(NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD | NFC_ECC_OP, @@ -783,31 +840,31 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct mtd_info *mtd, if (ret) return ret; - *cur_off = oob_off + ecc->bytes + 4; + *cur_off = oob_off + ecc->bytes + user_data_sz; pattern_found = readl(nfc->regs + nfc->caps->reg_pat_found); pattern_found = field_get(NFC_ECC_PAT_FOUND_MSK(nfc), pattern_found); - if (pattern_found & NFC_ECC_PAT_FOUND(0)) { + if (pattern_found & NFC_ECC_PAT_FOUND(nfc_step)) { u8 pattern = 0xff; if (unlikely(!(readl(nfc->regs + NFC_REG_PAT_ID(nfc)) & 0x1))) pattern = 0x0; memset(data, pattern, ecc->size); - memset(oob, pattern, ecc->bytes + 4); + memset(oob, pattern, ecc->bytes + user_data_sz); return 1; } - ret = NFC_ECC_ERR_CNT(0, readl(nfc->regs + NFC_REG_ECC_ERR_CNT(nfc, 0))); + ret = NFC_ECC_ERR_CNT(nfc_step, readl(nfc->regs + NFC_REG_ECC_ERR_CNT(nfc, nfc_step))); memcpy_fromio(data, nfc->regs + NFC_RAM0_BASE, ecc->size); nand->cmdfunc(mtd, NAND_CMD_RNDOUT, oob_off, -1); - sunxi_nfc_randomizer_read_buf(mtd, oob, ecc->bytes + 4, true, page); + sunxi_nfc_randomizer_read_buf(mtd, oob, ecc->bytes + user_data_sz, true, page); status = readl(nfc->regs + NFC_REG_ECC_ST); - if (status & NFC_ECC_ERR(0)) { + if (status & NFC_ECC_ERR(nfc_step)) { /* * Re-read the data with the randomizer disabled to identify * bitflips in erased pages. @@ -816,26 +873,21 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct mtd_info *mtd, nand->cmdfunc(mtd, NAND_CMD_RNDOUT, data_off, -1); nand->read_buf(mtd, data, ecc->size); nand->cmdfunc(mtd, NAND_CMD_RNDOUT, oob_off, -1); - nand->read_buf(mtd, oob, ecc->bytes + 4); + nand->read_buf(mtd, oob, ecc->bytes + user_data_sz); } ret = nand_check_erased_ecc_chunk(data, ecc->size, - oob, ecc->bytes + 4, + oob, ecc->bytes + user_data_sz, NULL, 0, ecc->strength); if (ret >= 0) raw_mode = 1; } else { /* - * The engine protects 4 bytes of OOB data per chunk. + * The engine protects user_data_sz bytes of OOB data per chunk. * Retrieve the corrected OOB bytes. */ - sunxi_nfc_user_data_to_buf(readl(nfc->regs + - NFC_REG_USER_DATA(nfc, 0)), - oob); - - /* De-randomize the Bad Block Marker. */ - if (bbm && nand->options & NAND_NEED_SCRAMBLING) - sunxi_nfc_randomize_bbm(mtd, page, oob); + sunxi_nfc_hw_ecc_get_prot_oob_bytes(nand, oob, nfc_step, + bbm, page, user_data_sz); } if (ret < 0) { @@ -848,13 +900,30 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct mtd_info *mtd, return raw_mode; } +/* + * Returns the offset of the OOB for each step. + * (it includes the user data before the ECC data.) + */ +static int sunxi_get_oob_offset(struct sunxi_nand_chip *sunxi_nand, + struct nand_ecc_ctrl *ecc, int step) +{ + int ecc_off = step * ecc->bytes; + int i; + + for (i = 0; i < step; i++) + ecc_off += sunxi_nfc_user_data_sz(sunxi_nand, i); + + return ecc_off; +} + static void sunxi_nfc_hw_ecc_read_extra_oob(struct mtd_info *mtd, u8 *oob, int *cur_off, bool randomize, int page) { struct nand_chip *nand = mtd_to_nand(mtd); struct nand_ecc_ctrl *ecc = &nand->ecc; - int offset = ((ecc->bytes + 4) * ecc->steps); + struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); + int offset = sunxi_get_oob_offset(sunxi_nand, ecc, ecc->steps); int len = mtd->oobsize - offset; if (len <= 0) @@ -881,13 +950,18 @@ static inline u32 sunxi_nfc_buf_to_user_data(const u8 *buf) static int sunxi_nfc_hw_ecc_write_chunk(struct mtd_info *mtd, const u8 *data, int data_off, const u8 *oob, int oob_off, - int *cur_off, bool bbm, + int *cur_off, int step, int page) { struct nand_chip *nand = mtd_to_nand(mtd); struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); + struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); + unsigned int user_data_sz = sunxi_nfc_user_data_sz(sunxi_nand, step); struct nand_ecc_ctrl *ecc = &nand->ecc; + bool bbm = !step; int ret; + /* From the controller point of view, we are at step 0 */ + const int nfc_step = 0; if (data_off != *cur_off) nand->cmdfunc(mtd, NAND_CMD_RNDIN, data_off, -1); @@ -896,15 +970,20 @@ static int sunxi_nfc_hw_ecc_write_chunk(struct mtd_info *mtd, /* Fill OOB data in */ if ((nand->options & NAND_NEED_SCRAMBLING) && bbm) { - u8 user_data[4]; + u8 *user_data; + + user_data = kzalloc(user_data_sz, GFP_KERNEL); + if (!user_data) + return -ENOMEM; - memcpy(user_data, oob, 4); + memcpy(user_data, oob, user_data_sz); sunxi_nfc_randomize_bbm(mtd, page, user_data); writel(sunxi_nfc_buf_to_user_data(user_data), - nfc->regs + NFC_REG_USER_DATA(nfc, 0)); + nfc->regs + NFC_REG_USER_DATA(nfc, nfc_step)); + kfree(user_data); } else { writel(sunxi_nfc_buf_to_user_data(oob), - nfc->regs + NFC_REG_USER_DATA(nfc, 0)); + nfc->regs + NFC_REG_USER_DATA(nfc, nfc_step)); } if (data_off + ecc->size != oob_off) @@ -914,8 +993,7 @@ static int sunxi_nfc_hw_ecc_write_chunk(struct mtd_info *mtd, if (ret) return ret; - sunxi_nfc_reset_user_data_len(nfc); - sunxi_nfc_set_user_data_len(nfc, 4, 0); + sunxi_nfc_set_user_data_len(nfc, user_data_sz, nfc_step); sunxi_nfc_randomizer_enable(mtd); writel(NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD | @@ -927,7 +1005,7 @@ static int sunxi_nfc_hw_ecc_write_chunk(struct mtd_info *mtd, if (ret) return ret; - *cur_off = oob_off + ecc->bytes + 4; + *cur_off = oob_off + ecc->bytes + user_data_sz; return 0; } @@ -938,7 +1016,8 @@ static void sunxi_nfc_hw_ecc_write_extra_oob(struct mtd_info *mtd, { struct nand_chip *nand = mtd_to_nand(mtd); struct nand_ecc_ctrl *ecc = &nand->ecc; - int offset = ((ecc->bytes + 4) * ecc->steps); + struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); + int offset = sunxi_get_oob_offset(sunxi_nand, ecc, ecc->steps); int len = mtd->oobsize - offset; if (len <= 0) @@ -957,6 +1036,8 @@ static int sunxi_nfc_hw_ecc_read_page(struct mtd_info *mtd, struct nand_chip *chip, uint8_t *buf, int oob_required, int page) { + struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(chip); + struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller); struct nand_ecc_ctrl *ecc = &chip->ecc; unsigned int max_bitflips = 0; int ret, i, cur_off = 0; @@ -964,16 +1045,17 @@ static int sunxi_nfc_hw_ecc_read_page(struct mtd_info *mtd, sunxi_nfc_hw_ecc_enable(mtd); + sunxi_nfc_reset_user_data_len(nfc); for (i = 0; i < ecc->steps; i++) { int data_off = i * ecc->size; - int oob_off = i * (ecc->bytes + 4); + int oob_off = sunxi_get_oob_offset(sunxi_nand, ecc, i); u8 *data = buf + data_off; u8 *oob = chip->oob_poi + oob_off; ret = sunxi_nfc_hw_ecc_read_chunk(mtd, data, data_off, oob, oob_off + mtd->writesize, &cur_off, &max_bitflips, - !i, page); + i, page); if (ret < 0) return ret; else if (ret) @@ -994,23 +1076,26 @@ static int sunxi_nfc_hw_ecc_read_subpage(struct mtd_info *mtd, uint32_t data_offs, uint32_t readlen, uint8_t *bufpoi, int page) { + struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(chip); + struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller); struct nand_ecc_ctrl *ecc = &chip->ecc; int ret, i, cur_off = 0; unsigned int max_bitflips = 0; sunxi_nfc_hw_ecc_enable(mtd); + sunxi_nfc_reset_user_data_len(nfc); chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page); for (i = data_offs / ecc->size; i < DIV_ROUND_UP(data_offs + readlen, ecc->size); i++) { int data_off = i * ecc->size; - int oob_off = i * (ecc->bytes + 4); + int oob_off = sunxi_get_oob_offset(sunxi_nand, ecc, i); u8 *data = bufpoi + data_off; u8 *oob = chip->oob_poi + oob_off; ret = sunxi_nfc_hw_ecc_read_chunk(mtd, data, data_off, oob, oob_off + mtd->writesize, - &cur_off, &max_bitflips, !i, page); + &cur_off, &max_bitflips, i, page); if (ret < 0) return ret; } @@ -1025,20 +1110,23 @@ static int sunxi_nfc_hw_ecc_write_page(struct mtd_info *mtd, const uint8_t *buf, int oob_required, int page) { + struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(chip); + struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller); struct nand_ecc_ctrl *ecc = &chip->ecc; int ret, i, cur_off = 0; sunxi_nfc_hw_ecc_enable(mtd); + sunxi_nfc_reset_user_data_len(nfc); for (i = 0; i < ecc->steps; i++) { int data_off = i * ecc->size; - int oob_off = i * (ecc->bytes + 4); + int oob_off = sunxi_get_oob_offset(sunxi_nand, ecc, i); const u8 *data = buf + data_off; const u8 *oob = chip->oob_poi + oob_off; ret = sunxi_nfc_hw_ecc_write_chunk(mtd, data, data_off, oob, oob_off + mtd->writesize, - &cur_off, !i, page); + &cur_off, i, page); if (ret) return ret; } @@ -1058,21 +1146,24 @@ static int sunxi_nfc_hw_ecc_write_subpage(struct mtd_info *mtd, const u8 *buf, int oob_required, int page) { + struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(chip); + struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller); struct nand_ecc_ctrl *ecc = &chip->ecc; int ret, i, cur_off = 0; sunxi_nfc_hw_ecc_enable(mtd); + sunxi_nfc_reset_user_data_len(nfc); for (i = data_offs / ecc->size; i < DIV_ROUND_UP(data_offs + data_len, ecc->size); i++) { int data_off = i * ecc->size; - int oob_off = i * (ecc->bytes + 4); + int oob_off = sunxi_get_oob_offset(sunxi_nand, ecc, i); const u8 *data = buf + data_off; const u8 *oob = chip->oob_poi + oob_off; ret = sunxi_nfc_hw_ecc_write_chunk(mtd, data, data_off, oob, oob_off + mtd->writesize, - &cur_off, !i, page); + &cur_off, i, page); if (ret) return ret; } @@ -1087,18 +1178,23 @@ static int sunxi_nfc_hw_syndrome_ecc_read_page(struct mtd_info *mtd, uint8_t *buf, int oob_required, int page) { + struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(chip); + struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller); struct nand_ecc_ctrl *ecc = &chip->ecc; unsigned int max_bitflips = 0; int ret, i, cur_off = 0; bool raw_mode = false; + /* With hw_syndrome, user data length is fixed */ + unsigned int user_data_sz = sunxi_nfc_user_data_sz(sunxi_nand, 0); sunxi_nfc_hw_ecc_enable(mtd); + sunxi_nfc_reset_user_data_len(nfc); for (i = 0; i < ecc->steps; i++) { - int data_off = i * (ecc->size + ecc->bytes + 4); + int data_off = i * (ecc->size + ecc->bytes + user_data_sz); int oob_off = data_off + ecc->size; u8 *data = buf + (i * ecc->size); - u8 *oob = chip->oob_poi + (i * (ecc->bytes + 4)); + u8 *oob = chip->oob_poi + (i * (ecc->bytes + user_data_sz)); ret = sunxi_nfc_hw_ecc_read_chunk(mtd, data, data_off, oob, oob_off, &cur_off, @@ -1123,16 +1219,19 @@ static int sunxi_nfc_hw_syndrome_ecc_write_page(struct mtd_info *mtd, const uint8_t *buf, int oob_required, int page) { + struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(chip); struct nand_ecc_ctrl *ecc = &chip->ecc; int ret, i, cur_off = 0; + /* With hw_syndrome, user data length is fixed */ + unsigned int user_data_sz = sunxi_nfc_user_data_sz(sunxi_nand, 0); sunxi_nfc_hw_ecc_enable(mtd); for (i = 0; i < ecc->steps; i++) { - int data_off = i * (ecc->size + ecc->bytes + 4); + int data_off = i * (ecc->size + ecc->bytes + user_data_sz); int oob_off = data_off + ecc->size; const u8 *data = buf + (i * ecc->size); - const u8 *oob = chip->oob_poi + (i * (ecc->bytes + 4)); + const u8 *oob = chip->oob_poi + (i * (ecc->bytes + user_data_sz)); ret = sunxi_nfc_hw_ecc_write_chunk(mtd, data, data_off, oob, oob_off, &cur_off, @@ -1334,6 +1433,34 @@ static int sunxi_nand_chip_init_timings(struct sunxi_nfc *nfc, return sunxi_nand_chip_set_timings(nfc, chip, timings); } +static int sunxi_nfc_maximize_user_data(struct nand_chip *nand, uint32_t oobsize, + int ecc_bytes, int nsectors) +{ + struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); + struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); + const struct sunxi_nfc_caps *c = nfc->caps; + int remaining_bytes = oobsize - (ecc_bytes * nsectors); + int i, step; + + sunxi_nand->user_data_bytes = devm_kzalloc(nfc->dev, nsectors, + GFP_KERNEL); + if (!sunxi_nand->user_data_bytes) + return -ENOMEM; + + for (step = 0; (step < nsectors) && (remaining_bytes > 0); step++) { + for (i = 0; i < c->nuser_data_tab; i++) { + if (c->user_data_len_tab[i] > remaining_bytes) + break; + sunxi_nand->user_data_bytes[step] = c->user_data_len_tab[i]; + } + remaining_bytes -= sunxi_nand->user_data_bytes[step]; + if (sunxi_nand->user_data_bytes[step] == 0) + break; + } + + return 0; +} + static int sunxi_nand_hw_common_ecc_ctrl_init(struct mtd_info *mtd, struct nand_ecc_ctrl *ecc) { @@ -1342,6 +1469,7 @@ static int sunxi_nand_hw_common_ecc_ctrl_init(struct mtd_info *mtd, struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller); struct sunxi_nand_hw_ecc *data; struct nand_ecclayout *layout; + unsigned int total_user_data_sz = 0; int nsectors; int ret; int i; @@ -1390,7 +1518,15 @@ static int sunxi_nand_hw_common_ecc_ctrl_init(struct mtd_info *mtd, layout = &data->layout; nsectors = mtd->writesize / ecc->size; - if (mtd->oobsize < ((ecc->bytes + 4) * nsectors)) { + /* Use the remaining OOB space for user data */ + if (nfc->caps->reg_user_data_len) + sunxi_nfc_maximize_user_data(nand, mtd->oobsize, ecc->bytes, + nsectors); + + for (i = 0; i < nsectors; i++) + total_user_data_sz += sunxi_nfc_user_data_sz(sunxi_nand, i); + + if (mtd->oobsize < ecc->bytes * nsectors + total_user_data_sz) { ret = -EINVAL; goto err; } @@ -1404,6 +1540,8 @@ static int sunxi_nand_hw_common_ecc_ctrl_init(struct mtd_info *mtd, err: kfree(data); + devm_kfree(nfc->dev, sunxi_nand->user_data_bytes); + sunxi_nand->user_data_bytes = NULL; return ret; } @@ -1418,7 +1556,10 @@ static void sunxi_nand_hw_common_ecc_ctrl_cleanup(struct nand_ecc_ctrl *ecc) static int sunxi_nand_hw_ecc_ctrl_init(struct mtd_info *mtd, struct nand_ecc_ctrl *ecc) { + struct nand_chip *nand = mtd_to_nand(mtd); + struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); struct nand_ecclayout *layout; + unsigned int total_user_data_sz = 0; int nsectors; int i, j; int ret; @@ -1440,14 +1581,14 @@ static int sunxi_nand_hw_ecc_ctrl_init(struct mtd_info *mtd, layout->oobfree[i - 1].offset + layout->oobfree[i - 1].length + ecc->bytes; - layout->oobfree[i].length = 4; + layout->oobfree[i].length = sunxi_nfc_user_data_sz(sunxi_nand, i); } else { /* * The first 2 bytes are used for BB markers, hence we - * only have 2 bytes available in the first user data - * section. + * only have user_data_len(0) - 2 bytes available in the + * first user data section. */ - layout->oobfree[i].length = 2; + layout->oobfree[i].length = sunxi_nfc_user_data_sz(sunxi_nand, i) - 2; layout->oobfree[i].offset = 2; } @@ -1457,13 +1598,16 @@ static int sunxi_nand_hw_ecc_ctrl_init(struct mtd_info *mtd, layout->oobfree[i].length + j; } - if (mtd->oobsize > (ecc->bytes + 4) * nsectors) { + for (i = 0; i < nsectors; i++) + total_user_data_sz += sunxi_nfc_user_data_sz(sunxi_nand, i); + + if (mtd->oobsize > ecc->bytes * nsectors + total_user_data_sz) { layout->oobfree[nsectors].offset = layout->oobfree[nsectors - 1].offset + layout->oobfree[nsectors - 1].length + ecc->bytes; layout->oobfree[nsectors].length = mtd->oobsize - - ((ecc->bytes + 4) * nsectors); + (ecc->bytes * nsectors + total_user_data_sz); } return 0; @@ -1472,6 +1616,8 @@ static int sunxi_nand_hw_ecc_ctrl_init(struct mtd_info *mtd, static int sunxi_nand_hw_syndrome_ecc_ctrl_init(struct mtd_info *mtd, struct nand_ecc_ctrl *ecc) { + struct nand_chip *nand = mtd_to_nand(mtd); + struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); struct nand_ecclayout *layout; int nsectors; int i; @@ -1481,7 +1627,13 @@ static int sunxi_nand_hw_syndrome_ecc_ctrl_init(struct mtd_info *mtd, if (ret) return ret; - ecc->prepad = 4; + for (i = 0; i < nsectors; i++) + if (sunxi_nfc_user_data_sz(sunxi_nand, i) != + sunxi_nfc_user_data_sz(sunxi_nand, 0)) { + dev_err(mtd->dev, "Variable user data length not upported with NAND_ECC_HW_SYNDROME\n"); + return -EOPNOTSUPP; + } + ecc->prepad = sunxi_nfc_user_data_sz(sunxi_nand, 0); ecc->read_page = sunxi_nfc_hw_syndrome_ecc_read_page; ecc->write_page = sunxi_nfc_hw_syndrome_ecc_write_page; @@ -1596,21 +1748,20 @@ static int sunxi_nand_chip_init(struct udevice *dev, struct sunxi_nfc *nfc, if (ret) { dev_err(dev, "could not retrieve reg property: %d\n", ret); - kfree(chip); - return ret; + goto err_free; } if (tmp > NFC_MAX_CS) { dev_err(dev, "invalid reg value: %u (max CS = 7)\n", tmp); - kfree(chip); - return -EINVAL; + ret = -EINVAL; + goto err_free; } if (test_and_set_bit(tmp, &nfc->assigned_cs)) { dev_err(dev, "CS %d already assigned\n", tmp); - kfree(chip); - return -EINVAL; + ret = -EINVAL; + goto err_free; } chip->sels[i].cs = tmp; @@ -1636,15 +1787,13 @@ static int sunxi_nand_chip_init(struct udevice *dev, struct sunxi_nfc *nfc, dev_err(dev, "could not retrieve timings for ONFI mode 0: %d\n", ret); - kfree(chip); - return ret; + goto err_free; } ret = sunxi_nand_chip_set_timings(nfc, chip, timings); if (ret) { dev_err(dev, "could not configure chip timings: %d\n", ret); - kfree(chip); - return ret; + goto err_free; } nand = &chip->nand; @@ -1665,10 +1814,8 @@ static int sunxi_nand_chip_init(struct udevice *dev, struct sunxi_nfc *nfc, mtd = nand_to_mtd(nand); ret = nand_scan_ident(mtd, nsels, NULL); - if (ret) { - kfree(chip); - return ret; - } + if (ret) + goto err_free; if (nand->bbt_options & NAND_BBT_USE_FLASH) nand->bbt_options |= NAND_BBT_NO_OOB; @@ -1681,34 +1828,35 @@ static int sunxi_nand_chip_init(struct udevice *dev, struct sunxi_nfc *nfc, ret = sunxi_nand_chip_init_timings(nfc, chip); if (ret) { dev_err(dev, "could not configure chip timings: %d\n", ret); - kfree(chip); - return ret; + goto err_free; } ret = sunxi_nand_ecc_init(mtd, &nand->ecc); if (ret) { dev_err(dev, "ECC init failed: %d\n", ret); - kfree(chip); - return ret; + goto err_free; } ret = nand_scan_tail(mtd); if (ret) { dev_err(dev, "nand_scan_tail failed: %d\n", ret); - kfree(chip); - return ret; + goto err_free; } ret = nand_register(devnum, mtd); if (ret) { dev_err(dev, "failed to register mtd device: %d\n", ret); - kfree(chip); - return ret; + goto err_free; } list_add_tail(&chip->node, &nfc->chips); return 0; + +err_free: + kfree(chip); + + return ret; } static int sunxi_nand_chips_init(struct udevice *dev, struct sunxi_nfc *nfc) @@ -1736,6 +1884,7 @@ static void sunxi_nand_chips_cleanup(struct sunxi_nfc *nfc) nand_release(&chip->mtd); sunxi_nand_ecc_cleanup(&chip->nand.ecc); list_del(&chip->node); + devm_kfree(nfc->dev, chip->user_data_bytes); kfree(chip); } } diff --git a/drivers/mtd/nand/raw/sunxi_nand.h b/drivers/mtd/nand/raw/sunxi_nand.h index 6ee3ea14ee1..d7a8b3dd40c 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.h +++ b/drivers/mtd/nand/raw/sunxi_nand.h @@ -181,6 +181,9 @@ #define NFC_MAX_CS 7 +/* On A10, the user data length register is 4 bytes */ +#define USER_DATA_SZ 4 + /* * NAND Controller capabilities structure: stores NAND controller capabilities * for distinction between compatible strings. diff --git a/drivers/mtd/nand/raw/sunxi_nand_spl.c b/drivers/mtd/nand/raw/sunxi_nand_spl.c index 67f7d22ed2c..cf351de4e8d 100644 --- a/drivers/mtd/nand/raw/sunxi_nand_spl.c +++ b/drivers/mtd/nand/raw/sunxi_nand_spl.c @@ -28,6 +28,7 @@ struct nfc_config { bool randomize; bool valid; const struct sunxi_nfc_caps *caps; + u8 *user_data_bytes; }; /* minimal "boot0" style NAND support for Allwinner A20 */ @@ -223,22 +224,6 @@ static int nand_change_column(u16 column) return 0; } -/* - * On H6/H616 the user_data length has to be set in specific registers - * before writing. - */ -static void sunxi_nfc_reset_user_data_len(const struct nfc_config *nfc) -{ - int loop_step = NFC_REG_USER_DATA_LEN_CAPACITY; - - /* not all SoCs have this register */ - if (!NFC_REG_USER_DATA_LEN(nfc, 0)) - return; - - for (int i = 0; i < nfc->caps->max_ecc_steps; i += loop_step) - writel_nfc(0, NFC_REG_USER_DATA_LEN(nfc, i)); -} - static void sunxi_nfc_set_user_data_len(const struct nfc_config *nfc, int len, int step) { @@ -269,13 +254,19 @@ static void sunxi_nfc_set_user_data_len(const struct nfc_config *nfc, writel_nfc(val, NFC_REG_USER_DATA_LEN(nfc, step)); } +/* + * Values in this table are obtained by doing: + * DIV_ROUND_UP(info->ecc_strength * 14, 8) + * So it's the number of bytes needed for ECC one step + * (not counting the user data length) + */ #if defined(CONFIG_MACH_SUN50I_H616) || defined(CONFIG_MACH_SUN50I_H6) static const int ecc_bytes[] = { - 32, 46, 54, 60, 74, 82, 88, 96, 102, 110, 116, 124, 130, 138, 144 + 28, 42, 50, 56, 70, 78, 84, 92, 98, 106, 112, 120, 126, 134, 140 }; #else static const int ecc_bytes[] = { - 32, 46, 54, 60, 74, 88, 102, 110, 116 + 28, 42, 50, 56, 70, 84, 98, 106, 112 }; #endif @@ -288,6 +279,14 @@ static void nand_readlcpy(u32 *dest, u32 * __iomem src, size_t len) *dest++ = readl(src++); } +static u8 nand_user_data_sz(const struct nfc_config *conf, int step) +{ + if (!conf->user_data_bytes) + return USER_DATA_SZ; + + return conf->user_data_bytes[step]; +} + static int nand_read_page(const struct nfc_config *conf, u32 offs, void *dest, int len) { @@ -295,8 +294,11 @@ static int nand_read_page(const struct nfc_config *conf, u32 offs, u16 rand_seed = 0; int oob_chunk_sz = ecc_bytes[conf->ecc_strength]; int page = offs / conf->page_size; + int oob_off = conf->page_size; u32 ecc_st, pattern_found; int i; + /* From the controller point of view, we are at step 0 */ + const int nfc_step = 0; if (offs % conf->page_size || len % conf->ecc_size || len > conf->page_size || len < 0) @@ -309,9 +311,9 @@ static int nand_read_page(const struct nfc_config *conf, u32 offs, /* Retrieve data from SRAM (PIO) */ for (i = 0; i < nsectors; i++) { int data_off = i * conf->ecc_size; - int oob_off = conf->page_size + (i * oob_chunk_sz); u8 *data = dest + data_off; u32 ecc512_bit = 0; + unsigned int user_data_sz = nand_user_data_sz(conf, i); if (conf->caps->has_ecc_block_512 && conf->ecc_size == 512) ecc512_bit = NFC_ECC_BLOCK_512; @@ -337,8 +339,7 @@ static int nand_read_page(const struct nfc_config *conf, u32 offs, */ nand_change_column(oob_off); - sunxi_nfc_reset_user_data_len(conf); - sunxi_nfc_set_user_data_len(conf, 4, 0); + sunxi_nfc_set_user_data_len(conf, user_data_sz, nfc_step); nand_exec_cmd(NFC_DATA_TRANS | NFC_ECC_OP); /* Get the ECC status */ @@ -356,7 +357,7 @@ static int nand_read_page(const struct nfc_config *conf, u32 offs, pattern_found = readl_nfc(conf->caps->reg_pat_found); pattern_found = field_get(NFC_ECC_PAT_FOUND_MSK(conf), pattern_found); - if (pattern_found & NFC_ECC_PAT_FOUND(0)) + if (pattern_found & NFC_ECC_PAT_FOUND(nfc_step)) return 1; } @@ -364,13 +365,61 @@ static int nand_read_page(const struct nfc_config *conf, u32 offs, nand_readlcpy((u32 *)data, (void *)(uintptr_t)SUNXI_NFC_BASE + NFC_RAM0_BASE, conf->ecc_size); - /* Stop the ECC engine */ writel_nfc(readl_nfc(NFC_REG_ECC_CTL) & ~NFC_ECC_EN, NFC_REG_ECC_CTL); if (data_off + conf->ecc_size >= len) break; + + oob_off += oob_chunk_sz + user_data_sz; + } + + return 0; +} + +static int nand_min_user_data_sz(struct nfc_config *conf, int nsectors) +{ + const struct sunxi_nfc_caps *c = conf->caps; + int min_user_data_sz = 0; + int i; + + if (!c->reg_user_data_len) { + for (i = 0; i < nsectors; i++) + min_user_data_sz += nand_user_data_sz(conf, i); + } else { + for (i = 0; i < c->nuser_data_tab; i++) + /* We want at least enough size for the BBM */ + if (c->user_data_len_tab[i] >= 2) + break; + min_user_data_sz = c->user_data_len_tab[i]; + } + + return min_user_data_sz; +} + +static int nand_maximize_user_data(struct nfc_config *conf, uint32_t oobsize, + int ecc_len, int nsectors) +{ + const struct sunxi_nfc_caps *c = conf->caps; + int remaining_bytes = oobsize - (ecc_len * nsectors); + int i, step; + + kfree(conf->user_data_bytes); + + conf->user_data_bytes = kzalloc(nsectors, GFP_KERNEL); + if (!conf->user_data_bytes) + return -ENOMEM; + + for (step = 0; (step < nsectors) && (remaining_bytes > 0); step++) { + for (i = 0; i < c->nuser_data_tab; i++) { + if (c->user_data_len_tab[i] > remaining_bytes) + break; + conf->user_data_bytes[step] = c->user_data_len_tab[i]; + } + remaining_bytes -= conf->user_data_bytes[step]; + if (conf->user_data_bytes[step] == 0) + break; } return 0; @@ -380,7 +429,8 @@ static int nand_max_ecc_strength(struct nfc_config *conf) { int max_oobsize, max_ecc_bytes; int nsectors = conf->page_size / conf->ecc_size; - int i; + unsigned int total_user_data_sz = 0; + int ecc_idx, i; /* * ECC strength is limited by the size of the OOB area which is @@ -405,15 +455,38 @@ static int nand_max_ecc_strength(struct nfc_config *conf) max_ecc_bytes = max_oobsize / nsectors; - for (i = 0; i < ARRAY_SIZE(ecc_bytes); i++) { - if (ecc_bytes[i] > max_ecc_bytes) + /* + * nand_min_user_data_sz() will return the total_user_data_sz in case + * of a fixed user data length, or the minimal usable user data size + * in case of variable data length (with at least enough space for the + * BBM. + */ + total_user_data_sz = nand_min_user_data_sz(conf, nsectors); + + for (ecc_idx = 0; ecc_idx < ARRAY_SIZE(ecc_bytes); ecc_idx++) { + if (ecc_bytes[ecc_idx] + total_user_data_sz > max_ecc_bytes) break; } - if (!i) + if (!ecc_idx) return -EINVAL; - return i - 1; + ecc_idx--; + + /* + * The rationale for variable data length is to prioritize maximum ECC + * strength, and then use the remaining space for user data. + */ + if (conf->caps->reg_user_data_len) { + nand_maximize_user_data(conf, max_oobsize, + ecc_bytes[ecc_idx], nsectors); + + total_user_data_sz = 0; + for (i = 0; i < nsectors; i++) + total_user_data_sz += nand_user_data_sz(conf, i); + } + + return ecc_idx; } static int nand_detect_ecc_config(struct nfc_config *conf, u32 offs, diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c index fd357ab0d4e..a8632aeaf8f 100644 --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c @@ -603,6 +603,7 @@ static const struct sunxi_pinctrl_function sun20i_d1_pinctrl_functions[] = { { "gpio_in", 0 }, { "gpio_out", 1 }, { "i2c0", 4 }, /* PB10-PB11 */ + { "i2c3", 3 }, /* PG10-PG11 */ { "mmc0", 2 }, /* PF0-PF5 */ { "mmc1", 2 }, /* PG0-PG5 */ { "mmc2", 3 }, /* PC2-PC7 */ diff --git a/drivers/spi/spi-sunxi.c b/drivers/spi/spi-sunxi.c index 0bdc112d249..08b603f04a2 100644 --- a/drivers/spi/spi-sunxi.c +++ b/drivers/spi/spi-sunxi.c @@ -344,7 +344,7 @@ static int sun4i_spi_xfer(struct udevice *dev, unsigned int bitlen, struct sun4i_spi_priv *priv = dev_get_priv(bus); struct dm_spi_slave_plat *slave_plat = dev_get_parent_plat(dev); - u32 len = bitlen / 8; + u32 rst, val, len = bitlen / 8; u8 nbytes; int ret; @@ -360,8 +360,11 @@ static int sun4i_spi_xfer(struct udevice *dev, unsigned int bitlen, sun4i_spi_set_cs(bus, slave_plat->cs[0], true); /* Reset FIFOs */ - setbits_le32(SPI_REG(priv, SPI_FCR), SPI_BIT(priv, SPI_FCR_RF_RST) | - SPI_BIT(priv, SPI_FCR_TF_RST)); + rst = SPI_BIT(priv, SPI_FCR_RF_RST) | SPI_BIT(priv, SPI_FCR_TF_RST); + setbits_le32(SPI_REG(priv, SPI_FCR), rst); + ret = readl_poll_timeout(SPI_REG(priv, SPI_FCR), val, !(rst & val), 20); + if (ret) + return -EBUSY; while (len) { /* Setup the transfer now... */ diff --git a/include/configs/sunxi-common.h b/include/configs/sunxi-common.h index b29a25d5617..49d5617f028 100644 --- a/include/configs/sunxi-common.h +++ b/include/configs/sunxi-common.h @@ -280,7 +280,7 @@ CONSOLE_STDIN_SETTINGS \ CONSOLE_STDOUT_SETTINGS -#ifdef CONFIG_ARM64 +#if defined(CONFIG_ARM64) || defined(CONFIG_RISCV) #define FDTFILE "allwinner/" CONFIG_DEFAULT_DEVICE_TREE ".dtb" #else #define FDTFILE CONFIG_DEFAULT_DEVICE_TREE ".dtb" |
