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

Marek Kraus gamelaster at outlook.com
Fri Jul 26 08:56:58 UTC 2019


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>
Cc: Jagan Teki <jagan at amarulasolutions.com>
---
Changes for v2:
   - Macros for sun6i offsets, when different base address
---
 arch/arm/mach-sunxi/Kconfig         |   2 +-
 arch/arm/mach-sunxi/spl_spi_sunxi.c | 154 +++++++++++++++++++++++++-----------
 configs/pine_h64_defconfig          |   1 +
 3 files changed, 109 insertions(+), 48 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..b4c082340e 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.
  */
 
@@ -54,15 +54,16 @@
 /* SUN6I variant of the SPI controller                                       */
 /*****************************************************************************/
 
-#define SUN6I_SPI0_CCTL             (0x01C68000 + 0x24)
-#define SUN6I_SPI0_GCR              (0x01C68000 + 0x04)
-#define SUN6I_SPI0_TCR              (0x01C68000 + 0x08)
-#define SUN6I_SPI0_FIFO_STA         (0x01C68000 + 0x1C)
-#define SUN6I_SPI0_MBC              (0x01C68000 + 0x30)
-#define SUN6I_SPI0_MTC              (0x01C68000 + 0x34)
-#define SUN6I_SPI0_BCC              (0x01C68000 + 0x38)
-#define SUN6I_SPI0_TXD              (0x01C68000 + 0x200)
-#define SUN6I_SPI0_RXD              (0x01C68000 + 0x300)
+#define SUN6I_SPI0                  0x01C68000
+#define SUN6I_SPI_CCTL              0x24
+#define SUN6I_SPI_GCR               0x04
+#define SUN6I_SPI_TCR               0x08
+#define SUN6I_SPI_FIFO_STA          0x1C
+#define SUN6I_SPI_MBC               0x30
+#define SUN6I_SPI_MTC               0x34
+#define SUN6I_SPI_BCC               0x38
+#define SUN6I_SPI_TXD               0x200
+#define SUN6I_SPI_RXD               0x300
 
 #define SUN6I_CTL_ENABLE            BIT(0)
 #define SUN6I_CTL_MASTER            BIT(1)
@@ -70,6 +71,17 @@
 #define SUN6I_TCR_XCH               BIT(31)
 
 /*****************************************************************************/
+/* SUN50I_H6 variant of the SPI controller                                   */
+/*****************************************************************************/
+
+#define SUN50I_H6_SPI0              0x05010000
+
+#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 +97,28 @@
 
 /*
  * 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 +127,47 @@ 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_SUNXI_GEN_SUN6I) ||
+	    IS_ENABLED(CONFIG_MACH_SUN50I_H6)) {
+		u64 spi0_base = IS_ENABLED(CONFIG_MACH_SUN50I_H6) ?
+				SUN50I_H6_SPI0 : SUN6I_SPI0;
+		writel(SPI0_CLK_DIV_BY_4, spi0_base + SUN6I_SPI_CCTL);
+	} else {
+		writel(SPI0_CLK_DIV_BY_4, 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) ||
+	    IS_ENABLED(CONFIG_MACH_SUN50I_H6)) {
+		u64 spi0_base = IS_ENABLED(CONFIG_MACH_SUN50I_H6) ?
+				     SUN50I_H6_SPI0 : SUN6I_SPI0;
 
-	if (IS_ENABLED(CONFIG_SUNXI_GEN_SUN6I)) {
 		/* 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(spi0_base + SUN6I_SPI_GCR,
+			     SUN6I_CTL_MASTER |
+			     SUN6I_CTL_ENABLE |
+			     SUN6I_CTL_SRST);
+
 		/* Wait for completion */
-		while (readl(SUN6I_SPI0_GCR) & SUN6I_CTL_SRST)
+		while (readl(spi0_base + SUN6I_SPI_GCR) & SUN6I_CTL_SRST)
 			;
 	} else {
 		/* Enable SPI in the master mode and reset FIFO */
@@ -139,22 +181,35 @@ 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);
-	else
+	if (IS_ENABLED(CONFIG_SUNXI_GEN_SUN6I) ||
+	    IS_ENABLED(CONFIG_MACH_SUN50I_H6)) {
+		u64 spi0_base = IS_ENABLED(CONFIG_MACH_SUN50I_H6) ?
+				     SUN50I_H6_SPI0 : SUN6I_SPI0;
+		clrbits_le32(spi0_base + SUN6I_SPI_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 +217,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 +228,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,16 +290,19 @@ 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_SUNXI_GEN_SUN6I) ||
+		    IS_ENABLED(CONFIG_MACH_SUN50I_H6)) {
+			u64 base = IS_ENABLED(CONFIG_MACH_SUN50I_H6) ?
+					SUN50I_H6_SPI0 : SUN6I_SPI0;
 			sunxi_spi0_read_data(buf8, addr, chunk_len,
-					     SUN6I_SPI0_TCR,
-					     SUN6I_TCR_XCH,
-					     SUN6I_SPI0_FIFO_STA,
-					     SUN6I_SPI0_TXD,
-					     SUN6I_SPI0_RXD,
-					     SUN6I_SPI0_MBC,
-					     SUN6I_SPI0_MTC,
-					     SUN6I_SPI0_BCC);
+					     base + SUN6I_SPI_TCR,
+						    SUN6I_TCR_XCH,
+					     base + SUN6I_SPI_FIFO_STA,
+					     base + SUN6I_SPI_TXD,
+					     base + SUN6I_SPI_RXD,
+					     base + SUN6I_SPI_MBC,
+					     base + SUN6I_SPI_MTC,
+					     base + SUN6I_SPI_BCC);
 		} else {
 			sunxi_spi0_read_data(buf8, addr, chunk_len,
 					     SUN4I_SPI0_CTL,
@@ -282,7 +342,7 @@ static int spl_spi_load_image(struct spl_image_info *spl_image,
 
 	spi0_read_data((void *)header, CONFIG_SYS_SPI_U_BOOT_OFFS, 0x40);
 
-        if (IS_ENABLED(CONFIG_SPL_LOAD_FIT) &&
+	if (IS_ENABLED(CONFIG_SPL_LOAD_FIT) &&
 		image_get_magic(header) == FDT_MAGIC) {
 		struct spl_load_info load;
 
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



More information about the U-Boot mailing list