[U-Boot] [PATCH] sunxi: Add H6 SPI SPL support

Jagan Teki jagan at amarulasolutions.com
Fri Apr 12 13:28:43 UTC 2019


On Tue, Apr 9, 2019 at 4:20 AM Marek Kraus <gamelaster at outlook.com> wrote:
>
> Add H6 SPI addresses and masks
> (since H6 memory map is totally different).
> Tested on Pine H64 rev B with Winbond W25Q128FW,
>
> Signed-off-by: Marek Kraus <gamelaster at outlook.com>
> ---
>
>  arch/arm/mach-sunxi/Kconfig         |   2 +-
>  arch/arm/mach-sunxi/spl_spi_sunxi.c | 123 ++++++++++++++++++++++++++++--------
>  configs/pine_h64_defconfig          |   1 +
>  3 files changed, 98 insertions(+), 28 deletions(-)
>
> diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
> index 74e234cded..81b5948454 100644
> --- a/arch/arm/mach-sunxi/Kconfig
> +++ b/arch/arm/mach-sunxi/Kconfig
> @@ -972,7 +972,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
> +       depends on MACH_SUN4I || MACH_SUN5I || MACH_SUN7I || MACH_SUNXI_H3_H5 || MACH_SUN50I || MACH_SUN50I_H6
>         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 043d9f6ead..cdf6d53ec5 100644
> --- a/arch/arm/mach-sunxi/spl_spi_sunxi.c
> +++ b/arch/arm/mach-sunxi/spl_spi_sunxi.c
> @@ -28,7 +28,7 @@
>   * A10/A13/A20 (sun4i variant) and everything else (sun6i variant).
>   * Both of them are supported.
>   *
> - * The pin mixing part is SoC specific and only A10/A13/A20/H3/A64 are
> + * The pin mixing part is SoC specific and only A10/A13/A20/H3/A64/H6 are
>   * supported at the moment.
>   */
>
> @@ -70,6 +70,25 @@
>  #define SUN6I_TCR_XCH               BIT(31)
>
>  /*****************************************************************************/
> +/* SUN50I_H6 variant of the SPI controller                                   */
> +/*****************************************************************************/
> +
> +#define SUN50I_H6_SPI0_CCTL         (0x05010000 + 0x24)
> +#define SUN50I_H6_SPI0_GCR          (0x05010000 + 0x04)
> +#define SUN50I_H6_SPI0_TCR          (0x05010000 + 0x08)
> +#define SUN50I_H6_SPI0_FIFO_STA     (0x05010000 + 0x1C)
> +#define SUN50I_H6_SPI0_MBC          (0x05010000 + 0x30)
> +#define SUN50I_H6_SPI0_MTC          (0x05010000 + 0x34)
> +#define SUN50I_H6_SPI0_BCC          (0x05010000 + 0x38)
> +#define SUN50I_H6_SPI0_TXD          (0x05010000 + 0x200)
> +#define SUN50I_H6_SPI0_RXD          (0x05010000 + 0x300)

Seems like reg offset seems to be same as existing sun6i, just mange
the existing macros with base address.

