aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/spi/mpc512x_psc_spi.c
diff options
context:
space:
mode:
authorAnatolij Gustschin <agust@denx.de>2010-04-30 09:21:27 -0400
committerGrant Likely <grant.likely@secretlab.ca>2010-05-25 02:23:17 -0400
commit6e27388f1bd60b55e0b1a83d14233e6c7ad33700 (patch)
treeaab88490ac722b354e90d72a4d0d040acc02f127 /drivers/spi/mpc512x_psc_spi.c
parent2da8cb6af5fe0d9e16b8a49399c8b7c6cfa94d5a (diff)
spi/mpc5121: Add SPI master driver for MPC5121 PSC
Signed-off-by: John Rigby <jcrigby@gmail.com> Signed-off-by: Anatolij Gustschin <agust@denx.de> Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
Diffstat (limited to 'drivers/spi/mpc512x_psc_spi.c')
-rw-r--r--drivers/spi/mpc512x_psc_spi.c576
1 files changed, 576 insertions, 0 deletions
diff --git a/drivers/spi/mpc512x_psc_spi.c b/drivers/spi/mpc512x_psc_spi.c
new file mode 100644
index 000000000000..28a126d2742b
--- /dev/null
+++ b/drivers/spi/mpc512x_psc_spi.c
@@ -0,0 +1,576 @@
1/*
2 * MPC512x PSC in SPI mode driver.
3 *
4 * Copyright (C) 2007,2008 Freescale Semiconductor Inc.
5 * Original port from 52xx driver:
6 * Hongjun Chen <hong-jun.chen@freescale.com>
7 *
8 * Fork of mpc52xx_psc_spi.c:
9 * Copyright (C) 2006 TOPTICA Photonics AG., Dragos Carp
10 *
11 * This program is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License as published by the
13 * Free Software Foundation; either version 2 of the License, or (at your
14 * option) any later version.
15 */
16
17#include <linux/module.h>
18#include <linux/kernel.h>
19#include <linux/init.h>
20#include <linux/errno.h>
21#include <linux/interrupt.h>
22#include <linux/of_platform.h>
23#include <linux/workqueue.h>
24#include <linux/completion.h>
25#include <linux/io.h>
26#include <linux/delay.h>
27#include <linux/clk.h>
28#include <linux/spi/spi.h>
29#include <linux/fsl_devices.h>
30#include <asm/mpc52xx_psc.h>
31
32struct mpc512x_psc_spi {
33 void (*cs_control)(struct spi_device *spi, bool on);
34 u32 sysclk;
35
36 /* driver internal data */
37 struct mpc52xx_psc __iomem *psc;
38 struct mpc512x_psc_fifo __iomem *fifo;
39 unsigned int irq;
40 u8 bits_per_word;
41 u8 busy;
42 u32 mclk;
43 u8 eofbyte;
44
45 struct workqueue_struct *workqueue;
46 struct work_struct work;
47
48 struct list_head queue;
49 spinlock_t lock; /* Message queue lock */
50
51 struct completion done;
52};
53
54/* controller state */
55struct mpc512x_psc_spi_cs {
56 int bits_per_word;
57 int speed_hz;
58};
59
60/* set clock freq, clock ramp, bits per work
61 * if t is NULL then reset the values to the default values
62 */
63static int mpc512x_psc_spi_transfer_setup(struct spi_device *spi,
64 struct spi_transfer *t)
65{
66 struct mpc512x_psc_spi_cs *cs = spi->controller_state;
67
68 cs->speed_hz = (t && t->speed_hz)
69 ? t->speed_hz : spi->max_speed_hz;
70 cs->bits_per_word = (t && t->bits_per_word)
71 ? t->bits_per_word : spi->bits_per_word;
72 cs->bits_per_word = ((cs->bits_per_word + 7) / 8) * 8;
73 return 0;
74}
75
76static void mpc512x_psc_spi_activate_cs(struct spi_device *spi)
77{
78 struct mpc512x_psc_spi_cs *cs = spi->controller_state;
79 struct mpc512x_psc_spi *mps = spi_master_get_devdata(spi->master);
80 struct mpc52xx_psc __iomem *psc = mps->psc;
81 u32 sicr;
82 u32 ccr;
83 u16 bclkdiv;
84
85 sicr = in_be32(&psc->sicr);
86
87 /* Set clock phase and polarity */
88 if (spi->mode & SPI_CPHA)
89 sicr |= 0x00001000;
90 else
91 sicr &= ~0x00001000;
92
93 if (spi->mode & SPI_CPOL)
94 sicr |= 0x00002000;
95 else
96 sicr &= ~0x00002000;
97
98 if (spi->mode & SPI_LSB_FIRST)
99 sicr |= 0x10000000;
100 else
101 sicr &= ~0x10000000;
102 out_be32(&psc->sicr, sicr);
103
104 ccr = in_be32(&psc->ccr);
105 ccr &= 0xFF000000;
106 if (cs->speed_hz)
107 bclkdiv = (mps->mclk / cs->speed_hz) - 1;
108 else
109 bclkdiv = (mps->mclk / 1000000) - 1; /* default 1MHz */
110
111 ccr |= (((bclkdiv & 0xff) << 16) | (((bclkdiv >> 8) & 0xff) << 8));
112 out_be32(&psc->ccr, ccr);
113 mps->bits_per_word = cs->bits_per_word;
114
115 if (mps->cs_control)
116 mps->cs_control(spi, (spi->mode & SPI_CS_HIGH) ? 1 : 0);
117}
118
119static void mpc512x_psc_spi_deactivate_cs(struct spi_device *spi)
120{
121 struct mpc512x_psc_spi *mps = spi_master_get_devdata(spi->master);
122
123 if (mps->cs_control)
124 mps->cs_control(spi, (spi->mode & SPI_CS_HIGH) ? 0 : 1);
125
126}
127
128/* extract and scale size field in txsz or rxsz */
129#define MPC512x_PSC_FIFO_SZ(sz) ((sz & 0x7ff) << 2);
130
131#define EOFBYTE 1
132
133static int mpc512x_psc_spi_transfer_rxtx(struct spi_device *spi,
134 struct spi_transfer *t)
135{
136 struct mpc512x_psc_spi *mps = spi_master_get_devdata(spi->master);
137 struct mpc52xx_psc __iomem *psc = mps->psc;
138 struct mpc512x_psc_fifo __iomem *fifo = mps->fifo;
139 size_t len = t->len;
140 u8 *tx_buf = (u8 *)t->tx_buf;
141 u8 *rx_buf = (u8 *)t->rx_buf;
142
143 if (!tx_buf && !rx_buf && t->len)
144 return -EINVAL;
145
146 /* Zero MR2 */
147 in_8(&psc->mode);
148 out_8(&psc->mode, 0x0);
149
150 while (len) {
151 int count;
152 int i;
153 u8 data;
154 size_t fifosz;
155 int rxcount;
156
157 /*
158 * The number of bytes that can be sent at a time
159 * depends on the fifo size.
160 */
161 fifosz = MPC512x_PSC_FIFO_SZ(in_be32(&fifo->txsz));
162 count = min(fifosz, len);
163
164 for (i = count; i > 0; i--) {
165 data = tx_buf ? *tx_buf++ : 0;
166 if (len == EOFBYTE)
167 setbits32(&fifo->txcmd, MPC512x_PSC_FIFO_EOF);
168 out_8(&fifo->txdata_8, data);
169 len--;
170 }
171
172 INIT_COMPLETION(mps->done);
173
174 /* interrupt on tx fifo empty */
175 out_be32(&fifo->txisr, MPC512x_PSC_FIFO_EMPTY);
176 out_be32(&fifo->tximr, MPC512x_PSC_FIFO_EMPTY);
177
178 /* enable transmiter/receiver */
179 out_8(&psc->command,
180 MPC52xx_PSC_TX_ENABLE | MPC52xx_PSC_RX_ENABLE);
181
182 wait_for_completion(&mps->done);
183
184 mdelay(1);
185
186 /* rx fifo should have count bytes in it */
187 rxcount = in_be32(&fifo->rxcnt);
188 if (rxcount != count)
189 mdelay(1);
190
191 rxcount = in_be32(&fifo->rxcnt);
192 if (rxcount != count) {
193 dev_warn(&spi->dev, "expected %d bytes in rx fifo "
194 "but got %d\n", count, rxcount);
195 }
196
197 rxcount = min(rxcount, count);
198 for (i = rxcount; i > 0; i--) {
199 data = in_8(&fifo->rxdata_8);
200 if (rx_buf)
201 *rx_buf++ = data;
202 }
203 while (in_be32(&fifo->rxcnt)) {
204 in_8(&fifo->rxdata_8);
205 }
206
207 out_8(&psc->command,
208 MPC52xx_PSC_TX_DISABLE | MPC52xx_PSC_RX_DISABLE);
209 }
210 /* disable transmiter/receiver and fifo interrupt */
211 out_8(&psc->command, MPC52xx_PSC_TX_DISABLE | MPC52xx_PSC_RX_DISABLE);
212 out_be32(&fifo->tximr, 0);
213 return 0;
214}
215
216static void mpc512x_psc_spi_work(struct work_struct *work)
217{
218 struct mpc512x_psc_spi *mps = container_of(work,
219 struct mpc512x_psc_spi,
220 work);
221
222 spin_lock_irq(&mps->lock);
223 mps->busy = 1;
224 while (!list_empty(&mps->queue)) {
225 struct spi_message *m;
226 struct spi_device *spi;
227 struct spi_transfer *t = NULL;
228 unsigned cs_change;
229 int status;
230
231 m = container_of(mps->queue.next, struct spi_message, queue);
232 list_del_init(&m->queue);
233 spin_unlock_irq(&mps->lock);
234
235 spi = m->spi;
236 cs_change = 1;
237 status = 0;
238 list_for_each_entry(t, &m->transfers, transfer_list) {
239 if (t->bits_per_word || t->speed_hz) {
240 status = mpc512x_psc_spi_transfer_setup(spi, t);
241 if (status < 0)
242 break;
243 }
244
245 if (cs_change)
246 mpc512x_psc_spi_activate_cs(spi);
247 cs_change = t->cs_change;
248
249 status = mpc512x_psc_spi_transfer_rxtx(spi, t);
250 if (status)
251 break;
252 m->actual_length += t->len;
253
254 if (t->delay_usecs)
255 udelay(t->delay_usecs);
256
257 if (cs_change)
258 mpc512x_psc_spi_deactivate_cs(spi);
259 }
260
261 m->status = status;
262 m->complete(m->context);
263
264 if (status || !cs_change)
265 mpc512x_psc_spi_deactivate_cs(spi);
266
267 mpc512x_psc_spi_transfer_setup(spi, NULL);
268
269 spin_lock_irq(&mps->lock);
270 }
271 mps->busy = 0;
272 spin_unlock_irq(&mps->lock);
273}
274
275static int mpc512x_psc_spi_setup(struct spi_device *spi)
276{
277 struct mpc512x_psc_spi *mps = spi_master_get_devdata(spi->master);
278 struct mpc512x_psc_spi_cs *cs = spi->controller_state;
279 unsigned long flags;
280
281 if (spi->bits_per_word % 8)
282 return -EINVAL;
283
284 if (!cs) {
285 cs = kzalloc(sizeof *cs, GFP_KERNEL);
286 if (!cs)
287 return -ENOMEM;
288 spi->controller_state = cs;
289 }
290
291 cs->bits_per_word = spi->bits_per_word;
292 cs->speed_hz = spi->max_speed_hz;
293
294 spin_lock_irqsave(&mps->lock, flags);
295 if (!mps->busy)
296 mpc512x_psc_spi_deactivate_cs(spi);
297 spin_unlock_irqrestore(&mps->lock, flags);
298
299 return 0;
300}
301
302static int mpc512x_psc_spi_transfer(struct spi_device *spi,
303 struct spi_message *m)
304{
305 struct mpc512x_psc_spi *mps = spi_master_get_devdata(spi->master);
306 unsigned long flags;
307
308 m->actual_length = 0;
309 m->status = -EINPROGRESS;
310
311 spin_lock_irqsave(&mps->lock, flags);
312 list_add_tail(&m->queue, &mps->queue);
313 queue_work(mps->workqueue, &mps->work);
314 spin_unlock_irqrestore(&mps->lock, flags);
315
316 return 0;
317}
318
319static void mpc512x_psc_spi_cleanup(struct spi_device *spi)
320{
321 kfree(spi->controller_state);
322}
323
324static int mpc512x_psc_spi_port_config(struct spi_master *master,
325 struct mpc512x_psc_spi *mps)
326{
327 struct mpc52xx_psc __iomem *psc = mps->psc;
328 struct mpc512x_psc_fifo __iomem *fifo = mps->fifo;
329 struct clk *spiclk;
330 int ret = 0;
331 char name[32];
332 u32 sicr;
333 u32 ccr;
334 u16 bclkdiv;
335
336 sprintf(name, "psc%d_mclk", master->bus_num);
337 spiclk = clk_get(&master->dev, name);
338 clk_enable(spiclk);
339 mps->mclk = clk_get_rate(spiclk);
340 clk_put(spiclk);
341
342 /* Reset the PSC into a known state */
343 out_8(&psc->command, MPC52xx_PSC_RST_RX);
344 out_8(&psc->command, MPC52xx_PSC_RST_TX);
345 out_8(&psc->command, MPC52xx_PSC_TX_DISABLE | MPC52xx_PSC_RX_DISABLE);
346
347 /* Disable psc interrupts all useful interrupts are in fifo */
348 out_be16(&psc->isr_imr.imr, 0);
349
350 /* Disable fifo interrupts, will be enabled later */
351 out_be32(&fifo->tximr, 0);
352 out_be32(&fifo->rximr, 0);
353
354 /* Setup fifo slice address and size */
355 /*out_be32(&fifo->txsz, 0x0fe00004);*/
356 /*out_be32(&fifo->rxsz, 0x0ff00004);*/
357
358 sicr = 0x01000000 | /* SIM = 0001 -- 8 bit */
359 0x00800000 | /* GenClk = 1 -- internal clk */
360 0x00008000 | /* SPI = 1 */
361 0x00004000 | /* MSTR = 1 -- SPI master */
362 0x00000800; /* UseEOF = 1 -- SS low until EOF */
363
364 out_be32(&psc->sicr, sicr);
365
366 ccr = in_be32(&psc->ccr);
367 ccr &= 0xFF000000;
368 bclkdiv = (mps->mclk / 1000000) - 1; /* default 1MHz */
369 ccr |= (((bclkdiv & 0xff) << 16) | (((bclkdiv >> 8) & 0xff) << 8));
370 out_be32(&psc->ccr, ccr);
371
372 /* Set 2ms DTL delay */
373 out_8(&psc->ctur, 0x00);
374 out_8(&psc->ctlr, 0x82);
375
376 /* we don't use the alarms */
377 out_be32(&fifo->rxalarm, 0xfff);
378 out_be32(&fifo->txalarm, 0);
379
380 /* Enable FIFO slices for Rx/Tx */
381 out_be32(&fifo->rxcmd,
382 MPC512x_PSC_FIFO_ENABLE_SLICE | MPC512x_PSC_FIFO_ENABLE_DMA);
383 out_be32(&fifo->txcmd,
384 MPC512x_PSC_FIFO_ENABLE_SLICE | MPC512x_PSC_FIFO_ENABLE_DMA);
385
386 mps->bits_per_word = 8;
387
388 return ret;
389}
390
391static irqreturn_t mpc512x_psc_spi_isr(int irq, void *dev_id)
392{
393 struct mpc512x_psc_spi *mps = (struct mpc512x_psc_spi *)dev_id;
394 struct mpc512x_psc_fifo __iomem *fifo = mps->fifo;
395
396 /* clear interrupt and wake up the work queue */
397 if (in_be32(&fifo->txisr) &
398 in_be32(&fifo->tximr) & MPC512x_PSC_FIFO_EMPTY) {
399 out_be32(&fifo->txisr, MPC512x_PSC_FIFO_EMPTY);
400 out_be32(&fifo->tximr, 0);
401 complete(&mps->done);
402 return IRQ_HANDLED;
403 }
404 return IRQ_NONE;
405}
406
407/* bus_num is used only for the case dev->platform_data == NULL */
408static int __init mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr,
409 u32 size, unsigned int irq,
410 s16 bus_num)
411{
412 struct fsl_spi_platform_data *pdata = dev->platform_data;
413 struct mpc512x_psc_spi *mps;
414 struct spi_master *master;
415 int ret;
416 void *tempp;
417
418 master = spi_alloc_master(dev, sizeof *mps);
419 if (master == NULL)
420 return -ENOMEM;
421
422 dev_set_drvdata(dev, master);
423 mps = spi_master_get_devdata(master);
424 mps->irq = irq;
425
426 if (pdata == NULL) {
427 dev_err(dev, "probe called without platform data, no "
428 "cs_control function will be called\n");
429 mps->cs_control = NULL;
430 mps->sysclk = 0;
431 master->bus_num = bus_num;
432 master->num_chipselect = 255;
433 } else {
434 mps->cs_control = pdata->cs_control;
435 mps->sysclk = pdata->sysclk;
436 master->bus_num = pdata->bus_num;
437 master->num_chipselect = pdata->max_chipselect;
438 }
439
440 master->setup = mpc512x_psc_spi_setup;
441 master->transfer = mpc512x_psc_spi_transfer;
442 master->cleanup = mpc512x_psc_spi_cleanup;
443
444 tempp = ioremap(regaddr, size);
445 if (!tempp) {
446 dev_err(dev, "could not ioremap I/O port range\n");
447 ret = -EFAULT;
448 goto free_master;
449 }
450 mps->psc = tempp;
451 mps->fifo =
452 (struct mpc512x_psc_fifo *)(tempp + sizeof(struct mpc52xx_psc));
453
454 ret = request_irq(mps->irq, mpc512x_psc_spi_isr, IRQF_SHARED,
455 "mpc512x-psc-spi", mps);
456 if (ret)
457 goto free_master;
458
459 ret = mpc512x_psc_spi_port_config(master, mps);
460 if (ret < 0)
461 goto free_irq;
462
463 spin_lock_init(&mps->lock);
464 init_completion(&mps->done);
465 INIT_WORK(&mps->work, mpc512x_psc_spi_work);
466 INIT_LIST_HEAD(&mps->queue);
467
468 mps->workqueue =
469 create_singlethread_workqueue(dev_name(master->dev.parent));
470 if (mps->workqueue == NULL) {
471 ret = -EBUSY;
472 goto free_irq;
473 }
474
475 ret = spi_register_master(master);
476 if (ret < 0)
477 goto unreg_master;
478
479 return ret;
480
481unreg_master:
482 destroy_workqueue(mps->workqueue);
483free_irq:
484 free_irq(mps->irq, mps);
485free_master:
486 if (mps->psc)
487 iounmap(mps->psc);
488 spi_master_put(master);
489
490 return ret;
491}
492
493static int __exit mpc512x_psc_spi_do_remove(struct device *dev)
494{
495 struct spi_master *master = dev_get_drvdata(dev);
496 struct mpc512x_psc_spi *mps = spi_master_get_devdata(master);
497
498 flush_workqueue(mps->workqueue);
499 destroy_workqueue(mps->workqueue);
500 spi_unregister_master(master);
501 free_irq(mps->irq, mps);
502 if (mps->psc)
503 iounmap(mps->psc);
504
505 return 0;
506}
507
508static int __init mpc512x_psc_spi_of_probe(struct of_device *op,
509 const struct of_device_id *match)
510{
511 const u32 *regaddr_p;
512 u64 regaddr64, size64;
513 s16 id = -1;
514
515 regaddr_p = of_get_address(op->node, 0, &size64, NULL);
516 if (!regaddr_p) {
517 dev_err(&op->dev, "Invalid PSC address\n");
518 return -EINVAL;
519 }
520 regaddr64 = of_translate_address(op->node, regaddr_p);
521
522 /* get PSC id (0..11, used by port_config) */
523 if (op->dev.platform_data == NULL) {
524 const u32 *psc_nump;
525
526 psc_nump = of_get_property(op->node, "cell-index", NULL);
527 if (!psc_nump || *psc_nump > 11) {
528 dev_err(&op->dev, "mpc512x_psc_spi: Device node %s "
529 "has invalid cell-index property\n",
530 op->node->full_name);
531 return -EINVAL;
532 }
533 id = *psc_nump;
534 }
535
536 return mpc512x_psc_spi_do_probe(&op->dev, (u32) regaddr64, (u32) size64,
537 irq_of_parse_and_map(op->node, 0), id);
538}
539
540static int __exit mpc512x_psc_spi_of_remove(struct of_device *op)
541{
542 return mpc512x_psc_spi_do_remove(&op->dev);
543}
544
545static struct of_device_id mpc512x_psc_spi_of_match[] = {
546 { .compatible = "fsl,mpc5121-psc-spi", },
547 {},
548};
549
550MODULE_DEVICE_TABLE(of, mpc512x_psc_spi_of_match);
551
552static struct of_platform_driver mpc512x_psc_spi_of_driver = {
553 .match_table = mpc512x_psc_spi_of_match,
554 .probe = mpc512x_psc_spi_of_probe,
555 .remove = __exit_p(mpc512x_psc_spi_of_remove),
556 .driver = {
557 .name = "mpc512x-psc-spi",
558 .owner = THIS_MODULE,
559 },
560};
561
562static int __init mpc512x_psc_spi_init(void)
563{
564 return of_register_platform_driver(&mpc512x_psc_spi_of_driver);
565}
566module_init(mpc512x_psc_spi_init);
567
568static void __exit mpc512x_psc_spi_exit(void)
569{
570 of_unregister_platform_driver(&mpc512x_psc_spi_of_driver);
571}
572module_exit(mpc512x_psc_spi_exit);
573
574MODULE_AUTHOR("John Rigby");
575MODULE_DESCRIPTION("MPC512x PSC SPI Driver");
576MODULE_LICENSE("GPL");