aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c/busses/i2c-omap.c
diff options
context:
space:
mode:
authorFelipe Balbi <balbi@ti.com>2012-09-12 06:58:13 -0400
committerWolfram Sang <w.sang@pengutronix.de>2012-09-12 09:03:56 -0400
commit3b2f8f82dad7d1f79cdc8fc05bd1c94baf109bde (patch)
tree4e4a703638914bc76bfeb5a21aa5866d94c72bb8 /drivers/i2c/busses/i2c-omap.c
parentd741d0c792bda4761fd3f0089e7b0d34e99acbff (diff)
i2c: omap: switch to threaded IRQ support
for OMAP2, we can easily switch over to threaded IRQs on the I2C driver. This will allow us to spend less time in hardirq context. Signed-off-by: Felipe Balbi <balbi@ti.com> [Trivial formating changes] Signed-off-by: Shubhrajyoti D <shubhrajyoti@ti.com> Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
Diffstat (limited to 'drivers/i2c/busses/i2c-omap.c')
-rw-r--r--drivers/i2c/busses/i2c-omap.c43
1 files changed, 37 insertions, 6 deletions
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index 498a462c49b7..049331cebb7f 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -176,6 +176,7 @@ enum {
176#define I2C_OMAP_ERRATA_I462 (1 << 1) 176#define I2C_OMAP_ERRATA_I462 (1 << 1)
177 177
178struct omap_i2c_dev { 178struct omap_i2c_dev {
179 spinlock_t lock; /* IRQ synchronization */
179 struct device *dev; 180 struct device *dev;
180 void __iomem *base; /* virtual */ 181 void __iomem *base; /* virtual */
181 int irq; 182 int irq;
@@ -854,9 +855,30 @@ static int omap_i2c_transmit_data(struct omap_i2c_dev *dev, u8 num_bytes,
854} 855}
855 856
856static irqreturn_t 857static irqreturn_t
857omap_i2c_isr(int this_irq, void *dev_id) 858omap_i2c_isr(int irq, void *dev_id)
858{ 859{
859 struct omap_i2c_dev *dev = dev_id; 860 struct omap_i2c_dev *dev = dev_id;
861 irqreturn_t ret = IRQ_HANDLED;
862 u16 mask;
863 u16 stat;
864
865 spin_lock(&dev->lock);
866 mask = omap_i2c_read_reg(dev, OMAP_I2C_IE_REG);
867 stat = omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG);
868
869 if (stat & mask)
870 ret = IRQ_WAKE_THREAD;
871
872 spin_unlock(&dev->lock);
873
874 return ret;
875}
876
877static irqreturn_t
878omap_i2c_isr_thread(int this_irq, void *dev_id)
879{
880 struct omap_i2c_dev *dev = dev_id;
881 unsigned long flags;
860 u16 bits; 882 u16 bits;
861 u16 stat; 883 u16 stat;
862 int err = 0, count = 0; 884 int err = 0, count = 0;
@@ -864,6 +886,7 @@ omap_i2c_isr(int this_irq, void *dev_id)
864 if (pm_runtime_suspended(dev->dev)) 886 if (pm_runtime_suspended(dev->dev))
865 return IRQ_NONE; 887 return IRQ_NONE;
866 888
889 spin_lock_irqsave(&dev->lock, flags);
867 do { 890 do {
868 bits = omap_i2c_read_reg(dev, OMAP_I2C_IE_REG); 891 bits = omap_i2c_read_reg(dev, OMAP_I2C_IE_REG);
869 stat = omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG); 892 stat = omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG);
@@ -877,6 +900,7 @@ omap_i2c_isr(int this_irq, void *dev_id)
877 900
878 if (!stat) { 901 if (!stat) {
879 /* my work here is done */ 902 /* my work here is done */
903 spin_unlock_irqrestore(&dev->lock, flags);
880 return IRQ_HANDLED; 904 return IRQ_HANDLED;
881 } 905 }
882 906
@@ -985,6 +1009,8 @@ omap_i2c_isr(int this_irq, void *dev_id)
985 1009
986out: 1010out:
987 omap_i2c_complete_cmd(dev, err); 1011 omap_i2c_complete_cmd(dev, err);
1012 spin_unlock_irqrestore(&dev->lock, flags);
1013
988 return IRQ_HANDLED; 1014 return IRQ_HANDLED;
989} 1015}
990 1016
@@ -1028,7 +1054,6 @@ omap_i2c_probe(struct platform_device *pdev)
1028 struct omap_i2c_bus_platform_data *pdata = pdev->dev.platform_data; 1054 struct omap_i2c_bus_platform_data *pdata = pdev->dev.platform_data;
1029 struct device_node *node = pdev->dev.of_node; 1055 struct device_node *node = pdev->dev.of_node;
1030 const struct of_device_id *match; 1056 const struct of_device_id *match;
1031 irq_handler_t isr;
1032 int irq; 1057 int irq;
1033 int r; 1058 int r;
1034 1059
@@ -1078,6 +1103,8 @@ omap_i2c_probe(struct platform_device *pdev)
1078 dev->dev = &pdev->dev; 1103 dev->dev = &pdev->dev;
1079 dev->irq = irq; 1104 dev->irq = irq;
1080 1105
1106 spin_lock_init(&dev->lock);
1107
1081 platform_set_drvdata(pdev, dev); 1108 platform_set_drvdata(pdev, dev);
1082 init_completion(&dev->cmd_complete); 1109 init_completion(&dev->cmd_complete);
1083 1110
@@ -1130,10 +1157,14 @@ omap_i2c_probe(struct platform_device *pdev)
1130 /* reset ASAP, clearing any IRQs */ 1157 /* reset ASAP, clearing any IRQs */
1131 omap_i2c_init(dev); 1158 omap_i2c_init(dev);
1132 1159
1133 isr = (dev->rev < OMAP_I2C_OMAP1_REV_2) ? omap_i2c_omap1_isr : 1160 if (dev->rev < OMAP_I2C_OMAP1_REV_2)
1134 omap_i2c_isr; 1161 r = devm_request_irq(&pdev->dev, dev->irq, omap_i2c_omap1_isr,
1135 r = devm_request_irq(&pdev->dev, dev->irq, isr, IRQF_NO_SUSPEND, 1162 IRQF_NO_SUSPEND, pdev->name, dev);
1136 pdev->name, dev); 1163 else
1164 r = devm_request_threaded_irq(&pdev->dev, dev->irq,
1165 omap_i2c_isr, omap_i2c_isr_thread,
1166 IRQF_NO_SUSPEND | IRQF_ONESHOT,
1167 pdev->name, dev);
1137 1168
1138 if (r) { 1169 if (r) {
1139 dev_err(dev->dev, "failure requesting irq %i\n", dev->irq); 1170 dev_err(dev->dev, "failure requesting irq %i\n", dev->irq);