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".
.../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...@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...@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