add for gpio
author沈睿汀 <srt@rock-chips.com>
Thu, 29 Apr 2010 09:23:23 +0000 (09:23 +0000)
committer黄涛 <huangtao@rock-chips.com>
Mon, 21 Jun 2010 05:34:48 +0000 (13:34 +0800)
arch/arm/mach-rk2818/gpio.c [new file with mode: 0644]
arch/arm/mach-rk2818/include/mach/gpio.h [new file with mode: 0755]

diff --git a/arch/arm/mach-rk2818/gpio.c b/arch/arm/mach-rk2818/gpio.c
new file mode 100644 (file)
index 0000000..920c467
--- /dev/null
@@ -0,0 +1,1240 @@
+/* arch/arm/mach-rk2818/gpio.c
+ *
+ * Copyright (C) 2010 ROCKCHIP, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+#include <linux/clk.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/io.h>
+
+#include <mach/hardware.h>
+#include <mach/gpio.h>
+#include <mach/rk2818_iomap.h>
+#include <mach/iomux.h>
+
+#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º¯Êý²Ù×÷ºÍÂß¼­ÐÅÏ¢*/
+       struct rk2818_gpio_chip *next;          /* Bank sharing same clock */
+       struct rk2818_gpio_bank *bank;          /* Bank definition */
+       unsigned char  __iomem  *regbase;       /* Base of register bank */
+};
+
+static int gpio_banks;//GPIO×éÊý
+/*
+ * This lock class tells lockdep that GPIO irqs are in a different
+ * category than their parents, so it won't report false recursion.
+ */
+static struct lock_class_key gpio_lock_class;
+
+static void rk2818_gpiolib_dbg_show(struct seq_file *s, struct gpio_chip *chip);
+static void rk2818_gpiolib_set(struct gpio_chip *chip, unsigned offset, int val);
+static int rk2818_gpiolib_get(struct gpio_chip *chip, unsigned offset);
+static int rk2818_gpiolib_direction_output(struct gpio_chip *chip,
+                                        unsigned offset, int val);
+static int rk2818_gpiolib_direction_input(struct gpio_chip *chip,
+                                       unsigned offset);
+static int rk2818_gpiolib_PullUpDown(struct gpio_chip *chip, unsigned offset, unsigned value);
+static int rk2818_gpiolib_to_irq(struct gpio_chip *chip,
+                                               unsigned offset);
+/*
+ÉùÃ÷Á˽ṹÌårk2818gpio_chipÊý×飬²¢×¢²áÁËGPIOÏà¹Ø²Ù×÷
+µÄ»Øµ÷º¯ÊýºÍÏà¹ØÂß¼­ÐÅÏ¢¡£
+*/
+#define RK2818_GPIO_CHIP(name, base_gpio, nr_gpio)                     \
+       {                                                               \
+               .chip = {                                               \
+                       .label            = name,                       \
+                       .direction_input  = rk2818_gpiolib_direction_input, \
+                       .direction_output = rk2818_gpiolib_direction_output, \
+                       .get              = rk2818_gpiolib_get,         \
+                       .set              = rk2818_gpiolib_set,         \
+                       .pull_updown  = rk2818_gpiolib_PullUpDown,         \
+                       .dbg_show         = rk2818_gpiolib_dbg_show,    \
+                       .to_irq       = rk2818_gpiolib_to_irq,     \
+                       .base             = base_gpio,                  \
+                       .ngpio            = nr_gpio,                    \
+               },                                                      \
+       }
+
+static struct rk2818_gpio_chip rk2818gpio_chip[] = {
+       RK2818_GPIO_CHIP("A", 0*NUM_GROUP + PIN_BASE, NUM_GROUP),
+       RK2818_GPIO_CHIP("B", 1*NUM_GROUP + PIN_BASE, NUM_GROUP),
+       RK2818_GPIO_CHIP("C", 2*NUM_GROUP + PIN_BASE, NUM_GROUP),
+       RK2818_GPIO_CHIP("D", 3*NUM_GROUP + PIN_BASE, NUM_GROUP),
+       RK2818_GPIO_CHIP("A", 4*NUM_GROUP + PIN_BASE, NUM_GROUP),
+       RK2818_GPIO_CHIP("B", 5*NUM_GROUP + PIN_BASE, NUM_GROUP),
+       RK2818_GPIO_CHIP("C", 6*NUM_GROUP + PIN_BASE, NUM_GROUP),
+       RK2818_GPIO_CHIP("D", 7*NUM_GROUP + PIN_BASE, NUM_GROUP),
+};
+
+/*----------------------------------------------------------------------
+Name   : rk2818_gpio_write
+Desc           : ÍùÖ¸¶¨¼Ä´æÆ÷дÈëÖ¸¶¨Öµ
+Params : ÊäÈë²ÎÊý:
+                               regbase :Ö¸¶¨¼Ä´æÆ÷µÄ»ùµØÖ·
+                               regOff  :Ö¸¶¨¼Ä´æÆ÷µÄÆ«ÒƵØÖ·
+                               val             :Ö¸¶¨Ð´ÈëµÄÊýÖµ                 
+                 Êä³ö²ÎÊý:
+                               ÎÞ
+Return :
+                ÎÞ
+----------------------------------------------------------------------*/
+static inline void rk2818_gpio_write(unsigned char  __iomem    *regbase, unsigned int regOff,unsigned int val)
+{
+       __raw_writel(val,regbase + regOff);
+       return ;
+}
+
+/*----------------------------------------------------------------------
+Name   : rk2818_gpio_read
+Desc           : ¶ÁÈ¡Ö¸¶¨¼Ä´æÆ÷µÄÊýÖµ
+Params : ÊäÈë²ÎÊý:
+                               regbase :Ö¸¶¨¼Ä´æÆ÷µÄ»ùµØÖ·
+                               regOff  :Ö¸¶¨¼Ä´æÆ÷µÄÆ«ÒƵØÖ·                   
+                 Êä³ö²ÎÊý:
+                               ÎÞ
+Return :
+               ¶ÁÈ¡µ½µÄÊýÖµ
+----------------------------------------------------------------------*/
+static inline unsigned int rk2818_gpio_read(unsigned char  __iomem     *regbase, unsigned int regOff)
+{
+       return __raw_readl(regbase + regOff);
+}
+
+/*----------------------------------------------------------------------
+Name   : rk2818_gpio_bitOp
+Desc           : ¶ÔÖ¸¶¨¼Ä´æÆ÷½øÐÐÂß¼­ÔËËã
+Params : ÊäÈë²ÎÊý:
+                               regbase :Ö¸¶¨¼Ä´æÆ÷µÄ»ùµØÖ·
+                               regOff  :Ö¸¶¨¼Ä´æÆ÷µÄÆ«ÒƵØÖ·
+                               mask    :ÆÁ±Îλ
+                               opFlag  :0--½øÐÐÓë0ÔËËã;1--½øÐлò1ÔËËã
+                 Êä³ö²ÎÊý:
+                               ÎÞ
+Return :
+                ÎÞ
+----------------------------------------------------------------------*/
+static inline void rk2818_gpio_bitOp(unsigned char  __iomem    *regbase, unsigned int regOff,unsigned int mask,unsigned char opFlag)
+{
+       unsigned int valTemp = 0;
+       unsigned char  __iomem  *regAddr = regbase + regOff;
+       
+       if(opFlag == 0)//¶Ô¼Ä´æÆ÷ÏàӦλ½øÐÐÓë0²Ù×÷
+       {
+               valTemp = __raw_readl(regAddr);
+               valTemp &= (~mask);
+               //printk(KERN_INFO "rk2818_gpio_bitOp--0:regAddr=%x,valTemp=%x\n",regAddr,valTemp);
+               __raw_writel(valTemp,regAddr);
+       }
+       else if(opFlag == 1)//¶Ô¼Ä´æÆ÷ÏàӦλ½øÐлò1²Ù×÷
+       {
+               valTemp = __raw_readl(regAddr);
+               valTemp |= mask;
+               //printk(KERN_INFO "rk2818_gpio_bitOp--1:regAddr=%x,valTemp=%x\n",regAddr,valTemp);
+               __raw_writel(valTemp,regAddr);
+       }
+
+       return;
+}
+
+/*----------------------------------------------------------------------
+Name   : GPIOSetPinDirection
+Desc           : ÉèÖö˿ڷ½Ïò£¬PA¡¢PEĬÈÏΪDebounce·½Ê½
+Params : ÊäÈë²ÎÊý:
+                               chip            :rk2818µÄÊôÐÔchip£¬Èç&rk2818_gpio->chip
+                               mask    :¼Ä´æÆ÷ÆÁ±Îλ
+                               direction       :ÊäÈëÊä³ö·½Ïò    0--ÊäÈë; 1--Êä³ö                               
+                 Êä³ö²ÎÊý:
+                               ÎÞ
+Return :
+                 0     --- ³É¹¦
+                 -1    --- Ê§°Ü
+----------------------------------------------------------------------*/
+static int GPIOSetPinDirection(struct gpio_chip *chip, unsigned int mask,eGPIOPinDirection_t direction)
+{
+       struct rk2818_gpio_chip *rk2818_gpio = to_rk2818_gpio_chip(chip);
+       unsigned char  __iomem  *gpioRegBase = rk2818_gpio->regbase;
+
+       if(!rk2818_gpio || !gpioRegBase)
+       {
+               return -1;
+       }
+       
+       if(strcmp(rk2818_gpio->chip.label,"A") == 0)
+       {
+               rk2818_gpio_bitOp(gpioRegBase,GPIO_SWPORTA_DDR,mask,direction);
+               rk2818_gpio_bitOp(gpioRegBase,GPIO_DEBOUNCE,mask,1); 
+       }
+       else    if(strcmp(rk2818_gpio->chip.label,"B") == 0)
+       {
+               rk2818_gpio_bitOp(gpioRegBase,GPIO_SWPORTB_DDR,mask,direction);
+       }
+       else    if(strcmp(rk2818_gpio->chip.label,"C") == 0)
+       {
+               rk2818_gpio_bitOp(gpioRegBase,GPIO_SWPORTC_DDR,mask,direction);
+       }
+       else    if(strcmp(rk2818_gpio->chip.label,"D") == 0)
+       {
+               rk2818_gpio_bitOp(gpioRegBase,GPIO_SWPORTD_DDR,mask,direction);
+       }
+       else
+       {
+               return -1;
+       }
+       return 0;
+
+}
+
+/*----------------------------------------------------------------------
+Name   : GPIOSetPinLevel
+Desc           : ÉèÖö˿ڵçƽ
+Params : ÊäÈë²ÎÊý:
+                               chip            :rk2818µÄÊôÐÔchip£¬Èç&rk2818_gpio->chip
+                               mask    :¼Ä´æÆ÷ÆÁ±Îλ
+                               level           :µçƽ    0:low 1:high                                   
+                 Êä³ö²ÎÊý:
+                               ÎÞ
+Return :
+                 0     --- ³É¹¦
+                 -1    --- Ê§°Ü
+----------------------------------------------------------------------*/
+static int GPIOSetPinLevel(struct gpio_chip *chip, unsigned int mask,eGPIOPinLevel_t level)
+{
+       struct rk2818_gpio_chip *rk2818_gpio = to_rk2818_gpio_chip(chip);
+       unsigned char  __iomem  *gpioRegBase = rk2818_gpio->regbase;
+
+       if(!rk2818_gpio || !gpioRegBase)
+       {
+               return -1;
+       }
+       
+       if(strcmp(rk2818_gpio->chip.label,"A") == 0)
+       {
+               rk2818_gpio_bitOp(gpioRegBase,GPIO_SWPORTA_DDR,mask,1);
+               rk2818_gpio_bitOp(gpioRegBase,GPIO_SWPORTA_DR,mask,level);
+       }
+       else    if(strcmp(rk2818_gpio->chip.label,"B") == 0)
+       {
+               rk2818_gpio_bitOp(gpioRegBase,GPIO_SWPORTB_DDR,mask,1);
+               rk2818_gpio_bitOp(gpioRegBase,GPIO_SWPORTB_DR,mask,level);
+       }
+       else    if(strcmp(rk2818_gpio->chip.label,"C") == 0)
+       {
+               rk2818_gpio_bitOp(gpioRegBase,GPIO_SWPORTC_DDR,mask,1);
+               rk2818_gpio_bitOp(gpioRegBase,GPIO_SWPORTC_DR,mask,level);
+       }
+       else    if(strcmp(rk2818_gpio->chip.label,"D") == 0)
+       {
+               rk2818_gpio_bitOp(gpioRegBase,GPIO_SWPORTD_DDR,mask,1);
+               rk2818_gpio_bitOp(gpioRegBase,GPIO_SWPORTD_DR,mask,level);
+       }
+       else
+       {
+               return -1;
+       }
+       return 0;
+}
+
+/*----------------------------------------------------------------------
+Name   : GPIOGetPinLevel
+Desc           : »ñÈ¡¶Ë¿Úµçƽ
+Params : ÊäÈë²ÎÊý:
+                               chip            :rk2818µÄÊôÐÔchip£¬Èç&rk2818_gpio->chip
+                               mask    :¼Ä´æÆ÷ÆÁ±Îλ                           
+                 Êä³ö²ÎÊý:
+                               ÎÞ
+Return :
+                 0     --- µÍµçƽ
+                 1     --- ¸ßµçƽ
+                 -1    --- Ê§°Ü
+----------------------------------------------------------------------*/
+static int GPIOGetPinLevel(struct gpio_chip *chip, unsigned int mask)
+{
+       unsigned int valTemp;
+       struct rk2818_gpio_chip *rk2818_gpio = to_rk2818_gpio_chip(chip);
+       unsigned char  __iomem  *gpioRegBase = rk2818_gpio->regbase;
+
+       if(!rk2818_gpio || !gpioRegBase)
+       {
+               return -1;
+       }
+       
+       if(strcmp(rk2818_gpio->chip.label,"A") == 0)
+       {
+               valTemp = rk2818_gpio_read(gpioRegBase,GPIO_EXT_PORTA);
+       }
+       else    if(strcmp(rk2818_gpio->chip.label,"B") == 0)
+       {
+               valTemp = rk2818_gpio_read(gpioRegBase,GPIO_EXT_PORTB);
+       }
+       else    if(strcmp(rk2818_gpio->chip.label,"C") == 0)
+       {
+               valTemp = rk2818_gpio_read(gpioRegBase,GPIO_EXT_PORTC);
+       }
+       else    if(strcmp(rk2818_gpio->chip.label,"D") == 0)
+       {
+               valTemp = rk2818_gpio_read(gpioRegBase,GPIO_EXT_PORTD);
+       }
+       else
+       {
+               return -1;
+       }
+//printk(KERN_INFO "GPIOGetPinLevel:%s,%x,%x,%x\n",rk2818_gpio->chip.label,rk2818_gpio->regbase,mask,valTemp);
+       return ((valTemp & mask) != 0);
+}
+
+/*----------------------------------------------------------------------
+Name   : GPIOEnableIntr
+Desc           : ÉèÖö˿ڵÄÖжϽţ¬Ö»ÓÐPA¡¢PE¿Ú²Å¿ÉÒÔÖжÏ
+Params : ÊäÈë²ÎÊý:
+                               chip            :rk2818µÄÊôÐÔchip£¬Èç&rk2818_gpio->chip
+                               mask    :¼Ä´æÆ÷ÆÁ±Îλ                           
+                 Êä³ö²ÎÊý:
+                               ÎÞ
+Return :
+                 0     --- ³É¹¦
+                 -1    --- Ê§°Ü
+----------------------------------------------------------------------*/
+static int GPIOEnableIntr(struct gpio_chip *chip, unsigned int mask)
+{
+       struct rk2818_gpio_chip *rk2818_gpio = to_rk2818_gpio_chip(chip);
+       unsigned char  __iomem  *gpioRegBase = rk2818_gpio->regbase;
+
+       if(!rk2818_gpio || !gpioRegBase)
+       {
+               return -1;
+       }
+       
+       rk2818_gpio_bitOp(gpioRegBase,GPIO_INTEN,mask,1);
+       return 0;
+}
+
+/*----------------------------------------------------------------------
+Name   : GPIODisableIntr
+Desc           :  ÉèÖö˿ڲ»ÄÜÖжϣ¬Ö»ÓÐPA¡¢PE²Å¿ÉÒÔÖжÏ
+Params : ÊäÈë²ÎÊý:
+                               chip            :rk2818µÄÊôÐÔchip£¬Èç&rk2818_gpio->chip
+                               mask    :¼Ä´æÆ÷ÆÁ±Îλ                   
+                 Êä³ö²ÎÊý:
+                               ÎÞ
+Return :
+                 0     --- ³É¹¦
+                 -1    --- Ê§°Ü
+----------------------------------------------------------------------*/
+static int GPIODisableIntr(struct gpio_chip *chip, unsigned int mask)
+{
+       struct rk2818_gpio_chip *rk2818_gpio = to_rk2818_gpio_chip(chip);
+       unsigned char  __iomem  *gpioRegBase = rk2818_gpio->regbase;
+
+       if(!rk2818_gpio || !gpioRegBase)
+       {
+               return -1;
+       }
+       
+       rk2818_gpio_bitOp(gpioRegBase,GPIO_INTEN,mask,0);
+       return 0;
+}
+#if 0
+/*----------------------------------------------------------------------
+Name   : GPIOClearIntr
+Desc           : Çå³ýÖжϿڱêÖ¾£¬Ö»ÓÐÔÚ±ßÑØÖжÏʱÓÐЧ£¬µçƽÖжÏÎÞЧ
+Params : ÊäÈë²ÎÊý:
+                               chip            :rk2818µÄÊôÐÔchip£¬Èç&rk2818_gpio->chip
+                               mask    :¼Ä´æÆ÷ÆÁ±Îλ                   
+                 Êä³ö²ÎÊý:
+                               ÎÞ
+Return :
+                 0     --- ³É¹¦
+                 -1    --- Ê§°Ü
+----------------------------------------------------------------------*/
+static int GPIOClearIntr(struct gpio_chip *chip, unsigned int mask)
+{       
+       struct rk2818_gpio_chip *rk2818_gpio = to_rk2818_gpio_chip(chip);
+       unsigned char  __iomem  *gpioRegBase = rk2818_gpio->regbase;
+
+       if(!rk2818_gpio || !gpioRegBase)
+       {
+               return -1;
+       }
+       
+       rk2818_gpio_bitOp(gpioRegBase,GPIO_PORTS_EOI,mask,1);
+       return  0;
+}
+#endif
+/*----------------------------------------------------------------------
+Name   : GPIOInmarkIntr
+Desc           : ÏÈÆÁ±ÎÆäÖеÄij¸öÖжϣ¬ÔÚµçƽÖжÏÖбØÐëÒªÕâÑù×ö£¬·ñÔò»á½Ó×ÅÖжÏ
+Params : ÊäÈë²ÎÊý:
+                               chip            :rk2818µÄÊôÐÔchip£¬Èç&rk2818_gpio->chip
+                               mask    :¼Ä´æÆ÷ÆÁ±Îλ                           
+                 Êä³ö²ÎÊý:
+                               ÎÞ
+Return :
+                 0     --- ³É¹¦
+                 -1    --- Ê§°Ü
+----------------------------------------------------------------------*/
+static int GPIOInmarkIntr(struct gpio_chip *chip, unsigned int mask)
+{
+       struct rk2818_gpio_chip *rk2818_gpio = to_rk2818_gpio_chip(chip);
+       unsigned char  __iomem  *gpioRegBase = rk2818_gpio->regbase;
+
+       if(!rk2818_gpio || !gpioRegBase)
+       {
+               return -1;
+       }
+       
+       rk2818_gpio_bitOp(gpioRegBase,GPIO_INTMASK,mask,1);
+       return 0;
+}
+
+/*----------------------------------------------------------------------
+Name   : GPIOUnInmarkIntr
+Desc           : ²»ÆÁ±Îij¸öÖжϣ¬Õë¶ÔµÄÊǵçƽÖжÏ
+Params : ÊäÈë²ÎÊý:
+                               chip            :rk2818µÄÊôÐÔchip£¬Èç&rk2818_gpio->chip
+                               mask    :¼Ä´æÆ÷ÆÁ±Îλ                           
+                 Êä³ö²ÎÊý:
+                               ÎÞ
+Return :
+                 0     --- ³É¹¦
+                 -1    --- Ê§°Ü
+----------------------------------------------------------------------*/
+static int GPIOUnInmarkIntr(struct gpio_chip *chip, unsigned int mask)
+{
+       struct rk2818_gpio_chip *rk2818_gpio = to_rk2818_gpio_chip(chip);
+       unsigned char  __iomem  *gpioRegBase = rk2818_gpio->regbase;
+
+       if(!rk2818_gpio || !gpioRegBase)
+       {
+               return -1;
+       }
+       
+       rk2818_gpio_bitOp(gpioRegBase,GPIO_INTMASK,mask,0);
+       return 0;
+}
+
+/*----------------------------------------------------------------------
+Name   : GPIOSetIntrType
+Desc           : ÉèÖÃÖжÏÀàÐÍ
+Params : ÊäÈë²ÎÊý:
+                               chip            :rk2818µÄÊôÐÔchip£¬Èç&rk2818_gpio->chip
+                               mask    :¼Ä´æÆ÷ÆÁ±Îλ
+                               IntType :Öжϴ¥·¢ÀàÐÍ                   
+                 Êä³ö²ÎÊý:
+                               ÎÞ
+Return :
+                 0     --- ³É¹¦
+                 -1    --- Ê§°Ü
+----------------------------------------------------------------------*/
+static int GPIOSetIntrType(struct gpio_chip *chip, unsigned int mask, eGPIOIntType_t IntType)
+{
+       struct rk2818_gpio_chip *rk2818_gpio = to_rk2818_gpio_chip(chip);
+       unsigned char  __iomem  *gpioRegBase = rk2818_gpio->regbase;
+
+       
+       if(!rk2818_gpio || !gpioRegBase)
+       {
+               return -1;
+       }
+       
+       switch ( IntType )
+       {
+               case GPIOLevelLow:
+                       rk2818_gpio_bitOp(gpioRegBase,GPIO_INT_POLARITY,mask,0);        
+                       rk2818_gpio_bitOp(gpioRegBase,GPIO_INTTYPE_LEVEL,mask,0);       
+                       break;
+               case GPIOLevelHigh:
+                       rk2818_gpio_bitOp(gpioRegBase,GPIO_INTTYPE_LEVEL,mask,0);       
+                       rk2818_gpio_bitOp(gpioRegBase,GPIO_INT_POLARITY,mask,1);        
+                       break;
+               case GPIOEdgelFalling:
+                       rk2818_gpio_bitOp(gpioRegBase,GPIO_INTTYPE_LEVEL,mask,1);       
+                       rk2818_gpio_bitOp(gpioRegBase,GPIO_INT_POLARITY,mask,0);        
+                       break;
+               case GPIOEdgelRising:
+                       rk2818_gpio_bitOp(gpioRegBase,GPIO_INTTYPE_LEVEL,mask,1);       
+                       rk2818_gpio_bitOp(gpioRegBase,GPIO_INT_POLARITY,mask,1);        
+                       break;
+               default:
+                       return(-1);
+       }
+        return(0);
+}
+
+/*----------------------------------------------------------------------
+Name   : GPIOPullUpDown
+Desc           : ¶ÔÆäÖеĽÅλ½øÐж˿ÚÉÏÀ­»òÏÂÀ­³õʼ»¯
+Params : ÊäÈë²ÎÊý:
+                               chip            :rk2818µÄÊôÐÔchip£¬Èç&rk2818_gpio->chip
+                               offset  :Æ«ÒÆÖµ
+                               GPIOPullUpDown  :0--    Õý³£;1--ÉÏÀ­;2--ÏÂÀ­;3--δ³õʼ»¯                
+                 Êä³ö²ÎÊý:
+                               ÎÞ
+Return :
+                 0     --- ³É¹¦
+                 -1    --- Ê§°Ü
+----------------------------------------------------------------------*/
+static int GPIOPullUpDown(struct gpio_chip *chip, unsigned int offset, eGPIOPullType_t GPIOPullUpDown)
+{
+       unsigned char temp=0;
+       struct rk2818_gpio_chip *rk2818_gpio = to_rk2818_gpio_chip(chip);
+       unsigned char  __iomem *pAPBRegBase = (unsigned char  __iomem *)RK2818_REGFILE_BASE;
+       unsigned int mask1 = 0,mask2 = 0;
+
+       if(!rk2818_gpio || !pAPBRegBase)
+       {
+               return -1;
+       }
+       
+       if(offset >= 8)
+       {
+               return -1;
+       }
+
+       if(rk2818_gpio->bank->id%2 == 1)
+       {
+               temp = 16;
+       }
+       mask1 = 0x03<<(2*offset+temp);
+       mask2 = GPIOPullUpDown <<(2*offset+temp);
+       if(rk2818_gpio->bank->id==AT2818_ID_PIOA || rk2818_gpio->bank->id==AT2818_ID_PIOB)
+       {
+               
+               rk2818_gpio_bitOp(pAPBRegBase,GPIO0_AB_PU_CON,mask1,0);
+               rk2818_gpio_bitOp(pAPBRegBase,GPIO0_AB_PU_CON,mask2,1);
+       }
+       else if(rk2818_gpio->bank->id==AT2818_ID_PIOC || rk2818_gpio->bank->id==AT2818_ID_PIOD)
+       {
+               rk2818_gpio_bitOp(pAPBRegBase,GPIO0_CD_PU_CON,mask1,0);
+               rk2818_gpio_bitOp(pAPBRegBase,GPIO0_CD_PU_CON,mask2,1);
+       }
+       else if(rk2818_gpio->bank->id==AT2818_ID_PIOE || rk2818_gpio->bank->id==AT2818_ID_PIOF)
+       {
+               rk2818_gpio_bitOp(pAPBRegBase,GPIO1_AB_PU_CON,mask1,0);
+               rk2818_gpio_bitOp(pAPBRegBase,GPIO1_AB_PU_CON,mask2,1);
+       }
+       else if(rk2818_gpio->bank->id==AT2818_ID_PIOG|| rk2818_gpio->bank->id==AT2818_ID_PIOH)
+       {
+               rk2818_gpio_bitOp(pAPBRegBase,GPIO1_CD_PU_CON,mask1,0);
+               rk2818_gpio_bitOp(pAPBRegBase,GPIO1_CD_PU_CON,mask2,1);
+       }
+       else
+       {
+               return -1;
+       }
+       return 0;
+}
+
+/*----------------------------------------------------------------------
+Name   : pin_to_gpioChip
+Desc           : ¸ù¾ÝÊäÈëµÄPINÖµËã³ö¶ÔÓ¦µÄchip½á¹¹ÌåÊ×µØÖ·
+Params : ÊäÈë²ÎÊý:
+                               pin             :ÊäÈëµÄPINÖµ                            
+                 Êä³ö²ÎÊý:
+                               ÎÞ
+Return :
+                ·µ»Ø¶ÔÓ¦µÄchip½á¹¹ÌåÊ×µØÖ·£¬Ê§°ÜÔò·µ»ØNULL
+----------------------------------------------------------------------*/
+static inline  struct gpio_chip *pin_to_gpioChip(unsigned pin)
+{
+       if(pin < PIN_BASE)
+               return NULL;
+       
+       pin -= PIN_BASE;
+       pin /= NUM_GROUP;
+       if (likely(pin < gpio_banks))
+               return &(rk2818gpio_chip[pin].chip);
+       return NULL;
+}
+
+/*----------------------------------------------------------------------
+Name   : pin_to_mask
+Desc           : ¸ù¾ÝÊäÈëµÄPINÖµËã³ö¶ÔÓ¦µÄÆÁ±Îλ
+Params : ÊäÈë²ÎÊý:
+                               pin             :ÊäÈëµÄPINÖµ    
+                 Êä³ö²ÎÊý:
+                               ÎÞ
+Return :
+                 ·µ»Ø¶ÔÓ¦µÄÆÁ±Îλֵ£¬0±íʾʧ°Ü
+----------------------------------------------------------------------*/
+static inline unsigned  pin_to_mask(unsigned pin)
+{
+       if(pin < PIN_BASE)
+               return 0;
+       pin -= PIN_BASE;
+       return 1ul << (pin % NUM_GROUP);
+}
+
+/*----------------------------------------------------------------------
+Name   : offset_to_mask
+Desc           : ¸ù¾ÝÆ«ÒÆÁ¿Ëã³ö¶ÔÓ¦µÄÆÁ±Îλֵ
+Params : ÊäÈë²ÎÊý:
+                               offset          :Æ«ÒÆÁ¿                         
+                 Êä³ö²ÎÊý:
+                               ÎÞ
+Return :
+                ·µ»Ø¶ÔÓ¦µÄÆÁ±Îλֵ
+----------------------------------------------------------------------*/
+static inline unsigned  offset_to_mask(unsigned offset)
+{
+       return 1ul << (offset% NUM_GROUP);
+}
+
+ #if 0
+int  rk2818_set_gpio_input(unsigned pin, int use_pullup)
+{
+       struct gpio_chip *chip = pin_to_gpioChip(pin);
+       unsigned        mask = pin_to_mask(pin);
+       unsigned offset = 0;
+       
+       if (!chip || !mask)
+               return -EINVAL;
+       
+       offset = (pin-PIN_BASE) % NUM_GROUP;
+
+       if(GPIOSetPinDirection(chip,mask,GPIO_IN) == 0)
+       {
+               if(use_pullup)
+               {
+                       return GPIOPullUpDown(chip,offset,GPIOPullUp);
+               }
+               else
+               {
+                       return GPIOPullUpDown(chip,offset,GPIOPullDown);
+               }
+       }
+       else
+       {       
+               return -1;
+       }
+}
+
+/*
+ * mux the pin to the gpio controller (instead of "A" or "B" peripheral),
+ * and configure it for an output.
+ */
+int  rk2818_set_gpio_output(unsigned pin, int value)
+{
+       struct gpio_chip *chip = pin_to_gpioChip(pin);
+       unsigned        mask = pin_to_mask(pin);
+
+       if (!chip || !mask)
+               return -EINVAL;
+       
+       if(GPIOSetPinDirection(chip,mask,GPIO_OUT) == 0)
+       {
+               return GPIOSetPinLevel(chip,mask,value);
+       }
+       else
+       {
+               return -1;
+       }
+}
+
+/*
+ * assuming the pin is muxed as a gpio output, set its value.
+ */
+int rk2818_set_gpio_value(unsigned pin, int value)
+{
+       struct gpio_chip *chip = pin_to_gpioChip(pin);
+       unsigned        mask = pin_to_mask(pin);
+
+       if (!chip || !mask)
+               return -EINVAL;
+       
+       GPIOSetPinLevel(chip,mask,value);
+       
+       return 0;
+}
+
+/*
+ * read the pin's value (works even if it's not muxed as a gpio).
+ */
+int rk2818_get_gpio_value(unsigned pin)
+{
+       struct gpio_chip *chip = pin_to_gpioChip(pin);
+       unsigned        mask = pin_to_mask(pin);
+
+       if (!chip || !mask)
+               return -EINVAL;
+       
+       return GPIOGetPinLevel(chip,mask);
+}
+#endif
+/*--------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------
+Name   : gpio_irq_disable
+Desc           : ²»Ê¹ÄÜÖжϣ¬Ö»ÓÐPA¡¢PE²Å¿ÉÒÔÖжÏ
+Params : ÊäÈë²ÎÊý:
+                               irq             :Ö¸¶¨²»Ê¹ÄܵÄIRQ                                
+                 Êä³ö²ÎÊý:
+                               ÎÞ
+Return :
+                 ÎÞ
+----------------------------------------------------------------------*/
+ static void gpio_irq_disable(unsigned irq)
+{
+       unsigned int pin = irq_to_gpio(irq);
+       struct gpio_chip *chip = pin_to_gpioChip(pin);
+       unsigned        mask = pin_to_mask(pin);
+
+       if(chip && mask)
+               GPIODisableIntr(chip,mask);
+       
+       return;
+}
+
+/*----------------------------------------------------------------------
+Name   : gpio_irq_enable
+Desc           : Ê¹ÄÜÖжϣ¬Ö»ÓÐPA¡¢PE²Å¿ÉÒÔÖжÏ
+Params : ÊäÈë²ÎÊý:
+                               irq             :Ö¸¶¨Ê¹ÄܵÄIRQ                                                          
+                 Êä³ö²ÎÊý:
+                               ÎÞ
+Return :
+                 ÎÞ
+----------------------------------------------------------------------*/
+static void gpio_irq_enable(unsigned irq)
+{
+       unsigned int pin = irq_to_gpio(irq);
+       struct gpio_chip *chip = pin_to_gpioChip(pin);
+       unsigned        mask = pin_to_mask(pin);
+
+       if(chip && mask)
+               GPIOEnableIntr(chip,mask);
+       
+       return;
+}
+
+/*----------------------------------------------------------------------
+Name   : gpio_irq_mask
+Desc           : ÆÁ±ÎÖжÏ
+Params : ÊäÈë²ÎÊý:
+                               irq             :Ö¸¶¨ÆÁ±ÎµÄIRQ                                                          
+                 Êä³ö²ÎÊý:
+                               ÎÞ
+Return :
+                 ÎÞ
+----------------------------------------------------------------------*/
+static void gpio_irq_mask(unsigned irq)
+{
+       unsigned int pin = irq_to_gpio(irq);
+       struct gpio_chip *chip = pin_to_gpioChip(pin);
+       unsigned        mask = pin_to_mask(pin);
+
+       if(chip && mask)
+               GPIOInmarkIntr(chip,mask);
+}
+
+/*----------------------------------------------------------------------
+Name   : gpio_irq_unmask
+Desc           : ²»ÆÁ±ÎÖжÏ
+Params : ÊäÈë²ÎÊý:
+                               irq             :Ö¸¶¨²»ÆÁ±ÎµÄIRQ                                                                
+                 Êä³ö²ÎÊý:
+                               ÎÞ
+Return :
+                 ÎÞ
+----------------------------------------------------------------------*/
+static void gpio_irq_unmask(unsigned irq)
+{
+       unsigned int pin = irq_to_gpio(irq);
+       struct gpio_chip *chip = pin_to_gpioChip(pin);
+       unsigned        mask = pin_to_mask(pin);
+
+       if (chip && mask)
+               GPIOUnInmarkIntr(chip,mask);
+}
+/*----------------------------------------------------------------------
+Name   : gpio_irq_type
+Desc           : ÉèÖÃÖжÏÀàÐÍ
+Params : ÊäÈë²ÎÊý:
+                               irq             :Ö¸¶¨µÄIRQ      
+                               type            :Ö¸¶¨µÄÖжÏÀàÐÍ         
+                 Êä³ö²ÎÊý:
+                               ÎÞ
+Return :
+                 0     --- ³É¹¦
+                 -22   --- Ê§°Ü
+----------------------------------------------------------------------*/
+static int gpio_irq_type(unsigned irq, unsigned type)
+{
+       unsigned int pin = irq_to_gpio(irq);
+       struct gpio_chip *chip = pin_to_gpioChip(pin);
+       unsigned        mask = pin_to_mask(pin);
+       
+       if(!chip || !mask)
+               return -EINVAL;
+       //ÉèÖÃΪÖжÏ֮ǰ£¬±ØÐëÏÈÉèÖÃΪÊäÈë״̬
+       GPIOSetPinDirection(chip,mask,GPIO_IN);
+       
+       switch (type) {
+               case IRQ_TYPE_NONE:
+                       break;
+               case IRQ_TYPE_EDGE_RISING:
+                       GPIOSetIntrType(chip,mask,GPIOEdgelRising);
+                       break;
+               case IRQ_TYPE_EDGE_FALLING:
+                       GPIOSetIntrType(chip,mask,GPIOEdgelFalling);
+                       break;
+               case IRQ_TYPE_EDGE_BOTH:
+                       break;
+               case IRQ_TYPE_LEVEL_HIGH:
+                       GPIOSetIntrType(chip,mask,GPIOLevelHigh);
+                       break;
+               case IRQ_TYPE_LEVEL_LOW:
+                       GPIOSetIntrType(chip,mask,GPIOLevelLow);
+                       break;
+               default:
+                       return -EINVAL;
+       }
+       return 0;
+}
+
+static struct irq_chip rk2818gpio_irqchip = {
+       .name           = "RK2818_GPIOIRQ",
+       .enable                 = gpio_irq_enable,
+       .disable                = gpio_irq_disable,
+       .mask           = gpio_irq_mask,
+       .unmask         = gpio_irq_unmask,
+       .set_type               = gpio_irq_type,
+       .set_wake       = gpio_irq_set_wake,
+};
+
+/*----------------------------------------------------------------------
+Name   : gpio_irq_handler
+Desc           : ÖжÏ6»òÖжÏ7µÄ´¦Àíº¯Êý
+Params : ÊäÈë²ÎÊý:
+                               irq             :±»´¥·¢µÄÖжϺÅ6»òÖжϺÅ7
+                               desc            :ÖжϽṹÌå                     
+                 Êä³ö²ÎÊý:
+                               ÎÞ
+Return :
+                 ÎÞ
+----------------------------------------------------------------------*/
+static void gpio_irq_handler(unsigned irq, struct irq_desc *desc)
+{
+       unsigned        pin,gpioToirq=0;
+       struct irq_desc *gpio;
+       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;
+
+       //ÆÁ±ÎÖжÏ6»ò7
+       desc->chip->mask(irq);
+       //¶ÁÈ¡µ±Ç°ÖжÏ״̬£¬¼´²éѯ¾ßÌåÊÇGPIOµÄÄĸöPINÒýÆðµÄÖжÏ
+       isr = rk2818_gpio_read(gpioRegBase,GPIO_INT_STATUS);
+       if (!isr) {
+                       desc->chip->unmask(irq);
+                       return;
+       }
+
+       pin = rk2818_gpio->chip.base;
+       gpioToirq = gpio_to_irq(pin);
+       gpio = &irq_desc[gpioToirq];
+
+       while (isr) {
+               if (isr & 1) {
+                       if (unlikely(gpio->depth)) {
+                               /*
+                                * The core ARM interrupt handler lazily disables IRQs so
+                                * another IRQ must be generated before it actually gets
+                                * here to be disabled on the GPIO controller.
+                                */
+                               gpio_irq_mask(gpioToirq);
+                       }
+                       else
+                       {
+                               unsigned int gpio_Int_Level = 0;
+                               unsigned int mask = pin_to_mask(pin);
+                               if(!mask)
+                                       break;
+                               gpio_Int_Level =  rk2818_gpio_read(gpioRegBase,GPIO_INTTYPE_LEVEL);
+                               if(gpio_Int_Level == 0)//±íʾ´ËÖжÏÀàÐÍÊǵçƽÖжÏ
+                               {
+                                       rk2818_gpio_bitOp(gpioRegBase,GPIO_INTMASK,mask,1);
+                               }
+                               generic_handle_irq(gpioToirq);
+                               
+                               if(gpio_Int_Level)//±íʾ´ËÖжÏÀàÐÍÊDZßÑØÖжÏ
+                               {
+                                       rk2818_gpio_bitOp(gpioRegBase,GPIO_PORTS_EOI,mask,1);
+                               }
+                               else//±íʾ´ËÖжÏÀàÐÍÊǵçƽÖжÏ
+                               {
+                                       rk2818_gpio_bitOp(gpioRegBase,GPIO_INTMASK,mask,0);
+                               }
+                       }
+                               
+               }
+               pin++;
+               gpio++;
+               isr >>= 1;
+               gpioToirq = gpio_to_irq(pin);
+       }
+       //printk(KERN_INFO "gpio_irq_handler:end");
+       desc->chip->unmask(irq);
+       /* now it may re-trigger */
+}
+
+ /*----------------------------------------------------------------------
+Name   : rk2818_gpio_irq_setup
+Desc           : enable GPIO interrupt support.
+Params : ÊäÈë²ÎÊý:
+                               ÎÞ                      
+                 Êä³ö²ÎÊý:
+                               ÎÞ
+Return :
+                 ÎÞ
+----------------------------------------------------------------------*/
+void __init rk2818_gpio_irq_setup(void)
+{
+       unsigned        int     i,j, pin,irq=IRQ_NR_GPIO0;
+       struct rk2818_gpio_chip *this;
+       
+       this = rk2818gpio_chip;
+       pin = NR_AIC_IRQS;
+
+       for(i=0;i<2;i++)
+       {
+               rk2818_gpio_write(this->regbase,GPIO_INTEN,0);
+               for (j = 0; j < 8; j++) 
+               {
+                       lockdep_set_class(&irq_desc[pin+j].lock, &gpio_lock_class);
+                       /*
+                        * Can use the "simple" and not "edge" handler since it's
+                        * shorter, and the AIC handles interrupts sanely.
+                        */
+                       set_irq_chip(pin+j, &rk2818gpio_irqchip);
+                       set_irq_handler(pin+j, handle_simple_irq);
+                       set_irq_flags(pin+j, IRQF_VALID);
+               }
+               if(this->bank->id == AT2818_ID_PIOA)
+               {       
+                       irq = IRQ_NR_GPIO0;
+                       
+               }
+               else if(this->bank->id == AT2818_ID_PIOE)
+               {
+                       irq = IRQ_NR_GPIO1;
+               }
+               set_irq_chip_data(irq, this);
+               set_irq_chained_handler(irq, gpio_irq_handler);
+               this += 4; 
+               pin += 8;
+       }
+       pr_info("rk2818_gpio_irq_setup: %d gpio irqs in %d banks\n", pin - PIN_BASE, gpio_banks);
+
+}
+
+/*----------------------------------------------------------------------
+Name   : rk2818_gpiolib_direction_input
+Desc           : ÉèÖö˿ÚΪÊäÈë
+Params : ÊäÈë²ÎÊý:
+                               chip            :rk2818µÄÊôÐÔchip£¬Èç&rk2818_gpio->chip
+                               offset  :¼Ä´æÆ÷λƫÒÆÁ¿                         
+                 Êä³ö²ÎÊý:
+                               ÎÞ
+Return :
+                 0     --- ³É¹¦
+                 -1    --- Ê§°Ü
+----------------------------------------------------------------------*/
+static int rk2818_gpiolib_direction_input(struct gpio_chip *chip,
+                                       unsigned offset)
+{
+       unsigned        mask = offset_to_mask(offset);
+       
+       return GPIOSetPinDirection(chip,mask,GPIO_IN);
+}
+/*----------------------------------------------------------------------
+Name   : rk2818_gpiolib_direction_output
+Desc           : ÉèÖö˿ÚΪÊä³ö£¬ÇÒÉèÖõçƽ
+Params : ÊäÈë²ÎÊý:
+                               chip            :rk2818µÄÊôÐÔchip£¬Èç&rk2818_gpio->chip
+                               offset  :¼Ä´æÆ÷λƫÒÆÁ¿ 
+                               val             :0--µÍµçƽ;1--¸ßµçƽ
+                 Êä³ö²ÎÊý:
+                               ÎÞ
+Return :
+                 0     --- ³É¹¦
+                 -1    --- Ê§°Ü
+----------------------------------------------------------------------*/
+static int rk2818_gpiolib_direction_output(struct gpio_chip *chip,
+                                        unsigned offset, int val)
+{
+       unsigned        mask = offset_to_mask(offset);
+       
+       if(GPIOSetPinDirection(chip,mask,GPIO_OUT) == 0)
+       {
+               return GPIOSetPinLevel(chip,mask,val);
+       }
+       else
+       {
+               return -1;
+       }
+}
+
+/*----------------------------------------------------------------------
+Name   : rk2818_gpiolib_PullUpDown
+Desc           : ¶ÔÆäÖеĽÅλ½øÐж˿ÚÉÏÀ­»òÏÂÀ­³õʼ»¯
+Params : ÊäÈë²ÎÊý:
+                               chip            :rk2818µÄÊôÐÔchip£¬Èç&rk2818_gpio->chip
+                               offset  :¼Ä´æÆ÷λƫÒÆÖµ
+                               GPIOPullUpDown  :0--    Õý³£;1--ÉÏÀ­;2--ÏÂÀ­;3--δ³õʼ»¯                
+                 Êä³ö²ÎÊý:
+                               ÎÞ
+Return :
+                 0     --- ³É¹¦
+                 -1    --- Ê§°Ü
+----------------------------------------------------------------------*/
+static int rk2818_gpiolib_PullUpDown(struct gpio_chip *chip, unsigned offset, unsigned val)
+{
+       return GPIOPullUpDown(chip, offset, val);
+}
+/*----------------------------------------------------------------------
+Name   : rk2818_gpiolib_get
+Desc           : »ñÈ¡¶Ë¿Úµçƽ
+Params : ÊäÈë²ÎÊý:
+                               chip            :rk2818µÄÊôÐÔchip£¬Èç&rk2818_gpio->chip
+                               offset  :¼Ä´æÆ÷λƫÒÆÖµ 
+                 Êä³ö²ÎÊý:
+                               ÎÞ
+Return :
+                 0     --- µÍµçƽ
+                 1     --- ¸ßµçƽ
+                 -1    --- Ê§°Ü
+----------------------------------------------------------------------*/
+static int rk2818_gpiolib_get(struct gpio_chip *chip, unsigned offset)
+{
+       unsigned        mask = offset_to_mask(offset);
+       
+       return GPIOGetPinLevel(chip,mask);
+}
+
+/*----------------------------------------------------------------------
+Name   : rk2818_gpiolib_set
+Desc           : ÉèÖö˿ڵçƽ
+Params : ÊäÈë²ÎÊý:
+                               chip            :rk2818µÄÊôÐÔchip£¬Èç&rk2818_gpio->chip
+                               offset  :¼Ä´æÆ÷λƫÒÆÖµ                                 
+                 Êä³ö²ÎÊý:
+                               ÎÞ
+Return :
+                ÎÞ
+----------------------------------------------------------------------*/
+static void rk2818_gpiolib_set(struct gpio_chip *chip, unsigned offset, int val)
+{
+       unsigned        mask = offset_to_mask(offset);
+       
+       GPIOSetPinLevel(chip,mask,val);
+       return;
+}
+
+/*----------------------------------------------------------------------
+Name   : rk2818_gpiolib_to_irq
+Desc           : °ÑGPIOתΪIRQ
+Params : ÊäÈë²ÎÊý:
+                               chip            :rk2818µÄÊôÐÔchip£¬Èç&rk2818_gpio->chip
+                               offset  :PINÆ«ÒÆÖµ
+                               level           :µçƽ    0:low 1:high                                   
+                 Êä³ö²ÎÊý:
+                               ÎÞ
+Return :
+                 ÆäËûÖµ        --- ¶ÔÓ¦µÄIRQÖµ
+                 -6    --- Ê§°Ü
+----------------------------------------------------------------------*/
+static int rk2818_gpiolib_to_irq(struct gpio_chip *chip,
+                                               unsigned offset)
+{
+    struct rk2818_gpio_chip *rk2818_gpio = to_rk2818_gpio_chip(chip);
+
+    if(!rk2818_gpio)
+    {
+        return -1;
+    }
+    if(rk2818_gpio->bank->id==AT2818_ID_PIOA)
+    {
+        return offset + NR_AIC_IRQS;
+    }
+    else if(rk2818_gpio->bank->id==AT2818_ID_PIOE)
+    {
+        return offset + NR_AIC_IRQS + NUM_GROUP;
+    }
+    else
+    {
+        return -1;
+    }
+}
+
+/*----------------------------------------------------------------------
+Name   : rk2818_gpiolib_dbg_show
+Desc           : DBG
+Params : ÊäÈë²ÎÊý:     
+                               s               :Îļþ
+                               chip            :rk2818µÄÊôÐÔchip£¬Èç&rk2818_gpio->chip                         
+                 Êä³ö²ÎÊý:
+                               ÎÞ
+Return :
+                ÎÞ
+----------------------------------------------------------------------*/
+static void rk2818_gpiolib_dbg_show(struct seq_file *s, struct gpio_chip *chip)
+{
+
+       int i;
+
+       for (i = 0; i < chip->ngpio; i++) {
+               unsigned pin = chip->base + i;
+               struct gpio_chip *chip = pin_to_gpioChip(pin);
+               unsigned mask = pin_to_mask(pin);
+               const char *gpio_label;
+               
+               if(!chip ||!mask)
+                       return;
+               
+               gpio_label = gpiochip_is_requested(chip, i);
+               if (gpio_label) {
+                       seq_printf(s, "[%s] GPIO%s%d: ",
+                                  gpio_label, chip->label, i);
+                       
+                       if (!chip || !mask)
+                       {
+                               seq_printf(s, "!chip || !mask\t");
+                               return;
+                       }
+                               
+                       GPIOSetPinDirection(chip,mask,GPIO_IN);
+                       seq_printf(s, "pin=%d,level=%d\t", pin,GPIOGetPinLevel(chip,mask));
+                       seq_printf(s, "\t");
+               }
+       }
+
+       return;
+}
+
+ /*----------------------------------------------------------------------
+Name   : rk2818_gpio_init
+Desc           : enable GPIO pin support.
+Params : ÊäÈë²ÎÊý:
+                               data            :rk2818_gpio_bank½á¹¹Ìå
+                               nr_banks        :GPIO×éÊý                               
+                 Êä³ö²ÎÊý:
+                               ÎÞ
+Return :
+                 ÎÞ
+----------------------------------------------------------------------*/
+void __init rk2818_gpio_init(struct rk2818_gpio_bank *data, int nr_banks)
+{
+       unsigned                i;
+       struct rk2818_gpio_chip *rk2818_gpio, *last = NULL;
+       
+       BUG_ON(nr_banks > MAX_GPIO_BANKS);
+
+       gpio_banks = nr_banks;
+
+       for (i = 0; i < nr_banks; i++) {
+               
+               rk2818_gpio = &rk2818gpio_chip[i];
+               rk2818_gpio->bank = &data[i];
+               rk2818_gpio->regbase = (unsigned char  __iomem *)rk2818_gpio->bank->offset;
+
+               if(last)
+                       last->next = rk2818_gpio;
+               last = rk2818_gpio;
+
+               gpiochip_add(&rk2818_gpio->chip);
+       }
+       pr_info("rk2818_gpio_init:nr_banks=%d\n",nr_banks);
+       return;
+}
+
+
+#if 0
+//#ifdef CONFIG_DEBUG_FS
+
+static int rk2818_gpio_show(struct seq_file *s, void *unused)
+{
+       int bank, j;
+       //printk(KERN_INFO "rk2818_gpio_show\n");
+       /* print heading */
+       seq_printf(s, "Pin\t");
+       for (bank = 0; bank < gpio_banks; bank++) {
+               seq_printf(s, "PIO%c\t", 'A' + bank);
+       };
+       seq_printf(s, "\n\n");
+
+       /* print pin status */
+       for (j = 0; j < NUM_GROUP; j++) {
+               seq_printf(s, "%d:\t", j);
+
+               for (bank = 0; bank < gpio_banks; bank++) {
+                       unsigned        pin  = PIN_BASE + (NUM_GROUP * bank) + j;
+                       struct gpio_chip *chip = pin_to_gpioChip(pin);
+                       unsigned        mask = pin_to_mask(pin);
+                       
+                       if (!chip ||!mask)
+                       {
+                               seq_printf(s, "!chip || !mask\t");
+                               //printk(KERN_INFO "rk2818_gpio_show:!chip || !mask\n");
+                               return -1;
+                       }
+                               
+                       GPIOSetPinDirection(chip,mask,GPIO_IN);
+                       seq_printf(s, "pin=%d,level=%d\t", pin,GPIOGetPinLevel(chip,mask));
+                       seq_printf(s, "\t");
+               }
+               seq_printf(s, "\n");
+       }
+
+       return 0;
+}
+
+static int rk2818_gpio_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, rk2818_gpio_show, NULL);
+}
+
+static const struct file_operations rk2818_gpio_operations = {
+       .open           = rk2818_gpio_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
+static int __init rk2818_gpio_debugfs_init(void)
+{
+       /* /sys/kernel/debug/rk2818_gpio */
+       //printk(KERN_INFO "rk2818_gpio_debugfs_init\n");
+
+       (void) debugfs_create_file("rk2818_gpio", S_IFREG | S_IRUGO, NULL, NULL, &rk2818_gpio_operations);
+       return 0;
+}
+postcore_initcall(rk2818_gpio_debugfs_init);
+
+#endif
+
diff --git a/arch/arm/mach-rk2818/include/mach/gpio.h b/arch/arm/mach-rk2818/include/mach/gpio.h
new file mode 100755 (executable)
index 0000000..88f0a4c
--- /dev/null
@@ -0,0 +1,212 @@
+/* arch/arm/mach-rk2818/GPIO.h
+ *
+ * Copyright (C) 2010 ROCKCHIP, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+#ifndef __ARCH_ARM_MACH_RK2818_GPIO_H
+#define __ARCH_ARM_MACH_RK2818_GPIO_H
+
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <asm/irq.h>
+
+#define PIN_BASE                       0//¶¨ÒåRK2818ÄÚ²¿GPIOµÄµÚÒ»¸öPIN¿Ú(¼´GPIO0_A0)ÔÚgpio_descÊý×éµÄµØÖ·
+#define NUM_GROUP                      8// ¶¨ÒåRK2818ÄÚ²¿GPIOÿһ×é×î´óµÄPINÊýÄ¿£¬ÏÖÔÚ¶¨Îª8¸ö£¬¼´GPIOX_Y0~ GPIOX_Y7(ÆäÖÐX=0/1;Y=A/B/C/D)
+#define MAX_GPIO_BANKS         8//¶¨ÒåRK2818ÄÚ²¿GPIO×ܹ²Óм¸×飬ÏÖÔÚ¶¨Îª8×飬¼´GPIO0_A~ GPIO0_D£¬GPIO1_A~ GPIO1_D¡£
+//¶¨ÒåGPIOµÄPIN¿Ú×î´óÊýÄ¿¡£(NUM_GROUP*MAX_GPIO_BANKS)±íʾRK2818µÄÄÚ²¿GPIOµÄPIN¿Ú×î´óÊýÄ¿£»CONFIG_ARCH_EXTEND_GPIOS±íʾÀ©Õ¹IOµÄ×î´óÊýÄ¿¡£
+#define ARCH_NR_GPIOS  (NUM_GROUP*MAX_GPIO_BANKS) + CONFIG_ARCH_EXTEND_GPIOS
+typedef enum eGPIOPinLevel
+{
+       GPIO_LOW=0,
+       GPIO_HIGH
+}eGPIOPinLevel_t;
+
+typedef enum eGPIOPinDirection
+{
+       GPIO_IN=0,
+       GPIO_OUT
+}eGPIOPinDirection_t;
+typedef enum GPIOPullType {
+       GPIONormal,
+       GPIOPullUp,
+       GPIOPullDown,
+       GPIONOInit
+}eGPIOPullType_t;
+
+typedef enum GPIOIntType {
+       GPIOLevelLow=0,
+       GPIOLevelHigh,   
+       GPIOEdgelFalling,
+       GPIOEdgelRising
+}eGPIOIntType_t;
+//GPIO Registers
+
+struct rk2818_gpio_bank {
+       unsigned short id;                      //GPIO¼Ä´æÆ÷×éµÄIDʶ±ðºÅ
+       unsigned long offset;           //GPIO0»òGPIO1µÄ»ùµØÖ·
+       struct clk *clock;              /* associated clock */
+};
+//¶¨ÒåGPIOÏà¹Ø¼Ä´æÆ÷Æ«ÒƵØÖ·
+#define        GPIO_SWPORTA_DR         0x00
+#define        GPIO_SWPORTA_DDR        0x04
+
+#define        GPIO_SWPORTB_DR         0x0c
+#define        GPIO_SWPORTB_DDR        0x10
+
+#define        GPIO_SWPORTC_DR         0x18
+#define        GPIO_SWPORTC_DDR        0x1c
+
+#define        GPIO_SWPORTD_DR         0x24
+#define        GPIO_SWPORTD_DDR        0x28
+
+#define        GPIO_INTEN                      0x30
+#define        GPIO_INTMASK                    0x34
+#define        GPIO_INTTYPE_LEVEL      0x38
+#define        GPIO_INT_POLARITY       0x3c
+#define        GPIO_INT_STATUS                 0x40
+#define        GPIO_INT_RAWSTATUS      0x44
+#define        GPIO_DEBOUNCE           0x48
+#define        GPIO_PORTS_EOI          0x4c
+#define        GPIO_EXT_PORTA                  0x50
+#define        GPIO_EXT_PORTB          0x54
+#define        GPIO_EXT_PORTC                  0x58
+#define        GPIO_EXT_PORTD          0x5c
+#define        GPIO_LS_SYNC                    0x60
+
+#define AT2818_ID_PIOA 0
+#define AT2818_ID_PIOB 1
+#define AT2818_ID_PIOC 2
+#define AT2818_ID_PIOD 3
+#define AT2818_ID_PIOE 4
+#define AT2818_ID_PIOF 5
+#define AT2818_ID_PIOG 6
+#define AT2818_ID_PIOH 7
+/* these pin numbers double as IRQ numbers, like RK2818xxx_ID_* values */
+
+#define        RK2818_PIN_PA0          (PIN_BASE + 0*NUM_GROUP + 0)
+#define        RK2818_PIN_PA1          (PIN_BASE + 0*NUM_GROUP + 1)
+#define        RK2818_PIN_PA2          (PIN_BASE + 0*NUM_GROUP + 2)
+#define        RK2818_PIN_PA3          (PIN_BASE + 0*NUM_GROUP + 3)
+#define        RK2818_PIN_PA4          (PIN_BASE + 0*NUM_GROUP + 4)
+#define        RK2818_PIN_PA5          (PIN_BASE + 0*NUM_GROUP + 5)
+#define        RK2818_PIN_PA6          (PIN_BASE + 0*NUM_GROUP + 6)
+#define        RK2818_PIN_PA7          (PIN_BASE + 0*NUM_GROUP + 7)
+
+
+#define        RK2818_PIN_PB0          (PIN_BASE + 1*NUM_GROUP + 0)
+#define        RK2818_PIN_PB1          (PIN_BASE + 1*NUM_GROUP + 1)
+#define        RK2818_PIN_PB2          (PIN_BASE + 1*NUM_GROUP + 2)
+#define        RK2818_PIN_PB3          (PIN_BASE + 1*NUM_GROUP + 3)
+#define        RK2818_PIN_PB4          (PIN_BASE + 1*NUM_GROUP + 4)
+#define        RK2818_PIN_PB5          (PIN_BASE + 1*NUM_GROUP + 5)
+#define        RK2818_PIN_PB6          (PIN_BASE + 1*NUM_GROUP + 6)
+#define        RK2818_PIN_PB7          (PIN_BASE + 1*NUM_GROUP + 7)
+
+#define        RK2818_PIN_PC0          (PIN_BASE + 2*NUM_GROUP + 0)
+#define        RK2818_PIN_PC1          (PIN_BASE + 2*NUM_GROUP + 1)
+#define        RK2818_PIN_PC2          (PIN_BASE + 2*NUM_GROUP + 2)
+#define        RK2818_PIN_PC3          (PIN_BASE + 2*NUM_GROUP + 3)
+#define        RK2818_PIN_PC4          (PIN_BASE + 2*NUM_GROUP + 4)
+#define        RK2818_PIN_PC5          (PIN_BASE + 2*NUM_GROUP + 5)
+#define        RK2818_PIN_PC6          (PIN_BASE + 2*NUM_GROUP + 6)
+#define        RK2818_PIN_PC7          (PIN_BASE + 2*NUM_GROUP + 7)
+
+#define        RK2818_PIN_PD0  (PIN_BASE + 3*NUM_GROUP + 0)
+#define        RK2818_PIN_PD1  (PIN_BASE + 3*NUM_GROUP + 1)
+#define        RK2818_PIN_PD2  (PIN_BASE + 3*NUM_GROUP + 2)
+#define        RK2818_PIN_PD3  (PIN_BASE + 3*NUM_GROUP + 3)
+#define        RK2818_PIN_PD4  (PIN_BASE + 3*NUM_GROUP + 4)
+#define        RK2818_PIN_PD5  (PIN_BASE + 3*NUM_GROUP + 5)
+#define        RK2818_PIN_PD6  (PIN_BASE + 3*NUM_GROUP + 6)
+#define        RK2818_PIN_PD7  (PIN_BASE + 3*NUM_GROUP + 7)
+
+#define        RK2818_PIN_PE0          (PIN_BASE + 4*NUM_GROUP + 0)
+#define        RK2818_PIN_PE1          (PIN_BASE + 4*NUM_GROUP + 1)
+#define        RK2818_PIN_PE2          (PIN_BASE + 4*NUM_GROUP + 2)
+#define        RK2818_PIN_PE3          (PIN_BASE + 4*NUM_GROUP + 3)
+#define        RK2818_PIN_PE4          (PIN_BASE + 4*NUM_GROUP + 4)
+#define        RK2818_PIN_PE5          (PIN_BASE + 4*NUM_GROUP + 5)
+#define        RK2818_PIN_PE6          (PIN_BASE + 4*NUM_GROUP + 6)
+#define        RK2818_PIN_PE7          (PIN_BASE + 4*NUM_GROUP + 7)
+
+#define        RK2818_PIN_PF0          (PIN_BASE + 5*NUM_GROUP + 0)
+#define        RK2818_PIN_PF1          (PIN_BASE + 5*NUM_GROUP + 1)
+#define        RK2818_PIN_PF2          (PIN_BASE + 5*NUM_GROUP + 2)
+#define        RK2818_PIN_PF3          (PIN_BASE + 5*NUM_GROUP + 3)
+#define        RK2818_PIN_PF4          (PIN_BASE + 5*NUM_GROUP + 4)
+#define        RK2818_PIN_PF5          (PIN_BASE + 5*NUM_GROUP + 5)
+#define        RK2818_PIN_PF6          (PIN_BASE + 5*NUM_GROUP + 6)
+#define        RK2818_PIN_PF7          (PIN_BASE + 5*NUM_GROUP + 7)
+
+
+#define        RK2818_PIN_PG0  (PIN_BASE + 6*NUM_GROUP + 0)
+#define        RK2818_PIN_PG1  (PIN_BASE + 6*NUM_GROUP + 1)
+#define        RK2818_PIN_PG2  (PIN_BASE + 6*NUM_GROUP + 2)
+#define        RK2818_PIN_PG3  (PIN_BASE + 6*NUM_GROUP + 3)
+#define        RK2818_PIN_PG4  (PIN_BASE + 6*NUM_GROUP + 4)
+#define        RK2818_PIN_PG5  (PIN_BASE + 6*NUM_GROUP + 5)
+#define        RK2818_PIN_PG6  (PIN_BASE + 6*NUM_GROUP + 6)
+#define        RK2818_PIN_PG7  (PIN_BASE + 6*NUM_GROUP + 7)
+
+#define        RK2818_PIN_PH0  (PIN_BASE + 7*NUM_GROUP + 0)
+#define        RK2818_PIN_PH1  (PIN_BASE + 7*NUM_GROUP + 1)
+#define        RK2818_PIN_PH2  (PIN_BASE + 7*NUM_GROUP + 2)
+#define        RK2818_PIN_PH3  (PIN_BASE + 7*NUM_GROUP + 3)
+#define        RK2818_PIN_PH4  (PIN_BASE + 7*NUM_GROUP + 4)
+#define        RK2818_PIN_PH5  (PIN_BASE + 7*NUM_GROUP + 5)
+#define        RK2818_PIN_PH6  (PIN_BASE + 7*NUM_GROUP + 6)
+#define        RK2818_PIN_PH7  (PIN_BASE + 7*NUM_GROUP + 7)
+
+#ifndef __ASSEMBLY__
+extern void __init rk2818_gpio_init(struct rk2818_gpio_bank *data, int nr_banks);
+extern void __init rk2818_gpio_irq_setup(void);
+
+/*-------------------------------------------------------------------------*/
+
+/* wrappers for "new style" GPIO calls. the old RK2818-specfic ones should
+ * eventually be removed (along with this errno.h inclusion), and the
+ * gpio request/free calls should probably be implemented.
+ */
+
+#include <asm/errno.h>
+#include <asm-generic/gpio.h>          /* cansleep wrappers */
+
+#define gpio_get_value __gpio_get_value
+#define gpio_set_value __gpio_set_value
+#define gpio_cansleep  __gpio_cansleep
+
+static inline int gpio_to_irq(unsigned gpio)
+{
+       return __gpio_to_irq(gpio);
+}
+
+static inline int irq_to_gpio(unsigned irq)
+{
+       if((irq - __gpio_to_irq(RK2818_PIN_PA0)) < NUM_GROUP)
+    {
+        return (RK2818_PIN_PA0 + (irq - __gpio_to_irq(RK2818_PIN_PA0)));
+    } 
+    else if((irq - __gpio_to_irq(RK2818_PIN_PA0)) < 2*NUM_GROUP)
+    {
+        return (RK2818_PIN_PE0 + (irq - __gpio_to_irq(RK2818_PIN_PE0)));
+    }
+    else
+    {
+        return -ENXIO;
+    }        
+}
+
+#endif /* __ASSEMBLY__ */
+
+#endif
+