aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/spi
diff options
context:
space:
mode:
authorWenyou Yang <wenyou.yang@atmel.com>2014-10-16 05:23:10 -0400
committerMark Brown <broonie@kernel.org>2014-10-20 07:24:18 -0400
commitce0c4caf256cb828e0465d3cd363ec145e446e21 (patch)
treef618cbdb4334545faecc9ae71634d1f3c0e7cc2b /drivers/spi
parent5398ad6897ec666a416b1d7428f0e8a51adf4254 (diff)
spi/atmel: add support for runtime PM
Drivers should put the device into low power states proactively whenever the device is not in use. Thus implement support for runtime PM and use the autosuspend feature to make sure that we can still perform well in case we see lots of SPI traffic within short period of time. Signed-off-by: Wenyou Yang <wenyou.yang@atmel.com> Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'drivers/spi')
-rw-r--r--drivers/spi/spi-atmel.c68
1 files changed, 61 insertions, 7 deletions
diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c
index 649dcb5a603c..bc9d96902837 100644
--- a/drivers/spi/spi-atmel.c
+++ b/drivers/spi/spi-atmel.c
@@ -26,6 +26,7 @@
26#include <linux/io.h> 26#include <linux/io.h>
27#include <linux/gpio.h> 27#include <linux/gpio.h>
28#include <linux/pinctrl/consumer.h> 28#include <linux/pinctrl/consumer.h>
29#include <linux/pm_runtime.h>
29 30
30/* SPI register offsets */ 31/* SPI register offsets */
31#define SPI_CR 0x0000 32#define SPI_CR 0x0000
@@ -191,6 +192,8 @@
191 192
192#define SPI_DMA_TIMEOUT (msecs_to_jiffies(1000)) 193#define SPI_DMA_TIMEOUT (msecs_to_jiffies(1000))
193 194
195#define AUTOSUSPEND_TIMEOUT 2000
196
194struct atmel_spi_dma { 197struct atmel_spi_dma {
195 struct dma_chan *chan_rx; 198 struct dma_chan *chan_rx;
196 struct dma_chan *chan_tx; 199 struct dma_chan *chan_tx;
@@ -1313,6 +1316,7 @@ static int atmel_spi_probe(struct platform_device *pdev)
1313 master->setup = atmel_spi_setup; 1316 master->setup = atmel_spi_setup;
1314 master->transfer_one_message = atmel_spi_transfer_one_message; 1317 master->transfer_one_message = atmel_spi_transfer_one_message;
1315 master->cleanup = atmel_spi_cleanup; 1318 master->cleanup = atmel_spi_cleanup;
1319 master->auto_runtime_pm = true;
1316 platform_set_drvdata(pdev, master); 1320 platform_set_drvdata(pdev, master);
1317 1321
1318 as = spi_master_get_devdata(master); 1322 as = spi_master_get_devdata(master);
@@ -1385,6 +1389,11 @@ static int atmel_spi_probe(struct platform_device *pdev)
1385 dev_info(&pdev->dev, "Atmel SPI Controller at 0x%08lx (irq %d)\n", 1389 dev_info(&pdev->dev, "Atmel SPI Controller at 0x%08lx (irq %d)\n",
1386 (unsigned long)regs->start, irq); 1390 (unsigned long)regs->start, irq);
1387 1391
1392 pm_runtime_set_autosuspend_delay(&pdev->dev, AUTOSUSPEND_TIMEOUT);
1393 pm_runtime_use_autosuspend(&pdev->dev);
1394 pm_runtime_set_active(&pdev->dev);
1395 pm_runtime_enable(&pdev->dev);
1396
1388 ret = devm_spi_register_master(&pdev->dev, master); 1397 ret = devm_spi_register_master(&pdev->dev, master);
1389 if (ret) 1398 if (ret)
1390 goto out_free_dma; 1399 goto out_free_dma;
@@ -1392,6 +1401,9 @@ static int atmel_spi_probe(struct platform_device *pdev)
1392 return 0; 1401 return 0;
1393 1402
1394out_free_dma: 1403out_free_dma:
1404 pm_runtime_disable(&pdev->dev);
1405 pm_runtime_set_suspended(&pdev->dev);
1406
1395 if (as->use_dma) 1407 if (as->use_dma)
1396 atmel_spi_release_dma(as); 1408 atmel_spi_release_dma(as);
1397 1409
@@ -1413,6 +1425,8 @@ static int atmel_spi_remove(struct platform_device *pdev)
1413 struct spi_master *master = platform_get_drvdata(pdev); 1425 struct spi_master *master = platform_get_drvdata(pdev);
1414 struct atmel_spi *as = spi_master_get_devdata(master); 1426 struct atmel_spi *as = spi_master_get_devdata(master);
1415 1427
1428 pm_runtime_get_sync(&pdev->dev);
1429
1416 /* reset the hardware and block queue progress */ 1430 /* reset the hardware and block queue progress */
1417 spin_lock_irq(&as->lock); 1431 spin_lock_irq(&as->lock);
1418 if (as->use_dma) { 1432 if (as->use_dma) {
@@ -1430,9 +1444,13 @@ static int atmel_spi_remove(struct platform_device *pdev)
1430 1444
1431 clk_disable_unprepare(as->clk); 1445 clk_disable_unprepare(as->clk);
1432 1446
1447 pm_runtime_put_noidle(&pdev->dev);
1448 pm_runtime_disable(&pdev->dev);
1449
1433 return 0; 1450 return 0;
1434} 1451}
1435 1452
1453#ifdef CONFIG_PM
1436#ifdef CONFIG_PM_SLEEP 1454#ifdef CONFIG_PM_SLEEP
1437static int atmel_spi_suspend(struct device *dev) 1455static int atmel_spi_suspend(struct device *dev)
1438{ 1456{
@@ -1447,9 +1465,10 @@ static int atmel_spi_suspend(struct device *dev)
1447 return ret; 1465 return ret;
1448 } 1466 }
1449 1467
1450 clk_disable_unprepare(as->clk); 1468 if (!pm_runtime_suspended(dev)) {
1451 1469 clk_disable_unprepare(as->clk);
1452 pinctrl_pm_select_sleep_state(dev); 1470 pinctrl_pm_select_sleep_state(dev);
1471 }
1453 1472
1454 return 0; 1473 return 0;
1455} 1474}
@@ -1460,9 +1479,12 @@ static int atmel_spi_resume(struct device *dev)
1460 struct atmel_spi *as = spi_master_get_devdata(master); 1479 struct atmel_spi *as = spi_master_get_devdata(master);
1461 int ret; 1480 int ret;
1462 1481
1463 pinctrl_pm_select_default_state(dev); 1482 if (!pm_runtime_suspended(dev)) {
1464 1483 pinctrl_pm_select_default_state(dev);
1465 clk_prepare_enable(as->clk); 1484 ret = clk_prepare_enable(as->clk);
1485 if (ret)
1486 return ret;
1487 }
1466 1488
1467 /* Start the queue running */ 1489 /* Start the queue running */
1468 ret = spi_master_resume(master); 1490 ret = spi_master_resume(master);
@@ -1471,9 +1493,41 @@ static int atmel_spi_resume(struct device *dev)
1471 1493
1472 return ret; 1494 return ret;
1473} 1495}
1496#endif
1474 1497
1475static SIMPLE_DEV_PM_OPS(atmel_spi_pm_ops, atmel_spi_suspend, atmel_spi_resume); 1498#ifdef CONFIG_PM_RUNTIME
1499static int atmel_spi_runtime_suspend(struct device *dev)
1500{
1501 struct spi_master *master = dev_get_drvdata(dev);
1502 struct atmel_spi *as = spi_master_get_devdata(master);
1476 1503
1504 clk_disable_unprepare(as->clk);
1505 pinctrl_pm_select_sleep_state(dev);
1506
1507 return 0;
1508}
1509
1510static int atmel_spi_runtime_resume(struct device *dev)
1511{
1512 struct spi_master *master = dev_get_drvdata(dev);
1513 struct atmel_spi *as = spi_master_get_devdata(master);
1514 int ret;
1515
1516 pinctrl_pm_select_default_state(dev);
1517
1518 ret = clk_prepare_enable(as->clk);
1519 if (ret)
1520 return ret;
1521
1522 return 0;
1523}
1524#endif
1525
1526static const struct dev_pm_ops atmel_spi_pm_ops = {
1527 SET_SYSTEM_SLEEP_PM_OPS(atmel_spi_suspend, atmel_spi_resume)
1528 SET_RUNTIME_PM_OPS(atmel_spi_runtime_suspend,
1529 atmel_spi_runtime_resume, NULL)
1530};
1477#define ATMEL_SPI_PM_OPS (&atmel_spi_pm_ops) 1531#define ATMEL_SPI_PM_OPS (&atmel_spi_pm_ops)
1478#else 1532#else
1479#define ATMEL_SPI_PM_OPS NULL 1533#define ATMEL_SPI_PM_OPS NULL