aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/spi/spi-orion.c59
1 files changed, 50 insertions, 9 deletions
diff --git a/drivers/spi/spi-orion.c b/drivers/spi/spi-orion.c
index 24844984ef36..aa3ecfc6b466 100644
--- a/drivers/spi/spi-orion.c
+++ b/drivers/spi/spi-orion.c
@@ -16,6 +16,7 @@
16#include <linux/io.h> 16#include <linux/io.h>
17#include <linux/spi/spi.h> 17#include <linux/spi/spi.h>
18#include <linux/module.h> 18#include <linux/module.h>
19#include <linux/pm_runtime.h>
19#include <linux/of.h> 20#include <linux/of.h>
20#include <linux/clk.h> 21#include <linux/clk.h>
21#include <linux/sizes.h> 22#include <linux/sizes.h>
@@ -23,6 +24,9 @@
23 24
24#define DRIVER_NAME "orion_spi" 25#define DRIVER_NAME "orion_spi"
25 26
27/* Runtime PM autosuspend timeout: PM is fairly light on this driver */
28#define SPI_AUTOSUSPEND_TIMEOUT 200
29
26#define ORION_NUM_CHIPSELECTS 1 /* only one slave is supported*/ 30#define ORION_NUM_CHIPSELECTS 1 /* only one slave is supported*/
27#define ORION_SPI_WAIT_RDY_MAX_LOOP 2000 /* in usec */ 31#define ORION_SPI_WAIT_RDY_MAX_LOOP 2000 /* in usec */
28 32
@@ -277,7 +281,6 @@ out:
277 return xfer->len - count; 281 return xfer->len - count;
278} 282}
279 283
280
281static int orion_spi_transfer_one_message(struct spi_master *master, 284static int orion_spi_transfer_one_message(struct spi_master *master,
282 struct spi_message *m) 285 struct spi_message *m)
283{ 286{
@@ -370,6 +373,7 @@ static int orion_spi_probe(struct platform_device *pdev)
370 master->transfer_one_message = orion_spi_transfer_one_message; 373 master->transfer_one_message = orion_spi_transfer_one_message;
371 master->num_chipselect = ORION_NUM_CHIPSELECTS; 374 master->num_chipselect = ORION_NUM_CHIPSELECTS;
372 master->bits_per_word_mask = SPI_BPW_MASK(8) | SPI_BPW_MASK(16); 375 master->bits_per_word_mask = SPI_BPW_MASK(8) | SPI_BPW_MASK(16);
376 master->auto_runtime_pm = true;
373 377
374 platform_set_drvdata(pdev, master); 378 platform_set_drvdata(pdev, master);
375 379
@@ -397,16 +401,26 @@ static int orion_spi_probe(struct platform_device *pdev)
397 goto out_rel_clk; 401 goto out_rel_clk;
398 } 402 }
399 403
404 pm_runtime_set_active(&pdev->dev);
405 pm_runtime_use_autosuspend(&pdev->dev);
406 pm_runtime_set_autosuspend_delay(&pdev->dev, SPI_AUTOSUSPEND_TIMEOUT);
407 pm_runtime_enable(&pdev->dev);
408
400 if (orion_spi_reset(spi) < 0) 409 if (orion_spi_reset(spi) < 0)
401 goto out_rel_clk; 410 goto out_rel_pm;
411
412 pm_runtime_mark_last_busy(&pdev->dev);
413 pm_runtime_put_autosuspend(&pdev->dev);
402 414
403 master->dev.of_node = pdev->dev.of_node; 415 master->dev.of_node = pdev->dev.of_node;
404 status = devm_spi_register_master(&pdev->dev, master); 416 status = spi_register_master(master);
405 if (status < 0) 417 if (status < 0)
406 goto out_rel_clk; 418 goto out_rel_pm;
407 419
408 return status; 420 return status;
409 421
422out_rel_pm:
423 pm_runtime_disable(&pdev->dev);
410out_rel_clk: 424out_rel_clk:
411 clk_disable_unprepare(spi->clk); 425 clk_disable_unprepare(spi->clk);
412out: 426out:
@@ -417,19 +431,45 @@ out:
417 431
418static int orion_spi_remove(struct platform_device *pdev) 432static int orion_spi_remove(struct platform_device *pdev)
419{ 433{
420 struct spi_master *master; 434 struct spi_master *master = platform_get_drvdata(pdev);
421 struct orion_spi *spi; 435 struct orion_spi *spi = spi_master_get_devdata(master);
422
423 master = platform_get_drvdata(pdev);
424 spi = spi_master_get_devdata(master);
425 436
437 pm_runtime_get_sync(&pdev->dev);
426 clk_disable_unprepare(spi->clk); 438 clk_disable_unprepare(spi->clk);
427 439
440 spi_unregister_master(master);
441 pm_runtime_disable(&pdev->dev);
442
428 return 0; 443 return 0;
429} 444}
430 445
431MODULE_ALIAS("platform:" DRIVER_NAME); 446MODULE_ALIAS("platform:" DRIVER_NAME);
432 447
448#ifdef CONFIG_PM_RUNTIME
449static int orion_spi_runtime_suspend(struct device *dev)
450{
451 struct spi_master *master = dev_get_drvdata(dev);
452 struct orion_spi *spi = spi_master_get_devdata(master);
453
454 clk_disable_unprepare(spi->clk);
455 return 0;
456}
457
458static int orion_spi_runtime_resume(struct device *dev)
459{
460 struct spi_master *master = dev_get_drvdata(dev);
461 struct orion_spi *spi = spi_master_get_devdata(master);
462
463 return clk_prepare_enable(spi->clk);
464}
465#endif
466
467static const struct dev_pm_ops orion_spi_pm_ops = {
468 SET_RUNTIME_PM_OPS(orion_spi_runtime_suspend,
469 orion_spi_runtime_resume,
470 NULL)
471};
472
433static const struct of_device_id orion_spi_of_match_table[] = { 473static const struct of_device_id orion_spi_of_match_table[] = {
434 { .compatible = "marvell,orion-spi", }, 474 { .compatible = "marvell,orion-spi", },
435 {} 475 {}
@@ -440,6 +480,7 @@ static struct platform_driver orion_spi_driver = {
440 .driver = { 480 .driver = {
441 .name = DRIVER_NAME, 481 .name = DRIVER_NAME,
442 .owner = THIS_MODULE, 482 .owner = THIS_MODULE,
483 .pm = &orion_spi_pm_ops,
443 .of_match_table = of_match_ptr(orion_spi_of_match_table), 484 .of_match_table = of_match_ptr(orion_spi_of_match_table),
444 }, 485 },
445 .probe = orion_spi_probe, 486 .probe = orion_spi_probe,