Various power management updates and enhancements linux-2.6.34-lpc32x0_v1.07
authorKevin Wells <wellsk40@gmail.com>
Tue, 18 Jan 2011 20:00:30 +0000 (12:00 -0800)
committerKevin Wells <wellsk40@gmail.com>
Tue, 18 Jan 2011 20:00:30 +0000 (12:00 -0800)
Added CPU standby mode for interrupt level wakeup
Added several missing IRQs for wakeup
Fixed some defines
Fixed ethernet support so it goes into a lower power state on sleep
Added suspend/resume for AMBA CLCD for disabling/enabling clocks

Signed-off-by: Martin Chaplet <m.chaplet@kerlink.fr>

arch/arm/mach-lpc32xx/include/mach/irqs.h
arch/arm/mach-lpc32xx/irq.c
arch/arm/mach-lpc32xx/pm.c
drivers/net/lpc_eth.c
drivers/video/amba-clcd.c

index 2667f52..9e3b90d 100644 (file)
@@ -61,7 +61,7 @@
  */
 #define IRQ_LPC32XX_JTAG_COMM_TX       LPC32XX_SIC1_IRQ(1)
 #define IRQ_LPC32XX_JTAG_COMM_RX       LPC32XX_SIC1_IRQ(2)
-#define IRQ_LPC32XX_GPI_11             LPC32XX_SIC1_IRQ(4)
+#define IRQ_LPC32XX_GPI_28             LPC32XX_SIC1_IRQ(4)
 #define IRQ_LPC32XX_TS_P               LPC32XX_SIC1_IRQ(6)
 #define IRQ_LPC32XX_TS_IRQ             LPC32XX_SIC1_IRQ(7)
 #define IRQ_LPC32XX_TS_AUX             LPC32XX_SIC1_IRQ(8)
index 8452395..24110b6 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/irq.h>
 #include <linux/err.h>
 #include <linux/io.h>
+#include <linux/kobject.h>
 
 #include <mach/irqs.h>
 #include <mach/hardware.h>
