Re: [PATCH 2/2] arm: omap3: am35x: Disable hlt when using Davinci EMAC

2012-07-20 Thread Mark A. Greer
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

2012-07-19 Thread Mark A. Greer
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

2012-07-19 Thread Paul Walmsley
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

2012-07-19 Thread Mark A. Greer
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

2012-07-19 Thread Paul Walmsley
+ 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

2012-07-18 Thread Mark A. Greer
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

2012-07-18 Thread Paul Walmsley
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

2012-07-17 Thread Paul Walmsley
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

2012-05-15 Thread Igor Grinberg
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

2012-05-15 Thread Mark A. Greer
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

2012-05-14 Thread Igor Grinberg
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

2012-05-14 Thread Mark A. Greer
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

2012-05-14 Thread Kevin Hilman
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