[PATCH v1 1/2] sunxi: SPL SPI: Add SPI boot support for the Allwinner R528/T113 SoCs
John Watts
contact at jookia.org
Thu Apr 11 06:31:02 CEST 2024
Hi there,
I've been using my own independent implementation of this patch but
today I gave this one a test in my tree and found out it works.
The code looks fine in comparison, so here's a Tested-by and a
Reviewed-by.
John.
Tested-by: John Watts <contact at jookia.org>
Reviewed-by: John Watts <contact at jookia.org>
On Sat, Nov 11, 2023 at 04:33:07PM +0300, Maksim Kiselev wrote:
> R528/T113 SoCs uses the same SPI IP as the H6, also have the same clocks
> and reset bits layout, but the CCU base is different. Another difference
> is that the new SoCs do not have a clock divider inside. Instead of this
> we should configure sample mode depending on input clock rate.
>
> The pin assignment is also different: the H6 uses PC0, the R528/T113 PC4
> instead. This makes for a change in spi0_pinmux_setup() routine.
>
> This patch extends the H6/H616 #ifdef guards to also cover the R528/T113,
> using the shared CONFIG_SUNXI_GEN_NCAT2 and CONFIG_MACH_SUN8I_R528
> symbols. Also use CONFIG_SUNXI_GEN_NCAT2 symbol for the Kconfig
> dependency.
>
> Signed-off-by: Maksim Kiselev <bigunclemax at gmail.com>
> Tested-by: Sam Edwards <CFSworks at gmail.com>
> ---
> arch/arm/mach-sunxi/Kconfig | 2 +-
> arch/arm/mach-sunxi/spl_spi_sunxi.c | 78 +++++++++++++++++++++--------
> 2 files changed, 58 insertions(+), 22 deletions(-)
>
> diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
> index a10e4c06b6..732f60821a 100644
> --- a/arch/arm/mach-sunxi/Kconfig
> +++ b/arch/arm/mach-sunxi/Kconfig
> @@ -1044,7 +1044,7 @@ config SPL_STACK_R_ADDR
>
> config SPL_SPI_SUNXI
> bool "Support for SPI Flash on Allwinner SoCs in SPL"
> - depends on MACH_SUN4I || MACH_SUN5I || MACH_SUN7I || MACH_SUNXI_H3_H5 || MACH_SUN50I || MACH_SUN8I_R40 || SUN50I_GEN_H6 || MACH_SUNIV
> + depends on MACH_SUN4I || MACH_SUN5I || MACH_SUN7I || MACH_SUNXI_H3_H5 || MACH_SUN50I || MACH_SUN8I_R40 || SUN50I_GEN_H6 || MACH_SUNIV || SUNXI_GEN_NCAT2
> help
> Enable support for SPI Flash. This option allows SPL to read from
> sunxi SPI Flash. It uses the same method as the boot ROM, so does
> diff --git a/arch/arm/mach-sunxi/spl_spi_sunxi.c b/arch/arm/mach-sunxi/spl_spi_sunxi.c
> index c2410dd7bb..ba3b1579f0 100644
> --- a/arch/arm/mach-sunxi/spl_spi_sunxi.c
> +++ b/arch/arm/mach-sunxi/spl_spi_sunxi.c
> @@ -73,18 +73,27 @@
> #define SUN6I_CTL_ENABLE BIT(0)
> #define SUN6I_CTL_MASTER BIT(1)
> #define SUN6I_CTL_SRST BIT(31)
> +#define SUN6I_TCR_SDM BIT(13)
> #define SUN6I_TCR_XCH BIT(31)
>
> /*****************************************************************************/
>
> -#define CCM_AHB_GATING0 (0x01C20000 + 0x60)
> -#define CCM_H6_SPI_BGR_REG (0x03001000 + 0x96c)
> -#ifdef CONFIG_SUN50I_GEN_H6
> -#define CCM_SPI0_CLK (0x03001000 + 0x940)
> +#if IS_ENABLED(CONFIG_SUN50I_GEN_H6)
> +#define CCM_BASE 0x03001000
> +#elif IS_ENABLED(CONFIG_SUNXI_GEN_NCAT2)
> +#define CCM_BASE 0x02001000
> #else
> -#define CCM_SPI0_CLK (0x01C20000 + 0xA0)
> +#define CCM_BASE 0x01C20000
> #endif
> -#define SUN6I_BUS_SOFT_RST_REG0 (0x01C20000 + 0x2C0)
> +
> +#define CCM_AHB_GATING0 (CCM_BASE + 0x60)
> +#define CCM_H6_SPI_BGR_REG (CCM_BASE + 0x96c)
> +#if IS_ENABLED(CONFIG_SUN50I_GEN_H6) || IS_ENABLED(CONFIG_SUNXI_GEN_NCAT2)
> +#define CCM_SPI0_CLK (CCM_BASE + 0x940)
> +#else
> +#define CCM_SPI0_CLK (CCM_BASE + 0xA0)
> +#endif
> +#define SUN6I_BUS_SOFT_RST_REG0 (CCM_BASE + 0x2C0)
>
> #define AHB_RESET_SPI0_SHIFT 20
> #define AHB_GATE_OFFSET_SPI0 20
> @@ -102,17 +111,22 @@
> */
> static void spi0_pinmux_setup(unsigned int pin_function)
> {
> - /* All chips use PC0 and PC2. */
> - sunxi_gpio_set_cfgpin(SUNXI_GPC(0), pin_function);
> + /* All chips use PC2. And all chips use PC0, except R528/T113 */
> + if (!IS_ENABLED(CONFIG_MACH_SUN8I_R528))
> + sunxi_gpio_set_cfgpin(SUNXI_GPC(0), pin_function);
> +
> sunxi_gpio_set_cfgpin(SUNXI_GPC(2), pin_function);
>
> - /* All chips except H6 and H616 use PC1. */
> - if (!IS_ENABLED(CONFIG_SUN50I_GEN_H6))
> + /* All chips except H6/H616/R528/T113 use PC1. */
> + if (!IS_ENABLED(CONFIG_SUN50I_GEN_H6) &&
> + !IS_ENABLED(CONFIG_MACH_SUN8I_R528))
> sunxi_gpio_set_cfgpin(SUNXI_GPC(1), pin_function);
>
> - if (IS_ENABLED(CONFIG_MACH_SUN50I_H6))
> + if (IS_ENABLED(CONFIG_MACH_SUN50I_H6) ||
> + IS_ENABLED(CONFIG_MACH_SUN8I_R528))
> sunxi_gpio_set_cfgpin(SUNXI_GPC(5), pin_function);
> - if (IS_ENABLED(CONFIG_MACH_SUN50I_H616))
> + if (IS_ENABLED(CONFIG_MACH_SUN50I_H616) ||
> + IS_ENABLED(CONFIG_MACH_SUN8I_R528))
> sunxi_gpio_set_cfgpin(SUNXI_GPC(4), pin_function);
>
> /* Older generations use PC23 for CS, newer ones use PC3. */
> @@ -126,7 +140,8 @@ static void spi0_pinmux_setup(unsigned int pin_function)
> static bool is_sun6i_gen_spi(void)
> {
> return IS_ENABLED(CONFIG_SUNXI_GEN_SUN6I) ||
> - IS_ENABLED(CONFIG_SUN50I_GEN_H6);
> + IS_ENABLED(CONFIG_SUN50I_GEN_H6) ||
> + IS_ENABLED(CONFIG_SUNXI_GEN_NCAT2);
> }
>
> static uintptr_t spi0_base_address(void)
> @@ -137,6 +152,9 @@ static uintptr_t spi0_base_address(void)
> if (IS_ENABLED(CONFIG_SUN50I_GEN_H6))
> return 0x05010000;
>
> + if (IS_ENABLED(CONFIG_SUNXI_GEN_NCAT2))
> + return 0x04025000;
> +
> if (!is_sun6i_gen_spi() ||
> IS_ENABLED(CONFIG_MACH_SUNIV))
> return 0x01C05000;
> @@ -152,23 +170,30 @@ static void spi0_enable_clock(void)
> uintptr_t base = spi0_base_address();
>
> /* Deassert SPI0 reset on SUN6I */
> - if (IS_ENABLED(CONFIG_SUN50I_GEN_H6))
> + if (IS_ENABLED(CONFIG_SUN50I_GEN_H6) ||
> + IS_ENABLED(CONFIG_SUNXI_GEN_NCAT2))
> setbits_le32(CCM_H6_SPI_BGR_REG, (1U << 16) | 0x1);
> else if (is_sun6i_gen_spi())
> setbits_le32(SUN6I_BUS_SOFT_RST_REG0,
> (1 << AHB_RESET_SPI0_SHIFT));
>
> /* Open the SPI0 gate */
> - if (!IS_ENABLED(CONFIG_SUN50I_GEN_H6))
> + if (!IS_ENABLED(CONFIG_SUN50I_GEN_H6) &&
> + !IS_ENABLED(CONFIG_SUNXI_GEN_NCAT2))
> setbits_le32(CCM_AHB_GATING0, (1 << AHB_GATE_OFFSET_SPI0));
>
> if (IS_ENABLED(CONFIG_MACH_SUNIV)) {
> /* Divide by 32, clock source is AHB clock 200MHz */
> writel(SPI0_CLK_DIV_BY_32, base + SUN6I_SPI0_CCTL);
> } else {
> - /* Divide by 4 */
> - writel(SPI0_CLK_DIV_BY_4, base + (is_sun6i_gen_spi() ?
> - SUN6I_SPI0_CCTL : SUN4I_SPI0_CCTL));
> + /* New SoCs do not have a clock divider inside */
> + if (!IS_ENABLED(CONFIG_SUNXI_GEN_NCAT2)) {
> + /* Divide by 4 */
> + writel(SPI0_CLK_DIV_BY_4,
> + base + (is_sun6i_gen_spi() ? SUN6I_SPI0_CCTL :
> + SUN4I_SPI0_CCTL));
> + }
> +
> /* 24MHz from OSC24M */
> writel((1 << 31), CCM_SPI0_CLK);
> }
> @@ -180,6 +205,14 @@ static void spi0_enable_clock(void)
> /* Wait for completion */
> while (readl(base + SUN6I_SPI0_GCR) & SUN6I_CTL_SRST)
> ;
> +
> + /*
> + * For new SoCs we should configure sample mode depending on
> + * input clock. As 24MHz from OSC24M is used, we could use
> + * normal sample mode by setting SDM bit in the TCR register
> + */
> + if (IS_ENABLED(CONFIG_SUNXI_GEN_NCAT2))
> + setbits_le32(base + SUN6I_SPI0_TCR, SUN6I_TCR_SDM);
> } else {
> /* Enable SPI in the master mode and reset FIFO */
> setbits_le32(base + SUN4I_SPI0_CTL, SUN4I_CTL_MASTER |
> @@ -206,11 +239,13 @@ static void spi0_disable_clock(void)
> writel(0, CCM_SPI0_CLK);
>
> /* Close the SPI0 gate */
> - if (!IS_ENABLED(CONFIG_SUN50I_GEN_H6))
> + if (!IS_ENABLED(CONFIG_SUN50I_GEN_H6) &&
> + !IS_ENABLED(CONFIG_SUNXI_GEN_NCAT2))
> clrbits_le32(CCM_AHB_GATING0, (1 << AHB_GATE_OFFSET_SPI0));
>
> /* Assert SPI0 reset on SUN6I */
> - if (IS_ENABLED(CONFIG_SUN50I_GEN_H6))
> + if (IS_ENABLED(CONFIG_SUN50I_GEN_H6) ||
> + IS_ENABLED(CONFIG_SUNXI_GEN_NCAT2))
> clrbits_le32(CCM_H6_SPI_BGR_REG, (1U << 16) | 0x1);
> else if (is_sun6i_gen_spi())
> clrbits_le32(SUN6I_BUS_SOFT_RST_REG0,
> @@ -224,7 +259,8 @@ static void spi0_init(void)
> if (IS_ENABLED(CONFIG_MACH_SUN50I) ||
> IS_ENABLED(CONFIG_SUN50I_GEN_H6))
> pin_function = SUN50I_GPC_SPI0;
> - else if (IS_ENABLED(CONFIG_MACH_SUNIV))
> + else if (IS_ENABLED(CONFIG_MACH_SUNIV) ||
> + IS_ENABLED(CONFIG_MACH_SUN8I_R528))
> pin_function = SUNIV_GPC_SPI0;
>
> spi0_pinmux_setup(pin_function);
> --
> 2.40.1
>
More information about the U-Boot
mailing list