Skip to content

Commit

Permalink
i2c: omap: switch to threaded IRQ support
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Felipe Balbi authored and Wolfram Sang committed Sep 12, 2012
1 parent d741d0c commit 3b2f8f8
Showing 1 changed file with 37 additions and 6 deletions.
43 changes: 37 additions & 6 deletions drivers/i2c/busses/i2c-omap.c
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ enum {
#define I2C_OMAP_ERRATA_I462 (1 << 1)

struct omap_i2c_dev {
spinlock_t lock; /* IRQ synchronization */
struct device *dev;
void __iomem *base; /* virtual */
int irq;
Expand Down Expand Up @@ -854,16 +855,38 @@ static int omap_i2c_transmit_data(struct omap_i2c_dev *dev, u8 num_bytes,
}

static irqreturn_t
omap_i2c_isr(int this_irq, void *dev_id)
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)
{
struct omap_i2c_dev *dev = dev_id;
unsigned long flags;
u16 bits;
u16 stat;
int err = 0, count = 0;

if (pm_runtime_suspended(dev->dev))
return IRQ_NONE;

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);
Expand All @@ -877,6 +900,7 @@ omap_i2c_isr(int this_irq, void *dev_id)

if (!stat) {
/* my work here is done */
spin_unlock_irqrestore(&dev->lock, flags);
return IRQ_HANDLED;
}

Expand Down Expand Up @@ -985,6 +1009,8 @@ omap_i2c_isr(int this_irq, void *dev_id)

out:
omap_i2c_complete_cmd(dev, err);
spin_unlock_irqrestore(&dev->lock, flags);

return IRQ_HANDLED;
}

Expand Down Expand Up @@ -1028,7 +1054,6 @@ omap_i2c_probe(struct platform_device *pdev)
struct omap_i2c_bus_platform_data *pdata = pdev->dev.platform_data;
struct device_node *node = pdev->dev.of_node;
const struct of_device_id *match;
irq_handler_t isr;
int irq;
int r;

Expand Down Expand Up @@ -1078,6 +1103,8 @@ omap_i2c_probe(struct platform_device *pdev)
dev->dev = &pdev->dev;
dev->irq = irq;

spin_lock_init(&dev->lock);

platform_set_drvdata(pdev, dev);
init_completion(&dev->cmd_complete);

Expand Down Expand Up @@ -1130,10 +1157,14 @@ omap_i2c_probe(struct platform_device *pdev)
/* reset ASAP, clearing any IRQs */
omap_i2c_init(dev);

isr = (dev->rev < OMAP_I2C_OMAP1_REV_2) ? omap_i2c_omap1_isr :
omap_i2c_isr;
r = devm_request_irq(&pdev->dev, dev->irq, isr, IRQF_NO_SUSPEND,
pdev->name, dev);
if (dev->rev < OMAP_I2C_OMAP1_REV_2)
r = devm_request_irq(&pdev->dev, dev->irq, omap_i2c_omap1_isr,
IRQF_NO_SUSPEND, 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);

if (r) {
dev_err(dev->dev, "failure requesting irq %i\n", dev->irq);
Expand Down

0 comments on commit 3b2f8f8

Please sign in to comment.