aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c/busses
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/i2c/busses')
-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);