armbian-build/patch/u-boot/sunxi-dev-u-boot-a523/allwinner-a523-support-spl-spi-controllers.patch

237 lines
7.8 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Marvin Wewer <mwewer37@proton.me>
Date: Mon, 10 Nov 2025 22:10:36 +0000
Subject: Add Allwinner A523 support for SPL SPI controllers
Signed-off-by: Marvin Wewer <mwewer37@proton.me>
---
arch/arm/mach-sunxi/spl_spi_sunxi.c | 107 ++++++----
1 file changed, 68 insertions(+), 39 deletions(-)
diff --git a/arch/arm/mach-sunxi/spl_spi_sunxi.c b/arch/arm/mach-sunxi/spl_spi_sunxi.c
index 111111111111..222222222222 100644
--- a/arch/arm/mach-sunxi/spl_spi_sunxi.c
+++ b/arch/arm/mach-sunxi/spl_spi_sunxi.c
@@ -99,35 +99,44 @@
#define SPI0_CLK_DIV_BY_2 0x1000
#define SPI0_CLK_DIV_BY_4 0x1001
#define SPI0_CLK_DIV_BY_32 0x100f
+#define SUN55I_BUF_STA_REG 0x400
+
/*****************************************************************************/
/*
* 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.
* The H6 uses PC0, PC2, PC3, PC5, the H616 PC0, PC2, PC3, PC4.
*/
static void spi0_pinmux_setup(unsigned int pin_function)
{
+ if (IS_ENABLED(CONFIG_MACH_SUN55I_A523)) {
+ sunxi_gpio_set_cfgpin(SUNXI_GPC(12), pin_function);
+ }
+
/* All chips use PC2. And all chips use PC0, except R528/T113 */
- if (!IS_ENABLED(CONFIG_MACH_SUN8I_R528))
+ if (!IS_ENABLED(CONFIG_MACH_SUN8I_R528) &&
+ !IS_ENABLED(CONFIG_MACH_SUN55I_A523))
sunxi_gpio_set_cfgpin(SUNXI_GPC(0), pin_function);
sunxi_gpio_set_cfgpin(SUNXI_GPC(2), pin_function);
/* All chips except H6/H616/R528/T113 use PC1. */
if (!IS_ENABLED(CONFIG_SUN50I_GEN_H6) &&
- !IS_ENABLED(CONFIG_MACH_SUN8I_R528))
+ !IS_ENABLED(CONFIG_MACH_SUN8I_R528) &&
+ !IS_ENABLED(CONFIG_MACH_SUN55I_A523))
sunxi_gpio_set_cfgpin(SUNXI_GPC(1), pin_function);
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) ||
- IS_ENABLED(CONFIG_MACH_SUN8I_R528))
+ IS_ENABLED(CONFIG_MACH_SUN8I_R528) ||
+ IS_ENABLED(CONFIG_MACH_SUN55I_A523))
sunxi_gpio_set_cfgpin(SUNXI_GPC(4), pin_function);
/* Older generations use PC23 for CS, newer ones use PC3. */
if (IS_ENABLED(CONFIG_MACH_SUN4I) || IS_ENABLED(CONFIG_MACH_SUN7I) ||
IS_ENABLED(CONFIG_MACH_SUN8I_R40))
@@ -142,10 +151,15 @@ static bool is_sun6i_gen_spi(void)
IS_ENABLED(CONFIG_SUN50I_GEN_H6) ||
IS_ENABLED(CONFIG_SUNXI_GEN_NCAT2) ||
IS_ENABLED(CONFIG_MACH_SUN8I_V3S);
}
+static bool is_sun55i_gen_spi(void)
+{
+ return IS_ENABLED(CONFIG_MACH_SUN55I_A523);
+}
+
static uintptr_t spi0_base_address(void)
{
if (IS_ENABLED(CONFIG_MACH_SUN8I_R40))
return 0x01C05000;
@@ -225,11 +239,11 @@ static void spi0_enable_clock(void)
static void spi0_disable_clock(void)
{
uintptr_t base = spi0_base_address();
/* Disable the SPI0 controller */
- if (is_sun6i_gen_spi())
+ if (is_sun6i_gen_spi() || is_sun55i_gen_spi())
clrbits_le32(base + SUN6I_SPI0_GCR, SUN6I_CTL_MASTER |
SUN6I_CTL_ENABLE);
else
clrbits_le32(base + SUN4I_SPI0_CTL, SUN4I_CTL_MASTER |
SUN4I_CTL_ENABLE);
@@ -255,11 +269,12 @@ static void spi0_disable_clock(void)
static void spi0_init(void)
{
unsigned int pin_function = SUNXI_GPC_SPI0;
if (IS_ENABLED(CONFIG_MACH_SUN50I) ||
- IS_ENABLED(CONFIG_SUN50I_GEN_H6))
+ IS_ENABLED(CONFIG_SUN50I_GEN_H6) ||
+ IS_ENABLED(CONFIG_MACH_SUN55I_A523))
pin_function = SUN50I_GPC_SPI0;
else if (IS_ENABLED(CONFIG_MACH_SUNIV) ||
IS_ENABLED(CONFIG_MACH_SUN8I_R528))
pin_function = SUNIV_GPC_SPI0;
@@ -270,11 +285,12 @@ static void spi0_init(void)
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_sun6i_gen_spi())
+ if (is_sun6i_gen_spi() ||
+ is_sun55i_gen_spi())
pin_function = SUNXI_GPIO_DISABLE;
spi0_disable_clock();
spi0_pinmux_setup(pin_function);
}
@@ -282,46 +298,49 @@ static void spi0_deinit(void)
/*****************************************************************************/
#define SPI_READ_MAX_SIZE 60 /* FIFO size, minus 4 bytes of the header */
static void sunxi_spi0_read_data(u8 *buf, u32 addr, u32 bufsize,
- ulong spi_ctl_reg,
- ulong spi_ctl_xch_bitmask,
- ulong spi_fifo_reg,
- ulong spi_tx_reg,
- ulong spi_rx_reg,
- ulong spi_bc_reg,
- ulong spi_tc_reg,
- ulong spi_bcc_reg)
+ ulong spi_ctl_reg,
+ ulong spi_ctl_xch_bitmask,
+ ulong spi_fifo_reg,
+ ulong spi_tx_reg,
+ ulong spi_rx_reg,
+ ulong spi_bc_reg,
+ ulong spi_tc_reg,
+ ulong spi_bcc_reg)
{
- writel(4 + bufsize, spi_bc_reg); /* Burst counter (total bytes) */
- writel(4, spi_tc_reg); /* Transfer counter (bytes to send) */
- if (spi_bcc_reg)
- writel(4, spi_bcc_reg); /* SUN6I also needs this */
-
- /* Send the Read Data Bytes (03h) command header */
- writeb(0x03, spi_tx_reg);
- writeb((u8)(addr >> 16), spi_tx_reg);
- writeb((u8)(addr >> 8), spi_tx_reg);
- writeb((u8)(addr), spi_tx_reg);
-
- /* Start the data transfer */
- setbits_le32(spi_ctl_reg, spi_ctl_xch_bitmask);
-
- /* Wait until everything is received in the RX FIFO */
- while ((readl(spi_fifo_reg) & 0x7F) < 4 + bufsize)
- ;
+ writel(4 + bufsize, spi_bc_reg); /* Burst counter (total bytes) */
+ writel(4, spi_tc_reg); /* Transfer counter (bytes to send) */
+ if (spi_bcc_reg)
+ writel(4, spi_bcc_reg); /* SUN6I also needs this */
+
+ /* Send the Read Data Bytes (03h) command header */
+ writeb(0x03, spi_tx_reg);
+ writeb((u8)(addr >> 16), spi_tx_reg);
+ writeb((u8)(addr >> 8), spi_tx_reg);
+ writeb((u8)(addr), spi_tx_reg);
+
+ /* Start the data transfer */
+ setbits_le32(spi_ctl_reg, spi_ctl_xch_bitmask);
+
+ /* Wait until everything is received in the RX FIFO */
+#if IS_ENABLED(CONFIG_MACH_SUN55I_A523)
+ while ((readl(spi_fifo_reg) & 0xFF) < 4 + bufsize);
+#else
+ while ((readl(spi_fifo_reg) & 0x7F) < 4 + bufsize);
+#endif
- /* Skip 4 bytes */
- readl(spi_rx_reg);
+ /* Skip 4 bytes */
+ readl(spi_rx_reg);
- /* Read the data */
- while (bufsize-- > 0)
- *buf++ = readb(spi_rx_reg);
+ /* Read the data */
+ while (bufsize-- > 0)
+ *buf++ = readb(spi_rx_reg);
- /* tSHSL time is up to 100 ns in various SPI flash datasheets */
- udelay(1);
+ /* tSHSL time is up to 100 ns in various SPI flash datasheets */
+ udelay(1);
}
static void spi0_read_data(void *buf, u32 addr, u32 len)
{
u8 *buf8 = buf;
@@ -331,20 +350,30 @@ static void spi0_read_data(void *buf, u32 addr, u32 len)
while (len > 0) {
chunk_len = len;
if (chunk_len > SPI_READ_MAX_SIZE)
chunk_len = SPI_READ_MAX_SIZE;
- if (is_sun6i_gen_spi()) {
+ if (is_sun6i_gen_spi() && !is_sun55i_gen_spi()) {
sunxi_spi0_read_data(buf8, addr, chunk_len,
base + SUN6I_SPI0_TCR,
SUN6I_TCR_XCH,
base + SUN6I_SPI0_FIFO_STA,
base + SUN6I_SPI0_TXD,
base + SUN6I_SPI0_RXD,
base + SUN6I_SPI0_MBC,
base + SUN6I_SPI0_MTC,
base + SUN6I_SPI0_BCC);
+ } else if (is_sun55i_gen_spi()) {
+ sunxi_spi0_read_data(buf8, addr, chunk_len,
+ base + SUN6I_SPI0_TCR,
+ SUN6I_TCR_XCH,
+ base + SUN55I_BUF_STA_REG,
+ base + SUN6I_SPI0_TXD,
+ base + SUN6I_SPI0_RXD,
+ base + SUN6I_SPI0_MBC,
+ base + SUN6I_SPI0_MTC,
+ base + SUN6I_SPI0_BCC);
} else {
sunxi_spi0_read_data(buf8, addr, chunk_len,
base + SUN4I_SPI0_CTL,
SUN4I_CTL_XCH,
base + SUN4I_SPI0_FIFO_STA,
--
Armbian