Skip to contentSkip to conversation

i2c: omap: few more patches

PATCH New Felipe Balbi 3 participants 12 messages Aug 6, 2012 – Aug 7, 2012

Subsystems (4)
lore
Share & tools
lore
#0 lore raw

cover i2c: omap: few more patches

Just a few extra patches on top of the earlier series I sent.

With these patches, we have threaded irq support and autosuspend support for i2c-omap driver.

All patches boot tested with pandaboard.

Felipe Balbi (4):
i2c: omap: always return IRQ_HANDLED
i2c: omap: switch to threaded IRQ support
i2c: omap: remove unnecessary pm_runtime_suspended check
i2c: omap: switch over to autosuspend API

 drivers/i2c/busses/i2c-omap.c | 53 ++++++++++++++++++++++++++++++++++---------
 1 file changed, 42 insertions(+), 11 deletions(-)
Signature · 1 line
1.7.12.rc0
#1 lore raw

PATCH 1/4 i2c: omap: always return IRQ_HANDLED

even if our clocks are disabled, we still
handled the IRQ, so we should return IRQ_HANDLED.

---
 drivers/i2c/busses/i2c-omap.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/i2c/busses/i2c-omap.c +1 -1
index 2dd2301..f5eafb7 100644
@@ -862,7 +862,7 @@ omap_i2c_isr(int this_irq, void *dev_id)
 	int err = 0, count = 0;
 
 	if (pm_runtime_suspended(dev->dev))
-		return IRQ_NONE;
+		return IRQ_HANDLED;
 
 	do {
 		bits = omap_i2c_read_reg(dev, OMAP_I2C_IE_REG);
Signature · 1 line
1.7.12.rc0
#2 lore raw

PATCH 2/4 i2c: omap: switch to threaded IRQ support

In reply to Felipe Balbi

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.

---
 drivers/i2c/busses/i2c-omap.c | 42 ++++++++++++++++++++++++++++++++++++------
 1 file changed, 36 insertions(+), 6 deletions(-)
drivers/i2c/busses/i2c-omap.c +36 -6
index f5eafb7..a3db053 100644
@@ -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;
@@ -854,9 +855,30 @@ 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;
@@ -864,6 +886,7 @@ omap_i2c_isr(int this_irq, void *dev_id)
 	if (pm_runtime_suspended(dev->dev))
 		return IRQ_HANDLED;
 
+	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);
@@ -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;
 		}
 
@@ -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;
 }
 
@@ -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;
 
@@ -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);
 
@@ -1130,10 +1157,13 @@ 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);
Signature · 1 line
1.7.12.rc0
#3 lore raw

PATCH 3/4 i2c: omap: remove unnecessary pm_runtime_suspended check

In reply to Felipe Balbi

before starting any messages we call pm_runtime_get_sync() which will make sure that by the time we program a transfer and our IRQ handler gets called, we're not suspended anymore.

---
 drivers/i2c/busses/i2c-omap.c | 3 ---
 1 file changed, 3 deletions(-)
drivers/i2c/busses/i2c-omap.c +0 -3
index a3db053..60928f2 100644
@@ -883,9 +883,6 @@ omap_i2c_isr_thread(int this_irq, void *dev_id)
 	u16 stat;
 	int err = 0, count = 0;
 
-	if (pm_runtime_suspended(dev->dev))
-		return IRQ_HANDLED;
-
 	spin_lock_irqsave(&dev->lock, flags);
 	do {
 		bits = omap_i2c_read_reg(dev, OMAP_I2C_IE_REG);
Signature · 1 line
1.7.12.rc0
#4 lore raw

PATCH 4/4 i2c: omap: switch over to autosuspend API

In reply to Felipe Balbi

this helps us reduce unnecessary pm transitions
in case we have another i2c message been started
soon.

---
 drivers/i2c/busses/i2c-omap.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)
drivers/i2c/busses/i2c-omap.c +6 -2
index 60928f2..22efaba 100644
@@ -645,7 +645,8 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
 
 	omap_i2c_wait_for_bb(dev);
 out:
-	pm_runtime_put(dev->dev);
+	pm_runtime_mark_last_busy(dev->dev);
+	pm_runtime_put_autosuspend(dev->dev);
 	return r;
 }
 
@@ -1113,6 +1114,9 @@ omap_i2c_probe(struct platform_device *pdev)
 		dev->regs = (u8 *)reg_map_ip_v1;
 
 	pm_runtime_enable(dev->dev);
+	pm_runtime_set_autosuspend_delay(dev->dev, 1000);
+	pm_runtime_use_autosuspend(dev->dev);
+
 	r = pm_runtime_get_sync(dev->dev);
 	if (IS_ERR_VALUE(r))
 		goto err_free_mem;
@@ -1189,7 +1193,7 @@ omap_i2c_probe(struct platform_device *pdev)
 
 	of_i2c_register_devices(adap);
 
-	pm_runtime_put(dev->dev);
+	pm_runtime_put_autosuspend(dev->dev);
 
 	return 0;
 
Signature · 1 line
1.7.12.rc0
#5 lore raw

