[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