diff options
| author | David Peyer <David.Peyer@motorola.com> | 2014-06-19 13:05:09 -0500 |
|---|---|---|
| committer | James Wylder <jwylder@motorola.com> | 2014-06-30 16:35:01 +0000 |
| commit | ced90b56ec3983bb9a4429272a92f15769cfe633 (patch) | |
| tree | 9d23e5a5ecdd8ee7993d375f0b1e7abfdba59cf5 | |
| parent | 836476bd5d53fd49a923d2a3b997bea095891159 (diff) | |
| download | olio-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.c | 71 |
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); |