PATCH 4/4 i2c: omap: switch over to autosuspend API

Hi Felipe,

Quoted 34 lines · Felipe Balbi

this helps us reduce unnecessary pm transitions
in case we have another i2c message been started
soon.

---
 drivers/i2c/busses/i2c-omap.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)
drivers/i2c/busses/i2c-omap.c +5 -1
index 60928f2..22efaba 100644
@@ -645,7 +645,8 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
 
 	omap_i2c_wait_for_bb(dev);
 out:
-	pm_runtime_put(dev->dev);
+	pm_runtime_mark_last_busy(dev->dev);
+	pm_runtime_put_autosuspend(dev->dev);
 	return r;
 }
 
@@ -1113,6 +1114,9 @@ omap_i2c_probe(struct platform_device *pdev)
 		dev->regs = (u8 *)reg_map_ip_v1;
 
 	pm_runtime_enable(dev->dev);
+	pm_runtime_set_autosuspend_delay(dev->dev, 1000);
+	pm_runtime_use_autosuspend(dev->dev);
+
 	r = pm_runtime_get_sync(dev->dev);
 	if (IS_ERR_VALUE(r))
 		goto err_free_mem;

drivers/i2c/busses/i2c-omap.c omap_i2c_probe(struct platform_device *pdev) · line 1192

Quoted 4 lines
drivers/i2c/busses/i2c-omap.c +0 -1
@@ -1189,7 +1193,7 @@ omap_i2c_probe(struct platform_device *pdev)
 
 	of_i2c_register_devices(adap);
 
-	pm_runtime_put(dev->dev);

Should we mark it last busy stamp here here? Or it may not take effect till the first transaction.

Quoted 4 lines
drivers/i2c/busses/i2c-omap.c +1 -0
+	pm_runtime_put_autosuspend(dev->dev);
 
 	return 0;
 
#6 lore raw

PATCH 4/4 i2c: omap: switch over to autosuspend API

In reply to Felipe Balbi

Hi,

Quoted 34 lines · Felipe Balbi

this helps us reduce unnecessary pm transitions
in case we have another i2c message been started
soon.

---
 drivers/i2c/busses/i2c-omap.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)
drivers/i2c/busses/i2c-omap.c +5 -1
index 60928f2..22efaba 100644
@@ -645,7 +645,8 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
 
 	omap_i2c_wait_for_bb(dev);
 out:
-	pm_runtime_put(dev->dev);
+	pm_runtime_mark_last_busy(dev->dev);
+	pm_runtime_put_autosuspend(dev->dev);
 	return r;
 }
 
@@ -1113,6 +1114,9 @@ omap_i2c_probe(struct platform_device *pdev)
 		dev->regs = (u8 *)reg_map_ip_v1;
 
 	pm_runtime_enable(dev->dev);
+	pm_runtime_set_autosuspend_delay(dev->dev, 1000);
+	pm_runtime_use_autosuspend(dev->dev);
+
 	r = pm_runtime_get_sync(dev->dev);
 	if (IS_ERR_VALUE(r))
 		goto err_free_mem;

drivers/i2c/busses/i2c-omap.c omap_i2c_probe(struct platform_device *pdev) · line 1196

Quoted 5 lines
drivers/i2c/busses/i2c-omap.c +1 -1
@@ -1189,7 +1193,7 @@ omap_i2c_probe(struct platform_device *pdev)
 
 	of_i2c_register_devices(adap);
 
-	pm_runtime_put(dev->dev);
+	pm_runtime_put_autosuspend(dev->dev);

Probably... nice catch. Will send v2

Signature · 8 lines
balbi
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20120807/c737c871/attachment.sig>
#7 lore raw

PATCH 1/1 i2c: omap: switch over to autosuspend API

this helps us reduce unnecessary pm transitions
in case we have another i2c message been started
soon.

---
 drivers/i2c/busses/i2c-omap.c | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)
drivers/i2c/busses/i2c-omap.c +7 -2
index 60928f2..c210b45 100644
@@ -645,7 +645,8 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
 
 	omap_i2c_wait_for_bb(dev);
 out:
-	pm_runtime_put(dev->dev);
+	pm_runtime_mark_last_busy(dev->dev);
+	pm_runtime_put_autosuspend(dev->dev);
 	return r;
 }
 
@@ -1113,6 +1114,9 @@ omap_i2c_probe(struct platform_device *pdev)
 		dev->regs = (u8 *)reg_map_ip_v1;
 
 	pm_runtime_enable(dev->dev);
+	pm_runtime_set_autosuspend_delay(dev->dev, 1000);
+	pm_runtime_use_autosuspend(dev->dev);
+
 	r = pm_runtime_get_sync(dev->dev);
 	if (IS_ERR_VALUE(r))
 		goto err_free_mem;
@@ -1189,7 +1193,8 @@ omap_i2c_probe(struct platform_device *pdev)
 
 	of_i2c_register_devices(adap);
 
-	pm_runtime_put(dev->dev);
+	pm_runtime_mark_last_busy(dev->dev);
+	pm_runtime_put_autosuspend(dev->dev);
 
 	return 0;
 
