Commit bc98d13f5cce1b617305966c3e95f7b2e62aa820

Authored by Steven King
Committed by Grant Likely
1 parent 5fda88f5e1

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>

Showing 1 changed file with 114 additions and 141 deletions Side-by-side Diff

drivers/spi/spi-coldfire-qspi.c
... ... @@ -25,12 +25,12 @@
25 25 #include <linux/errno.h>
26 26 #include <linux/platform_device.h>
27 27 #include <linux/sched.h>
28   -#include <linux/workqueue.h>
29 28 #include <linux/delay.h>
30 29 #include <linux/io.h>
31 30 #include <linux/clk.h>
32 31 #include <linux/err.h>
33 32 #include <linux/spi/spi.h>
  33 +#include <linux/pm_runtime.h>
34 34  
35 35 #include <asm/coldfire.h>
36 36 #include <asm/mcfsim.h>
... ... @@ -78,10 +78,7 @@
78 78  
79 79 wait_queue_head_t waitq;
80 80  
81   - struct work_struct work;
82   - struct workqueue_struct *workq;
83   - spinlock_t lock;
84   - struct list_head msgq;
  81 + struct device *dev;
85 82 };
86 83  
87 84 static void mcfqspi_wr_qmr(struct mcfqspi *mcfqspi, u16 val)
88 85  
89 86  
90 87  
91 88  
92 89  
93 90  
94 91  
95 92  
96 93  
97 94  
98 95  
99 96  
100 97  
101 98  
102 99  
103 100  
... ... @@ -303,120 +300,80 @@
303 300 }
304 301 }
305 302  
306   -static void mcfqspi_work(struct work_struct *work)
  303 +static 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);
309   - unsigned long flags;
  306 + struct mcfqspi *mcfqspi = spi_master_get_devdata(master);
  307 + struct spi_device *spi = msg->spi;
  308 + struct spi_transfer *t;
  309 + int status = 0;
