aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorDragos Carp <dragos.carp@toptica.com>2007-05-11 01:22:52 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-05-11 11:29:35 -0400
commit00b8fd236764e3d5bc1d30dc65e256e283de4c3d (patch)
tree014b5a7a6f194915646713d1324cc02459a01f40 /drivers
parent0ea971801625184a91a6d80ea85e53875caa0bf5 (diff)
MPC52xx PSC SPI master driver
SPI master driver for MPC52xx using its Programmable Serial Controller. Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> Signed-off-by: Dragos Carp <dragos.carp@toptica.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/spi/Kconfig7
-rw-r--r--drivers/spi/Makefile1
-rw-r--r--drivers/spi/mpc52xx_psc_spi.c654
3 files changed, 662 insertions, 0 deletions
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 7c9d37f651e3..5e3f748f2693 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -107,6 +107,13 @@ config SPI_IMX
107 This enables using the Freescale iMX SPI controller in master 107 This enables using the Freescale iMX SPI controller in master
108 mode. 108 mode.
109 109
110config SPI_MPC52xx_PSC
111 tristate "Freescale MPC52xx PSC SPI controller"
112 depends on SPI_MASTER && PPC_MPC52xx && EXPERIMENTAL
113 help
114 This enables using the Freescale MPC52xx Programmable Serial
115 Controller in master SPI mode.
116
110config SPI_MPC83xx 117config SPI_MPC83xx
111 tristate "Freescale MPC83xx SPI controller" 118 tristate "Freescale MPC83xx SPI controller"
112 depends on SPI_MASTER && PPC_83xx && EXPERIMENTAL 119 depends on SPI_MASTER && PPC_83xx && EXPERIMENTAL
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 624b6363f490..5788d867de84 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -19,6 +19,7 @@ obj-$(CONFIG_SPI_BUTTERFLY) += spi_butterfly.o
19obj-$(CONFIG_SPI_IMX) += spi_imx.o 19obj-$(CONFIG_SPI_IMX) += spi_imx.o
20obj-$(CONFIG_SPI_PXA2XX) += pxa2xx_spi.o 20obj-$(CONFIG_SPI_PXA2XX) += pxa2xx_spi.o
21obj-$(CONFIG_SPI_OMAP_UWIRE) += omap_uwire.o 21obj-$(CONFIG_SPI_OMAP_UWIRE) += omap_uwire.o
22obj-$(CONFIG_SPI_MPC52xx_PSC) += mpc52xx_psc_spi.o
22obj-$(CONFIG_SPI_MPC83xx) += spi_mpc83xx.o 23obj-$(CONFIG_SPI_MPC83xx) += spi_mpc83xx.o
23obj-$(CONFIG_SPI_S3C24XX_GPIO) += spi_s3c24xx_gpio.o 24obj-$(CONFIG_SPI_S3C24XX_GPIO) += spi_s3c24xx_gpio.o
24obj-$(CONFIG_SPI_S3C24XX) += spi_s3c24xx.o 25obj-$(CONFIG_SPI_S3C24XX) += spi_s3c24xx.o
diff --git a/drivers/spi/mpc52xx_psc_spi.c b/drivers/spi/mpc52xx_psc_spi.c
new file mode 100644
index 000000000000..052359fc41ee
--- /dev/null
+++ b/drivers/spi/mpc52xx_psc_spi.c
@@ -0,0 +1,654 @@
1/*
2 * MPC52xx SPC in SPI mode driver.
3 *
4 * Maintainer: Dragos Carp
5 *
6 * Copyright (C) 2006 TOPTICA Photonics AG.
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 */
13
14#include <linux/module.h>
15#include <linux/init.h>
16#include <linux/errno.h>
17#include <linux/interrupt.h>
18
19#if defined(CONFIG_PPC_MERGE)
20#include <asm/of_platform.h>
21#else
22#include <linux/platform_device.h>
23#endif
24
25#include <linux/workqueue.h>
26#include <linux/completion.h>
27#include <linux/io.h>
28#include <linux/delay.h>
29#include <linux/spi/spi.h>
30#include <linux/fsl_devices.h>
31
32#include <asm/mpc52xx.h>
33#include <asm/mpc52xx_psc.h>
34
35#define MCLK 20000000 /* PSC port MClk in hz */
36
37struct mpc52xx_psc_spi {
38 /* fsl_spi_platform data */
39 void (*activate_cs)(u8, u8);
40 void (*deactivate_cs)(u8, u8);
41 u32 sysclk;
42
43 /* driver internal data */
44 struct mpc52xx_psc __iomem *psc;
45 unsigned int irq;
46 u8 bits_per_word;
47 u8 busy;
48
49 struct workqueue_struct *workqueue;
50 struct work_struct work;
51
52 struct list_head queue;
53 spinlock_t lock;
54
55 struct completion done;
56};
57
58/* controller state */
59struct mpc52xx_psc_spi_cs {
60 int bits_per_word;
61 int speed_hz;
62};
63
64/* set clock freq, clock ramp, bits per work
65 * if t is NULL then reset the values to the default values
66 */
67static int mpc52xx_psc_spi_transfer_setup(struct spi_device *spi,
68 struct spi_transfer *t)
69{
70 struct mpc52xx_psc_spi_cs *cs = spi->controller_state;
71
72 cs->speed_hz = (t && t->speed_hz)
73 ? t->speed_hz : spi->max_speed_hz;
74 cs->bits_per_word = (t && t->bits_per_word)
75 ? t->bits_per_word : spi->bits_per_word;
76 cs->bits_per_word = ((cs->bits_per_word + 7) / 8) * 8;
77 return 0;
78}
79
80static void mpc52xx_psc_spi_activate_cs(struct spi_device *spi)
81{
82 struct mpc52xx_psc_spi_cs *cs = spi->controller_state;
83 struct mpc52xx_psc_spi *mps = spi_master_get_devdata(spi->master);
84 struct mpc52xx_psc __iomem *psc = mps->psc;
85 u32 sicr;
86 u16 ccr;
87
88 sicr = in_be32(&psc->sicr);
89
90 /* Set clock phase and polarity */
91 if (spi->mode & SPI_CPHA)
92 sicr |= 0x00001000;
93 else
94 sicr &= ~0x00001000;
95 if (spi->mode & SPI_CPOL)
96 sicr |= 0x00002000;
97 else
98 sicr &= ~0x00002000;
99
100 if (spi->mode & SPI_LSB_FIRST)
101 sicr |= 0x10000000;
102 else
103 sicr &= ~0x10000000;
104 out_be32(&psc->sicr, sicr);
105
106 /* Set clock frequency and bits per word
107 * Because psc->ccr is defined as 16bit register instead of 32bit
108 * just set the lower byte of BitClkDiv
109 */
110 ccr = in_be16(&psc->ccr);
111 ccr &= 0xFF00;
112 if (cs->speed_hz)
113 ccr |= (MCLK / cs->speed_hz - 1) & 0xFF;
114 else /* by default SPI Clk 1MHz */
115 ccr |= (MCLK / 1000000 - 1) & 0xFF;
116 out_be16(&psc->ccr, ccr);
117 mps->bits_per_word = cs->bits_per_word;
118
119 if (mps->activate_cs)
120 mps->activate_cs(spi->chip_select,
121 (spi->mode & SPI_CS_HIGH) ? 1 : 0);
122}
123
124static void mpc52xx_psc_spi_deactivate_cs(struct spi_device *spi)
125{
126 struct mpc52xx_psc_spi *mps = spi_master_get_devdata(spi->master);
127
128 if (mps->deactivate_cs)
129 mps->deactivate_cs(spi->chip_select,
130 (spi->mode & SPI_CS_HIGH) ? 1 : 0);
131}
132
133#define MPC52xx_PSC_BUFSIZE (MPC52xx_PSC_RFNUM_MASK + 1)
134/* wake up when 80% fifo full */
135#define MPC52xx_PSC_RFALARM (MPC52xx_PSC_BUFSIZE * 20 / 100)
136
137static int mpc52xx_psc_spi_transfer_rxtx(struct spi_device *spi,
138 struct spi_transfer *t)
139{
140 struct mpc52xx_psc_spi *mps = spi_master_get_devdata(spi->master);
141 struct mpc52xx_psc __iomem *psc = mps->psc;
142 unsigned rb = 0; /* number of bytes receieved */
143 unsigned sb = 0; /* number of bytes sent */
144 unsigned char *rx_buf = (unsigned char *)t->rx_buf;
145 unsigned char *tx_buf = (unsigned char *)t->tx_buf;
146 unsigned rfalarm;
147 unsigned send_at_once = MPC52xx_PSC_BUFSIZE;
148 unsigned recv_at_once;
149 unsigned bpw = mps->bits_per_word / 8;
150
151 if (!t->tx_buf && !t->rx_buf && t->len)
152 return -EINVAL;
153
154 /* enable transmiter/receiver */
155 out_8(&psc->command, MPC52xx_PSC_TX_ENABLE | MPC52xx_PSC_RX_ENABLE);
156 while (rb < t->len) {
157 if (t->len - rb > MPC52xx_PSC_BUFSIZE) {
158 rfalarm = MPC52xx_PSC_RFALARM;
159 } else {
160 send_at_once = t->len - sb;
161 rfalarm = MPC52xx_PSC_BUFSIZE - (t->len - rb);
162 }
163
164 dev_dbg(&spi->dev, "send %d bytes...\n", send_at_once);
165 if (tx_buf) {
166 for (; send_at_once; sb++, send_at_once--) {
167 /* set EOF flag */
168 if (mps->bits_per_word
169 && (sb + 1) % bpw == 0)
170 out_8(&psc->ircr2, 0x01);
171 out_8(&psc->mpc52xx_psc_buffer_8, tx_buf[sb]);
172 }
173 } else {
174 for (; send_at_once; sb++, send_at_once--) {
175 /* set EOF flag */
176 if (mps->bits_per_word
177 && ((sb + 1) % bpw) == 0)
178 out_8(&psc->ircr2, 0x01);
179 out_8(&psc->mpc52xx_psc_buffer_8, 0);
180 }
181 }
182
183
184 /* enable interupts and wait for wake up
185 * if just one byte is expected the Rx FIFO genererates no
186 * FFULL interrupt, so activate the RxRDY interrupt
187 */
188 out_8(&psc->command, MPC52xx_PSC_SEL_MODE_REG_1);
189 if (t->len - rb == 1) {
190 out_8(&psc->mode, 0);
191 } else {
192 out_8(&psc->mode, MPC52xx_PSC_MODE_FFULL);
193 out_be16(&psc->rfalarm, rfalarm);
194 }
195 out_be16(&psc->mpc52xx_psc_imr, MPC52xx_PSC_IMR_RXRDY);
196 wait_for_completion(&mps->done);
197 recv_at_once = in_be16(&psc->rfnum);
198 dev_dbg(&spi->dev, "%d bytes received\n", recv_at_once);
199
200 send_at_once = recv_at_once;
201 if (rx_buf) {
202 for (; recv_at_once; rb++, recv_at_once--)
203 rx_buf[rb] = in_8(&psc->mpc52xx_psc_buffer_8);
204 } else {
205 for (; recv_at_once; rb++, recv_at_once--)
206 in_8(&psc->mpc52xx_psc_buffer_8);
207 }
208 }
209 /* disable transmiter/receiver */
210 out_8(&psc->command, MPC52xx_PSC_TX_DISABLE | MPC52xx_PSC_RX_DISABLE);
211
212 return 0;
213}
214
215static void mpc52xx_psc_spi_work(struct work_struct *work)
216{
217 struct mpc52xx_psc_spi *mps =
218 container_of(work, struct mpc52xx_psc_spi, work);
219
220 spin_lock_irq(&mps->lock);
221 mps->busy = 1;
222 while (!list_empty(&mps->queue)) {
223 struct spi_message *m;
224 struct spi_device *spi;
225 struct spi_transfer *t = NULL;
226 unsigned cs_change;
227 int status;
228
229 m = container_of(mps->queue.next, struct spi_message, queue);
230 list_del_init(&m->queue);
231 spin_unlock_irq(&mps->lock);
232
233 spi = m->spi;
234 cs_change = 1;
235 status = 0;
236 list_for_each_entry (t, &m->transfers, transfer_list) {
237 if (t->bits_per_word || t->speed_hz) {
238 status = mpc52xx_psc_spi_transfer_setup(spi, t);
239 if (status < 0)
240 break;
241 }
242
243 if (cs_change)
244 mpc52xx_psc_spi_activate_cs(spi);
245 cs_change = t->cs_change;
246
247 status = mpc52xx_psc_spi_transfer_rxtx(spi, t);
248 if (status)
249 break;
250 m->actual_length += t->len;
251
252 if (t->delay_usecs)
253 udelay(t->delay_usecs);
254
255 if (cs_change)
256 mpc52xx_psc_spi_deactivate_cs(spi);
257 }
258
259 m->status = status;
260 m->complete(m->context);
261
262 if (status || !cs_change)
263 mpc52xx_psc_spi_deactivate_cs(spi);
264
265 mpc52xx_psc_spi_transfer_setup(spi, NULL);
266
267 spin_lock_irq(&mps->lock);
268 }
269 mps->busy = 0;
270 spin_unlock_irq(&mps->lock);
271}
272
273static int mpc52xx_psc_spi_setup(struct spi_device *spi)
274{
275 struct mpc52xx_psc_spi *mps = spi_master_get_devdata(spi->master);
276 struct mpc52xx_psc_spi_cs *cs = spi->controller_state;
277 unsigned long flags;
278
279 if (spi->bits_per_word%8)
280 return -EINVAL;
281
282 if (!cs) {
283 cs = kzalloc(sizeof *cs, GFP_KERNEL);
284 if (!cs)
285 return -ENOMEM;
286 spi->controller_state = cs;
287 }
288
289 cs->bits_per_word = spi->bits_per_word;
290 cs->speed_hz = spi->max_speed_hz;
291
292 spin_lock_irqsave(&mps->lock, flags);
293 if (!mps->busy)
294 mpc52xx_psc_spi_deactivate_cs(spi);
295 spin_unlock_irqrestore(&mps->lock, flags);
296
297 return 0;
298}
299
300static int mpc52xx_psc_spi_transfer(struct spi_device *spi,
301 struct spi_message *m)
302{
303 struct mpc52xx_psc_spi *mps = spi_master_get_devdata(spi->master);
304 unsigned long flags;
305
306 m->actual_length = 0;
307 m->status = -EINPROGRESS;
308
309 spin_lock_irqsave(&mps->lock, flags);
310 list_add_tail(&m->queue, &mps->queue);
311 queue_work(mps->workqueue, &mps->work);
312 spin_unlock_irqrestore(&mps->lock, flags);
313
314 return 0;
315}
316
317static void mpc52xx_psc_spi_cleanup(struct spi_device *spi)
318{
319 kfree(spi->controller_state);
320}
321
322static int mpc52xx_psc_spi_port_config(int psc_id, struct mpc52xx_psc_spi *mps)
323{
324 struct mpc52xx_cdm __iomem *cdm;
325 struct mpc52xx_gpio __iomem *gpio;
326 struct mpc52xx_psc __iomem *psc = mps->psc;
327 u32 ul;
328 u32 mclken_div;
329 int ret = 0;
330
331#if defined(CONFIG_PPC_MERGE)
332 cdm = mpc52xx_find_and_map("mpc52xx-cdm");
333 gpio = mpc52xx_find_and_map("mpc52xx-gpio");
334#else
335 cdm = ioremap(MPC52xx_PA(MPC52xx_CDM_OFFSET), MPC52xx_CDM_SIZE);
336 gpio = ioremap(MPC52xx_PA(MPC52xx_GPIO_OFFSET), MPC52xx_GPIO_SIZE);
337#endif
338 if (!cdm || !gpio) {
339 printk(KERN_ERR "Error mapping CDM/GPIO\n");
340 ret = -EFAULT;
341 goto unmap_regs;
342 }
343
344 /* default sysclk is 512MHz */
345 mclken_div = 0x8000 |
346 (((mps->sysclk ? mps->sysclk : 512000000) / MCLK) & 0x1FF);
347
348 switch (psc_id) {
349 case 1:
350 ul = in_be32(&gpio->port_config);
351 ul &= 0xFFFFFFF8;
352 ul |= 0x00000006;
353 out_be32(&gpio->port_config, ul);
354 out_be16(&cdm->mclken_div_psc1, mclken_div);
355 ul = in_be32(&cdm->clk_enables);
356 ul |= 0x00000020;
357 out_be32(&cdm->clk_enables, ul);
358 break;
359 case 2:
360 ul = in_be32(&gpio->port_config);
361 ul &= 0xFFFFFF8F;
362 ul |= 0x00000060;
363 out_be32(&gpio->port_config, ul);
364 out_be16(&cdm->mclken_div_psc2, mclken_div);
365 ul = in_be32(&cdm->clk_enables);
366 ul |= 0x00000040;
367 out_be32(&cdm->clk_enables, ul);
368 break;
369 case 3:
370 ul = in_be32(&gpio->port_config);
371 ul &= 0xFFFFF0FF;
372 ul |= 0x00000600;
373 out_be32(&gpio->port_config, ul);
374 out_be16(&cdm->mclken_div_psc3, mclken_div);
375 ul = in_be32(&cdm->clk_enables);
376 ul |= 0x00000080;
377 out_be32(&cdm->clk_enables, ul);
378 break;
379 case 6:
380 ul = in_be32(&gpio->port_config);
381 ul &= 0xFF8FFFFF;
382 ul |= 0x00700000;
383 out_be32(&gpio->port_config, ul);
384 out_be16(&cdm->mclken_div_psc6, mclken_div);
385 ul = in_be32(&cdm->clk_enables);
386 ul |= 0x00000010;
387 out_be32(&cdm->clk_enables, ul);
388 break;
389 default:
390 ret = -EINVAL;
391 goto unmap_regs;
392 }
393
394 /* Reset the PSC into a known state */
395 out_8(&psc->command, MPC52xx_PSC_RST_RX);
396 out_8(&psc->command, MPC52xx_PSC_RST_TX);
397 out_8(&psc->command, MPC52xx_PSC_TX_DISABLE | MPC52xx_PSC_RX_DISABLE);
398
399 /* Disable interrupts, interrupts are based on alarm level */
400 out_be16(&psc->mpc52xx_psc_imr, 0);
401 out_8(&psc->command, MPC52xx_PSC_SEL_MODE_REG_1);
402 out_8(&psc->rfcntl, 0);
403 out_8(&psc->mode, MPC52xx_PSC_MODE_FFULL);
404
405 /* Configure 8bit codec mode as a SPI master and use EOF flags */
406 /* SICR_SIM_CODEC8|SICR_GENCLK|SICR_SPI|SICR_MSTR|SICR_USEEOF */
407 out_be32(&psc->sicr, 0x0180C800);
408 out_be16(&psc->ccr, 0x070F); /* by default SPI Clk 1MHz */
409
410 /* Set 2ms DTL delay */
411 out_8(&psc->ctur, 0x00);
412 out_8(&psc->ctlr, 0x84);
413
414 mps->bits_per_word = 8;
415
416unmap_regs:
417 if (cdm)
418 iounmap(cdm);
419 if (gpio)
420 iounmap(gpio);
421
422 return ret;
423}
424
425static irqreturn_t mpc52xx_psc_spi_isr(int irq, void *dev_id)
426{
427 struct mpc52xx_psc_spi *mps = (struct mpc52xx_psc_spi *)dev_id;
428 struct mpc52xx_psc __iomem *psc = mps->psc;
429
430 /* disable interrupt and wake up the work queue */
431 if (in_be16(&psc->mpc52xx_psc_isr) & MPC52xx_PSC_IMR_RXRDY) {
432 out_be16(&psc->mpc52xx_psc_imr, 0);
433 complete(&mps->done);
434 return IRQ_HANDLED;
435 }
436 return IRQ_NONE;
437}
438
439/* bus_num is used only for the case dev->platform_data == NULL */
440static int __init mpc52xx_psc_spi_do_probe(struct device *dev, u32 regaddr,
441 u32 size, unsigned int irq, s16 bus_num)
442{
443 struct fsl_spi_platform_data *pdata = dev->platform_data;
444 struct mpc52xx_psc_spi *mps;
445 struct spi_master *master;
446 int ret;
447
448 if (pdata == NULL)
449 return -ENODEV;
450
451 master = spi_alloc_master(dev, sizeof *mps);
452 if (master == NULL)
453 return -ENOMEM;
454
455 dev_set_drvdata(dev, master);
456 mps = spi_master_get_devdata(master);
457
458 mps->irq = irq;
459 if (pdata == NULL) {
460 dev_warn(dev, "probe called without platform data, no "
461 "(de)activate_cs function will be called\n");
462 mps->activate_cs = NULL;
463 mps->deactivate_cs = NULL;
464 mps->sysclk = 0;
465 master->bus_num = bus_num;
466 master->num_chipselect = 255;
467 } else {
468 mps->activate_cs = pdata->activate_cs;
469 mps->deactivate_cs = pdata->deactivate_cs;
470 mps->sysclk = pdata->sysclk;
471 master->bus_num = pdata->bus_num;
472 master->num_chipselect = pdata->max_chipselect;
473 }
474 master->setup = mpc52xx_psc_spi_setup;
475 master->transfer = mpc52xx_psc_spi_transfer;
476 master->cleanup = mpc52xx_psc_spi_cleanup;
477
478 mps->psc = ioremap(regaddr, size);
479 if (!mps->psc) {
480 dev_err(dev, "could not ioremap I/O port range\n");
481 ret = -EFAULT;
482 goto free_master;
483 }
484
485 ret = request_irq(mps->irq, mpc52xx_psc_spi_isr, 0, "mpc52xx-psc-spi",
486 mps);
487 if (ret)
488 goto free_master;
489
490 ret = mpc52xx_psc_spi_port_config(master->bus_num, mps);
491 if (ret < 0)
492 goto free_irq;
493
494 spin_lock_init(&mps->lock);
495 init_completion(&mps->done);
496 INIT_WORK(&mps->work, mpc52xx_psc_spi_work);
497 INIT_LIST_HEAD(&mps->queue);
498
499 mps->workqueue = create_singlethread_workqueue(
500 master->cdev.dev->bus_id);
501 if (mps->workqueue == NULL) {
502 ret = -EBUSY;
503 goto free_irq;
504 }
505
506 ret = spi_register_master(master);
507 if (ret < 0)
508 goto unreg_master;
509
510 return ret;
511
512unreg_master:
513 destroy_workqueue(mps->workqueue);
514free_irq:
515 free_irq(mps->irq, mps);
516free_master:
517 if (mps->psc)
518 iounmap(mps->psc);
519 spi_master_put(master);
520
521 return ret;
522}
523
524static int __exit mpc52xx_psc_spi_do_remove(struct device *dev)
525{
526 struct spi_master *master = dev_get_drvdata(dev);
527 struct mpc52xx_psc_spi *mps = spi_master_get_devdata(master);
528
529 flush_workqueue(mps->workqueue);
530 destroy_workqueue(mps->workqueue);
531 spi_unregister_master(master);
532 free_irq(mps->irq, mps);
533 if (mps->psc)
534 iounmap(mps->psc);
535
536 return 0;
537}
538
539#if !defined(CONFIG_PPC_MERGE)
540static int __init mpc52xx_psc_spi_probe(struct platform_device *dev)
541{
542 switch(dev->id) {
543 case 1:
544 case 2:
545 case 3:
546 case 6:
547 return mpc52xx_psc_spi_do_probe(&dev->dev,
548 MPC52xx_PA(MPC52xx_PSCx_OFFSET(dev->id)),
549 MPC52xx_PSC_SIZE, platform_get_irq(dev, 0), dev->id);
550 default:
551 return -EINVAL;
552 }
553}
554
555static int __exit mpc52xx_psc_spi_remove(struct platform_device *dev)
556{
557 return mpc52xx_psc_spi_do_remove(&dev->dev);
558}
559
560static struct platform_driver mpc52xx_psc_spi_platform_driver = {
561 .remove = __exit_p(mpc52xx_psc_spi_remove),
562 .driver = {
563 .name = "mpc52xx-psc-spi",
564 .owner = THIS_MODULE,
565 },
566};
567
568static int __init mpc52xx_psc_spi_init(void)
569{
570 return platform_driver_probe(&mpc52xx_psc_spi_platform_driver,
571 mpc52xx_psc_spi_probe);
572}
573module_init(mpc52xx_psc_spi_init);
574
575static void __exit mpc52xx_psc_spi_exit(void)
576{
577 platform_driver_unregister(&mpc52xx_psc_spi_platform_driver);
578}
579module_exit(mpc52xx_psc_spi_exit);
580
581#else /* defined(CONFIG_PPC_MERGE) */
582
583static int __init mpc52xx_psc_spi_of_probe(struct of_device *op,
584 const struct of_device_id *match)
585{
586 const u32 *regaddr_p;
587 u64 regaddr64, size64;
588 s16 id = -1;
589
590 regaddr_p = of_get_address(op->node, 0, &size64, NULL);
591 if (!regaddr_p) {
592 printk(KERN_ERR "Invalid PSC address\n");
593 return -EINVAL;
594 }
595 regaddr64 = of_translate_address(op->node, regaddr_p);
596
597 if (op->dev.platform_data == NULL) {
598 struct device_node *np;
599 int i = 0;
600
601 for_each_node_by_type(np, "spi") {
602 if (of_find_device_by_node(np) == op) {
603 id = i;
604 break;
605 }
606 i++;
607 }
608 }
609
610 return mpc52xx_psc_spi_do_probe(&op->dev, (u32)regaddr64, (u32)size64,
611 irq_of_parse_and_map(op->node, 0), id);
612}
613
614static int __exit mpc52xx_psc_spi_of_remove(struct of_device *op)
615{
616 return mpc52xx_psc_spi_do_remove(&op->dev);
617}
618
619static struct of_device_id mpc52xx_psc_spi_of_match[] = {
620 { .type = "spi", .compatible = "mpc52xx-psc-spi", },
621 {},
622};
623
624MODULE_DEVICE_TABLE(of, mpc52xx_psc_spi_of_match);
625
626static struct of_platform_driver mpc52xx_psc_spi_of_driver = {
627 .owner = THIS_MODULE,
628 .name = "mpc52xx-psc-spi",
629 .match_table = mpc52xx_psc_spi_of_match,
630 .probe = mpc52xx_psc_spi_of_probe,
631 .remove = __exit_p(mpc52xx_psc_spi_of_remove),
632 .driver = {
633 .name = "mpc52xx-psc-spi",
634 .owner = THIS_MODULE,
635 },
636};
637
638static int __init mpc52xx_psc_spi_init(void)
639{
640 return of_register_platform_driver(&mpc52xx_psc_spi_of_driver);
641}
642module_init(mpc52xx_psc_spi_init);
643
644static void __exit mpc52xx_psc_spi_exit(void)
645{
646 of_unregister_platform_driver(&mpc52xx_psc_spi_of_driver);
647}
648module_exit(mpc52xx_psc_spi_exit);
649
650#endif /* defined(CONFIG_PPC_MERGE) */
651
652MODULE_AUTHOR("Dragos Carp");
653MODULE_DESCRIPTION("MPC52xx PSC SPI Driver");
654MODULE_LICENSE("GPL");