mirror of https://gitee.com/openkylin/linux.git
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>
This commit is contained in:
parent
d741d0c792
commit
3b2f8f82da
|
@ -176,6 +176,7 @@ enum {
|
||||||
#define I2C_OMAP_ERRATA_I462 (1 << 1)
|
#define I2C_OMAP_ERRATA_I462 (1 << 1)
|
||||||
|
|
||||||
struct omap_i2c_dev {
|
struct omap_i2c_dev {
|
||||||
|
spinlock_t lock; /* IRQ synchronization */
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
void __iomem *base; /* virtual */
|
void __iomem *base; /* virtual */
|
||||||
int irq;
|
int irq;
|
||||||
|
@ -854,9 +855,30 @@ static int omap_i2c_transmit_data(struct omap_i2c_dev *dev, u8 num_bytes,
|
||||||
}
|
}
|
||||||
|
|
||||||
static irqreturn_t
|
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;
|
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 bits;
|
||||||
u16 stat;
|
u16 stat;
|
||||||
int err = 0, count = 0;
|
int err = 0, count = 0;
|
||||||
|
@ -864,6 +886,7 @@ omap_i2c_isr(int this_irq, void *dev_id)
|
||||||
if (pm_runtime_suspended(dev->dev))
|
if (pm_runtime_suspended(dev->dev))
|
||||||
return IRQ_NONE;
|
return IRQ_NONE;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&dev->lock, flags);
|
||||||
do {
|
do {
|
||||||
bits = omap_i2c_read_reg(dev, OMAP_I2C_IE_REG);
|
bits = omap_i2c_read_reg(dev, OMAP_I2C_IE_REG);
|
||||||
stat = omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG);
|
stat = omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG);
|
||||||
|
@ -877,6 +900,7 @@ omap_i2c_isr(int this_irq, void *dev_id)
|
||||||
|
|
||||||
if (!stat) {
|
if (!stat) {
|
||||||
/* my work here is done */
|
/* my work here is done */
|
||||||
|
spin_unlock_irqrestore(&dev->lock, flags);
|
||||||
return IRQ_HANDLED;
|
return IRQ_HANDLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -985,6 +1009,8 @@ omap_i2c_isr(int this_irq, void *dev_id)
|
||||||
|
|
||||||
out:
|
out:
|
||||||
omap_i2c_complete_cmd(dev, err);
|
omap_i2c_complete_cmd(dev, err);
|
||||||
|
spin_unlock_irqrestore(&dev->lock, flags);
|
||||||
|
|
||||||
return IRQ_HANDLED;
|
return IRQ_HANDLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1028,7 +1054,6 @@ omap_i2c_probe(struct platform_device *pdev)
|
||||||
struct omap_i2c_bus_platform_data *pdata = pdev->dev.platform_data;
|
struct omap_i2c_bus_platform_data *pdata = pdev->dev.platform_data;
|
||||||
struct device_node *node = pdev->dev.of_node;
|
struct device_node *node = pdev->dev.of_node;
|
||||||
const struct of_device_id *match;
|
const struct of_device_id *match;
|
||||||
irq_handler_t isr;
|
|
||||||
int irq;
|
int irq;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
|
@ -1078,6 +1103,8 @@ omap_i2c_probe(struct platform_device *pdev)
|
||||||
dev->dev = &pdev->dev;
|
dev->dev = &pdev->dev;
|
||||||
dev->irq = irq;
|
dev->irq = irq;
|
||||||
|
|
||||||
|
spin_lock_init(&dev->lock);
|
||||||
|
|
||||||
platform_set_drvdata(pdev, dev);
|
platform_set_drvdata(pdev, dev);
|
||||||
init_completion(&dev->cmd_complete);
|
init_completion(&dev->cmd_complete);
|
||||||
|
|
||||||
|
@ -1130,10 +1157,14 @@ omap_i2c_probe(struct platform_device *pdev)
|
||||||
/* reset ASAP, clearing any IRQs */
|
/* reset ASAP, clearing any IRQs */
|
||||||
omap_i2c_init(dev);
|
omap_i2c_init(dev);
|
||||||
|
|
||||||
isr = (dev->rev < OMAP_I2C_OMAP1_REV_2) ? omap_i2c_omap1_isr :
|
if (dev->rev < OMAP_I2C_OMAP1_REV_2)
|
||||||
omap_i2c_isr;
|
r = devm_request_irq(&pdev->dev, dev->irq, omap_i2c_omap1_isr,
|
||||||
r = devm_request_irq(&pdev->dev, dev->irq, isr, IRQF_NO_SUSPEND,
|
IRQF_NO_SUSPEND, pdev->name, dev);
|
||||||
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) {
|
if (r) {
|
||||||
dev_err(dev->dev, "failure requesting irq %i\n", dev->irq);
|
dev_err(dev->dev, "failure requesting irq %i\n", dev->irq);
|
||||||
|
|
Loading…
Reference in New Issue