310 310  
311   - spin_lock_irqsave(&mcfqspi->lock, flags);
312   - while (!list_empty(&mcfqspi->msgq)) {
313   - struct spi_message *msg;
314   - struct spi_device *spi;
315   - struct spi_transfer *xfer;
316   - int status = 0;
  311 + list_for_each_entry(t, &msg->transfers, transfer_list) {
  312 + bool cs_high = spi->mode & SPI_CS_HIGH;
  313 + u16 qmr = MCFQSPI_QMR_MSTR;
317 314  
318   - msg = container_of(mcfqspi->msgq.next, struct spi_message,
319   - queue);
  315 + if (t->bits_per_word)
  316 + qmr |= t->bits_per_word << 10;
  317 + else
  318 + qmr |= spi->bits_per_word << 10;
  319 + if (spi->mode & SPI_CPHA)
  320 + qmr |= MCFQSPI_QMR_CPHA;
  321 + if (spi->mode & SPI_CPOL)
  322 + qmr |= MCFQSPI_QMR_CPOL;
  323 + if (t->speed_hz)
  324 + qmr |= mcfqspi_qmr_baud(t->speed_hz);
  325 + else
  326 + qmr |= mcfqspi_qmr_baud(spi->max_speed_hz);
  327 + mcfqspi_wr_qmr(mcfqspi, qmr);
320 328  
321   - list_del_init(&msg->queue);
322   - spin_unlock_irqrestore(&mcfqspi->lock, flags);
  329 + mcfqspi_cs_select(mcfqspi, spi->chip_select, cs_high);
323 330  
324   - spi = msg->spi;
  331 + mcfqspi_wr_qir(mcfqspi, MCFQSPI_QIR_SPIFE);
  332 + if ((t->bits_per_word ? t->bits_per_word :
  333 + spi->bits_per_word) == 8)
  334 + mcfqspi_transfer_msg8(mcfqspi, t->len, t->tx_buf,
  335 + t->rx_buf);
  336 + else
  337 + mcfqspi_transfer_msg16(mcfqspi, t->len / 2, t->tx_buf,
  338 + t->rx_buf);
  339 + mcfqspi_wr_qir(mcfqspi, 0);
325 340  
326   - list_for_each_entry(xfer, &msg->transfers, transfer_list) {
327   - bool cs_high = spi->mode & SPI_CS_HIGH;
328   - u16 qmr = MCFQSPI_QMR_MSTR;
  341 + if (t->delay_usecs)
  342 + udelay(t->delay_usecs);
  343 + if (t->cs_change) {
  344 + if (!list_is_last(&t->transfer_list, &msg->transfers))
  345 + mcfqspi_cs_deselect(mcfqspi, spi->chip_select,
  346 + cs_high);
  347 + } else {
  348 + if (list_is_last(&t->transfer_list, &msg->transfers))
  349 + mcfqspi_cs_deselect(mcfqspi, spi->chip_select,
  350 + cs_high);
  351 + }
  352 + msg->actual_length += t->len;
  353 + }
  354 + msg->status = status;
  355 + spi_finalize_current_message(master);
329 356  
330   - if (xfer->bits_per_word)
331   - qmr |= xfer->bits_per_word << 10;
332   - else
333   - qmr |= spi->bits_per_word << 10;
334   - if (spi->mode & SPI_CPHA)
335   - qmr |= MCFQSPI_QMR_CPHA;
336   - if (spi->mode & SPI_CPOL)
337   - qmr |= MCFQSPI_QMR_CPOL;
338   - if (xfer->speed_hz)
339   - qmr |= mcfqspi_qmr_baud(xfer->speed_hz);
340   - else
341   - qmr |= mcfqspi_qmr_baud(spi->max_speed_hz);
342   - mcfqspi_wr_qmr(mcfqspi, qmr);
  357 + return status;
343 358  
344   - mcfqspi_cs_select(mcfqspi, spi->chip_select, cs_high);
  359 +}
345 360  
346   - mcfqspi_wr_qir(mcfqspi, MCFQSPI_QIR_SPIFE);
347   - if ((xfer->bits_per_word ? xfer->bits_per_word :
348   - spi->bits_per_word) == 8)
349   - mcfqspi_transfer_msg8(mcfqspi, xfer->len,
350   - xfer->tx_buf,
351   - xfer->rx_buf);
352   - else
353   - mcfqspi_transfer_msg16(mcfqspi, xfer->len / 2,
354   - xfer->tx_buf,
355   - xfer->rx_buf);
356   - mcfqspi_wr_qir(mcfqspi, 0);
  361 +static int mcfqspi_prepare_transfer_hw(struct spi_master *master)
  362 +{
  363 + struct mcfqspi *mcfqspi = spi_master_get_devdata(master);
357 364  
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   - }
375   - msg->status = status;
376   - msg->complete(msg->context);
  365 + pm_runtime_get_sync(mcfqspi->dev);
377 366  
378   - spin_lock_irqsave(&mcfqspi->lock, flags);
379   - }
380   - spin_unlock_irqrestore(&mcfqspi->lock, flags);
  367 + return 0;
381 368 }
382 369  
383   -static int mcfqspi_transfer(struct spi_device *spi, struct spi_message *msg)
  370 +static int mcfqspi_unprepare_transfer_hw(struct spi_master *master)
