From 9d8ef9b6c95aa424cbb773f58b96c3a531ea934e Mon Sep 17 00:00:00 2001 From: =?utf8?q?=E6=B2=88=E7=9D=BF=E6=B1=80?= Date: Thu, 29 Apr 2010 09:23:23 +0000 Subject: [PATCH] add for gpio --- arch/arm/mach-rk2818/gpio.c | 1240 ++++++++++++++++++++++ arch/arm/mach-rk2818/include/mach/gpio.h | 212 ++++ 2 files changed, 1452 insertions(+) create mode 100644 arch/arm/mach-rk2818/gpio.c create mode 100755 arch/arm/mach-rk2818/include/mach/gpio.h diff --git a/arch/arm/mach-rk2818/gpio.c b/arch/arm/mach-rk2818/gpio.c new file mode 100644 index 000000000000..920c4679be9e --- /dev/null +++ b/arch/arm/mach-rk2818/gpio.c @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#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 index 000000000000..88f0a4cb872b --- /dev/null +++ b/arch/arm/mach-rk2818/include/mach/gpio.h @@ -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 +#include +#include + +#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 +#include /* 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 + -- 2.34.1