aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/spi/spi-xtensa-xtfpga.txt9
-rw-r--r--MAINTAINERS6
-rw-r--r--drivers/spi/Kconfig13
-rw-r--r--drivers/spi/Makefile1
-rw-r--r--drivers/spi/spi-xilinx.c26
-rw-r--r--drivers/spi/spi-xtensa-xtfpga.c170
6 files changed, 205 insertions, 20 deletions
diff --git a/Documentation/devicetree/bindings/spi/spi-xtensa-xtfpga.txt b/Documentation/devicetree/bindings/spi/spi-xtensa-xtfpga.txt
new file mode 100644
index 000000000000..b6ebe2bc7041
--- /dev/null
+++ b/Documentation/devicetree/bindings/spi/spi-xtensa-xtfpga.txt
@@ -0,0 +1,9 @@
1Cadence Xtensa XTFPGA platform SPI controller.
2
3This simple SPI master controller is built into xtfpga bitstreams and is used
4to control daughterboard audio codec.
5
6Required properties:
7- compatible: should be "cdns,xtfpga-spi".
8- reg: physical base address of the controller and length of memory mapped
9 region.
diff --git a/MAINTAINERS b/MAINTAINERS
index 82640e640f36..338db2514585 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9782,6 +9782,12 @@ L: linux-serial@vger.kernel.org
9782S: Maintained 9782S: Maintained
9783F: drivers/tty/serial/uartlite.c 9783F: drivers/tty/serial/uartlite.c
9784 9784
9785XTENSA XTFPGA PLATFORM SUPPORT
9786M: Max Filippov <jcmvbkbc@gmail.com>
9787L: linux-xtensa@linux-xtensa.org
9788S: Maintained
9789F: drivers/spi/spi-xtensa-xtfpga.c
9790
9785YAM DRIVER FOR AX.25 9791YAM DRIVER FOR AX.25
9786M: Jean-Paul Roubelat <jpr@f6fbb.org> 9792M: Jean-Paul Roubelat <jpr@f6fbb.org>
9787L: linux-hams@vger.kernel.org 9793L: linux-hams@vger.kernel.org
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 756b5b3ca200..efe1960af2b3 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -538,6 +538,19 @@ config SPI_XILINX
538 538
539 Or for the DS570, see "XPS Serial Peripheral Interface (SPI) (v2.00b)" 539 Or for the DS570, see "XPS Serial Peripheral Interface (SPI) (v2.00b)"
540 540
541config SPI_XTENSA_XTFPGA
542 tristate "Xtensa SPI controller for xtfpga"
543 depends on (XTENSA && XTENSA_PLATFORM_XTFPGA) || COMPILE_TEST
544 select SPI_BITBANG
545 help
546 SPI driver for xtfpga SPI master controller.
547
548 This simple SPI master controller is built into xtfpga bitstreams
549 and is used to control daughterboard audio codec. It always transfers
550 16 bit words in SPI mode 0, automatically asserting CS on transfer
551 start and deasserting on end.
552
553
541config SPI_NUC900 554config SPI_NUC900
542 tristate "Nuvoton NUC900 series SPI" 555 tristate "Nuvoton NUC900 series SPI"
543 depends on ARCH_W90X900 556 depends on ARCH_W90X900
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index e245b94d07d8..bd792669e563 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -81,3 +81,4 @@ obj-$(CONFIG_SPI_TOPCLIFF_PCH) += spi-topcliff-pch.o
81obj-$(CONFIG_SPI_TXX9) += spi-txx9.o 81obj-$(CONFIG_SPI_TXX9) += spi-txx9.o
82obj-$(CONFIG_SPI_XCOMM) += spi-xcomm.o 82obj-$(CONFIG_SPI_XCOMM) += spi-xcomm.o
83obj-$(CONFIG_SPI_XILINX) += spi-xilinx.o 83obj-$(CONFIG_SPI_XILINX) += spi-xilinx.o
84obj-$(CONFIG_SPI_XTENSA_XTFPGA) += spi-xtensa-xtfpga.o
diff --git a/drivers/spi/spi-xilinx.c b/drivers/spi/spi-xilinx.c
index e6cd1112ae40..a3b0b9944bf0 100644
--- a/drivers/spi/spi-xilinx.c
+++ b/drivers/spi/spi-xilinx.c
@@ -87,10 +87,10 @@ struct xilinx_spi {
87 const u8 *tx_ptr; /* pointer in the Rx buffer */ 87 const u8 *tx_ptr; /* pointer in the Rx buffer */
88 int remaining_bytes; /* the number of bytes left to transfer */ 88 int remaining_bytes; /* the number of bytes left to transfer */
89 u8 bits_per_word; 89 u8 bits_per_word;
90 unsigned int (*read_fn) (void __iomem *); 90 unsigned int (*read_fn)(void __iomem *);
91 void (*write_fn) (u32, void __iomem *); 91 void (*write_fn)(u32, void __iomem *);
92 void (*tx_fn) (struct xilinx_spi *); 92 void (*tx_fn)(struct xilinx_spi *);
93 void (*rx_fn) (struct xilinx_spi *); 93 void (*rx_fn)(struct xilinx_spi *);
94}; 94};
95 95
96static void xspi_write32(u32 val, void __iomem *addr) 96static void xspi_write32(u32 val, void __iomem *addr)
@@ -208,26 +208,11 @@ static void xilinx_spi_chipselect(struct spi_device *spi, int is_on)
208} 208}
209 209
210/* spi_bitbang requires custom setup_transfer() to be defined if there is a 210/* spi_bitbang requires custom setup_transfer() to be defined if there is a
211 * custom txrx_bufs(). We have nothing to setup here as the SPI IP block 211 * custom txrx_bufs().
212 * supports 8 or 16 bits per word which cannot be changed in software.
213 * SPI clock can't be changed in software either.
214 * Check for correct bits per word. Chip select delay calculations could be
215 * added here as soon as bitbang_work() can be made aware of the delay value.
216 */ 212 */
217static int xilinx_spi_setup_transfer(struct spi_device *spi, 213static int xilinx_spi_setup_transfer(struct spi_device *spi,
218 struct spi_transfer *t) 214 struct spi_transfer *t)
219{ 215{
220 struct xilinx_spi *xspi = spi_master_get_devdata(spi->master);
221 u8 bits_per_word;
222
223 bits_per_word = (t && t->bits_per_word)
224 ? t->bits_per_word : spi->bits_per_word;
225 if (bits_per_word != xspi->bits_per_word) {
226 dev_err(&spi->dev, "%s, unsupported bits_per_word=%d\n",
227 __func__, bits_per_word);
228 return -EINVAL;
229 }
230
231 return 0; 216 return 0;
232} 217}
233 218
@@ -406,6 +391,7 @@ static int xilinx_spi_probe(struct platform_device *pdev)
406 xspi->write_fn = xspi_write32_be; 391 xspi->write_fn = xspi_write32_be;
407 } 392 }
408 393
394 master->bits_per_word_mask = SPI_BPW_MASK(bits_per_word);
409 xspi->bits_per_word = bits_per_word; 395 xspi->bits_per_word = bits_per_word;
410 if (xspi->bits_per_word == 8) { 396 if (xspi->bits_per_word == 8) {
411 xspi->tx_fn = xspi_tx8; 397 xspi->tx_fn = xspi_tx8;
diff --git a/drivers/spi/spi-xtensa-xtfpga.c b/drivers/spi/spi-xtensa-xtfpga.c
new file mode 100644
index 000000000000..41e158187f9d
--- /dev/null
+++ b/drivers/spi/spi-xtensa-xtfpga.c
@@ -0,0 +1,170 @@
1/*
2 * Xtensa xtfpga SPI controller driver
3 *
4 * Copyright (c) 2014 Cadence Design Systems Inc.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10
11#include <linux/delay.h>
12#include <linux/io.h>
13#include <linux/module.h>
14#include <linux/of.h>
15#include <linux/platform_device.h>
16#include <linux/spi/spi.h>
17#include <linux/spi/spi_bitbang.h>
18
19#define XTFPGA_SPI_NAME "xtfpga_spi"
20
21#define XTFPGA_SPI_START 0x0
22#define XTFPGA_SPI_BUSY 0x4
23#define XTFPGA_SPI_DATA 0x8
24
25#define BUSY_WAIT_US 100
26
27struct xtfpga_spi {
28 struct spi_bitbang bitbang;
29 void __iomem *regs;
30 u32 data;
31 unsigned data_sz;
32};
33
34static inline void xtfpga_spi_write32(const struct xtfpga_spi *spi,
35 unsigned addr, u32 val)
36{
37 iowrite32(val, spi->regs + addr);
38}
39
40static inline unsigned int xtfpga_spi_read32(const struct xtfpga_spi *spi,
41 unsigned addr)
42{
43 return ioread32(spi->regs + addr);
44}
45
46static inline void xtfpga_spi_wait_busy(struct xtfpga_spi *xspi)
47{
48 unsigned i;
49 for (i = 0; xtfpga_spi_read32(xspi, XTFPGA_SPI_BUSY) &&
50 i < BUSY_WAIT_US; ++i)
51 udelay(1);
52 WARN_ON_ONCE(i == BUSY_WAIT_US);
53}
54
55static u32 xtfpga_spi_txrx_word(struct spi_device *spi, unsigned nsecs,
56 u32 v, u8 bits)
57{
58 struct xtfpga_spi *xspi = spi_master_get_devdata(spi->master);
59
60 xspi->data = (xspi->data << bits) | (v & GENMASK(bits - 1, 0));
61 xspi->data_sz += bits;
62 if (xspi->data_sz >= 16) {
63 xtfpga_spi_write32(xspi, XTFPGA_SPI_DATA,
64 xspi->data >> (xspi->data_sz - 16));
65 xspi->data_sz -= 16;
66 xtfpga_spi_write32(xspi, XTFPGA_SPI_START, 1);
67 xtfpga_spi_wait_busy(xspi);
68 xtfpga_spi_write32(xspi, XTFPGA_SPI_START, 0);
69 }
70
71 return 0;
72}
73
74static void xtfpga_spi_chipselect(struct spi_device *spi, int is_on)
75{
76 struct xtfpga_spi *xspi = spi_master_get_devdata(spi->master);
77
78 WARN_ON(xspi->data_sz != 0);
79 xspi->data_sz = 0;
80}
81
82static int xtfpga_spi_probe(struct platform_device *pdev)
83{
84 struct xtfpga_spi *xspi;
85 struct resource *mem;
86 int ret;
87 struct spi_master *master;
88
89 master = spi_alloc_master(&pdev->dev, sizeof(struct xtfpga_spi));
90 if (!master)
91 return -ENOMEM;
92
93 master->flags = SPI_MASTER_NO_RX;
94 master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 16);
95 master->bus_num = pdev->dev.id;
96 master->dev.of_node = pdev->dev.of_node;
97
98 xspi = spi_master_get_devdata(master);
99 xspi->bitbang.master = master;
100 xspi->bitbang.chipselect = xtfpga_spi_chipselect;
101 xspi->bitbang.txrx_word[SPI_MODE_0] = xtfpga_spi_txrx_word;
102
103 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
104 if (!mem) {
105 dev_err(&pdev->dev, "No memory resource\n");
106 ret = -ENODEV;
107 goto err;
108 }
109 xspi->regs = devm_ioremap_resource(&pdev->dev, mem);
110 if (IS_ERR(xspi->regs)) {
111 ret = PTR_ERR(xspi->regs);
112 goto err;
113 }
114
115 xtfpga_spi_write32(xspi, XTFPGA_SPI_START, 0);
116 usleep_range(1000, 2000);
117 if (xtfpga_spi_read32(xspi, XTFPGA_SPI_BUSY)) {
118 dev_err(&pdev->dev, "Device stuck in busy state\n");
119 ret = -EBUSY;
120 goto err;
121 }
122
123 ret = spi_bitbang_start(&xspi->bitbang);
124 if (ret < 0) {
125 dev_err(&pdev->dev, "spi_bitbang_start failed\n");
126 goto err;
127 }
128
129 platform_set_drvdata(pdev, master);
130 return 0;
131err:
132 spi_master_put(master);
133 return ret;
134}
135
136static int xtfpga_spi_remove(struct platform_device *pdev)
137{
138 struct spi_master *master = platform_get_drvdata(pdev);
139 struct xtfpga_spi *xspi = spi_master_get_devdata(master);
140
141 spi_bitbang_stop(&xspi->bitbang);
142 spi_master_put(master);
143
144 return 0;
145}
146
147MODULE_ALIAS("platform:" XTFPGA_SPI_NAME);
148
149#ifdef CONFIG_OF
150static const struct of_device_id xtfpga_spi_of_match[] = {
151 { .compatible = "cdns,xtfpga-spi", },
152 {}
153};
154MODULE_DEVICE_TABLE(of, xtfpga_spi_of_match);
155#endif
156
157static struct platform_driver xtfpga_spi_driver = {
158 .probe = xtfpga_spi_probe,
159 .remove = xtfpga_spi_remove,
160 .driver = {
161 .name = XTFPGA_SPI_NAME,
162 .owner = THIS_MODULE,
163 .of_match_table = of_match_ptr(xtfpga_spi_of_match),
164 },
165};
166module_platform_driver(xtfpga_spi_driver);
167
168MODULE_AUTHOR("Max Filippov <jcmvbkbc@gmail.com>");
169MODULE_DESCRIPTION("xtensa xtfpga SPI driver");
170MODULE_LICENSE("GPL");