aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/spi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/spi')
-rw-r--r--drivers/spi/spi-s3c64xx.c114
1 files changed, 103 insertions, 11 deletions
diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c
index dcf7e1006426..b899af6640a2 100644
--- a/drivers/spi/spi-s3c64xx.c
+++ b/drivers/spi/spi-s3c64xx.c
@@ -20,10 +20,12 @@
20#include <linux/init.h> 20#include <linux/init.h>
21#include <linux/module.h> 21#include <linux/module.h>
22#include <linux/workqueue.h> 22#include <linux/workqueue.h>
23#include <linux/interrupt.h>
23#include <linux/delay.h> 24#include <linux/delay.h>
24#include <linux/clk.h> 25#include <linux/clk.h>
25#include <linux/dma-mapping.h> 26#include <linux/dma-mapping.h>
26#include <linux/platform_device.h> 27#include <linux/platform_device.h>
28#include <linux/pm_runtime.h>
27#include <linux/spi/spi.h> 29#include <linux/spi/spi.h>
28 30
29#include <mach/dma.h> 31#include <mach/dma.h>
@@ -153,6 +155,7 @@ struct s3c64xx_spi_dma_data {
153 * @tx_dmach: Controller's DMA channel for Tx. 155 * @tx_dmach: Controller's DMA channel for Tx.
154 * @sfr_start: BUS address of SPI controller regs. 156 * @sfr_start: BUS address of SPI controller regs.
155 * @regs: Pointer to ioremap'ed controller registers. 157 * @regs: Pointer to ioremap'ed controller registers.
158 * @irq: interrupt
156 * @xfer_completion: To indicate completion of xfer task. 159 * @xfer_completion: To indicate completion of xfer task.
157 * @cur_mode: Stores the active configuration of the controller. 160 * @cur_mode: Stores the active configuration of the controller.
158 * @cur_bpw: Stores the active bits per word settings. 161 * @cur_bpw: Stores the active bits per word settings.
@@ -780,6 +783,8 @@ static void s3c64xx_spi_work(struct work_struct *work)
780 while (!acquire_dma(sdd)) 783 while (!acquire_dma(sdd))
781 msleep(10); 784 msleep(10);
782 785
786 pm_runtime_get_sync(&sdd->pdev->dev);
787
783 spin_lock_irqsave(&sdd->lock, flags); 788 spin_lock_irqsave(&sdd->lock, flags);
784 789
785 while (!list_empty(&sdd->queue) 790 while (!list_empty(&sdd->queue)
@@ -808,6 +813,8 @@ static void s3c64xx_spi_work(struct work_struct *work)
808 /* Free DMA channels */ 813 /* Free DMA channels */
809 sdd->ops->release(sdd->rx_dma.ch, &s3c64xx_spi_dma_client); 814 sdd->ops->release(sdd->rx_dma.ch, &s3c64xx_spi_dma_client);
810 sdd->ops->release(sdd->tx_dma.ch, &s3c64xx_spi_dma_client); 815 sdd->ops->release(sdd->tx_dma.ch, &s3c64xx_spi_dma_client);
816
817 pm_runtime_put(&sdd->pdev->dev);
811} 818}
812 819
813static int s3c64xx_spi_transfer(struct spi_device *spi, 820static int s3c64xx_spi_transfer(struct spi_device *spi,
@@ -890,6 +897,8 @@ static int s3c64xx_spi_setup(struct spi_device *spi)
890 goto setup_exit; 897 goto setup_exit;
891 } 898 }
892 899
900 pm_runtime_get_sync(&sdd->pdev->dev);
901
893 /* Check if we can provide the requested rate */ 902 /* Check if we can provide the requested rate */
894 if (!sci->clk_from_cmu) { 903 if (!sci->clk_from_cmu) {
895 u32 psr, speed; 904 u32 psr, speed;
@@ -922,6 +931,8 @@ static int s3c64xx_spi_setup(struct spi_device *spi)
922 err = -EINVAL; 931 err = -EINVAL;
923 } 932 }
924 933
934 pm_runtime_put(&sdd->pdev->dev);
935
925setup_exit: 936setup_exit:
926 937
927 /* setup() returns with device de-selected */ 938 /* setup() returns with device de-selected */
@@ -930,6 +941,33 @@ setup_exit:
930 return err; 941 return err;
931} 942}
932 943
944static irqreturn_t s3c64xx_spi_irq(int irq, void *data)
945{
946 struct s3c64xx_spi_driver_data *sdd = data;
947 struct spi_master *spi = sdd->master;
948 unsigned int val;
949
950 val = readl(sdd->regs + S3C64XX_SPI_PENDING_CLR);
951
952 val &= S3C64XX_SPI_PND_RX_OVERRUN_CLR |
953 S3C64XX_SPI_PND_RX_UNDERRUN_CLR |
954 S3C64XX_SPI_PND_TX_OVERRUN_CLR |
955 S3C64XX_SPI_PND_TX_UNDERRUN_CLR;
956
957 writel(val, sdd->regs + S3C64XX_SPI_PENDING_CLR);
958
959 if (val & S3C64XX_SPI_PND_RX_OVERRUN_CLR)
960 dev_err(&spi->dev, "RX overrun\n");
961 if (val & S3C64XX_SPI_PND_RX_UNDERRUN_CLR)
962 dev_err(&spi->dev, "RX underrun\n");
963 if (val & S3C64XX_SPI_PND_TX_OVERRUN_CLR)
964 dev_err(&spi->dev, "TX overrun\n");
965 if (val & S3C64XX_SPI_PND_TX_UNDERRUN_CLR)
966 dev_err(&spi->dev, "TX underrun\n");
967
968 return IRQ_HANDLED;
969}
970
933static void s3c64xx_spi_hwinit(struct s3c64xx_spi_driver_data *sdd, int channel) 971static void s3c64xx_spi_hwinit(struct s3c64xx_spi_driver_data *sdd, int channel)
934{ 972{
935 struct s3c64xx_spi_info *sci = sdd->cntrlr_info; 973 struct s3c64xx_spi_info *sci = sdd->cntrlr_info;
@@ -970,7 +1008,7 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev)
970 struct s3c64xx_spi_driver_data *sdd; 1008 struct s3c64xx_spi_driver_data *sdd;
971 struct s3c64xx_spi_info *sci; 1009 struct s3c64xx_spi_info *sci;
972 struct spi_master *master; 1010 struct spi_master *master;
973 int ret; 1011 int ret, irq;
974 char clk_name[16]; 1012 char clk_name[16];
975 1013
976 if (pdev->id < 0) { 1014 if (pdev->id < 0) {
@@ -1006,6 +1044,12 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev)
1006 return -ENXIO; 1044 return -ENXIO;
1007 } 1045 }
1008 1046
1047 irq = platform_get_irq(pdev, 0);
1048 if (irq < 0) {
1049 dev_warn(&pdev->dev, "Failed to get IRQ: %d\n", irq);
1050 return irq;
1051 }
1052
1009 master = spi_alloc_master(&pdev->dev, 1053 master = spi_alloc_master(&pdev->dev,
1010 sizeof(struct s3c64xx_spi_driver_data)); 1054 sizeof(struct s3c64xx_spi_driver_data));
1011 if (master == NULL) { 1055 if (master == NULL) {
@@ -1100,10 +1144,21 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev)
1100 INIT_WORK(&sdd->work, s3c64xx_spi_work); 1144 INIT_WORK(&sdd->work, s3c64xx_spi_work);
1101 INIT_LIST_HEAD(&sdd->queue); 1145 INIT_LIST_HEAD(&sdd->queue);
1102 1146
1147 ret = request_irq(irq, s3c64xx_spi_irq, 0, "spi-s3c64xx", sdd);
1148 if (ret != 0) {
1149 dev_err(&pdev->dev, "Failed to request IRQ %d: %d\n",
1150 irq, ret);
1151 goto err8;
1152 }
1153
1154 writel(S3C64XX_SPI_INT_RX_OVERRUN_EN | S3C64XX_SPI_INT_RX_UNDERRUN_EN |
1155 S3C64XX_SPI_INT_TX_OVERRUN_EN | S3C64XX_SPI_INT_TX_UNDERRUN_EN,
1156 sdd->regs + S3C64XX_SPI_INT_EN);
1157
1103 if (spi_register_master(master)) { 1158 if (spi_register_master(master)) {
1104 dev_err(&pdev->dev, "cannot register SPI master\n"); 1159 dev_err(&pdev->dev, "cannot register SPI master\n");
1105 ret = -EBUSY; 1160 ret = -EBUSY;
1106 goto err8; 1161 goto err9;
1107 } 1162 }
1108 1163
1109 dev_dbg(&pdev->dev, "Samsung SoC SPI Driver loaded for Bus SPI-%d " 1164 dev_dbg(&pdev->dev, "Samsung SoC SPI Driver loaded for Bus SPI-%d "
@@ -1113,8 +1168,12 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev)
1113 mem_res->end, mem_res->start, 1168 mem_res->end, mem_res->start,
1114 sdd->rx_dma.dmach, sdd->tx_dma.dmach); 1169 sdd->rx_dma.dmach, sdd->tx_dma.dmach);
1115 1170
1171 pm_runtime_enable(&pdev->dev);
1172
1116 return 0; 1173 return 0;
1117 1174
1175err9:
1176 free_irq(irq, sdd);
1118err8: 1177err8:
1119 destroy_workqueue(sdd->workqueue); 1178 destroy_workqueue(sdd->workqueue);
1120err7: 1179err7:
@@ -1144,6 +1203,8 @@ static int s3c64xx_spi_remove(struct platform_device *pdev)
1144 struct resource *mem_res; 1203 struct resource *mem_res;
1145 unsigned long flags; 1204 unsigned long flags;
1146 1205
1206 pm_runtime_disable(&pdev->dev);
1207
1147 spin_lock_irqsave(&sdd->lock, flags); 1208 spin_lock_irqsave(&sdd->lock, flags);
1148 sdd->state |= SUSPND; 1209 sdd->state |= SUSPND;
1149 spin_unlock_irqrestore(&sdd->lock, flags); 1210 spin_unlock_irqrestore(&sdd->lock, flags);
@@ -1153,6 +1214,10 @@ static int s3c64xx_spi_remove(struct platform_device *pdev)
1153 1214
1154 spi_unregister_master(master); 1215 spi_unregister_master(master);
1155 1216
1217 writel(0, sdd->regs + S3C64XX_SPI_INT_EN);
1218
1219 free_irq(platform_get_irq(pdev, 0), sdd);
1220
1156 destroy_workqueue(sdd->workqueue); 1221 destroy_workqueue(sdd->workqueue);
1157 1222
1158 clk_disable(sdd->src_clk); 1223 clk_disable(sdd->src_clk);
@@ -1174,9 +1239,9 @@ static int s3c64xx_spi_remove(struct platform_device *pdev)
1174} 1239}
1175 1240
1176#ifdef CONFIG_PM 1241#ifdef CONFIG_PM
1177static int s3c64xx_spi_suspend(struct platform_device *pdev, pm_message_t state) 1242static int s3c64xx_spi_suspend(struct device *dev)
1178{ 1243{
1179 struct spi_master *master = spi_master_get(platform_get_drvdata(pdev)); 1244 struct spi_master *master = spi_master_get(dev_get_drvdata(dev));
1180 struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master); 1245 struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master);
1181 unsigned long flags; 1246 unsigned long flags;
1182 1247
@@ -1196,9 +1261,10 @@ static int s3c64xx_spi_suspend(struct platform_device *pdev, pm_message_t state)
1196 return 0; 1261 return 0;
1197} 1262}
1198 1263
1199static int s3c64xx_spi_resume(struct platform_device *pdev) 1264static int s3c64xx_spi_resume(struct device *dev)
1200{ 1265{
1201 struct spi_master *master = spi_master_get(platform_get_drvdata(pdev)); 1266 struct platform_device *pdev = to_platform_device(dev);
1267 struct spi_master *master = spi_master_get(dev_get_drvdata(dev));
1202 struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master); 1268 struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master);
1203 struct s3c64xx_spi_info *sci = sdd->cntrlr_info; 1269 struct s3c64xx_spi_info *sci = sdd->cntrlr_info;
1204 unsigned long flags; 1270 unsigned long flags;
@@ -1217,19 +1283,45 @@ static int s3c64xx_spi_resume(struct platform_device *pdev)
1217 1283
1218 return 0; 1284 return 0;
1219} 1285}
1220#else
1221#define s3c64xx_spi_suspend NULL
1222#define s3c64xx_spi_resume NULL
1223#endif /* CONFIG_PM */ 1286#endif /* CONFIG_PM */
1224 1287
1288#ifdef CONFIG_PM_RUNTIME
1289static int s3c64xx_spi_runtime_suspend(struct device *dev)
1290{
1291 struct spi_master *master = spi_master_get(dev_get_drvdata(dev));
1292 struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master);
1293
1294 clk_disable(sdd->clk);
1295 clk_disable(sdd->src_clk);
1296
1297 return 0;
1298}
1299
1300static int s3c64xx_spi_runtime_resume(struct device *dev)
1301{
1302 struct spi_master *master = spi_master_get(dev_get_drvdata(dev));
1303 struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master);
1304
1305 clk_enable(sdd->src_clk);
1306 clk_enable(sdd->clk);
1307
1308 return 0;
1309}
1310#endif /* CONFIG_PM_RUNTIME */
1311
1312static const struct dev_pm_ops s3c64xx_spi_pm = {
1313 SET_SYSTEM_SLEEP_PM_OPS(s3c64xx_spi_suspend, s3c64xx_spi_resume)
1314 SET_RUNTIME_PM_OPS(s3c64xx_spi_runtime_suspend,
1315 s3c64xx_spi_runtime_resume, NULL)
1316};
1317
1225static struct platform_driver s3c64xx_spi_driver = { 1318static struct platform_driver s3c64xx_spi_driver = {
1226 .driver = { 1319 .driver = {
1227 .name = "s3c64xx-spi", 1320 .name = "s3c64xx-spi",
1228 .owner = THIS_MODULE, 1321 .owner = THIS_MODULE,
1322 .pm = &s3c64xx_spi_pm,
1229 }, 1323 },
1230 .remove = s3c64xx_spi_remove, 1324 .remove = s3c64xx_spi_remove,
1231 .suspend = s3c64xx_spi_suspend,
1232 .resume = s3c64xx_spi_resume,
1233}; 1325};
1234MODULE_ALIAS("platform:s3c64xx-spi"); 1326MODULE_ALIAS("platform:s3c64xx-spi");
1235 1327