Re: [PATCH] i2c: omap: fix spurious IRQs: disable/enable IRQ at INTC when idle
to, 2012-11-01 kello 23:49 +0100, Wolfram Sang kirjoitti: Hi, Anyway new patch coming soon :) Was there one? I have skimmed a number of threads discussing spurious interrupts or interrupt floods but AFAICS all discussions ended up in trying another approach later or fixing the issue somewhere else than I2C. Is this correct? Or is there a bugfix patch left for 3.7 that I missed? The problem was not actually in the i2c driver itself, the twl4030 Primary/Secondary interrupt handler irq wake up order was the problem. The fix was this: https://patchwork.kernel.org/patch/1601271/ Actually, Samuel, did you pick up my patch? I never got any response after Kevin acked it. - Kalle Thanks, Wolfram -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v3] ARM: OMAP: i2c: fix interrupt flood during resume
ke, 2012-10-17 kello 19:02 +0300, Felipe Balbi kirjoitti: Hi, On Thu, Oct 11, 2012 at 02:08:25PM -0700, Kevin Hilman wrote: Hi Kalle, Kalle Jokiniemi kalle.jokini...@jollamobile.com writes: The resume_noirq enables interrupts one-by-one starting from first one. Now if the wake up event for suspend came from i2c device, the i2c bus irq gets enabled before the threaded i2c device irq, causing a flood of i2c bus interrupts as the threaded irq that should clear the event is not enabled yet. Fixed the issue by adding suspend_noirq and resume_early functions that keep i2c bus interrupts disabled until resume_noirq has run completely. Issue was detected doing a wake up from autosleep with twl4030 power key on N9. Patch tested on N9. Signed-off-by: Kalle Jokiniemi kalle.jokini...@jollamobile.com This version looks good, thanks for the extra comments. Reviewed-by: Kevin Hilman khil...@ti.com Tested-by: Kevin Hilman khil...@ti.com Wolfram, This should also probably be Cc'd to stable since it affects earlier kernels as well. Thanks, just to make sure we're not fixing the wrong problem... does [1] help in any way ? Yes, I was fixing the wrong problem, this patch is obsolete. But the problem was in the TWL interrupt handling (PIH was run before SIH), not in i2c. See my other patch twl4030: Fix chained irq handling on resume from suspend [1] http://marc.info/?l=linux-omapm=135048839915719w=2 Could be related, though if I understood correctly, that runtime pm stuff gets run at noirq phase, so it probably does not help. - Kalle -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] i2c: omap: fix spurious IRQs: disable/enable IRQ at INTC when idle
Hi, ma, 2012-10-15 kello 18:02 -0700, Tony Lindgren kirjoitti: * Kevin Hilman khil...@deeprootsystems.com [121015 10:32]: Kalle Jokiniemi kalle.jokini...@jollamobile.com writes: Does not work for me :( As I said, the issue occurs for me when I enter static suspend (echo mem /sys/power/autosleep or /sys/power/state). I don't think doing this just in runtime pm will fix my issue. Or do those handlers get run in the normal suspend path as well? If the I2C device is still active during the suspend path, these handlers will get run by the PM domain code (in omap_device.) However, now that I think about it, the current omap_device PM domain code calls these at the noirq level, not the late/early level, so it does not address your original problem. :( I suspect we'll need this and your original patch. Have you checked that this is not related to flushing the posted write? If it is, reading back any register from the i2c controller after writing to it ensures the write actually reaches the i2c controller. The twl4030-irq handler (handle_twl4030_pih) function just reads the PIH irq status over the i2c and calls handle_nested_irq for each set module (like USB, GPIO, etc) irq bit. This does not clear the interrupt however, that is done in the nested interrupt, once it runs (by clearing the actual interrupt inside the module). I'm thinking now that it's actually this PIH handler that should be postponed until resume_noirq has finished. I had another idea as well yesterday to mark the secondary irq handlers with IRQF_EARLY_RESUME flag. Though that did not work on the quick test I did. Anyway new patch coming soon :) - Kalle Regards, Tony -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 1/1] twl4030: Fix chained irq handling on resume from suspend
The irqs are enabled one-by-one in pm core resume_noirq phase. This leads to situation where the twl4030 primary interrupt handler (PIH) is enabled before the chained secondary handlers (SIH). As the PIH cannot clear the pending interrupt, and SIHs have not been enabled yet, a flood of interrupts hangs the device. Fixed the issue by setting the SIH irqs with IRQF_EARLY_RESUME flags, so they get enabled before the PIH. Signed-off-by: Kalle Jokiniemi kalle.jokini...@jollamobile.com --- drivers/mfd/twl4030-irq.c |3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/drivers/mfd/twl4030-irq.c b/drivers/mfd/twl4030-irq.c index ad733d7..cdd1173 100644 --- a/drivers/mfd/twl4030-irq.c +++ b/drivers/mfd/twl4030-irq.c @@ -672,7 +672,8 @@ int twl4030_sih_setup(struct device *dev, int module, int irq_base) irq = sih_mod + twl4030_irq_base; irq_set_handler_data(irq, agent); agent-irq_name = kasprintf(GFP_KERNEL, twl4030_%s, sih-name); - status = request_threaded_irq(irq, NULL, handle_twl4030_sih, 0, + status = request_threaded_irq(irq, NULL, handle_twl4030_sih, + IRQF_EARLY_RESUME, agent-irq_name ?: sih-name, NULL); dev_info(dev, %s (irq %d) chaining IRQs %d..%d\n, sih-name, -- 1.7.4.1 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 1/1] twl4030: Fix chained irq handling on resume from suspend
Hi, ti, 2012-10-16 kello 17:59 +0300, Kalle Jokiniemi kirjoitti: The irqs are enabled one-by-one in pm core resume_noirq phase. This leads to situation where the twl4030 primary interrupt handler (PIH) is enabled before the chained secondary handlers (SIH). As the PIH cannot clear the pending interrupt, and SIHs have not been enabled yet, a flood of interrupts hangs the device. Fixed the issue by setting the SIH irqs with IRQF_EARLY_RESUME flags, so they get enabled before the PIH. Did it this way now, since the tl4030_irq is not really a driver that could do normal suspend / resume calls... and this is what the flag is for. Added Samuel to recipients, as get_maintainer reported him as maintainer. - Kalle Signed-off-by: Kalle Jokiniemi kalle.jokini...@jollamobile.com --- drivers/mfd/twl4030-irq.c |3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/drivers/mfd/twl4030-irq.c b/drivers/mfd/twl4030-irq.c index ad733d7..cdd1173 100644 --- a/drivers/mfd/twl4030-irq.c +++ b/drivers/mfd/twl4030-irq.c @@ -672,7 +672,8 @@ int twl4030_sih_setup(struct device *dev, int module, int irq_base) irq = sih_mod + twl4030_irq_base; irq_set_handler_data(irq, agent); agent-irq_name = kasprintf(GFP_KERNEL, twl4030_%s, sih-name); - status = request_threaded_irq(irq, NULL, handle_twl4030_sih, 0, + status = request_threaded_irq(irq, NULL, handle_twl4030_sih, + IRQF_EARLY_RESUME, agent-irq_name ?: sih-name, NULL); dev_info(dev, %s (irq %d) chaining IRQs %d..%d\n, sih-name, -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
RE: [PATCH v3] ARM: OMAP: i2c: fix interrupt flood during resume
Hi, pe, 2012-10-12 kello 14:46 +, Strashko, Grygorii kirjoitti: Hi Kevin, yep, [1] is the same fix - thanks. Hi Kalle, i've applied these changes and PM runtime fix on top of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap.git (omap2plus_defconfig) Could you check it with your use case, pls? (just to be sure that idea is right) Odd, it's not working. I'll add some debug prints to see what happens there. - Kalle diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index a0e49f6..cb09e20 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -586,6 +586,9 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) if (IS_ERR_VALUE(r)) goto out; + /* We have the bus, enable IRQ */ + enable_irq(dev-irq); + r = omap_i2c_wait_for_bb(dev); if (r 0) goto out; @@ -606,6 +609,7 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) r = num; omap_i2c_wait_for_bb(dev); + disable_irq(dev-irq); out: pm_runtime_put(dev-dev); return r; @@ -1060,6 +1064,9 @@ omap_i2c_probe(struct platform_device *pdev) omap_i2c_isr; r = request_irq(dev-irq, isr, IRQF_NO_SUSPEND, pdev-name, dev); + /* We enable IRQ only when request for I2C from master */ +disable_irq(dev-irq); + if (r) { dev_err(dev-dev, failure requesting irq %i\n, dev-irq); goto err_unuse_clocks; @@ -1182,7 +1189,23 @@ static int omap_i2c_runtime_resume(struct device *dev) } #endif /* CONFIG_PM_RUNTIME */ +static int omap_i2c_suspend(struct device *dev) +{ + int ret; + + /* +* Enable I2C device, so it will be accessible during +* later stages of suspending when device Runtime PM is disabled. +* I2C device will be turned off at noirq suspend stage. +*/ + ret = pm_runtime_resume(dev); + if (ret 0) + return ret; + return 0; +} + static struct dev_pm_ops omap_i2c_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(omap_i2c_suspend, NULL) SET_RUNTIME_PM_OPS(omap_i2c_runtime_suspend, omap_i2c_runtime_resume, NULL) }; - Grygorii From: Kevin Hilman [khil...@deeprootsystems.com] Sent: Friday, October 12, 2012 5:34 PM To: Strashko, Grygorii Cc: Kalle Jokiniemi; linux-...@vger.kernel.org; w.s...@pengutronix.de; ben-li...@fluff.org; t...@atomide.com; linux-omap@vger.kernel.org; Datta, Shubhrajyoti; Kankroliwala, Huzefa Subject: Re: [PATCH v3] ARM: OMAP: i2c: fix interrupt flood during resume Strashko, Grygorii grygorii.stras...@ti.com writes: Hi All, Sorry, for the late reply. + CC Huzefa Kankroliwala - who is I2C driver owner on Android Kernel 3.4. Hi Grygorii, thanks for reviewing. I was hoping you would have some ideas here as this was sounding familiar to something you had mentioned elsewhere. Regarding this patch - from my point of view, it fixes corner case and not an issue in general. Let take a look on resume sequence: - platform resume - syscore resume - resume_noirq - enable IRQs - resume_device_irqs() |- at this point IRQ handler will be invoked if IRQ state is IRQS_PENDING. |- so, the I2C device IRQ handler may be called at time when I2C adapter IRQ is still disabled and, as result, the I2C device IRQ-handler may fail. (I2C device and I2C adapter may use different physical IRQ lines) - resume_late |- enable I2C bus IRQ Possibly, the better way is to enable/disable I2C bus IRQ when needed - in our case in omap_i2c_xfer(). We use such approach in Android kernel 3.4 (http://git.omapzoom.org/?p=kernel/omap.git;a=commitdiff;h=1445a4d3b587c164bd30d108b6176007365e) I agree, that should work and cover the cases where I2C is used by other processors also. Shubhrajyoti already posted something similar[1] but it needed some rework (comments from Russell and myself.) Huzefa, Shubhrajyoti, who can rework this idea for the upstream and/or follow up with the earlier patch[1]? Wolfram, I guess for now lets hold off on $SUBJECT patch. Seems we can come up with a broader solution. Thanks. Kevin [1] http://lists.infradead.org/pipermail/linux-arm-kernel/2012-October/124427.html -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] i2c: omap: fix spurious IRQs: disable/enable IRQ at INTC when idle
Hi, la, 2012-10-13 kello 01:00 +0530, Shubhrajyoti Datta kirjoitti: On Sat, Oct 13, 2012 at 12:10 AM, Kevin Hilman khil...@deeprootsystems.com wrote: From: Kevin Hilman khil...@ti.com Currently, runtime PM is used to keep the device enabled only during active transfers and for a configurable runtime PM autosuspend timout after an xfer. In addition to idling the device, driver's -runtime_suspend() method currently disables device interrupts when idle. However, on some SoCs (notably OMAP4+), the I2C hardware may shared with other coprocessors. This means that the MPU will still recieve interrupts if a coprocessor is using the I2C device. To avoid this, also disable interrupts at the MPU INTC when idling the device in -runtime_suspend() (and re-enable them in -runtime_resume().) This part based on an original patch from Shubhrajyoti Datta. NOTE: for proper sharing the I2C with a coprocessor, this driver still needs hwspinlock support added. This change is also meant to address an issue reported by Kalle Jokiniemi where I2C bus interrupt may be enabled before an I2C device interrupt handler (e.g. just after noirq resume phase) causing an It is actually in middle of resume_noirq. interrupt flood on the I2C bus interrupt before the device interrupt is enabled (e.g. interrupts coming from devices on I2C connected PMIC before the PMIC chained hanlder is enabled.) This problem is addresed by ensuring that the I2C bus interrupt left disabled until an I2C xfer is requested. Looks good to me. Will wait for Kalle though. Does not work for me :( As I said, the issue occurs for me when I enter static suspend (echo mem /sys/power/autosleep or /sys/power/state). I don't think doing this just in runtime pm will fix my issue. Or do those handlers get run in the normal suspend path as well? - Kalle Cc: Kalle Jokiniemi kalle.jokini...@jollamobile.com Cc: Grygorii Strashko grygorii.stras...@ti.com Cc: Shubhrajyoti Datta shubhrajy...@ti.com, Cc: Huzefa Kankroliwala huzef...@ti.com Cc: Nishanth Menon n...@ti.com Signed-off-by: Kevin Hilman khil...@ti.com --- drivers/i2c/busses/i2c-omap.c |3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index db31eae..e6413e8 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -1255,6 +1255,7 @@ static int omap_i2c_runtime_suspend(struct device *dev) /* Flush posted write */ omap_i2c_read_reg(_dev, OMAP_I2C_STAT_REG); } + disable_irq(_dev-irq); return 0; } @@ -1275,6 +1276,8 @@ static int omap_i2c_runtime_resume(struct device *dev) omap_i2c_write_reg(_dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN); } + enable_irq(_dev-irq); + /* * Don't write to this register if the IE state is 0 as it can * cause deadlock. -- 1.7.9.2 -- To unsubscribe from this list: send the line unsubscribe linux-i2c in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v3] ARM: OMAP: i2c: fix interrupt flood during resume
ma, 2012-10-15 kello 15:41 +0530, Shubhrajyoti Datta kirjoitti: On Mon, Oct 15, 2012 at 2:46 PM, Kalle Jokiniemi kalle.jokini...@jollamobile.com wrote: ma, 2012-10-15 kello 09:21 +0300, Kalle Jokiniemi kirjoitti: Hi, pe, 2012-10-12 kello 14:46 +, Strashko, Grygorii kirjoitti: Hi Kevin, yep, [1] is the same fix - thanks. Hi Kalle, i've applied these changes and PM runtime fix on top of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap.git (omap2plus_defconfig) Could you check it with your use case, pls? (just to be sure that idea is right) Odd, it's not working. I'll add some debug prints to see what happens there. Well, seems after enabling irq 23 in the resume_noirq, someone does i2c_xfer and there is consequent flood of i2c_xfers and interrupts. If there is continuous xfers, you could enable debug LL and see who is queuing the transfers. Not sure now how these IRQ numbers get mapped these days, my debug print says it's irq number 72 (UART1 from TRM) that is flooding (although it's printed from the i2c-omap isr function, so it's still I2C bus irq...). Can you do a cat /proc/interrupts Yes :) [root@localhost proc]# cat interrupts CPU0 20: 0 INTC gpmc 23: 2 INTC TWL4030-PIH 25: 0 INTC l3-debug-irq 26: 0 INTC l3-app-irq 28: 48157 INTC DMA 40: 0 INTC omap-iommu.0 52: 0 INTC dsp_wdt 53: 807807 INTC gp_timer 65: 0 INTC omap-sham 72: 5490 INTC omap_i2c 73: 85 INTC omap_i2c 77: 0 INTC omap_i2c 90: 1069 INTC OMAP UART2 102: 55940 INTC mmc0 179: 6142 GPIO omap2-onenand 306: 44666 PRCM pm_wkup 315: 4 PRCM hwmod_io, pm_io 338: 0 twl4030 twl4030_gpio 343: 2 twl4030 twl4030_power 346: 0 twl4030 twl4030_pwrbutton 348: 2 twl4030 twl4030_usb 349: 0 twl4030 rtc0 Hmm, I did not notice that PIH handler before, makes sense now that it triggers the flood (irq 23) as it is really the one that passes the interrupts to other handlers. - Kalle The irq enabling (in resume_noirq) is still slightly progressing after the flooding starts, but my watchdog kicks in before we get to the finish. Attached my debug prints patch and log. I used also no_console_suspend boot option. - Kalle -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
RE: [PATCH v3] ARM: OMAP: i2c: fix interrupt flood during resume
Hi, pe, 2012-10-12 kello 10:18 +, Strashko, Grygorii kirjoitti: Hi All, Sorry, for the late reply. + CC Huzefa Kankroliwala - who is I2C driver owner on Android Kernel 3.4. Regarding this patch - from my point of view, it fixes corner case and not an issue in general. Let take a look on resume sequence: - platform resume - syscore resume - resume_noirq - enable IRQs - resume_device_irqs() |- at this point IRQ handler will be invoked if IRQ state is IRQS_PENDING. |- so, the I2C device IRQ handler may be called at time when I2C adapter IRQ is still disabled and, as result, the I2C device IRQ-handler may fail. (I2C device and I2C adapter may use different physical IRQ lines) The use case is to wake up the the device from suspend via twl4030 power key line. The twl4030 then will interrupt host via the i2c bus. And on the host the i2c bus is then read by the twl4030-pwrkey threaded SW interrupt (which is disabled at the point when i2c bus HW interrupt occurs). - resume_late |- enable I2C bus IRQ Possibly, the better way is to enable/disable I2C bus IRQ when needed - in our case in omap_i2c_xfer(). We use such approach in Android kernel 3.4 (http://git.omapzoom.org/?p=kernel/omap.git;a=commitdiff;h=1445a4d3b587c164bd30d108b6176007365e) Sounds like it could work... however I tested the patch above, but my device now dies when waking it from suspend (autosleep, actually) with power key :( Have you guys considered reworking that patch for upstream? There seems to be some spinlocking there that was not in linux-omap that I tested on. - Kalle Grygorii From: Kevin Hilman [khil...@deeprootsystems.com] Sent: Friday, October 12, 2012 12:08 AM To: Kalle Jokiniemi Cc: linux-...@vger.kernel.org; w.s...@pengutronix.de; ben-li...@fluff.org; t...@atomide.com; linux-omap@vger.kernel.org; Strashko, Grygorii; Datta, Shubhrajyoti Subject: Re: [PATCH v3] ARM: OMAP: i2c: fix interrupt flood during resume Hi Kalle, Kalle Jokiniemi kalle.jokini...@jollamobile.com writes: The resume_noirq enables interrupts one-by-one starting from first one. Now if the wake up event for suspend came from i2c device, the i2c bus irq gets enabled before the threaded i2c device irq, causing a flood of i2c bus interrupts as the threaded irq that should clear the event is not enabled yet. Fixed the issue by adding suspend_noirq and resume_early functions that keep i2c bus interrupts disabled until resume_noirq has run completely. Issue was detected doing a wake up from autosleep with twl4030 power key on N9. Patch tested on N9. Signed-off-by: Kalle Jokiniemi kalle.jokini...@jollamobile.com This version looks good, thanks for the extra comments. Reviewed-by: Kevin Hilman khil...@ti.com Tested-by: Kevin Hilman khil...@ti.com Wolfram, This should also probably be Cc'd to stable since it affects earlier kernels as well. Thanks, Kevin --- drivers/i2c/busses/i2c-omap.c | 34 ++ 1 files changed, 34 insertions(+), 0 deletions(-) diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index a0e49f6..991341b 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -1132,6 +1132,36 @@ static int __devexit omap_i2c_remove(struct platform_device *pdev) } #ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP +static int omap_i2c_suspend_noirq(struct device *dev) +{ + + struct platform_device *pdev = to_platform_device(dev); + struct omap_i2c_dev *_dev = platform_get_drvdata(pdev); + + /* Disabling irq here to balance the enable in resume_early */ + disable_irq(_dev-irq); + return 0; +} + +static int omap_i2c_resume_early(struct device *dev) +{ + + struct platform_device *pdev = to_platform_device(dev); + struct omap_i2c_dev *_dev = platform_get_drvdata(pdev); + + /* + * The noirq_resume enables the interrupts one by one, + * this causes a interrupt flood if the SW irq actually reading + * event from i2c device is enabled only after i2c bus irq, as the + * irq that should clear the event is still disabled. We have to + * keep the bus irq disabled until all other irqs have been enabled. + */ + enable_irq(_dev-irq); + + return 0; +} +#endif #ifdef CONFIG_PM_RUNTIME static int omap_i2c_runtime_suspend(struct device *dev) { @@ -1183,6 +1213,10 @@ static int omap_i2c_runtime_resume(struct device *dev) #endif /* CONFIG_PM_RUNTIME */ static struct dev_pm_ops omap_i2c_pm_ops = { +#ifdef CONFIG_PM_SLEEP + .suspend_noirq = omap_i2c_suspend_noirq, + .resume_early = omap_i2c_resume_early, +#endif SET_RUNTIME_PM_OPS(omap_i2c_runtime_suspend, omap_i2c_runtime_resume, NULL
[PATCH v2] ARM: OMAP: i2c: fix interrupt flood during resume
The resume_noirq enables interrupts one-by-one starting from first one. Now if the wake up event for suspend came from i2c device, the i2c bus irq gets enabled before the threaded i2c device irq, causing a flood of i2c bus interrupts as the threaded irq that should clear the event is not enabled yet. Fixed the issue by adding suspend_late and resume_early functions that keep i2c bus interrupts disabled until resume_noirq has run completely. Issue was detected doing a wake up from autosleep with twl4030 power key on N9. Patch tested on N9. Signed-off-by: Kalle Jokiniemi kalle.jokini...@jollamobile.com --- drivers/i2c/busses/i2c-omap.c | 34 ++ 1 files changed, 34 insertions(+), 0 deletions(-) diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index a0e49f6..991341b 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -1132,6 +1132,36 @@ static int __devexit omap_i2c_remove(struct platform_device *pdev) } #ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP +static int omap_i2c_suspend_noirq(struct device *dev) +{ + + struct platform_device *pdev = to_platform_device(dev); + struct omap_i2c_dev *_dev = platform_get_drvdata(pdev); + + /* Disabling irq here to balance the enable in resume_early */ + disable_irq(_dev-irq); + return 0; +} + +static int omap_i2c_resume_early(struct device *dev) +{ + + struct platform_device *pdev = to_platform_device(dev); + struct omap_i2c_dev *_dev = platform_get_drvdata(pdev); + + /* +* The noirq_resume enables the interrupts one by one, +* this causes a interrupt flood if the SW irq actually reading +* event from i2c device is enabled only after i2c bus irq, as the +* irq that should clear the event is still disabled. We have to +* keep the bus irq disabled until all other irqs have been enabled. +*/ + enable_irq(_dev-irq); + + return 0; +} +#endif #ifdef CONFIG_PM_RUNTIME static int omap_i2c_runtime_suspend(struct device *dev) { @@ -1183,6 +1213,10 @@ static int omap_i2c_runtime_resume(struct device *dev) #endif /* CONFIG_PM_RUNTIME */ static struct dev_pm_ops omap_i2c_pm_ops = { +#ifdef CONFIG_PM_SLEEP + .suspend_noirq = omap_i2c_suspend_noirq, + .resume_early = omap_i2c_resume_early, +#endif SET_RUNTIME_PM_OPS(omap_i2c_runtime_suspend, omap_i2c_runtime_resume, NULL) }; -- 1.7.4.1 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v2] ARM: OMAP: i2c: fix interrupt flood during resume
ke, 2012-10-10 kello 14:46 +0300, Kalle Jokiniemi kirjoitti: The resume_noirq enables interrupts one-by-one starting from first one. Now if the wake up event for suspend came from i2c device, the i2c bus irq gets enabled before the threaded i2c device irq, causing a flood of i2c bus interrupts as the threaded irq that should clear the event is not enabled yet. Fixed the issue by adding suspend_late and resume_early functions that keep i2c bus interrupts disabled until resume_noirq has run completely. Issue was detected doing a wake up from autosleep with twl4030 power key on N9. Patch tested on N9. I did this now on top of latest linux-omap, should apply also to Jean's staging tree. Let me know if something more is needed. - Kalle Signed-off-by: Kalle Jokiniemi kalle.jokini...@jollamobile.com --- drivers/i2c/busses/i2c-omap.c | 34 ++ 1 files changed, 34 insertions(+), 0 deletions(-) diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index a0e49f6..991341b 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -1132,6 +1132,36 @@ static int __devexit omap_i2c_remove(struct platform_device *pdev) } #ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP +static int omap_i2c_suspend_noirq(struct device *dev) +{ + + struct platform_device *pdev = to_platform_device(dev); + struct omap_i2c_dev *_dev = platform_get_drvdata(pdev); + + /* Disabling irq here to balance the enable in resume_early */ + disable_irq(_dev-irq); + return 0; +} + +static int omap_i2c_resume_early(struct device *dev) +{ + + struct platform_device *pdev = to_platform_device(dev); + struct omap_i2c_dev *_dev = platform_get_drvdata(pdev); + + /* + * The noirq_resume enables the interrupts one by one, + * this causes a interrupt flood if the SW irq actually reading + * event from i2c device is enabled only after i2c bus irq, as the + * irq that should clear the event is still disabled. We have to + * keep the bus irq disabled until all other irqs have been enabled. + */ + enable_irq(_dev-irq); + + return 0; +} +#endif #ifdef CONFIG_PM_RUNTIME static int omap_i2c_runtime_suspend(struct device *dev) { @@ -1183,6 +1213,10 @@ static int omap_i2c_runtime_resume(struct device *dev) #endif /* CONFIG_PM_RUNTIME */ static struct dev_pm_ops omap_i2c_pm_ops = { +#ifdef CONFIG_PM_SLEEP + .suspend_noirq = omap_i2c_suspend_noirq, + .resume_early = omap_i2c_resume_early, +#endif SET_RUNTIME_PM_OPS(omap_i2c_runtime_suspend, omap_i2c_runtime_resume, NULL) }; -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3] ARM: OMAP: i2c: fix interrupt flood during resume
The resume_noirq enables interrupts one-by-one starting from first one. Now if the wake up event for suspend came from i2c device, the i2c bus irq gets enabled before the threaded i2c device irq, causing a flood of i2c bus interrupts as the threaded irq that should clear the event is not enabled yet. Fixed the issue by adding suspend_noirq and resume_early functions that keep i2c bus interrupts disabled until resume_noirq has run completely. Issue was detected doing a wake up from autosleep with twl4030 power key on N9. Patch tested on N9. Signed-off-by: Kalle Jokiniemi kalle.jokini...@jollamobile.com --- drivers/i2c/busses/i2c-omap.c | 34 ++ 1 files changed, 34 insertions(+), 0 deletions(-) diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index a0e49f6..991341b 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -1132,6 +1132,36 @@ static int __devexit omap_i2c_remove(struct platform_device *pdev) } #ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP +static int omap_i2c_suspend_noirq(struct device *dev) +{ + + struct platform_device *pdev = to_platform_device(dev); + struct omap_i2c_dev *_dev = platform_get_drvdata(pdev); + + /* Disabling irq here to balance the enable in resume_early */ + disable_irq(_dev-irq); + return 0; +} + +static int omap_i2c_resume_early(struct device *dev) +{ + + struct platform_device *pdev = to_platform_device(dev); + struct omap_i2c_dev *_dev = platform_get_drvdata(pdev); + + /* +* The noirq_resume enables the interrupts one by one, +* this causes a interrupt flood if the SW irq actually reading +* event from i2c device is enabled only after i2c bus irq, as the +* irq that should clear the event is still disabled. We have to +* keep the bus irq disabled until all other irqs have been enabled. +*/ + enable_irq(_dev-irq); + + return 0; +} +#endif #ifdef CONFIG_PM_RUNTIME static int omap_i2c_runtime_suspend(struct device *dev) { @@ -1183,6 +1213,10 @@ static int omap_i2c_runtime_resume(struct device *dev) #endif /* CONFIG_PM_RUNTIME */ static struct dev_pm_ops omap_i2c_pm_ops = { +#ifdef CONFIG_PM_SLEEP + .suspend_noirq = omap_i2c_suspend_noirq, + .resume_early = omap_i2c_resume_early, +#endif SET_RUNTIME_PM_OPS(omap_i2c_runtime_suspend, omap_i2c_runtime_resume, NULL) }; -- 1.7.4.1 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] i2c: i2c-omap: fix interrupt flood during resume
pe, 2012-10-05 kello 15:07 -0700, Kevin Hilman kirjoitti: +Grygorii (who's been working on various I2C related suspend/resume issues also) Hi Kalle, Kalle Jokiniemi kalle.jokini...@jollamobile.com writes: The resume_noirq enables interrupts one-by-one starting from first one. Now if the wake up event for suspend came from i2c device, the i2c bus irq gets enabled before the threaded i2c device irq, causing a flood of i2c bus interrupts as the threaded irq that should clear the event is not enabled yet. Ugh, another reason we need some sort of driver dependency tracking in the driver model. Fixed the issue by adding suspend_late and resume_early functions that keep i2c bus interrupts disabled until resume_noirq has run completely. Hmm, any reason we couldn't put the disable in the .suspend_noirq callback? I just liked the symmetry of late/early. The reason being is that other drivers might use I2C in their suspend or late_suspend callbacks. I'm not aware of any using I2C in their late_suspend callbacks in mainline, but in theory I2C should work all the way through the late callbacks. Makes sense, I'll change that. I know it might look strange to have a disable_irq() in the noirq callback, since IRQs are already disabled at that point, but a comment stating that it's just there to balance the (re)enable in the early_resume callback should be clear. Some other minor comments below... Issue was detected doing a wake up from autosleep with twl4030 power key on N9. Patch tested on N9. Signed-off-by: Kalle Jokiniemi kalle.jokini...@jollamobile.com --- drivers/i2c/busses/i2c-omap.c | 37 + 1 files changed, 37 insertions(+), 0 deletions(-) diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index 801df60..b77b0c2 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -1158,6 +1158,35 @@ omap_i2c_remove(struct platform_device *pdev) return 0; } +#ifdef CONFIG_SUSPEND This should be CONFIG_PM_SLEEP in order to cover hibernation also. Ok, I'll fix these, thanks. +static int omap_i2c_suspend_late(struct device *dev) +{ + + struct platform_device *pdev = to_platform_device(dev); + struct omap_i2c_dev *_dev = platform_get_drvdata(pdev); + + /* +* The noirq_resume enables the interrupts one by one, +* this causes a interrupt flood if the SW irq actually reading +* event from i2c device is enabled only after i2c bus irq, as the +* irq that should clear the event is still disabled. We have to +* disable the bus irq until all other irqs have been enabled. +*/ This comment probably belongs in the resume handler. Ok. I'll move it. - Kalle + disable_irq(_dev-irq); + return 0; +} + +static int omap_i2c_resume_early(struct device *dev) +{ + + struct platform_device *pdev = to_platform_device(dev); + struct omap_i2c_dev *_dev = platform_get_drvdata(pdev); + + enable_irq(_dev-irq); + + return 0; +} +#endif #ifdef CONFIG_PM_RUNTIME static int omap_i2c_runtime_suspend(struct device *dev) { @@ -1178,10 +1207,18 @@ static int omap_i2c_runtime_resume(struct device *dev) return 0; } +#endif +#if defined(CONFIG_SUSPEND) || defined(CONFIG_PM_RUNTIME) #ifdef CONFIG_PM will cover this static struct dev_pm_ops omap_i2c_pm_ops = { +#ifdef CONFIG_SUSPEND again, CONFIG_PM_SLEEP here + .suspend_late = omap_i2c_suspend_late, + .resume_early = omap_i2c_resume_early, +#endif +#ifdef CONFIG_PM_RUNTIME .runtime_suspend = omap_i2c_runtime_suspend, .runtime_resume = omap_i2c_runtime_resume, +#endif }; #define OMAP_I2C_PM_OPS (omap_i2c_pm_ops) #else Kevin -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] i2c: i2c-omap: fix interrupt flood during resume
The resume_noirq enables interrupts one-by-one starting from first one. Now if the wake up event for suspend came from i2c device, the i2c bus irq gets enabled before the threaded i2c device irq, causing a flood of i2c bus interrupts as the threaded irq that should clear the event is not enabled yet. Fixed the issue by adding suspend_late and resume_early functions that keep i2c bus interrupts disabled until resume_noirq has run completely. Issue was detected doing a wake up from autosleep with twl4030 power key on N9. Patch tested on N9. Signed-off-by: Kalle Jokiniemi kalle.jokini...@jollamobile.com --- drivers/i2c/busses/i2c-omap.c | 37 + 1 files changed, 37 insertions(+), 0 deletions(-) diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index 801df60..b77b0c2 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -1158,6 +1158,35 @@ omap_i2c_remove(struct platform_device *pdev) return 0; } +#ifdef CONFIG_SUSPEND +static int omap_i2c_suspend_late(struct device *dev) +{ + + struct platform_device *pdev = to_platform_device(dev); + struct omap_i2c_dev *_dev = platform_get_drvdata(pdev); + + /* +* The noirq_resume enables the interrupts one by one, +* this causes a interrupt flood if the SW irq actually reading +* event from i2c device is enabled only after i2c bus irq, as the +* irq that should clear the event is still disabled. We have to +* disable the bus irq until all other irqs have been enabled. +*/ + disable_irq(_dev-irq); + return 0; +} + +static int omap_i2c_resume_early(struct device *dev) +{ + + struct platform_device *pdev = to_platform_device(dev); + struct omap_i2c_dev *_dev = platform_get_drvdata(pdev); + + enable_irq(_dev-irq); + + return 0; +} +#endif #ifdef CONFIG_PM_RUNTIME static int omap_i2c_runtime_suspend(struct device *dev) { @@ -1178,10 +1207,18 @@ static int omap_i2c_runtime_resume(struct device *dev) return 0; } +#endif +#if defined(CONFIG_SUSPEND) || defined(CONFIG_PM_RUNTIME) static struct dev_pm_ops omap_i2c_pm_ops = { +#ifdef CONFIG_SUSPEND + .suspend_late = omap_i2c_suspend_late, + .resume_early = omap_i2c_resume_early, +#endif +#ifdef CONFIG_PM_RUNTIME .runtime_suspend = omap_i2c_runtime_suspend, .runtime_resume = omap_i2c_runtime_resume, +#endif }; #define OMAP_I2C_PM_OPS (omap_i2c_pm_ops) #else -- 1.7.4.1 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 0/2] omap3isp/rx-51: Add vdds_csib regulator handling
The CSIb block is used in rx-51 to handle camera ccp2 IO. Adding support to omap3isp driver for managing the power supply for the CSIb IO complex via regulator framework. Also create the apropriate regulator definitions in the rx-51 board file. I propose to push this set through the linux-media, since most of the changes are on the omap3isp driver side. Tested on Nokia N900 and the MeeGo testing daily images (.37 based kernel). Patches on top of Mauro's linux-next tree, build tested and boot tested with that. v2: updated patch 1/2 with comment from Laurent Pinchart v3: removed unnecessary vaux2 consumer regulator supply Kalle Jokiniemi (2): OMAP3: ISP: Add regulator control for omap34xx OMAP3: RX-51: define vdds_csib regulator supply arch/arm/mach-omap2/board-rx51-peripherals.c |6 + drivers/media/video/omap3isp/ispccp2.c | 27 - drivers/media/video/omap3isp/ispccp2.h |1 + 3 files changed, 32 insertions(+), 2 deletions(-) -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 2/2] OMAP3: RX-51: define vdds_csib regulator supply
The RX-51 uses the CSIb IO complex for camera operation. The board file is missing definition for the regulator supplying the CSIb complex, so this is added for better power management. Signed-off-by: Kalle Jokiniemi kalle.jokini...@nokia.com --- arch/arm/mach-omap2/board-rx51-peripherals.c |6 ++ 1 files changed, 6 insertions(+), 0 deletions(-) diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c index bbcb677..2f12425 100644 --- a/arch/arm/mach-omap2/board-rx51-peripherals.c +++ b/arch/arm/mach-omap2/board-rx51-peripherals.c @@ -337,6 +337,10 @@ static struct omap2_hsmmc_info mmc[] __initdata = { static struct regulator_consumer_supply rx51_vmmc1_supply = REGULATOR_SUPPLY(vmmc, omap_hsmmc.0); +static struct regulator_consumer_supply rx51_vaux2_supply[] = { + REGULATOR_SUPPLY(vdds_csib, omap3isp), +}; + static struct regulator_consumer_supply rx51_vaux3_supply = REGULATOR_SUPPLY(vmmc, omap_hsmmc.1); @@ -400,6 +404,8 @@ static struct regulator_init_data rx51_vaux2 = { .valid_ops_mask = REGULATOR_CHANGE_MODE | REGULATOR_CHANGE_STATUS, }, + .num_consumer_supplies = 1, + .consumer_supplies = rx51_vaux2_supply, }; /* VAUX3 - adds more power to VIO_18 rail */ -- 1.7.1 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 1/2] OMAP3: ISP: Add regulator control for omap34xx
The current omap3isp driver is missing regulator handling for CSIb complex in omap34xx based devices. This patch adds a mechanism for this to the omap3isp driver. Signed-off-by: Kalle Jokiniemi kalle.jokini...@nokia.com Acked-by: Laurent Pinchart laurent.pinch...@ideasonboard.com --- drivers/media/video/omap3isp/ispccp2.c | 27 +-- drivers/media/video/omap3isp/ispccp2.h |1 + 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/omap3isp/ispccp2.c b/drivers/media/video/omap3isp/ispccp2.c index 0e16cab..ec9e395 100644 --- a/drivers/media/video/omap3isp/ispccp2.c +++ b/drivers/media/video/omap3isp/ispccp2.c @@ -30,6 +30,7 @@ #include linux/module.h #include linux/mutex.h #include linux/uaccess.h +#include linux/regulator/consumer.h #include isp.h #include ispreg.h @@ -163,6 +164,9 @@ static void ccp2_if_enable(struct isp_ccp2_device *ccp2, u8 enable) struct isp_pipeline *pipe = to_isp_pipeline(ccp2-subdev.entity); int i; + if (enable ccp2-vdds_csib) + regulator_enable(ccp2-vdds_csib); + /* Enable/Disable all the LCx channels */ for (i = 0; i CCP2_LCx_CHANS_NUM; i++) isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LCx_CTRL(i), @@ -186,6 +190,9 @@ static void ccp2_if_enable(struct isp_ccp2_device *ccp2, u8 enable) ISPCCP2_LC01_IRQENABLE, ISPCCP2_LC01_IRQSTATUS_LC0_FS_IRQ); } + + if (!enable ccp2-vdds_csib) + regulator_disable(ccp2-vdds_csib); } /* @@ -1137,6 +1144,9 @@ error: */ void omap3isp_ccp2_cleanup(struct isp_device *isp) { + struct isp_ccp2_device *ccp2 = isp-isp_ccp2; + + regulator_put(ccp2-vdds_csib); } /* @@ -1151,14 +1161,27 @@ int omap3isp_ccp2_init(struct isp_device *isp) init_waitqueue_head(ccp2-wait); - /* On the OMAP36xx, the CCP2 uses the CSI PHY1 or PHY2, shared with + /* +* On the OMAP34xx the CSI1 receiver is operated in the CSIb IO +* complex, which is powered by vdds_csib power rail. Hence the +* request for the regulator. +* +* On the OMAP36xx, the CCP2 uses the CSI PHY1 or PHY2, shared with * the CSI2c or CSI2a receivers. The PHY then needs to be explicitly * configured. * * TODO: Don't hardcode the usage of PHY1 (shared with CSI2c). */ - if (isp-revision == ISP_REVISION_15_0) + if (isp-revision == ISP_REVISION_2_0) { + ccp2-vdds_csib = regulator_get(isp-dev, vdds_csib); + if (IS_ERR(ccp2-vdds_csib)) { + dev_dbg(isp-dev, + Could not get regulator vdds_csib\n); + ccp2-vdds_csib = NULL; + } + } else if (isp-revision == ISP_REVISION_15_0) { ccp2-phy = isp-isp_csiphy1; + } ret = ccp2_init_entities(ccp2); if (ret 0) diff --git a/drivers/media/video/omap3isp/ispccp2.h b/drivers/media/video/omap3isp/ispccp2.h index 5505a86..6674e9d 100644 --- a/drivers/media/video/omap3isp/ispccp2.h +++ b/drivers/media/video/omap3isp/ispccp2.h @@ -81,6 +81,7 @@ struct isp_ccp2_device { struct isp_interface_mem_config mem_cfg; struct isp_video video_in; struct isp_csiphy *phy; + struct regulator *vdds_csib; unsigned int error; enum isp_pipeline_stream_state state; wait_queue_head_t wait; -- 1.7.1 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 1/1] OMAP3: rx-51: Add full regulator definitions
The vaux2 (VCSI) regulator is left on by the bootloader in rx-51. Since there the product has shipped and there won't be any bootloader updates to fix this issue, we need to define all the regulators and declare full constraints for the regulator FW. This will allow the regulator FW to disable unused regulators. Also this helps in adding more fine grain regulator support for rx-51 in the future. Thanks for Mark Brown for pointing out the correct solution. Signed-off-by: Kalle Jokiniemi kalle.jokini...@nokia.com Cc: Mark Brown broo...@opensource.wolfsonmicro.com --- arch/arm/mach-omap2/board-rx51-peripherals.c | 69 ++ 1 files changed, 69 insertions(+), 0 deletions(-) diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c index bbcb677..4026b4b 100644 --- a/arch/arm/mach-omap2/board-rx51-peripherals.c +++ b/arch/arm/mach-omap2/board-rx51-peripherals.c @@ -475,6 +475,32 @@ static struct regulator_init_data rx51_vmmc2 = { .consumer_supplies = rx51_vmmc2_supplies, }; +static struct regulator_init_data rx51_vpll1 = { + .constraints = { + .name = VPLL, + .min_uV = 180, + .max_uV = 180, + .apply_uV = true, + .always_on = true, + .valid_modes_mask = REGULATOR_MODE_NORMAL + | REGULATOR_MODE_STANDBY, + .valid_ops_mask = REGULATOR_CHANGE_MODE, + }, +}; + +static struct regulator_init_data rx51_vpll2 = { + .constraints = { + .name = VSDI_CSI, + .min_uV = 180, + .max_uV = 180, + .apply_uV = true, + .always_on = true, + .valid_modes_mask = REGULATOR_MODE_NORMAL + | REGULATOR_MODE_STANDBY, + .valid_ops_mask = REGULATOR_CHANGE_MODE, + }, +}; + static struct regulator_init_data rx51_vsim = { .constraints = { .name = VMMC2_IO_18, @@ -519,6 +545,43 @@ static struct regulator_init_data rx51_vio = { .consumer_supplies = rx51_vio_supplies, }; +static struct regulator_init_data rx51_vintana1 = { + .constraints = { + .name = VINTANA1, + .min_uV = 150, + .max_uV = 150, + .always_on = true, + .valid_modes_mask = REGULATOR_MODE_NORMAL + | REGULATOR_MODE_STANDBY, + .valid_ops_mask = REGULATOR_CHANGE_MODE, + }, +}; + +static struct regulator_init_data rx51_vintana2 = { + .constraints = { + .name = VINTANA2, + .min_uV = 275, + .max_uV = 275, + .apply_uV = true, + .always_on = true, + .valid_modes_mask = REGULATOR_MODE_NORMAL + | REGULATOR_MODE_STANDBY, + .valid_ops_mask = REGULATOR_CHANGE_MODE, + }, +}; + +static struct regulator_init_data rx51_vintdig = { + .constraints = { + .name = VINTDIG, + .min_uV = 150, + .max_uV = 150, + .always_on = true, + .valid_modes_mask = REGULATOR_MODE_NORMAL + | REGULATOR_MODE_STANDBY, + .valid_ops_mask = REGULATOR_CHANGE_MODE, + }, +}; + static struct si4713_platform_data rx51_si4713_i2c_data __initdata_or_module = { .gpio_reset = RX51_FMTX_RESET_GPIO, }; @@ -767,8 +830,13 @@ static struct twl4030_platform_data rx51_twldata __initdata = { .vaux2 = rx51_vaux2, .vaux4 = rx51_vaux4, .vmmc1 = rx51_vmmc1, + .vpll1 = rx51_vpll1, + .vpll2 = rx51_vpll2, .vsim = rx51_vsim, .vdac = rx51_vdac, + .vintana1 = rx51_vintana1, + .vintana2 = rx51_vintana2, + .vintdig= rx51_vintdig, .vio= rx51_vio, }; @@ -969,6 +1037,7 @@ error: void __init rx51_peripherals_init(void) { rx51_i2c_init(); + regulator_has_full_constraints(); gpmc_onenand_init(board_onenand_data); board_smc91x_init(); rx51_add_gpio_keys(); -- 1.7.1 -- To unsubscribe from this list: send the line unsubscribe linux-omap
[PATCH v2 0/1] RX-51: add full regulator definitions
Adding regulator definitions to correctly shut down unneeded regulators. Needed, but previously undefined regulators were marked always_on. Tested on top of MeeGo N900 DE daily release (.37 kernel) and with linux-omap. Patch based on linux-omap HEAD. v2: updated as per comments from Jarkko Nikula and Mark Brown. Kalle Jokiniemi (1): OMAP3: rx-51: Add full regulator definitions arch/arm/mach-omap2/board-rx51-peripherals.c | 69 ++ 1 files changed, 69 insertions(+), 0 deletions(-) -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 1/2] OMAP3: ISP: Add regulator control for omap34xx
The current omap3isp driver is missing regulator handling for CSIb complex in omap34xx based devices. This patch adds a mechanism for this to the omap3isp driver. Signed-off-by: Kalle Jokiniemi kalle.jokini...@nokia.com --- drivers/media/video/omap3isp/ispccp2.c | 27 +-- drivers/media/video/omap3isp/ispccp2.h |1 + 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/omap3isp/ispccp2.c b/drivers/media/video/omap3isp/ispccp2.c index 0e16cab..ec9e395 100644 --- a/drivers/media/video/omap3isp/ispccp2.c +++ b/drivers/media/video/omap3isp/ispccp2.c @@ -30,6 +30,7 @@ #include linux/module.h #include linux/mutex.h #include linux/uaccess.h +#include linux/regulator/consumer.h #include isp.h #include ispreg.h @@ -163,6 +164,9 @@ static void ccp2_if_enable(struct isp_ccp2_device *ccp2, u8 enable) struct isp_pipeline *pipe = to_isp_pipeline(ccp2-subdev.entity); int i; + if (enable ccp2-vdds_csib) + regulator_enable(ccp2-vdds_csib); + /* Enable/Disable all the LCx channels */ for (i = 0; i CCP2_LCx_CHANS_NUM; i++) isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LCx_CTRL(i), @@ -186,6 +190,9 @@ static void ccp2_if_enable(struct isp_ccp2_device *ccp2, u8 enable) ISPCCP2_LC01_IRQENABLE, ISPCCP2_LC01_IRQSTATUS_LC0_FS_IRQ); } + + if (!enable ccp2-vdds_csib) + regulator_disable(ccp2-vdds_csib); } /* @@ -1137,6 +1144,9 @@ error: */ void omap3isp_ccp2_cleanup(struct isp_device *isp) { + struct isp_ccp2_device *ccp2 = isp-isp_ccp2; + + regulator_put(ccp2-vdds_csib); } /* @@ -1151,14 +1161,27 @@ int omap3isp_ccp2_init(struct isp_device *isp) init_waitqueue_head(ccp2-wait); - /* On the OMAP36xx, the CCP2 uses the CSI PHY1 or PHY2, shared with + /* +* On the OMAP34xx the CSI1 receiver is operated in the CSIb IO +* complex, which is powered by vdds_csib power rail. Hence the +* request for the regulator. +* +* On the OMAP36xx, the CCP2 uses the CSI PHY1 or PHY2, shared with * the CSI2c or CSI2a receivers. The PHY then needs to be explicitly * configured. * * TODO: Don't hardcode the usage of PHY1 (shared with CSI2c). */ - if (isp-revision == ISP_REVISION_15_0) + if (isp-revision == ISP_REVISION_2_0) { + ccp2-vdds_csib = regulator_get(isp-dev, vdds_csib); + if (IS_ERR(ccp2-vdds_csib)) { + dev_dbg(isp-dev, + Could not get regulator vdds_csib\n); + ccp2-vdds_csib = NULL; + } + } else if (isp-revision == ISP_REVISION_15_0) { ccp2-phy = isp-isp_csiphy1; + } ret = ccp2_init_entities(ccp2); if (ret 0) diff --git a/drivers/media/video/omap3isp/ispccp2.h b/drivers/media/video/omap3isp/ispccp2.h index 5505a86..6674e9d 100644 --- a/drivers/media/video/omap3isp/ispccp2.h +++ b/drivers/media/video/omap3isp/ispccp2.h @@ -81,6 +81,7 @@ struct isp_ccp2_device { struct isp_interface_mem_config mem_cfg; struct isp_video video_in; struct isp_csiphy *phy; + struct regulator *vdds_csib; unsigned int error; enum isp_pipeline_stream_state state; wait_queue_head_t wait; -- 1.7.1 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 0/2] omap3isp/rx-51: Add vdds_csib regulator handling
The CSIb block is used in rx-51 to handle camera ccp2 IO. Adding support to omap3isp driver for managing the power supply for the CSIb IO complex via regulator framework. Also create the apropriate regulator definitions in the rx-51 board file. I propose to push this set through the linux-media, since most of the changes are on the omap3isp driver side. Any comments/review appreciated. Tested on Nokia N900 and the MeeGo testing daily images (.37 based kernel). Patches on top of Mauro's linux-next tree, build tested and boot tested with that. v2: updated patch 1/2 with comment from Laurent Pinchart Kalle Jokiniemi (2): OMAP3: ISP: Add regulator control for omap34xx OMAP3: RX-51: define vdds_csib regulator supply arch/arm/mach-omap2/board-rx51-peripherals.c |9 drivers/media/video/omap3isp/ispccp2.c | 27 - drivers/media/video/omap3isp/ispccp2.h |1 + 3 files changed, 35 insertions(+), 2 deletions(-) -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 2/2] OMAP3: RX-51: define vdds_csib regulator supply
The RX-51 uses the CSIb IO complex for camera operation. The board file is missing definition for the regulator supplying the CSIb complex, so this is added for better power management. Signed-off-by: Kalle Jokiniemi kalle.jokini...@nokia.com --- arch/arm/mach-omap2/board-rx51-peripherals.c |9 + 1 files changed, 9 insertions(+), 0 deletions(-) diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c index bbcb677..1324ba3 100644 --- a/arch/arm/mach-omap2/board-rx51-peripherals.c +++ b/arch/arm/mach-omap2/board-rx51-peripherals.c @@ -337,6 +337,13 @@ static struct omap2_hsmmc_info mmc[] __initdata = { static struct regulator_consumer_supply rx51_vmmc1_supply = REGULATOR_SUPPLY(vmmc, omap_hsmmc.0); +static struct regulator_consumer_supply rx51_vaux2_supplies[] = { + REGULATOR_SUPPLY(vdds_csib, omap3isp), + { + .supply = vaux2, + }, +}; + static struct regulator_consumer_supply rx51_vaux3_supply = REGULATOR_SUPPLY(vmmc, omap_hsmmc.1); @@ -400,6 +407,8 @@ static struct regulator_init_data rx51_vaux2 = { .valid_ops_mask = REGULATOR_CHANGE_MODE | REGULATOR_CHANGE_STATUS, }, + .num_consumer_supplies = ARRAY_SIZE(rx51_vaux2_supplies), + .consumer_supplies = rx51_vaux2_supplies, }; /* VAUX3 - adds more power to VIO_18 rail */ -- 1.7.1 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 0/2] omap3isp/rx-51: Add vdds_csib regulator handling
The CSIb block is used in rx-51 to handle camera ccp2 IO. Adding support to omap3isp driver for managing the power supply for the CSIb IO complex via regulator framework. Also create the apropriate regulator definitions in the rx-51 board file. I propose to push this set through the linux-media, since most of the changes are on the omap3isp driver side. Any comments/review appreciated. Tested on Nokia N900 and the MeeGo testing daily images (.37 based kernel). Patches on top of Mauro's linux-next tree, build tested and boot tested with that. Kalle Jokiniemi (2): OMAP3: ISP: Add regulator control for omap34xx OMAP3: RX-51: define vdds_csib regulator supply arch/arm/mach-omap2/board-rx51-peripherals.c |9 + drivers/media/video/omap3isp/ispccp2.c | 24 +++- drivers/media/video/omap3isp/ispccp2.h |1 + 3 files changed, 33 insertions(+), 1 deletions(-) -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 1/2] OMAP3: ISP: Add regulator control for omap34xx
The current omap3isp driver is missing regulator handling for CSIb complex in omap34xx based devices. This patch adds a mechanism for this to the omap3isp driver. Signed-off-by: Kalle Jokiniemi kalle.jokini...@nokia.com --- drivers/media/video/omap3isp/ispccp2.c | 24 +++- drivers/media/video/omap3isp/ispccp2.h |1 + 2 files changed, 24 insertions(+), 1 deletions(-) diff --git a/drivers/media/video/omap3isp/ispccp2.c b/drivers/media/video/omap3isp/ispccp2.c index 0e16cab..3b17b0d 100644 --- a/drivers/media/video/omap3isp/ispccp2.c +++ b/drivers/media/video/omap3isp/ispccp2.c @@ -30,6 +30,7 @@ #include linux/module.h #include linux/mutex.h #include linux/uaccess.h +#include linux/regulator/consumer.h #include isp.h #include ispreg.h @@ -163,6 +164,9 @@ static void ccp2_if_enable(struct isp_ccp2_device *ccp2, u8 enable) struct isp_pipeline *pipe = to_isp_pipeline(ccp2-subdev.entity); int i; + if (enable ccp2-vdds_csib) + regulator_enable(ccp2-vdds_csib); + /* Enable/Disable all the LCx channels */ for (i = 0; i CCP2_LCx_CHANS_NUM; i++) isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LCx_CTRL(i), @@ -186,6 +190,8 @@ static void ccp2_if_enable(struct isp_ccp2_device *ccp2, u8 enable) ISPCCP2_LC01_IRQENABLE, ISPCCP2_LC01_IRQSTATUS_LC0_FS_IRQ); } + if (!enable ccp2-vdds_csib) + regulator_disable(ccp2-vdds_csib); } /* @@ -1137,6 +1143,10 @@ error: */ void omap3isp_ccp2_cleanup(struct isp_device *isp) { + struct isp_ccp2_device *ccp2 = isp-isp_ccp2; + + if (isp-revision == ISP_REVISION_2_0) + regulator_put(ccp2-vdds_csib); } /* @@ -1155,10 +1165,22 @@ int omap3isp_ccp2_init(struct isp_device *isp) * the CSI2c or CSI2a receivers. The PHY then needs to be explicitly * configured. * +* On the OMAP34xx the CSI1/CCB is operated in the CSIb IO complex, +* which is powered by vdds_csib power rail. Hence the request for +* the regulator. +* * TODO: Don't hardcode the usage of PHY1 (shared with CSI2c). */ - if (isp-revision == ISP_REVISION_15_0) + if (isp-revision == ISP_REVISION_15_0) { ccp2-phy = isp-isp_csiphy1; + } else if (isp-revision == ISP_REVISION_2_0) { + ccp2-vdds_csib = regulator_get(isp-dev, vdds_csib); + if (IS_ERR(ccp2-vdds_csib)) { + dev_dbg(isp-dev, + Could not get regulator vdds_csib\n); + ccp2-vdds_csib = NULL; + } + } ret = ccp2_init_entities(ccp2); if (ret 0) diff --git a/drivers/media/video/omap3isp/ispccp2.h b/drivers/media/video/omap3isp/ispccp2.h index 5505a86..6674e9d 100644 --- a/drivers/media/video/omap3isp/ispccp2.h +++ b/drivers/media/video/omap3isp/ispccp2.h @@ -81,6 +81,7 @@ struct isp_ccp2_device { struct isp_interface_mem_config mem_cfg; struct isp_video video_in; struct isp_csiphy *phy; + struct regulator *vdds_csib; unsigned int error; enum isp_pipeline_stream_state state; wait_queue_head_t wait; -- 1.7.1 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 2/2] OMAP3: RX-51: define vdds_csib regulator supply
The RX-51 uses the CSIb IO complex for camera operation. The board file is missing definition for the regulator supplying the CSIb complex, so this is added for better power management. Signed-off-by: Kalle Jokiniemi kalle.jokini...@nokia.com --- arch/arm/mach-omap2/board-rx51-peripherals.c |9 + 1 files changed, 9 insertions(+), 0 deletions(-) diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c index bbcb677..1324ba3 100644 --- a/arch/arm/mach-omap2/board-rx51-peripherals.c +++ b/arch/arm/mach-omap2/board-rx51-peripherals.c @@ -337,6 +337,13 @@ static struct omap2_hsmmc_info mmc[] __initdata = { static struct regulator_consumer_supply rx51_vmmc1_supply = REGULATOR_SUPPLY(vmmc, omap_hsmmc.0); +static struct regulator_consumer_supply rx51_vaux2_supplies[] = { + REGULATOR_SUPPLY(vdds_csib, omap3isp), + { + .supply = vaux2, + }, +}; + static struct regulator_consumer_supply rx51_vaux3_supply = REGULATOR_SUPPLY(vmmc, omap_hsmmc.1); @@ -400,6 +407,8 @@ static struct regulator_init_data rx51_vaux2 = { .valid_ops_mask = REGULATOR_CHANGE_MODE | REGULATOR_CHANGE_STATUS, }, + .num_consumer_supplies = ARRAY_SIZE(rx51_vaux2_supplies), + .consumer_supplies = rx51_vaux2_supplies, }; /* VAUX3 - adds more power to VIO_18 rail */ -- 1.7.1 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 1/1] OMAP3: rx-51: Add full regulator definitions
The vaux2 (VCSI) regulator is left on by the bootloader in rx-51. Since there the product has shipped and there won't be any bootloader updates to fix this issue, we need to define all the regulators and declare full constraints for the regulator FW. This will allow the regulator FW to disable unused regulators. Also this helps in adding more fine grain regulator support for rx-51 in the future. Thanks for Mark Brown for pointing out the correct solution. Signed-off-by: Kalle Jokiniemi kalle.jokini...@nokia.com Cc: Mark Brown broo...@opensource.wolfsonmicro.com --- arch/arm/mach-omap2/board-rx51-peripherals.c | 75 ++ 1 files changed, 75 insertions(+), 0 deletions(-) diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c index bbcb677..8373b74 100644 --- a/arch/arm/mach-omap2/board-rx51-peripherals.c +++ b/arch/arm/mach-omap2/board-rx51-peripherals.c @@ -475,6 +475,34 @@ static struct regulator_init_data rx51_vmmc2 = { .consumer_supplies = rx51_vmmc2_supplies, }; +static struct regulator_init_data rx51_vpll1 = { + .constraints = { + .name = VPLL, + .min_uV = 180, + .max_uV = 180, + .apply_uV = true, + .always_on = true, + .valid_modes_mask = REGULATOR_MODE_NORMAL + | REGULATOR_MODE_STANDBY, + .valid_ops_mask = REGULATOR_CHANGE_MODE + | REGULATOR_CHANGE_STATUS, + }, +}; + +static struct regulator_init_data rx51_vpll2 = { + .constraints = { + .name = VSDI_CSI, + .min_uV = 180, + .max_uV = 180, + .apply_uV = true, + .always_on = true, + .valid_modes_mask = REGULATOR_MODE_NORMAL + | REGULATOR_MODE_STANDBY, + .valid_ops_mask = REGULATOR_CHANGE_MODE + | REGULATOR_CHANGE_STATUS, + }, +}; + static struct regulator_init_data rx51_vsim = { .constraints = { .name = VMMC2_IO_18, @@ -519,6 +547,46 @@ static struct regulator_init_data rx51_vio = { .consumer_supplies = rx51_vio_supplies, }; +static struct regulator_init_data rx51_vintana1 = { + .constraints = { + .name = VINTANA1, + .min_uV = 150, + .max_uV = 150, + .always_on = true, + .valid_modes_mask = REGULATOR_MODE_NORMAL + | REGULATOR_MODE_STANDBY, + .valid_ops_mask = REGULATOR_CHANGE_MODE + | REGULATOR_CHANGE_STATUS, + }, +}; + +static struct regulator_init_data rx51_vintana2 = { + .constraints = { + .name = VINTANA2, + .min_uV = 275, + .max_uV = 275, + .apply_uV = true, + .always_on = true, + .valid_modes_mask = REGULATOR_MODE_NORMAL + | REGULATOR_MODE_STANDBY, + .valid_ops_mask = REGULATOR_CHANGE_MODE + | REGULATOR_CHANGE_STATUS, + }, +}; + +static struct regulator_init_data rx51_vintdig = { + .constraints = { + .name = VINTDIG, + .min_uV = 150, + .max_uV = 150, + .always_on = true, + .valid_modes_mask = REGULATOR_MODE_NORMAL + | REGULATOR_MODE_STANDBY, + .valid_ops_mask = REGULATOR_CHANGE_MODE + | REGULATOR_CHANGE_STATUS, + }, +}; + static struct si4713_platform_data rx51_si4713_i2c_data __initdata_or_module = { .gpio_reset = RX51_FMTX_RESET_GPIO, }; @@ -767,8 +835,13 @@ static struct twl4030_platform_data rx51_twldata __initdata = { .vaux2 = rx51_vaux2, .vaux4 = rx51_vaux4, .vmmc1 = rx51_vmmc1, + .vpll1 = rx51_vpll1, + .vpll2 = rx51_vpll2, .vsim = rx51_vsim, .vdac = rx51_vdac, + .vintana1 = rx51_vintana1, + .vintana2 = rx51_vintana2, + .vintdig= rx51_vintdig, .vio= rx51_vio
[PATCH 0/1] RX-51: add full regulator definitions
Adding regulator definitions to correctly shut down unneeded regulators. Needed, but previously undefined regulators were marked always_on. Tested on top of MeeGo N900 DE daily release (.37 kernel) and with linux-omap. Patch based on linux-omap HEAD. Kalle Jokiniemi (1): OMAP3: rx-51: Add full regulator definitions arch/arm/mach-omap2/board-rx51-peripherals.c | 75 ++ 1 files changed, 75 insertions(+), 0 deletions(-) -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 0/2] isp1704_charger: fix powering for N900
This patch set enables powering down the isp1704 usb tranceiver when not in use. tested on RX-51 and MeeGo. Thanks to Felipe Balbi, Sergei Shtylyov, and Heikki Krogerus for comments. v3: * fixed power down handling in isp1704_charger_probe * removed init_done variable * changed BUG_ON to WARN_ON * editorial fixes v2: fixed boot issue in the 1/2 patch. Kalle Jokiniemi (2): isp1704_charger: allow board specific powering routine RX-51: Enable isp1704 power on/off arch/arm/mach-omap2/board-rx51-peripherals.c | 27 ++- drivers/power/isp1704_charger.c | 22 +++ include/linux/power/isp1704_charger.h| 29 ++ 3 files changed, 76 insertions(+), 2 deletions(-) create mode 100644 include/linux/power/isp1704_charger.h -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 1/2] isp1704_charger: allow board specific powering routine
The ISP1704/1707 chip can be put to full power down state by asserting the CHIP_SEL line. This patch enables platform or board specific hooks to put the device into power down mode in case not needed. This patch is a preparation for enabling this powering routine in n900 (rx-51) devices. Thanks to Heikki Krogerus for helping out with the patch. Signed-off-by: Kalle Jokiniemi kalle.jokini...@nokia.com Cc: Heikki Krogerus heikki.kroge...@nokia.com --- drivers/power/isp1704_charger.c | 22 ++ include/linux/power/isp1704_charger.h | 29 + 2 files changed, 51 insertions(+), 0 deletions(-) create mode 100644 include/linux/power/isp1704_charger.h diff --git a/drivers/power/isp1704_charger.c b/drivers/power/isp1704_charger.c index 2ad9b14..f6d72b4 100644 --- a/drivers/power/isp1704_charger.c +++ b/drivers/power/isp1704_charger.c @@ -33,6 +33,7 @@ #include linux/usb/ulpi.h #include linux/usb/ch9.h #include linux/usb/gadget.h +#include linux/power/isp1704_charger.h /* Vendor specific Power Control register */ #define ISP1704_PWR_CTRL 0x3d @@ -71,6 +72,18 @@ struct isp1704_charger { }; /* + * Disable/enable the power from the isp1704 if a function for it + * has been provided with platform data. + */ +static void isp1704_charger_set_power(struct isp1704_charger *isp, bool on) +{ + struct isp1704_charger_data *board = isp-dev-platform_data; + + if (board-set_power) + board-set_power(on); +} + +/* * Determine is the charging port DCP (dedicated charger) or CDP (Host/HUB * chargers). * @@ -222,6 +235,9 @@ static void isp1704_charger_work(struct work_struct *data) mutex_lock(lock); + if (event != USB_EVENT_NONE) + isp1704_charger_set_power(isp, 1); + switch (event) { case USB_EVENT_VBUS: isp-online = true; @@ -269,6 +285,8 @@ static void isp1704_charger_work(struct work_struct *data) */ if (isp-otg-gadget) usb_gadget_disconnect(isp-otg-gadget); + + isp1704_charger_set_power(isp, 0); break; case USB_EVENT_ENUMERATED: if (isp-present) @@ -394,6 +412,8 @@ static int __devinit isp1704_charger_probe(struct platform_device *pdev) isp-dev = pdev-dev; platform_set_drvdata(pdev, isp); + isp1704_charger_set_power(isp, 1); + ret = isp1704_test_ulpi(isp); if (ret 0) goto fail1; @@ -434,6 +454,7 @@ static int __devinit isp1704_charger_probe(struct platform_device *pdev) /* Detect charger if VBUS is valid (the cable was already plugged). */ ret = otg_io_read(isp-otg, ULPI_USB_INT_STS); + isp1704_charger_set_power(isp, 0); if ((ret ULPI_INT_VBUS_VALID) !isp-otg-default_a) { isp-event = USB_EVENT_VBUS; schedule_work(isp-work); @@ -459,6 +480,7 @@ static int __devexit isp1704_charger_remove(struct platform_device *pdev) otg_unregister_notifier(isp-otg, isp-nb); power_supply_unregister(isp-psy); otg_put_transceiver(isp-otg); + isp1704_charger_set_power(isp, 0); kfree(isp); return 0; diff --git a/include/linux/power/isp1704_charger.h b/include/linux/power/isp1704_charger.h new file mode 100644 index 000..68096a6 --- /dev/null +++ b/include/linux/power/isp1704_charger.h @@ -0,0 +1,29 @@ +/* + * ISP1704 USB Charger Detection driver + * + * Copyright (C) 2011 Nokia Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifndef __ISP1704_CHARGER_H +#define __ISP1704_CHARGER_H + +struct isp1704_charger_data { + void(*set_power)(bool on); +}; + +#endif -- 1.7.1 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 2/2] RX-51: Enable isp1704 power on/off
The isp1704 usb tranceiver is used for charging and can be disabled when not in use. Provide the powering routine to the driver via platform data. Also changed the indent of .name variable in rx51_charger_device definition to use tabs same way as the new .dev variable indent. Put this in the same patch since the indent fix is only needed when there are multiple members in the struct definition. Loosely based on earlier patches from Heikki Krogerus in Nokia N900 maemo kernel. Signed-off-by: Kalle Jokiniemi kalle.jokini...@nokia.com Cc: Heikki Krogerus heikki.kroge...@nokia.com --- arch/arm/mach-omap2/board-rx51-peripherals.c | 27 - 1 files changed, 25 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c index bbcb677..fad98ab 100644 --- a/arch/arm/mach-omap2/board-rx51-peripherals.c +++ b/arch/arm/mach-omap2/board-rx51-peripherals.c @@ -23,6 +23,7 @@ #include linux/gpio.h #include linux/gpio_keys.h #include linux/mmc/host.h +#include linux/power/isp1704_charger.h #include plat/mcspi.h #include plat/board.h @@ -52,6 +53,8 @@ #define RX51_FMTX_RESET_GPIO 163 #define RX51_FMTX_IRQ 53 +#define RX51_USB_TRANSCEIVER_RST_GPIO 67 + /* list all spi devices here */ enum { RX51_SPI_WL1251, @@ -110,10 +113,30 @@ static struct spi_board_info rx51_peripherals_spi_board_info[] __initdata = { }, }; +static void rx51_charger_set_power(bool on) +{ + gpio_set_value(RX51_USB_TRANSCEIVER_RST_GPIO, on); +} + +static struct isp1704_charger_data rx51_charger_data = { + .set_power = rx51_charger_set_power, +}; + static struct platform_device rx51_charger_device = { - .name = isp1704_charger, + .name = isp1704_charger, + .dev= { + .platform_data = rx51_charger_data, + }, }; +static void __init rx51_charger_init(void) +{ + WARN_ON(gpio_request_one(RX51_USB_TRANSCEIVER_RST_GPIO, + GPIOF_OUT_INIT_LOW, isp1704_reset)); + + platform_device_register(rx51_charger_device); +} + #if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE) #define RX51_GPIO_CAMERA_LENS_COVER110 @@ -981,6 +1004,6 @@ void __init rx51_peripherals_init(void) if (partition) omap2_hsmmc_init(mmc); - platform_device_register(rx51_charger_device); + rx51_charger_init(); } -- 1.7.1 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 0/2] isp1704_charger: fix powering for N900
This patch set enables powering down the isp1704 usb tranceiver when not in use. Tested on RX-51. Kalle Jokiniemi (2): isp1704_charger: allow board specific powering routine RX-51: Enable isp1704 power on/off arch/arm/mach-omap2/board-rx51-peripherals.c | 27 ++- drivers/power/isp1704_charger.c | 25 +- include/linux/power/isp1704_charger.h| 29 ++ 3 files changed, 78 insertions(+), 3 deletions(-) create mode 100644 include/linux/power/isp1704_charger.h -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 1/2] isp1704_charger: allow board specific powering routine
The ISP1704/1707 chip can be put to full power down state by asserting the CHIP_SEL line. This patch enables platform or board specific hooks to put the device into power down mode in case not needed. These patches are preparatio for enabling this powering routine in n900 (rx-51) devices. Thanks to Heikki Krogerus for helping out with the patch. Signed-off-by: Kalle Jokiniemi kalle.jokini...@nokia.com Cc: Heikki Krogerus heikki.kroge...@nokia.com --- drivers/power/isp1704_charger.c | 23 +++ include/linux/power/isp1704_charger.h | 29 + 2 files changed, 52 insertions(+), 0 deletions(-) create mode 100644 include/linux/power/isp1704_charger.h diff --git a/drivers/power/isp1704_charger.c b/drivers/power/isp1704_charger.c index 2ad9b14..06f69c7 100644 --- a/drivers/power/isp1704_charger.c +++ b/drivers/power/isp1704_charger.c @@ -33,6 +33,7 @@ #include linux/usb/ulpi.h #include linux/usb/ch9.h #include linux/usb/gadget.h +#include linux/power/isp1704_charger.h /* Vendor specific Power Control register */ #define ISP1704_PWR_CTRL 0x3d @@ -71,6 +72,18 @@ struct isp1704_charger { }; /* + * Disable/enable the power from the isp1704 if a function for it + * has been provided with platform data. + */ +static void isp1704_charger_set_power(struct isp1704_charger *isp, bool on) +{ + struct isp1704_charger_data *board = isp-dev-platform_data; + + if (board-set_power) + board-set_power(on); +} + +/* * Determine is the charging port DCP (dedicated charger) or CDP (Host/HUB * chargers). * @@ -222,6 +235,9 @@ static void isp1704_charger_work(struct work_struct *data) mutex_lock(lock); + if (event != USB_EVENT_NONE) + isp1704_charger_set_power(isp, 1); + switch (event) { case USB_EVENT_VBUS: isp-online = true; @@ -269,6 +285,8 @@ static void isp1704_charger_work(struct work_struct *data) */ if (isp-otg-gadget) usb_gadget_disconnect(isp-otg-gadget); + /* As last thing, disable the power from the charger */ + isp1704_charger_set_power(isp, 0); break; case USB_EVENT_ENUMERATED: if (isp-present) @@ -394,6 +412,8 @@ static int __devinit isp1704_charger_probe(struct platform_device *pdev) isp-dev = pdev-dev; platform_set_drvdata(pdev, isp); + isp1704_charger_set_power(isp, 1); + ret = isp1704_test_ulpi(isp); if (ret 0) goto fail1; @@ -437,6 +457,8 @@ static int __devinit isp1704_charger_probe(struct platform_device *pdev) if ((ret ULPI_INT_VBUS_VALID) !isp-otg-default_a) { isp-event = USB_EVENT_VBUS; schedule_work(isp-work); + } else { + isp1704_charger_set_power(isp, 0); } return 0; @@ -459,6 +481,7 @@ static int __devexit isp1704_charger_remove(struct platform_device *pdev) otg_unregister_notifier(isp-otg, isp-nb); power_supply_unregister(isp-psy); otg_put_transceiver(isp-otg); + isp1704_charger_set_power(isp, 0); kfree(isp); return 0; diff --git a/include/linux/power/isp1704_charger.h b/include/linux/power/isp1704_charger.h new file mode 100644 index 000..68096a6 --- /dev/null +++ b/include/linux/power/isp1704_charger.h @@ -0,0 +1,29 @@ +/* + * ISP1704 USB Charger Detection driver + * + * Copyright (C) 2011 Nokia Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifndef __ISP1704_CHARGER_H +#define __ISP1704_CHARGER_H + +struct isp1704_charger_data { + void(*set_power)(bool on); +}; + +#endif -- 1.7.1 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 1/2] isp1704_charger: allow board specific powering routine
The ISP1704/1707 chip can be put to full power down state by asserting the CHIP_SEL line. This patch enables platform or board specific hooks to put the device into power down mode in case not needed. These patches are preparatio for enabling this powering routine in n900 (rx-51) devices. Thanks to Heikki Krogerus for helping out with the patch. Signed-off-by: Kalle Jokiniemi kalle.jokini...@nokia.com Cc: Heikki Krogerus heikki.kroge...@nokia.com --- drivers/power/isp1704_charger.c | 26 ++ include/linux/power/isp1704_charger.h | 29 + 2 files changed, 55 insertions(+), 0 deletions(-) create mode 100644 include/linux/power/isp1704_charger.h diff --git a/drivers/power/isp1704_charger.c b/drivers/power/isp1704_charger.c index 2ad9b14..c796b9f 100644 --- a/drivers/power/isp1704_charger.c +++ b/drivers/power/isp1704_charger.c @@ -33,6 +33,7 @@ #include linux/usb/ulpi.h #include linux/usb/ch9.h #include linux/usb/gadget.h +#include linux/power/isp1704_charger.h /* Vendor specific Power Control register */ #define ISP1704_PWR_CTRL 0x3d @@ -63,6 +64,7 @@ struct isp1704_charger { charmodel[8]; unsignedpresent:1; unsignedonline:1; + unsignedinit_done; unsignedcurrent_max; /* temp storage variables */ @@ -71,6 +73,18 @@ struct isp1704_charger { }; /* + * Disable/enable the power from the isp1704 if a function for it + * has been provided with platform data. + */ +static void isp1704_charger_set_power(struct isp1704_charger *isp, bool on) +{ + struct isp1704_charger_data *board = isp-dev-platform_data; + + if (board-set_power) + board-set_power(on); +} + +/* * Determine is the charging port DCP (dedicated charger) or CDP (Host/HUB * chargers). * @@ -222,6 +236,9 @@ static void isp1704_charger_work(struct work_struct *data) mutex_lock(lock); + if (event != USB_EVENT_NONE) + isp1704_charger_set_power(isp, 1); + switch (event) { case USB_EVENT_VBUS: isp-online = true; @@ -269,6 +286,9 @@ static void isp1704_charger_work(struct work_struct *data) */ if (isp-otg-gadget) usb_gadget_disconnect(isp-otg-gadget); + /* If we're initialized, we can power down the isp */ + if (isp-init_done) + isp1704_charger_set_power(isp, 0); break; case USB_EVENT_ENUMERATED: if (isp-present) @@ -394,6 +414,8 @@ static int __devinit isp1704_charger_probe(struct platform_device *pdev) isp-dev = pdev-dev; platform_set_drvdata(pdev, isp); + isp1704_charger_set_power(isp, 1); + ret = isp1704_test_ulpi(isp); if (ret 0) goto fail1; @@ -437,8 +459,11 @@ static int __devinit isp1704_charger_probe(struct platform_device *pdev) if ((ret ULPI_INT_VBUS_VALID) !isp-otg-default_a) { isp-event = USB_EVENT_VBUS; schedule_work(isp-work); + } else { + isp1704_charger_set_power(isp, 0); } + isp-init_done = 1; return 0; fail2: power_supply_unregister(isp-psy); @@ -459,6 +484,7 @@ static int __devexit isp1704_charger_remove(struct platform_device *pdev) otg_unregister_notifier(isp-otg, isp-nb); power_supply_unregister(isp-psy); otg_put_transceiver(isp-otg); + isp1704_charger_set_power(isp, 0); kfree(isp); return 0; diff --git a/include/linux/power/isp1704_charger.h b/include/linux/power/isp1704_charger.h new file mode 100644 index 000..68096a6 --- /dev/null +++ b/include/linux/power/isp1704_charger.h @@ -0,0 +1,29 @@ +/* + * ISP1704 USB Charger Detection driver + * + * Copyright (C) 2011 Nokia Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifndef __ISP1704_CHARGER_H +#define __ISP1704_CHARGER_H + +struct isp1704_charger_data { + void(*set_power)(bool on); +}; + +#endif -- 1.7.1 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord
[PATCH v2 2/2] RX-51: Enable isp1704 power on/off
The isp1704 usb tranceiver is used for charging and can be disabled when not in use. Provide the powering routine to the driver via platform data. Loosely based on earlier patches from Heikki Krogerus in Nokia N900 maemo kernel. Signed-off-by: Kalle Jokiniemi kalle.jokini...@nokia.com Cc: Heikki Krogerus heikki.kroge...@nokia.com --- arch/arm/mach-omap2/board-rx51-peripherals.c | 27 - 1 files changed, 25 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c index e75e240..8584dd8 100644 --- a/arch/arm/mach-omap2/board-rx51-peripherals.c +++ b/arch/arm/mach-omap2/board-rx51-peripherals.c @@ -23,6 +23,7 @@ #include linux/gpio.h #include linux/gpio_keys.h #include linux/mmc/host.h +#include linux/power/isp1704_charger.h #include plat/mcspi.h #include plat/board.h @@ -48,6 +49,8 @@ #define RX51_WL1251_POWER_GPIO 87 #define RX51_WL1251_IRQ_GPIO 42 +#define RX51_USB_TRANSCEIVER_RST_GPIO 67 + /* list all spi devices here */ enum { RX51_SPI_WL1251, @@ -106,10 +109,30 @@ static struct spi_board_info rx51_peripherals_spi_board_info[] __initdata = { }, }; +static void rx51_charger_set_power(bool on) +{ + gpio_set_value(RX51_USB_TRANSCEIVER_RST_GPIO, on); +} + +static struct isp1704_charger_data rx51_charger_data = { + .set_power = rx51_charger_set_power, +}; + static struct platform_device rx51_charger_device = { - .name = isp1704_charger, + .name = isp1704_charger, + .dev= { + .platform_data = rx51_charger_data, + }, }; +static void __init rx51_charger_init(void) +{ + BUG_ON(gpio_request_one(RX51_USB_TRANSCEIVER_RST_GPIO, + GPIOF_OUT_INIT_LOW, isp1704_reset)); + + platform_device_register(rx51_charger_device); +} + #if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE) #define RX51_GPIO_CAMERA_LENS_COVER110 @@ -928,6 +951,6 @@ void __init rx51_peripherals_init(void) if (partition) omap2_hsmmc_init(mmc); - platform_device_register(rx51_charger_device); + rx51_charger_init(); } -- 1.7.1 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 0/2] isp1704_charger: fix powering for N900
This patch set enables powering down the isp1704 usb tranceiver when not in use. Tested on RX-51 and MeeGo. v2: fixed a boot issue in the 1/2 patch. Kalle Jokiniemi (2): isp1704_charger: allow board specific powering routine RX-51: Enable isp1704 power on/off arch/arm/mach-omap2/board-rx51-peripherals.c | 27 ++- drivers/power/isp1704_charger.c | 25 +- include/linux/power/isp1704_charger.h| 29 ++ 3 files changed, 78 insertions(+), 3 deletions(-) create mode 100644 include/linux/power/isp1704_charger.h -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 0/2] USB: twl4030-usb: fix isp1707 xceiver powering
These two patches introduce phy_power calls form board files to twl4030-usb. This fixes a problem in Nokia N900, where the ISP1707 serial tranceiver did not get disabled during phy power down. Based on patches used on n900 maemo kernel, mainly from Heikki Krogerus. Commentstesting appreciated. Basic test done on MeeGo + linux usb that the ISP powering happens correctly. Also simple data transfer tests done with backported patches on MeeGo n900 kernel. Cross posting to linux-omap, but I propose that we'd push these to linux-usb. Patches based on linux-usb master. Kalle Jokiniemi (2): USB: twl4030-usb: do board specific phy_power up/down OMAP3: rx51: specify phy_power for usb tranceiver arch/arm/mach-omap2/board-rx51-peripherals.c | 32 ++ drivers/usb/otg/twl4030-usb.c|9 ++- 2 files changed, 40 insertions(+), 1 deletions(-) -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 1/2] USB: twl4030-usb: do board specific phy_power up/down
In case some board has special powering sequences for the USB tranceiver, call those during __twl4030_phy_power calls. This is a preparation patch to allow powering down the ISP1707 USB serial tranceiver in Nokia N900. Signed-off-by: Kalle Jokiniemi kalle.jokini...@nokia.com --- drivers/usb/otg/twl4030-usb.c |9 - 1 files changed, 8 insertions(+), 1 deletions(-) diff --git a/drivers/usb/otg/twl4030-usb.c b/drivers/usb/otg/twl4030-usb.c index 6ca505f..dea99b1 100644 --- a/drivers/usb/otg/twl4030-usb.c +++ b/drivers/usb/otg/twl4030-usb.c @@ -348,13 +348,20 @@ static void twl4030_i2c_access(struct twl4030_usb *twl, int on) static void __twl4030_phy_power(struct twl4030_usb *twl, int on) { - u8 pwr = twl4030_usb_read(twl, PHY_PWR_CTRL); + u8 pwr; + struct twl4030_usb_data *board = twl-dev-platform_data; + + pwr = twl4030_usb_read(twl, PHY_PWR_CTRL); if (on) pwr = ~PHY_PWR_PHYPWD; else pwr |= PHY_PWR_PHYPWD; + /* do board specific power up/down, if available */ + if (board-phy_power) + board-phy_power(twl-dev, 0, on); + WARN_ON(twl4030_usb_write_verify(twl, PHY_PWR_CTRL, pwr) 0); } -- 1.7.1 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 2/2] OMAP3: wdtimer: Disable SMART idle mode
The smart idle mode in wdtimer2 prevents CORE power domain idle transitions. Disable SMART idle mode to allow FORCE idle mode to be used. Signed-off-by: Kalle Jokiniemi kalle.jokini...@nokia.com --- arch/arm/mach-omap2/omap_hwmod_3xxx_data.c |7 +-- 1 files changed, 5 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c index 196a834..0be56bd 100644 --- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c @@ -1240,7 +1240,10 @@ static struct omap_hwmod_ocp_if omap3xxx_l4_wkup__wd_timer2 = { /* * 'wd_timer' class * 32-bit watchdog upward counter that generates a pulse on the reset pin on - * overflow condition + * overflow condition. + * + * Disallow SIDLE_SMART to use SIDLE_FORCE instead as the CORE power domain + * sleep transitions only work when wdtimer2 is in SIDLE_FORCE mode. */ static struct omap_hwmod_class_sysconfig omap3xxx_wd_timer_sysc = { @@ -1250,7 +1253,7 @@ static struct omap_hwmod_class_sysconfig omap3xxx_wd_timer_sysc = { .sysc_flags = (SYSC_HAS_SIDLEMODE | SYSC_HAS_EMUFREE | SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE | SYSC_HAS_CLOCKACTIVITY), - .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART), + .idlemodes = (SIDLE_FORCE | SIDLE_NO), /* SIDLE_SMART disabled */ .sysc_fields= omap_hwmod_sysc_type1, }; -- 1.7.1 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 1/2] OMAP: hw_mod: consider supported idlemodes in enable_sysc
Current implementation of the hw_mod sysconfig configuration always sets up SMART idle mode for HW modules. However, a certain HW module may not support smart idle mode or may have HW bugs that prevent using smart idle mode. This patch introduces a mechanism to check supported idle modes and select in following priority: 1. Smart idle mode 2. Force idle mode 3. No idle mode. Signed-off-by: Kalle Jokiniemi kalle.jokini...@nokia.com --- arch/arm/mach-omap2/omap_hwmod.c | 28 1 files changed, 20 insertions(+), 8 deletions(-) diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index 028efda..ef77697 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -757,7 +757,7 @@ static void __iomem * __init _find_mpu_rt_base(struct omap_hwmod *oh, u8 index) */ static void _enable_sysc(struct omap_hwmod *oh) { - u8 idlemode, sf; + u8 idlemode, sf, idlemode_flags; u32 v; if (!oh-class-sysc) @@ -765,17 +765,28 @@ static void _enable_sysc(struct omap_hwmod *oh) v = oh-_sysc_cache; sf = oh-class-sysc-sysc_flags; + idlemode_flags = oh-class-sysc-idlemodes; + + /* Set the idlemode, priority order: 1. SMART 2. FORCE 3. NOIDLE */ + if (idlemode_flags SIDLE_SMART) + idlemode = HWMOD_IDLEMODE_SMART; + else if (idlemode_flags SIDLE_FORCE) + idlemode = HWMOD_IDLEMODE_FORCE; + else + idlemode = HWMOD_IDLEMODE_NO; if (sf SYSC_HAS_SIDLEMODE) { - idlemode = (oh-flags HWMOD_SWSUP_SIDLE) ? - HWMOD_IDLEMODE_NO : HWMOD_IDLEMODE_SMART; - _set_slave_idlemode(oh, idlemode, v); + if (oh-flags HWMOD_SWSUP_SIDLE) + _set_slave_idlemode(oh, HWMOD_IDLEMODE_NO, v); + else + _set_slave_idlemode(oh, idlemode, v); } if (sf SYSC_HAS_MIDLEMODE) { - idlemode = (oh-flags HWMOD_SWSUP_MSTANDBY) ? - HWMOD_IDLEMODE_NO : HWMOD_IDLEMODE_SMART; - _set_master_standbymode(oh, idlemode, v); + if (oh-flags HWMOD_SWSUP_MSTANDBY) + _set_master_standbymode(oh, HWMOD_IDLEMODE_NO, v); + else + _set_master_standbymode(oh, idlemode, v); } /* @@ -788,7 +799,8 @@ static void _enable_sysc(struct omap_hwmod *oh) _set_clockactivity(oh, oh-class-sysc-clockact, v); /* If slave is in SMARTIDLE, also enable wakeup */ - if ((sf SYSC_HAS_SIDLEMODE) !(oh-flags HWMOD_SWSUP_SIDLE)) + if ((sf SYSC_HAS_SIDLEMODE) !(oh-flags HWMOD_SWSUP_SIDLE) + idlemode_flags SIDLE_SMART) _enable_wakeup(oh, v); _write_sysconfig(v, oh); -- 1.7.1 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 2/2] OMAP3: wdtimer: Fix CORE idle transition
From: Paul Walmsley p...@pwsan.com The HW superwised smart idle for wdtimer in OMAP3 prevents CORE power domain idle transitions. Disable it by swithing to SW supervised transitions. Signed-off-by: Kalle Jokiniemi kalle.jokini...@nokia.com Signed-off-by: Paul Walmsley p...@pwsan.com --- arch/arm/mach-omap2/omap_hwmod_3xxx_data.c |1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c index 196a834..a99a4f3 100644 --- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c @@ -1293,6 +1293,7 @@ static struct omap_hwmod omap3xxx_wd_timer2_hwmod = { .slaves = omap3xxx_wd_timer2_slaves, .slaves_cnt = ARRAY_SIZE(omap3xxx_wd_timer2_slaves), .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430), + .flags = HWMOD_SWSUP_SIDLE, }; /* UART common */ -- 1.7.1 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 1/2] Watchdog: omap_wdt: add fine grain runtime-pm
From: Paul Walmsley p...@pwsan.com The omap_wdt should only be in full active state when the registers are being accessed. Otherwise the device can be on lower power mode. This patch is based on a patch created by Atal Shargorodsky: http://lkml.org/lkml/2009/3/10/266. Signed-off-by: Paul Walmsley p...@pwsan.com Signed-off-by: Kalle Jokiniemi kalle.jokini...@nokia.com Tested-by: Kalle Jokiniemi kalle.jokini...@nokia.com --- drivers/watchdog/omap_wdt.c | 25 +++-- 1 files changed, 23 insertions(+), 2 deletions(-) diff --git a/drivers/watchdog/omap_wdt.c b/drivers/watchdog/omap_wdt.c index 3dd4971..2b4acb8 100644 --- a/drivers/watchdog/omap_wdt.c +++ b/drivers/watchdog/omap_wdt.c @@ -124,6 +124,8 @@ static void omap_wdt_set_timeout(struct omap_wdt_dev *wdev) u32 pre_margin = GET_WLDR_VAL(timer_margin); void __iomem *base = wdev-base; + pm_runtime_get_sync(wdev-dev); + /* just count up at 32 KHz */ while (__raw_readl(base + OMAP_WATCHDOG_WPS) 0x04) cpu_relax(); @@ -131,6 +133,8 @@ static void omap_wdt_set_timeout(struct omap_wdt_dev *wdev) __raw_writel(pre_margin, base + OMAP_WATCHDOG_LDR); while (__raw_readl(base + OMAP_WATCHDOG_WPS) 0x04) cpu_relax(); + + pm_runtime_put_sync(wdev-dev); } /* @@ -160,6 +164,8 @@ static int omap_wdt_open(struct inode *inode, struct file *file) omap_wdt_ping(wdev); /* trigger loading of new timeout value */ omap_wdt_enable(wdev); + pm_runtime_put_sync(wdev-dev); + return nonseekable_open(inode, file); } @@ -171,6 +177,7 @@ static int omap_wdt_release(struct inode *inode, struct file *file) * Shut off the timer unless NOWAYOUT is defined. */ #ifndef CONFIG_WATCHDOG_NOWAYOUT + pm_runtime_get_sync(wdev-dev); omap_wdt_disable(wdev); @@ -190,9 +197,11 @@ static ssize_t omap_wdt_write(struct file *file, const char __user *data, /* Refresh LOAD_TIME. */ if (len) { + pm_runtime_get_sync(wdev-dev); spin_lock(wdt_lock); omap_wdt_ping(wdev); spin_unlock(wdt_lock); + pm_runtime_put_sync(wdev-dev); } return len; } @@ -224,15 +233,18 @@ static long omap_wdt_ioctl(struct file *file, unsigned int cmd, return put_user(omap_prcm_get_reset_sources(), (int __user *)arg); case WDIOC_KEEPALIVE: + pm_runtime_get_sync(wdev-dev); spin_lock(wdt_lock); omap_wdt_ping(wdev); spin_unlock(wdt_lock); + pm_runtime_put_sync(wdev-dev); return 0; case WDIOC_SETTIMEOUT: if (get_user(new_margin, (int __user *)arg)) return -EFAULT; omap_wdt_adjust_timeout(new_margin); + pm_runtime_get_sync(wdev-dev); spin_lock(wdt_lock); omap_wdt_disable(wdev); omap_wdt_set_timeout(wdev); @@ -240,6 +252,7 @@ static long omap_wdt_ioctl(struct file *file, unsigned int cmd, omap_wdt_ping(wdev); spin_unlock(wdt_lock); + pm_runtime_put_sync(wdev-dev); /* Fall */ case WDIOC_GETTIMEOUT: return put_user(timer_margin, (int __user *)arg); @@ -345,8 +358,11 @@ static void omap_wdt_shutdown(struct platform_device *pdev) { struct omap_wdt_dev *wdev = platform_get_drvdata(pdev); - if (wdev-omap_wdt_users) + if (wdev-omap_wdt_users) { + pm_runtime_get_sync(wdev-dev); omap_wdt_disable(wdev); + pm_runtime_put_sync(wdev-dev); + } } static int __devexit omap_wdt_remove(struct platform_device *pdev) @@ -381,8 +397,11 @@ static int omap_wdt_suspend(struct platform_device *pdev, pm_message_t state) { struct omap_wdt_dev *wdev = platform_get_drvdata(pdev); - if (wdev-omap_wdt_users) + if (wdev-omap_wdt_users) { + pm_runtime_get_sync(wdev-dev); omap_wdt_disable(wdev); + pm_runtime_put_sync(wdev-dev); + } return 0; } @@ -392,8 +411,10 @@ static int omap_wdt_resume(struct platform_device *pdev) struct omap_wdt_dev *wdev = platform_get_drvdata(pdev); if (wdev-omap_wdt_users) { + pm_runtime_get_sync(wdev-dev); omap_wdt_enable(wdev); omap_wdt_ping(wdev); + pm_runtime_put_sync(wdev-dev); } return 0; -- 1.7.1 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 0/2] OMAP3: wdtimer: Fix CORE idle
These patches fix the issue where the wdtimer blocks CORE idle transitions on n900 (OMAP3). The root cause was that SMART idle mode in wdtimer did not allow the CORE idle transition to happen. Paul, I added your S-o-bs to the patches already. Please check that they are ok by you. Paul Walmsley (2): Watchdog: omap_wdt: add fine grain runtime-pm OMAP3: wdtimer: Fix CORE idle transition arch/arm/mach-omap2/omap_hwmod_3xxx_data.c |1 + drivers/watchdog/omap_wdt.c| 25 +++-- 2 files changed, 24 insertions(+), 2 deletions(-) -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 0/2] OMAP3: wdtimer: Fix CORE idle
These patches fix the issue where the wdtimer blocks CORE idle transitions on n900 (OMAP3). The root cause was that SMART idle mode in wdtimer did not allow the CORE idle transition to happen. v2: updated commit message on patch 1/2, Cc'd Wim, and added comments to code about possible HW bug in wdtimer2. Wim, please check patch number one and add your acked by. I propose that we push these upstream via linux-omap-pm, as the patches deal with PM and need to be applied together to get the desired functionality. Paul Walmsley (2): Watchdog: omap_wdt: add fine grain runtime-pm OMAP3: wdtimer: Fix CORE idle transition arch/arm/mach-omap2/omap_hwmod_3xxx_data.c |1 + drivers/watchdog/omap_wdt.c| 25 +++-- 2 files changed, 24 insertions(+), 2 deletions(-) -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 2/2] OMAP3: wdtimer: Fix CORE idle transition
From: Paul Walmsley p...@pwsan.com The HW superwised smart idle for wdtimer in OMAP3 prevents CORE power domain idle transitions. Disable it by swithing to SW supervised transitions. This could be a hardware bug in the OMAP3 wdtimer2 block. Signed-off-by: Kalle Jokiniemi kalle.jokini...@nokia.com Signed-off-by: Paul Walmsley p...@pwsan.com Cc: Benoit Cousson b-cous...@ti.com --- arch/arm/mach-omap2/omap_hwmod_3xxx_data.c |5 + 1 files changed, 5 insertions(+), 0 deletions(-) diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c index 196a834..ebd3309 100644 --- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c @@ -1293,6 +1293,11 @@ static struct omap_hwmod omap3xxx_wd_timer2_hwmod = { .slaves = omap3xxx_wd_timer2_slaves, .slaves_cnt = ARRAY_SIZE(omap3xxx_wd_timer2_slaves), .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430), + /* +* XXX: Use software supervised mode, HW supervised smartidle seems to +* block CORE power domain idle transitions. Maybe a HW bug in wdt2? +*/ + .flags = HWMOD_SWSUP_SIDLE, }; /* UART common */ -- 1.7.1 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 1/2] Watchdog: omap_wdt: add fine grain runtime-pm
From: Paul Walmsley p...@pwsan.com The omap_wdt should only be in full active state when the registers are being accessed. Otherwise the device can be on lower power mode. This patch is based on a patch created by Kalle Jokiniemi: https://patchwork.kernel.org/patch/618231/ which is itself based on a patch created by Atal Shargorodsky: http://lkml.org/lkml/2009/3/10/266. Signed-off-by: Paul Walmsley p...@pwsan.com Signed-off-by: Kalle Jokiniemi kalle.jokini...@nokia.com Tested-by: Kalle Jokiniemi kalle.jokini...@nokia.com Cc: Wim Van Sebroeck w...@iguana.be --- drivers/watchdog/omap_wdt.c | 25 +++-- 1 files changed, 23 insertions(+), 2 deletions(-) diff --git a/drivers/watchdog/omap_wdt.c b/drivers/watchdog/omap_wdt.c index 3dd4971..2b4acb8 100644 --- a/drivers/watchdog/omap_wdt.c +++ b/drivers/watchdog/omap_wdt.c @@ -124,6 +124,8 @@ static void omap_wdt_set_timeout(struct omap_wdt_dev *wdev) u32 pre_margin = GET_WLDR_VAL(timer_margin); void __iomem *base = wdev-base; + pm_runtime_get_sync(wdev-dev); + /* just count up at 32 KHz */ while (__raw_readl(base + OMAP_WATCHDOG_WPS) 0x04) cpu_relax(); @@ -131,6 +133,8 @@ static void omap_wdt_set_timeout(struct omap_wdt_dev *wdev) __raw_writel(pre_margin, base + OMAP_WATCHDOG_LDR); while (__raw_readl(base + OMAP_WATCHDOG_WPS) 0x04) cpu_relax(); + + pm_runtime_put_sync(wdev-dev); } /* @@ -160,6 +164,8 @@ static int omap_wdt_open(struct inode *inode, struct file *file) omap_wdt_ping(wdev); /* trigger loading of new timeout value */ omap_wdt_enable(wdev); + pm_runtime_put_sync(wdev-dev); + return nonseekable_open(inode, file); } @@ -171,6 +177,7 @@ static int omap_wdt_release(struct inode *inode, struct file *file) * Shut off the timer unless NOWAYOUT is defined. */ #ifndef CONFIG_WATCHDOG_NOWAYOUT + pm_runtime_get_sync(wdev-dev); omap_wdt_disable(wdev); @@ -190,9 +197,11 @@ static ssize_t omap_wdt_write(struct file *file, const char __user *data, /* Refresh LOAD_TIME. */ if (len) { + pm_runtime_get_sync(wdev-dev); spin_lock(wdt_lock); omap_wdt_ping(wdev); spin_unlock(wdt_lock); + pm_runtime_put_sync(wdev-dev); } return len; } @@ -224,15 +233,18 @@ static long omap_wdt_ioctl(struct file *file, unsigned int cmd, return put_user(omap_prcm_get_reset_sources(), (int __user *)arg); case WDIOC_KEEPALIVE: + pm_runtime_get_sync(wdev-dev); spin_lock(wdt_lock); omap_wdt_ping(wdev); spin_unlock(wdt_lock); + pm_runtime_put_sync(wdev-dev); return 0; case WDIOC_SETTIMEOUT: if (get_user(new_margin, (int __user *)arg)) return -EFAULT; omap_wdt_adjust_timeout(new_margin); + pm_runtime_get_sync(wdev-dev); spin_lock(wdt_lock); omap_wdt_disable(wdev); omap_wdt_set_timeout(wdev); @@ -240,6 +252,7 @@ static long omap_wdt_ioctl(struct file *file, unsigned int cmd, omap_wdt_ping(wdev); spin_unlock(wdt_lock); + pm_runtime_put_sync(wdev-dev); /* Fall */ case WDIOC_GETTIMEOUT: return put_user(timer_margin, (int __user *)arg); @@ -345,8 +358,11 @@ static void omap_wdt_shutdown(struct platform_device *pdev) { struct omap_wdt_dev *wdev = platform_get_drvdata(pdev); - if (wdev-omap_wdt_users) + if (wdev-omap_wdt_users) { + pm_runtime_get_sync(wdev-dev); omap_wdt_disable(wdev); + pm_runtime_put_sync(wdev-dev); + } } static int __devexit omap_wdt_remove(struct platform_device *pdev) @@ -381,8 +397,11 @@ static int omap_wdt_suspend(struct platform_device *pdev, pm_message_t state) { struct omap_wdt_dev *wdev = platform_get_drvdata(pdev); - if (wdev-omap_wdt_users) + if (wdev-omap_wdt_users) { + pm_runtime_get_sync(wdev-dev); omap_wdt_disable(wdev); + pm_runtime_put_sync(wdev-dev); + } return 0; } @@ -392,8 +411,10 @@ static int omap_wdt_resume(struct platform_device *pdev) struct omap_wdt_dev *wdev = platform_get_drvdata(pdev); if (wdev-omap_wdt_users) { + pm_runtime_get_sync(wdev-dev); omap_wdt_enable(wdev); omap_wdt_ping(wdev); + pm_runtime_put_sync(wdev-dev); } return 0; -- 1.7.1 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org
[PATCH 0/2] omap_wdt: fix interface clock handling
The runtime PM does not offer enough granularity to control individual clocks separately as needed. Current pm implementation of omap_wdt blocks the CORE power domain from idling in OMAP SoC, as it keeps the interface clock of the watchdog always on. This causes severe power leakage in devices where the omap watchdog is in active use. This patch set reverts the omap_wdt move to runtime_pm and introduces a tight control of the interface clock in the driver to only enable it when registers are accessed. The patch is based on earlier patch by Atal Shargorodsky. If anyone has good suggestions how to fix this with runtime_pm, feel free to propose patches. Otherwise I suggest we revert back to something that works. Tested with RX-51 S4.0 Macroboard, linux-omap-pm/pm branch and MeeGo armv7l release. Kalle Jokiniemi (2): Revert OMAP: WDT: Use PM runtime APIs instead of clk FW APIs Watchdog: omap_wdt: fix interface clock handling drivers/watchdog/omap_wdt.c | 64 +-- 1 files changed, 55 insertions(+), 9 deletions(-) -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 1/2] Revert OMAP: WDT: Use PM runtime APIs instead of clk FW APIs
This reverts commit 7ec5ad0f3c1e28b693185c35f768953c5db32291. The runtime PM APIs do not allow separate switching of watchdog interface clock. Both functional clock and interface clock are switched at the same time. This results in the CORE power domain being unable to sleep due to the watchdog interface clock always remaining on when the watchdog is active. Signed-off-by: Kalle Jokiniemi kalle.jokini...@nokia.com --- drivers/watchdog/omap_wdt.c | 42 +++--- 1 files changed, 35 insertions(+), 7 deletions(-) diff --git a/drivers/watchdog/omap_wdt.c b/drivers/watchdog/omap_wdt.c index 3dd4971..81e3d61 100644 --- a/drivers/watchdog/omap_wdt.c +++ b/drivers/watchdog/omap_wdt.c @@ -38,11 +38,11 @@ #include linux/err.h #include linux/platform_device.h #include linux/moduleparam.h +#include linux/clk.h #include linux/bitops.h #include linux/io.h #include linux/uaccess.h #include linux/slab.h -#include linux/pm_runtime.h #include mach/hardware.h #include plat/prcm.h @@ -61,6 +61,8 @@ struct omap_wdt_dev { void __iomem*base; /* physical */ struct device *dev; int omap_wdt_users; + struct clk *ick; + struct clk *fck; struct resource *mem; struct miscdevice omap_wdt_miscdev; }; @@ -144,7 +146,8 @@ static int omap_wdt_open(struct inode *inode, struct file *file) if (test_and_set_bit(1, (unsigned long *)(wdev-omap_wdt_users))) return -EBUSY; - pm_runtime_get_sync(wdev-dev); + clk_enable(wdev-ick);/* Enable the interface clock */ + clk_enable(wdev-fck);/* Enable the functional clock */ /* initialize prescaler */ while (__raw_readl(base + OMAP_WATCHDOG_WPS) 0x01) @@ -174,7 +177,8 @@ static int omap_wdt_release(struct inode *inode, struct file *file) omap_wdt_disable(wdev); - pm_runtime_put_sync(wdev-dev); + clk_disable(wdev-ick); + clk_disable(wdev-fck); #else printk(KERN_CRIT omap_wdt: Unexpected close, not stopping!\n); #endif @@ -289,7 +293,19 @@ static int __devinit omap_wdt_probe(struct platform_device *pdev) wdev-omap_wdt_users = 0; wdev-mem = mem; - wdev-dev = pdev-dev; + + wdev-ick = clk_get(pdev-dev, ick); + if (IS_ERR(wdev-ick)) { + ret = PTR_ERR(wdev-ick); + wdev-ick = NULL; + goto err_clk; + } + wdev-fck = clk_get(pdev-dev, fck); + if (IS_ERR(wdev-fck)) { + ret = PTR_ERR(wdev-fck); + wdev-fck = NULL; + goto err_clk; + } wdev-base = ioremap(res-start, resource_size(res)); if (!wdev-base) { @@ -299,8 +315,8 @@ static int __devinit omap_wdt_probe(struct platform_device *pdev) platform_set_drvdata(pdev, wdev); - pm_runtime_enable(wdev-dev); - pm_runtime_get_sync(wdev-dev); + clk_enable(wdev-ick); + clk_enable(wdev-fck); omap_wdt_disable(wdev); omap_wdt_adjust_timeout(timer_margin); @@ -318,7 +334,11 @@ static int __devinit omap_wdt_probe(struct platform_device *pdev) __raw_readl(wdev-base + OMAP_WATCHDOG_REV) 0xFF, timer_margin); - pm_runtime_put_sync(wdev-dev); + /* autogate OCP interface clock */ + __raw_writel(0x01, wdev-base + OMAP_WATCHDOG_SYS_CONFIG); + + clk_disable(wdev-ick); + clk_disable(wdev-fck); omap_wdt_dev = pdev; @@ -330,6 +350,12 @@ err_misc: err_ioremap: wdev-base = NULL; + +err_clk: + if (wdev-ick) + clk_put(wdev-ick); + if (wdev-fck) + clk_put(wdev-fck); kfree(wdev); err_kzalloc: @@ -361,6 +387,8 @@ static int __devexit omap_wdt_remove(struct platform_device *pdev) release_mem_region(res-start, resource_size(res)); platform_set_drvdata(pdev, NULL); + clk_put(wdev-ick); + clk_put(wdev-fck); iounmap(wdev-base); kfree(wdev); -- 1.7.1 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 2/2] Watchdog: omap_wdt: fix interface clock handling
Keeping the omap watchdog interface clock always enabled blocks OMAP CORE power domain from sleeping. Introduce fine grain clock control to fix the issue. This patch is based on a patch created by Atal Shargorodsky: http://lkml.org/lkml/2009/3/10/266. Signed-off-by: Kalle Jokiniemi kalle.jokini...@nokia.com Cc: Atal Shargorodsky ext-atal.shargorod...@nokia.com --- drivers/watchdog/omap_wdt.c | 22 -- 1 files changed, 20 insertions(+), 2 deletions(-) diff --git a/drivers/watchdog/omap_wdt.c b/drivers/watchdog/omap_wdt.c index 81e3d61..f74eca2 100644 --- a/drivers/watchdog/omap_wdt.c +++ b/drivers/watchdog/omap_wdt.c @@ -126,6 +126,7 @@ static void omap_wdt_set_timeout(struct omap_wdt_dev *wdev) u32 pre_margin = GET_WLDR_VAL(timer_margin); void __iomem *base = wdev-base; + clk_enable(wdev-ick); /* just count up at 32 KHz */ while (__raw_readl(base + OMAP_WATCHDOG_WPS) 0x04) cpu_relax(); @@ -133,6 +134,7 @@ static void omap_wdt_set_timeout(struct omap_wdt_dev *wdev) __raw_writel(pre_margin, base + OMAP_WATCHDOG_LDR); while (__raw_readl(base + OMAP_WATCHDOG_WPS) 0x04) cpu_relax(); + clk_disable(wdev-ick); } /* @@ -162,6 +164,7 @@ static int omap_wdt_open(struct inode *inode, struct file *file) omap_wdt_set_timeout(wdev); omap_wdt_ping(wdev); /* trigger loading of new timeout value */ omap_wdt_enable(wdev); + clk_disable(wdev-ick); return nonseekable_open(inode, file); } @@ -175,6 +178,7 @@ static int omap_wdt_release(struct inode *inode, struct file *file) */ #ifndef CONFIG_WATCHDOG_NOWAYOUT + clk_enable(wdev-ick); omap_wdt_disable(wdev); clk_disable(wdev-ick); @@ -194,9 +198,11 @@ static ssize_t omap_wdt_write(struct file *file, const char __user *data, /* Refresh LOAD_TIME. */ if (len) { + clk_enable(wdev-ick); spin_lock(wdt_lock); omap_wdt_ping(wdev); spin_unlock(wdt_lock); + clk_disable(wdev-ick); } return len; } @@ -228,15 +234,18 @@ static long omap_wdt_ioctl(struct file *file, unsigned int cmd, return put_user(omap_prcm_get_reset_sources(), (int __user *)arg); case WDIOC_KEEPALIVE: + clk_enable(wdev-ick); spin_lock(wdt_lock); omap_wdt_ping(wdev); spin_unlock(wdt_lock); + clk_disable(wdev-ick); return 0; case WDIOC_SETTIMEOUT: if (get_user(new_margin, (int __user *)arg)) return -EFAULT; omap_wdt_adjust_timeout(new_margin); + clk_enable(wdev-ick); spin_lock(wdt_lock); omap_wdt_disable(wdev); omap_wdt_set_timeout(wdev); @@ -244,6 +253,7 @@ static long omap_wdt_ioctl(struct file *file, unsigned int cmd, omap_wdt_ping(wdev); spin_unlock(wdt_lock); + clk_disable(wdev-ick); /* Fall */ case WDIOC_GETTIMEOUT: return put_user(timer_margin, (int __user *)arg); @@ -371,8 +381,11 @@ static void omap_wdt_shutdown(struct platform_device *pdev) { struct omap_wdt_dev *wdev = platform_get_drvdata(pdev); - if (wdev-omap_wdt_users) + if (wdev-omap_wdt_users) { + clk_enable(wdev-ick); omap_wdt_disable(wdev); + clk_disable(wdev-ick); + } } static int __devexit omap_wdt_remove(struct platform_device *pdev) @@ -409,8 +422,11 @@ static int omap_wdt_suspend(struct platform_device *pdev, pm_message_t state) { struct omap_wdt_dev *wdev = platform_get_drvdata(pdev); - if (wdev-omap_wdt_users) + if (wdev-omap_wdt_users) { + clk_enable(wdev-ick); omap_wdt_disable(wdev); + clk_disable(wdev-ick); + } return 0; } @@ -420,8 +436,10 @@ static int omap_wdt_resume(struct platform_device *pdev) struct omap_wdt_dev *wdev = platform_get_drvdata(pdev); if (wdev-omap_wdt_users) { + clk_enable(wdev-ick); omap_wdt_enable(wdev); omap_wdt_ping(wdev); + clk_disable(wdev-ick); } return 0; -- 1.7.1 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] OMAP: I2C: Add mpu wake up latency constraint in i2c
From: ext Kalle Jokiniemi kalle.jokini...@digia.com While waiting for completion of the i2c transfer, the MPU could hit OFF mode and cause several msecs of delay that made i2c transfers fail more often. The extra delays and subsequent re-trys cause i2c clocks to be active more often. This has also an negative effect on power consumption. Created a mechanism for passing and using the constraint setting function in driver code. The used mpu wake up latency constraints are now set individually per bus, and they are calculated based on clock rate and fifo size. Thanks to Jarkko Nikula, Moiz Sonasath, Paul Walmsley, and Nishanth Menon for tuning out the details of this patch. Cc: Moiz Sonasath m-sonas...@ti.com Cc: Jarkko Nikula jhnik...@gmail.com Cc: Paul Walmsley p...@pwsan.com Cc: Nishanth Menon n...@ti.com Signed-off-by: Kalle Jokiniemi kalle.jokini...@digia.com --- arch/arm/plat-omap/i2c.c | 54 +++- drivers/i2c/busses/i2c-omap.c | 25 --- include/linux/i2c-omap.h |9 +++ 3 files changed, 72 insertions(+), 16 deletions(-) create mode 100644 include/linux/i2c-omap.h diff --git a/arch/arm/plat-omap/i2c.c b/arch/arm/plat-omap/i2c.c index 8b84839..3c122cd 100644 --- a/arch/arm/plat-omap/i2c.c +++ b/arch/arm/plat-omap/i2c.c @@ -26,8 +26,10 @@ #include linux/kernel.h #include linux/platform_device.h #include linux/i2c.h +#include linux/i2c-omap.h #include mach/irqs.h #include mach/mux.h +#include mach/omap-pm.h #define OMAP_I2C_SIZE 0x3f #define OMAP1_I2C_BASE 0xfffb3800 @@ -69,14 +71,14 @@ static struct resource i2c_resources[][2] = { }, \ } -static u32 i2c_rate[ARRAY_SIZE(i2c_resources)]; +static struct omap_i2c_bus_platform_data i2c_pdata[ARRAY_SIZE(i2c_resources)]; static struct platform_device omap_i2c_devices[] = { - I2C_DEV_BUILDER(1, i2c_resources[0], i2c_rate[0]), + I2C_DEV_BUILDER(1, i2c_resources[0], i2c_pdata[0]), #ifdefined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) - I2C_DEV_BUILDER(2, i2c_resources[1], i2c_rate[1]), + I2C_DEV_BUILDER(2, i2c_resources[1], i2c_pdata[1]), #endif #ifdefined(CONFIG_ARCH_OMAP34XX) - I2C_DEV_BUILDER(3, i2c_resources[2], i2c_rate[2]), + I2C_DEV_BUILDER(3, i2c_resources[2], i2c_pdata[2]), #endif }; @@ -100,6 +102,31 @@ static const int omap34xx_pins[][2] = {}; #define OMAP_I2C_CMDLINE_SETUP (BIT(31)) +#ifdef CONFIG_ARCH_OMAP34XX +/* + * omap_i2c_set_wfc_mpu_wkup_lat - sets mpu wake up constraint + * @dev: i2c bus device pointer + * @val: latency constraint to set, -1 to disable constraint + * + * When waiting for completion of a i2c transfer, we need to set a wake up + * latency constraint for the MPU. This is to ensure quick enough wakeup from + * idle, when transfer completes. + */ +static void omap_i2c_set_wfc_mpu_wkup_lat(struct device *dev, int val) +{ + omap_pm_set_max_mpu_wakeup_lat(dev, val); +} +#endif + +static void __init omap_set_i2c_constraint_func( + struct omap_i2c_bus_platform_data *pd) +{ + if (cpu_is_omap34xx()) + pd-set_mpu_wkup_lat = omap_i2c_set_wfc_mpu_wkup_lat; + else + pd-set_mpu_wkup_lat = NULL; +} + static void __init omap_i2c_mux_pins(int bus) { int scl, sda; @@ -180,8 +207,8 @@ static int __init omap_i2c_bus_setup(char *str) get_options(str, 3, ints); if (ints[0] 2 || ints[1] 1 || ints[1] ports) return 0; - i2c_rate[ints[1] - 1] = ints[2]; - i2c_rate[ints[1] - 1] |= OMAP_I2C_CMDLINE_SETUP; + i2c_pdata[ints[1] - 1].clkrate = ints[2]; + i2c_pdata[ints[1] - 1].clkrate |= OMAP_I2C_CMDLINE_SETUP; return 1; } @@ -195,9 +222,10 @@ static int __init omap_register_i2c_bus_cmdline(void) { int i, err = 0; - for (i = 0; i ARRAY_SIZE(i2c_rate); i++) - if (i2c_rate[i] OMAP_I2C_CMDLINE_SETUP) { - i2c_rate[i] = ~OMAP_I2C_CMDLINE_SETUP; + for (i = 0; i ARRAY_SIZE(i2c_pdata); i++) + if (i2c_pdata[i].clkrate OMAP_I2C_CMDLINE_SETUP) { + i2c_pdata[i].clkrate = ~OMAP_I2C_CMDLINE_SETUP; + omap_set_i2c_constraint_func(i2c_pdata[i]); err = omap_i2c_add_bus(i + 1); if (err) goto out; @@ -231,9 +259,11 @@ int __init omap_register_i2c_bus(int bus_id, u32 clkrate, return err; } - if (!i2c_rate[bus_id - 1]) - i2c_rate[bus_id - 1] = clkrate; - i2c_rate[bus_id - 1] = ~OMAP_I2C_CMDLINE_SETUP; + if (!i2c_pdata[bus_id - 1].clkrate) + i2c_pdata[bus_id - 1].clkrate = clkrate; + + omap_set_i2c_constraint_func(i2c_pdata[bus_id - 1]); + i2c_pdata[bus_id - 1].clkrate = ~OMAP_I2C_CMDLINE_SETUP
Re: [PATCH 1/3] OMAP3: Only update pm-counters when needed
Hi Kevin, On Fri, 2009-10-30 at 01:07 +0200, Kevin Hilman wrote: Kalle Jokiniemi kalle.jokini...@digia.com writes: From: Kalle Jokiniemi ext-kalle.jokini...@nokia.com The biggest source of latency in idle loop (omap_sram_idle function) comes from updating the state counters for each power domain. The two purposes of these counters are to provide debug data in debugfs, and to keep track of context losses occurring during idle transitions (off mode counters). I created new debugfs interface enable_count for enabling the count interface, which exposes the debug part of these counters. The counters are not updated anymore for CORE ON idle transitions, when the count interface is disabled. For deeper CORE states, counters are still updated to preserve context loss tracking. This change decreases C1/C2 state latency over 100us at OPP2. Signed-off-by: Kalle Jokiniemi ext-kalle.jokini...@nokia.com I'm not opposed to this patch in principle, but I wonder if we might be able to get rid of most of this delay with some optimizations in the powerdomain code. Well, I had similar thoughts, but opted just disabling what I could when not using the debugfs. It seems like valid approach, since we do not want unused debug functionality to hinder performance. With more thinkwork and these discussions, I'm sure we can get the powerdomain code to perform much better, in addition to my patch. I'm guessing it's the reads from the PRCM that are causing such a delay since otherwise, that should be a pretty fast codepath. In this case there are reads of PWRSTST and reads and writes of PREPWRSTST for each powerdomain. Yes, I wonder why they are so slow? I noticed the same in patch 2/3 of this set: reading the PREPWRSTST_PER seems to take over 10us at OPP2. That's a huge delay for a simple register access IMO. I even tried removing all the fancy bit-toggling and use a direct read with a bitmask, but that did not have effect, still over 10us. Paul has mentioned a few times the idea of having some powerdomain enhancements that cache a copy of some of these registers so they don't have to always be read/written from the PRCM, although I'm not sure without digging some more if that makes sense for the PWRST and PREPWRST registers. If I can make it today, I'll check how long a PWRST reg read takes. I know the PREPWRST takes long. Reading the next state (PWRSTCTRL) is fast according to my earlier measurements. I think we could also be a bit smarter about doing the transition counters for every powerdomain. During most of the transitions, we don't actually expect a transition for many of the powerdomains because a transition hasn't been programmed. Maybe we can skip the PRM reads in those cases. This is a good point. There's no sense in updating the statuses for non-transitioning power domains (and spending tens of us waiting for those updates). Anyways, some comments on the actual patch below... --- arch/arm/mach-omap2/pm-debug.c | 51 ++- arch/arm/mach-omap2/pm.h |2 + arch/arm/mach-omap2/pm34xx.c | 12 + 3 files changed, 58 insertions(+), 7 deletions(-) diff --git a/arch/arm/mach-omap2/pm-debug.c b/arch/arm/mach-omap2/pm-debug.c index 5aac64f..76c2696 100644 --- a/arch/arm/mach-omap2/pm-debug.c +++ b/arch/arm/mach-omap2/pm-debug.c @@ -37,6 +37,9 @@ #include prm-regbits-34xx.h int omap2_pm_debug; +static int pm_dbg_count_active; +static struct dentry *de_pm_debug_count; +static struct dentry *de_pm_debug; #define DUMP_PRM_MOD_REG(mod, reg)\ regs[reg_count].name = #mod . #reg; \ @@ -327,6 +330,11 @@ int pm_dbg_regset_save(int reg_set) return 0; } +int pm_dbg_count_is_active(void) +{ + return pm_dbg_count_active; +} + static const char pwrdm_state_names[][4] = { OFF, RET, @@ -460,6 +468,40 @@ static const struct file_operations debug_reg_fops = { .release= single_release, }; +static int pm_dbg_count_enable_get(void *data, u64 *val) +{ + *val = pm_dbg_count_active; + return 0; +} + +static int pm_dbg_count_enable_set(void *data, u64 val) +{ + if (val 1) { + printk(KERN_ERR Invalid value! 1 to enable, 0 to disable\n); + return -EINVAL; + } + + if (val == 1 !pm_dbg_count_active) { + de_pm_debug_count = debugfs_create_file(count, S_IRUGO, + de_pm_debug, (void *)DEBUG_FILE_COUNTERS, debug_fops); + + if (de_pm_debug_count == NULL) { + printk(KERN_ERR Error: could not create debugfs + entry\n); + return -ENOMEM; + } + pm_dbg_count_active = 1; + } else if (val == 0 pm_dbg_count_active) { + debugfs_remove(de_pm_debug_count); + de_pm_debug_count = NULL
[PATCH V2] OMAP3: Only update pm-counters when needed
From: Kalle Jokiniemi ext-kalle.jokini...@nokia.com The biggest source of latency in idle loop (omap_sram_idle function) comes from updating the state counters for each power domain. The two purposes of these counters are to provide debug data in debugfs, and to keep track of context losses occurring during idle transitions (off mode counters). I created new debugfs interface enable_count for enabling the count interface, which exposes the debug part of these counters. The counters are not updated anymore for CORE ON idle transitions, when the count interface is disabled. For deeper CORE states, counters are still updated to preserve context loss tracking. This change decreases C1/C2 state latency over 100us at OPP2. Signed-off-by: Kalle Jokiniemi ext-kalle.jokini...@nokia.com --- arch/arm/mach-omap2/pm-debug.c| 51 - arch/arm/mach-omap2/pm.h |2 + arch/arm/mach-omap2/pm34xx.c | 10 ++-- arch/arm/mach-omap2/powerdomain.c | 10 +++-- arch/arm/plat-omap/include/mach/powerdomain.h |4 +- 5 files changed, 64 insertions(+), 13 deletions(-) diff --git a/arch/arm/mach-omap2/pm-debug.c b/arch/arm/mach-omap2/pm-debug.c index 5aac64f..76c2696 100644 --- a/arch/arm/mach-omap2/pm-debug.c +++ b/arch/arm/mach-omap2/pm-debug.c @@ -37,6 +37,9 @@ #include prm-regbits-34xx.h int omap2_pm_debug; +static int pm_dbg_count_active; +static struct dentry *de_pm_debug_count; +static struct dentry *de_pm_debug; #define DUMP_PRM_MOD_REG(mod, reg)\ regs[reg_count].name = #mod . #reg; \ @@ -327,6 +330,11 @@ int pm_dbg_regset_save(int reg_set) return 0; } +int pm_dbg_count_is_active(void) +{ + return pm_dbg_count_active; +} + static const char pwrdm_state_names[][4] = { OFF, RET, @@ -460,6 +468,40 @@ static const struct file_operations debug_reg_fops = { .release= single_release, }; +static int pm_dbg_count_enable_get(void *data, u64 *val) +{ + *val = pm_dbg_count_active; + return 0; +} + +static int pm_dbg_count_enable_set(void *data, u64 val) +{ + if (val 1) { + printk(KERN_ERR Invalid value! 1 to enable, 0 to disable\n); + return -EINVAL; + } + + if (val == 1 !pm_dbg_count_active) { + de_pm_debug_count = debugfs_create_file(count, S_IRUGO, + de_pm_debug, (void *)DEBUG_FILE_COUNTERS, debug_fops); + + if (de_pm_debug_count == NULL) { + printk(KERN_ERR Error: could not create debugfs + entry\n); + return -ENOMEM; + } + pm_dbg_count_active = 1; + } else if (val == 0 pm_dbg_count_active) { + debugfs_remove(de_pm_debug_count); + de_pm_debug_count = NULL; + pm_dbg_count_active = 0; + } + return 0; +} + +DEFINE_SIMPLE_ATTRIBUTE(enable_count_fops, pm_dbg_count_enable_get, + pm_dbg_count_enable_set, %llu\n); + int pm_dbg_regset_init(int reg_set) { char name[2]; @@ -576,12 +618,17 @@ static int __init pm_dbg_init(void) return -ENODEV; } + pm_dbg_count_active = 0; + d = debugfs_create_dir(pm_debug, NULL); if (IS_ERR(d)) return PTR_ERR(d); + de_pm_debug = d; + + (void) debugfs_create_file(enable_count, S_IRUGO | + S_IWUGO, d, pm_dbg_count_active, + enable_count_fops); - (void) debugfs_create_file(count, S_IRUGO, - d, (void *)DEBUG_FILE_COUNTERS, debug_fops); (void) debugfs_create_file(time, S_IRUGO, d, (void *)DEBUG_FILE_TIMERS, debug_fops); diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h index f8d11a2..3f0202b 100644 --- a/arch/arm/mach-omap2/pm.h +++ b/arch/arm/mach-omap2/pm.h @@ -63,12 +63,14 @@ extern int omap2_pm_debug; extern void pm_dbg_update_time(struct powerdomain *pwrdm, int prev); extern int pm_dbg_regset_save(int reg_set); extern int pm_dbg_regset_init(int reg_set); +extern int pm_dbg_count_is_active(void); #else #define omap2_pm_dump(mode, resume, us)do {} while (0); #define omap2_pm_debug 0 #define pm_dbg_update_time(pwrdm, prev) do {} while (0); #define pm_dbg_regset_save(reg_set) do {} while (0); #define pm_dbg_regset_init(reg_set) do {} while (0); +#define pm_dbg_count_is_active() 0 #endif /* CONFIG_PM_DEBUG */ extern void omap24xx_idle_loop_suspend(void); diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c index 01260ec..1e3041e 100644 --- a/arch/arm/mach-omap2/pm34xx.c +++ b/arch/arm/mach-omap2/pm34xx.c @@ -378,15 +378,16 @@ void omap_sram_idle(void) return; } - pwrdm_pre_transition(); + per_next_state
Re: [PATCH V2] OMAP3: Only update pm-counters when needed
On Fri, 2009-10-30 at 13:26 +0200, Kalle Jokiniemi wrote: From: Kalle Jokiniemi ext-kalle.jokini...@nokia.com The biggest source of latency in idle loop (omap_sram_idle function) comes from updating the state counters for each power domain. The two purposes of these counters are to provide debug data in debugfs, and to keep track of context losses occurring during idle transitions (off mode counters). I created new debugfs interface enable_count for enabling the count interface, which exposes the debug part of these counters. The counters are not updated anymore for CORE ON idle transitions, when the count interface is disabled. For deeper CORE states, counters are still updated to preserve context loss tracking. This change decreases C1/C2 state latency over 100us at OPP2. Signed-off-by: Kalle Jokiniemi ext-kalle.jokini...@nokia.com --- arch/arm/mach-omap2/pm-debug.c| 51 - arch/arm/mach-omap2/pm.h |2 + arch/arm/mach-omap2/pm34xx.c | 10 ++-- arch/arm/mach-omap2/powerdomain.c | 10 +++-- arch/arm/plat-omap/include/mach/powerdomain.h |4 +- 5 files changed, 64 insertions(+), 13 deletions(-) diff --git a/arch/arm/mach-omap2/pm-debug.c b/arch/arm/mach-omap2/pm-debug.c index 5aac64f..76c2696 100644 --- a/arch/arm/mach-omap2/pm-debug.c +++ b/arch/arm/mach-omap2/pm-debug.c @@ -37,6 +37,9 @@ #include prm-regbits-34xx.h int omap2_pm_debug; +static int pm_dbg_count_active; +static struct dentry *de_pm_debug_count; +static struct dentry *de_pm_debug; #define DUMP_PRM_MOD_REG(mod, reg)\ regs[reg_count].name = #mod . #reg; \ @@ -327,6 +330,11 @@ int pm_dbg_regset_save(int reg_set) return 0; } +int pm_dbg_count_is_active(void) +{ + return pm_dbg_count_active; +} + static const char pwrdm_state_names[][4] = { OFF, RET, @@ -460,6 +468,40 @@ static const struct file_operations debug_reg_fops = { .release= single_release, }; +static int pm_dbg_count_enable_get(void *data, u64 *val) +{ + *val = pm_dbg_count_active; + return 0; +} + +static int pm_dbg_count_enable_set(void *data, u64 val) +{ + if (val 1) { + printk(KERN_ERR Invalid value! 1 to enable, 0 to disable\n); + return -EINVAL; + } + + if (val == 1 !pm_dbg_count_active) { + de_pm_debug_count = debugfs_create_file(count, S_IRUGO, + de_pm_debug, (void *)DEBUG_FILE_COUNTERS, debug_fops); + + if (de_pm_debug_count == NULL) { + printk(KERN_ERR Error: could not create debugfs + entry\n); + return -ENOMEM; + } + pm_dbg_count_active = 1; + } else if (val == 0 pm_dbg_count_active) { + debugfs_remove(de_pm_debug_count); + de_pm_debug_count = NULL; + pm_dbg_count_active = 0; + } + return 0; +} + +DEFINE_SIMPLE_ATTRIBUTE(enable_count_fops, pm_dbg_count_enable_get, + pm_dbg_count_enable_set, %llu\n); + int pm_dbg_regset_init(int reg_set) { char name[2]; @@ -576,12 +618,17 @@ static int __init pm_dbg_init(void) return -ENODEV; } + pm_dbg_count_active = 0; + d = debugfs_create_dir(pm_debug, NULL); if (IS_ERR(d)) return PTR_ERR(d); + de_pm_debug = d; + + (void) debugfs_create_file(enable_count, S_IRUGO | + S_IWUGO, d, pm_dbg_count_active, + enable_count_fops); - (void) debugfs_create_file(count, S_IRUGO, - d, (void *)DEBUG_FILE_COUNTERS, debug_fops); (void) debugfs_create_file(time, S_IRUGO, d, (void *)DEBUG_FILE_TIMERS, debug_fops); diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h index f8d11a2..3f0202b 100644 --- a/arch/arm/mach-omap2/pm.h +++ b/arch/arm/mach-omap2/pm.h @@ -63,12 +63,14 @@ extern int omap2_pm_debug; extern void pm_dbg_update_time(struct powerdomain *pwrdm, int prev); extern int pm_dbg_regset_save(int reg_set); extern int pm_dbg_regset_init(int reg_set); +extern int pm_dbg_count_is_active(void); #else #define omap2_pm_dump(mode, resume, us) do {} while (0); #define omap2_pm_debug 0 #define pm_dbg_update_time(pwrdm, prev) do {} while (0); #define pm_dbg_regset_save(reg_set) do {} while (0); #define pm_dbg_regset_init(reg_set) do {} while (0); +#define pm_dbg_count_is_active() 0 #endif /* CONFIG_PM_DEBUG */ extern void omap24xx_idle_loop_suspend(void); diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c index 01260ec..1e3041e 100644 --- a/arch/arm/mach-omap2/pm34xx.c +++ b/arch/arm/mach-omap2/pm34xx.c @@ -378,15 +378,16 @@ void
[PATCH 0/3] Update CPU idle parameter passing
Hi Kevin, Made some patches to enable setting RX-51 cpu idle parameters as we use them. Added valid field passing to cpuidle_params in the process. Tested on RX-51. Applies on top of linux-omap/pm branch. Kalle Jokiniemi (3): OMAP:PM: Fix non-cpu idle builds using omap3_pm_init_cpuidle OMAP3: Add valid field into C-state parameter passing OMAP: RX-51: Pass cpu idle parameters kajok...@ubuntu:~/work/linux-open/linux-omap$ git diff --stat HEAD~3..HEAD arch/arm/mach-omap2/board-3430sdp.c | 14 ++-- arch/arm/mach-omap2/board-rx51.c| 18 + arch/arm/mach-omap2/cpuidle34xx.c | 37 +- arch/arm/mach-omap2/pm.h|8 +++ 4 files changed, 56 insertions(+), 21 deletions(-) -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 1/3] OMAP:PM: Fix non-cpu idle builds using omap3_pm_init_cpuidle
Building without CONFIG_CPU_IDLE causes build to fail if cpu idle parameters are tried to pass using omap3_pm_init_cpuidle function. Fixed by defining a dummy function for non-cpu idle builds. Signed-off-by: Kalle Jokiniemi kalle.jokini...@digia.com --- arch/arm/mach-omap2/pm.h |7 +++ 1 files changed, 7 insertions(+), 0 deletions(-) diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h index b576424..b9421e8 100644 --- a/arch/arm/mach-omap2/pm.h +++ b/arch/arm/mach-omap2/pm.h @@ -49,7 +49,14 @@ struct cpuidle_params { }; extern void omap3_pm_init_vc(struct prm_setup_vc *setup_vc); +#ifdef CONFIG_CPU_IDLE extern void omap3_pm_init_cpuidle(struct cpuidle_params *cpuidle_board_params); +#else +static inline void omap3_pm_init_cpuidle( + struct cpuidle_params *cpuidle_board_params) +{ +} +#endif extern int resource_set_opp_level(int res, u32 target_level, int flags); extern int resource_access_opp_lock(int res, int delta); -- 1.5.4.3 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 2/3] OMAP3: Add valid field into C-state parameter passing
Different boards benefit differently from the available seven C-states for cpu idle. In most cases, only few, properly spaced (in terms of consumption and latency) C-states are required to make the power management optimal. Hence we need a possibility to pass which C-states are actually used for each board. So added the valid field to cpuidle_params and added support to 3430sdp, which uses the paramenter passing. Signed-off-by: Kalle Jokiniemi kalle.jokini...@digia.com --- arch/arm/mach-omap2/board-3430sdp.c | 14 ++-- arch/arm/mach-omap2/cpuidle34xx.c | 37 +- arch/arm/mach-omap2/pm.h|1 + 3 files changed, 31 insertions(+), 21 deletions(-) diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c index 11f0dc5..74c20ee 100644 --- a/arch/arm/mach-omap2/board-3430sdp.c +++ b/arch/arm/mach-omap2/board-3430sdp.c @@ -76,19 +76,19 @@ static struct prm_setup_vc omap3_setuptime_table = { /* FIXME: These values need to be updated based on more profiling on 3430sdp*/ static struct cpuidle_params omap3_cpuidle_params_table[] = { /* C1 */ - {2, 2, 5}, + {1, 2, 2, 5}, /* C2 */ - {10, 10, 30}, + {1, 10, 10, 30}, /* C3 */ - {50, 50, 300}, + {1, 50, 50, 300}, /* C4 */ - {1500, 1800, 4000}, + {1, 1500, 1800, 4000}, /* C5 */ - {2500, 7500, 12000}, + {1, 2500, 7500, 12000}, /* C6 */ - {3000, 8500, 15000}, + {1, 3000, 8500, 15000}, /* C7 */ - {1, 3, 30}, + {1, 1, 3, 30}, }; static int board_keymap[] = { diff --git a/arch/arm/mach-omap2/cpuidle34xx.c b/arch/arm/mach-omap2/cpuidle34xx.c index fdfa1d5..9c9474a 100644 --- a/arch/arm/mach-omap2/cpuidle34xx.c +++ b/arch/arm/mach-omap2/cpuidle34xx.c @@ -69,19 +69,19 @@ struct powerdomain *mpu_pd, *core_pd; */ static struct cpuidle_params cpuidle_params_table[] = { /* C1 */ - {2, 2, 5}, + {1, 2, 2, 5}, /* C2 */ - {10, 10, 30}, + {1, 10, 10, 30}, /* C3 */ - {50, 50, 300}, + {1, 50, 50, 300}, /* C4 */ - {1500, 1800, 4000}, + {1, 1500, 1800, 4000}, /* C5 */ - {2500, 7500, 12000}, + {1, 2500, 7500, 12000}, /* C6 */ - {3000, 8500, 15000}, + {1, 3000, 8500, 15000}, /* C7 */ - {1, 3, 30}, + {1, 1, 3, 30}, }; static int omap3_idle_bm_check(void) @@ -197,6 +197,8 @@ void omap3_pm_init_cpuidle(struct cpuidle_params *cpuidle_board_params) return; for (i = OMAP3_STATE_C1; i OMAP3_MAX_STATES; i++) { + cpuidle_params_table[i].valid = + cpuidle_board_params[i].valid; cpuidle_params_table[i].sleep_latency = cpuidle_board_params[i].sleep_latency; cpuidle_params_table[i].wake_latency = @@ -221,7 +223,8 @@ void omap3_pm_init_cpuidle(struct cpuidle_params *cpuidle_board_params) void omap_init_power_states(void) { /* C1 . MPU WFI + Core active */ - omap3_power_states[OMAP3_STATE_C1].valid = 1; + omap3_power_states[OMAP3_STATE_C1].valid = + cpuidle_params_table[OMAP3_STATE_C1].valid; omap3_power_states[OMAP3_STATE_C1].type = OMAP3_STATE_C1; omap3_power_states[OMAP3_STATE_C1].sleep_latency = cpuidle_params_table[OMAP3_STATE_C1].sleep_latency; @@ -234,7 +237,8 @@ void omap_init_power_states(void) omap3_power_states[OMAP3_STATE_C1].flags = CPUIDLE_FLAG_TIME_VALID; /* C2 . MPU WFI + Core inactive */ - omap3_power_states[OMAP3_STATE_C2].valid = 1; + omap3_power_states[OMAP3_STATE_C2].valid = + cpuidle_params_table[OMAP3_STATE_C2].valid; omap3_power_states[OMAP3_STATE_C2].type = OMAP3_STATE_C2; omap3_power_states[OMAP3_STATE_C2].sleep_latency = cpuidle_params_table[OMAP3_STATE_C2].sleep_latency; @@ -247,7 +251,8 @@ void omap_init_power_states(void) omap3_power_states[OMAP3_STATE_C2].flags = CPUIDLE_FLAG_TIME_VALID; /* C3 . MPU CSWR + Core inactive */ - omap3_power_states[OMAP3_STATE_C3].valid = 1; + omap3_power_states[OMAP3_STATE_C3].valid = + cpuidle_params_table[OMAP3_STATE_C3].valid; omap3_power_states[OMAP3_STATE_C3].type = OMAP3_STATE_C3; omap3_power_states[OMAP3_STATE_C3].sleep_latency = cpuidle_params_table[OMAP3_STATE_C3].sleep_latency; @@ -261,7 +266,8 @@ void omap_init_power_states(void) CPUIDLE_FLAG_CHECK_BM; /* C4 . MPU OFF + Core inactive */ - omap3_power_states[OMAP3_STATE_C4].valid = 1; + omap3_power_states[OMAP3_STATE_C4].valid = + cpuidle_params_table[OMAP3_STATE_C4].valid; omap3_power_states
RE: [PATCH V4 3/3] OMAP: I2C: Add mpu wake up latency constraint in i2c
OK, let's try this once more, since my mail did not seem to go to linux-omap. Sorry for the spam. See my comments below: On Fri, 2009-10-23 at 18:53 +0300, Sonasath, Moiz wrote: Hello Jokiniemi! -Original Message- From: Kalle Jokiniemi [mailto:kalle.jokini...@digia.com] Sent: Wednesday, October 21, 2009 6:51 AM To: khil...@deeprootsystems.com Cc: linux-omap@vger.kernel.org; Kalle Jokiniemi; Sonasath, Moiz; Jarkko Nikula; Paul Walmsley; Menon, Nishanth Subject: [PATCH V4 3/3] OMAP: I2C: Add mpu wake up latency constraint in i2c While waiting for completion of the i2c transfer, the MPU could hit OFF mode and cause several msecs of delay that made i2c transfers fail more often. The extra delays and subsequent re-trys cause i2c clocks to be active more often. This has also an negative effect on power consumption. Created a mechanism for passing and using the constraint setting function in driver code. The used mpu wake up latency constraints are now set individually per bus, and they are calculated based on clock rate and fifo size. Thanks to Jarkko Nikula, Moiz Sonasath, Paul Walmsley, and Nishanth Menon for tuning out the details of this patch. Cc: Moiz Sonasath m-sonas...@ti.com Cc: Jarkko Nikula jhnik...@gmail.com Cc: Paul Walmsley p...@pwsan.com Cc: Nishanth Menon n...@ti.com Signed-off-by: Kalle Jokiniemi kalle.jokini...@digia.com --- dev-speed = speed; dev-idle = 1; @@ -911,6 +923,11 @@ omap_i2c_probe(struct platform_device *pdev) */ dev-fifo_size = (dev-fifo_size / 2); dev-b_hw = 1; /* Enable hardware fixes */ + + /* calculate wakeup latency constraint for MPU */ + if (dev-set_mpu_wkup_lat != NULL) + dev-latency = (100 * dev-fifo_size) / + (1000 * speed / 8); } IMHO, here instead of using 'dev-fifo_size' for calculating the 'dev-latency', we need to use: 1. For RX case, to avoid Reciver overrun: if (msg-flags I2C_M_RD) Use [(FIFO Depth)bytes - (FIFO THRSH)bytes] in calculating dev-latency Because conceptually, RDR/RRDY interrupts are generated when RTRSH is reached, so we want the MPU to be wake up within the time it takes to fill the FIFO from RTRSH to FIFO Depth (FIFO full). 2. For TX case, to avoid Transmitter Underflow: if (!(msg-flags I2C_M_RD)) Use (FIFO THRSH)bytes in calculating dev-latency Because conceptually, XDR/XRDY interrupts are generated when XTRSH is reached, so we want the MPU to be wake up within the time it takes to drain the FIFO from XTRSH to Zero (FIFO empty). Using, dev-fifo_size instead, works in the present code because we have a RTRSH/XTRSH = dev-fifo_size/2 = 4 bytes And therefore, (FIFO Depth)bytes - (FIFO THRSH)bytes = 8 - 4 = 4 bytes But, to make it more generic in future and to make it independent of any changes in the RTRSH/XTRSH values or FIFO depths in future, we should use a generic code here. Well, I don't completely agree with the necessity of preparing for different rx/tx thresholds. For this to make sense, the i2c-omap driver should first separate in it's code the use of rx and tx thresholds. If someone is planning to do that, he/she should anyway update the usage of fifo_size throughout the code, including the wake up latency setting. Anyways, attached a patch that separates the mpu wake up latencies for rx and tx. In case that is needed. Though I'm not for it, since it adds unneeded complexity. - Kalle /* reset ASAP, clearing any IRQs */ diff --git a/include/linux/i2c-omap.h b/include/linux/i2c-omap.h new file mode 100644 index 000..1362fba --- /dev/null +++ b/include/linux/i2c-omap.h @@ -0,0 +1,9 @@ +#ifndef __I2C_OMAP_H__ +#define __I2C_OMAP_H__ + +struct omap_i2c_bus_platform_data { + u32 clkrate; + void(*set_mpu_wkup_lat)(struct device *dev, int set); +}; + +#endif -- 1.5.4.3 Regards Moiz Sonasath 0001-OMAP-I2C-Add-mpu-wake-up-latency-constraint-in-i2c.patch Description: 0001-OMAP-I2C-Add-mpu-wake-up-latency-constraint-in-i2c.patch
Re: [PATCH 0/3] PM: Misc latency fixes
Hi Kevin, On Wed, 2009-10-21 at 14:51 +0300, Kalle Jokiniemi wrote: Hello, Here are some fruits from digging out the latency sources of our idle loop. The main latency source was powerdomain state counter updating at beginning and end of the idle loop. Also PER previous state reading strangely seemed to cause some latency with significance. Could not find any TRM or errata comment to why this is, though. The I2C mpu wakeup latency constraint patch has been updated to calculate latencies at boot from clkrate and fifo size. This was included in this set, since it benefits from the reduced latency of the other patches. Patches tested on linux-omap/pm and rx-51. Kalle Jokiniemi (3): OMAP3: Only update pm-counters when needed PM: Skip PER previous state register read How about those latency optimization patches? Are you are you going to take them in? I'd like to know if there is something to fix in those, so I can finish it this week. Starting next week I'll be moving to other responsibilities and might not be able to do additional changes for the patches. OMAP: I2C: Add mpu wake up latency constraint in i2c This i2c patch can be pushed separately, in case you're waiting for that thread to finish. - Kalle arch/arm/mach-omap2/pm-debug.c | 51 - arch/arm/mach-omap2/pm.h |2 + arch/arm/mach-omap2/pm34xx.c | 31 ++ arch/arm/plat-omap/i2c.c | 54 +++- drivers/i2c/busses/i2c-omap.c | 25 +++--- include/linux/i2c-omap.h |9 ++ 6 files changed, 143 insertions(+), 29 deletions(-) -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 2/3] PM: Skip PER previous state register read
According to measurements, reading the previous state of PER domain after wfi takes ~11us on OPP2. Removed this unneccessary latency from cases where we know PER power domain did not try to enter off mode. Signed-off-by: Kalle Jokiniemi kalle.jokini...@digia.com --- arch/arm/mach-omap2/pm34xx.c | 19 +-- 1 files changed, 13 insertions(+), 6 deletions(-) diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c index 237c819..b70ea19 100644 --- a/arch/arm/mach-omap2/pm34xx.c +++ b/arch/arm/mach-omap2/pm34xx.c @@ -489,12 +489,19 @@ void omap_sram_idle(void) /* PER */ if (per_next_state PWRDM_POWER_ON) { - per_prev_state = pwrdm_read_prev_pwrst(per_pwrdm); - if (per_prev_state == PWRDM_POWER_OFF) { - omap3_per_restore_context(); - omap3_gpio_restore_pad_context(0); - } else if (per_next_state == PWRDM_POWER_OFF) - omap3_gpio_restore_pad_context(1); + if (per_next_state == PWRDM_POWER_OFF) { + /* +* Reading the prev-state takes long time (1...@opp2), +* only do it, if we really tried to put PER in OFF +*/ + per_prev_state = pwrdm_read_prev_pwrst(per_pwrdm); + if (per_prev_state == PWRDM_POWER_OFF) { + omap3_per_restore_context(); + omap3_gpio_restore_pad_context(0); + } else if (per_next_state == PWRDM_POWER_OFF) { + omap3_gpio_restore_pad_context(1); + } + } omap2_gpio_resume_after_idle(); omap_uart_resume_idle(2); if (per_state_modified) -- 1.5.4.3 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 0/3] PM: Misc latency fixes
Hello, Here are some fruits from digging out the latency sources of our idle loop. The main latency source was powerdomain state counter updating at beginning and end of the idle loop. Also PER previous state reading strangely seemed to cause some latency with significance. Could not find any TRM or errata comment to why this is, though. The I2C mpu wakeup latency constraint patch has been updated to calculate latencies at boot from clkrate and fifo size. This was included in this set, since it benefits from the reduced latency of the other patches. Patches tested on linux-omap/pm and rx-51. Kalle Jokiniemi (3): OMAP3: Only update pm-counters when needed PM: Skip PER previous state register read OMAP: I2C: Add mpu wake up latency constraint in i2c arch/arm/mach-omap2/pm-debug.c | 51 - arch/arm/mach-omap2/pm.h |2 + arch/arm/mach-omap2/pm34xx.c | 31 ++ arch/arm/plat-omap/i2c.c | 54 +++- drivers/i2c/busses/i2c-omap.c | 25 +++--- include/linux/i2c-omap.h |9 ++ 6 files changed, 143 insertions(+), 29 deletions(-) -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 1/3] OMAP3: Only update pm-counters when needed
From: Kalle Jokiniemi ext-kalle.jokini...@nokia.com The biggest source of latency in idle loop (omap_sram_idle function) comes from updating the state counters for each power domain. The two purposes of these counters are to provide debug data in debugfs, and to keep track of context losses occurring during idle transitions (off mode counters). I created new debugfs interface enable_count for enabling the count interface, which exposes the debug part of these counters. The counters are not updated anymore for CORE ON idle transitions, when the count interface is disabled. For deeper CORE states, counters are still updated to preserve context loss tracking. This change decreases C1/C2 state latency over 100us at OPP2. Signed-off-by: Kalle Jokiniemi ext-kalle.jokini...@nokia.com --- arch/arm/mach-omap2/pm-debug.c | 51 ++- arch/arm/mach-omap2/pm.h |2 + arch/arm/mach-omap2/pm34xx.c | 12 + 3 files changed, 58 insertions(+), 7 deletions(-) diff --git a/arch/arm/mach-omap2/pm-debug.c b/arch/arm/mach-omap2/pm-debug.c index 5aac64f..76c2696 100644 --- a/arch/arm/mach-omap2/pm-debug.c +++ b/arch/arm/mach-omap2/pm-debug.c @@ -37,6 +37,9 @@ #include prm-regbits-34xx.h int omap2_pm_debug; +static int pm_dbg_count_active; +static struct dentry *de_pm_debug_count; +static struct dentry *de_pm_debug; #define DUMP_PRM_MOD_REG(mod, reg)\ regs[reg_count].name = #mod . #reg; \ @@ -327,6 +330,11 @@ int pm_dbg_regset_save(int reg_set) return 0; } +int pm_dbg_count_is_active(void) +{ + return pm_dbg_count_active; +} + static const char pwrdm_state_names[][4] = { OFF, RET, @@ -460,6 +468,40 @@ static const struct file_operations debug_reg_fops = { .release= single_release, }; +static int pm_dbg_count_enable_get(void *data, u64 *val) +{ + *val = pm_dbg_count_active; + return 0; +} + +static int pm_dbg_count_enable_set(void *data, u64 val) +{ + if (val 1) { + printk(KERN_ERR Invalid value! 1 to enable, 0 to disable\n); + return -EINVAL; + } + + if (val == 1 !pm_dbg_count_active) { + de_pm_debug_count = debugfs_create_file(count, S_IRUGO, + de_pm_debug, (void *)DEBUG_FILE_COUNTERS, debug_fops); + + if (de_pm_debug_count == NULL) { + printk(KERN_ERR Error: could not create debugfs + entry\n); + return -ENOMEM; + } + pm_dbg_count_active = 1; + } else if (val == 0 pm_dbg_count_active) { + debugfs_remove(de_pm_debug_count); + de_pm_debug_count = NULL; + pm_dbg_count_active = 0; + } + return 0; +} + +DEFINE_SIMPLE_ATTRIBUTE(enable_count_fops, pm_dbg_count_enable_get, + pm_dbg_count_enable_set, %llu\n); + int pm_dbg_regset_init(int reg_set) { char name[2]; @@ -576,12 +618,17 @@ static int __init pm_dbg_init(void) return -ENODEV; } + pm_dbg_count_active = 0; + d = debugfs_create_dir(pm_debug, NULL); if (IS_ERR(d)) return PTR_ERR(d); + de_pm_debug = d; + + (void) debugfs_create_file(enable_count, S_IRUGO | + S_IWUGO, d, pm_dbg_count_active, + enable_count_fops); - (void) debugfs_create_file(count, S_IRUGO, - d, (void *)DEBUG_FILE_COUNTERS, debug_fops); (void) debugfs_create_file(time, S_IRUGO, d, (void *)DEBUG_FILE_TIMERS, debug_fops); diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h index f8d11a2..3f0202b 100644 --- a/arch/arm/mach-omap2/pm.h +++ b/arch/arm/mach-omap2/pm.h @@ -63,12 +63,14 @@ extern int omap2_pm_debug; extern void pm_dbg_update_time(struct powerdomain *pwrdm, int prev); extern int pm_dbg_regset_save(int reg_set); extern int pm_dbg_regset_init(int reg_set); +extern int pm_dbg_count_is_active(void); #else #define omap2_pm_dump(mode, resume, us)do {} while (0); #define omap2_pm_debug 0 #define pm_dbg_update_time(pwrdm, prev) do {} while (0); #define pm_dbg_regset_save(reg_set) do {} while (0); #define pm_dbg_regset_init(reg_set) do {} while (0); +#define pm_dbg_count_is_active() 0 #endif /* CONFIG_PM_DEBUG */ extern void omap24xx_idle_loop_suspend(void); diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c index 01260ec..237c819 100644 --- a/arch/arm/mach-omap2/pm34xx.c +++ b/arch/arm/mach-omap2/pm34xx.c @@ -378,15 +378,17 @@ void omap_sram_idle(void) return; } - pwrdm_pre_transition(); + per_next_state = pwrdm_read_next_pwrst(per_pwrdm); + core_next_state = pwrdm_read_next_pwrst(core_pwrdm); + + if (pm_dbg_count_is_active
RE: [PATCH 1/1] OMAP: I2C: Add mpu wake up latency constraint in i2c
Hi, On Mon, 2009-10-05 at 20:08 +0300, Pandita, Vikram wrote: Jokiniemi -Original Message- From: linux-omap-ow...@vger.kernel.org [mailto:linux-omap-ow...@vger.kernel.org] On Behalf Of Kalle Jokiniemi Sent: Thursday, September 17, 2009 11:29 AM To: khil...@deeprootsystems.com Cc: jhnik...@gmail.com; linux-omap@vger.kernel.org; Kalle Jokiniemi Subject: [PATCH 1/1] OMAP: I2C: Add mpu wake up latency constraint in i2c While waiting for completion of the i2c transfer, the MPU could hit OFF mode and cause several msecs of delay that made i2c transfers fail more often. The How many bytes i2c read were you doing, that failed? This I don't know. I was monitoring average transfer times from clk_enable to clk_disable in i2c-omap.c and I noticed the transfers timed out to 1000ms several times. Hence the conclusion that something went wrong (this is what I was referring to with fail more often). What OPP are you in when you observe these failures? VDD1:OPP? I had on-demand governor in use, but device was mostly idling, so OPP2 probably. extra delays and subsequent re-trys cause i2c clocks to be active more often. This has also an negative effect on power consumption. Added a constraint that allows MPU to wake up in few hundred usecs, which is roughly the average i2c wait period. How did you arrive at the number 500us for the wakeup latency? This was about the average time that I observed i2c-transfers to be (from clk_enable to clk_disable), when off mode was not enabled. On Zoom2 with Synaptic touch screen controller on I2C-2, at vdd1:opp1 we need to put a wakeup latency of 400us else we see data corruption. Hmm, I guess you are using new cpu idle latency numbers on zoom2, since on current pm-branch code 500us==400us==C3 C-state. But I'll repost with 400us, it might make a difference once those C-state latency numbers are updated in pm-branch. - Kalle Our case is doing a write of 1 byte followed by read of 16 bytes. The constraint function is passed as platform data from plat-omap/i2c.c and applied only on OMAP34XX devices. Signed-off-by: Kalle Jokiniemi kalle.jokini...@digia.com --- arch/arm/plat-omap/i2c.c | 49 +++-- drivers/i2c/busses/i2c-omap.c | 17 +++--- include/linux/i2c-omap.h |9 +++ 3 files changed, 59 insertions(+), 16 deletions(-) create mode 100644 include/linux/i2c-omap.h diff --git a/arch/arm/plat-omap/i2c.c b/arch/arm/plat-omap/i2c.c index 8b84839..d43d0ad 100644 --- a/arch/arm/plat-omap/i2c.c +++ b/arch/arm/plat-omap/i2c.c @@ -26,8 +26,10 @@ #include linux/kernel.h #include linux/platform_device.h #include linux/i2c.h +#include linux/i2c-omap.h #include mach/irqs.h #include mach/mux.h +#include mach/omap-pm.h #define OMAP_I2C_SIZE 0x3f #define OMAP1_I2C_BASE 0xfffb3800 @@ -69,14 +71,14 @@ static struct resource i2c_resources[][2] = { }, \ } -static u32 i2c_rate[ARRAY_SIZE(i2c_resources)]; +static struct omap_i2c_bus_platform_data i2c_pdata[ARRAY_SIZE(i2c_resources)]; static struct platform_device omap_i2c_devices[] = { -I2C_DEV_BUILDER(1, i2c_resources[0], i2c_rate[0]), +I2C_DEV_BUILDER(1, i2c_resources[0], i2c_pdata[0]), #if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) -I2C_DEV_BUILDER(2, i2c_resources[1], i2c_rate[1]), +I2C_DEV_BUILDER(2, i2c_resources[1], i2c_pdata[1]), #endif #if defined(CONFIG_ARCH_OMAP34XX) -I2C_DEV_BUILDER(3, i2c_resources[2], i2c_rate[2]), +I2C_DEV_BUILDER(3, i2c_resources[2], i2c_pdata[2]), #endif }; @@ -100,6 +102,25 @@ static const int omap34xx_pins[][2] = {}; #define OMAP_I2C_CMDLINE_SETUP (BIT(31)) +/** + * omap_i2c_set_wfc_mpu_wkup_lat - sets mpu wake up constraint + * @dev:i2c bus device pointer + * @set:set or clear constraints + * + * When waiting for completion of a i2c transfer, we need to set a wake up + * latency constraint for the MPU. This is to ensure quick enough wakeup + * from idle, when transfer completes. + */ +#ifdef CONFIG_ARCH_OMAP34XX +static void omap_i2c_set_wfc_mpu_wkup_lat(struct device *dev, int set) +{ +omap_pm_set_max_mpu_wakeup_lat(dev, set ? 500 : -1); +} +#else +static inline void omap_i2c_set_wfc_mpu_wkup_lat(struct device *dev, int set) +{; } +#endif + static void __init omap_i2c_mux_pins(int bus) { int scl, sda; @@ -180,8 +201,8 @@ static int __init omap_i2c_bus_setup(char *str) get_options(str, 3, ints); if (ints[0] 2 || ints[1] 1 || ints[1] ports) return 0; -i2c_rate[ints[1] - 1] = ints[2]; -i2c_rate[ints[1] - 1] |= OMAP_I2C_CMDLINE_SETUP; +i2c_pdata[ints[1] - 1].clkrate = ints[2]; +i2c_pdata[ints[1] - 1].clkrate |= OMAP_I2C_CMDLINE_SETUP; return 1; } @@ -195,9 +216,11 @@ static int __init
[PATCH V3] OMAP: I2C: Add mpu wake up latency constraint in i2c
While waiting for completion of the i2c transfer, the MPU could hit OFF mode and cause several msecs of delay that made i2c transfers fail more often. The extra delays and subsequent re-trys cause i2c clocks to be active more often. This has also an negative effect on power consumption. Added a constraint that allows MPU to wake up in few hundred usecs, which is roughly the average i2c wait period. The constraint function is passed as platform data from plat-omap/i2c.c. Currently there is implementation for omap3 constraint. Future omap platforms should implement their own functions, and pass them instead. Signed-off-by: Kalle Jokiniemi kalle.jokini...@digia.com --- arch/arm/plat-omap/i2c.c | 54 +++- drivers/i2c/busses/i2c-omap.c | 19 +++--- include/linux/i2c-omap.h |9 +++ 3 files changed, 66 insertions(+), 16 deletions(-) create mode 100644 include/linux/i2c-omap.h diff --git a/arch/arm/plat-omap/i2c.c b/arch/arm/plat-omap/i2c.c index 8b84839..e923db5 100644 --- a/arch/arm/plat-omap/i2c.c +++ b/arch/arm/plat-omap/i2c.c @@ -26,8 +26,10 @@ #include linux/kernel.h #include linux/platform_device.h #include linux/i2c.h +#include linux/i2c-omap.h #include mach/irqs.h #include mach/mux.h +#include mach/omap-pm.h #define OMAP_I2C_SIZE 0x3f #define OMAP1_I2C_BASE 0xfffb3800 @@ -69,14 +71,14 @@ static struct resource i2c_resources[][2] = { }, \ } -static u32 i2c_rate[ARRAY_SIZE(i2c_resources)]; +static struct omap_i2c_bus_platform_data i2c_pdata[ARRAY_SIZE(i2c_resources)]; static struct platform_device omap_i2c_devices[] = { - I2C_DEV_BUILDER(1, i2c_resources[0], i2c_rate[0]), + I2C_DEV_BUILDER(1, i2c_resources[0], i2c_pdata[0]), #ifdefined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) - I2C_DEV_BUILDER(2, i2c_resources[1], i2c_rate[1]), + I2C_DEV_BUILDER(2, i2c_resources[1], i2c_pdata[1]), #endif #ifdefined(CONFIG_ARCH_OMAP34XX) - I2C_DEV_BUILDER(3, i2c_resources[2], i2c_rate[2]), + I2C_DEV_BUILDER(3, i2c_resources[2], i2c_pdata[2]), #endif }; @@ -100,6 +102,31 @@ static const int omap34xx_pins[][2] = {}; #define OMAP_I2C_CMDLINE_SETUP (BIT(31)) +/** + * omap3_i2c_set_wfc_mpu_wkup_lat - sets mpu wake up constraint + * @dev: i2c bus device pointer + * @set: set or clear constraints + * + * When waiting for completion of a i2c transfer, we need to set a wake up + * latency constraint for the MPU. This is to ensure quick enough wakeup from + * idle, when transfer completes. For OMAP3 platform. + */ +#ifdef CONFIG_ARCH_OMAP34XX +static void omap3_i2c_set_wfc_mpu_wkup_lat(struct device *dev, int set) +{ + omap_pm_set_max_mpu_wakeup_lat(dev, set ? 400 : -1); +} +#endif + +static void __init omap_set_i2c_constraint_func( + struct omap_i2c_bus_platform_data *pd) +{ + if (cpu_is_omap34xx()) + pd-set_mpu_wkup_lat = omap3_i2c_set_wfc_mpu_wkup_lat; + else + pd-set_mpu_wkup_lat = NULL; +} + static void __init omap_i2c_mux_pins(int bus) { int scl, sda; @@ -180,8 +207,8 @@ static int __init omap_i2c_bus_setup(char *str) get_options(str, 3, ints); if (ints[0] 2 || ints[1] 1 || ints[1] ports) return 0; - i2c_rate[ints[1] - 1] = ints[2]; - i2c_rate[ints[1] - 1] |= OMAP_I2C_CMDLINE_SETUP; + i2c_pdata[ints[1] - 1].clkrate = ints[2]; + i2c_pdata[ints[1] - 1].clkrate |= OMAP_I2C_CMDLINE_SETUP; return 1; } @@ -195,9 +222,10 @@ static int __init omap_register_i2c_bus_cmdline(void) { int i, err = 0; - for (i = 0; i ARRAY_SIZE(i2c_rate); i++) - if (i2c_rate[i] OMAP_I2C_CMDLINE_SETUP) { - i2c_rate[i] = ~OMAP_I2C_CMDLINE_SETUP; + for (i = 0; i ARRAY_SIZE(i2c_pdata); i++) + if (i2c_pdata[i].clkrate OMAP_I2C_CMDLINE_SETUP) { + i2c_pdata[i].clkrate = ~OMAP_I2C_CMDLINE_SETUP; + omap_set_i2c_constraint_func(i2c_pdata[i]); err = omap_i2c_add_bus(i + 1); if (err) goto out; @@ -231,9 +259,11 @@ int __init omap_register_i2c_bus(int bus_id, u32 clkrate, return err; } - if (!i2c_rate[bus_id - 1]) - i2c_rate[bus_id - 1] = clkrate; - i2c_rate[bus_id - 1] = ~OMAP_I2C_CMDLINE_SETUP; + if (!i2c_pdata[bus_id - 1].clkrate) + i2c_pdata[bus_id - 1].clkrate = clkrate; + + omap_set_i2c_constraint_func(i2c_pdata[bus_id - 1]); + i2c_pdata[bus_id - 1].clkrate = ~OMAP_I2C_CMDLINE_SETUP; return omap_i2c_add_bus(bus_id); } diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index 75bf3ad..168623f 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c
Re: [PATCH 1/1] OMAP: I2C: Add mpu wake up latency constraint in i2c
On Thu, 2009-10-01 at 14:41 +0300, Aaro Koskinen wrote: Hello, Kalle Jokiniemi wrote: On Wed, 2009-09-30 at 19:36 +0300, Kevin Hilman wrote: Seems like the latency value should also be (optionally) passed in pdata so this can be experimented with per-platform. Well, it kind of is already, since we pass the function that sets the latency from platform code. And that function has the latency hard-coded. Paul Walmsley suggested earlier that the latency value should be calculated from bus specific parameters: http://www.mail-archive.com/linux-omap@vger.kernel.org/msg12358.html Yes, this is a good idea in theory, but the reality of wake-up latencies kind-a kill this one. Wake-up from even C1 (MPU INA, CORE ON) takes ~130us on fastest OPP. And when you add 70us of sleep transition into that, you get 200us at minimum. So what it would require to actually get latencies that Paul calculated, is a new C-state that bypasses the idle loop completely. This would essentially keep cpu in busy loop while waiting for interrupt (or i2c completion in this case). In pm-sense, it seems unwise. For us, the 500us constraint seems to work quite nicely. It removes the problems we had with i2c transfers timing out with off mode, and restores average transfer times (from clk_enable to clk_disable) to few hundred us (that were observed with retention). But it's open software, people are free to experiment :) - Kalle A. -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] OMAP: I2C: Add mpu wake up latency constraint in i2c
While waiting for completion of the i2c transfer, the MPU could hit OFF mode and cause several msecs of delay that made i2c transfers fail more often. The extra delays and subsequent re-trys cause i2c clocks to be active more often. This has also an negative effect on power consumption. Added a constraint that allows MPU to wake up in few hundred usecs, which is roughly the average i2c wait period. The constraint function is passed as platform data from plat-omap/i2c.c. Currently there is implementation for omap3 constraint. Future omap platforms should implement their own functions, and pass them instead. Signed-off-by: Kalle Jokiniemi kalle.jokini...@digia.com --- arch/arm/plat-omap/i2c.c | 54 +++- drivers/i2c/busses/i2c-omap.c | 19 +++--- include/linux/i2c-omap.h |9 +++ 3 files changed, 66 insertions(+), 16 deletions(-) create mode 100644 include/linux/i2c-omap.h diff --git a/arch/arm/plat-omap/i2c.c b/arch/arm/plat-omap/i2c.c index 8b84839..4ab7a92 100644 --- a/arch/arm/plat-omap/i2c.c +++ b/arch/arm/plat-omap/i2c.c @@ -26,8 +26,10 @@ #include linux/kernel.h #include linux/platform_device.h #include linux/i2c.h +#include linux/i2c-omap.h #include mach/irqs.h #include mach/mux.h +#include mach/omap-pm.h #define OMAP_I2C_SIZE 0x3f #define OMAP1_I2C_BASE 0xfffb3800 @@ -69,14 +71,14 @@ static struct resource i2c_resources[][2] = { }, \ } -static u32 i2c_rate[ARRAY_SIZE(i2c_resources)]; +static struct omap_i2c_bus_platform_data i2c_pdata[ARRAY_SIZE(i2c_resources)]; static struct platform_device omap_i2c_devices[] = { - I2C_DEV_BUILDER(1, i2c_resources[0], i2c_rate[0]), + I2C_DEV_BUILDER(1, i2c_resources[0], i2c_pdata[0]), #ifdefined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) - I2C_DEV_BUILDER(2, i2c_resources[1], i2c_rate[1]), + I2C_DEV_BUILDER(2, i2c_resources[1], i2c_pdata[1]), #endif #ifdefined(CONFIG_ARCH_OMAP34XX) - I2C_DEV_BUILDER(3, i2c_resources[2], i2c_rate[2]), + I2C_DEV_BUILDER(3, i2c_resources[2], i2c_pdata[2]), #endif }; @@ -100,6 +102,31 @@ static const int omap34xx_pins[][2] = {}; #define OMAP_I2C_CMDLINE_SETUP (BIT(31)) +/** + * omap3_i2c_set_wfc_mpu_wkup_lat - sets mpu wake up constraint + * @dev: i2c bus device pointer + * @set: set or clear constraints + * + * When waiting for completion of a i2c transfer, we need to set a wake up + * latency constraint for the MPU. This is to ensure quick enough wakeup from + * idle, when transfer completes. For OMAP3 platform. + */ +#ifdef CONFIG_ARCH_OMAP34XX +static void omap3_i2c_set_wfc_mpu_wkup_lat(struct device *dev, int set) +{ + omap_pm_set_max_mpu_wakeup_lat(dev, set ? 500 : -1); +} +#endif + +static void __init omap_set_i2c_constraint_func( + struct omap_i2c_bus_platform_data *pd) +{ + if (cpu_is_omap34xx()) + pd-set_mpu_wkup_lat = omap3_i2c_set_wfc_mpu_wkup_lat; + else + pd-set_mpu_wkup_lat = NULL; +} + static void __init omap_i2c_mux_pins(int bus) { int scl, sda; @@ -180,8 +207,8 @@ static int __init omap_i2c_bus_setup(char *str) get_options(str, 3, ints); if (ints[0] 2 || ints[1] 1 || ints[1] ports) return 0; - i2c_rate[ints[1] - 1] = ints[2]; - i2c_rate[ints[1] - 1] |= OMAP_I2C_CMDLINE_SETUP; + i2c_pdata[ints[1] - 1].clkrate = ints[2]; + i2c_pdata[ints[1] - 1].clkrate |= OMAP_I2C_CMDLINE_SETUP; return 1; } @@ -195,9 +222,10 @@ static int __init omap_register_i2c_bus_cmdline(void) { int i, err = 0; - for (i = 0; i ARRAY_SIZE(i2c_rate); i++) - if (i2c_rate[i] OMAP_I2C_CMDLINE_SETUP) { - i2c_rate[i] = ~OMAP_I2C_CMDLINE_SETUP; + for (i = 0; i ARRAY_SIZE(i2c_pdata); i++) + if (i2c_pdata[i].clkrate OMAP_I2C_CMDLINE_SETUP) { + i2c_pdata[i].clkrate = ~OMAP_I2C_CMDLINE_SETUP; + omap_set_i2c_constraint_func(i2c_pdata[i]); err = omap_i2c_add_bus(i + 1); if (err) goto out; @@ -231,9 +259,11 @@ int __init omap_register_i2c_bus(int bus_id, u32 clkrate, return err; } - if (!i2c_rate[bus_id - 1]) - i2c_rate[bus_id - 1] = clkrate; - i2c_rate[bus_id - 1] = ~OMAP_I2C_CMDLINE_SETUP; + if (!i2c_pdata[bus_id - 1].clkrate) + i2c_pdata[bus_id - 1].clkrate = clkrate; + + omap_set_i2c_constraint_func(i2c_pdata[bus_id - 1]); + i2c_pdata[bus_id - 1].clkrate = ~OMAP_I2C_CMDLINE_SETUP; return omap_i2c_add_bus(bus_id); } diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index 75bf3ad..168623f 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c
Re: [PATCH] OMAP: I2C: Add mpu wake up latency constraint in i2c
On Fri, 2009-10-02 at 16:11 +0300, Jokiniemi Kalle wrote: While waiting for completion of the i2c transfer, the MPU could hit OFF mode and cause several msecs of delay that made i2c transfers fail more often. The extra delays and subsequent re-trys cause i2c clocks to be active more often. This has also an negative effect on power consumption. Added a constraint that allows MPU to wake up in few hundred usecs, which is roughly the average i2c wait period. The constraint function is passed as platform data from plat-omap/i2c.c. Currently there is implementation for omap3 constraint. Future omap platforms should implement their own functions, and pass them instead. So this is the new version of setting mpu wakeup constraints in i2c driver. Only build tested. Kevin, could you run some tests on beagle or some other. I could not get my zImage to work on RX-51 (tried rx51_defconfig and omap3_pm_defconfig builds). Applies on top of pm-branch. - Kalle Signed-off-by: Kalle Jokiniemi kalle.jokini...@digia.com --- arch/arm/plat-omap/i2c.c | 54 +++- drivers/i2c/busses/i2c-omap.c | 19 +++--- include/linux/i2c-omap.h |9 +++ 3 files changed, 66 insertions(+), 16 deletions(-) create mode 100644 include/linux/i2c-omap.h diff --git a/arch/arm/plat-omap/i2c.c b/arch/arm/plat-omap/i2c.c index 8b84839..4ab7a92 100644 --- a/arch/arm/plat-omap/i2c.c +++ b/arch/arm/plat-omap/i2c.c @@ -26,8 +26,10 @@ #include linux/kernel.h #include linux/platform_device.h #include linux/i2c.h +#include linux/i2c-omap.h #include mach/irqs.h #include mach/mux.h +#include mach/omap-pm.h #define OMAP_I2C_SIZE0x3f #define OMAP1_I2C_BASE 0xfffb3800 @@ -69,14 +71,14 @@ static struct resource i2c_resources[][2] = { }, \ } -static u32 i2c_rate[ARRAY_SIZE(i2c_resources)]; +static struct omap_i2c_bus_platform_data i2c_pdata[ARRAY_SIZE(i2c_resources)]; static struct platform_device omap_i2c_devices[] = { - I2C_DEV_BUILDER(1, i2c_resources[0], i2c_rate[0]), + I2C_DEV_BUILDER(1, i2c_resources[0], i2c_pdata[0]), #if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) - I2C_DEV_BUILDER(2, i2c_resources[1], i2c_rate[1]), + I2C_DEV_BUILDER(2, i2c_resources[1], i2c_pdata[1]), #endif #if defined(CONFIG_ARCH_OMAP34XX) - I2C_DEV_BUILDER(3, i2c_resources[2], i2c_rate[2]), + I2C_DEV_BUILDER(3, i2c_resources[2], i2c_pdata[2]), #endif }; @@ -100,6 +102,31 @@ static const int omap34xx_pins[][2] = {}; #define OMAP_I2C_CMDLINE_SETUP (BIT(31)) +/** + * omap3_i2c_set_wfc_mpu_wkup_lat - sets mpu wake up constraint + * @dev: i2c bus device pointer + * @set: set or clear constraints + * + * When waiting for completion of a i2c transfer, we need to set a wake up + * latency constraint for the MPU. This is to ensure quick enough wakeup from + * idle, when transfer completes. For OMAP3 platform. + */ +#ifdef CONFIG_ARCH_OMAP34XX +static void omap3_i2c_set_wfc_mpu_wkup_lat(struct device *dev, int set) +{ + omap_pm_set_max_mpu_wakeup_lat(dev, set ? 500 : -1); +} +#endif + +static void __init omap_set_i2c_constraint_func( + struct omap_i2c_bus_platform_data *pd) +{ + if (cpu_is_omap34xx()) + pd-set_mpu_wkup_lat = omap3_i2c_set_wfc_mpu_wkup_lat; + else + pd-set_mpu_wkup_lat = NULL; +} + static void __init omap_i2c_mux_pins(int bus) { int scl, sda; @@ -180,8 +207,8 @@ static int __init omap_i2c_bus_setup(char *str) get_options(str, 3, ints); if (ints[0] 2 || ints[1] 1 || ints[1] ports) return 0; - i2c_rate[ints[1] - 1] = ints[2]; - i2c_rate[ints[1] - 1] |= OMAP_I2C_CMDLINE_SETUP; + i2c_pdata[ints[1] - 1].clkrate = ints[2]; + i2c_pdata[ints[1] - 1].clkrate |= OMAP_I2C_CMDLINE_SETUP; return 1; } @@ -195,9 +222,10 @@ static int __init omap_register_i2c_bus_cmdline(void) { int i, err = 0; - for (i = 0; i ARRAY_SIZE(i2c_rate); i++) - if (i2c_rate[i] OMAP_I2C_CMDLINE_SETUP) { - i2c_rate[i] = ~OMAP_I2C_CMDLINE_SETUP; + for (i = 0; i ARRAY_SIZE(i2c_pdata); i++) + if (i2c_pdata[i].clkrate OMAP_I2C_CMDLINE_SETUP) { + i2c_pdata[i].clkrate = ~OMAP_I2C_CMDLINE_SETUP; + omap_set_i2c_constraint_func(i2c_pdata[i]); err = omap_i2c_add_bus(i + 1); if (err) goto out; @@ -231,9 +259,11 @@ int __init omap_register_i2c_bus(int bus_id, u32 clkrate, return err; } - if (!i2c_rate[bus_id - 1]) - i2c_rate[bus_id - 1] = clkrate; - i2c_rate[bus_id - 1] = ~OMAP_I2C_CMDLINE_SETUP; + if (!i2c_pdata[bus_id
Re: [PATCH 1/1] OMAP: I2C: Add mpu wake up latency constraint in i2c
On Thu, 2009-10-01 at 09:10 +0300, Jarkko Nikula wrote: Hi Kalle Few minor comments below. On Thu, 17 Sep 2009 19:28:43 +0300 Kalle Jokiniemi kalle.jokini...@digia.com wrote: -static u32 i2c_rate[ARRAY_SIZE(i2c_resources)]; +static struct omap_i2c_bus_platform_data i2c_pdata[ARRAY_SIZE(i2c_resources)]; static struct platform_device omap_i2c_devices[] = { - I2C_DEV_BUILDER(1, i2c_resources[0], i2c_rate[0]), + I2C_DEV_BUILDER(1, i2c_resources[0], i2c_pdata[0]), #ifdefined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) - I2C_DEV_BUILDER(2, i2c_resources[1], i2c_rate[1]), + I2C_DEV_BUILDER(2, i2c_resources[1], i2c_pdata[1]), #endif #ifdefined(CONFIG_ARCH_OMAP34XX) - I2C_DEV_BUILDER(3, i2c_resources[2], i2c_rate[2]), + I2C_DEV_BUILDER(3, i2c_resources[2], i2c_pdata[2]), #endif }; This is good idea. IRCC, e.g. the I2C_SCL t_high and t_low timing values can be board dependent values so passing just the i2c_rate as a platform_data seems to be not enough in the future. I gather that this t_high/t_low passing change can be added later ;) @@ -526,8 +529,10 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap, * REVISIT: We should abort the transfer on signals, but the bus goes * into arbitration and we're currently unable to recover from it. */ + dev-set_mpu_wkup_lat(dev-dev, 1); r = wait_for_completion_timeout(dev-cmd_complete, OMAP_I2C_TIMEOUT); + dev-set_mpu_wkup_lat(dev-dev, 0); These lines here and lines below in omap_i2c_probe looks suspicious. I would rather allow callback to be NULL (and then you would not need empty function in arch/arm/plat-omap/i2c.c) and just test it here before executing. Looks much more safe code then. Yes, this needs to be fixed. Otherwise we could get null pointer calls. Nice catch. - Kalle + if (pdata != NULL) { + speed = pdata-clkrate; + dev-set_mpu_wkup_lat = pdata-set_mpu_wkup_lat; + } else { + speed = 100;/* Default speed */ + dev-set_mpu_wkup_lat = NULL; + } -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 0/1] OMAP: I2C: Add mpu wake up latency constraint
Sending this patch that fixes a problem where I2C transfers get stalled because MPU can hit off mode while i2c is waiting for transfer completion. There are some changes on how clkrate is passed to i2c-omap bus driver, as I needed to pass also the constraint setting function. So review comments are most welcome. Applies on top of pm-branch. Just build tested for omap3_pm_defconfig. Could not get linux-omap to boot on my rx-51, so it's only tested with our internal tree. - Kalle -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 1/1] OMAP: I2C: Add mpu wake up latency constraint in i2c
While waiting for completion of the i2c transfer, the MPU could hit OFF mode and cause several msecs of delay that made i2c transfers fail more often. The extra delays and subsequent re-trys cause i2c clocks to be active more often. This has also an negative effect on power consumption. Added a constraint that allows MPU to wake up in few hundred usecs, which is roughly the average i2c wait period. The constraint function is passed as platform data from plat-omap/i2c.c and applied only on OMAP34XX devices. Signed-off-by: Kalle Jokiniemi kalle.jokini...@digia.com --- arch/arm/plat-omap/i2c.c | 49 +++-- drivers/i2c/busses/i2c-omap.c | 17 +++--- include/linux/i2c-omap.h |9 +++ 3 files changed, 59 insertions(+), 16 deletions(-) create mode 100644 include/linux/i2c-omap.h diff --git a/arch/arm/plat-omap/i2c.c b/arch/arm/plat-omap/i2c.c index 8b84839..d43d0ad 100644 --- a/arch/arm/plat-omap/i2c.c +++ b/arch/arm/plat-omap/i2c.c @@ -26,8 +26,10 @@ #include linux/kernel.h #include linux/platform_device.h #include linux/i2c.h +#include linux/i2c-omap.h #include mach/irqs.h #include mach/mux.h +#include mach/omap-pm.h #define OMAP_I2C_SIZE 0x3f #define OMAP1_I2C_BASE 0xfffb3800 @@ -69,14 +71,14 @@ static struct resource i2c_resources[][2] = { }, \ } -static u32 i2c_rate[ARRAY_SIZE(i2c_resources)]; +static struct omap_i2c_bus_platform_data i2c_pdata[ARRAY_SIZE(i2c_resources)]; static struct platform_device omap_i2c_devices[] = { - I2C_DEV_BUILDER(1, i2c_resources[0], i2c_rate[0]), + I2C_DEV_BUILDER(1, i2c_resources[0], i2c_pdata[0]), #ifdefined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) - I2C_DEV_BUILDER(2, i2c_resources[1], i2c_rate[1]), + I2C_DEV_BUILDER(2, i2c_resources[1], i2c_pdata[1]), #endif #ifdefined(CONFIG_ARCH_OMAP34XX) - I2C_DEV_BUILDER(3, i2c_resources[2], i2c_rate[2]), + I2C_DEV_BUILDER(3, i2c_resources[2], i2c_pdata[2]), #endif }; @@ -100,6 +102,25 @@ static const int omap34xx_pins[][2] = {}; #define OMAP_I2C_CMDLINE_SETUP (BIT(31)) +/** + * omap_i2c_set_wfc_mpu_wkup_lat - sets mpu wake up constraint + * @dev: i2c bus device pointer + * @set: set or clear constraints + * + * When waiting for completion of a i2c transfer, we need to set a wake up + * latency constraint for the MPU. This is to ensure quick enough wakeup + * from idle, when transfer completes. + */ +#ifdef CONFIG_ARCH_OMAP34XX +static void omap_i2c_set_wfc_mpu_wkup_lat(struct device *dev, int set) +{ + omap_pm_set_max_mpu_wakeup_lat(dev, set ? 500 : -1); +} +#else +static inline void omap_i2c_set_wfc_mpu_wkup_lat(struct device *dev, int set) +{; } +#endif + static void __init omap_i2c_mux_pins(int bus) { int scl, sda; @@ -180,8 +201,8 @@ static int __init omap_i2c_bus_setup(char *str) get_options(str, 3, ints); if (ints[0] 2 || ints[1] 1 || ints[1] ports) return 0; - i2c_rate[ints[1] - 1] = ints[2]; - i2c_rate[ints[1] - 1] |= OMAP_I2C_CMDLINE_SETUP; + i2c_pdata[ints[1] - 1].clkrate = ints[2]; + i2c_pdata[ints[1] - 1].clkrate |= OMAP_I2C_CMDLINE_SETUP; return 1; } @@ -195,9 +216,11 @@ static int __init omap_register_i2c_bus_cmdline(void) { int i, err = 0; - for (i = 0; i ARRAY_SIZE(i2c_rate); i++) - if (i2c_rate[i] OMAP_I2C_CMDLINE_SETUP) { - i2c_rate[i] = ~OMAP_I2C_CMDLINE_SETUP; + for (i = 0; i ARRAY_SIZE(i2c_pdata); i++) + if (i2c_pdata[i].clkrate OMAP_I2C_CMDLINE_SETUP) { + i2c_pdata[i].clkrate = ~OMAP_I2C_CMDLINE_SETUP; + i2c_pdata[i].set_mpu_wkup_lat = + omap_i2c_set_wfc_mpu_wkup_lat; err = omap_i2c_add_bus(i + 1); if (err) goto out; @@ -231,9 +254,11 @@ int __init omap_register_i2c_bus(int bus_id, u32 clkrate, return err; } - if (!i2c_rate[bus_id - 1]) - i2c_rate[bus_id - 1] = clkrate; - i2c_rate[bus_id - 1] = ~OMAP_I2C_CMDLINE_SETUP; + if (!i2c_pdata[bus_id - 1].clkrate) + i2c_pdata[bus_id - 1].clkrate = clkrate; + + i2c_pdata[bus_id - 1].set_mpu_wkup_lat = omap_i2c_set_wfc_mpu_wkup_lat; + i2c_pdata[bus_id - 1].clkrate = ~OMAP_I2C_CMDLINE_SETUP; return omap_i2c_add_bus(bus_id); } diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index 75bf3ad..da6d276 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -37,6 +37,7 @@ #include linux/platform_device.h #include linux/clk.h #include linux/io.h +#include linux/i2c-omap.h /* I2C controller revisions */ #define OMAP_I2C_REV_2 0x20 @@ -165,6
[PATCH] OMAP: Fix race condition with autodeps
There is a possible race condition in clockdomain code handling hw supported idle transitions. When multiple autodeps dependencies are being added or removed, a transition of still remaining dependent powerdomain can result in false readings of the state counter. This is especially fatal for off mode state counter, as it could result in a driver not noticing a context loss. Fixed by disabling hw supported state transitions when autodeps are being changed. Signed-off-by: Kalle Jokiniemi kalle.jokini...@digia.com --- arch/arm/mach-omap2/clockdomain.c | 74 ++--- 1 files changed, 44 insertions(+), 30 deletions(-) diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c index 4ef7b4f..1a8c386 100644 --- a/arch/arm/mach-omap2/clockdomain.c +++ b/arch/arm/mach-omap2/clockdomain.c @@ -137,6 +137,36 @@ static void _clkdm_del_autodeps(struct clockdomain *clkdm) } } +/* + * _omap2_clkdm_set_hwsup - set high the hwsup idle transition bit + * @clkdm: struct clockdomain * + * @enable: int 0 to disable, 1 to enable + * + * Internal helper for actually switching the bit that controls hwsup + * idle transitions for clkdm. + */ +void _omap2_clkdm_set_hwsup(struct clockdomain *clkdm, int enable) +{ + u32 v; + + if (cpu_is_omap24xx()) { + if (enable) + v = OMAP24XX_CLKSTCTRL_ENABLE_AUTO; + else + v = OMAP24XX_CLKSTCTRL_DISABLE_AUTO; + } else if (cpu_is_omap34xx()) { + if (enable) + v = OMAP34XX_CLKSTCTRL_ENABLE_AUTO; + else + v = OMAP34XX_CLKSTCTRL_DISABLE_AUTO; + } else { + BUG(); + } + + cm_rmw_mod_reg_bits(clkdm-clktrctrl_mask, + v __ffs(clkdm-clktrctrl_mask), + clkdm-pwrdm.ptr-prcm_offs, CM_CLKSTCTRL); +} static struct clockdomain *_clkdm_lookup(const char *name) { @@ -456,8 +486,6 @@ int omap2_clkdm_wakeup(struct clockdomain *clkdm) */ void omap2_clkdm_allow_idle(struct clockdomain *clkdm) { - u32 v; - if (!clkdm) return; @@ -473,18 +501,7 @@ void omap2_clkdm_allow_idle(struct clockdomain *clkdm) if (atomic_read(clkdm-usecount) 0) _clkdm_add_autodeps(clkdm); - if (cpu_is_omap24xx()) - v = OMAP24XX_CLKSTCTRL_ENABLE_AUTO; - else if (cpu_is_omap34xx()) - v = OMAP34XX_CLKSTCTRL_ENABLE_AUTO; - else - BUG(); - - - cm_rmw_mod_reg_bits(clkdm-clktrctrl_mask, - v __ffs(clkdm-clktrctrl_mask), - clkdm-pwrdm.ptr-prcm_offs, - CM_CLKSTCTRL); + _omap2_clkdm_set_hwsup(clkdm, 1); pwrdm_clkdm_state_switch(clkdm); } @@ -500,8 +517,6 @@ void omap2_clkdm_allow_idle(struct clockdomain *clkdm) */ void omap2_clkdm_deny_idle(struct clockdomain *clkdm) { - u32 v; - if (!clkdm) return; @@ -514,16 +529,7 @@ void omap2_clkdm_deny_idle(struct clockdomain *clkdm) pr_debug(clockdomain: disabling automatic idle transitions for %s\n, clkdm-name); - if (cpu_is_omap24xx()) - v = OMAP24XX_CLKSTCTRL_DISABLE_AUTO; - else if (cpu_is_omap34xx()) - v = OMAP34XX_CLKSTCTRL_DISABLE_AUTO; - else - BUG(); - - cm_rmw_mod_reg_bits(clkdm-clktrctrl_mask, - v __ffs(clkdm-clktrctrl_mask), - clkdm-pwrdm.ptr-prcm_offs, CM_CLKSTCTRL); + _omap2_clkdm_set_hwsup(clkdm, 0); if (atomic_read(clkdm-usecount) 0) _clkdm_del_autodeps(clkdm); @@ -569,10 +575,14 @@ int omap2_clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk) v = omap2_clkdm_clktrctrl_read(clkdm); if ((cpu_is_omap34xx() v == OMAP34XX_CLKSTCTRL_ENABLE_AUTO) || - (cpu_is_omap24xx() v == OMAP24XX_CLKSTCTRL_ENABLE_AUTO)) + (cpu_is_omap24xx() v == OMAP24XX_CLKSTCTRL_ENABLE_AUTO)) { + /* Disable HW transitions when we are changing deps */ + _omap2_clkdm_set_hwsup(clkdm, 0); _clkdm_add_autodeps(clkdm); - else + _omap2_clkdm_set_hwsup(clkdm, 1); + } else { omap2_clkdm_wakeup(clkdm); + } pwrdm_wait_transition(clkdm-pwrdm.ptr); pwrdm_clkdm_state_switch(clkdm); @@ -623,10 +633,14 @@ int omap2_clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk) v = omap2_clkdm_clktrctrl_read(clkdm); if ((cpu_is_omap34xx() v == OMAP34XX_CLKSTCTRL_ENABLE_AUTO) || - (cpu_is_omap24xx() v == OMAP24XX_CLKSTCTRL_ENABLE_AUTO)) + (cpu_is_omap24xx() v == OMAP24XX_CLKSTCTRL_ENABLE_AUTO)) { + /* Disable HW transitions when we are changing deps */ + _omap2_clkdm_set_hwsup
Re: [PATCH] OMAP: Fix race condition with autodeps
On Wed, 2009-09-16 at 15:07 +0300, Tommi Rantala wrote: 2009/9/16 Kalle Jokiniemi kalle.jokini...@digia.com: There is a possible race condition in clockdomain code handling hw supported idle transitions. When multiple autodeps dependencies are being added or removed, a transition of still remaining dependent powerdomain can result in false readings of the state counter. This is especially fatal for off mode state counter, as it could result in a driver not noticing a context loss. Fixed by disabling hw supported state transitions when autodeps are being changed. Signed-off-by: Kalle Jokiniemi kalle.jokini...@digia.com --- arch/arm/mach-omap2/clockdomain.c | 74 ++--- 1 files changed, 44 insertions(+), 30 deletions(-) diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c index 4ef7b4f..1a8c386 100644 --- a/arch/arm/mach-omap2/clockdomain.c +++ b/arch/arm/mach-omap2/clockdomain.c @@ -137,6 +137,36 @@ static void _clkdm_del_autodeps(struct clockdomain *clkdm) } } +/* + * _omap2_clkdm_set_hwsup - set high the hwsup idle transition bit + * @clkdm: struct clockdomain * + * @enable: int 0 to disable, 1 to enable + * + * Internal helper for actually switching the bit that controls hwsup + * idle transitions for clkdm. + */ static missing here. Oops, good catch. I'll repost. - Kalle +void _omap2_clkdm_set_hwsup(struct clockdomain *clkdm, int enable) +{ + u32 v; + + if (cpu_is_omap24xx()) { + if (enable) + v = OMAP24XX_CLKSTCTRL_ENABLE_AUTO; + else + v = OMAP24XX_CLKSTCTRL_DISABLE_AUTO; + } else if (cpu_is_omap34xx()) { + if (enable) + v = OMAP34XX_CLKSTCTRL_ENABLE_AUTO; + else + v = OMAP34XX_CLKSTCTRL_DISABLE_AUTO; + } else { + BUG(); + } + + cm_rmw_mod_reg_bits(clkdm-clktrctrl_mask, + v __ffs(clkdm-clktrctrl_mask), + clkdm-pwrdm.ptr-prcm_offs, CM_CLKSTCTRL); +} static struct clockdomain *_clkdm_lookup(const char *name) { [...] Regards, Tommi Rantala -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH V2] OMAP: Fix race condition with autodeps
There is a possible race condition in clockdomain code handling hw supported idle transitions. When multiple autodeps dependencies are being added or removed, a transition of still remaining dependent powerdomain can result in false readings of the state counter. This is especially fatal for off mode state counter, as it could result in a driver not noticing a context loss. Fixed by disabling hw supported state transitions when autodeps are being changed. Signed-off-by: Kalle Jokiniemi kalle.jokini...@digia.com --- arch/arm/mach-omap2/clockdomain.c | 74 ++--- 1 files changed, 44 insertions(+), 30 deletions(-) diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c index 4ef7b4f..58aff84 100644 --- a/arch/arm/mach-omap2/clockdomain.c +++ b/arch/arm/mach-omap2/clockdomain.c @@ -137,6 +137,36 @@ static void _clkdm_del_autodeps(struct clockdomain *clkdm) } } +/* + * _omap2_clkdm_set_hwsup - set the hwsup idle transition bit + * @clkdm: struct clockdomain * + * @enable: int 0 to disable, 1 to enable + * + * Internal helper for actually switching the bit that controls hwsup + * idle transitions for clkdm. + */ +static void _omap2_clkdm_set_hwsup(struct clockdomain *clkdm, int enable) +{ + u32 v; + + if (cpu_is_omap24xx()) { + if (enable) + v = OMAP24XX_CLKSTCTRL_ENABLE_AUTO; + else + v = OMAP24XX_CLKSTCTRL_DISABLE_AUTO; + } else if (cpu_is_omap34xx()) { + if (enable) + v = OMAP34XX_CLKSTCTRL_ENABLE_AUTO; + else + v = OMAP34XX_CLKSTCTRL_DISABLE_AUTO; + } else { + BUG(); + } + + cm_rmw_mod_reg_bits(clkdm-clktrctrl_mask, + v __ffs(clkdm-clktrctrl_mask), + clkdm-pwrdm.ptr-prcm_offs, CM_CLKSTCTRL); +} static struct clockdomain *_clkdm_lookup(const char *name) { @@ -456,8 +486,6 @@ int omap2_clkdm_wakeup(struct clockdomain *clkdm) */ void omap2_clkdm_allow_idle(struct clockdomain *clkdm) { - u32 v; - if (!clkdm) return; @@ -473,18 +501,7 @@ void omap2_clkdm_allow_idle(struct clockdomain *clkdm) if (atomic_read(clkdm-usecount) 0) _clkdm_add_autodeps(clkdm); - if (cpu_is_omap24xx()) - v = OMAP24XX_CLKSTCTRL_ENABLE_AUTO; - else if (cpu_is_omap34xx()) - v = OMAP34XX_CLKSTCTRL_ENABLE_AUTO; - else - BUG(); - - - cm_rmw_mod_reg_bits(clkdm-clktrctrl_mask, - v __ffs(clkdm-clktrctrl_mask), - clkdm-pwrdm.ptr-prcm_offs, - CM_CLKSTCTRL); + _omap2_clkdm_set_hwsup(clkdm, 1); pwrdm_clkdm_state_switch(clkdm); } @@ -500,8 +517,6 @@ void omap2_clkdm_allow_idle(struct clockdomain *clkdm) */ void omap2_clkdm_deny_idle(struct clockdomain *clkdm) { - u32 v; - if (!clkdm) return; @@ -514,16 +529,7 @@ void omap2_clkdm_deny_idle(struct clockdomain *clkdm) pr_debug(clockdomain: disabling automatic idle transitions for %s\n, clkdm-name); - if (cpu_is_omap24xx()) - v = OMAP24XX_CLKSTCTRL_DISABLE_AUTO; - else if (cpu_is_omap34xx()) - v = OMAP34XX_CLKSTCTRL_DISABLE_AUTO; - else - BUG(); - - cm_rmw_mod_reg_bits(clkdm-clktrctrl_mask, - v __ffs(clkdm-clktrctrl_mask), - clkdm-pwrdm.ptr-prcm_offs, CM_CLKSTCTRL); + _omap2_clkdm_set_hwsup(clkdm, 0); if (atomic_read(clkdm-usecount) 0) _clkdm_del_autodeps(clkdm); @@ -569,10 +575,14 @@ int omap2_clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk) v = omap2_clkdm_clktrctrl_read(clkdm); if ((cpu_is_omap34xx() v == OMAP34XX_CLKSTCTRL_ENABLE_AUTO) || - (cpu_is_omap24xx() v == OMAP24XX_CLKSTCTRL_ENABLE_AUTO)) + (cpu_is_omap24xx() v == OMAP24XX_CLKSTCTRL_ENABLE_AUTO)) { + /* Disable HW transitions when we are changing deps */ + _omap2_clkdm_set_hwsup(clkdm, 0); _clkdm_add_autodeps(clkdm); - else + _omap2_clkdm_set_hwsup(clkdm, 1); + } else { omap2_clkdm_wakeup(clkdm); + } pwrdm_wait_transition(clkdm-pwrdm.ptr); pwrdm_clkdm_state_switch(clkdm); @@ -623,10 +633,14 @@ int omap2_clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk) v = omap2_clkdm_clktrctrl_read(clkdm); if ((cpu_is_omap34xx() v == OMAP34XX_CLKSTCTRL_ENABLE_AUTO) || - (cpu_is_omap24xx() v == OMAP24XX_CLKSTCTRL_ENABLE_AUTO)) + (cpu_is_omap24xx() v == OMAP24XX_CLKSTCTRL_ENABLE_AUTO)) { + /* Disable HW transitions when we are changing deps
Re: [RFC][PATCH] OMAP3: PM: Fix workaround implementation for OMAP3 errata (1.142)
On Fri, 2009-08-07 at 01:14 +0300, Kevin Hilman wrote: Roger Quadros ext-roger.quad...@nokia.com writes: As per errata 1.142, on EMU/HS devices, SDRC_POWER should be programmed for automatic self-refresh before transition to OFF mode. In the current implementation this is done in omap3_scratchpad_contents() which is wrong, since this is the value that will be restored while resuming from OFF mode and not while transitioning to it. This patch implements the workaround in the correct way as per errata. Signed-off-by: Roger Quadros ext-roger.quad...@nokia.com This looks right to me. Rajendra, Kalle, any comments? since you were the originators of the original patch. Kevin --- arch/arm/mach-omap2/control.c | 16 ++-- arch/arm/mach-omap2/pm34xx.c | 20 ++-- 2 files changed, 16 insertions(+), 20 deletions(-) diff --git a/arch/arm/mach-omap2/control.c b/arch/arm/mach-omap2/control.c index a7159a9..0a563c8 100644 --- a/arch/arm/mach-omap2/control.c +++ b/arch/arm/mach-omap2/control.c @@ -272,20 +272,8 @@ void omap3_save_scratchpad_contents(void) (sdrc_read_reg(SDRC_ERR_TYPE) 0x); sdrc_block_contents.dll_a_ctrl = sdrc_read_reg(SDRC_DLLA_CTRL); sdrc_block_contents.dll_b_ctrl = 0x0; - /* -* Due to a OMAP3 errata (1.142), on EMU/HS devices SRDC should -* be programed to issue automatic self refresh on timeout -* of AUTO_CNT = 1 prior to any transition to OFF mode. -*/ - if ((omap_type() != OMAP2_DEVICE_TYPE_GP) -(omap_rev() = OMAP3430_REV_ES3_0)) - sdrc_block_contents.power = (sdrc_read_reg(SDRC_POWER) - ~(SDRC_POWER_AUTOCOUNT_MASK| - SDRC_POWER_CLKCTRL_MASK)) | - (1 SDRC_POWER_AUTOCOUNT_SHIFT) | - SDRC_SELF_REFRESH_ON_AUTOCOUNT; - else - sdrc_block_contents.power = sdrc_read_reg(SDRC_POWER); + + sdrc_block_contents.power = sdrc_read_reg(SDRC_POWER); Why do you want to remove the workaround from scratchpad? When we wake up from off mode, the boot ROM code writes these settings as the first sdrc_power settings after wakeup. If that setting does not include the workaround, we'll have a period of time where sdram is not being refreshed. This hits especially HS devices that do long secure context restore in ROM code as well. sdrc_block_contents.cs_0 = 0x0; sdrc_block_contents.mcfg_0 = sdrc_read_reg(SDRC_MCFG_0); diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c index 14f10bc..eb3c9e5 100644 --- a/arch/arm/mach-omap2/pm34xx.c +++ b/arch/arm/mach-omap2/pm34xx.c @@ -405,15 +405,23 @@ void omap_sram_idle(void) } /* - * On EMU/HS devices ROM code restores a SRDC value - * from scratchpad which has automatic self refresh on timeout - * of AUTO_CNT = 1 enabled. This takes care of errata 1.142. - * Hence store/restore the SDRC_POWER register here. - */ +* Due to a OMAP3 errata (1.142), on EMU/HS devices SRDC should +* be programed to issue automatic self refresh on timeout +* of AUTO_CNT = 1 prior to any transition to OFF mode. +*/ + if (omap_rev() = OMAP3430_REV_ES3_0 omap_type() != OMAP2_DEVICE_TYPE_GP - core_next_state == PWRDM_POWER_OFF) + core_next_state == PWRDM_POWER_OFF) { + sdrc_pwr = sdrc_read_reg(SDRC_POWER); + sdrc_write_reg((sdrc_pwr + ~(SDRC_POWER_AUTOCOUNT_MASK| + SDRC_POWER_CLKCTRL_MASK)) | + (1 SDRC_POWER_AUTOCOUNT_SHIFT) | + SDRC_SELF_REFRESH_ON_AUTOCOUNT, + SDRC_POWER); + } This part seems ok to me. - Kalle if (regset_save_on_suspend) pm_dbg_regset_save(1); -- 1.6.0.4 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC][PATCH] OMAP3: PM: Fix workaround implementation for OMAP3 errata (1.142)
On Fri, 2009-08-07 at 11:03 +0300, Roger Quadros wrote: ext Kalle Jokiniemi wrote: On Fri, 2009-08-07 at 01:14 +0300, Kevin Hilman wrote: Roger Quadros ext-roger.quad...@nokia.com writes: As per errata 1.142, on EMU/HS devices, SDRC_POWER should be programmed for automatic self-refresh before transition to OFF mode. In the current implementation this is done in omap3_scratchpad_contents() which is wrong, since this is the value that will be restored while resuming from OFF mode and not while transitioning to it. This patch implements the workaround in the correct way as per errata. Signed-off-by: Roger Quadros ext-roger.quad...@nokia.com This looks right to me. Rajendra, Kalle, any comments? since you were the originators of the original patch. Kevin --- arch/arm/mach-omap2/control.c | 16 ++-- arch/arm/mach-omap2/pm34xx.c | 20 ++-- 2 files changed, 16 insertions(+), 20 deletions(-) diff --git a/arch/arm/mach-omap2/control.c b/arch/arm/mach-omap2/control.c index a7159a9..0a563c8 100644 --- a/arch/arm/mach-omap2/control.c +++ b/arch/arm/mach-omap2/control.c @@ -272,20 +272,8 @@ void omap3_save_scratchpad_contents(void) (sdrc_read_reg(SDRC_ERR_TYPE) 0x); sdrc_block_contents.dll_a_ctrl = sdrc_read_reg(SDRC_DLLA_CTRL); sdrc_block_contents.dll_b_ctrl = 0x0; - /* - * Due to a OMAP3 errata (1.142), on EMU/HS devices SRDC should - * be programed to issue automatic self refresh on timeout - * of AUTO_CNT = 1 prior to any transition to OFF mode. - */ - if ((omap_type() != OMAP2_DEVICE_TYPE_GP) - (omap_rev() = OMAP3430_REV_ES3_0)) - sdrc_block_contents.power = (sdrc_read_reg(SDRC_POWER) - ~(SDRC_POWER_AUTOCOUNT_MASK| - SDRC_POWER_CLKCTRL_MASK)) | - (1 SDRC_POWER_AUTOCOUNT_SHIFT) | - SDRC_SELF_REFRESH_ON_AUTOCOUNT; - else - sdrc_block_contents.power = sdrc_read_reg(SDRC_POWER); + + sdrc_block_contents.power = sdrc_read_reg(SDRC_POWER); Why do you want to remove the workaround from scratchpad? When we wake up from off mode, the boot ROM code writes these settings as the first sdrc_power settings after wakeup. If that setting does not include the workaround, we'll have a period of time where sdram is not being refreshed. This hits especially HS devices that do long secure context restore in ROM code as well. I suppose SDRAM is always refreshed (i.e. auto refresh) when ON. However when we enter OFF mode it should be _self_ refreshed. That is done by the below code before we switch to OFF mode. The erratum speaks of auto-refresh failing after waking up from CORE off mode. I think there is the described workaround in place in sleep34xx.S code to kick up the auto refresh, but this still leaves a short gap between boot ROM and the sleep code. Unless the self-refresh mode does not get changed by the scratchpad settings? - Kalle When we wake up from OFF mode (the scratchpad contents are used), we should restore the original register setting that was there before we went to OFF mode and not the self refresh mode setting. Hence the removal of above code. -roger sdrc_block_contents.cs_0 = 0x0; sdrc_block_contents.mcfg_0 = sdrc_read_reg(SDRC_MCFG_0); diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c index 14f10bc..eb3c9e5 100644 --- a/arch/arm/mach-omap2/pm34xx.c +++ b/arch/arm/mach-omap2/pm34xx.c @@ -405,15 +405,23 @@ void omap_sram_idle(void) } /* - * On EMU/HS devices ROM code restores a SRDC value - * from scratchpad which has automatic self refresh on timeout - * of AUTO_CNT = 1 enabled. This takes care of errata 1.142. - * Hence store/restore the SDRC_POWER register here. - */ + * Due to a OMAP3 errata (1.142), on EMU/HS devices SRDC should + * be programed to issue automatic self refresh on timeout + * of AUTO_CNT = 1 prior to any transition to OFF mode. + */ + if (omap_rev() = OMAP3430_REV_ES3_0 omap_type() != OMAP2_DEVICE_TYPE_GP - core_next_state == PWRDM_POWER_OFF) + core_next_state == PWRDM_POWER_OFF) { + sdrc_pwr = sdrc_read_reg(SDRC_POWER); + sdrc_write_reg((sdrc_pwr + ~(SDRC_POWER_AUTOCOUNT_MASK| + SDRC_POWER_CLKCTRL_MASK)) | + (1 SDRC_POWER_AUTOCOUNT_SHIFT) | + SDRC_SELF_REFRESH_ON_AUTOCOUNT, + SDRC_POWER); + } This part seems ok to me. - Kalle if (regset_save_on_suspend) pm_dbg_regset_save(1); -- 1.6.0.4 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http
Re: [RFC][PATCH] OMAP3: PM: Fix workaround implementation for OMAP3 errata (1.142)
On Fri, 2009-08-07 at 11:48 +0300, Roger Quadros wrote: ext Kalle Jokiniemi wrote: On Fri, 2009-08-07 at 11:03 +0300, Roger Quadros wrote: ext Kalle Jokiniemi wrote: On Fri, 2009-08-07 at 01:14 +0300, Kevin Hilman wrote: Roger Quadros ext-roger.quad...@nokia.com writes: As per errata 1.142, on EMU/HS devices, SDRC_POWER should be programmed for automatic self-refresh before transition to OFF mode. In the current implementation this is done in omap3_scratchpad_contents() which is wrong, since this is the value that will be restored while resuming from OFF mode and not while transitioning to it. This patch implements the workaround in the correct way as per errata. Signed-off-by: Roger Quadros ext-roger.quad...@nokia.com This looks right to me. Rajendra, Kalle, any comments? since you were the originators of the original patch. Kevin --- arch/arm/mach-omap2/control.c | 16 ++-- arch/arm/mach-omap2/pm34xx.c | 20 ++-- 2 files changed, 16 insertions(+), 20 deletions(-) diff --git a/arch/arm/mach-omap2/control.c b/arch/arm/mach-omap2/control.c index a7159a9..0a563c8 100644 --- a/arch/arm/mach-omap2/control.c +++ b/arch/arm/mach-omap2/control.c @@ -272,20 +272,8 @@ void omap3_save_scratchpad_contents(void) (sdrc_read_reg(SDRC_ERR_TYPE) 0x); sdrc_block_contents.dll_a_ctrl = sdrc_read_reg(SDRC_DLLA_CTRL); sdrc_block_contents.dll_b_ctrl = 0x0; - /* -* Due to a OMAP3 errata (1.142), on EMU/HS devices SRDC should -* be programed to issue automatic self refresh on timeout -* of AUTO_CNT = 1 prior to any transition to OFF mode. -*/ - if ((omap_type() != OMAP2_DEVICE_TYPE_GP) -(omap_rev() = OMAP3430_REV_ES3_0)) - sdrc_block_contents.power = (sdrc_read_reg(SDRC_POWER) - ~(SDRC_POWER_AUTOCOUNT_MASK| - SDRC_POWER_CLKCTRL_MASK)) | - (1 SDRC_POWER_AUTOCOUNT_SHIFT) | - SDRC_SELF_REFRESH_ON_AUTOCOUNT; - else - sdrc_block_contents.power = sdrc_read_reg(SDRC_POWER); + + sdrc_block_contents.power = sdrc_read_reg(SDRC_POWER); Why do you want to remove the workaround from scratchpad? When we wake up from off mode, the boot ROM code writes these settings as the first sdrc_power settings after wakeup. If that setting does not include the workaround, we'll have a period of time where sdram is not being refreshed. This hits especially HS devices that do long secure context restore in ROM code as well. I suppose SDRAM is always refreshed (i.e. auto refresh) when ON. However when we enter OFF mode it should be _self_ refreshed. That is done by the below code before we switch to OFF mode. The erratum speaks of auto-refresh failing after waking up from CORE off mode. I think there is the described workaround in place in sleep34xx.S code to kick up the auto refresh, but this still leaves a short gap between boot ROM and the sleep code. Unless the self-refresh mode does not get changed by the scratchpad settings? - Kalle There are 2 parts in the errata 1.142. The 1st part is what you are talking about. And it needs to be applied only on ES3.0 devices. The 2nd part is valid only for HS devices. ..it is mandatory on HS device to have the SDRC issuing automatic self-refresh entries on inactivity periods.. My patch is only fixing the implementation of the 2nd part without changing the work around for the 1st part. no? The fix for second part is ok. But I have understood that the scratchpad change was an additional safeguard against the 1st part. Rajendra, any comments? I don't know how fast SDRAM corrupts when not refreshed, but on low OPP it takes several msecs to reach public code from boot ROM. So keeping SDRAM in self-refresh also in this period, seems sensible to me (even though the erratum does not mention a requirement for this). - Kalle -roger When we wake up from OFF mode (the scratchpad contents are used), we should restore the original register setting that was there before we went to OFF mode and not the self refresh mode setting. Hence the removal of above code. -roger sdrc_block_contents.cs_0 = 0x0; sdrc_block_contents.mcfg_0 = sdrc_read_reg(SDRC_MCFG_0); diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c index 14f10bc..eb3c9e5 100644 --- a/arch/arm/mach-omap2/pm34xx.c +++ b/arch/arm/mach-omap2/pm34xx.c @@ -405,15 +405,23 @@ void omap_sram_idle(void) } /* - * On EMU/HS devices ROM code restores a SRDC value - * from scratchpad which has automatic self refresh on timeout - * of AUTO_CNT = 1 enabled. This takes
Re: [RFC][PATCH] OMAP3: PM: Fix workaround implementation for OMAP3 errata (1.142)
On Fri, 2009-08-07 at 13:54 +0300, Roger Quadros wrote: ext Kalle Jokiniemi wrote: On Fri, 2009-08-07 at 11:48 +0300, Roger Quadros wrote: ext Kalle Jokiniemi wrote: On Fri, 2009-08-07 at 11:03 +0300, Roger Quadros wrote: ext Kalle Jokiniemi wrote: On Fri, 2009-08-07 at 01:14 +0300, Kevin Hilman wrote: Roger Quadros ext-roger.quad...@nokia.com writes: As per errata 1.142, on EMU/HS devices, SDRC_POWER should be programmed for automatic self-refresh before transition to OFF mode. In the current implementation this is done in omap3_scratchpad_contents() which is wrong, since this is the value that will be restored while resuming from OFF mode and not while transitioning to it. This patch implements the workaround in the correct way as per errata. Signed-off-by: Roger Quadros ext-roger.quad...@nokia.com This looks right to me. Rajendra, Kalle, any comments? since you were the originators of the original patch. Kevin --- arch/arm/mach-omap2/control.c | 16 ++-- arch/arm/mach-omap2/pm34xx.c | 20 ++-- 2 files changed, 16 insertions(+), 20 deletions(-) diff --git a/arch/arm/mach-omap2/control.c b/arch/arm/mach-omap2/control.c index a7159a9..0a563c8 100644 --- a/arch/arm/mach-omap2/control.c +++ b/arch/arm/mach-omap2/control.c @@ -272,20 +272,8 @@ void omap3_save_scratchpad_contents(void) (sdrc_read_reg(SDRC_ERR_TYPE) 0x); sdrc_block_contents.dll_a_ctrl = sdrc_read_reg(SDRC_DLLA_CTRL); sdrc_block_contents.dll_b_ctrl = 0x0; - /* - * Due to a OMAP3 errata (1.142), on EMU/HS devices SRDC should - * be programed to issue automatic self refresh on timeout - * of AUTO_CNT = 1 prior to any transition to OFF mode. - */ - if ((omap_type() != OMAP2_DEVICE_TYPE_GP) - (omap_rev() = OMAP3430_REV_ES3_0)) - sdrc_block_contents.power = (sdrc_read_reg(SDRC_POWER) - ~(SDRC_POWER_AUTOCOUNT_MASK| - SDRC_POWER_CLKCTRL_MASK)) | - (1 SDRC_POWER_AUTOCOUNT_SHIFT) | - SDRC_SELF_REFRESH_ON_AUTOCOUNT; - else - sdrc_block_contents.power = sdrc_read_reg(SDRC_POWER); + + sdrc_block_contents.power = sdrc_read_reg(SDRC_POWER); Why do you want to remove the workaround from scratchpad? When we wake up from off mode, the boot ROM code writes these settings as the first sdrc_power settings after wakeup. If that setting does not include the workaround, we'll have a period of time where sdram is not being refreshed. This hits especially HS devices that do long secure context restore in ROM code as well. I suppose SDRAM is always refreshed (i.e. auto refresh) when ON. However when we enter OFF mode it should be _self_ refreshed. That is done by the below code before we switch to OFF mode. The erratum speaks of auto-refresh failing after waking up from CORE off mode. I think there is the described workaround in place in sleep34xx.S code to kick up the auto refresh, but this still leaves a short gap between boot ROM and the sleep code. Unless the self-refresh mode does not get changed by the scratchpad settings? - Kalle There are 2 parts in the errata 1.142. The 1st part is what you are talking about. And it needs to be applied only on ES3.0 devices. The 2nd part is valid only for HS devices. ..it is mandatory on HS device to have the SDRC issuing automatic self-refresh entries on inactivity periods.. My patch is only fixing the implementation of the 2nd part without changing the work around for the 1st part. no? The fix for second part is ok. But I have understood that the scratchpad change was an additional safeguard against the 1st part. Rajendra, any comments? I don't know how fast SDRAM corrupts when not refreshed, but on low OPP it takes several msecs to reach public code from boot ROM. So keeping SDRAM in self-refresh also in this period, seems sensible to me (even though the erratum does not mention a requirement for this). - Kalle If what you are saying is right then this should be done for all OMAPs and not only non GP right? GP devices skip secure context restore, which decreases the wakeup time considerably. But I assume the gap to exist nevertheless, however smaller it may be. The question that I don't know the answer to in this scratchpad part, is that: If we use the normal sdrc_power setting in scratchpad, will it stop the self-refresh mode when boot ROM writes the normal scratchpad setting into sdrc_power register? If it does not, then we can remove the workaround from scratchpad settings. Rajendra, any comments. - Kalle -roger -roger When we wake up from OFF mode (the scratchpad contents are used), we should restore
RE: [PATCH 01/04] OMAP3: PM: Disable PER DPLL idle before OFF, reduces OFF latency by 20ms
On Wed, 2009-06-17 at 12:50 +0300, Nayak, Rajendra wrote: -Original Message- From: Kalle Jokiniemi [mailto:kalle.jokini...@digia.com] Sent: Wednesday, June 17, 2009 1:17 PM To: Nayak, Rajendra Cc: linux-omap@vger.kernel.org; Derrick, David; Woodruff, Richard Subject: Re: [PATCH 01/04] OMAP3: PM: Disable PER DPLL idle before OFF, reduces OFF latency by 20ms Hi Rajendra, On Tue, 2009-06-16 at 14:52 +0300, Rajendra Nayak wrote: If autoidle for DPLL4 is enabled in the stored scratchpad value of CM_AUTOIDLE_PLL then there is an added delay by the boot ROM when coming out of OFF mode. The patch disables this bitfield in the stored scratchpad value. This should significantly reduce CORE OFF latency and also bring down the threshold for CORE OFF, making OFF affordable even with smaller sleep times. I did some measurements on RX-51 with this patch, and it seems it does not reduce latency, it increases it by few hundred us. Servicing an empty timer interrupt from off mode (measured from VDD1 ramp up to start of VDD1 ramp down): with dpll4 patch : ~14100us without patch: ~13600us I attached pictures of both situations. My kernel had only C7 state enabled. Have you measured the latency effects on SDP or some other board? I haven't done the latency measurements on SDP yet, but David had done it sometime back, using a different codebase though. OK, I also used our internal code base. Though the PM functionality is pretty much the same as in l-o:pm branch. Can you explain more on how you are measuring the latency here, I am a bit confused. This is supposed to bring down the OFF wakeup latency, the sleep latency remains the same. I'm doing a timer interrupt periodically. Servicing that timer interrupt takes the same amount of time every time. What varies (with the patch) is the transition times from off to active and back to off. In the pictures the top graph shows current and bottom graph shows the VDD1 and VDD2 voltages. I zoomed from the pictures the interval from when VDD1 goes up, to the point when it starts to go down again. So I measured: wakeup latency + interrupt service + sleep latency. - Kalle - Kalle This patch however does not optimize the C state threshold for CORE OFF states based on the new latency. Signed-off-by: Rajendra Nayak rna...@ti.com --- arch/arm/mach-omap2/control.c |7 +++ 1 files changed, 7 insertions(+), 0 deletions(-) diff --git a/arch/arm/mach-omap2/control.c b/arch/arm/mach-omap2/control.c index c9407c0..a7159a9 100644 --- a/arch/arm/mach-omap2/control.c +++ b/arch/arm/mach-omap2/control.c @@ -238,6 +238,13 @@ void omap3_save_scratchpad_contents(void) cm_read_mod_reg(PLL_MOD, CM_CLKEN); prcm_block_contents.cm_autoidle_pll = cm_read_mod_reg(PLL_MOD, OMAP3430_CM_AUTOIDLE_PLL); + /* + * ROM restore takes 20mS longer if PER idle is enabled before OFF. + * Clear feature before sleep. The origional idle state is + * restored by software as part of wake procedure. + */ + prcm_block_contents.cm_autoidle_pll = ~OMAP3430_AUTO_PERIPH_DPLL_MASK; + prcm_block_contents.cm_clksel1_pll = cm_read_mod_reg(PLL_MOD, OMAP3430_CM_CLKSEL1_PLL); prcm_block_contents.cm_clksel2_pll = -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
RE: [PATCH 01/04] OMAP3: PM: Disable PER DPLL idle before OFF, reduces OFF latency by 20ms
On Wed, 2009-06-17 at 15:38 +0300, Nayak, Rajendra wrote: -Original Message- From: Kalle Jokiniemi [mailto:kalle.jokini...@digia.com] Sent: Wednesday, June 17, 2009 3:56 PM To: Nayak, Rajendra Cc: linux-omap@vger.kernel.org; Derrick, David; Woodruff, Richard Subject: RE: [PATCH 01/04] OMAP3: PM: Disable PER DPLL idle before OFF, reduces OFF latency by 20ms On Wed, 2009-06-17 at 12:50 +0300, Nayak, Rajendra wrote: -Original Message- From: Kalle Jokiniemi [mailto:kalle.jokini...@digia.com] Sent: Wednesday, June 17, 2009 1:17 PM To: Nayak, Rajendra Cc: linux-omap@vger.kernel.org; Derrick, David; Woodruff, Richard Subject: Re: [PATCH 01/04] OMAP3: PM: Disable PER DPLL idle before OFF, reduces OFF latency by 20ms Hi Rajendra, On Tue, 2009-06-16 at 14:52 +0300, Rajendra Nayak wrote: If autoidle for DPLL4 is enabled in the stored scratchpad value of CM_AUTOIDLE_PLL then there is an added delay by the boot ROM when coming out of OFF mode. The patch disables this bitfield in the stored scratchpad value. This should significantly reduce CORE OFF latency and also bring down the threshold for CORE OFF, making OFF affordable even with smaller sleep times. I did some measurements on RX-51 with this patch, and it seems it does not reduce latency, it increases it by few hundred us. Servicing an empty timer interrupt from off mode (measured from VDD1 ramp up to start of VDD1 ramp down): with dpll4 patch : ~14100us without patch: ~13600us I attached pictures of both situations. My kernel had only C7 state enabled. Have you measured the latency effects on SDP or some other board? I haven't done the latency measurements on SDP yet, but David had done it sometime back, using a different codebase though. OK, I also used our internal code base. Though the PM functionality is pretty much the same as in l-o:pm branch. Can you explain more on how you are measuring the latency here, I am a bit confused. This is supposed to bring down the OFF wakeup latency, the sleep latency remains the same. I'm doing a timer interrupt periodically. Servicing that timer interrupt takes the same amount of time every time. What varies (with the patch) is the transition times from off to active and back to off. In the pictures the top graph shows current and bottom graph shows the VDD1 and VDD2 voltages. I zoomed from the pictures the interval from when VDD1 goes up, to the point when it starts to go down again. So I measured: wakeup latency + interrupt service + sleep latency. Is the boot ROM different on the OMAP devices on nokia h/w or is it the same as that on the SDP? I have heard that our ROM version would be somehow older version, but I really don't have any facts on that matter. - Kalle - Kalle - Kalle This patch however does not optimize the C state threshold for CORE OFF states based on the new latency. Signed-off-by: Rajendra Nayak rna...@ti.com --- arch/arm/mach-omap2/control.c |7 +++ 1 files changed, 7 insertions(+), 0 deletions(-) diff --git a/arch/arm/mach-omap2/control.c b/arch/arm/mach-omap2/control.c index c9407c0..a7159a9 100644 --- a/arch/arm/mach-omap2/control.c +++ b/arch/arm/mach-omap2/control.c @@ -238,6 +238,13 @@ void omap3_save_scratchpad_contents(void) cm_read_mod_reg(PLL_MOD, CM_CLKEN); prcm_block_contents.cm_autoidle_pll = cm_read_mod_reg(PLL_MOD, OMAP3430_CM_AUTOIDLE_PLL); + /* +* ROM restore takes 20mS longer if PER idle is enabled before OFF. +* Clear feature before sleep. The origional idle state is +* restored by software as part of wake procedure. +*/ + prcm_block_contents.cm_autoidle_pll = ~OMAP3430_AUTO_PERIPH_DPLL_MASK; + prcm_block_contents.cm_clksel1_pll = cm_read_mod_reg(PLL_MOD, OMAP3430_CM_CLKSEL1_PLL); prcm_block_contents.cm_clksel2_pll = -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: PM: timeout waiting for write of PM_WKEN_WKUP.EN_IO_CHAIN
On Thu, 2009-05-14 at 18:57 +0300, Kevin Hilman wrote: Kalle, In your Enable IO-CHAIN wakeup patch[1], you set a timout based on 1000 tries of reading back from PM_WKST_WKUP. Just curious how you came up with that value. I tested it around a few times, and the loop seemed to run 2 iterations max. 1000 is just a random (big enough) number that I think should work if everything is ok. On ES3.1 3430SDP, some TI folks are seeing that timeout warning every time hitting idle. Then there is something wrong and the io-chain enable is not working. Please try removing the timeout and see if it hangs completely. I don't have a SDP to test on. - Kalle Kevin [1] http://marc.info/?l=linux-omapm=123807750921423w=2 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
RE: [PATCH] PM: Disable usb host HW save and restore
On Thu, 2009-05-14 at 20:40 +0300, Woodruff, Richard wrote: From: Kevin Hilman [mailto:khil...@deeprootsystems.com] Sent: Thursday, May 14, 2009 12:10 PM To: Kalle Jokiniemi Kalle Jokiniemi kalle.jokini...@digia.com writes: The hardware SAVEANDRESTORE mechanism seems to leave USB HOST power domain permanently into active state after one transition from off to active state. Disabling for now. Some are is needed around USB host domain handling. There are a couple errata impacting different chip revs. Today in the older TI reference code this condition of a stuck on power domain does not happen. However, we are using a software supervised method to disable the power domain. May be this code has a bug or the hardware does around auto use for this domain. Yes, usb-host autoidle was enabled when I was digging this issue. You will want TLL or host SAR activated to minimally work around a possible false cold reset issue. There is a window coming back from OFF where a reset will be thrown. Enabling SAR conclusively moves the internal window so there is no danger. The error is fairly easily seen so if you start taking resets know this is likely the root cause. What Rev of CPU is the issue occurring on? I think the usb-host problem was on ES3.1 at least. The USBTLL SAR in 3.0 and before silicon will case a deadlock on 2nd sleep attempt. On 3.1 and after its fixed. So ES3.0 devices are exposed to the cold reset issue (since USBTLL SAR is only enabled in ES3.1). Would you suspect that we can enable USB host SAR, if the AUTOIDLE is turned off? Then we would not need this patch. - Kalle Regards, Richard W. -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
RE: [PATCH] PM: Disable usb host HW save and restore
On Fri, 2009-05-15 at 14:47 +0300, Woodruff, Richard wrote: couple errata impacting different chip revs. Today in the older TI reference code this condition of a stuck on power domain does not happen. However, we are using a software supervised method to disable the power domain. May be this code has a bug or the hardware does around auto use for this domain. Yes, usb-host autoidle was enabled when I was digging this issue. Host domain? (not host module). OTG_SYSCONFIG.AUTOIDLE was what I meant. The USBTLL SAR in 3.0 and before silicon will case a deadlock on 2nd sleep attempt. On 3.1 and after its fixed. So ES3.0 devices are exposed to the cold reset issue (since USBTLL SAR is only enabled in ES3.1). Would you suspect that we can enable USB host SAR, if the AUTOIDLE is turned off? Then we would not need this patch. For 3.0 we used a software sar if ohci was in use. For ehci its not good enough as there is state not accessible by software. USB is by no means my specialty. That being said, using HW SAR could be used on ohci as well, right? Like you said: the cold reset issue will remain, if we don't use HW SAR for either USBTLL or USB HOST. And using USBTLL is not possible for ES3.0 due to that errata. Not as you wrote. I was thinking you need to try to go to idle using CM_CLKSTCTRL_USBHOST = 1. Not at 0x3 and then waiting for a dependent event to trigger you. Once your preconditions are met you can initiate and idle ack sequence. Ok, now I understand what you meant. I used toggling /sys/power/enable_off_mode to switch the USB HOST power domain state from RET-OFF-RET- Problem was I got RET-OFF-ON-ON-ON The resource framework takes care of switching usb-state (with next_state values and hw automated state transition) in this case. We would need some special usb sw transition code in resource framework and/or pm code to make the transitions work for usb host. - Kalle Regards, Richard W. -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 1/1] ARM: OMAP3: Add missing iva2 clken_pll save/restore
The CM_CLKEN_PLL_IVA2 register was not being saved by the current prcm save/restore code. This patch adds the proper save/restore for that register. Signed-off-by: Kalle Jokiniemi kalle.jokini...@digia.com --- arch/arm/mach-omap2/prcm.c |5 + 1 files changed, 5 insertions(+), 0 deletions(-) diff --git a/arch/arm/mach-omap2/prcm.c b/arch/arm/mach-omap2/prcm.c index a24792a..4f7fd99 100644 --- a/arch/arm/mach-omap2/prcm.c +++ b/arch/arm/mach-omap2/prcm.c @@ -54,6 +54,7 @@ struct omap3_prcm_regs { u32 pll_cm_clken2; u32 cm_polctrl; u32 iva2_cm_fclken; + u32 iva2_cm_clken_pll; u32 core_cm_fclken1; u32 core_cm_fclken3; u32 sgx_cm_fclken; @@ -260,6 +261,8 @@ void omap3_prcm_save_context(void) prcm_context.cm_polctrl = __raw_readl(OMAP3430_CM_POLCTRL); prcm_context.iva2_cm_fclken = cm_read_mod_reg(OMAP3430_IVA2_MOD, CM_FCLKEN); + prcm_context.iva2_cm_clken_pll = cm_read_mod_reg(OMAP3430_IVA2_MOD, + OMAP3430_CM_CLKEN_PLL); prcm_context.core_cm_fclken1 = cm_read_mod_reg(CORE_MOD, CM_FCLKEN1); prcm_context.core_cm_fclken3 = @@ -414,6 +417,8 @@ void omap3_prcm_restore_context(void) __raw_writel(prcm_context.cm_polctrl, OMAP3430_CM_POLCTRL); cm_write_mod_reg(prcm_context.iva2_cm_fclken, OMAP3430_IVA2_MOD, CM_FCLKEN); + cm_write_mod_reg(prcm_context.iva2_cm_clken_pll, OMAP3430_IVA2_MOD, + OMAP3430_CM_CLKEN_PLL); cm_write_mod_reg(prcm_context.core_cm_fclken1, CORE_MOD, CM_FCLKEN1); cm_write_mod_reg(prcm_context.core_cm_fclken3, CORE_MOD, OMAP3430ES2_CM_FCLKEN3); -- 1.5.4.3 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 1/1] ARM: OMAP: Add missing SMS_SYSCONFIG save/restore
SMS_SYSCONFIG register gets reset in off mode, added a save/restore mechanism for that. Signed-off-by: Kalle Jokiniemi kalle.jokini...@digia.com --- arch/arm/mach-omap2/pm34xx.c |1 + arch/arm/mach-omap2/sdrc.c | 27 +++ arch/arm/plat-omap/include/mach/sdrc.h |2 ++ 3 files changed, 30 insertions(+), 0 deletions(-) diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c index 60a1c4c..6e286ef 100644 --- a/arch/arm/mach-omap2/pm34xx.c +++ b/arch/arm/mach-omap2/pm34xx.c @@ -439,6 +439,7 @@ void omap_sram_idle(void) omap3_core_restore_context(); omap3_prcm_restore_context(); omap3_sram_restore_context(); + omap2_sms_restore_context(); } omap_uart_resume_idle(0); omap_uart_resume_idle(1); diff --git a/arch/arm/mach-omap2/sdrc.c b/arch/arm/mach-omap2/sdrc.c index 2045441..c832d83 100644 --- a/arch/arm/mach-omap2/sdrc.c +++ b/arch/arm/mach-omap2/sdrc.c @@ -37,12 +37,38 @@ static struct omap_sdrc_params *sdrc_init_params; void __iomem *omap2_sdrc_base; void __iomem *omap2_sms_base; +struct omap2_sms_regs { + u32 sms_sysconfig; +}; + +static struct omap2_sms_regs sms_context; + /* SDRC_POWER register bits */ #define SDRC_POWER_EXTCLKDIS_SHIFT 3 #define SDRC_POWER_PWDENA_SHIFT2 #define SDRC_POWER_PAGEPOLICY_SHIFT0 /** + * omap2_sms_save_context - Save SMS registers + * + * Save SMS registers that need to be restored after off mode. + */ +void omap2_sms_save_context(void) +{ + sms_context.sms_sysconfig = sms_read_reg(SMS_SYSCONFIG); +} + +/** + * omap2_sms_restore_context - Restore SMS registers + * + * Restore SMS registers that need to be Restored after off mode. + */ +void omap2_sms_restore_context(void) +{ + sms_write_reg(sms_context.sms_sysconfig, SMS_SYSCONFIG); +} + +/** * omap2_sdrc_get_params - return SDRC register values for a given clock rate * @r: SDRC clock rate (in Hz) * @@ -110,4 +136,5 @@ void __init omap2_sdrc_init(struct omap_sdrc_params *sp) (1 SDRC_POWER_PWDENA_SHIFT) | (1 SDRC_POWER_PAGEPOLICY_SHIFT); sdrc_write_reg(l, SDRC_POWER); + omap2_sms_save_context(); } diff --git a/arch/arm/plat-omap/include/mach/sdrc.h b/arch/arm/plat-omap/include/mach/sdrc.h index a5a6cf9..a678bc8 100644 --- a/arch/arm/plat-omap/include/mach/sdrc.h +++ b/arch/arm/plat-omap/include/mach/sdrc.h @@ -112,6 +112,8 @@ struct omap_sdrc_params { u32 mr; }; +void omap2_sms_save_context(void); +void omap2_sms_restore_context(void); void __init omap2_sdrc_init(struct omap_sdrc_params *); struct omap_sdrc_params *omap2_sdrc_get_params(unsigned long r); -- 1.5.4.3 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 1/1] ARM:OMAP3: Fix PLL_MOD CLKEN offset in scratchpad
The CM_CLKEN_PLL register saved in scratchpad memory was wrongly using offset of 0x0004 instead of 0x. The effect of this was that boot ROM code would restore the wrong value when waking up from off mode. This wrong value, however, will be overwritten by prcm context restore. Still, a short period of wrong clock settings in CM_CLKEN_PLL remained between ROM code and prcm context restore. This is fixed by the patch. Problem reported by: Jouni Högander jouni.hogan...@nokia.com Signed-off-by: Kalle Jokiniemi kalle.jokini...@digia.com --- arch/arm/mach-omap2/control.c |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/arch/arm/mach-omap2/control.c b/arch/arm/mach-omap2/control.c index a0429fe..60de860 100644 --- a/arch/arm/mach-omap2/control.c +++ b/arch/arm/mach-omap2/control.c @@ -235,7 +235,7 @@ void omap3_save_scratchpad_contents(void) prcm_block_contents.cm_clksel_wkup = cm_read_mod_reg(WKUP_MOD, CM_CLKSEL); prcm_block_contents.cm_clken_pll = - cm_read_mod_reg(PLL_MOD, OMAP3430_CM_CLKEN_PLL); + cm_read_mod_reg(PLL_MOD, CM_CLKEN); prcm_block_contents.cm_autoidle_pll = cm_read_mod_reg(PLL_MOD, OMAP3430_CM_AUTOIDLE_PLL); prcm_block_contents.cm_clksel1_pll = -- 1.5.4.3 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 0/1] ARM:OMAP3: Fix PLL_MOD CLKEN offset in scratchpad
Following patch should apply on top of pm-branch. Build tested for rx-51. Kalle Jokiniemi (1): ARM:OMAP3: Fix PLL_MOD CLKEN offset in scratchpad arch/arm/mach-omap2/control.c |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 0/1] Fix OMAP_CHIP_INIT usage
Found this chip init problem while debugging a problem with usb host getting stuck at active mode when toggling the /sys/power/enable_off_mode. The OMAP_CHIP_INIT calls used is ES2.0 macros, while it should be now according to the new macro definitions greater or equal to ES2.0. Boot tested on RX51 (smartreflex disabled, as there is that problem vp_init problem) Should apply on latest pm branch. - Kalle -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] ARM: OMAP3: Fix OMAP_CHIP_INIT usage
Some modules have been specified only to exist in ES2.0 devices while they should exist on = ES2.0 devices. Fixed OMAP_CHIP_INIT() calls to take this to account. Signed-off-by: Kalle Jokiniemi kalle.jokini...@digia.com --- arch/arm/mach-omap2/omapdev3xxx.h |8 arch/arm/mach-omap2/resource34xx.h |4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/arm/mach-omap2/omapdev3xxx.h b/arch/arm/mach-omap2/omapdev3xxx.h index dce87df..d2772c4 100644 --- a/arch/arm/mach-omap2/omapdev3xxx.h +++ b/arch/arm/mach-omap2/omapdev3xxx.h @@ -374,7 +374,7 @@ static struct omapdev neon_3xxx_omapdev = { static struct omapdev sgx_3xxx_omapdev = { .name = sgx_omapdev, .pwrdm = { .name = sgx_pwrdm }, - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES2), + .omap_chip = OMAP_CHIP_INIT(CHIP_GE_OMAP3430ES2), }; /* CORE */ @@ -435,7 +435,7 @@ static struct omapdev hsmmc3_3xxx_omapdev = { .pwrdm = { .name = core_pwrdm }, .pdev_name = mmci-omap, .pdev_id= 2, - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES2), + .omap_chip = OMAP_CHIP_INIT(CHIP_GE_OMAP3430ES2), }; static struct omapdev mcspi4_3xxx_omapdev = { @@ -658,7 +658,7 @@ static struct omapdev usbhost_3xxx_omapdev = { .pwrdm = { .name = usbhost_pwrdm }, .pdev_name = ehci-omap, .pdev_id= 0, - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES2), + .omap_chip = OMAP_CHIP_INIT(CHIP_GE_OMAP3430ES2), }; static struct omapdev usbotg_3xxx_omapdev = { @@ -666,7 +666,7 @@ static struct omapdev usbotg_3xxx_omapdev = { .pwrdm = { .name = usbhost_pwrdm }, .pdev_name = musb_hdrc, .pdev_id= -1, - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES2), + .omap_chip = OMAP_CHIP_INIT(CHIP_GE_OMAP3430ES2), }; static struct omapdev usbtll_3xxx_omapdev = { diff --git a/arch/arm/mach-omap2/resource34xx.h b/arch/arm/mach-omap2/resource34xx.h index b847208..8d95a00 100644 --- a/arch/arm/mach-omap2/resource34xx.h +++ b/arch/arm/mach-omap2/resource34xx.h @@ -133,7 +133,7 @@ static struct shared_resource gfx_pwrdm_latency = { static struct shared_resource sgx_pwrdm_latency = { .name = sgx_pwrdm_latency, - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES2), + .omap_chip = OMAP_CHIP_INIT(CHIP_GE_OMAP3430ES2), .resource_data = sgx_pwrdm_lat_db, .ops= pd_lat_res_ops, }; @@ -208,7 +208,7 @@ static struct pd_latency_db usbhost_pwrdm_lat_db = { static struct shared_resource usbhost_pwrdm_latency = { .name = usbhost_pwrdm_latency, - .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES2), + .omap_chip = OMAP_CHIP_INIT(CHIP_GE_OMAP3430ES2), .resource_data = usbhost_pwrdm_lat_db, .ops= pd_lat_res_ops, }; -- 1.5.4.3 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 0/1] Fix OMAP_CHIP_INIT usage
On Thu, 2009-04-23 at 12:43 +0300, Kalle Jokiniemi wrote: Found this chip init problem while debugging a problem with usb host getting stuck at active mode when toggling the BTW, this usb host problem is not fixed by this chip init patch. I'm sending a separate patch that completely disables the usb host hardware save/restore. That fixes the usb_host active problem. - Kalle /sys/power/enable_off_mode. The OMAP_CHIP_INIT calls used is ES2.0 macros, while it should be now according to the new macro definitions greater or equal to ES2.0. Boot tested on RX51 (smartreflex disabled, as there is that problem vp_init problem) Should apply on latest pm branch. - Kalle -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] PM: Disable usb host HW save and restore
The hardware SAVEANDRESTORE mechanism seems to leave USB HOST power domain permanently into active state after one transition from off to active state. Disabling for now. Signed-off-by: Kalle Jokiniemi ext-kalle.jokini...@nokia.com --- arch/arm/mach-omap2/powerdomains34xx.h |8 +++- 1 files changed, 7 insertions(+), 1 deletions(-) diff --git a/arch/arm/mach-omap2/powerdomains34xx.h b/arch/arm/mach-omap2/powerdomains34xx.h index 4dcf94b..aa557b2 100644 --- a/arch/arm/mach-omap2/powerdomains34xx.h +++ b/arch/arm/mach-omap2/powerdomains34xx.h @@ -338,7 +338,13 @@ static struct powerdomain usbhost_pwrdm = { .sleepdep_srcs= dss_per_usbhost_sleepdeps, .pwrsts = PWRSTS_OFF_RET_ON, .pwrsts_logic_ret = PWRDM_POWER_RET, - .flags= PWRDM_HAS_HDWR_SAR, /* for USBHOST ctrlr only */ + /* +* REVISIT: Enabling usb host save and restore mechanism seems to +* leave the usb host domain permanently in ACTIVE mode after +* changing the usb host power domain state from OFF to active once. +* Disabling for now. +*/ + /*.flags = PWRDM_HAS_HDWR_SAR,*/ /* for USBHOST ctrlr only */ .banks= 1, .pwrsts_mem_ret = { [0] = PWRDM_POWER_RET, /* MEMRETSTATE */ -- 1.5.4.3 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] ARM: OMAP3: Fix HW SAVEANDRESTORE shift define
The OMAP3430ES2_SAVEANDRESTORE_SHIFT macro is used by powerdomain code in 1 OMAP3430ES2_SAVEANDRESTORE_SHIFT manner, but the definition was also (1 4), meaning we actually modified bit 16. So the definition needs to be 4. This fixes also a cold reset HW bug in OMAP3430 ES3.x where some of the efuse bits are not isolated during wake-up from off mode. This can cause randomish cold resets with off mode. Enabling the USBTLL hardware SAVEANDRESTORE causes the core power up assert to be delayed in a way that we will not get faulty values when boot ROM is reading the unisolated registers. Signed-off-by: Kalle Jokiniemi kalle.jokini...@digia.com --- arch/arm/mach-omap2/prm-regbits-34xx.h |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/arch/arm/mach-omap2/prm-regbits-34xx.h b/arch/arm/mach-omap2/prm-regbits-34xx.h index d73eee8..d792c29 100644 --- a/arch/arm/mach-omap2/prm-regbits-34xx.h +++ b/arch/arm/mach-omap2/prm-regbits-34xx.h @@ -409,7 +409,7 @@ /* PM_PREPWSTST_CAM specific bits */ /* PM_PWSTCTRL_USBHOST specific bits */ -#define OMAP3430ES2_SAVEANDRESTORE_SHIFT (1 4) +#define OMAP3430ES2_SAVEANDRESTORE_SHIFT 4 /* RM_RSTST_PER specific bits */ -- 1.5.4.3 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 0/1] Fix HW SAVEANDRESTORE shift define
Here's a patch that fixes a bug in enabling and disabling hardware save-and-restore functionality in powerdomain.c code. This affects power management, as it also fixes a hw bug in off-mode, but I think this should be applied directly to linux-omap. As this part of code is already there and its setting up wrong bits in PM_PWSTCTRL registers. Kalle Jokiniemi (1): ARM: OMAP3: Fix HW SAVEANDRESTORE shift define -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 0/1] ARM:OMAP3: Misc off mode fixes
Here's a set of patches to fix some off mode problems in ES3.0 and ES3.1 devices. Should apply on top of pm branch. Kalle Jokiniemi (3): ARM:OMAP3: Enable SDRC workaround for ES3.1 ARM: OMAP3: Fix secure sram saving ARM: OMAP3: Enable IO-CHAIN wakeup -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 2/3] ARM: OMAP3: Fix secure sram saving
The secure sram context save uses dma channels 0 and 1. In order to avoid collision between kernel DMA transfers and ROM code dma transfers, we need to reserve DMA channels 0 1 on high security devices. A bug in ROM code leaves dma irq status bits uncleared. Hence those irq status bits need to be cleared when restoring DMA context after off mode. There was also a faulty parameter given to PPA in the secure ram context save assembly code, which caused interrupts to be enabled during secure ram context save. This caused the save to fail sometimes, which resulted the saved context to be corrupted, but also left DMA channels in secure mode. The secure mode DMA channels caused DMA secure error with device 0 errors to be displayed. Signed-off-by: Kalle Jokiniemi kalle.jokini...@digia.com Signed-off-by: Jouni Hogander jouni.hogan...@nokia.com --- arch/arm/mach-omap2/pm34xx.c|3 --- arch/arm/mach-omap2/sleep34xx.S |2 +- arch/arm/plat-omap/dma.c| 22 ++ 3 files changed, 19 insertions(+), 8 deletions(-) diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c index c21d4e9..7bbbcce 100644 --- a/arch/arm/mach-omap2/pm34xx.c +++ b/arch/arm/mach-omap2/pm34xx.c @@ -144,9 +144,6 @@ static void omap3_save_secure_ram_context(u32 target_mpu_state) u32 ret; if (omap_type() != OMAP2_DEVICE_TYPE_GP) { - /* Disable dma irq before calling secure rom code API */ - omap_dma_disable_irq(0); - omap_dma_disable_irq(1); /* * MPU next state must be set to POWER_ON temporarily, * otherwise the WFI executed inside the ROM code diff --git a/arch/arm/mach-omap2/sleep34xx.S b/arch/arm/mach-omap2/sleep34xx.S index 33ee85b..0a58c30 100644 --- a/arch/arm/mach-omap2/sleep34xx.S +++ b/arch/arm/mach-omap2/sleep34xx.S @@ -138,7 +138,7 @@ save_secure_ram_debug: mov r0, #25 @ set service ID for PPA mov r12, r0 @ copy secure service ID in r12 mov r1, #0 @ set task id for ROM code in r1 - mov r2, #7 @ set some flags in r2, r6 + mov r2, #4 @ set some flags in r2, r6 mov r6, #0xff mcr p15, 0, r0, c7, c10, 4 @ data write barrier mcr p15, 0, r0, c7, c10, 5 @ data memory barrier diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c index 94b3e4d..a040dbc 100755 --- a/arch/arm/plat-omap/dma.c +++ b/arch/arm/plat-omap/dma.c @@ -2322,14 +2322,21 @@ EXPORT_SYMBOL(omap_dma_global_context_save); void omap_dma_global_context_restore(void) { - dma_write(0x2, OCP_SYSCONFIG); - while (!__raw_readl(omap_dma_base + OMAP_DMA4_SYSSTATUS)) - ; dma_write(omap_dma_global_context.dma_gcr, GCR); dma_write(omap_dma_global_context.dma_ocp_sysconfig, OCP_SYSCONFIG); dma_write(omap_dma_global_context.dma_irqenable_l0, IRQENABLE_L0); + + /* +* A bug in ROM code leaves IRQ status for channels 0 and 1 uncleared +* after secure sram context save and restore. Hence we need to +* manually clear those IRQs to avoid spurious interrupts. This +* affects only secure devices. +*/ + if (cpu_is_omap34xx() (omap_type() != OMAP2_DEVICE_TYPE_GP)) { + dma_write(0x3 , IRQSTATUS_L0); + } } EXPORT_SYMBOL(omap_dma_global_context_restore); @@ -2465,8 +2472,8 @@ static int __init omap_init_dma(void) if (cpu_class_is_omap2()) setup_irq(INT_24XX_SDMA_IRQ0, omap24xx_dma_irq); - /* Enable smartidle idlemodes and autoidle */ if (cpu_is_omap34xx()) { + /* Enable smartidle idlemodes and autoidle */ u32 v = dma_read(OCP_SYSCONFIG); v = ~(DMA_SYSCONFIG_MIDLEMODE_MASK | DMA_SYSCONFIG_SIDLEMODE_MASK | @@ -2475,6 +2482,13 @@ static int __init omap_init_dma(void) DMA_SYSCONFIG_SIDLEMODE(DMA_IDLEMODE_SMARTIDLE) | DMA_SYSCONFIG_AUTOIDLE); dma_write(v , OCP_SYSCONFIG); + /* reserve dma channels 0 and 1 in high security devices */ + if (omap_type() != OMAP2_DEVICE_TYPE_GP) { + printk(KERN_INFO Reserving DMA channels 0 and 1 for + HS ROM code\n); + dma_chan[0].dev_id = 0; + dma_chan[1].dev_id = 1; + } } -- 1.5.4.3 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 3/3] ARM: OMAP3: Enable IO-CHAIN wakeup
OMAP 3430 ES3.1 chips have a separate bit for IO daisy-chain wake up enabling. It needs to be enabled when entering retention or off state, otherwise waking up might not work in all situations. Signed-off-by: Kalle Jokiniemi kalle.jokini...@digia.com --- arch/arm/mach-omap2/pm34xx.c | 37 +-- arch/arm/mach-omap2/prm-regbits-34xx.h |2 + 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c index 7bbbcce..4345df1 100644 --- a/arch/arm/mach-omap2/pm34xx.c +++ b/arch/arm/mach-omap2/pm34xx.c @@ -101,6 +101,34 @@ static inline void omap3_per_restore_context(void) omap3_gpio_restore_context(); } +static void omap3_enable_io_chain(void) +{ + int timeout = 0; + + if (omap_rev() = OMAP3430_REV_ES3_1) { + prm_set_mod_reg_bits(OMAP3430_EN_IO_CHAIN, WKUP_MOD, PM_WKEN); + /* Do a readback to assure write has been done */ + prm_read_mod_reg(WKUP_MOD, PM_WKEN); + + while (!(prm_read_mod_reg(WKUP_MOD, PM_WKST) + OMAP3430_ST_IO_CHAIN)) { + timeout++; + if (timeout 1000) { + printk(KERN_ERR Wake up daisy chain + activation failed.\n); + return; + } + prm_set_mod_reg_bits(OMAP3430_ST_IO_CHAIN, WKUP_MOD, PM_WKST); + } + } +} + +static void omap3_disable_io_chain(void) +{ + if (omap_rev() = OMAP3430_REV_ES3_1) + prm_clear_mod_reg_bits(OMAP3430_EN_IO_CHAIN, WKUP_MOD, PM_WKEN); +} + static void omap3_core_save_context(void) { u32 control_padconf_off; @@ -358,8 +386,9 @@ void omap_sram_idle(void) omap3_core_save_context(); omap3_prcm_save_context(); } - /* Enable IO-PAD wakeup */ + /* Enable IO-PAD and IO-CHAIN wakeups */ prm_set_mod_reg_bits(OMAP3430_EN_IO, WKUP_MOD, PM_WKEN); + omap3_enable_io_chain(); } /* @@ -425,9 +454,11 @@ void omap_sram_idle(void) pwrdm_set_next_pwrst(per_pwrdm, PWRDM_POWER_OFF); } - /* Disable IO-PAD wakeup */ - if (core_next_state PWRDM_POWER_ON) + /* Disable IO-PAD and IO-CHAIN wakeup */ + if (core_next_state PWRDM_POWER_ON) { prm_clear_mod_reg_bits(OMAP3430_EN_IO, WKUP_MOD, PM_WKEN); + omap3_disable_io_chain(); + } /* Enable smartreflex after WFI */ enable_smartreflex(SR1); diff --git a/arch/arm/mach-omap2/prm-regbits-34xx.h b/arch/arm/mach-omap2/prm-regbits-34xx.h index cb648f9..06fee29 100644 --- a/arch/arm/mach-omap2/prm-regbits-34xx.h +++ b/arch/arm/mach-omap2/prm-regbits-34xx.h @@ -365,6 +365,7 @@ /* PM_PREPWSTST_GFX specific bits */ /* PM_WKEN_WKUP specific bits */ +#define OMAP3430_EN_IO_CHAIN (1 16) #define OMAP3430_EN_IO (1 8) #define OMAP3430_EN_GPIO1 (1 3) @@ -373,6 +374,7 @@ /* PM_IVA2GRPSEL_WKUP specific bits */ /* PM_WKST_WKUP specific bits */ +#define OMAP3430_ST_IO_CHAIN (1 16) #define OMAP3430_ST_IO (1 8) /* PRM_CLKSEL */ -- 1.5.4.3 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [patch 2.6.29-rc3-git 2/2] USB: disable twl4030 USB regulators when cable unplugged
On Thu, 2009-02-26 at 14:40 -0800, David Brownell wrote: On Thursday 26 February 2009, Liam Girdwood wrote: On Sun, 2009-02-08 at 10:52 -0800, David Brownell wrote: From: Kalle Jokiniemi kalle.jokini...@digia.com This patch disables LDO regulators VUSB1V5, VUSB1V8, and VUSB3V1 when the USB cable is unplugged, to eliminate that source of power waste. (Enabled LDOs consume power at all times.) Signed-off-by: Kalle Jokiniemi kalle.jokini...@digia.com Signed-off-by: David Brownell dbrown...@users.sourceforge.net --- Depends on the twl4030 regulator driver, so I'm suggesting this be merged (with that driver) through the regulator patch queue to simplify things. drivers/usb/otg/twl4030-usb.c | 30 -- 1 file changed, 24 insertions(+), 6 deletions(-) Applied. Better suggestion: grab Kalle's updated patch from Greg's USB queue: http://www.kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/gregkh-04-usb/ patch name usb-twl-disable-vusb-regulators-when-cable-unplugged.patch Yep, this previous one lacked some error checks and a build dependency to TWL_REGULATOR. - Kalle - Dave -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 0/2] TWL: USB: Start using twl4030/5030 regulator driver
On Fri, 2009-02-13 at 14:35 -0800, David Brownell wrote: On Friday 13 February 2009, Kalle Jokiniemi wrote: I ran into some trouble with the merged fix. For some reason clearing the VUSB3V1_DEV_GRP register causes VUSB_DEDICATED2.VUSB3V1_SLEEP bit to be enabled. This means that once VUSB3V1_DEV_GRP is put back to enabled state (VUSB3V1 changed to be part of P1 group again), VUSB3V1 does not go ACTIVE, but SLEEP state instead. Anyone have a clue what might cause this? Curious. No ... is that specific to some TWL revision? TWL5030, I think the revision is ES1.0. I got additional info from TI that when the LDO goes into off state, the sleep bit indeed resets back to default value of 1. Which is to remap active state to sleep. So I have a patch that takes this into account by clearing the remap bit every time we wake up the VUSB3V1 regulator. - Kalle I'll poke around after I get this new board working better for me. - Dave -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 1/1] TWL: USB: disable VUSB regulators when cable unplugged
From: Jouni Hogander jouni.hogan...@nokia.com This patch disables USB regulators VUSB1V5, VUSB1V8, and VUSB3V1 when the USB cable is unplugged to reduce power consumption. Added a depencency from twl4030 usb driver to TWL_REGULATOR. Signed-off-by: Jouni Hogander jouni.hogan...@nokia.com Signed-off-by: Kalle Jokiniemi kalle.jokini...@digia.com --- drivers/usb/otg/Kconfig |2 +- drivers/usb/otg/twl4030-usb.c | 73 - 2 files changed, 65 insertions(+), 10 deletions(-) diff --git a/drivers/usb/otg/Kconfig b/drivers/usb/otg/Kconfig index ee55b44..5790a5b 100644 --- a/drivers/usb/otg/Kconfig +++ b/drivers/usb/otg/Kconfig @@ -43,7 +43,7 @@ config ISP1301_OMAP config TWL4030_USB tristate TWL4030 USB Transceiver Driver - depends on TWL4030_CORE + depends on TWL4030_CORE REGULATOR_TWL4030 select USB_OTG_UTILS help Enable this to support the USB OTG transceiver on TWL4030 diff --git a/drivers/usb/otg/twl4030-usb.c b/drivers/usb/otg/twl4030-usb.c index 416e441..d9478d0 100644 --- a/drivers/usb/otg/twl4030-usb.c +++ b/drivers/usb/otg/twl4030-usb.c @@ -34,6 +34,8 @@ #include linux/delay.h #include linux/usb/otg.h #include linux/i2c/twl4030.h +#include linux/regulator/consumer.h +#include linux/err.h /* Register defines */ @@ -246,6 +248,11 @@ struct twl4030_usb { struct otg_transceiver otg; struct device *dev; + /* TWL4030 internal USB regulator supplies */ + struct regulator*usb1v5; + struct regulator*usb1v8; + struct regulator*usb3v1; + /* for vbus reporting with irqs disabled */ spinlock_t lock; @@ -434,6 +441,18 @@ static void twl4030_phy_power(struct twl4030_usb *twl, int on) pwr = twl4030_usb_read(twl, PHY_PWR_CTRL); if (on) { + regulator_enable(twl-usb3v1); + regulator_enable(twl-usb1v8); + /* +* Disabling usb3v1 regulator (= writing 0 to VUSB3V1_DEV_GRP +* in twl4030) resets the VUSB_DEDICATED2 register. This reset +* enables VUSB3V1_SLEEP bit that remaps usb3v1 ACTIVE state to +* SLEEP. We work around this by clearing the bit after usv3v1 +* is re-activated. This ensures that VUSB3V1 is really active. +*/ + twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, + VUSB_DEDICATED2); + regulator_enable(twl-usb1v5); pwr = ~PHY_PWR_PHYPWD; WARN_ON(twl4030_usb_write_verify(twl, PHY_PWR_CTRL, pwr) 0); twl4030_usb_write(twl, PHY_CLK_CTRL, @@ -443,6 +462,9 @@ static void twl4030_phy_power(struct twl4030_usb *twl, int on) } else { pwr |= PHY_PWR_PHYPWD; WARN_ON(twl4030_usb_write_verify(twl, PHY_PWR_CTRL, pwr) 0); + regulator_disable(twl-usb1v5); + regulator_disable(twl-usb1v8); + regulator_disable(twl-usb3v1); } } @@ -468,7 +490,7 @@ static void twl4030_phy_resume(struct twl4030_usb *twl) twl-asleep = 0; } -static void twl4030_usb_ldo_init(struct twl4030_usb *twl) +static int twl4030_usb_ldo_init(struct twl4030_usb *twl) { /* Enable writing to power configuration registers */ twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0xC0, PROTECT_KEY); @@ -480,20 +502,45 @@ static void twl4030_usb_ldo_init(struct twl4030_usb *twl) /* input to VUSB3V1 LDO is from VBAT, not VBUS */ twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x14, VUSB_DEDICATED1); - /* turn on 3.1V regulator */ - twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x20, VUSB3V1_DEV_GRP); + /* Initialize 3.1V regulator */ + twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB3V1_DEV_GRP); + + twl-usb3v1 = regulator_get(twl-dev, usb3v1); + if (IS_ERR(twl-usb3v1)) + return -ENODEV; + twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB3V1_TYPE); - /* turn on 1.5V regulator */ - twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x20, VUSB1V5_DEV_GRP); + /* Initialize 1.5V regulator */ + twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V5_DEV_GRP); + + twl-usb1v5 = regulator_get(twl-dev, usb1v5); + if (IS_ERR(twl-usb1v5)) + goto fail1; + twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V5_TYPE); - /* turn on 1.8V regulator */ - twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x20, VUSB1V8_DEV_GRP); + /* Initialize 1.8V regulator */ + twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V8_DEV_GRP); + + twl-usb1v8 = regulator_get(twl-dev, usb1v8); + if (IS_ERR(twl-usb1v8)) + goto fail2; + twl4030_i2c_write_u8
[PATCH 0/1] USB: disable twl4030 usb regulators
This patch combines the two patches TWL: USB: disable VUSB regulators when cable unplugged and USB: OTG: Twl4030 depends on REGULATOR_TWL4030 sent earlier by me. New thing is that the patch now handles situations where disabling of VUSB3V1 regulator resets the ACTIVE state remapping to SLEEP to be enabled. Thanks to Jouni Hogander and David Brownell for helping out with the patch. drivers/usb/otg/Kconfig |2 +- drivers/usb/otg/twl4030-usb.c | 73 - 2 files changed, 65 insertions(+), 10 deletions(-) -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 0/2] TWL: USB: Start using twl4030/5030 regulator driver
On Wed, 2009-02-11 at 12:47 +0200, Kalle Jokiniemi wrote: On Tue, 2009-02-10 at 23:23 -0800, David Brownell wrote: On Tuesday 10 February 2009, Kalle Jokiniemi wrote: These couple of patches enable dynamic swithcing of the regulators used by twl4030 usb tranceiver. This set replaces the single patch USB: disable twl4030 USB regulators when cable unplugged sent previously. The change to previous version is that possible errors in regulator_get are now handled and the twl4030 usb driver requires TWL_REGULATOR support to be compiled. It'd make more sense to me as a single patch ... :) OK, I'll put them together. And also, instead of *continuing* after the regulators can't be acquired, it's better to abort. It's not going to be able to do anything ... so don't finish probing, and don't register this dead transceiver. Makes sense. I'll fix that. I ran into some trouble with the merged fix. For some reason clearing the VUSB3V1_DEV_GRP register causes VUSB_DEDICATED2.VUSB3V1_SLEEP bit to be enabled. This means that once VUSB3V1_DEV_GRP is put back to enabled state (VUSB3V1 changed to be part of P1 group again), VUSB3V1 does not go ACTIVE, but SLEEP state instead. Anyone have a clue what might cause this? The VUSB_DEDICATED2.VUSB3V1_SLEEP bit remaps ACTIVE state to SLEEP. I tested with the original patch as well and it has the same behaviour. But I'm quite sure that I did not see this when I was doing the original patch. I can workaround this by clearing the VUSB_DEDICATED2.VUSB3V1_SLEEP every time we enable the VUSB3V1 regulator, but I'd rather know why it changes in the first place. Dropped LKM from the cc... - Kalle -Kalle - Dave -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 0/2] TWL: USB: Start using twl4030/5030 regulator driver
On Tue, 2009-02-10 at 23:23 -0800, David Brownell wrote: On Tuesday 10 February 2009, Kalle Jokiniemi wrote: These couple of patches enable dynamic swithcing of the regulators used by twl4030 usb tranceiver. This set replaces the single patch USB: disable twl4030 USB regulators when cable unplugged sent previously. The change to previous version is that possible errors in regulator_get are now handled and the twl4030 usb driver requires TWL_REGULATOR support to be compiled. It'd make more sense to me as a single patch ... :) OK, I'll put them together. And also, instead of *continuing* after the regulators can't be acquired, it's better to abort. It's not going to be able to do anything ... so don't finish probing, and don't register this dead transceiver. Makes sense. I'll fix that. -Kalle - Dave -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [patch 2.6.29-rc3-git 2/2] USB: disable twl4030 USB regulators when cable unplugged
On Sun, 2009-02-08 at 10:52 -0800, David Brownell wrote: From: Kalle Jokiniemi kalle.jokini...@digia.com This patch disables LDO regulators VUSB1V5, VUSB1V8, and VUSB3V1 when the USB cable is unplugged, to eliminate that source of power waste. (Enabled LDOs consume power at all times.) Please put this one on hold. A bug has been discovered here. If the twl-regulator is not compiled in, the twl4030-usb fails while trying to access the reg-fw interfaces (and not checking error values). Also it's bit confusing how we get different error values if reg_fw is not compiled (no error) vs. reg_fw is compiled, but twl_regulator is not... (error) Also problems with boot order were discovered. I'll post a set that fixes this soon. - Kalle Signed-off-by: Kalle Jokiniemi kalle.jokini...@digia.com Signed-off-by: David Brownell dbrown...@users.sourceforge.net --- Depends on the twl4030 regulator driver, so I'm suggesting this be merged (with that driver) through the regulator patch queue to simplify things. drivers/usb/otg/twl4030-usb.c | 30 -- 1 file changed, 24 insertions(+), 6 deletions(-) --- a/drivers/usb/otg/twl4030-usb.c +++ b/drivers/usb/otg/twl4030-usb.c @@ -34,6 +34,7 @@ #include linux/delay.h #include linux/usb/otg.h #include linux/i2c/twl4030.h +#include linux/regulator/consumer.h /* Register defines */ @@ -246,6 +247,11 @@ struct twl4030_usb { struct otg_transceiver otg; struct device *dev; + /* TWL4030 internal USB regulator supplies */ + struct regulator*usb1v5; + struct regulator*usb1v8; + struct regulator*usb3v1; + /* for vbus reporting with irqs disabled */ spinlock_t lock; @@ -434,6 +440,9 @@ static void twl4030_phy_power(struct twl pwr = twl4030_usb_read(twl, PHY_PWR_CTRL); if (on) { + regulator_enable(twl-usb1v5); + regulator_enable(twl-usb1v8); + regulator_enable(twl-usb3v1); pwr = ~PHY_PWR_PHYPWD; WARN_ON(twl4030_usb_write_verify(twl, PHY_PWR_CTRL, pwr) 0); twl4030_usb_write(twl, PHY_CLK_CTRL, @@ -443,6 +452,9 @@ static void twl4030_phy_power(struct twl } else { pwr |= PHY_PWR_PHYPWD; WARN_ON(twl4030_usb_write_verify(twl, PHY_PWR_CTRL, pwr) 0); + regulator_disable(twl-usb1v5); + regulator_disable(twl-usb1v8); + regulator_disable(twl-usb3v1); } } @@ -480,16 +492,19 @@ static void twl4030_usb_ldo_init(struct /* input to VUSB3V1 LDO is from VBAT, not VBUS */ twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x14, VUSB_DEDICATED1); - /* turn on 3.1V regulator */ - twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x20, VUSB3V1_DEV_GRP); + /* Initialize 3.1V regulator */ + twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB3V1_DEV_GRP); + twl-usb3v1 = regulator_get(twl-dev, usb3v1); twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB3V1_TYPE); - /* turn on 1.5V regulator */ - twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x20, VUSB1V5_DEV_GRP); + /* Initialize 1.5V regulator */ + twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V5_DEV_GRP); + twl-usb1v5 = regulator_get(twl-dev, usb1v5); twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V5_TYPE); - /* turn on 1.8V regulator */ - twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x20, VUSB1V8_DEV_GRP); + /* Initialize 1.8V regulator */ + twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V8_DEV_GRP); + twl-usb1v8 = regulator_get(twl-dev, usb1v8); twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V8_TYPE); /* disable access to power configuration registers */ @@ -688,6 +703,9 @@ static int __exit twl4030_usb_remove(str twl4030_usb_clear_bits(twl, POWER_CTRL, POWER_CTRL_OTG_ENAB); twl4030_phy_power(twl, 0); + regulator_put(twl-usb1v5); + regulator_put(twl-usb1v8); + regulator_put(twl-usb3v1); kfree(twl); -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html