@@ -72,6 +73,8 @@ struct lpc32xx_event_info {
 
 /*
  * Maps an IRQ number to and event mask and register
+ * All IRQs are event based wakeup IRQs except the UARTs. The UART RX
+ * wakeup is based on the pin state, not the UART IRQ state.
  */
 static const struct lpc32xx_event_info lpc32xx_events[NR_IRQS] = {
        [IRQ_LPC32XX_GPI_08] = {
@@ -118,6 +121,10 @@ static const struct lpc32xx_event_info lpc32xx_events[NR_IRQS] = {
                .event_group = &lpc32xx_event_pin_regs,
                .mask = LPC32XX_CLKPWR_EXTSRC_GPI_06_BIT,
        },
+       [IRQ_LPC32XX_GPI_28] = {
+               .event_group = &lpc32xx_event_pin_regs,
+               .mask = LPC32XX_CLKPWR_EXTSRC_GPI_28_BIT,
+       },
        [IRQ_LPC32XX_GPIO_00] = {
                .event_group = &lpc32xx_event_int_regs,
                .mask = LPC32XX_CLKPWR_INTSRC_GPIO_00_BIT,
@@ -146,6 +153,10 @@ static const struct lpc32xx_event_info lpc32xx_events[NR_IRQS] = {
                .event_group = &lpc32xx_event_int_regs,
                .mask = LPC32XX_CLKPWR_INTSRC_KEY_BIT,
        },
+        [IRQ_LPC32XX_ETHERNET] = {
+                .event_group = &lpc32xx_event_int_regs,
+                .mask = LPC32XX_CLKPWR_INTSRC_MAC_BIT,
+        },
        [IRQ_LPC32XX_USB_OTG_ATX] = {
                .event_group = &lpc32xx_event_int_regs,
                .mask = LPC32XX_CLKPWR_INTSRC_USBATXINT_BIT,
@@ -302,9 +313,18 @@ static int lpc32xx_irq_wake(unsigned int irqno, unsigned int state)
 
                if (state)
                        eventreg |= lpc32xx_events[irqno].mask;
-               else
+               else {
                        eventreg &= ~lpc32xx_events[irqno].mask;
 
+                       /*
+                        * When disabling the wakeup, clear the latched
+                        * event
+                        */
+                       __raw_writel(lpc32xx_events[irqno].mask,
+                               lpc32xx_events[irqno].
+                               event_group->rawstat_reg);
+               }
+
                __raw_writel(eventreg,
                        lpc32xx_events[irqno].event_group->enab_reg);
 
index 733329b..3af3640 100644 (file)
  *  Suspend mode is exited
  */
 
+#include <linux/pm.h>
 #include <linux/suspend.h>
 #include <linux/io.h>
 #include <linux/slab.h>
+#include <linux/delay.h>
 
 #include <asm/cacheflush.h>
 
 static void *iram_swap_area;
 static int (*lpc32xx_suspend_ptr) (void);
 
-/*
- * Both STANDBY and MEM suspend states are handled the same with no
- * loss of CPU or memory state
- */
-static int lpc32xx_pm_enter(suspend_state_t state)
-{
+static inline int lpc32xx_suspend(void)
+ {
        /* Backup a small area of IRAM used for the suspend code */
        memcpy(iram_swap_area, (void *) TEMP_IRAM_AREA,
                lpc32xx_sys_suspend_sz);
@@ -110,8 +108,32 @@ static int lpc32xx_pm_enter(suspend_state_t state)
        return 0;
 }
 
+static int lpc32xx_pm_enter(suspend_state_t state)
+{
+       int ret = 0;
+
+       switch (state)
+       {
+               case PM_SUSPEND_STANDBY:
+                       asm("mcr p15, 0, r0, c7, c0, 4");
+                       break;
+               case PM_SUSPEND_MEM:
+                       ret = lpc32xx_suspend();
+                       break;
+       }
+
+       return ret;
+}
+
+static int lpc32xx_pm_valid(suspend_state_t state)
+{
+       return (state == PM_SUSPEND_STANDBY) ||
+              (state == PM_SUSPEND_MEM);
+}
+
+
 static struct platform_suspend_ops lpc32xx_pm_ops = {
-       .valid  = suspend_valid_only_mem,
+       .valid  = lpc32xx_pm_valid,
        .enter  = lpc32xx_pm_enter,
 };
 
@@ -136,7 +158,6 @@ static int __init lpc32xx_pm_init(void)
        }
 
        lpc32xx_suspend_ptr = (void *) TEMP_IRAM_AREA;
-
        suspend_set_ops(&lpc32xx_pm_ops);
 
        return 0;
index 4cdd979..d99a22b 100644 (file)
@@ -1211,6 +1211,9 @@ static int lpc_net_drv_probe(struct platform_device *pdev)
                ndev->name, phydev->drv->name, dev_name(&phydev->dev),
                phydev->irq);
 
+       device_init_wakeup(&pdev->dev, 1);
+       device_set_wakeup_enable(&pdev->dev, 0);
+
        return 0;
 
 err_out_unregister_netdev:
@@ -1265,11 +1268,20 @@ static int lpc_net_drv_suspend(struct platform_device *pdev,
        struct net_device *ndev = platform_get_drvdata(pdev);
        struct netdata_local *pldat = netdev_priv(ndev);
 
+       if (device_may_wakeup(&pdev->dev))
+               enable_irq_wake(ndev->irq);
+
        if (ndev) {
                if (netif_running(ndev)) {
                        netif_device_detach(ndev);
                        __lpc_net_shutdown(pldat);
                        clk_disable(pldat->clk);
+
+                       /*
+                        * Reset again now clock is disable to be sure
+                        * EMC_MDC is down
+                        */
+                       __lpc_eth_reset(pldat);
                }
        }
 
@@ -1281,6 +1293,9 @@ static int lpc_net_drv_resume(struct platform_device *pdev)
        struct net_device *ndev = platform_get_drvdata(pdev);
        struct netdata_local *pldat;
 
+       if (device_may_wakeup(&pdev->dev))
+               disable_irq_wake(ndev->irq);
+
        if (ndev) {
                if (netif_running(ndev)) {
                        pldat = netdev_priv(ndev);
index afe21e6..171908c 100644 (file)
@@ -521,6 +521,27 @@ static int clcdfb_remove(struct amba_device *dev)
        return 0;
 }
 
+#ifdef CONFIG_PM
+static int clcdfb_suspend(struct amba_device *dev, pm_message_t msg)
+{
+       struct clcd_fb *fb = amba_get_drvdata(dev);
+       
+       clcdfb_disable(fb);
+       return 0;
+}
+
+static int clcdfb_resume(struct amba_device *dev)
+{
+       struct clcd_fb *fb = amba_get_drvdata(dev);
+       
+       clcdfb_enable(fb, fb->clcd_cntl);
+       return 0;
+}
+#else
+#define clcdfb_suspend NULL
+#define clcdfb_resume  NULL
+#endif 
+
 static struct amba_id clcdfb_id_table[] = {
        {
                .id     = 0x00041110,
@@ -535,6 +556,8 @@ static struct amba_driver clcd_driver = {
        },
        .probe          = clcdfb_probe,
        .remove         = clcdfb_remove,
+       .suspend        = clcdfb_suspend,
+       .resume         = clcdfb_resume,
        .id_table       = clcdfb_id_table,
 };