aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/spi
diff options
context:
space:
mode:
authorSteven King <sfking@fdwdc.com>2012-05-10 12:26:55 -0400
committerGrant Likely <grant.likely@secretlab.ca>2012-05-20 00:57:27 -0400
commitbc98d13f5cce1b617305966c3e95f7b2e62aa820 (patch)
tree1c2d889dd2a3758aea8ff7793ded48ee37b443ac /drivers/spi
parent5fda88f5e17ea0e767360a3f09eac80f83296ea9 (diff)
spi: refactor spi-coldfire-qspi to use SPI queue framework.
Use the new SPI queue framework; remove use of workqueue, replace mcfqspi_transfer with mcfqspi_transfer_one_message, add mcfqspi_prepare_transfer_hw and mcfqspi_unprepare_transfer_hw, update power management routines. Signed-off-by: Steven King <sfking@fdwdc.com> Acked-by: Greg Ungerer <gerg@snapgear.com> Acked-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
Diffstat (limited to 'drivers/spi')
-rw-r--r--drivers/spi/spi-coldfire-qspi.c255
1 files changed, 114 insertions, 141 deletions
diff --git a/drivers/spi/spi-coldfire-qspi.c b/drivers/spi/spi-coldfire-qspi.c
index 6eee64a5d240..b2d4b9e4e010 100644
--- a/drivers/spi/spi-coldfire-qspi.c
+++ b/drivers/spi/spi-coldfire-qspi.c
@@ -25,12 +25,12 @@
25#include <linux/errno.h> 25#include <linux/errno.h>
26#include <linux/platform_device.h> 26#include <linux/platform_device.h>
27#include <linux/sched.h> 27#include <linux/sched.h>
28#include <linux/workqueue.h>
29#include <linux/delay.h> 28#include <linux/delay.h>
30#include <linux/io.h> 29#include <linux/io.h>
31#include <linux/clk.h> 30#include <linux/clk.h>
32#include <linux/err.h> 31#include <linux/err.h>
33#include <linux/spi/spi.h> 32#include <linux/spi/spi.h>
33#include <linux/pm_runtime.h>
34 34
35#include <asm/coldfire.h> 35#include <asm/coldfire.h>
36#include <asm/mcfsim.h> 36#include <asm/mcfsim.h>
@@ -78,10 +78,7 @@ struct mcfqspi {
78 78
79 wait_queue_head_t waitq; 79 wait_queue_head_t waitq;
80 80
81 struct work_struct work; 81 struct device *dev;
82 struct workqueue_struct *workq;
83 spinlock_t lock;
84 struct list_head msgq;
85}; 82};
86 83
87static void mcfqspi_wr_qmr(struct mcfqspi *mcfqspi, u16 val) 84static void mcfqspi_wr_qmr(struct mcfqspi *mcfqspi, u16 val)
@@ -303,120 +300,80 @@ static void mcfqspi_transfer_msg16(struct mcfqspi *mcfqspi, unsigned count,
303 } 300 }
304} 301}
305 302
306static void mcfqspi_work(struct work_struct *work) 303static int mcfqspi_transfer_one_message(struct spi_master *master,
304 struct spi_message *msg)
307{ 305{
308 struct mcfqspi *mcfqspi = container_of(work, struct mcfqspi, work); 306 struct mcfqspi *mcfqspi = spi_master_get_devdata(master);
309 unsigned long flags; 307 struct spi_device *spi = msg->spi;
310 308 struct spi_transfer *t;
311 spin_lock_irqsave(&mcfqspi->lock, flags); 309 int status = 0;
312 while (!list_empty(&mcfqspi->msgq)) { 310
313 struct spi_message *msg; 311 list_for_each_entry(t, &msg->transfers, transfer_list) {
314 struct spi_device *spi; 312 bool cs_high = spi->mode & SPI_CS_HIGH;
315 struct spi_transfer *xfer; 313 u16 qmr = MCFQSPI_QMR_MSTR;
316 int status = 0; 314
317 315 if (t->bits_per_word)
318 msg = container_of(mcfqspi->msgq.next, struct spi_message, 316 qmr |= t->bits_per_word << 10;
319 queue); 317 else
320 318 qmr |= spi->bits_per_word << 10;
321 list_del_init(&msg->queue); 319 if (spi->mode & SPI_CPHA)
322 spin_unlock_irqrestore(&mcfqspi->lock, flags); 320 qmr |= MCFQSPI_QMR_CPHA;
323 321 if (spi->mode & SPI_CPOL)
324 spi = msg->spi; 322 qmr |= MCFQSPI_QMR_CPOL;
325 323 if (t->speed_hz)
326 list_for_each_entry(xfer, &msg->transfers, transfer_list) { 324 qmr |= mcfqspi_qmr_baud(t->speed_hz);
327 bool cs_high = spi->mode & SPI_CS_HIGH; 325 else
328 u16 qmr = MCFQSPI_QMR_MSTR; 326 qmr |= mcfqspi_qmr_baud(spi->max_speed_hz);
329 327 mcfqspi_wr_qmr(mcfqspi, qmr);
330 if (xfer->bits_per_word) 328
331 qmr |= xfer->bits_per_word << 10; 329 mcfqspi_cs_select(mcfqspi, spi->chip_select, cs_high);
332 else 330
333 qmr |= spi->bits_per_word << 10; 331 mcfqspi_wr_qir(mcfqspi, MCFQSPI_QIR_SPIFE);
334 if (spi->mode & SPI_CPHA) 332 if ((t->bits_per_word ? t->bits_per_word :
335 qmr |= MCFQSPI_QMR_CPHA; 333 spi->bits_per_word) == 8)
336 if (spi->mode & SPI_CPOL) 334 mcfqspi_transfer_msg8(mcfqspi, t->len, t->tx_buf,
337 qmr |= MCFQSPI_QMR_CPOL; 335 t->rx_buf);
338 if (xfer->speed_hz) 336 else
339 qmr |= mcfqspi_qmr_baud(xfer->speed_hz); 337 mcfqspi_transfer_msg16(mcfqspi, t->len / 2, t->tx_buf,
340 else 338 t->rx_buf);
341 qmr |= mcfqspi_qmr_baud(spi->max_speed_hz); 339 mcfqspi_wr_qir(mcfqspi, 0);
342 mcfqspi_wr_qmr(mcfqspi, qmr); 340
343 341 if (t->delay_usecs)
344 mcfqspi_cs_select(mcfqspi, spi->chip_select, cs_high); 342 udelay(t->delay_usecs);
345 343 if (t->cs_change) {
346 mcfqspi_wr_qir(mcfqspi, MCFQSPI_QIR_SPIFE); 344 if (!list_is_last(&t->transfer_list, &msg->transfers))
347 if ((xfer->bits_per_word ? xfer->bits_per_word : 345 mcfqspi_cs_deselect(mcfqspi, spi->chip_select,
348 spi->bits_per_word) == 8) 346 cs_high);
349 mcfqspi_transfer_msg8(mcfqspi, xfer->len, 347 } else {
350 xfer->tx_buf, 348 if (list_is_last(&t->transfer_list, &msg->transfers))
351 xfer->rx_buf); 349 mcfqspi_cs_deselect(mcfqspi, spi->chip_select,
352 else 350 cs_high);
353 mcfqspi_transfer_msg16(mcfqspi, xfer->len / 2,
354 xfer->tx_buf,
355 xfer->rx_buf);
356 mcfqspi_wr_qir(mcfqspi, 0);
357
358 if (xfer->delay_usecs)
359 udelay(xfer->delay_usecs);
360 if (xfer->cs_change) {
361 if (!list_is_last(&xfer->transfer_list,
362 &msg->transfers))
363 mcfqspi_cs_deselect(mcfqspi,
364 spi->chip_select,
365 cs_high);
366 } else {
367 if (list_is_last(&xfer->transfer_list,
368 &msg->transfers))
369 mcfqspi_cs_deselect(mcfqspi,
370 spi->chip_select,
371 cs_high);
372 }
373 msg->actual_length += xfer->len;
374 } 351 }
375 msg->status = status; 352 msg->actual_length += t->len;
376 msg->complete(msg->context);
377
378 spin_lock_irqsave(&mcfqspi->lock, flags);
379 } 353 }
380 spin_unlock_irqrestore(&mcfqspi->lock, flags); 354 msg->status = status;
355 spi_finalize_current_message(master);
356
357 return status;
358
381} 359}
382 360
383static int mcfqspi_transfer(struct spi_device *spi, struct spi_message *msg) 361static int mcfqspi_prepare_transfer_hw(struct spi_master *master)
384{ 362{
385 struct mcfqspi *mcfqspi; 363 struct mcfqspi *mcfqspi = spi_master_get_devdata(master);
386 struct spi_transfer *xfer;
387 unsigned long flags;
388
389 mcfqspi = spi_master_get_devdata(spi->master);
390
391 list_for_each_entry(xfer, &msg->transfers, transfer_list) {
392 if (xfer->bits_per_word && ((xfer->bits_per_word < 8)
393 || (xfer->bits_per_word > 16))) {
394 dev_dbg(&spi->dev,
395 "%d bits per word is not supported\n",
396 xfer->bits_per_word);
397 goto fail;
398 }
399 if (xfer->speed_hz) {
400 u32 real_speed = MCFQSPI_BUSCLK /
401 mcfqspi_qmr_baud(xfer->speed_hz);
402 if (real_speed != xfer->speed_hz)
403 dev_dbg(&spi->dev,
404 "using speed %d instead of %d\n",
405 real_speed, xfer->speed_hz);
406 }
407 }
408 msg->status = -EINPROGRESS;
409 msg->actual_length = 0;
410 364
411 spin_lock_irqsave(&mcfqspi->lock, flags); 365 pm_runtime_get_sync(mcfqspi->dev);
412 list_add_tail(&msg->queue, &mcfqspi->msgq); 366
413 queue_work(mcfqspi->workq, &mcfqspi->work); 367 return 0;
414 spin_unlock_irqrestore(&mcfqspi->lock, flags); 368}
369
370static int mcfqspi_unprepare_transfer_hw(struct spi_master *master)
371{
372 struct mcfqspi *mcfqspi = spi_master_get_devdata(master);
373
374 pm_runtime_put_sync(mcfqspi->dev);
415 375
416 return 0; 376 return 0;
417fail:
418 msg->status = -EINVAL;
419 return -EINVAL;
420} 377}
421 378
422static int mcfqspi_setup(struct spi_device *spi) 379static int mcfqspi_setup(struct spi_device *spi)
@@ -502,21 +459,10 @@ static int __devinit mcfqspi_probe(struct platform_device *pdev)
502 } 459 }
503 clk_enable(mcfqspi->clk); 460 clk_enable(mcfqspi->clk);
504 461
505 mcfqspi->workq = create_singlethread_workqueue(dev_name(master->dev.parent));
506 if (!mcfqspi->workq) {
507 dev_dbg(&pdev->dev, "create_workqueue failed\n");
508 status = -ENOMEM;
509 goto fail4;
510 }
511 INIT_WORK(&mcfqspi->work, mcfqspi_work);
512 spin_lock_init(&mcfqspi->lock);
513 INIT_LIST_HEAD(&mcfqspi->msgq);
514 init_waitqueue_head(&mcfqspi->waitq);
515
516 pdata = pdev->dev.platform_data; 462 pdata = pdev->dev.platform_data;
517 if (!pdata) { 463 if (!pdata) {
518 dev_dbg(&pdev->dev, "platform data is missing\n"); 464 dev_dbg(&pdev->dev, "platform data is missing\n");
519 goto fail5; 465 goto fail4;
520 } 466 }
521 master->bus_num = pdata->bus_num; 467 master->bus_num = pdata->bus_num;
522 master->num_chipselect = pdata->num_chipselect; 468 master->num_chipselect = pdata->num_chipselect;
@@ -525,28 +471,33 @@ static int __devinit mcfqspi_probe(struct platform_device *pdev)
525 status = mcfqspi_cs_setup(mcfqspi); 471 status = mcfqspi_cs_setup(mcfqspi);
526 if (status) { 472 if (status) {
527 dev_dbg(&pdev->dev, "error initializing cs_control\n"); 473 dev_dbg(&pdev->dev, "error initializing cs_control\n");
528 goto fail5; 474 goto fail4;
529 } 475 }
530 476
477 init_waitqueue_head(&mcfqspi->waitq);
478 mcfqspi->dev = &pdev->dev;
479
531 master->mode_bits = SPI_CS_HIGH | SPI_CPOL | SPI_CPHA; 480 master->mode_bits = SPI_CS_HIGH | SPI_CPOL | SPI_CPHA;
532 master->setup = mcfqspi_setup; 481 master->setup = mcfqspi_setup;
533 master->transfer = mcfqspi_transfer; 482 master->transfer_one_message = mcfqspi_transfer_one_message;
483 master->prepare_transfer_hardware = mcfqspi_prepare_transfer_hw;
484 master->unprepare_transfer_hardware = mcfqspi_unprepare_transfer_hw;
534 485
535 platform_set_drvdata(pdev, master); 486 platform_set_drvdata(pdev, master);
536 487
537 status = spi_register_master(master); 488 status = spi_register_master(master);
538 if (status) { 489 if (status) {
539 dev_dbg(&pdev->dev, "spi_register_master failed\n"); 490 dev_dbg(&pdev->dev, "spi_register_master failed\n");
540 goto fail6; 491 goto fail5;
541 } 492 }
493 pm_runtime_enable(mcfqspi->dev);
494
542 dev_info(&pdev->dev, "Coldfire QSPI bus driver\n"); 495 dev_info(&pdev->dev, "Coldfire QSPI bus driver\n");
543 496
544 return 0; 497 return 0;
545 498
546fail6:
547 mcfqspi_cs_teardown(mcfqspi);
548fail5: 499fail5:
549 destroy_workqueue(mcfqspi->workq); 500 mcfqspi_cs_teardown(mcfqspi);
550fail4: 501fail4:
551 clk_disable(mcfqspi->clk); 502 clk_disable(mcfqspi->clk);
552 clk_put(mcfqspi->clk); 503 clk_put(mcfqspi->clk);
@@ -570,12 +521,12 @@ static int __devexit mcfqspi_remove(struct platform_device *pdev)
570 struct mcfqspi *mcfqspi = spi_master_get_devdata(master); 521 struct mcfqspi *mcfqspi = spi_master_get_devdata(master);
571 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 522 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
572 523
524 pm_runtime_disable(mcfqspi->dev);
573 /* disable the hardware (set the baud rate to 0) */ 525 /* disable the hardware (set the baud rate to 0) */
574 mcfqspi_wr_qmr(mcfqspi, MCFQSPI_QMR_MSTR); 526 mcfqspi_wr_qmr(mcfqspi, MCFQSPI_QMR_MSTR);
575 527
576 platform_set_drvdata(pdev, NULL); 528 platform_set_drvdata(pdev, NULL);
577 mcfqspi_cs_teardown(mcfqspi); 529 mcfqspi_cs_teardown(mcfqspi);
578 destroy_workqueue(mcfqspi->workq);
579 clk_disable(mcfqspi->clk); 530 clk_disable(mcfqspi->clk);
580 clk_put(mcfqspi->clk); 531 clk_put(mcfqspi->clk);
581 free_irq(mcfqspi->irq, mcfqspi); 532 free_irq(mcfqspi->irq, mcfqspi);
@@ -587,11 +538,13 @@ static int __devexit mcfqspi_remove(struct platform_device *pdev)
587 return 0; 538 return 0;
588} 539}
589 540
590#ifdef CONFIG_PM 541#ifdef CONFIG_PM_SLEEP
591
592static int mcfqspi_suspend(struct device *dev) 542static int mcfqspi_suspend(struct device *dev)
593{ 543{
594 struct mcfqspi *mcfqspi = platform_get_drvdata(to_platform_device(dev)); 544 struct spi_master *master = spi_master_get(dev_get_drvdata(dev));
545 struct mcfqspi *mcfqspi = spi_master_get_devdata(master);
546
547 spi_master_suspend(master);
595 548
596 clk_disable(mcfqspi->clk); 549 clk_disable(mcfqspi->clk);
597 550
@@ -600,27 +553,47 @@ static int mcfqspi_suspend(struct device *dev)
600 553
601static int mcfqspi_resume(struct device *dev) 554static int mcfqspi_resume(struct device *dev)
602{ 555{
603 struct mcfqspi *mcfqspi = platform_get_drvdata(to_platform_device(dev)); 556 struct spi_master *master = spi_master_get(dev_get_drvdata(dev));
557 struct mcfqspi *mcfqspi = spi_master_get_devdata(master);
558
559 spi_master_resume(master);
604 560
605 clk_enable(mcfqspi->clk); 561 clk_enable(mcfqspi->clk);
606 562
607 return 0; 563 return 0;
608} 564}
565#endif
609 566
610static struct dev_pm_ops mcfqspi_dev_pm_ops = { 567#ifdef CONFIG_PM_RUNTIME
611 .suspend = mcfqspi_suspend, 568static int mcfqspi_runtime_suspend(struct device *dev)
612 .resume = mcfqspi_resume, 569{
613}; 570 struct mcfqspi *mcfqspi = platform_get_drvdata(to_platform_device(dev));
614 571
615#define MCFQSPI_DEV_PM_OPS (&mcfqspi_dev_pm_ops) 572 clk_disable(mcfqspi->clk);
616#else 573
617#define MCFQSPI_DEV_PM_OPS NULL 574 return 0;
575}
576
577static int mcfqspi_runtime_resume(struct device *dev)
578{
579 struct mcfqspi *mcfqspi = platform_get_drvdata(to_platform_device(dev));
580
581 clk_enable(mcfqspi->clk);
582
583 return 0;
584}
618#endif 585#endif
619 586
587static const struct dev_pm_ops mcfqspi_pm = {
588 SET_SYSTEM_SLEEP_PM_OPS(mcfqspi_suspend, mcfqspi_resume)
589 SET_RUNTIME_PM_OPS(mcfqspi_runtime_suspend, mcfqspi_runtime_resume,
590 NULL)
591};
592
620static struct platform_driver mcfqspi_driver = { 593static struct platform_driver mcfqspi_driver = {
621 .driver.name = DRIVER_NAME, 594 .driver.name = DRIVER_NAME,
622 .driver.owner = THIS_MODULE, 595 .driver.owner = THIS_MODULE,
623 .driver.pm = MCFQSPI_DEV_PM_OPS, 596 .driver.pm = &mcfqspi_pm,
624 .probe = mcfqspi_probe, 597 .probe = mcfqspi_probe,
625 .remove = __devexit_p(mcfqspi_remove), 598 .remove = __devexit_p(mcfqspi_remove),
626}; 599};