aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteven King <sfking@fdwdc.com>2010-01-20 15:49:44 -0500
committerGrant Likely <grant.likely@secretlab.ca>2010-01-20 15:49:44 -0500
commit34b8c66173666025020e3a6f8d4a5c238b19cde5 (patch)
tree00680c39dde5cefa549028532347902d9f714b4c
parent631e61b7ca12ef14c834f99f8948e410c539f585 (diff)
spi: Add Freescale/Motorola Coldfire QSPI driver
Add support for the QSPI controller found some on Freescale/Motorola Coldfire MCUs. Full duplex, active high cs, spi modes 0-3 and word sizes 8-16 bits are supported. The hardware drives the MISO, MOSI and SCLK lines, but the chip selects are managed via GPIO and must be configured by the board code. The QSPI controller has an 80 byte buffer which allows us to transfer up to 16 words at a time. For transfers longer than 16 words, we split the buffer in half so we can update in one half while the controller is operating on the other half. Interrupt latencies then ultimately limits our sustained thru-put to something less than half the maximum speed supported by the part. Signed-off-by: Steven King <sfking@fdwdc.com> Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
-rw-r--r--drivers/spi/Kconfig10
-rw-r--r--drivers/spi/Makefile1
-rw-r--r--drivers/spi/coldfire_qspi.c640
3 files changed, 651 insertions, 0 deletions
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 82dabbca00c1..28becdd4dea9 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -100,6 +100,16 @@ config SPI_BUTTERFLY
100 inexpensive battery powered microcontroller evaluation board. 100 inexpensive battery powered microcontroller evaluation board.
101 This same cable can be used to flash new firmware. 101 This same cable can be used to flash new firmware.
102 102
103config SPI_COLDFIRE_QSPI
104 tristate "Freescale Coldfire QSPI controller"
105 depends on (M520x || M523x || M5249 || M527x || M528x || M532x)
106 help
107 This enables support for the Coldfire QSPI controller in master
108 mode.
109
110 This driver can also be built as a module. If so, the module
111 will be called coldfire_qspi.
112
103config SPI_DAVINCI 113config SPI_DAVINCI
104 tristate "SPI controller driver for DaVinci/DA8xx SoC's" 114 tristate "SPI controller driver for DaVinci/DA8xx SoC's"
105 depends on SPI_MASTER && ARCH_DAVINCI 115 depends on SPI_MASTER && ARCH_DAVINCI
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 84b490fb7f8a..d3a65ab8ebbf 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -16,6 +16,7 @@ obj-$(CONFIG_SPI_BFIN) += spi_bfin5xx.o
16obj-$(CONFIG_SPI_BITBANG) += spi_bitbang.o 16obj-$(CONFIG_SPI_BITBANG) += spi_bitbang.o
17obj-$(CONFIG_SPI_AU1550) += au1550_spi.o 17obj-$(CONFIG_SPI_AU1550) += au1550_spi.o
18obj-$(CONFIG_SPI_BUTTERFLY) += spi_butterfly.o 18obj-$(CONFIG_SPI_BUTTERFLY) += spi_butterfly.o
19obj-$(CONFIG_SPI_COLDFIRE_QSPI) += coldfire_qspi.o
19obj-$(CONFIG_SPI_DAVINCI) += davinci_spi.o 20obj-$(CONFIG_SPI_DAVINCI) += davinci_spi.o
20obj-$(CONFIG_SPI_DESIGNWARE) += dw_spi.o 21obj-$(CONFIG_SPI_DESIGNWARE) += dw_spi.o
21obj-$(CONFIG_SPI_DW_PCI) += dw_spi_pci.o 22obj-$(CONFIG_SPI_DW_PCI) += dw_spi_pci.o
diff --git a/drivers/spi/coldfire_qspi.c b/drivers/spi/coldfire_qspi.c
new file mode 100644
index 000000000000..59be3efe0636
--- /dev/null
+++ b/drivers/spi/coldfire_qspi.c
@@ -0,0 +1,640 @@
1/*
2 * Freescale/Motorola Coldfire Queued SPI driver
3 *
4 * Copyright 2010 Steven King <sfking@fdwdc.com>
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 as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA
19 *
20*/
21
22#include <linux/kernel.h>
23#include <linux/module.h>
24#include <linux/interrupt.h>
25#include <linux/errno.h>
26#include <linux/platform_device.h>
27#include <linux/workqueue.h>
28#include <linux/delay.h>
29#include <linux/io.h>
30#include <linux/clk.h>
31#include <linux/err.h>
32#include <linux/spi/spi.h>
33
34#include <asm/coldfire.h>
35#include <asm/mcfqspi.h>
36
37#define DRIVER_NAME "mcfqspi"
38
39#define MCFQSPI_BUSCLK (MCF_BUSCLK / 2)
40
41#define MCFQSPI_QMR 0x00
42#define MCFQSPI_QMR_MSTR 0x8000
43#define MCFQSPI_QMR_CPOL 0x0200
44#define MCFQSPI_QMR_CPHA 0x0100
45#define MCFQSPI_QDLYR 0x04
46#define MCFQSPI_QDLYR_SPE 0x8000
47#define MCFQSPI_QWR 0x08
48#define MCFQSPI_QWR_HALT 0x8000
49#define MCFQSPI_QWR_WREN 0x4000
50#define MCFQSPI_QWR_CSIV 0x1000
51#define MCFQSPI_QIR 0x0C
52#define MCFQSPI_QIR_WCEFB 0x8000
53#define MCFQSPI_QIR_ABRTB 0x4000
54#define MCFQSPI_QIR_ABRTL 0x1000
55#define MCFQSPI_QIR_WCEFE 0x0800
56#define MCFQSPI_QIR_ABRTE 0x0400
57#define MCFQSPI_QIR_SPIFE 0x0100
58#define MCFQSPI_QIR_WCEF 0x0008
59#define MCFQSPI_QIR_ABRT 0x0004
60#define MCFQSPI_QIR_SPIF 0x0001
61#define MCFQSPI_QAR 0x010
62#define MCFQSPI_QAR_TXBUF 0x00
63#define MCFQSPI_QAR_RXBUF 0x10
64#define MCFQSPI_QAR_CMDBUF 0x20
65#define MCFQSPI_QDR 0x014
66#define MCFQSPI_QCR 0x014
67#define MCFQSPI_QCR_CONT 0x8000
68#define MCFQSPI_QCR_BITSE 0x4000
69#define MCFQSPI_QCR_DT 0x2000
70
71struct mcfqspi {
72 void __iomem *iobase;
73 int irq;
74 struct clk *clk;
75 struct mcfqspi_cs_control *cs_control;
76
77 wait_queue_head_t waitq;
78
79 struct work_struct work;
80 struct workqueue_struct *workq;
81 spinlock_t lock;
82 struct list_head msgq;
83};
84
85static void mcfqspi_wr_qmr(struct mcfqspi *mcfqspi, u16 val)
86{
87 writew(val, mcfqspi->iobase + MCFQSPI_QMR);
88}
89
90static void mcfqspi_wr_qdlyr(struct mcfqspi *mcfqspi, u16 val)
91{
92 writew(val, mcfqspi->iobase + MCFQSPI_QDLYR);
93}
94
95static u16 mcfqspi_rd_qdlyr(struct mcfqspi *mcfqspi)
96{
97 return readw(mcfqspi->iobase + MCFQSPI_QDLYR);
98}
99
100static void mcfqspi_wr_qwr(struct mcfqspi *mcfqspi, u16 val)
101{
102 writew(val, mcfqspi->iobase + MCFQSPI_QWR);
103}
104
105static void mcfqspi_wr_qir(struct mcfqspi *mcfqspi, u16 val)
106{
107 writew(val, mcfqspi->iobase + MCFQSPI_QIR);
108}
109
110static void mcfqspi_wr_qar(struct mcfqspi *mcfqspi, u16 val)
111{
112 writew(val, mcfqspi->iobase + MCFQSPI_QAR);
113}
114
115static void mcfqspi_wr_qdr(struct mcfqspi *mcfqspi, u16 val)
116{
117 writew(val, mcfqspi->iobase + MCFQSPI_QDR);
118}
119
120static u16 mcfqspi_rd_qdr(struct mcfqspi *mcfqspi)
121{
122 return readw(mcfqspi->iobase + MCFQSPI_QDR);
123}
124
125static void mcfqspi_cs_select(struct mcfqspi *mcfqspi, u8 chip_select,
126 bool cs_high)
127{
128 mcfqspi->cs_control->select(mcfqspi->cs_control, chip_select, cs_high);
129}
130
131static void mcfqspi_cs_deselect(struct mcfqspi *mcfqspi, u8 chip_select,
132 bool cs_high)
133{
134 mcfqspi->cs_control->deselect(mcfqspi->cs_control, chip_select, cs_high);
135}
136
137static int mcfqspi_cs_setup(struct mcfqspi *mcfqspi)
138{
139 return (mcfqspi->cs_control && mcfqspi->cs_control->setup) ?
140 mcfqspi->cs_control->setup(mcfqspi->cs_control) : 0;
141}
142
143static void mcfqspi_cs_teardown(struct mcfqspi *mcfqspi)
144{
145 if (mcfqspi->cs_control && mcfqspi->cs_control->teardown)
146 mcfqspi->cs_control->teardown(mcfqspi->cs_control);
147}
148
149static u8 mcfqspi_qmr_baud(u32 speed_hz)
150{
151 return clamp((MCFQSPI_BUSCLK + speed_hz - 1) / speed_hz, 2u, 255u);
152}
153
154static bool mcfqspi_qdlyr_spe(struct mcfqspi *mcfqspi)
155{
156 return mcfqspi_rd_qdlyr(mcfqspi) & MCFQSPI_QDLYR_SPE;
157}
158
159static irqreturn_t mcfqspi_irq_handler(int this_irq, void *dev_id)
160{
161 struct mcfqspi *mcfqspi = dev_id;
162
163 /* clear interrupt */
164 mcfqspi_wr_qir(mcfqspi, MCFQSPI_QIR_SPIFE | MCFQSPI_QIR_SPIF);
165 wake_up(&mcfqspi->waitq);
166
167 return IRQ_HANDLED;
168}
169
170static void mcfqspi_transfer_msg8(struct mcfqspi *mcfqspi, unsigned count,
171 const u8 *txbuf, u8 *rxbuf)
172{
173 unsigned i, n, offset = 0;
174
175 n = min(count, 16u);
176
177 mcfqspi_wr_qar(mcfqspi, MCFQSPI_QAR_CMDBUF);
178 for (i = 0; i < n; ++i)
179 mcfqspi_wr_qdr(mcfqspi, MCFQSPI_QCR_BITSE);
180
181 mcfqspi_wr_qar(mcfqspi, MCFQSPI_QAR_TXBUF);
182 if (txbuf)
183 for (i = 0; i < n; ++i)
184 mcfqspi_wr_qdr(mcfqspi, *txbuf++);
185 else
186 for (i = 0; i < count; ++i)
187 mcfqspi_wr_qdr(mcfqspi, 0);
188
189 count -= n;
190 if (count) {
191 u16 qwr = 0xf08;
192 mcfqspi_wr_qwr(mcfqspi, 0x700);
193 mcfqspi_wr_qdlyr(mcfqspi, MCFQSPI_QDLYR_SPE);
194
195 do {
196 wait_event(mcfqspi->waitq, !mcfqspi_qdlyr_spe(mcfqspi));
197 mcfqspi_wr_qwr(mcfqspi, qwr);
198 mcfqspi_wr_qdlyr(mcfqspi, MCFQSPI_QDLYR_SPE);
199 if (rxbuf) {
200 mcfqspi_wr_qar(mcfqspi,
201 MCFQSPI_QAR_RXBUF + offset);
202 for (i = 0; i < 8; ++i)
203 *rxbuf++ = mcfqspi_rd_qdr(mcfqspi);
204 }
205 n = min(count, 8u);
206 if (txbuf) {
207 mcfqspi_wr_qar(mcfqspi,
208 MCFQSPI_QAR_TXBUF + offset);
209 for (i = 0; i < n; ++i)
210 mcfqspi_wr_qdr(mcfqspi, *txbuf++);
211 }
212 qwr = (offset ? 0x808 : 0) + ((n - 1) << 8);
213 offset ^= 8;
214 count -= n;
215 } while (count);
216 wait_event(mcfqspi->waitq, !mcfqspi_qdlyr_spe(mcfqspi));
217 mcfqspi_wr_qwr(mcfqspi, qwr);
218 mcfqspi_wr_qdlyr(mcfqspi, MCFQSPI_QDLYR_SPE);
219 if (rxbuf) {
220 mcfqspi_wr_qar(mcfqspi, MCFQSPI_QAR_RXBUF + offset);
221 for (i = 0; i < 8; ++i)
222 *rxbuf++ = mcfqspi_rd_qdr(mcfqspi);
223 offset ^= 8;
224 }
225 } else {
226 mcfqspi_wr_qwr(mcfqspi, (n - 1) << 8);
227 mcfqspi_wr_qdlyr(mcfqspi, MCFQSPI_QDLYR_SPE);
228 }
229 wait_event(mcfqspi->waitq, !mcfqspi_qdlyr_spe(mcfqspi));
230 if (rxbuf) {
231 mcfqspi_wr_qar(mcfqspi, MCFQSPI_QAR_RXBUF + offset);
232 for (i = 0; i < n; ++i)
233 *rxbuf++ = mcfqspi_rd_qdr(mcfqspi);
234 }
235}
236
237static void mcfqspi_transfer_msg16(struct mcfqspi *mcfqspi, unsigned count,
238 const u16 *txbuf, u16 *rxbuf)
239{
240 unsigned i, n, offset = 0;
241
242 n = min(count, 16u);
243
244 mcfqspi_wr_qar(mcfqspi, MCFQSPI_QAR_CMDBUF);
245 for (i = 0; i < n; ++i)
246 mcfqspi_wr_qdr(mcfqspi, MCFQSPI_QCR_BITSE);
247
248 mcfqspi_wr_qar(mcfqspi, MCFQSPI_QAR_TXBUF);
249 if (txbuf)
250 for (i = 0; i < n; ++i)
251 mcfqspi_wr_qdr(mcfqspi, *txbuf++);
252 else
253 for (i = 0; i < count; ++i)
254 mcfqspi_wr_qdr(mcfqspi, 0);
255
256 count -= n;
257 if (count) {
258 u16 qwr = 0xf08;
259 mcfqspi_wr_qwr(mcfqspi, 0x700);
260 mcfqspi_wr_qdlyr(mcfqspi, MCFQSPI_QDLYR_SPE);
261
262 do {
263 wait_event(mcfqspi->waitq, !mcfqspi_qdlyr_spe(mcfqspi));
264 mcfqspi_wr_qwr(mcfqspi, qwr);
265 mcfqspi_wr_qdlyr(mcfqspi, MCFQSPI_QDLYR_SPE);
266 if (rxbuf) {
267 mcfqspi_wr_qar(mcfqspi,
268 MCFQSPI_QAR_RXBUF + offset);
269 for (i = 0; i < 8; ++i)
270 *rxbuf++ = mcfqspi_rd_qdr(mcfqspi);
271 }
272 n = min(count, 8u);
273 if (txbuf) {
274 mcfqspi_wr_qar(mcfqspi,
275 MCFQSPI_QAR_TXBUF + offset);
276 for (i = 0; i < n; ++i)
277 mcfqspi_wr_qdr(mcfqspi, *txbuf++);
278 }
279 qwr = (offset ? 0x808 : 0x000) + ((n - 1) << 8);
280 offset ^= 8;
281 count -= n;
282 } while (count);
283 wait_event(mcfqspi->waitq, !mcfqspi_qdlyr_spe(mcfqspi));
284 mcfqspi_wr_qwr(mcfqspi, qwr);
285 mcfqspi_wr_qdlyr(mcfqspi, MCFQSPI_QDLYR_SPE);
286 if (rxbuf) {
287 mcfqspi_wr_qar(mcfqspi, MCFQSPI_QAR_RXBUF + offset);
288 for (i = 0; i < 8; ++i)
289 *rxbuf++ = mcfqspi_rd_qdr(mcfqspi);
290 offset ^= 8;
291 }
292 } else {
293 mcfqspi_wr_qwr(mcfqspi, (n - 1) << 8);
294 mcfqspi_wr_qdlyr(mcfqspi, MCFQSPI_QDLYR_SPE);
295 }
296 wait_event(mcfqspi->waitq, !mcfqspi_qdlyr_spe(mcfqspi));
297 if (rxbuf) {
298 mcfqspi_wr_qar(mcfqspi, MCFQSPI_QAR_RXBUF + offset);
299 for (i = 0; i < n; ++i)
300 *rxbuf++ = mcfqspi_rd_qdr(mcfqspi);
301 }
302}
303
304static void mcfqspi_work(struct work_struct *work)
305{
306 struct mcfqspi *mcfqspi = container_of(work, struct mcfqspi, work);
307 unsigned long flags;
308
309 spin_lock_irqsave(&mcfqspi->lock, flags);
310 while (!list_empty(&mcfqspi->msgq)) {
311 struct spi_message *msg;
312 struct spi_device *spi;
313 struct spi_transfer *xfer;
314 int status = 0;
315
316 msg = container_of(mcfqspi->msgq.next, struct spi_message,
317 queue);
318
319 list_del_init(&mcfqspi->msgq);
320 spin_unlock_irqrestore(&mcfqspi->lock, flags);
321
322 spi = msg->spi;
323
324 list_for_each_entry(xfer, &msg->transfers, transfer_list) {
325 bool cs_high = spi->mode & SPI_CS_HIGH;
326 u16 qmr = MCFQSPI_QMR_MSTR;
327
328 if (xfer->bits_per_word)
329 qmr |= xfer->bits_per_word << 10;
330 else
331 qmr |= spi->bits_per_word << 10;
332 if (spi->mode & SPI_CPHA)
333 qmr |= MCFQSPI_QMR_CPHA;
334 if (spi->mode & SPI_CPOL)
335 qmr |= MCFQSPI_QMR_CPOL;
336 if (xfer->speed_hz)
337 qmr |= mcfqspi_qmr_baud(xfer->speed_hz);
338 else
339 qmr |= mcfqspi_qmr_baud(spi->max_speed_hz);
340 mcfqspi_wr_qmr(mcfqspi, qmr);
341
342 mcfqspi_cs_select(mcfqspi, spi->chip_select, cs_high);
343
344 mcfqspi_wr_qir(mcfqspi, MCFQSPI_QIR_SPIFE);
345 if ((xfer->bits_per_word ? xfer->bits_per_word :
346 spi->bits_per_word) == 8)
347 mcfqspi_transfer_msg8(mcfqspi, xfer->len,
348 xfer->tx_buf,
349 xfer->rx_buf);
350 else
351 mcfqspi_transfer_msg16(mcfqspi, xfer->len / 2,
352 xfer->tx_buf,
353 xfer->rx_buf);
354 mcfqspi_wr_qir(mcfqspi, 0);
355
356 if (xfer->delay_usecs)
357 udelay(xfer->delay_usecs);
358 if (xfer->cs_change) {
359 if (!list_is_last(&xfer->transfer_list,
360 &msg->transfers))
361 mcfqspi_cs_deselect(mcfqspi,
362 spi->chip_select,
363 cs_high);
364 } else {
365 if (list_is_last(&xfer->transfer_list,
366 &msg->transfers))
367 mcfqspi_cs_deselect(mcfqspi,
368 spi->chip_select,
369 cs_high);
370 }
371 msg->actual_length += xfer->len;
372 }
373 msg->status = status;
374 msg->complete(msg->context);
375
376 spin_lock_irqsave(&mcfqspi->lock, flags);
377 }
378 spin_unlock_irqrestore(&mcfqspi->lock, flags);
379}
380
381static int mcfqspi_transfer(struct spi_device *spi, struct spi_message *msg)
382{
383 struct mcfqspi *mcfqspi;
384 struct spi_transfer *xfer;
385 unsigned long flags;
386
387 mcfqspi = spi_master_get_devdata(spi->master);
388
389 list_for_each_entry(xfer, &msg->transfers, transfer_list) {
390 if (xfer->bits_per_word && ((xfer->bits_per_word < 8)
391 || (xfer->bits_per_word > 16))) {
392 dev_dbg(&spi->dev,
393 "%d bits per word is not supported\n",
394 xfer->bits_per_word);
395 goto fail;
396 }
397 if (xfer->speed_hz) {
398 u32 real_speed = MCFQSPI_BUSCLK /
399 mcfqspi_qmr_baud(xfer->speed_hz);
400 if (real_speed != xfer->speed_hz)
401 dev_dbg(&spi->dev,
402 "using speed %d instead of %d\n",
403 real_speed, xfer->speed_hz);
404 }
405 }
406 msg->status = -EINPROGRESS;
407 msg->actual_length = 0;
408
409 spin_lock_irqsave(&mcfqspi->lock, flags);
410 list_add_tail(&msg->queue, &mcfqspi->msgq);
411 queue_work(mcfqspi->workq, &mcfqspi->work);
412 spin_unlock_irqrestore(&mcfqspi->lock, flags);
413
414 return 0;
415fail:
416 msg->status = -EINVAL;
417 return -EINVAL;
418}
419
420static int mcfqspi_setup(struct spi_device *spi)
421{
422 if ((spi->bits_per_word < 8) || (spi->bits_per_word > 16)) {
423 dev_dbg(&spi->dev, "%d bits per word is not supported\n",
424 spi->bits_per_word);
425 return -EINVAL;
426 }
427 if (spi->chip_select >= spi->master->num_chipselect) {
428 dev_dbg(&spi->dev, "%d chip select is out of range\n",
429 spi->chip_select);
430 return -EINVAL;
431 }
432
433 mcfqspi_cs_deselect(spi_master_get_devdata(spi->master),
434 spi->chip_select, spi->mode & SPI_CS_HIGH);
435
436 dev_dbg(&spi->dev,
437 "bits per word %d, chip select %d, speed %d KHz\n",
438 spi->bits_per_word, spi->chip_select,
439 (MCFQSPI_BUSCLK / mcfqspi_qmr_baud(spi->max_speed_hz))
440 / 1000);
441
442 return 0;
443}
444
445static int __devinit mcfqspi_probe(struct platform_device *pdev)
446{
447 struct spi_master *master;
448 struct mcfqspi *mcfqspi;
449 struct resource *res;
450 struct mcfqspi_platform_data *pdata;
451 int status;
452
453 master = spi_alloc_master(&pdev->dev, sizeof(*mcfqspi));
454 if (master == NULL) {
455 dev_dbg(&pdev->dev, "spi_alloc_master failed\n");
456 return -ENOMEM;
457 }
458
459 mcfqspi = spi_master_get_devdata(master);
460
461 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
462 if (!res) {
463 dev_dbg(&pdev->dev, "platform_get_resource failed\n");
464 status = -ENXIO;
465 goto fail0;
466 }
467
468 if (!request_mem_region(res->start, resource_size(res), pdev->name)) {
469 dev_dbg(&pdev->dev, "request_mem_region failed\n");
470 status = -EBUSY;
471 goto fail0;
472 }
473
474 mcfqspi->iobase = ioremap(res->start, resource_size(res));
475 if (!mcfqspi->iobase) {
476 dev_dbg(&pdev->dev, "ioremap failed\n");
477 status = -ENOMEM;
478 goto fail1;
479 }
480
481 mcfqspi->irq = platform_get_irq(pdev, 0);
482 if (mcfqspi->irq < 0) {
483 dev_dbg(&pdev->dev, "platform_get_irq failed\n");
484 status = -ENXIO;
485 goto fail2;
486 }
487
488 status = request_irq(mcfqspi->irq, mcfqspi_irq_handler, IRQF_DISABLED,
489 pdev->name, mcfqspi);
490 if (status) {
491 dev_dbg(&pdev->dev, "request_irq failed\n");
492 goto fail2;
493 }
494
495 mcfqspi->clk = clk_get(&pdev->dev, "qspi_clk");
496 if (IS_ERR(mcfqspi->clk)) {
497 dev_dbg(&pdev->dev, "clk_get failed\n");
498 status = PTR_ERR(mcfqspi->clk);
499 goto fail3;
500 }
501 clk_enable(mcfqspi->clk);
502
503 mcfqspi->workq = create_singlethread_workqueue(dev_name(master->dev.parent));
504 if (!mcfqspi->workq) {
505 dev_dbg(&pdev->dev, "create_workqueue failed\n");
506 status = -ENOMEM;
507 goto fail4;
508 }
509 INIT_WORK(&mcfqspi->work, mcfqspi_work);
510 spin_lock_init(&mcfqspi->lock);
511 INIT_LIST_HEAD(&mcfqspi->msgq);
512 init_waitqueue_head(&mcfqspi->waitq);
513
514 pdata = pdev->dev.platform_data;
515 if (!pdata) {
516 dev_dbg(&pdev->dev, "platform data is missing\n");
517 goto fail5;
518 }
519 master->bus_num = pdata->bus_num;
520 master->num_chipselect = pdata->num_chipselect;
521
522 mcfqspi->cs_control = pdata->cs_control;
523 status = mcfqspi_cs_setup(mcfqspi);
524 if (status) {
525 dev_dbg(&pdev->dev, "error initializing cs_control\n");
526 goto fail5;
527 }
528
529 master->mode_bits = SPI_CS_HIGH | SPI_CPOL | SPI_CPHA;
530 master->setup = mcfqspi_setup;
531 master->transfer = mcfqspi_transfer;
532
533 platform_set_drvdata(pdev, master);
534
535 status = spi_register_master(master);
536 if (status) {
537 dev_dbg(&pdev->dev, "spi_register_master failed\n");
538 goto fail6;
539 }
540 dev_info(&pdev->dev, "Coldfire QSPI bus driver\n");
541
542 return 0;
543
544fail6:
545 mcfqspi_cs_teardown(mcfqspi);
546fail5:
547 destroy_workqueue(mcfqspi->workq);
548fail4:
549 clk_disable(mcfqspi->clk);
550 clk_put(mcfqspi->clk);
551fail3:
552 free_irq(mcfqspi->irq, mcfqspi);
553fail2:
554 iounmap(mcfqspi->iobase);
555fail1:
556 release_mem_region(res->start, resource_size(res));
557fail0:
558 spi_master_put(master);
559
560 dev_dbg(&pdev->dev, "Coldfire QSPI probe failed\n");
561
562 return status;
563}
564
565static int __devexit mcfqspi_remove(struct platform_device *pdev)
566{
567 struct spi_master *master = platform_get_drvdata(pdev);
568 struct mcfqspi *mcfqspi = spi_master_get_devdata(master);
569 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
570
571 /* disable the hardware (set the baud rate to 0) */
572 mcfqspi_wr_qmr(mcfqspi, MCFQSPI_QMR_MSTR);
573
574 platform_set_drvdata(pdev, NULL);
575 mcfqspi_cs_teardown(mcfqspi);
576 destroy_workqueue(mcfqspi->workq);
577 clk_disable(mcfqspi->clk);
578 clk_put(mcfqspi->clk);
579 free_irq(mcfqspi->irq, mcfqspi);
580 iounmap(mcfqspi->iobase);
581 release_mem_region(res->start, resource_size(res));
582 spi_unregister_master(master);
583 spi_master_put(master);
584
585 return 0;
586}
587
588#ifdef CONFIG_PM
589
590static int mcfqspi_suspend(struct device *dev)
591{
592 struct mcfqspi *mcfqspi = platform_get_drvdata(to_platform_device(dev));
593
594 clk_disable(mcfqspi->clk);
595
596 return 0;
597}
598
599static int mcfqspi_resume(struct device *dev)
600{
601 struct mcfqspi *mcfqspi = platform_get_drvdata(to_platform_device(dev));
602
603 clk_enable(mcfqspi->clk);
604
605 return 0;
606}
607
608static struct dev_pm_ops mcfqspi_dev_pm_ops = {
609 .suspend = mcfqspi_suspend,
610 .resume = mcfqspi_resume,
611};
612
613#define MCFQSPI_DEV_PM_OPS (&mcfqspi_dev_pm_ops)
614#else
615#define MCFQSPI_DEV_PM_OPS NULL
616#endif
617
618static struct platform_driver mcfqspi_driver = {
619 .driver.name = DRIVER_NAME,
620 .driver.owner = THIS_MODULE,
621 .driver.pm = MCFQSPI_DEV_PM_OPS,
622 .remove = __devexit_p(mcfqspi_remove),
623};
624
625static int __init mcfqspi_init(void)
626{
627 return platform_driver_probe(&mcfqspi_driver, mcfqspi_probe);
628}
629module_init(mcfqspi_init);
630
631static void __exit mcfqspi_exit(void)
632{
633 platform_driver_unregister(&mcfqspi_driver);
634}
635module_exit(mcfqspi_exit);
636
637MODULE_AUTHOR("Steven King <sfking@fdwdc.com>");
638MODULE_DESCRIPTION("Coldfire QSPI Controller Driver");
639MODULE_LICENSE("GPL");
640MODULE_ALIAS("platform:" DRIVER_NAME);