summaryrefslogtreecommitdiffstats
path: root/drivers/spi/spi-altera.c
diff options
context:
space:
mode:
authorLars-Peter Clausen <lars@metafoo.de>2017-08-16 05:33:11 -0400
committerMark Brown <broonie@kernel.org>2017-08-16 06:53:27 -0400
commite19b63cd3cb7ebf1ca73d9c4f58934149337ed24 (patch)
treed5242464dc228351638f7298b08afe97f6682745 /drivers/spi/spi-altera.c
parent5771a8c08880cdca3bfb4a3fc6d309d6bba20877 (diff)
spi: altera: Switch to SPI core transfer queue management
The Altera SPI driver currently uses the spi-bitbang infrastructure for transfer queue management, but non of the bitbang functionality itself. This is because when the driver was written this was the only way to not have to do queue management in the driver itself. Nowadays transfer queue management is available from the SPI driver core itself and using the bitbang infrastructure just adds an additional level of indirection. Switch the driver over to using the core queue management directly. Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'drivers/spi/spi-altera.c')
-rw-r--r--drivers/spi/spi-altera.c94
1 files changed, 27 insertions, 67 deletions
diff --git a/drivers/spi/spi-altera.c b/drivers/spi/spi-altera.c
index b95010e72452..bfac34068999 100644
--- a/drivers/spi/spi-altera.c
+++ b/drivers/spi/spi-altera.c
@@ -18,7 +18,6 @@
18#include <linux/module.h> 18#include <linux/module.h>
19#include <linux/platform_device.h> 19#include <linux/platform_device.h>
20#include <linux/spi/spi.h> 20#include <linux/spi/spi.h>
21#include <linux/spi/spi_bitbang.h>
22#include <linux/io.h> 21#include <linux/io.h>
23#include <linux/of.h> 22#include <linux/of.h>
24 23
@@ -45,10 +44,6 @@
45#define ALTERA_SPI_CONTROL_SSO_MSK 0x400 44#define ALTERA_SPI_CONTROL_SSO_MSK 0x400
46 45
47struct altera_spi { 46struct altera_spi {
48 /* bitbang has to be first */
49 struct spi_bitbang bitbang;
50 struct completion done;
51
52 void __iomem *base; 47 void __iomem *base;
53 int irq; 48 int irq;
54 int len; 49 int len;
@@ -66,39 +61,18 @@ static inline struct altera_spi *altera_spi_to_hw(struct spi_device *sdev)
66 return spi_master_get_devdata(sdev->master); 61 return spi_master_get_devdata(sdev->master);
67} 62}
68 63
69static void altera_spi_chipsel(struct spi_device *spi, int value) 64static void altera_spi_set_cs(struct spi_device *spi, bool is_high)
70{ 65{
71 struct altera_spi *hw = altera_spi_to_hw(spi); 66 struct altera_spi *hw = altera_spi_to_hw(spi);
72 67
73 if (spi->mode & SPI_CS_HIGH) { 68 if (is_high) {
74 switch (value) { 69 hw->imr &= ~ALTERA_SPI_CONTROL_SSO_MSK;
75 case BITBANG_CS_INACTIVE: 70 writel(hw->imr, hw->base + ALTERA_SPI_CONTROL);
76 writel(1 << spi->chip_select, 71 writel(0, hw->base + ALTERA_SPI_SLAVE_SEL);
77 hw->base + ALTERA_SPI_SLAVE_SEL);
78 hw->imr |= ALTERA_SPI_CONTROL_SSO_MSK;
79 writel(hw->imr, hw->base + ALTERA_SPI_CONTROL);
80 break;
81
82 case BITBANG_CS_ACTIVE:
83 hw->imr &= ~ALTERA_SPI_CONTROL_SSO_MSK;
84 writel(hw->imr, hw->base + ALTERA_SPI_CONTROL);
85 writel(0, hw->base + ALTERA_SPI_SLAVE_SEL);
86 break;
87 }
88 } else { 72 } else {
89 switch (value) { 73 writel(BIT(spi->chip_select), hw->base + ALTERA_SPI_SLAVE_SEL);
90 case BITBANG_CS_INACTIVE: 74 hw->imr |= ALTERA_SPI_CONTROL_SSO_MSK;
91 hw->imr &= ~ALTERA_SPI_CONTROL_SSO_MSK; 75 writel(hw->imr, hw->base + ALTERA_SPI_CONTROL);
92 writel(hw->imr, hw->base + ALTERA_SPI_CONTROL);
93 break;
94
95 case BITBANG_CS_ACTIVE:
96 writel(1 << spi->chip_select,
97 hw->base + ALTERA_SPI_SLAVE_SEL);
98 hw->imr |= ALTERA_SPI_CONTROL_SSO_MSK;
99 writel(hw->imr, hw->base + ALTERA_SPI_CONTROL);
100 break;
101 }
102 } 76 }
103} 77}
104 78
@@ -116,9 +90,10 @@ static inline unsigned int hw_txbyte(struct altera_spi *hw, int count)
116 return 0; 90 return 0;
117} 91}
118 92
119static int altera_spi_txrx(struct spi_device *spi, struct spi_transfer *t) 93static int altera_spi_txrx(struct spi_master *master,
94 struct spi_device *spi, struct spi_transfer *t)
120{ 95{
121 struct altera_spi *hw = altera_spi_to_hw(spi); 96 struct altera_spi *hw = spi_master_get_devdata(master);
122 97
123 hw->tx = t->tx_buf; 98 hw->tx = t->tx_buf;
124 hw->rx = t->rx_buf; 99 hw->rx = t->rx_buf;
@@ -133,11 +108,6 @@ static int altera_spi_txrx(struct spi_device *spi, struct spi_transfer *t)
133 108
134 /* send the first byte */ 109 /* send the first byte */
135 writel(hw_txbyte(hw, 0), hw->base + ALTERA_SPI_TXDATA); 110 writel(hw_txbyte(hw, 0), hw->base + ALTERA_SPI_TXDATA);
136
137 wait_for_completion(&hw->done);
138 /* disable receive interrupt */
139 hw->imr &= ~ALTERA_SPI_CONTROL_IRRDY_MSK;
140 writel(hw->imr, hw->base + ALTERA_SPI_CONTROL);
141 } else { 111 } else {
142 while (hw->count < hw->len) { 112 while (hw->count < hw->len) {
143 unsigned int rxd; 113 unsigned int rxd;
@@ -164,14 +134,16 @@ static int altera_spi_txrx(struct spi_device *spi, struct spi_transfer *t)
164 134
165 hw->count++; 135 hw->count++;
166 } 136 }
137 spi_finalize_current_transfer(master);
167 } 138 }
168 139
169 return hw->count * hw->bytes_per_word; 140 return t->len;
170} 141}
171 142
172static irqreturn_t altera_spi_irq(int irq, void *dev) 143static irqreturn_t altera_spi_irq(int irq, void *dev)
173{ 144{
174 struct altera_spi *hw = dev; 145 struct spi_master *master = dev;
146 struct altera_spi *hw = spi_master_get_devdata(master);
175 unsigned int rxd; 147 unsigned int rxd;
176 148
177 rxd = readl(hw->base + ALTERA_SPI_RXDATA); 149 rxd = readl(hw->base + ALTERA_SPI_RXDATA);
@@ -189,10 +161,15 @@ static irqreturn_t altera_spi_irq(int irq, void *dev)
189 161
190 hw->count++; 162 hw->count++;
191 163
192 if (hw->count < hw->len) 164 if (hw->count < hw->len) {
193 writel(hw_txbyte(hw, hw->count), hw->base + ALTERA_SPI_TXDATA); 165 writel(hw_txbyte(hw, hw->count), hw->base + ALTERA_SPI_TXDATA);
194 else 166 } else {
195 complete(&hw->done); 167 /* disable receive interrupt */
168 hw->imr &= ~ALTERA_SPI_CONTROL_IRRDY_MSK;
169 writel(hw->imr, hw->base + ALTERA_SPI_CONTROL);
170
171 spi_finalize_current_transfer(master);
172 }
196 173
197 return IRQ_HANDLED; 174 return IRQ_HANDLED;
198} 175}
@@ -214,14 +191,10 @@ static int altera_spi_probe(struct platform_device *pdev)
214 master->mode_bits = SPI_CS_HIGH; 191 master->mode_bits = SPI_CS_HIGH;
215 master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 16); 192 master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 16);
216 master->dev.of_node = pdev->dev.of_node; 193 master->dev.of_node = pdev->dev.of_node;
194 master->transfer_one = altera_spi_txrx;
195 master->set_cs = altera_spi_set_cs;
217 196
218 hw = spi_master_get_devdata(master); 197 hw = spi_master_get_devdata(master);
219 platform_set_drvdata(pdev, hw);
220
221 /* setup the state for the bitbang driver */
222 hw->bitbang.master = master;
223 hw->bitbang.chipselect = altera_spi_chipsel;
224 hw->bitbang.txrx_bufs = altera_spi_txrx;
225 198
226 /* find and map our resources */ 199 /* find and map our resources */
227 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 200 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -239,15 +212,13 @@ static int altera_spi_probe(struct platform_device *pdev)
239 /* irq is optional */ 212 /* irq is optional */
240 hw->irq = platform_get_irq(pdev, 0); 213 hw->irq = platform_get_irq(pdev, 0);
241 if (hw->irq >= 0) { 214 if (hw->irq >= 0) {
242 init_completion(&hw->done);
243 err = devm_request_irq(&pdev->dev, hw->irq, altera_spi_irq, 0, 215 err = devm_request_irq(&pdev->dev, hw->irq, altera_spi_irq, 0,
244 pdev->name, hw); 216 pdev->name, master);
245 if (err) 217 if (err)
246 goto exit; 218 goto exit;
247 } 219 }
248 220
249 /* register our spi controller */ 221 err = devm_spi_register_master(&pdev->dev, master);
250 err = spi_bitbang_start(&hw->bitbang);
251 if (err) 222 if (err)
252 goto exit; 223 goto exit;
253 dev_info(&pdev->dev, "base %p, irq %d\n", hw->base, hw->irq); 224 dev_info(&pdev->dev, "base %p, irq %d\n", hw->base, hw->irq);
@@ -258,16 +229,6 @@ exit:
258 return err; 229 return err;
259} 230}
260 231
261static int altera_spi_remove(struct platform_device *dev)
262{
263 struct altera_spi *hw = platform_get_drvdata(dev);
264 struct spi_master *master = hw->bitbang.master;
265
266 spi_bitbang_stop(&hw->bitbang);
267 spi_master_put(master);
268 return 0;
269}
270
271#ifdef CONFIG_OF 232#ifdef CONFIG_OF
272static const struct of_device_id altera_spi_match[] = { 233static const struct of_device_id altera_spi_match[] = {
273 { .compatible = "ALTR,spi-1.0", }, 234 { .compatible = "ALTR,spi-1.0", },
@@ -279,7 +240,6 @@ MODULE_DEVICE_TABLE(of, altera_spi_match);
279 240
280static struct platform_driver altera_spi_driver = { 241static struct platform_driver altera_spi_driver = {
281 .probe = altera_spi_probe, 242 .probe = altera_spi_probe,
282 .remove = altera_spi_remove,
283 .driver = { 243 .driver = {
284 .name = DRV_NAME, 244 .name = DRV_NAME,
285 .pm = NULL, 245 .pm = NULL,