Signature · 1 line
1.7.12.rc0
#8 lore raw

PATCH 1/1 i2c: omap: switch over to autosuspend API

Quoted 4 lines · Felipe

this helps us reduce unnecessary pm transitions
in case we have another i2c message been started
soon.

s/been started/starting ?

Quoted 20 lines
---
 drivers/i2c/busses/i2c-omap.c | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)
drivers/i2c/busses/i2c-omap.c +2 -1
index 60928f2..c210b45 100644
@@ -645,7 +645,8 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
 
 	omap_i2c_wait_for_bb(dev);
 out:
-	pm_runtime_put(dev->dev);
+	pm_runtime_mark_last_busy(dev->dev);
+	pm_runtime_put_autosuspend(dev->dev);
 	return r;
 }
 

drivers/i2c/busses/i2c-omap.c omap_i2c_probe(struct platform_device *pdev) · line 1117

Quoted 4 lines
drivers/i2c/busses/i2c-omap.c +1 -0
@@ -1113,6 +1114,9 @@ omap_i2c_probe(struct platform_device *pdev)
 		dev->regs = (u8 *)reg_map_ip_v1;
 
 	pm_runtime_enable(dev->dev);
+	pm_runtime_set_autosuspend_delay(dev->dev, 1000);

I guess there will always be a debate around what's the right delay for autosuspend ;)

You can at least replace the magic number with a macro.

Quoted 24 lines
drivers/i2c/busses/i2c-omap.c +4 -1
+	pm_runtime_use_autosuspend(dev->dev);
+
 	r = pm_runtime_get_sync(dev->dev);
 	if (IS_ERR_VALUE(r))
 		goto err_free_mem;
@@ -1189,7 +1193,8 @@ omap_i2c_probe(struct platform_device *pdev)
 
 	of_i2c_register_devices(adap);
 
-	pm_runtime_put(dev->dev);
+	pm_runtime_mark_last_busy(dev->dev);
+	pm_runtime_put_autosuspend(dev->dev);
 
 	return 0;
 
Signature · 7 lines
1.7.12.rc0


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel at lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
#9 lore raw

PATCH v3 1/1 i2c: omap: switch over to autosuspend API

this helps us reduce unnecessary pm transitions in case we have another i2c message starting soon.

---
 drivers/i2c/busses/i2c-omap.c | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)
drivers/i2c/busses/i2c-omap.c +10 -2
index 60928f2..35e8207 100644
@@ -55,6 +55,9 @@
 /* timeout waiting for the controller to respond */
 #define OMAP_I2C_TIMEOUT (msecs_to_jiffies(1000))
 
+/* timeout for pm runtime autosuspend */
+#define OMAP_I2C_PM_TIMEOUT		1000	/* ms */
+
 /* For OMAP3 I2C_IV has changed to I2C_WE (wakeup enable) */
 enum {
 	OMAP_I2C_REV_REG = 0,
@@ -645,7 +648,8 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
 
 	omap_i2c_wait_for_bb(dev);
 out:
-	pm_runtime_put(dev->dev);
+	pm_runtime_mark_last_busy(dev->dev);
+	pm_runtime_put_autosuspend(dev->dev);
 	return r;
 }
 
@@ -1113,6 +1117,9 @@ omap_i2c_probe(struct platform_device *pdev)
 		dev->regs = (u8 *)reg_map_ip_v1;
 
 	pm_runtime_enable(dev->dev);
+	pm_runtime_set_autosuspend_delay(dev->dev, OMAP_I2C_PM_TIMEOUT);
+	pm_runtime_use_autosuspend(dev->dev);
+
 	r = pm_runtime_get_sync(dev->dev);
 	if (IS_ERR_VALUE(r))
 		goto err_free_mem;
@@ -1189,7 +1196,8 @@ omap_i2c_probe(struct platform_device *pdev)
 
 	of_i2c_register_devices(adap);
 
-	pm_runtime_put(dev->dev);
+	pm_runtime_mark_last_busy(dev->dev);
+	pm_runtime_put_autosuspend(dev->dev);
 
 	return 0;
 
Signature · 1 line
1.7.12.rc0
#11 lore raw

cover i2c: omap: few more patches

In reply to Felipe Balbi
Quoted 4 lines · Felipe Balbi

Just a few extra patches on top of the earlier series I sent.

With these patches, we have threaded irq support and autosuspend support for i2c-omap driver.

Thanks for the patches.

Quoted 2 lines

All patches boot tested with pandaboard.

On omap4sdp and omap3sdp
also on omap3 did some basic power testing.

Quoted 9 lines

Felipe Balbi (4):
i2c: omap: always return IRQ_HANDLED
i2c: omap: switch to threaded IRQ support
i2c: omap: remove unnecessary pm_runtime_suspended check
i2c: omap: switch over to autosuspend API

 drivers/i2c/busses/i2c-omap.c | 53 ++++++++++++++++++++++++++++++++++---------
 1 file changed, 42 insertions(+), 11 deletions(-)