aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/spi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/spi')
-rw-r--r--drivers/spi/spi-pxa2xx.c73
1 files changed, 67 insertions, 6 deletions
diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c
index c3d78073d1ad..7f8f939835fd 100644
--- a/drivers/spi/spi-pxa2xx.c
+++ b/drivers/spi/spi-pxa2xx.c
@@ -30,6 +30,7 @@
30#include <linux/gpio.h> 30#include <linux/gpio.h>
31#include <linux/slab.h> 31#include <linux/slab.h>
32#include <linux/clk.h> 32#include <linux/clk.h>
33#include <linux/pm_runtime.h>
33 34
34#include <asm/io.h> 35#include <asm/io.h>
35#include <asm/irq.h> 36#include <asm/irq.h>
@@ -417,10 +418,20 @@ static irqreturn_t ssp_int(int irq, void *dev_id)
417{ 418{
418 struct driver_data *drv_data = dev_id; 419 struct driver_data *drv_data = dev_id;
419 void __iomem *reg = drv_data->ioaddr; 420 void __iomem *reg = drv_data->ioaddr;
420 u32 sccr1_reg = read_SSCR1(reg); 421 u32 sccr1_reg;
421 u32 mask = drv_data->mask_sr; 422 u32 mask = drv_data->mask_sr;
422 u32 status; 423 u32 status;
423 424
425 /*
426 * The IRQ might be shared with other peripherals so we must first
427 * check that are we RPM suspended or not. If we are we assume that
428 * the IRQ was not for us (we shouldn't be RPM suspended when the
429 * interrupt is enabled).
430 */
431 if (pm_runtime_suspended(&drv_data->pdev->dev))
432 return IRQ_NONE;
433
434 sccr1_reg = read_SSCR1(reg);
424 status = read_SSSR(reg); 435 status = read_SSSR(reg);
425 436
426 /* Ignore possible writes if we don't need to write */ 437 /* Ignore possible writes if we don't need to write */
@@ -678,6 +689,27 @@ static int pxa2xx_spi_transfer_one_message(struct spi_master *master,
678 return 0; 689 return 0;
679} 690}
680 691
692static int pxa2xx_spi_prepare_transfer(struct spi_master *master)
693{
694 struct driver_data *drv_data = spi_master_get_devdata(master);
695
696 pm_runtime_get_sync(&drv_data->pdev->dev);
697 return 0;
698}
699
700static int pxa2xx_spi_unprepare_transfer(struct spi_master *master)
701{
702 struct driver_data *drv_data = spi_master_get_devdata(master);
703
704 /* Disable the SSP now */
705 write_SSCR0(read_SSCR0(drv_data->ioaddr) & ~SSCR0_SSE,
706 drv_data->ioaddr);
707
708 pm_runtime_mark_last_busy(&drv_data->pdev->dev);
709 pm_runtime_put_autosuspend(&drv_data->pdev->dev);
710 return 0;
711}
712
681static int setup_cs(struct spi_device *spi, struct chip_data *chip, 713static int setup_cs(struct spi_device *spi, struct chip_data *chip,
682 struct pxa2xx_spi_chip *chip_info) 714 struct pxa2xx_spi_chip *chip_info)
683{ 715{
@@ -915,6 +947,8 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
915 master->cleanup = cleanup; 947 master->cleanup = cleanup;
916 master->setup = setup; 948 master->setup = setup;
917 master->transfer_one_message = pxa2xx_spi_transfer_one_message; 949 master->transfer_one_message = pxa2xx_spi_transfer_one_message;
950 master->prepare_transfer_hardware = pxa2xx_spi_prepare_transfer;
951 master->unprepare_transfer_hardware = pxa2xx_spi_unprepare_transfer;
918 952
919 drv_data->ssp_type = ssp->type; 953 drv_data->ssp_type = ssp->type;
920 drv_data->null_dma_buf = (u32 *)PTR_ALIGN(&drv_data[1], DMA_ALIGNMENT); 954 drv_data->null_dma_buf = (u32 *)PTR_ALIGN(&drv_data[1], DMA_ALIGNMENT);
@@ -980,6 +1014,11 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
980 goto out_error_clock_enabled; 1014 goto out_error_clock_enabled;
981 } 1015 }
982 1016
1017 pm_runtime_set_autosuspend_delay(&pdev->dev, 50);
1018 pm_runtime_use_autosuspend(&pdev->dev);
1019 pm_runtime_set_active(&pdev->dev);
1020 pm_runtime_enable(&pdev->dev);
1021
983 return status; 1022 return status;
984 1023
985out_error_clock_enabled: 1024out_error_clock_enabled:
@@ -1002,6 +1041,8 @@ static int pxa2xx_spi_remove(struct platform_device *pdev)
1002 return 0; 1041 return 0;
1003 ssp = drv_data->ssp; 1042 ssp = drv_data->ssp;
1004 1043
1044 pm_runtime_get_sync(&pdev->dev);
1045
1005 /* Disable the SSP at the peripheral and SOC level */ 1046 /* Disable the SSP at the peripheral and SOC level */
1006 write_SSCR0(0, drv_data->ioaddr); 1047 write_SSCR0(0, drv_data->ioaddr);
1007 clk_disable_unprepare(ssp->clk); 1048 clk_disable_unprepare(ssp->clk);
@@ -1010,6 +1051,9 @@ static int pxa2xx_spi_remove(struct platform_device *pdev)
1010 if (drv_data->master_info->enable_dma) 1051 if (drv_data->master_info->enable_dma)
1011 pxa2xx_spi_dma_release(drv_data); 1052 pxa2xx_spi_dma_release(drv_data);
1012 1053
1054 pm_runtime_put_noidle(&pdev->dev);
1055 pm_runtime_disable(&pdev->dev);
1056
1013 /* Release IRQ */ 1057 /* Release IRQ */
1014 free_irq(ssp->irq, drv_data); 1058 free_irq(ssp->irq, drv_data);
1015 1059
@@ -1069,20 +1113,37 @@ static int pxa2xx_spi_resume(struct device *dev)
1069 1113
1070 return 0; 1114 return 0;
1071} 1115}
1116#endif
1117
1118#ifdef CONFIG_PM_RUNTIME
1119static int pxa2xx_spi_runtime_suspend(struct device *dev)
1120{
1121 struct driver_data *drv_data = dev_get_drvdata(dev);
1122
1123 clk_disable_unprepare(drv_data->ssp->clk);
1124 return 0;
1125}
1126
1127static int pxa2xx_spi_runtime_resume(struct device *dev)
1128{
1129 struct driver_data *drv_data = dev_get_drvdata(dev);
1130
1131 clk_prepare_enable(drv_data->ssp->clk);
1132 return 0;
1133}
1134#endif
1072 1135
1073static const struct dev_pm_ops pxa2xx_spi_pm_ops = { 1136static const struct dev_pm_ops pxa2xx_spi_pm_ops = {
1074 .suspend = pxa2xx_spi_suspend, 1137 SET_SYSTEM_SLEEP_PM_OPS(pxa2xx_spi_suspend, pxa2xx_spi_resume)
1075 .resume = pxa2xx_spi_resume, 1138 SET_RUNTIME_PM_OPS(pxa2xx_spi_runtime_suspend,
1139 pxa2xx_spi_runtime_resume, NULL)
1076}; 1140};
1077#endif
1078 1141
1079static struct platform_driver driver = { 1142static struct platform_driver driver = {
1080 .driver = { 1143 .driver = {
1081 .name = "pxa2xx-spi", 1144 .name = "pxa2xx-spi",
1082 .owner = THIS_MODULE, 1145 .owner = THIS_MODULE,
1083#ifdef CONFIG_PM
1084 .pm = &pxa2xx_spi_pm_ops, 1146 .pm = &pxa2xx_spi_pm_ops,
1085#endif
1086 }, 1147 },
1087 .probe = pxa2xx_spi_probe, 1148 .probe = pxa2xx_spi_probe,
1088 .remove = pxa2xx_spi_remove, 1149 .remove = pxa2xx_spi_remove,