aboutsummaryrefslogtreecommitdiff
path: root/arch/arm/mach-sunxi
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-sunxi')
-rw-r--r--arch/arm/mach-sunxi/Kconfig2
-rw-r--r--arch/arm/mach-sunxi/spl_spi_sunxi.c78
2 files changed, 58 insertions, 22 deletions
diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
index fe89aec6b9a..ddf9414b08e 100644
--- a/arch/arm/mach-sunxi/Kconfig
+++ b/arch/arm/mach-sunxi/Kconfig
@@ -1078,7 +1078,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 72faa7171c1..7acb44f52ae 100644
--- a/arch/arm/mach-sunxi/spl_spi_sunxi.c
+++ b/arch/arm/mach-sunxi/spl_spi_sunxi.c
@@ -72,18 +72,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
@@ -101,17 +110,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. */
@@ -125,7 +139,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)
@@ -136,6 +151,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;
@@ -151,23 +169,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);
}
@@ -179,6 +204,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 |
@@ -205,11 +238,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,
@@ -223,7 +258,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);