384 371 {
385   - struct mcfqspi *mcfqspi;
386   - struct spi_transfer *xfer;
387   - unsigned long flags;
  372 + struct mcfqspi *mcfqspi = spi_master_get_devdata(master);
388 373  
389   - mcfqspi = spi_master_get_devdata(spi->master);
  374 + pm_runtime_put_sync(mcfqspi->dev);
390 375  
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   -
411   - spin_lock_irqsave(&mcfqspi->lock, flags);
412   - list_add_tail(&msg->queue, &mcfqspi->msgq);
413   - queue_work(mcfqspi->workq, &mcfqspi->work);
414   - spin_unlock_irqrestore(&mcfqspi->lock, flags);
415   -
416 376 return 0;
417   -fail:
418   - msg->status = -EINVAL;
419   - return -EINVAL;
420 377 }
421 378  
422 379 static int mcfqspi_setup(struct spi_device *spi)
423 380  
... ... @@ -502,21 +459,10 @@
502 459 }
503 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 462 pdata = pdev->dev.platform_data;
517 463 if (!pdata) {
518 464 dev_dbg(&pdev->dev, "platform data is missing\n");
519   - goto fail5;
  465 + goto fail4;
520 466 }
521 467 master->bus_num = pdata->bus_num;
522 468 master->num_chipselect = pdata->num_chipselect;
523 469  
524 470  
525 471  
526 472  
527 473  
528 474  
... ... @@ -525,28 +471,33 @@
525 471 status = mcfqspi_cs_setup(mcfqspi);
526 472 if (status) {
527 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 480 master->mode_bits = SPI_CS_HIGH | SPI_CPOL | SPI_CPHA;
532 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 486 platform_set_drvdata(pdev, master);
536 487  
537 488 status = spi_register_master(master);
538 489 if (status) {
539 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 495 dev_info(&pdev->dev, "Coldfire QSPI bus driver\n");
543 496  
544 497 return 0;
545 498  
546   -fail6:
547   - mcfqspi_cs_teardown(mcfqspi);
548 499 fail5:
549   - destroy_workqueue(mcfqspi->workq);
  500 + mcfqspi_cs_teardown(mcfqspi);
550 501 fail4:
551 502 clk_disable(mcfqspi->clk);
552 503 clk_put(mcfqspi->clk);
553 504  
... ... @@ -570,12 +521,12 @@
570 521 struct mcfqspi *mcfqspi = spi_master_get_devdata(master);
571 522 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
572 523  
  524 + pm_runtime_disable(mcfqspi->dev);
573 525 /* disable the hardware (set the baud rate to 0) */
574 526 mcfqspi_wr_qmr(mcfqspi, MCFQSPI_QMR_MSTR);
575 527  
576 528 platform_set_drvdata(pdev, NULL);
577 529 mcfqspi_cs_teardown(mcfqspi);
578   - destroy_workqueue(mcfqspi->workq);
579 530 clk_disable(mcfqspi->clk);
580 531 clk_put(mcfqspi->clk);
581 532 free_irq(mcfqspi->irq, mcfqspi);
582 533  
583 534  
... ... @@ -587,12 +538,14 @@
587 538 return 0;
588 539 }
589 540  
590   -#ifdef CONFIG_PM
591   -
  541 +#ifdef CONFIG_PM_SLEEP
592 542 static 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);
595 546  
  547 + spi_master_suspend(master);
  548 +
596 549 clk_disable(mcfqspi->clk);
597 550  
598 551 return 0;
599 552  
600 553  
601 554  
602 555  
603 556  
604 557  
... ... @@ -600,27 +553,47 @@
600 553  
601 554 static 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);
604 558  
  559 + spi_master_resume(master);
  560 +
605 561 clk_enable(mcfqspi->clk);
606 562  
607 563 return 0;
608 564 }
  565 +#endif
609 566  
610   -static struct dev_pm_ops mcfqspi_dev_pm_ops = {
611   - .suspend = mcfqspi_suspend,
612   - .resume = mcfqspi_resume,
613   -};
  567 +#ifdef CONFIG_PM_RUNTIME
  568 +static int mcfqspi_runtime_suspend(struct device *dev)
  569 +{
  570 + struct mcfqspi *mcfqspi = platform_get_drvdata(to_platform_device(dev));
614 571  
615   -#define MCFQSPI_DEV_PM_OPS (&mcfqspi_dev_pm_ops)
616   -#else
617   -#define MCFQSPI_DEV_PM_OPS NULL
  572 + clk_disable(mcfqspi->clk);
  573 +
  574 + return 0;
  575 +}
  576 +
  577 +static 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 585 #endif
619 586  
  587 +static 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 +
620 593 static struct platform_driver mcfqspi_driver = {
621 594 .driver.name = DRIVER_NAME,
622 595 .driver.owner = THIS_MODULE,
623   - .driver.pm = MCFQSPI_DEV_PM_OPS,
  596 + .driver.pm = &mcfqspi_pm,
624 597 .probe = mcfqspi_probe,
625 598 .remove = __devexit_p(mcfqspi_remove),
626 599 };