[PATCH v1 1/2] sunxi: SPL SPI: Add SPI boot support for the Allwinner R528/T113 SoCs
Andre Przywara
andre.przywara at arm.com
Thu Apr 11 14:43:36 CEST 2024
On Thu, 11 Apr 2024 14:31:02 +1000
John Watts <contact at jookia.org> wrote:
Hi,
> 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>
Thanks for that. I considered this patch already for the last cycle, but
dropped it last minute, since I had some doubts and couldn't test it. I
will have a look again.
Cheers,
Andre
> 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