--- /dev/null
+/* 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
+
--- /dev/null
+/* 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
+