update for gpio PM
author沈睿汀 <srt@rock-chips.com>
Mon, 17 May 2010 07:52:56 +0000 (07:52 +0000)
committer黄涛 <huangtao@rock-chips.com>
Mon, 21 Jun 2010 05:34:55 +0000 (13:34 +0800)
arch/arm/mach-rk2818/gpio.c
arch/arm/mach-rk2818/include/mach/gpio.h

index 6f7682c92a21bd34719dd10e60ebc3d2abff2bce..b225a5349c07dbc6e14dc0d473e0a1ffc7112294 100644 (file)
@@ -31,7 +31,6 @@
 #include <asm/gpio.h>
 
 #define to_rk2818_gpio_chip(c) container_of(c, struct rk2818_gpio_chip, chip)
-#define gpio_irq_set_wake       NULL
 
 struct rk2818_gpio_chip {
        struct gpio_chip        chip;                           /*RK2818Ïà¹ØGPIOº¯Êý²Ù×÷ºÍÂß¼­ÐÅÏ¢*/
@@ -41,6 +40,7 @@ struct rk2818_gpio_chip {
 };
 
 static int gpio_banks;//GPIO×éÊý
+static int gpio_banksInGrp;//num of GPIOS.eg:GPIO0_X or GPIO1_X(X=A\B\C\D)
 /*
  * This lock class tells lockdep that GPIO irqs are in a different
  * category than their parents, so it won't report false recursion.
@@ -87,7 +87,8 @@ static struct rk2818_gpio_chip rk2818gpio_chip[] = {
        RK2818_GPIO_CHIP("C", 6*NUM_GROUP + PIN_BASE, NUM_GROUP),
        RK2818_GPIO_CHIP("D", 7*NUM_GROUP + PIN_BASE, NUM_GROUP),
 };
-
+static u32 wakeups[MAX_GPIO_BANKS];
+static u32 wakeupsDepth[MAX_GPIO_BANKS];
 /*----------------------------------------------------------------------
 Name   : rk2818_gpio_write
 Desc           : ÍùÖ¸¶¨¼Ä´æÆ÷дÈëÖ¸¶¨Öµ
@@ -600,6 +601,67 @@ static inline unsigned  offset_to_mask(unsigned offset)
 {
        return 1ul << (offset% NUM_GROUP);
 }
+static int gpio_irq_set_wake(unsigned irq, unsigned state)
+{      
+       unsigned int pin = irq_to_gpio(irq);
+       unsigned        mask = pin_to_mask(pin);
+       unsigned        bank = (pin - PIN_BASE) / NUM_GROUP;
+
+       if (unlikely(bank >= MAX_GPIO_BANKS))
+               return -EINVAL;
+       
+       if(rk2818gpio_chip[bank].bank->id == RK2818_ID_PIOA)
+       {
+               set_irq_wake(IRQ_NR_GPIO0, state);
+       }
+       else if(rk2818gpio_chip[bank].bank->id == RK2818_ID_PIOE)
+       {
+               set_irq_wake(IRQ_NR_GPIO1, state);
+       }
+       else
+       {
+               return 0;
+       }
+       
+       if (state)
+               wakeups[bank] |= mask;
+       else
+               wakeups[bank] &= ~mask;
+       
+       return 0;
+
+}
+void rk2818_gpio_resume(void)
+{
+       int i;
+       
+       for (i = 0; i < gpio_banks; i+=gpio_banksInGrp) {
+               printk("rk2818_gpio_resume:wakeups[%d]=%d,wakeupsDepth[%d]=%d\n",
+                       i,wakeups[i],i,wakeupsDepth[i]);
+               if (!wakeups[i] && wakeupsDepth[i])
+               {
+                       wakeupsDepth[i] = 0;
+                       clk_enable(rk2818gpio_chip[i].bank->clock);
+               }
+       }
+       return;
+}
+
+void rk2818_gpio_suspend(void)
+{
+       int i;
+
+       for (i = 0; i < gpio_banks; i+=gpio_banksInGrp)  {
+               printk("rk2818_gpio_suspend:wakeups[%d]=%d,wakeupsDepth[%d]=%d\n",
+                       i,wakeups[i],i,wakeupsDepth[i]);
+               if (!wakeups[i] && !wakeupsDepth[i])
+               {
+                       wakeupsDepth[i] = 1;
+                       clk_disable(rk2818gpio_chip[i].bank->clock);
+               }
+       }
+       return;
+}
 
  #if 0
 int  rk2818_set_gpio_input(unsigned pin, int use_pullup)
@@ -842,7 +904,7 @@ static void gpio_irq_handler(unsigned irq, struct irq_desc *desc)
        struct rk2818_gpio_chip *rk2818_gpio;
        unsigned char  __iomem  *gpioRegBase;
        u32             isr;
-       //printk(KERN_INFO "gpio_irq_handler:start");
+
        rk2818_gpio = get_irq_chip_data(irq);
        gpioRegBase = rk2818_gpio->regbase;
 
@@ -898,7 +960,7 @@ static void gpio_irq_handler(unsigned irq, struct irq_desc *desc)
                isr >>= 1;
                gpioToirq = gpio_to_irq(pin);
        }
-       //printk(KERN_INFO "gpio_irq_handler:end");
+
        desc->chip->unmask(irq);
        /* now it may re-trigger */
 }
@@ -1150,19 +1212,26 @@ Return  :
 ----------------------------------------------------------------------*/
 void __init rk2818_gpio_init(struct rk2818_gpio_bank *data, int nr_banks)
 {
-       unsigned                i;
+       unsigned        i;
+       const char clkId[2][6] = {"gpio0","gpio1"};
        struct rk2818_gpio_chip *rk2818_gpio, *last = NULL;
        
        BUG_ON(nr_banks > MAX_GPIO_BANKS);
 
        gpio_banks = nr_banks;
-
+       gpio_banksInGrp = nr_banks/2;
+       
        for (i = 0; i < nr_banks; i++) {
                
                rk2818_gpio = &rk2818gpio_chip[i];
                rk2818_gpio->bank = &data[i];
+               rk2818_gpio->bank->clock = clk_get(NULL,clkId[i/gpio_banksInGrp]);
                rk2818_gpio->regbase = (unsigned char  __iomem *)rk2818_gpio->bank->offset;
 
+               /* enable gpio controller's clock */
+               if(i%gpio_banksInGrp == 0)
+                       clk_enable(rk2818_gpio->bank->clock);
+               
                if(last)
                        last->next = rk2818_gpio;
                last = rk2818_gpio;
index 914e768d157e075ea10872caac15cbdc4a06a3d2..864274db46c2945af7cc2a1a1c87f63ea78bd256 100755 (executable)
@@ -170,7 +170,8 @@ struct rk2818_gpio_bank {
 #ifndef __ASSEMBLY__
 extern void __init rk2818_gpio_init(struct rk2818_gpio_bank *data, int nr_banks);
 extern void __init rk2818_gpio_irq_setup(void);
-
+extern void rk2818_gpio_suspend(void);
+extern void rk2818_gpio_resume(void);
 /*-------------------------------------------------------------------------*/
 
 /* wrappers for "new style" GPIO calls. the old RK2818-specfic ones should