Re: [PATCH 2/2] arm: omap3: am35x: Disable hlt when using Davinci EMAC
On Thu, Jul 19, 2012 at 04:59:06PM -0600, Paul Walmsley wrote: + Ilya Hi Mark Maybe try something like this on top of the patch that disables the MPU DPLL autoidle? I don't know what am35xx_enable_emac_int() is supposed to do. It seems strange to clear the interrupt status bits when one is supposed to enable the interrupts. Maybe Ilya can shed some light on it. Just an FYI for anyone following this thread. Paul has contacted me privately and said to not bother testing this patch. Mark -- 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/2] arm: omap3: am35x: Disable hlt when using Davinci EMAC
On Wed, Jul 18, 2012 at 05:25:16PM -0600, Paul Walmsley wrote: On Wed, 18 Jul 2012, Mark A. Greer wrote: On Tue, Jul 17, 2012 at 09:54:53PM -0600, Paul Walmsley wrote: Want to try something like this? It's your patch but modified to not use disable/enable_hlt(). If it doesn't work in your test case, maybe try uncommenting that second set of deny_idle / allow_idle ... I tested the modified patch (to get it to compile) below. Doh, sorry about that. No worries. It did not work with or without the core_dpll_ck deny_idle/allow_idle commented out. Here's a version with some of the CPUIdle states restricted. Maybe try this one if you're using CPUIdle? I wasn't but I tried this lastest patch with and without CPUidle... If it happens to work, it would also be interesting to know if it works with the CORE DPLL part commented out. ...and, unfortunately, it didnt' work in either case. Mark -- 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/2] arm: omap3: am35x: Disable hlt when using Davinci EMAC
On Thu, 19 Jul 2012, Mark A. Greer wrote: ...and, unfortunately, it didnt' work in either case. OK thanks for the tests. Is the EMAC/MDIO really active and asserting interrupts while all this is happening? Or has that driver called pm_runtime_put*(), and so the EMAC/MDIO isn't waking up? - Paul -- 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/2] arm: omap3: am35x: Disable hlt when using Davinci EMAC
On Thu, Jul 19, 2012 at 01:19:13PM -0600, Paul Walmsley wrote: On Thu, 19 Jul 2012, Mark A. Greer wrote: ...and, unfortunately, it didnt' work in either case. OK thanks for the tests. Is the EMAC/MDIO really active and asserting interrupts while all this is happening? I should be active but I have not way to tell for sure. Or has that driver called pm_runtime_put*(), and so the EMAC/MDIO isn't waking up? pm_runtime_get has definitely been called and pm_runtime_put has definitely _not_ been called. Mark -- 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/2] arm: omap3: am35x: Disable hlt when using Davinci EMAC
+ Ilya Hi Mark Maybe try something like this on top of the patch that disables the MPU DPLL autoidle? I don't know what am35xx_enable_emac_int() is supposed to do. It seems strange to clear the interrupt status bits when one is supposed to enable the interrupts. Maybe Ilya can shed some light on it. - Paul --- arch/arm/mach-omap2/am35xx-emac.c | 21 +++-- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/arch/arm/mach-omap2/am35xx-emac.c b/arch/arm/mach-omap2/am35xx-emac.c index 2c90ac6..231190e 100644 --- a/arch/arm/mach-omap2/am35xx-emac.c +++ b/arch/arm/mach-omap2/am35xx-emac.c @@ -23,23 +23,17 @@ #include control.h #include am35xx-emac.h -static void am35xx_enable_emac_int(void) -{ - u32 v; - - v = omap_ctrl_readl(AM35XX_CONTROL_LVL_INTR_CLEAR); - v |= (AM35XX_CPGMAC_C0_RX_PULSE_CLR | AM35XX_CPGMAC_C0_TX_PULSE_CLR | - AM35XX_CPGMAC_C0_MISC_PULSE_CLR | AM35XX_CPGMAC_C0_RX_THRESH_CLR); - omap_ctrl_writel(v, AM35XX_CONTROL_LVL_INTR_CLEAR); - omap_ctrl_readl(AM35XX_CONTROL_LVL_INTR_CLEAR); /* OCP barrier */ -} - static void am35xx_disable_emac_int(void) { u32 v; - v = omap_ctrl_readl(AM35XX_CONTROL_LVL_INTR_CLEAR); - v |= (AM35XX_CPGMAC_C0_RX_PULSE_CLR | AM35XX_CPGMAC_C0_TX_PULSE_CLR); + /* XXX What about the misc interrupts? */ + /* +* XXX MDIO driver should handle its interrupts through the EMAC +* driver +*/ + v = (AM35XX_CPGMAC_C0_RX_PULSE_CLR | AM35XX_CPGMAC_C0_TX_PULSE_CLR | +AM35XX_CPGMAC_C0_MISC_PULSE_CLR | AM35XX_CPGMAC_C0_RX_THRESH_CLR); omap_ctrl_writel(v, AM35XX_CONTROL_LVL_INTR_CLEAR); omap_ctrl_readl(AM35XX_CONTROL_LVL_INTR_CLEAR); /* OCP barrier */ } @@ -51,7 +45,6 @@ static struct emac_platform_data am35xx_emac_pdata = { .ctrl_ram_size = AM35XX_EMAC_CNTRL_RAM_SIZE, .hw_ram_addr= AM35XX_EMAC_HW_RAM_ADDR, .version= EMAC_VERSION_2, - .interrupt_enable = am35xx_enable_emac_int, .interrupt_disable = am35xx_disable_emac_int, }; -- 1.7.10.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: [PATCH 2/2] arm: omap3: am35x: Disable hlt when using Davinci EMAC
On Tue, Jul 17, 2012 at 09:54:53PM -0600, Paul Walmsley wrote: Hi Hi Paul. From the patch description, it doesn't sound like it's WFI entry that's the problem. The EMAC can assert its interrupt lines to the INTC, since the EMAC is active. If the MPU and CORE powerdomains are ON, then the ARM core should wake up out of WFI. (Unless there's some weird bug; always possible.) Probably the MPU DPLL has to stay running for it all to work, since I think that is activated and deactivated by the PRCM. Maybe the CORE DPLL has to stay running too (but I doubt it). But I'll bet that all the clocks downstream of the DPLLs can be gated. If it works, that would save a lot of energy over the disable_hlt() approach. With disable_hlt(), the ARM interconnect is just going to be burning power waiting for the interrupt to come in. Makes sense. Want to try something like this? It's your patch but modified to not use disable/enable_hlt(). If it doesn't work in your test case, maybe try uncommenting that second set of deny_idle / allow_idle ... I tested the modified patch (to get it to compile) below. It did not work with or without the core_dpll_ck deny_idle/allow_idle commented out. Mark --- arch/arm/mach-omap2/am35xx-emac.c | 56 ++--- arch/arm/mach-omap2/am35xx-emac.h | 13 ++- arch/arm/mach-omap2/board-am3517evm.c |3 +- arch/arm/mach-omap2/board-cm-t3517.c |3 +- 4 files changed, 66 insertions(+), 9 deletions(-) diff --git a/arch/arm/mach-omap2/am35xx-emac.c b/arch/arm/mach-omap2/am35xx-emac.c index 2c90ac6..ed695e8 100644 --- a/arch/arm/mach-omap2/am35xx-emac.c +++ b/arch/arm/mach-omap2/am35xx-emac.c @@ -16,13 +16,50 @@ */ #include linux/err.h +#include linux/clk.h #include linux/davinci_emac.h #include asm/system.h +#include plat/clock.h #include plat/omap_device.h #include mach/am35xx.h #include control.h #include am35xx-emac.h +static struct clk *mpu_dpll_ck, *core_dpll_ck; + +/* + * Default pm_lats for the am35x. + * The net effect of using am35xx_emac_pm_lats[] is that + * pm_idle or CPUidle won't be called while the emac + * interface is open. This is required because the + * EMAC can't wake up PRCM so if the MPU is executing + * a 'wfi' instruction (e.g., from pm_idle or CPUidle), + * it won't break out of it due to emac activity. + */ +static int am35xx_emac_deactivate_func(struct omap_device *od) +{ + mpu_dpll_ck-ops-deny_idle(mpu_dpll_ck); + /* core_dpll_ck-ops-deny_idle(core_dpll_ck); */ + return omap_device_idle_hwmods(od); +} + +static int am35xx_emac_activate_func(struct omap_device *od) +{ + mpu_dpll_ck-ops-allow_idle(mpu_dpll_ck); + /* core_dpll_ck-ops-allow_idle(core_dpll_ck); */ + return omap_device_enable_hwmods(od); +} + +struct omap_device_pm_latency am35xx_emac_pm_lats[] = { + { + .deactivate_func= am35xx_emac_deactivate_func, + .activate_func = am35xx_emac_activate_func, + .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST, + }, +}; + +int am35xx_emac_pm_lats_size = ARRAY_SIZE(am35xx_emac_pm_lats); + static void am35xx_enable_emac_int(void) { u32 v; @@ -58,12 +95,14 @@ static struct emac_platform_data am35xx_emac_pdata = { static struct mdio_platform_data am35xx_mdio_pdata; static int __init omap_davinci_emac_dev_init(struct omap_hwmod *oh, - void *pdata, int pdata_len) +void *pdata, int pdata_len, +struct omap_device_pm_latency *pm_lats, +int pm_lats_size) { struct platform_device *pdev; pdev = omap_device_build(oh-class-name, 0, oh, pdata, pdata_len, -NULL, 0, false); +pm_lats, pm_lats_size, false); if (IS_ERR(pdev)) { WARN(1, Can't build omap_device for %s:%s.\n, oh-class-name, oh-name); @@ -73,7 +112,8 @@ static int __init omap_davinci_emac_dev_init(struct omap_hwmod *oh, return 0; } -void __init am35xx_emac_init(unsigned long mdio_bus_freq, u8 rmii_en) +void __init am35xx_emac_init(unsigned long mdio_bus_freq, u8 rmii_en, + struct omap_device_pm_latency *pm_lats, int pm_lats_size) { struct omap_hwmod *oh; u32 v; @@ -88,7 +128,7 @@ void __init am35xx_emac_init(unsigned long mdio_bus_freq, u8 rmii_en) am35xx_mdio_pdata.bus_freq = mdio_bus_freq; ret = omap_davinci_emac_dev_init(oh, am35xx_mdio_pdata, -sizeof(am35xx_mdio_pdata)); +sizeof(am35xx_mdio_pdata), NULL, 0); if (ret) { pr_err(Could not build davinci_mdio hwmod device\n); return; @@ -103,12 +143,18 @@ void __init am35xx_emac_init(unsigned long
Re: [PATCH 2/2] arm: omap3: am35x: Disable hlt when using Davinci EMAC
On Wed, 18 Jul 2012, Mark A. Greer wrote: On Tue, Jul 17, 2012 at 09:54:53PM -0600, Paul Walmsley wrote: Want to try something like this? It's your patch but modified to not use disable/enable_hlt(). If it doesn't work in your test case, maybe try uncommenting that second set of deny_idle / allow_idle ... I tested the modified patch (to get it to compile) below. Doh, sorry about that. It did not work with or without the core_dpll_ck deny_idle/allow_idle commented out. Here's a version with some of the CPUIdle states restricted. Maybe try this one if you're using CPUIdle? If it happens to work, it would also be interesting to know if it works with the CORE DPLL part commented out. - Paul --- arch/arm/mach-omap2/am35xx-emac.c | 56 ++--- arch/arm/mach-omap2/am35xx-emac.h | 13 ++-- arch/arm/mach-omap2/board-am3517evm.c |3 +- arch/arm/mach-omap2/board-cm-t3517.c |3 +- arch/arm/mach-omap2/cpuidle34xx.c |5 +++ 5 files changed, 71 insertions(+), 9 deletions(-) diff --git a/arch/arm/mach-omap2/am35xx-emac.c b/arch/arm/mach-omap2/am35xx-emac.c index 2c90ac6..6b0edcd 100644 --- a/arch/arm/mach-omap2/am35xx-emac.c +++ b/arch/arm/mach-omap2/am35xx-emac.c @@ -16,13 +16,50 @@ */ #include linux/err.h +#include linux/clk.h #include linux/davinci_emac.h #include asm/system.h +#include plat/clock.h #include plat/omap_device.h #include mach/am35xx.h #include control.h #include am35xx-emac.h +static struct clk *mpu_dpll_ck, *core_dpll_ck; + +/* + * Default pm_lats for the am35x. + * The net effect of using am35xx_emac_pm_lats[] is that + * pm_idle or CPUidle won't be called while the emac + * interface is open. This is required because the + * EMAC can't wake up PRCM so if the MPU is executing + * a 'wfi' instruction (e.g., from pm_idle or CPUidle), + * it won't break out of it due to emac activity. + */ +static int am35xx_emac_deactivate_func(struct omap_device *od) +{ + mpu_dpll_ck-ops-deny_idle(mpu_dpll_ck); + core_dpll_ck-ops-deny_idle(core_dpll_ck); + return omap_device_idle_hwmods(od); +} + +static int am35xx_emac_activate_func(struct omap_device *od) +{ + mpu_dpll_ck-ops-allow_idle(mpu_dpll_ck); + core_dpll_ck-ops-allow_idle(core_dpll_ck); + return omap_device_enable_hwmods(od); +} + +struct omap_device_pm_latency am35xx_emac_pm_lats[] = { + { + .deactivate_func= am35xx_emac_deactivate_func, + .activate_func = am35xx_emac_activate_func, + .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST, + }, +}; + +int am35xx_emac_pm_lats_size = ARRAY_SIZE(am35xx_emac_pm_lats); + static void am35xx_enable_emac_int(void) { u32 v; @@ -58,12 +95,14 @@ static struct emac_platform_data am35xx_emac_pdata = { static struct mdio_platform_data am35xx_mdio_pdata; static int __init omap_davinci_emac_dev_init(struct omap_hwmod *oh, - void *pdata, int pdata_len) +void *pdata, int pdata_len, +struct omap_device_pm_latency *pm_lats, +int pm_lats_size) { struct platform_device *pdev; pdev = omap_device_build(oh-class-name, 0, oh, pdata, pdata_len, -NULL, 0, false); +pm_lats, pm_lats_size, false); if (IS_ERR(pdev)) { WARN(1, Can't build omap_device for %s:%s.\n, oh-class-name, oh-name); @@ -73,7 +112,8 @@ static int __init omap_davinci_emac_dev_init(struct omap_hwmod *oh, return 0; } -void __init am35xx_emac_init(unsigned long mdio_bus_freq, u8 rmii_en) +void __init am35xx_emac_init(unsigned long mdio_bus_freq, u8 rmii_en, + struct omap_device_pm_latency *pm_lats, int pm_lats_size) { struct omap_hwmod *oh; u32 v; @@ -88,7 +128,7 @@ void __init am35xx_emac_init(unsigned long mdio_bus_freq, u8 rmii_en) am35xx_mdio_pdata.bus_freq = mdio_bus_freq; ret = omap_davinci_emac_dev_init(oh, am35xx_mdio_pdata, -sizeof(am35xx_mdio_pdata)); +sizeof(am35xx_mdio_pdata), NULL, 0); if (ret) { pr_err(Could not build davinci_mdio hwmod device\n); return; @@ -103,12 +143,18 @@ void __init am35xx_emac_init(unsigned long mdio_bus_freq, u8 rmii_en) am35xx_emac_pdata.rmii_en = rmii_en; ret = omap_davinci_emac_dev_init(oh, am35xx_emac_pdata, -sizeof(am35xx_emac_pdata)); +sizeof(am35xx_emac_pdata), +pm_lats, pm_lats_size); if (ret) { pr_err(Could not build davinci_emac hwmod device\n); return; } +
Re: [PATCH 2/2] arm: omap3: am35x: Disable hlt when using Davinci EMAC
Hi just a quick comment on this one. On Fri, 11 May 2012, Mark A. Greer wrote: From: Mark A. Greer mgr...@animalcreek.com The am35x family of SoCs has a Davinci EMAC ethernet controller on-chip. Unfortunately, the EMAC is unable to wake the PRCM when there is network activity which leads to a hung or extremely slow system when the MPU has executed a 'wfi' instruction (because of pm_idle or CPUidle). To prevent this, add hooks to the EMAC pm_runtime suspend/resume calls so that hlt is disabled whenever the EMAC is in use. Signed-off-by: Mark A. Greer mgr...@animalcreek.com ... --- a/arch/arm/mach-omap2/am35xx-emac.c +++ b/arch/arm/mach-omap2/am35xx-emac.c @@ -23,6 +23,37 @@ #include control.h #include am35xx-emac.h +/* + * Default pm_lats for the am35x. + * The net effect of using am35xx_emac_pm_lats[] is that + * pm_idle or CPUidle won't be called while the emac + * interface is open. This is required because the + * EMAC can't wake up PRCM so if the MPU is executing + * a 'wfi' instruction (e.g., from pm_idle or CPUidle), + * it won't break out of it due to emac activity. + */ +static int am35xx_emac_deactivate_func(struct omap_device *od) +{ + enable_hlt(); + return omap_device_idle_hwmods(od); +} + +static int am35xx_emac_activate_func(struct omap_device *od) +{ + disable_hlt(); + return omap_device_enable_hwmods(od); +} From the patch description, it doesn't sound like it's WFI entry that's the problem. The EMAC can assert its interrupt lines to the INTC, since the EMAC is active. If the MPU and CORE powerdomains are ON, then the ARM core should wake up out of WFI. (Unless there's some weird bug; always possible.) Probably the MPU DPLL has to stay running for it all to work, since I think that is activated and deactivated by the PRCM. Maybe the CORE DPLL has to stay running too (but I doubt it). But I'll bet that all the clocks downstream of the DPLLs can be gated. If it works, that would save a lot of energy over the disable_hlt() approach. With disable_hlt(), the ARM interconnect is just going to be burning power waiting for the interrupt to come in. Want to try something like this? It's your patch but modified to not use disable/enable_hlt(). If it doesn't work in your test case, maybe try uncommenting that second set of deny_idle / allow_idle ... - Paul --- arch/arm/mach-omap2/am35xx-emac.c | 54 + 1 file changed, 49 insertions(+), 5 deletions(-) diff --git a/arch/arm/mach-omap2/am35xx-emac.c b/arch/arm/mach-omap2/am35xx-emac.c index 2c90ac6..d09ccd2 100644 --- a/arch/arm/mach-omap2/am35xx-emac.c +++ b/arch/arm/mach-omap2/am35xx-emac.c @@ -23,6 +23,41 @@ #include control.h #include am35xx-emac.h +static struct clk *mpu_dpll_ck, *core_dpll_ck; + +/* + * Default pm_lats for the am35x. + * The net effect of using am35xx_emac_pm_lats[] is that + * pm_idle or CPUidle won't be called while the emac + * interface is open. This is required because the + * EMAC can't wake up PRCM so if the MPU is executing + * a 'wfi' instruction (e.g., from pm_idle or CPUidle), + * it won't break out of it due to emac activity. + */ +static int am35xx_emac_deactivate_func(struct omap_device *od) +{ + mpu_dpll_ck-ops-deny_idle(mpu_dpll_ck); + /* core_dpll_ck-ops-deny_idle(core_dpll_ck); */ + return omap_device_idle_hwmods(od); +} + +static int am35xx_emac_activate_func(struct omap_device *od) +{ + mpu_dpll_ck-ops-allow_idle(mpu_dpll_ck); + /* core_dpll_ck-ops-allow_idle(core_dpll_ck); */ + return omap_device_enable_hwmods(od); +} + +struct omap_device_pm_latency am35xx_emac_pm_lats[] = { + { + .deactivate_func= am35xx_emac_deactivate_func, + .activate_func = am35xx_emac_activate_func, + .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST, + }, +}; + +int am35xx_emac_pm_lats_size = ARRAY_SIZE(am35xx_emac_pm_lats); + static void am35xx_enable_emac_int(void) { u32 v; @@ -58,12 +93,14 @@ static struct emac_platform_data am35xx_emac_pdata = { static struct mdio_platform_data am35xx_mdio_pdata; static int __init omap_davinci_emac_dev_init(struct omap_hwmod *oh, - void *pdata, int pdata_len) +void *pdata, int pdata_len, +struct omap_device_pm_latency *pm_lats, +int pm_lats_size) { struct platform_device *pdev; pdev = omap_device_build(oh-class-name, 0, oh, pdata, pdata_len, -NULL, 0, false); +pm_lats, pm_lats_size, false); if (IS_ERR(pdev)) { WARN(1, Can't build omap_device for %s:%s.\n, oh-class-name, oh-name); @@ -73,7 +110,8 @@ static int __init omap_davinci_emac_dev_init(struct omap_hwmod
Re: [PATCH 2/2] arm: omap3: am35x: Disable hlt when using Davinci EMAC
On 05/15/12 00:32, Kevin Hilman wrote: Mark A. Greer mgr...@animalcreek.com writes: On Mon, May 14, 2012 at 11:20:58AM +0300, Igor Grinberg wrote: Hi Mark, Hi Igor. Thanks for the great work! On 05/12/12 00:12, Mark A. Greer wrote: From: Mark A. Greer mgr...@animalcreek.com The am35x family of SoCs has a Davinci EMAC ethernet controller on-chip. Unfortunately, the EMAC is unable to wake the PRCM when there is network activity which leads to a hung or extremely slow system when the MPU has executed a 'wfi' instruction (because of pm_idle or CPUidle). To prevent this, add hooks to the EMAC pm_runtime suspend/resume calls so that hlt is disabled whenever the EMAC is in use. Signed-off-by: Mark A. Greer mgr...@animalcreek.com --- arch/arm/mach-omap2/am35xx-emac.c | 44 + arch/arm/mach-omap2/am35xx-emac.h | 16 +--- arch/arm/mach-omap2/board-am3517evm.c |3 ++- arch/arm/mach-omap2/board-cm-t3517.c |3 ++- 4 files changed, 56 insertions(+), 10 deletions(-) diff --git a/arch/arm/mach-omap2/am35xx-emac.c b/arch/arm/mach-omap2/am35xx-emac.c index 3bb5cb3..22ff968 100644 --- a/arch/arm/mach-omap2/am35xx-emac.c +++ b/arch/arm/mach-omap2/am35xx-emac.c @@ -23,6 +23,37 @@ #include control.h #include am35xx-emac.h +/* + * Default pm_lats for the am35x. + * The net effect of using am35xx_emac_pm_lats[] is that + * pm_idle or CPUidle won't be called while the emac + * interface is open. This is required because the + * EMAC can't wake up PRCM so if the MPU is executing + * a 'wfi' instruction (e.g., from pm_idle or CPUidle), + * it won't break out of it due to emac activity. + */ +static int am35xx_emac_deactivate_func(struct omap_device *od) +{ + enable_hlt(); + return omap_device_idle_hwmods(od); +} + +static int am35xx_emac_activate_func(struct omap_device *od) +{ + disable_hlt(); + return omap_device_enable_hwmods(od); +} + +struct omap_device_pm_latency am35xx_emac_pm_lats[] = { + { + .deactivate_func= am35xx_emac_deactivate_func, + .activate_func = am35xx_emac_activate_func, + .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST, + }, +}; + +int am35xx_emac_pm_lats_size = ARRAY_SIZE(am35xx_emac_pm_lats); + static void am35xx_enable_emac_int(void) { u32 regval; @@ -61,12 +92,13 @@ static struct emac_platform_data am35xx_emac_pdata = { static struct mdio_platform_data am35xx_mdio_pdata; static int __init omap_davinci_emac_dev_init(struct omap_hwmod *oh, - void *pdata, int pdata_len) + void *pdata, int pdata_len, + struct omap_device_pm_latency *pm_lats, int pm_lats_size) { struct platform_device *pdev; pdev = omap_device_build(oh-class-name, 0, oh, pdata, pdata_len, - NULL, 0, false); + pm_lats, pm_lats_size, false); if (IS_ERR(pdev)) { WARN(1, Can't build omap_device for %s:%s.\n, oh-class-name, oh-name); @@ -76,7 +108,8 @@ static int __init omap_davinci_emac_dev_init(struct omap_hwmod *oh, return 0; } -void __init am35xx_emac_init(unsigned long mdio_bus_freq, u8 rmii_en) +void __init am35xx_emac_init(unsigned long mdio_bus_freq, u8 rmii_en, + struct omap_device_pm_latency *pm_lats, int pm_lats_size) { struct omap_hwmod *oh; u32 regval; @@ -91,7 +124,7 @@ void __init am35xx_emac_init(unsigned long mdio_bus_freq, u8 rmii_en) am35xx_mdio_pdata.bus_freq = mdio_bus_freq; ret = omap_davinci_emac_dev_init(oh, am35xx_mdio_pdata, - sizeof(am35xx_mdio_pdata)); + sizeof(am35xx_mdio_pdata), NULL, 0); if (ret) { pr_err(Could not build davinci_mdio hwmod device\n); return; @@ -106,7 +139,8 @@ void __init am35xx_emac_init(unsigned long mdio_bus_freq, u8 rmii_en) am35xx_emac_pdata.rmii_en = rmii_en; ret = omap_davinci_emac_dev_init(oh, am35xx_emac_pdata, - sizeof(am35xx_emac_pdata)); + sizeof(am35xx_emac_pdata), + pm_lats, pm_lats_size); if (ret) { pr_err(Could not build davinci_emac hwmod device\n); return; diff --git a/arch/arm/mach-omap2/am35xx-emac.h b/arch/arm/mach-omap2/am35xx-emac.h index 15c6f9c..7c23808 100644 --- a/arch/arm/mach-omap2/am35xx-emac.h +++ b/arch/arm/mach-omap2/am35xx-emac.h @@ -6,10 +6,20 @@ * published by the Free Software Foundation. */ +#include plat/omap_device.h + #define AM35XX_DEFAULT_MDIO_FREQUENCY 100 -#if defined(CONFIG_TI_DAVINCI_EMAC) || defined(CONFIG_TI_DAVINCI_EMAC_MODULE) -void am35xx_emac_init(unsigned long mdio_bus_freq, u8 rmii_en); +#if IS_ENABLED(CONFIG_TI_DAVINCI_EMAC) +extern struct omap_device_pm_latency
Re: [PATCH 2/2] arm: omap3: am35x: Disable hlt when using Davinci EMAC
On Tue, May 15, 2012 at 03:42:09PM +0300, Igor Grinberg wrote: On 05/15/12 00:32, Kevin Hilman wrote: Mark A. Greer mgr...@animalcreek.com writes: On Mon, May 14, 2012 at 11:20:58AM +0300, Igor Grinberg wrote: Hi Mark, Hi Igor. Thanks for the great work! On 05/12/12 00:12, Mark A. Greer wrote: From: Mark A. Greer mgr...@animalcreek.com The am35x family of SoCs has a Davinci EMAC ethernet controller on-chip. Unfortunately, the EMAC is unable to wake the PRCM when there is network activity which leads to a hung or extremely slow system when the MPU has executed a 'wfi' instruction (because of pm_idle or CPUidle). To prevent this, add hooks to the EMAC pm_runtime suspend/resume calls so that hlt is disabled whenever the EMAC is in use. Signed-off-by: Mark A. Greer mgr...@animalcreek.com --- arch/arm/mach-omap2/am35xx-emac.c | 44 + arch/arm/mach-omap2/am35xx-emac.h | 16 +--- arch/arm/mach-omap2/board-am3517evm.c |3 ++- arch/arm/mach-omap2/board-cm-t3517.c |3 ++- 4 files changed, 56 insertions(+), 10 deletions(-) diff --git a/arch/arm/mach-omap2/am35xx-emac.c b/arch/arm/mach-omap2/am35xx-emac.c index 3bb5cb3..22ff968 100644 --- a/arch/arm/mach-omap2/am35xx-emac.c +++ b/arch/arm/mach-omap2/am35xx-emac.c @@ -23,6 +23,37 @@ #include control.h #include am35xx-emac.h +/* + * Default pm_lats for the am35x. + * The net effect of using am35xx_emac_pm_lats[] is that + * pm_idle or CPUidle won't be called while the emac + * interface is open. This is required because the + * EMAC can't wake up PRCM so if the MPU is executing + * a 'wfi' instruction (e.g., from pm_idle or CPUidle), + * it won't break out of it due to emac activity. + */ +static int am35xx_emac_deactivate_func(struct omap_device *od) +{ +enable_hlt(); +return omap_device_idle_hwmods(od); +} + +static int am35xx_emac_activate_func(struct omap_device *od) +{ +disable_hlt(); +return omap_device_enable_hwmods(od); +} + +struct omap_device_pm_latency am35xx_emac_pm_lats[] = { +{ +.deactivate_func= am35xx_emac_deactivate_func, +.activate_func = am35xx_emac_activate_func, +.flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST, +}, +}; + +int am35xx_emac_pm_lats_size = ARRAY_SIZE(am35xx_emac_pm_lats); + static void am35xx_enable_emac_int(void) { u32 regval; @@ -61,12 +92,13 @@ static struct emac_platform_data am35xx_emac_pdata = { static struct mdio_platform_data am35xx_mdio_pdata; static int __init omap_davinci_emac_dev_init(struct omap_hwmod *oh, -void *pdata, int pdata_len) +void *pdata, int pdata_len, +struct omap_device_pm_latency *pm_lats, int pm_lats_size) { struct platform_device *pdev; pdev = omap_device_build(oh-class-name, 0, oh, pdata, pdata_len, -NULL, 0, false); +pm_lats, pm_lats_size, false); if (IS_ERR(pdev)) { WARN(1, Can't build omap_device for %s:%s.\n, oh-class-name, oh-name); @@ -76,7 +108,8 @@ static int __init omap_davinci_emac_dev_init(struct omap_hwmod *oh, return 0; } -void __init am35xx_emac_init(unsigned long mdio_bus_freq, u8 rmii_en) +void __init am35xx_emac_init(unsigned long mdio_bus_freq, u8 rmii_en, +struct omap_device_pm_latency *pm_lats, int pm_lats_size) { struct omap_hwmod *oh; u32 regval; @@ -91,7 +124,7 @@ void __init am35xx_emac_init(unsigned long mdio_bus_freq, u8 rmii_en) am35xx_mdio_pdata.bus_freq = mdio_bus_freq; ret = omap_davinci_emac_dev_init(oh, am35xx_mdio_pdata, - sizeof(am35xx_mdio_pdata)); + sizeof(am35xx_mdio_pdata), NULL, 0); if (ret) { pr_err(Could not build davinci_mdio hwmod device\n); return; @@ -106,7 +139,8 @@ void __init am35xx_emac_init(unsigned long mdio_bus_freq, u8 rmii_en) am35xx_emac_pdata.rmii_en = rmii_en; ret = omap_davinci_emac_dev_init(oh, am35xx_emac_pdata, - sizeof(am35xx_emac_pdata)); + sizeof(am35xx_emac_pdata), + pm_lats, pm_lats_size); if (ret) { pr_err(Could not build davinci_emac hwmod device\n); return; diff --git a/arch/arm/mach-omap2/am35xx-emac.h b/arch/arm/mach-omap2/am35xx-emac.h index 15c6f9c..7c23808 100644 --- a/arch/arm/mach-omap2/am35xx-emac.h +++
Re: [PATCH 2/2] arm: omap3: am35x: Disable hlt when using Davinci EMAC
Hi Mark, Thanks for the great work! On 05/12/12 00:12, Mark A. Greer wrote: From: Mark A. Greer mgr...@animalcreek.com The am35x family of SoCs has a Davinci EMAC ethernet controller on-chip. Unfortunately, the EMAC is unable to wake the PRCM when there is network activity which leads to a hung or extremely slow system when the MPU has executed a 'wfi' instruction (because of pm_idle or CPUidle). To prevent this, add hooks to the EMAC pm_runtime suspend/resume calls so that hlt is disabled whenever the EMAC is in use. Signed-off-by: Mark A. Greer mgr...@animalcreek.com --- arch/arm/mach-omap2/am35xx-emac.c | 44 + arch/arm/mach-omap2/am35xx-emac.h | 16 +--- arch/arm/mach-omap2/board-am3517evm.c |3 ++- arch/arm/mach-omap2/board-cm-t3517.c |3 ++- 4 files changed, 56 insertions(+), 10 deletions(-) diff --git a/arch/arm/mach-omap2/am35xx-emac.c b/arch/arm/mach-omap2/am35xx-emac.c index 3bb5cb3..22ff968 100644 --- a/arch/arm/mach-omap2/am35xx-emac.c +++ b/arch/arm/mach-omap2/am35xx-emac.c @@ -23,6 +23,37 @@ #include control.h #include am35xx-emac.h +/* + * Default pm_lats for the am35x. + * The net effect of using am35xx_emac_pm_lats[] is that + * pm_idle or CPUidle won't be called while the emac + * interface is open. This is required because the + * EMAC can't wake up PRCM so if the MPU is executing + * a 'wfi' instruction (e.g., from pm_idle or CPUidle), + * it won't break out of it due to emac activity. + */ +static int am35xx_emac_deactivate_func(struct omap_device *od) +{ + enable_hlt(); + return omap_device_idle_hwmods(od); +} + +static int am35xx_emac_activate_func(struct omap_device *od) +{ + disable_hlt(); + return omap_device_enable_hwmods(od); +} + +struct omap_device_pm_latency am35xx_emac_pm_lats[] = { + { + .deactivate_func= am35xx_emac_deactivate_func, + .activate_func = am35xx_emac_activate_func, + .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST, + }, +}; + +int am35xx_emac_pm_lats_size = ARRAY_SIZE(am35xx_emac_pm_lats); + static void am35xx_enable_emac_int(void) { u32 regval; @@ -61,12 +92,13 @@ static struct emac_platform_data am35xx_emac_pdata = { static struct mdio_platform_data am35xx_mdio_pdata; static int __init omap_davinci_emac_dev_init(struct omap_hwmod *oh, - void *pdata, int pdata_len) + void *pdata, int pdata_len, + struct omap_device_pm_latency *pm_lats, int pm_lats_size) { struct platform_device *pdev; pdev = omap_device_build(oh-class-name, 0, oh, pdata, pdata_len, - NULL, 0, false); + pm_lats, pm_lats_size, false); if (IS_ERR(pdev)) { WARN(1, Can't build omap_device for %s:%s.\n, oh-class-name, oh-name); @@ -76,7 +108,8 @@ static int __init omap_davinci_emac_dev_init(struct omap_hwmod *oh, return 0; } -void __init am35xx_emac_init(unsigned long mdio_bus_freq, u8 rmii_en) +void __init am35xx_emac_init(unsigned long mdio_bus_freq, u8 rmii_en, + struct omap_device_pm_latency *pm_lats, int pm_lats_size) { struct omap_hwmod *oh; u32 regval; @@ -91,7 +124,7 @@ void __init am35xx_emac_init(unsigned long mdio_bus_freq, u8 rmii_en) am35xx_mdio_pdata.bus_freq = mdio_bus_freq; ret = omap_davinci_emac_dev_init(oh, am35xx_mdio_pdata, - sizeof(am35xx_mdio_pdata)); + sizeof(am35xx_mdio_pdata), NULL, 0); if (ret) { pr_err(Could not build davinci_mdio hwmod device\n); return; @@ -106,7 +139,8 @@ void __init am35xx_emac_init(unsigned long mdio_bus_freq, u8 rmii_en) am35xx_emac_pdata.rmii_en = rmii_en; ret = omap_davinci_emac_dev_init(oh, am35xx_emac_pdata, - sizeof(am35xx_emac_pdata)); + sizeof(am35xx_emac_pdata), + pm_lats, pm_lats_size); if (ret) { pr_err(Could not build davinci_emac hwmod device\n); return; diff --git a/arch/arm/mach-omap2/am35xx-emac.h b/arch/arm/mach-omap2/am35xx-emac.h index 15c6f9c..7c23808 100644 --- a/arch/arm/mach-omap2/am35xx-emac.h +++ b/arch/arm/mach-omap2/am35xx-emac.h @@ -6,10 +6,20 @@ * published by the Free Software Foundation. */ +#include plat/omap_device.h + #define AM35XX_DEFAULT_MDIO_FREQUENCY100 -#if defined(CONFIG_TI_DAVINCI_EMAC) || defined(CONFIG_TI_DAVINCI_EMAC_MODULE) -void am35xx_emac_init(unsigned long mdio_bus_freq, u8 rmii_en); +#if IS_ENABLED(CONFIG_TI_DAVINCI_EMAC) +extern struct omap_device_pm_latency am35xx_emac_pm_lats[]; +extern int am35xx_emac_pm_lats_size;
Re: [PATCH 2/2] arm: omap3: am35x: Disable hlt when using Davinci EMAC
On Mon, May 14, 2012 at 11:20:58AM +0300, Igor Grinberg wrote: Hi Mark, Hi Igor. Thanks for the great work! On 05/12/12 00:12, Mark A. Greer wrote: From: Mark A. Greer mgr...@animalcreek.com The am35x family of SoCs has a Davinci EMAC ethernet controller on-chip. Unfortunately, the EMAC is unable to wake the PRCM when there is network activity which leads to a hung or extremely slow system when the MPU has executed a 'wfi' instruction (because of pm_idle or CPUidle). To prevent this, add hooks to the EMAC pm_runtime suspend/resume calls so that hlt is disabled whenever the EMAC is in use. Signed-off-by: Mark A. Greer mgr...@animalcreek.com --- arch/arm/mach-omap2/am35xx-emac.c | 44 + arch/arm/mach-omap2/am35xx-emac.h | 16 +--- arch/arm/mach-omap2/board-am3517evm.c |3 ++- arch/arm/mach-omap2/board-cm-t3517.c |3 ++- 4 files changed, 56 insertions(+), 10 deletions(-) diff --git a/arch/arm/mach-omap2/am35xx-emac.c b/arch/arm/mach-omap2/am35xx-emac.c index 3bb5cb3..22ff968 100644 --- a/arch/arm/mach-omap2/am35xx-emac.c +++ b/arch/arm/mach-omap2/am35xx-emac.c @@ -23,6 +23,37 @@ #include control.h #include am35xx-emac.h +/* + * Default pm_lats for the am35x. + * The net effect of using am35xx_emac_pm_lats[] is that + * pm_idle or CPUidle won't be called while the emac + * interface is open. This is required because the + * EMAC can't wake up PRCM so if the MPU is executing + * a 'wfi' instruction (e.g., from pm_idle or CPUidle), + * it won't break out of it due to emac activity. + */ +static int am35xx_emac_deactivate_func(struct omap_device *od) +{ + enable_hlt(); + return omap_device_idle_hwmods(od); +} + +static int am35xx_emac_activate_func(struct omap_device *od) +{ + disable_hlt(); + return omap_device_enable_hwmods(od); +} + +struct omap_device_pm_latency am35xx_emac_pm_lats[] = { + { + .deactivate_func= am35xx_emac_deactivate_func, + .activate_func = am35xx_emac_activate_func, + .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST, + }, +}; + +int am35xx_emac_pm_lats_size = ARRAY_SIZE(am35xx_emac_pm_lats); + static void am35xx_enable_emac_int(void) { u32 regval; @@ -61,12 +92,13 @@ static struct emac_platform_data am35xx_emac_pdata = { static struct mdio_platform_data am35xx_mdio_pdata; static int __init omap_davinci_emac_dev_init(struct omap_hwmod *oh, - void *pdata, int pdata_len) + void *pdata, int pdata_len, + struct omap_device_pm_latency *pm_lats, int pm_lats_size) { struct platform_device *pdev; pdev = omap_device_build(oh-class-name, 0, oh, pdata, pdata_len, - NULL, 0, false); + pm_lats, pm_lats_size, false); if (IS_ERR(pdev)) { WARN(1, Can't build omap_device for %s:%s.\n, oh-class-name, oh-name); @@ -76,7 +108,8 @@ static int __init omap_davinci_emac_dev_init(struct omap_hwmod *oh, return 0; } -void __init am35xx_emac_init(unsigned long mdio_bus_freq, u8 rmii_en) +void __init am35xx_emac_init(unsigned long mdio_bus_freq, u8 rmii_en, + struct omap_device_pm_latency *pm_lats, int pm_lats_size) { struct omap_hwmod *oh; u32 regval; @@ -91,7 +124,7 @@ void __init am35xx_emac_init(unsigned long mdio_bus_freq, u8 rmii_en) am35xx_mdio_pdata.bus_freq = mdio_bus_freq; ret = omap_davinci_emac_dev_init(oh, am35xx_mdio_pdata, -sizeof(am35xx_mdio_pdata)); +sizeof(am35xx_mdio_pdata), NULL, 0); if (ret) { pr_err(Could not build davinci_mdio hwmod device\n); return; @@ -106,7 +139,8 @@ void __init am35xx_emac_init(unsigned long mdio_bus_freq, u8 rmii_en) am35xx_emac_pdata.rmii_en = rmii_en; ret = omap_davinci_emac_dev_init(oh, am35xx_emac_pdata, -sizeof(am35xx_emac_pdata)); +sizeof(am35xx_emac_pdata), +pm_lats, pm_lats_size); if (ret) { pr_err(Could not build davinci_emac hwmod device\n); return; diff --git a/arch/arm/mach-omap2/am35xx-emac.h b/arch/arm/mach-omap2/am35xx-emac.h index 15c6f9c..7c23808 100644 --- a/arch/arm/mach-omap2/am35xx-emac.h +++ b/arch/arm/mach-omap2/am35xx-emac.h @@ -6,10 +6,20 @@ * published by the Free Software Foundation. */ +#include plat/omap_device.h + #define AM35XX_DEFAULT_MDIO_FREQUENCY 100 -#if defined(CONFIG_TI_DAVINCI_EMAC) || defined(CONFIG_TI_DAVINCI_EMAC_MODULE) -void am35xx_emac_init(unsigned long mdio_bus_freq, u8 rmii_en); +#if
Re: [PATCH 2/2] arm: omap3: am35x: Disable hlt when using Davinci EMAC
Mark A. Greer mgr...@animalcreek.com writes: On Mon, May 14, 2012 at 11:20:58AM +0300, Igor Grinberg wrote: Hi Mark, Hi Igor. Thanks for the great work! On 05/12/12 00:12, Mark A. Greer wrote: From: Mark A. Greer mgr...@animalcreek.com The am35x family of SoCs has a Davinci EMAC ethernet controller on-chip. Unfortunately, the EMAC is unable to wake the PRCM when there is network activity which leads to a hung or extremely slow system when the MPU has executed a 'wfi' instruction (because of pm_idle or CPUidle). To prevent this, add hooks to the EMAC pm_runtime suspend/resume calls so that hlt is disabled whenever the EMAC is in use. Signed-off-by: Mark A. Greer mgr...@animalcreek.com --- arch/arm/mach-omap2/am35xx-emac.c | 44 + arch/arm/mach-omap2/am35xx-emac.h | 16 +--- arch/arm/mach-omap2/board-am3517evm.c |3 ++- arch/arm/mach-omap2/board-cm-t3517.c |3 ++- 4 files changed, 56 insertions(+), 10 deletions(-) diff --git a/arch/arm/mach-omap2/am35xx-emac.c b/arch/arm/mach-omap2/am35xx-emac.c index 3bb5cb3..22ff968 100644 --- a/arch/arm/mach-omap2/am35xx-emac.c +++ b/arch/arm/mach-omap2/am35xx-emac.c @@ -23,6 +23,37 @@ #include control.h #include am35xx-emac.h +/* + * Default pm_lats for the am35x. + * The net effect of using am35xx_emac_pm_lats[] is that + * pm_idle or CPUidle won't be called while the emac + * interface is open. This is required because the + * EMAC can't wake up PRCM so if the MPU is executing + * a 'wfi' instruction (e.g., from pm_idle or CPUidle), + * it won't break out of it due to emac activity. + */ +static int am35xx_emac_deactivate_func(struct omap_device *od) +{ + enable_hlt(); + return omap_device_idle_hwmods(od); +} + +static int am35xx_emac_activate_func(struct omap_device *od) +{ + disable_hlt(); + return omap_device_enable_hwmods(od); +} + +struct omap_device_pm_latency am35xx_emac_pm_lats[] = { + { + .deactivate_func= am35xx_emac_deactivate_func, + .activate_func = am35xx_emac_activate_func, + .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST, + }, +}; + +int am35xx_emac_pm_lats_size = ARRAY_SIZE(am35xx_emac_pm_lats); + static void am35xx_enable_emac_int(void) { u32 regval; @@ -61,12 +92,13 @@ static struct emac_platform_data am35xx_emac_pdata = { static struct mdio_platform_data am35xx_mdio_pdata; static int __init omap_davinci_emac_dev_init(struct omap_hwmod *oh, - void *pdata, int pdata_len) + void *pdata, int pdata_len, + struct omap_device_pm_latency *pm_lats, int pm_lats_size) { struct platform_device *pdev; pdev = omap_device_build(oh-class-name, 0, oh, pdata, pdata_len, - NULL, 0, false); + pm_lats, pm_lats_size, false); if (IS_ERR(pdev)) { WARN(1, Can't build omap_device for %s:%s.\n, oh-class-name, oh-name); @@ -76,7 +108,8 @@ static int __init omap_davinci_emac_dev_init(struct omap_hwmod *oh, return 0; } -void __init am35xx_emac_init(unsigned long mdio_bus_freq, u8 rmii_en) +void __init am35xx_emac_init(unsigned long mdio_bus_freq, u8 rmii_en, + struct omap_device_pm_latency *pm_lats, int pm_lats_size) { struct omap_hwmod *oh; u32 regval; @@ -91,7 +124,7 @@ void __init am35xx_emac_init(unsigned long mdio_bus_freq, u8 rmii_en) am35xx_mdio_pdata.bus_freq = mdio_bus_freq; ret = omap_davinci_emac_dev_init(oh, am35xx_mdio_pdata, - sizeof(am35xx_mdio_pdata)); + sizeof(am35xx_mdio_pdata), NULL, 0); if (ret) { pr_err(Could not build davinci_mdio hwmod device\n); return; @@ -106,7 +139,8 @@ void __init am35xx_emac_init(unsigned long mdio_bus_freq, u8 rmii_en) am35xx_emac_pdata.rmii_en = rmii_en; ret = omap_davinci_emac_dev_init(oh, am35xx_emac_pdata, - sizeof(am35xx_emac_pdata)); + sizeof(am35xx_emac_pdata), + pm_lats, pm_lats_size); if (ret) { pr_err(Could not build davinci_emac hwmod device\n); return; diff --git a/arch/arm/mach-omap2/am35xx-emac.h b/arch/arm/mach-omap2/am35xx-emac.h index 15c6f9c..7c23808 100644 --- a/arch/arm/mach-omap2/am35xx-emac.h +++ b/arch/arm/mach-omap2/am35xx-emac.h @@ -6,10 +6,20 @@ * published by the Free Software Foundation. */ +#include plat/omap_device.h + #define AM35XX_DEFAULT_MDIO_FREQUENCY 100 -#if defined(CONFIG_TI_DAVINCI_EMAC) || defined(CONFIG_TI_DAVINCI_EMAC_MODULE) -void am35xx_emac_init(unsigned long mdio_bus_freq, u8 rmii_en); +#if