[Letux-kernel] [PATCHv2] i2c: omap: Use noirq system sleep pm ops to idle device for suspend
Andreas Kemnade
andreas at kemnade.info
Fri Feb 22 21:08:12 CET 2019
On Fri, 22 Feb 2019 09:25:04 -0800
Tony Lindgren <tony at atomide.com> wrote:
> * Andreas Kemnade <andreas at kemnade.info> [190222 17:09]:
> > Tony Lindgren <tony at atomide.com> wrote:
> > > It's probaby some twl related code is (wrongly) trying to read/write
> > > registers at noirq suspend level. Sounds like some driver tagged with
> > > noirq suspend ops while it should not.
> > >
> > static irqreturn_t handle_twl4030_pih(int irq, void *devid)
> > in
> > drivers/mfd/twl4030-irq.c
> > is doing the failed i2c access.
>
> I wonder if tagging drivers/mfd/twl4030-irq.c request_threaded_irq
> with IRQF_NO_SUSPEND in addition to IRQF_ONESHOT might help if this
IRQF_NO_SUSPEND does not help.
> triggers right after resume_device_irqs()? Or do we already have
> IRQF_NO_SUSPEND set and some interrupt like USB battery charging
> is triggering during suspend?
well, if we are doing rtcwake, we could expect to have a twl4030 rtc
interrupt sitting behind the pih.
I would consider usb battery charging irq here a bug because
twl4030_charger and phy-twl4030_usb are modules and not loaded.
Some more research:
what failed is this:
static int
omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
{
struct omap_i2c_dev *omap = i2c_get_adapdata(adap);
int i;
int r;
r = pm_runtime_get_sync(omap->dev);
if (r < 0) {
we get -EACCESS there.
It is indeed the case that
handle_twl4030_pih is called before i2c runtime resume.
Since we have threaded irq here, we can do some sleep in case of
problems. So this dirty hack helps:
diff --git a/drivers/mfd/twl4030-irq.c b/drivers/mfd/twl4030-irq.c
index b16c16f194fd..6c729c4ec9b0 100644
--- a/drivers/mfd/twl4030-irq.c
+++ b/drivers/mfd/twl4030-irq.c
@@ -34,6 +34,7 @@
#include <linux/of.h>
#include <linux/irqdomain.h>
#include <linux/mfd/twl.h>
+#include <linux/delay.h>
#include "twl-core.h"
@@ -298,7 +299,11 @@ static irqreturn_t handle_twl4030_pih(int irq, void *devid)
REG_PIH_ISR_P1);
if (ret) {
pr_warn("twl4030: I2C error %d reading PIH ISR\n", ret);
- return IRQ_NONE;
+ msleep(10);
+ ret = twl_i2c_read_u8(TWL_MODULE_PIH, &pih_isr,
+ REG_PIH_ISR_P1);
+ if (ret)
+ return IRQ_NONE;
}
while (pih_isr) {
So if for some reason handle_twl4030_pih is called late enough, we will
not have those problems.
So maybe we just need to add a suspend/resume callback pair in
twl-core.c and disable/enable the pih there? So when the pih is run,
runtime_pm is ready, so you are allowed to do pm_runtime_get()
To wake up from suspend, it is sufficient to have
twl4030_pins: pinmux_twl4030_pins {
pinctrl-single,pins = <
OMAP3_CORE1_IOPAD(0x21e0, PIN_INPUT_PULLUP | PIN_OFF_WAKEUPENABLE | MUX_MODE0) /* sys_nirq.sys_nirq */
>;
};
I can even do
@ -752,7 +757,9 @@ int twl4030_init_irq(struct device *dev, int irq_num)
dev_err(dev, "could not claim irq%d: %d\n", irq_num, status);
goto fail_rqirq;
}
+#if 0
enable_irq_wake(irq_num);
+#endif
return irq_base;
fail_rqirq:
at least here. So disabling that irq on suspend might be an option.
Regards,
Andreas
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 833 bytes
Desc: OpenPGP digital signature
URL: <http://lists.goldelico.com/pipermail/letux-kernel/attachments/20190222/1f42e382/attachment.asc>
More information about the Letux-kernel
mailing list