diff options
| -rw-r--r-- | drivers/spi/spi-orion.c | 59 |
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 | |||
| 281 | static int orion_spi_transfer_one_message(struct spi_master *master, | 284 | static 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 | ||
| 422 | out_rel_pm: | ||
| 423 | pm_runtime_disable(&pdev->dev); | ||
| 410 | out_rel_clk: | 424 | out_rel_clk: |
| 411 | clk_disable_unprepare(spi->clk); | 425 | clk_disable_unprepare(spi->clk); |
| 412 | out: | 426 | out: |
| @@ -417,19 +431,45 @@ out: | |||
| 417 | 431 | ||
| 418 | static int orion_spi_remove(struct platform_device *pdev) | 432 | static 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 | ||
| 431 | MODULE_ALIAS("platform:" DRIVER_NAME); | 446 | MODULE_ALIAS("platform:" DRIVER_NAME); |
| 432 | 447 | ||
| 448 | #ifdef CONFIG_PM_RUNTIME | ||
| 449 | static 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 | |||
| 458 | static 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 | |||
| 467 | static 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 | |||
| 433 | static const struct of_device_id orion_spi_of_match_table[] = { | 473 | static 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, |
