summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Peyer <David.Peyer@motorola.com>2014-06-19 13:05:09 -0500
committerJames Wylder <jwylder@motorola.com>2014-06-30 16:35:01 +0000
commitced90b56ec3983bb9a4429272a92f15769cfe633 (patch)
tree9d23e5a5ecdd8ee7993d375f0b1e7abfdba59cf5
parent836476bd5d53fd49a923d2a3b997bea095891159 (diff)
downloadolio-linux-3.10-ced90b56ec3983bb9a4429272a92f15769cfe633.tar.xz
olio-linux-3.10-ced90b56ec3983bb9a4429272a92f15769cfe633.zip
IKXCLOCK-2635: i2c: inline the threaded interrupt on single core
The I2C driver uses a threaded interrupt, which results in over 100us of extra cpu activity. Update the omap i2c driver to not use a threaded interrupt on single core processors. This reduces the i2c latency from about 150us to 30us at 1.2GHz. Change-Id: I4ee424d2dac4ea3ea03d7e414224b764d5c11648 Signed-off-by: Jim Wylder <jwylder@motorola.com>
-rw-r--r--drivers/i2c/busses/i2c-omap.c71
1 files changed, 46 insertions, 25 deletions
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index ef08e8b72bf..1592dc0dc81 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -949,35 +949,12 @@ static int omap_i2c_transmit_data(struct omap_i2c_dev *dev, u8 num_bytes,
}
static irqreturn_t
-omap_i2c_isr(int irq, void *dev_id)
-{
- struct omap_i2c_dev *dev = dev_id;
- irqreturn_t ret = IRQ_HANDLED;
- u16 mask;
- u16 stat;
-
- spin_lock(&dev->lock);
- mask = omap_i2c_read_reg(dev, OMAP_I2C_IE_REG);
- stat = omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG);
-
- if (stat & mask)
- ret = IRQ_WAKE_THREAD;
-
- spin_unlock(&dev->lock);
-
- return ret;
-}
-
-static irqreturn_t
-omap_i2c_isr_thread(int this_irq, void *dev_id)
+omap_i2c_isr_handler(struct omap_i2c_dev *dev)
{
- struct omap_i2c_dev *dev = dev_id;
- unsigned long flags;
u16 bits;
u16 stat;
int err = 0, count = 0;
- spin_lock_irqsave(&dev->lock, flags);
do {
bits = omap_i2c_read_reg(dev, OMAP_I2C_IE_REG);
stat = omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG);
@@ -1100,9 +1077,47 @@ omap_i2c_isr_thread(int this_irq, void *dev_id)
omap_i2c_complete_cmd(dev, err);
out:
+ return IRQ_HANDLED;
+}
+
+#if (NR_CPUS != 1)
+static irqreturn_t
+omap_i2c_isr_thread(int this_irq, void *dev_id)
+{
+ struct omap_i2c_dev *dev = dev_id;
+ unsigned long flags;
+ irqreturn_t ret;
+
+ spin_lock_irqsave(&dev->lock, flags);
+ ret = omap_i2c_isr_handler(dev);
spin_unlock_irqrestore(&dev->lock, flags);
- return IRQ_HANDLED;
+ return ret;
+}
+#endif
+
+static irqreturn_t
+omap_i2c_isr(int irq, void *dev_id)
+{
+ struct omap_i2c_dev *dev = dev_id;
+ irqreturn_t ret = IRQ_HANDLED;
+ u16 mask;
+ u16 stat;
+
+ spin_lock(&dev->lock);
+ mask = omap_i2c_read_reg(dev, OMAP_I2C_IE_REG);
+ stat = omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG);
+
+ if (stat & mask)
+#if (NR_CPUS == 1)
+ ret = omap_i2c_isr_handler(dev);
+#else
+ ret = IRQ_WAKE_THREAD;
+#endif
+
+ spin_unlock(&dev->lock);
+
+ return ret;
}
static const struct i2c_algorithm omap_i2c_algo = {
@@ -1292,10 +1307,16 @@ omap_i2c_probe(struct platform_device *pdev)
r = devm_request_irq(&pdev->dev, dev->irq, omap_i2c_omap1_isr,
IRQF_NO_SUSPEND, pdev->name, dev);
else
+#if (NR_CPUS == 1)
+ r = devm_request_irq(&pdev->dev, dev->irq, omap_i2c_isr,
+ IRQF_NO_SUSPEND | IRQF_ONESHOT,
+ pdev->name, dev);
+#else
r = devm_request_threaded_irq(&pdev->dev, dev->irq,
omap_i2c_isr, omap_i2c_isr_thread,
IRQF_NO_SUSPEND | IRQF_ONESHOT,
pdev->name, dev);
+#endif
if (r) {
dev_err(dev->dev, "failure requesting irq %i\n", dev->irq);