> +
> +#define SUN50I_H6_SPI_GATING_REG    (0x03001000 + 0x96C)
> +#define SUN50I_H6_SPI0_RST          BIT(16)
> +#define SUN50I_H6_SPI0_GATING_CLK   BIT(0)
> +#define SUN50I_H6_CCU_SPI0_CLK      (0x03001000 + 0x940)
> +
> +/*****************************************************************************/
>
>  #define CCM_AHB_GATING0             (0x01C20000 + 0x60)
>  #define CCM_SPI0_CLK                (0x01C20000 + 0xA0)
> @@ -85,19 +104,29 @@
>
>  /*
>   * Allwinner A10/A20 SoCs were using pins PC0,PC1,PC2,PC23 for booting
> - * from SPI Flash, everything else is using pins PC0,PC1,PC2,PC3.
> + * from SPI Flash, H6 using PC0,PC2,PC3,PC5 , everything else is using
> + * pins PC0,PC1,PC2,PC3.
>   */
>  static void spi0_pinmux_setup(unsigned int pin_function)
>  {
>         unsigned int pin;
>
> -       for (pin = SUNXI_GPC(0); pin <= SUNXI_GPC(2); pin++)
> -               sunxi_gpio_set_cfgpin(pin, pin_function);
>
> -       if (IS_ENABLED(CONFIG_MACH_SUN4I) || IS_ENABLED(CONFIG_MACH_SUN7I))
> -               sunxi_gpio_set_cfgpin(SUNXI_GPC(23), pin_function);
> -       else
> +       if (IS_ENABLED(CONFIG_MACH_SUN50I_H6)) {
> +               sunxi_gpio_set_cfgpin(SUNXI_GPC(0), pin_function);
> +               sunxi_gpio_set_cfgpin(SUNXI_GPC(2), pin_function);
>                 sunxi_gpio_set_cfgpin(SUNXI_GPC(3), pin_function);
> +               sunxi_gpio_set_cfgpin(SUNXI_GPC(5), pin_function);
> +       } else {
> +               for (pin = SUNXI_GPC(0); pin <= SUNXI_GPC(2); pin++)
> +                       sunxi_gpio_set_cfgpin(pin, pin_function);
> +
> +               if (IS_ENABLED(CONFIG_MACH_SUN4I) ||
> +                   IS_ENABLED(CONFIG_MACH_SUN7I))
> +                       sunxi_gpio_set_cfgpin(SUNXI_GPC(23), pin_function);
> +               else
> +                       sunxi_gpio_set_cfgpin(SUNXI_GPC(3), pin_function);
> +       }
>  }
>
>  /*
> @@ -106,26 +135,43 @@ static void spi0_pinmux_setup(unsigned int pin_function)
>  static void spi0_enable_clock(void)
>  {
>         /* Deassert SPI0 reset on SUN6I */
> -       if (IS_ENABLED(CONFIG_SUNXI_GEN_SUN6I))
> +       if (IS_ENABLED(CONFIG_MACH_SUN50I_H6))
> +               setbits_le32(SUN50I_H6_SPI_GATING_REG,
> +                            SUN50I_H6_SPI0_RST);
> +       else if (IS_ENABLED(CONFIG_SUNXI_GEN_SUN6I))
>                 setbits_le32(SUN6I_BUS_SOFT_RST_REG0,
>                              (1 << AHB_RESET_SPI0_SHIFT));
>
>         /* Open the SPI0 gate */
> -       setbits_le32(CCM_AHB_GATING0, (1 << AHB_GATE_OFFSET_SPI0));
> +       if (IS_ENABLED(CONFIG_MACH_SUN50I_H6))
> +               setbits_le32(SUN50I_H6_SPI_GATING_REG,
> +                            SUN50I_H6_SPI0_GATING_CLK);
> +       else
> +               setbits_le32(CCM_AHB_GATING0, (1 << AHB_GATE_OFFSET_SPI0));
>
>         /* Divide by 4 */
> -       writel(SPI0_CLK_DIV_BY_4, IS_ENABLED(CONFIG_SUNXI_GEN_SUN6I) ?
> -                                 SUN6I_SPI0_CCTL : SUN4I_SPI0_CCTL);
> +       if (IS_ENABLED(CONFIG_MACH_SUN50I_H6))
> +               writel(SPI0_CLK_DIV_BY_4, SUN50I_H6_SPI0_CCTL);
> +       else
> +               writel(SPI0_CLK_DIV_BY_4, IS_ENABLED(CONFIG_SUNXI_GEN_SUN6I) ?
> +                                         SUN6I_SPI0_CCTL : SUN4I_SPI0_CCTL);
> +
>         /* 24MHz from OSC24M */
> -       writel((1 << 31), CCM_SPI0_CLK);
> +       writel((1 << 31), IS_ENABLED(CONFIG_MACH_SUN50I_H6) ?
> +                                SUN50I_H6_CCU_SPI0_CLK : CCM_SPI0_CLK);
>
> -       if (IS_ENABLED(CONFIG_SUNXI_GEN_SUN6I)) {
> +       if (IS_ENABLED(CONFIG_SUNXI_GEN_SUN6I) ||
> +           IS_ENABLED(CONFIG_MACH_SUN50I_H6)) {
>                 /* Enable SPI in the master mode and do a soft reset */
> -               setbits_le32(SUN6I_SPI0_GCR, SUN6I_CTL_MASTER |
> -                                            SUN6I_CTL_ENABLE |
> -                                            SUN6I_CTL_SRST);
> +               setbits_le32(IS_ENABLED(CONFIG_MACH_SUN50I_H6) ?
> +                            SUN50I_H6_SPI0_GCR : SUN6I_SPI0_GCR,
> +                            SUN6I_CTL_MASTER |
> +                            SUN6I_CTL_ENABLE |
> +                            SUN6I_CTL_SRST);
> +
>                 /* Wait for completion */
> -               while (readl(SUN6I_SPI0_GCR) & SUN6I_CTL_SRST)
> +               while (readl(IS_ENABLED(CONFIG_MACH_SUN50I_H6) ?
> +                       SUN50I_H6_SPI0_GCR : SUN6I_SPI0_GCR) & SUN6I_CTL_SRST)
>                         ;
>         } else {
>                 /* Enable SPI in the master mode and reset FIFO */
> @@ -139,22 +185,33 @@ static void spi0_enable_clock(void)
>  static void spi0_disable_clock(void)
>  {
>         /* Disable the SPI0 controller */
> -       if (IS_ENABLED(CONFIG_SUNXI_GEN_SUN6I))
> -               clrbits_le32(SUN6I_SPI0_GCR, SUN6I_CTL_MASTER |
> -                                            SUN6I_CTL_ENABLE);
> +       if (IS_ENABLED(CONFIG_SUNXI_GEN_SUN6I) ||
> +           IS_ENABLED(CONFIG_MACH_SUN50I_H6))
> +               clrbits_le32(IS_ENABLED(CONFIG_MACH_SUN50I_H6) ?
> +                            SUN50I_H6_SPI0_GCR : SUN6I_SPI0_GCR,
> +                            SUN6I_CTL_MASTER |
> +                            SUN6I_CTL_ENABLE);
>         else
>                 clrbits_le32(SUN4I_SPI0_CTL, SUN4I_CTL_MASTER |
>                                              SUN4I_CTL_ENABLE);
>
>         /* Disable the SPI0 clock */
> -       writel(0, CCM_SPI0_CLK);
> +       writel(0, IS_ENABLED(CONFIG_MACH_SUN50I_H6) ?
> +            SUN50I_H6_CCU_SPI0_CLK : CCM_SPI0_CLK);
>
>         /* Close the SPI0 gate */
> -       clrbits_le32(CCM_AHB_GATING0, (1 << AHB_GATE_OFFSET_SPI0));
> +       if (IS_ENABLED(CONFIG_MACH_SUN50I_H6))
> +               clrbits_le32(SUN50I_H6_SPI_GATING_REG,
> +                            SUN50I_H6_SPI0_GATING_CLK);
> +       else
> +               clrbits_le32(CCM_AHB_GATING0, (1 << AHB_GATE_OFFSET_SPI0));
>
>         /* Assert SPI0 reset on SUN6I */
> -       if (IS_ENABLED(CONFIG_SUNXI_GEN_SUN6I))
> -               clrbits_le32(SUN6I_BUS_SOFT_RST_REG0,
> +       if (IS_ENABLED(CONFIG_MACH_SUN50I_H6))
> +               setbits_le32(SUN50I_H6_SPI_GATING_REG,
> +                            SUN50I_H6_SPI0_RST);
> +       else if (IS_ENABLED(CONFIG_SUNXI_GEN_SUN6I))
> +               setbits_le32(SUN6I_BUS_SOFT_RST_REG0,
>                              (1 << AHB_RESET_SPI0_SHIFT));
>  }
>
> @@ -162,7 +219,7 @@ static void spi0_init(void)
>  {
>         unsigned int pin_function = SUNXI_GPC_SPI0;
>
> -       if (IS_ENABLED(CONFIG_MACH_SUN50I))
> +       if (IS_ENABLED(CONFIG_MACH_SUN50I) || IS_ENABLED(CONFIG_MACH_SUN50I_H6))
>                 pin_function = SUN50I_GPC_SPI0;
>
>         spi0_pinmux_setup(pin_function);
> @@ -173,7 +230,9 @@ static void spi0_deinit(void)
>  {
>         /* New SoCs can disable pins, older could only set them as input */
>         unsigned int pin_function = SUNXI_GPIO_INPUT;
> -       if (IS_ENABLED(CONFIG_SUNXI_GEN_SUN6I))
> +
> +       if (IS_ENABLED(CONFIG_SUNXI_GEN_SUN6I) ||
> +           IS_ENABLED(CONFIG_MACH_SUN50I_H6))
>                 pin_function = SUNXI_GPIO_DISABLE;
>
>         spi0_disable_clock();
> @@ -233,7 +292,17 @@ static void spi0_read_data(void *buf, u32 addr, u32 len)
>                 if (chunk_len > SPI_READ_MAX_SIZE)
>                         chunk_len = SPI_READ_MAX_SIZE;
>
> -               if (IS_ENABLED(CONFIG_SUNXI_GEN_SUN6I)) {
> +               if (IS_ENABLED(CONFIG_MACH_SUN50I_H6)) {
> +                       sunxi_spi0_read_data(buf8, addr, chunk_len,
> +                                            SUN50I_H6_SPI0_TCR,
> +                                            SUN6I_TCR_XCH,
> +                                            SUN50I_H6_SPI0_FIFO_STA,
> +                                            SUN50I_H6_SPI0_TXD,
> +                                            SUN50I_H6_SPI0_RXD,
> +                                            SUN50I_H6_SPI0_MBC,
> +                                            SUN50I_H6_SPI0_MTC,
> +                                            SUN50I_H6_SPI0_BCC);
> +               } else if (IS_ENABLED(CONFIG_SUNXI_GEN_SUN6I)) {
>                         sunxi_spi0_read_data(buf8, addr, chunk_len,
>                                              SUN6I_SPI0_TCR,
>                                              SUN6I_TCR_XCH,
> diff --git a/configs/pine_h64_defconfig b/configs/pine_h64_defconfig
> index e34f4fd1e4..baddc33abb 100644
> --- a/configs/pine_h64_defconfig
> +++ b/configs/pine_h64_defconfig
> @@ -6,6 +6,7 @@ CONFIG_MMC0_CD_PIN="PF6"
>  CONFIG_MMC_SUNXI_SLOT_EXTRA=2
>  # CONFIG_PSCI_RESET is not set
>  CONFIG_NR_DRAM_BANKS=1
> +CONFIG_SPL_SPI_SUNXI=y
>  # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
>  # CONFIG_CMD_FLASH is not set
>  # CONFIG_SPL_DOS_PARTITION is not set
> --
> 2.11.0
>
> _______________________________________________
> U-Boot mailing list
> U-Boot at lists.denx.de
> https://lists.denx.de/listinfo/u-boot



-- 
Jagan Teki
Senior Linux Kernel Engineer | Amarula Solutions
U-Boot, Linux | Upstream Maintainer
Hyderabad, India.


More information about the U-Boot mailing list