The Allwinner A23/A33 SoCs contain an SPI controller that is
largely identical to the one in the A31. The major differences
from A31 to A23/A33 are:

- The TX and RX FIFOs on the A23/A33 are only 64 Bytes deep
  compared to 128 Bytes on the A31.

- On A23/A33, the SPI_INTCTL register provides an additional
  "Master Sample Data Mode" configuration option.

Currently the FIFO depth is hardcoded to 128 Bytes in the
driver; this patch moves it into SoC-specific platform data
instead of defining it globally and adds a new compatible
"allwinner,sun8i-a23-spi".

Signed-off-by: Karsten Merker <mer...@debian.org>
---
 .../devicetree/bindings/spi/spi-sun6i.txt          |  6 ++-
 drivers/spi/spi-sun6i.c                            | 43 +++++++++++++++++++---
 2 files changed, 41 insertions(+), 8 deletions(-)

diff --git a/Documentation/devicetree/bindings/spi/spi-sun6i.txt 
b/Documentation/devicetree/bindings/spi/spi-sun6i.txt
index 21de73d..4d3eb86 100644
--- a/Documentation/devicetree/bindings/spi/spi-sun6i.txt
+++ b/Documentation/devicetree/bindings/spi/spi-sun6i.txt
@@ -1,7 +1,9 @@
-Allwinner A31 SPI controller
+Allwinner A31/A23 SPI controller
 
 Required properties:
-- compatible: Should be "allwinner,sun6i-a31-spi".
+- compatible: Should be one of
+   - "allwinner,sun6i-a31-spi"
+   - "allwinner,sun8i-a23-spi"
 - reg: Should contain register location and length.
 - interrupts: Should contain interrupt.
 - clocks: phandle to the clocks feeding the SPI controller. Two are
diff --git a/drivers/spi/spi-sun6i.c b/drivers/spi/spi-sun6i.c
index 9918a57..c6d88c9 100644
--- a/drivers/spi/spi-sun6i.c
+++ b/drivers/spi/spi-sun6i.c
@@ -5,6 +5,8 @@
  * Copyright (C) 2014 Maxime Ripard
  * Maxime Ripard <maxime.rip...@free-electrons.com>
  *
+ * Copyright (C) 2016 Karsten Merker <merker@@debian.org>
+ *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
  * published by the Free Software Foundation; either version 2 of
@@ -24,6 +26,7 @@
 #include <linux/spi/spi.h>
 
 #define SUN6I_FIFO_DEPTH               128
+#define SUN8I_A23_FIFO_DEPTH           64
 
 #define SUN6I_GBL_CTL_REG              0x04
 #define SUN6I_GBL_CTL_BUS_ENABLE               BIT(0)
@@ -92,6 +95,18 @@ struct sun6i_spi {
        int                     len;
 };
 
+struct sun6i_spi_platform_data {
+       int     fifo_depth;
+};
+
+static struct sun6i_spi_platform_data sun6i_a31_spi_platform_data = {
+       .fifo_depth     = SUN6I_FIFO_DEPTH,
+};
+
+static struct sun6i_spi_platform_data sun8i_a23_spi_platform_data = {
+       .fifo_depth     = SUN8I_A23_FIFO_DEPTH,
+};
+
 static inline u32 sun6i_spi_read(struct sun6i_spi *sspi, u32 reg)
 {
        return readl(sspi->base_addr + reg);
@@ -155,7 +170,10 @@ static void sun6i_spi_set_cs(struct spi_device *spi, bool 
enable)
 
 static size_t sun6i_spi_max_transfer_size(struct spi_device *spi)
 {
-       return SUN6I_FIFO_DEPTH - 1;
+       struct sun6i_spi_platform_data *pdata;
+
+       pdata = spi->dev.platform_data;
+       return (pdata->fifo_depth - 1);
 }
 
 static int sun6i_spi_transfer_one(struct spi_master *master,
@@ -168,9 +186,14 @@ static int sun6i_spi_transfer_one(struct spi_master 
*master,
        unsigned int tx_len = 0;
        int ret = 0;
        u32 reg;
+       int fifo_depth;
+       struct sun6i_spi_platform_data *pdata;
 
        /* We don't support transfer larger than the FIFO */
-       if (tfr->len > SUN6I_FIFO_DEPTH)
+       pdata = spi->dev.platform_data;
+       fifo_depth = pdata->fifo_depth;
+
+       if (tfr->len > fifo_depth)
                return -EINVAL;
 
        reinit_completion(&sspi->done);
@@ -265,7 +288,7 @@ static int sun6i_spi_transfer_one(struct spi_master *master,
                        SUN6I_BURST_CTL_CNT_STC(tx_len));
 
        /* Fill the TX FIFO */
-       sun6i_spi_fill_fifo(sspi, SUN6I_FIFO_DEPTH);
+       sun6i_spi_fill_fifo(sspi, fifo_depth);
 
        /* Enable the interrupts */
        sun6i_spi_write(sspi, SUN6I_INT_CTL_REG, SUN6I_INT_CTL_TC);
@@ -288,7 +311,7 @@ static int sun6i_spi_transfer_one(struct spi_master *master,
                goto out;
        }
 
-       sun6i_spi_drain_fifo(sspi, SUN6I_FIFO_DEPTH);
+       sun6i_spi_drain_fifo(sspi, fifo_depth);
 
 out:
        sun6i_spi_write(sspi, SUN6I_INT_CTL_REG, 0);
@@ -470,7 +493,14 @@ static int sun6i_spi_remove(struct platform_device *pdev)
 }
 
 static const struct of_device_id sun6i_spi_match[] = {
-       { .compatible = "allwinner,sun6i-a31-spi", },
+       {
+               .compatible = "allwinner,sun6i-a31-spi",
+               .data = &sun6i_a31_spi_platform_data,
+       },
+       {
+               .compatible = "allwinner,sun8i-a23-spi",
+               .data = &sun8i_a23_spi_platform_data,
+       },
        {}
 };
 MODULE_DEVICE_TABLE(of, sun6i_spi_match);
@@ -493,5 +523,6 @@ module_platform_driver(sun6i_spi_driver);
 
 MODULE_AUTHOR("Pan Nan <pan...@allwinnertech.com>");
 MODULE_AUTHOR("Maxime Ripard <maxime.rip...@free-electrons.com>");
-MODULE_DESCRIPTION("Allwinner A31 SPI controller driver");
+MODULE_AUTHOR("Karsten Merker <mer...@debian.org>");
+MODULE_DESCRIPTION("Allwinner A31/A23 SPI controller driver");
 MODULE_LICENSE("GPL");
-- 
2.1.4

-- 
You received this message because you are subscribed to the Google Groups 
"linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to linux-sunxi+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to