rk30:add gpio support
authorlw <lw@rock-chips.com>
Tue, 7 Feb 2012 06:15:09 +0000 (14:15 +0800)
committerlw <lw@rock-chips.com>
Tue, 7 Feb 2012 06:15:09 +0000 (14:15 +0800)
arch/arm/mach-rk30/common.c
arch/arm/mach-rk30/include/mach/gpio.h
drivers/gpio/Makefile
drivers/gpio/gpio-rk30.c [new file with mode: 0755]

index d52e55922d723912e5064a9647924158c98cc93c..3ec0c2d558b7a0993d17cb5978c0bd7c31b1c613 100755 (executable)
@@ -13,6 +13,7 @@
 void __init rk30_init_irq(void)
 {
        gic_init(0, IRQ_LOCALTIMER, RK30_GICD_BASE, RK30_GICC_BASE);
+       rk30_gpio_init();
 }
 
 void __init rk30_map_io(void)
index fb35bf93e53a1c4b6eec6e2bae9d192c0ed45a19..ea9390c4d0cc21492e9c02304344a0fe90708aa7 100644 (file)
@@ -2,9 +2,429 @@
 #define __MACH_GPIO_H
 
 #include <mach/irqs.h>
+typedef enum eGPIOPinLevel
+{
+       GPIO_LOW=0,
+       GPIO_HIGH
+}eGPIOPinLevel_t;
+
+typedef enum eGPIOPinDirection
+{
+       GPIO_IN=0,
+       GPIO_OUT
+}eGPIOPinDirection_t;
+
+typedef enum GPIOPullType {
+       PullDisable = 0,
+       PullEnable,
+       GPIONormal,  //PullEnable, please do not use it
+       GPIOPullUp,     //PullEnable, please do not use it
+       GPIOPullDown,//PullEnable, please do not use it
+       GPIONOInit,//PullEnable, please do not use it
+}eGPIOPullType_t;
+
+typedef enum GPIOIntType {
+       GPIOLevelLow=0,
+       GPIOLevelHigh,   
+       GPIOEdgelFalling,
+       GPIOEdgelRising
+}eGPIOIntType_t;
+
+//¶¨ÒåGPIOÏà¹Ø¼Ä´æÆ÷Æ«ÒƵØÖ·
+#define        GPIO_SWPORT_DR          0x00
+#define        GPIO_SWPORT_DDR         0x04
+#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_PORT           0x50
+#define        GPIO_LS_SYNC            0x60
+
+#define RK30_ID_GPIO0                  0
+#define RK30_ID_GPIO1                  1
+#define RK30_ID_GPIO2                  2
+#define RK30_ID_GPIO3                  3
+#define RK30_ID_GPIO4                  4
+#define RK30_ID_GPIO5                  5
+
+#define NUM_GROUP                              32
+#define MAX_BANK                               7
+
+#define PIN_BASE                               NR_GIC_IRQS
+
+#define RK30_TOTOL_GPIO_NUM    (NUM_GROUP*MAX_BANK)
+
+#define SPI_FPGA_EXPANDER_BASE (PIN_BASE+RK30_TOTOL_GPIO_NUM)
+
+#if defined (CONFIG_SPI_FPGA_GPIO)
+#define GPIO_EXPANDER_BASE     (PIN_BASE+RK30_TOTOL_GPIO_NUM+CONFIG_SPI_FPGA_GPIO_NUM)
+#else
+#define GPIO_EXPANDER_BASE     (PIN_BASE+RK30_TOTOL_GPIO_NUM)
+#endif
+
+#if defined(CONFIG_IOEXTEND_TCA6424)
+#define TCA6424_TOTOL_GPIO_NUM 24
+#define TCA6424_TOTOL_GPIO_IRQ_NUM     24
+#define TCA6424_GPIO_EXPANDER_BASE     GPIO_EXPANDER_BASE
+#else
+#define TCA6424_TOTOL_GPIO_NUM 0
+#define TCA6424_TOTOL_GPIO_IRQ_NUM     0
+#endif
+
+#if defined(CONFIG_GPIO_WM831X)
+#define WM831X_TOTOL_GPIO_NUM          12
+#define WM831X_GPIO_EXPANDER_BASE      (GPIO_EXPANDER_BASE+TCA6424_TOTOL_GPIO_NUM)
+#else
+#define WM831X_TOTOL_GPIO_NUM  0
+#define WM831X_GPIO_EXPANDER_BASE      (GPIO_EXPANDER_BASE+TCA6424_TOTOL_GPIO_NUM)
+#endif
+
+#if defined (CONFIG_GPIO_WM8994)
+#define CONFIG_GPIO_WM8994_NUM 11
+#define WM8994_GPIO_EXPANDER_BASE (GPIO_EXPANDER_BASE+WM831X_TOTOL_GPIO_NUM)
+#else
+#define CONFIG_GPIO_WM8994_NUM 0
+#endif
+
+//¶¨ÒåGPIOµÄPIN¿Ú×î´óÊýÄ¿¡£CONFIG_SPI_FPGA_GPIO_NUM±íʾFPGAµÄPIN½ÅÊý¡£
+#define ARCH_NR_GPIOS  (PIN_BASE + RK30_TOTOL_GPIO_NUM + TCA6424_TOTOL_GPIO_NUM + WM831X_TOTOL_GPIO_NUM + CONFIG_SPI_FPGA_GPIO_NUM+CONFIG_GPIO_WM8994_NUM)
+
+
+#define        RK30_PIN0_PA0           (0*NUM_GROUP + PIN_BASE + 0)
+#define        RK30_PIN0_PA1           (0*NUM_GROUP + PIN_BASE + 1)
+#define        RK30_PIN0_PA2           (0*NUM_GROUP + PIN_BASE + 2)
+#define        RK30_PIN0_PA3           (0*NUM_GROUP + PIN_BASE + 3)
+#define        RK30_PIN0_PA4           (0*NUM_GROUP + PIN_BASE + 4)
+#define        RK30_PIN0_PA5           (0*NUM_GROUP + PIN_BASE + 5)
+#define        RK30_PIN0_PA6           (0*NUM_GROUP + PIN_BASE + 6)
+#define        RK30_PIN0_PA7           (0*NUM_GROUP + PIN_BASE + 7)
+#define        RK30_PIN0_PB0           (0*NUM_GROUP + PIN_BASE + 8)
+#define        RK30_PIN0_PB1           (0*NUM_GROUP + PIN_BASE + 9)
+#define        RK30_PIN0_PB2           (0*NUM_GROUP + PIN_BASE + 10)
+#define        RK30_PIN0_PB3           (0*NUM_GROUP + PIN_BASE + 11)
+#define        RK30_PIN0_PB4           (0*NUM_GROUP + PIN_BASE + 12)
+#define        RK30_PIN0_PB5           (0*NUM_GROUP + PIN_BASE + 13)
+#define        RK30_PIN0_PB6           (0*NUM_GROUP + PIN_BASE + 14)
+#define        RK30_PIN0_PB7           (0*NUM_GROUP + PIN_BASE + 15)
+#define        RK30_PIN0_PC0           (0*NUM_GROUP + PIN_BASE + 16)
+#define        RK30_PIN0_PC1           (0*NUM_GROUP + PIN_BASE + 17)
+#define        RK30_PIN0_PC2           (0*NUM_GROUP + PIN_BASE + 18)
+#define        RK30_PIN0_PC3           (0*NUM_GROUP + PIN_BASE + 19)
+#define        RK30_PIN0_PC4           (0*NUM_GROUP + PIN_BASE + 20)
+#define        RK30_PIN0_PC5           (0*NUM_GROUP + PIN_BASE + 21)
+#define        RK30_PIN0_PC6           (0*NUM_GROUP + PIN_BASE + 22)
+#define        RK30_PIN0_PC7           (0*NUM_GROUP + PIN_BASE + 23)
+#define        RK30_PIN0_PD0           (0*NUM_GROUP + PIN_BASE + 24)
+#define        RK30_PIN0_PD1           (0*NUM_GROUP + PIN_BASE + 25)
+#define        RK30_PIN0_PD2           (0*NUM_GROUP + PIN_BASE + 26)
+#define        RK30_PIN0_PD3           (0*NUM_GROUP + PIN_BASE + 27)
+#define        RK30_PIN0_PD4           (0*NUM_GROUP + PIN_BASE + 28)
+#define        RK30_PIN0_PD5           (0*NUM_GROUP + PIN_BASE + 29)
+#define        RK30_PIN0_PD6           (0*NUM_GROUP + PIN_BASE + 30)
+#define        RK30_PIN0_PD7           (0*NUM_GROUP + PIN_BASE + 31)
+
+#define        RK30_PIN1_PA0           (1*NUM_GROUP + PIN_BASE + 0) 
+#define        RK30_PIN1_PA1           (1*NUM_GROUP + PIN_BASE + 1) 
+#define        RK30_PIN1_PA2           (1*NUM_GROUP + PIN_BASE + 2) 
+#define        RK30_PIN1_PA3           (1*NUM_GROUP + PIN_BASE + 3) 
+#define        RK30_PIN1_PA4           (1*NUM_GROUP + PIN_BASE + 4) 
+#define        RK30_PIN1_PA5           (1*NUM_GROUP + PIN_BASE + 5) 
+#define        RK30_PIN1_PA6           (1*NUM_GROUP + PIN_BASE + 6) 
+#define        RK30_PIN1_PA7           (1*NUM_GROUP + PIN_BASE + 7) 
+#define        RK30_PIN1_PB0           (1*NUM_GROUP + PIN_BASE + 8) 
+#define        RK30_PIN1_PB1           (1*NUM_GROUP + PIN_BASE + 9) 
+#define        RK30_PIN1_PB2           (1*NUM_GROUP + PIN_BASE + 10)
+#define        RK30_PIN1_PB3           (1*NUM_GROUP + PIN_BASE + 11)
+#define        RK30_PIN1_PB4           (1*NUM_GROUP + PIN_BASE + 12)
+#define        RK30_PIN1_PB5           (1*NUM_GROUP + PIN_BASE + 13)
+#define        RK30_PIN1_PB6           (1*NUM_GROUP + PIN_BASE + 14)
+#define        RK30_PIN1_PB7           (1*NUM_GROUP + PIN_BASE + 15)
+#define        RK30_PIN1_PC0           (1*NUM_GROUP + PIN_BASE + 16)
+#define        RK30_PIN1_PC1           (1*NUM_GROUP + PIN_BASE + 17)
+#define        RK30_PIN1_PC2           (1*NUM_GROUP + PIN_BASE + 18)
+#define        RK30_PIN1_PC3           (1*NUM_GROUP + PIN_BASE + 19)
+#define        RK30_PIN1_PC4           (1*NUM_GROUP + PIN_BASE + 20)
+#define        RK30_PIN1_PC5           (1*NUM_GROUP + PIN_BASE + 21)
+#define        RK30_PIN1_PC6           (1*NUM_GROUP + PIN_BASE + 22)
+#define        RK30_PIN1_PC7           (1*NUM_GROUP + PIN_BASE + 23)
+#define        RK30_PIN1_PD0           (1*NUM_GROUP + PIN_BASE + 24)
+#define        RK30_PIN1_PD1           (1*NUM_GROUP + PIN_BASE + 25)
+#define        RK30_PIN1_PD2           (1*NUM_GROUP + PIN_BASE + 26)
+#define        RK30_PIN1_PD3           (1*NUM_GROUP + PIN_BASE + 27)
+#define        RK30_PIN1_PD4           (1*NUM_GROUP + PIN_BASE + 28)
+#define        RK30_PIN1_PD5           (1*NUM_GROUP + PIN_BASE + 29)
+#define        RK30_PIN1_PD6           (1*NUM_GROUP + PIN_BASE + 30)
+#define        RK30_PIN1_PD7           (1*NUM_GROUP + PIN_BASE + 31)
+
+#define        RK30_PIN2_PA0           (2*NUM_GROUP + PIN_BASE + 0)
+#define        RK30_PIN2_PA1           (2*NUM_GROUP + PIN_BASE + 1)
+#define        RK30_PIN2_PA2           (2*NUM_GROUP + PIN_BASE + 2)
+#define        RK30_PIN2_PA3           (2*NUM_GROUP + PIN_BASE + 3)
+#define        RK30_PIN2_PA4           (2*NUM_GROUP + PIN_BASE + 4)
+#define        RK30_PIN2_PA5           (2*NUM_GROUP + PIN_BASE + 5)
+#define        RK30_PIN2_PA6           (2*NUM_GROUP + PIN_BASE + 6)
+#define        RK30_PIN2_PA7           (2*NUM_GROUP + PIN_BASE + 7)
+#define        RK30_PIN2_PB0           (2*NUM_GROUP + PIN_BASE + 8)
+#define        RK30_PIN2_PB1           (2*NUM_GROUP + PIN_BASE + 9)
+#define        RK30_PIN2_PB2           (2*NUM_GROUP + PIN_BASE + 10)
+#define        RK30_PIN2_PB3           (2*NUM_GROUP + PIN_BASE + 11)
+#define        RK30_PIN2_PB4           (2*NUM_GROUP + PIN_BASE + 12)
+#define        RK30_PIN2_PB5           (2*NUM_GROUP + PIN_BASE + 13)
+#define        RK30_PIN2_PB6           (2*NUM_GROUP + PIN_BASE + 14)
+#define        RK30_PIN2_PB7           (2*NUM_GROUP + PIN_BASE + 15)
+#define        RK30_PIN2_PC0           (2*NUM_GROUP + PIN_BASE + 16)
+#define        RK30_PIN2_PC1           (2*NUM_GROUP + PIN_BASE + 17)
+#define        RK30_PIN2_PC2           (2*NUM_GROUP + PIN_BASE + 18)
+#define        RK30_PIN2_PC3           (2*NUM_GROUP + PIN_BASE + 19)
+#define        RK30_PIN2_PC4           (2*NUM_GROUP + PIN_BASE + 20)
+#define        RK30_PIN2_PC5           (2*NUM_GROUP + PIN_BASE + 21)
+#define        RK30_PIN2_PC6           (2*NUM_GROUP + PIN_BASE + 22)
+#define        RK30_PIN2_PC7           (2*NUM_GROUP + PIN_BASE + 23)
+#define        RK30_PIN2_PD0           (2*NUM_GROUP + PIN_BASE + 24)
+#define        RK30_PIN2_PD1           (2*NUM_GROUP + PIN_BASE + 25)
+#define        RK30_PIN2_PD2           (2*NUM_GROUP + PIN_BASE + 26)
+#define        RK30_PIN2_PD3           (2*NUM_GROUP + PIN_BASE + 27)
+#define        RK30_PIN2_PD4           (2*NUM_GROUP + PIN_BASE + 28)
+#define        RK30_PIN2_PD5           (2*NUM_GROUP + PIN_BASE + 29)
+#define        RK30_PIN2_PD6           (2*NUM_GROUP + PIN_BASE + 30)
+#define        RK30_PIN2_PD7           (2*NUM_GROUP + PIN_BASE + 31)
+
+#define        RK30_PIN3_PA0           (3*NUM_GROUP + PIN_BASE + 0) 
+#define        RK30_PIN3_PA1           (3*NUM_GROUP + PIN_BASE + 1) 
+#define        RK30_PIN3_PA2           (3*NUM_GROUP + PIN_BASE + 2) 
+#define        RK30_PIN3_PA3           (3*NUM_GROUP + PIN_BASE + 3) 
+#define        RK30_PIN3_PA4           (3*NUM_GROUP + PIN_BASE + 4) 
+#define        RK30_PIN3_PA5           (3*NUM_GROUP + PIN_BASE + 5) 
+#define        RK30_PIN3_PA6           (3*NUM_GROUP + PIN_BASE + 6) 
+#define        RK30_PIN3_PA7           (3*NUM_GROUP + PIN_BASE + 7) 
+#define        RK30_PIN3_PB0           (3*NUM_GROUP + PIN_BASE + 8) 
+#define        RK30_PIN3_PB1           (3*NUM_GROUP + PIN_BASE + 9) 
+#define        RK30_PIN3_PB2           (3*NUM_GROUP + PIN_BASE + 10)
+#define        RK30_PIN3_PB3           (3*NUM_GROUP + PIN_BASE + 11)
+#define        RK30_PIN3_PB4           (3*NUM_GROUP + PIN_BASE + 12)
+#define        RK30_PIN3_PB5           (3*NUM_GROUP + PIN_BASE + 13)
+#define        RK30_PIN3_PB6           (3*NUM_GROUP + PIN_BASE + 14)
+#define        RK30_PIN3_PB7           (3*NUM_GROUP + PIN_BASE + 15)
+#define        RK30_PIN3_PC0           (3*NUM_GROUP + PIN_BASE + 16)
+#define        RK30_PIN3_PC1           (3*NUM_GROUP + PIN_BASE + 17)
+#define        RK30_PIN3_PC2           (3*NUM_GROUP + PIN_BASE + 18)
+#define        RK30_PIN3_PC3           (3*NUM_GROUP + PIN_BASE + 19)
+#define        RK30_PIN3_PC4           (3*NUM_GROUP + PIN_BASE + 20)
+#define        RK30_PIN3_PC5           (3*NUM_GROUP + PIN_BASE + 21)
+#define        RK30_PIN3_PC6           (3*NUM_GROUP + PIN_BASE + 22)
+#define        RK30_PIN3_PC7           (3*NUM_GROUP + PIN_BASE + 23)
+#define        RK30_PIN3_PD0           (3*NUM_GROUP + PIN_BASE + 24)
+#define        RK30_PIN3_PD1           (3*NUM_GROUP + PIN_BASE + 25)
+#define        RK30_PIN3_PD2           (3*NUM_GROUP + PIN_BASE + 26)
+#define        RK30_PIN3_PD3           (3*NUM_GROUP + PIN_BASE + 27)
+#define        RK30_PIN3_PD4           (3*NUM_GROUP + PIN_BASE + 28)
+#define        RK30_PIN3_PD5           (3*NUM_GROUP + PIN_BASE + 29)
+#define        RK30_PIN3_PD6           (3*NUM_GROUP + PIN_BASE + 30)
+#define        RK30_PIN3_PD7           (3*NUM_GROUP + PIN_BASE + 31)
+
+#define        RK30_PIN4_PA0           (4*NUM_GROUP + PIN_BASE + 0) 
+#define        RK30_PIN4_PA1           (4*NUM_GROUP + PIN_BASE + 1) 
+#define        RK30_PIN4_PA2           (4*NUM_GROUP + PIN_BASE + 2) 
+#define        RK30_PIN4_PA3           (4*NUM_GROUP + PIN_BASE + 3) 
+#define        RK30_PIN4_PA4           (4*NUM_GROUP + PIN_BASE + 4) 
+#define        RK30_PIN4_PA5           (4*NUM_GROUP + PIN_BASE + 5) 
+#define        RK30_PIN4_PA6           (4*NUM_GROUP + PIN_BASE + 6) 
+#define        RK30_PIN4_PA7           (4*NUM_GROUP + PIN_BASE + 7) 
+#define        RK30_PIN4_PB0           (4*NUM_GROUP + PIN_BASE + 8) 
+#define        RK30_PIN4_PB1           (4*NUM_GROUP + PIN_BASE + 9) 
+#define        RK30_PIN4_PB2           (4*NUM_GROUP + PIN_BASE + 10)
+#define        RK30_PIN4_PB3           (4*NUM_GROUP + PIN_BASE + 11)
+#define        RK30_PIN4_PB4           (4*NUM_GROUP + PIN_BASE + 12)
+#define        RK30_PIN4_PB5           (4*NUM_GROUP + PIN_BASE + 13)
+#define        RK30_PIN4_PB6           (4*NUM_GROUP + PIN_BASE + 14)
+#define        RK30_PIN4_PB7           (4*NUM_GROUP + PIN_BASE + 15)
+#define        RK30_PIN4_PC0           (4*NUM_GROUP + PIN_BASE + 16)
+#define        RK30_PIN4_PC1           (4*NUM_GROUP + PIN_BASE + 17)
+#define        RK30_PIN4_PC2           (4*NUM_GROUP + PIN_BASE + 18)
+#define        RK30_PIN4_PC3           (4*NUM_GROUP + PIN_BASE + 19)
+#define        RK30_PIN4_PC4           (4*NUM_GROUP + PIN_BASE + 20)
+#define        RK30_PIN4_PC5           (4*NUM_GROUP + PIN_BASE + 21)
+#define        RK30_PIN4_PC6           (4*NUM_GROUP + PIN_BASE + 22)
+#define        RK30_PIN4_PC7           (4*NUM_GROUP + PIN_BASE + 23)
+#define        RK30_PIN4_PD0           (4*NUM_GROUP + PIN_BASE + 24)
+#define        RK30_PIN4_PD1           (4*NUM_GROUP + PIN_BASE + 25)
+#define        RK30_PIN4_PD2           (4*NUM_GROUP + PIN_BASE + 26)
+#define        RK30_PIN4_PD3           (4*NUM_GROUP + PIN_BASE + 27)
+#define        RK30_PIN4_PD4           (4*NUM_GROUP + PIN_BASE + 28)
+#define        RK30_PIN4_PD5           (4*NUM_GROUP + PIN_BASE + 29)
+#define        RK30_PIN4_PD6           (4*NUM_GROUP + PIN_BASE + 30)
+#define        RK30_PIN4_PD7           (4*NUM_GROUP + PIN_BASE + 31)
+
+#define        RK30_PIN6_PD7           (6*NUM_GROUP + PIN_BASE + 31)
+
+#if defined(CONFIG_SPI_FPGA_GPIO)
+#define        FPGA_PIO0_00 (SPI_FPGA_EXPANDER_BASE + 0*NUM_GROUP + 0)
+#define        FPGA_PIO0_01 (SPI_FPGA_EXPANDER_BASE + 0*NUM_GROUP + 1)
+#define        FPGA_PIO0_02 (SPI_FPGA_EXPANDER_BASE + 0*NUM_GROUP + 2)
+#define        FPGA_PIO0_03 (SPI_FPGA_EXPANDER_BASE + 0*NUM_GROUP + 3)
+#define        FPGA_PIO0_04 (SPI_FPGA_EXPANDER_BASE + 0*NUM_GROUP + 4)
+#define        FPGA_PIO0_05 (SPI_FPGA_EXPANDER_BASE + 0*NUM_GROUP + 5)
+#define        FPGA_PIO0_06 (SPI_FPGA_EXPANDER_BASE + 0*NUM_GROUP + 6)
+#define        FPGA_PIO0_07 (SPI_FPGA_EXPANDER_BASE + 0*NUM_GROUP + 7)
+
+#define        FPGA_PIO0_08 (SPI_FPGA_EXPANDER_BASE + 1*NUM_GROUP + 0)
+#define        FPGA_PIO0_09 (SPI_FPGA_EXPANDER_BASE + 1*NUM_GROUP + 1)
+#define        FPGA_PIO0_10 (SPI_FPGA_EXPANDER_BASE + 1*NUM_GROUP + 2)
+#define        FPGA_PIO0_11 (SPI_FPGA_EXPANDER_BASE + 1*NUM_GROUP + 3)
+#define        FPGA_PIO0_12 (SPI_FPGA_EXPANDER_BASE + 1*NUM_GROUP + 4)
+#define        FPGA_PIO0_13 (SPI_FPGA_EXPANDER_BASE + 1*NUM_GROUP + 5)
+#define        FPGA_PIO0_14 (SPI_FPGA_EXPANDER_BASE + 1*NUM_GROUP + 6)
+#define        FPGA_PIO0_15 (SPI_FPGA_EXPANDER_BASE + 1*NUM_GROUP + 7)
+
+#define        FPGA_PIO1_00 (SPI_FPGA_EXPANDER_BASE + 2*NUM_GROUP + 0)
+#define        FPGA_PIO1_01 (SPI_FPGA_EXPANDER_BASE + 2*NUM_GROUP + 1)
+#define        FPGA_PIO1_02 (SPI_FPGA_EXPANDER_BASE + 2*NUM_GROUP + 2)
+#define        FPGA_PIO1_03 (SPI_FPGA_EXPANDER_BASE + 2*NUM_GROUP + 3)
+#define        FPGA_PIO1_04 (SPI_FPGA_EXPANDER_BASE + 2*NUM_GROUP + 4)
+#define        FPGA_PIO1_05 (SPI_FPGA_EXPANDER_BASE + 2*NUM_GROUP + 5)
+#define        FPGA_PIO1_06 (SPI_FPGA_EXPANDER_BASE + 2*NUM_GROUP + 6)
+#define        FPGA_PIO1_07 (SPI_FPGA_EXPANDER_BASE + 2*NUM_GROUP + 7)
+
+#define        FPGA_PIO1_08 (SPI_FPGA_EXPANDER_BASE + 3*NUM_GROUP + 0)
+#define        FPGA_PIO1_09 (SPI_FPGA_EXPANDER_BASE + 3*NUM_GROUP + 1)
+#define        FPGA_PIO1_10 (SPI_FPGA_EXPANDER_BASE + 3*NUM_GROUP + 2)
+#define        FPGA_PIO1_11 (SPI_FPGA_EXPANDER_BASE + 3*NUM_GROUP + 3)
+#define        FPGA_PIO1_12 (SPI_FPGA_EXPANDER_BASE + 3*NUM_GROUP + 4)
+#define        FPGA_PIO1_13 (SPI_FPGA_EXPANDER_BASE + 3*NUM_GROUP + 5)
+#define        FPGA_PIO1_14 (SPI_FPGA_EXPANDER_BASE + 3*NUM_GROUP + 6)
+#define        FPGA_PIO1_15 (SPI_FPGA_EXPANDER_BASE + 3*NUM_GROUP + 7)
+
+#define        FPGA_PIO2_00 (SPI_FPGA_EXPANDER_BASE + 4*NUM_GROUP + 0)
+#define        FPGA_PIO2_01 (SPI_FPGA_EXPANDER_BASE + 4*NUM_GROUP + 1)
+#define        FPGA_PIO2_02 (SPI_FPGA_EXPANDER_BASE + 4*NUM_GROUP + 2)
+#define        FPGA_PIO2_03 (SPI_FPGA_EXPANDER_BASE + 4*NUM_GROUP + 3)
+#define        FPGA_PIO2_04 (SPI_FPGA_EXPANDER_BASE + 4*NUM_GROUP + 4)
+#define        FPGA_PIO2_05 (SPI_FPGA_EXPANDER_BASE + 4*NUM_GROUP + 5)
+#define        FPGA_PIO2_06 (SPI_FPGA_EXPANDER_BASE + 4*NUM_GROUP + 6)
+#define        FPGA_PIO2_07 (SPI_FPGA_EXPANDER_BASE + 4*NUM_GROUP + 7)
+
+#define        FPGA_PIO2_08 (SPI_FPGA_EXPANDER_BASE + 5*NUM_GROUP + 0)
+#define        FPGA_PIO2_09 (SPI_FPGA_EXPANDER_BASE + 5*NUM_GROUP + 1)
+#define        FPGA_PIO2_10 (SPI_FPGA_EXPANDER_BASE + 5*NUM_GROUP + 2)
+#define        FPGA_PIO2_11 (SPI_FPGA_EXPANDER_BASE + 5*NUM_GROUP + 3)
+#define        FPGA_PIO2_12 (SPI_FPGA_EXPANDER_BASE + 5*NUM_GROUP + 4)
+#define        FPGA_PIO2_13 (SPI_FPGA_EXPANDER_BASE + 5*NUM_GROUP + 5)
+#define        FPGA_PIO2_14 (SPI_FPGA_EXPANDER_BASE + 5*NUM_GROUP + 6)
+#define        FPGA_PIO2_15 (SPI_FPGA_EXPANDER_BASE + 5*NUM_GROUP + 7)
+
+#define        FPGA_PIO3_00 (SPI_FPGA_EXPANDER_BASE + 6*NUM_GROUP + 0)
+#define        FPGA_PIO3_01 (SPI_FPGA_EXPANDER_BASE + 6*NUM_GROUP + 1)
+#define        FPGA_PIO3_02 (SPI_FPGA_EXPANDER_BASE + 6*NUM_GROUP + 2)
+#define        FPGA_PIO3_03 (SPI_FPGA_EXPANDER_BASE + 6*NUM_GROUP + 3)
+#define        FPGA_PIO3_04 (SPI_FPGA_EXPANDER_BASE + 6*NUM_GROUP + 4)
+#define        FPGA_PIO3_05 (SPI_FPGA_EXPANDER_BASE + 6*NUM_GROUP + 5)
+#define        FPGA_PIO3_06 (SPI_FPGA_EXPANDER_BASE + 6*NUM_GROUP + 6)
+#define        FPGA_PIO3_07 (SPI_FPGA_EXPANDER_BASE + 6*NUM_GROUP + 7)
+
+#define        FPGA_PIO3_08 (SPI_FPGA_EXPANDER_BASE + 7*NUM_GROUP + 0)
+#define        FPGA_PIO3_09 (SPI_FPGA_EXPANDER_BASE + 7*NUM_GROUP + 1)
+#define        FPGA_PIO3_10 (SPI_FPGA_EXPANDER_BASE + 7*NUM_GROUP + 2)
+#define        FPGA_PIO3_11 (SPI_FPGA_EXPANDER_BASE + 7*NUM_GROUP + 3)
+#define        FPGA_PIO3_12 (SPI_FPGA_EXPANDER_BASE + 7*NUM_GROUP + 4)
+#define        FPGA_PIO3_13 (SPI_FPGA_EXPANDER_BASE + 7*NUM_GROUP + 5)
+#define        FPGA_PIO3_14 (SPI_FPGA_EXPANDER_BASE + 7*NUM_GROUP + 6)
+#define        FPGA_PIO3_15 (SPI_FPGA_EXPANDER_BASE + 7*NUM_GROUP + 7)
+
+#define        FPGA_PIO4_00 (SPI_FPGA_EXPANDER_BASE + 8*NUM_GROUP + 0)
+#define        FPGA_PIO4_01 (SPI_FPGA_EXPANDER_BASE + 8*NUM_GROUP + 1)
+#define        FPGA_PIO4_02 (SPI_FPGA_EXPANDER_BASE + 8*NUM_GROUP + 2)
+#define        FPGA_PIO4_03 (SPI_FPGA_EXPANDER_BASE + 8*NUM_GROUP + 3)
+#define        FPGA_PIO4_04 (SPI_FPGA_EXPANDER_BASE + 8*NUM_GROUP + 4)
+#define        FPGA_PIO4_05 (SPI_FPGA_EXPANDER_BASE + 8*NUM_GROUP + 5)
+#define        FPGA_PIO4_06 (SPI_FPGA_EXPANDER_BASE + 8*NUM_GROUP + 6)
+#define        FPGA_PIO4_07 (SPI_FPGA_EXPANDER_BASE + 8*NUM_GROUP + 7)
+
+#define        FPGA_PIO4_08 (SPI_FPGA_EXPANDER_BASE + 9*NUM_GROUP + 0)
+#define        FPGA_PIO4_09 (SPI_FPGA_EXPANDER_BASE + 9*NUM_GROUP + 1)
+#define        FPGA_PIO4_10 (SPI_FPGA_EXPANDER_BASE + 9*NUM_GROUP + 2)
+#define        FPGA_PIO4_11 (SPI_FPGA_EXPANDER_BASE + 9*NUM_GROUP + 3)
+#define        FPGA_PIO4_12 (SPI_FPGA_EXPANDER_BASE + 9*NUM_GROUP + 4)
+#define        FPGA_PIO4_13 (SPI_FPGA_EXPANDER_BASE + 9*NUM_GROUP + 5)
+#define        FPGA_PIO4_14 (SPI_FPGA_EXPANDER_BASE + 9*NUM_GROUP + 6)
+#define        FPGA_PIO4_15 (SPI_FPGA_EXPANDER_BASE + 9*NUM_GROUP + 7)
+
+#define        FPGA_PIO5_00 (SPI_FPGA_EXPANDER_BASE + 10*NUM_GROUP + 0)
+#define        FPGA_PIO5_01 (SPI_FPGA_EXPANDER_BASE + 10*NUM_GROUP + 1)
+#define        FPGA_PIO5_02 (SPI_FPGA_EXPANDER_BASE + 10*NUM_GROUP + 2)
+#define        FPGA_PIO5_03 (SPI_FPGA_EXPANDER_BASE + 10*NUM_GROUP + 3)
+#define        FPGA_PIO5_04 (SPI_FPGA_EXPANDER_BASE + 10*NUM_GROUP + 4)
+#define        FPGA_PIO5_05 (SPI_FPGA_EXPANDER_BASE + 10*NUM_GROUP + 5)
+#define        FPGA_PIO5_06 (SPI_FPGA_EXPANDER_BASE + 10*NUM_GROUP + 6)
+#define        FPGA_PIO5_07 (SPI_FPGA_EXPANDER_BASE + 10*NUM_GROUP + 7)
+
+#define        FPGA_PIO5_08 (SPI_FPGA_EXPANDER_BASE + 11*NUM_GROUP + 0)
+#define        FPGA_PIO5_09 (SPI_FPGA_EXPANDER_BASE + 11*NUM_GROUP + 1)
+#define        FPGA_PIO5_10 (SPI_FPGA_EXPANDER_BASE + 11*NUM_GROUP + 2)
+#define        FPGA_PIO5_11 (SPI_FPGA_EXPANDER_BASE + 11*NUM_GROUP + 3)
+#define        FPGA_PIO5_12 (SPI_FPGA_EXPANDER_BASE + 11*NUM_GROUP + 4)
+#define        FPGA_PIO5_13 (SPI_FPGA_EXPANDER_BASE + 11*NUM_GROUP + 5)
+#define        FPGA_PIO5_14 (SPI_FPGA_EXPANDER_BASE + 11*NUM_GROUP + 6)
+#define        FPGA_PIO5_15 (SPI_FPGA_EXPANDER_BASE + 11*NUM_GROUP + 7)
+
+#endif
+
+#if defined(CONFIG_IOEXTEND_TCA6424)
+#define        TCA6424_P00 (TCA6424_GPIO_EXPANDER_BASE + 0*NUM_GROUP + 0)
+#define        TCA6424_P01 (TCA6424_GPIO_EXPANDER_BASE + 0*NUM_GROUP + 1)
+#define        TCA6424_P02 (TCA6424_GPIO_EXPANDER_BASE + 0*NUM_GROUP + 2)
+#define        TCA6424_P03 (TCA6424_GPIO_EXPANDER_BASE + 0*NUM_GROUP + 3)
+#define        TCA6424_P04 (TCA6424_GPIO_EXPANDER_BASE + 0*NUM_GROUP + 4)
+#define        TCA6424_P05 (TCA6424_GPIO_EXPANDER_BASE + 0*NUM_GROUP + 5)
+#define        TCA6424_P06 (TCA6424_GPIO_EXPANDER_BASE + 0*NUM_GROUP + 6)
+#define        TCA6424_P07 (TCA6424_GPIO_EXPANDER_BASE + 0*NUM_GROUP + 7)
+
+#define        TCA6424_P10 (TCA6424_GPIO_EXPANDER_BASE + 1*NUM_GROUP + 0)
+#define        TCA6424_P11 (TCA6424_GPIO_EXPANDER_BASE + 1*NUM_GROUP + 1)
+#define        TCA6424_P12 (TCA6424_GPIO_EXPANDER_BASE + 1*NUM_GROUP + 2)
+#define        TCA6424_P13 (TCA6424_GPIO_EXPANDER_BASE + 1*NUM_GROUP + 3)
+#define        TCA6424_P14 (TCA6424_GPIO_EXPANDER_BASE + 1*NUM_GROUP + 4)
+#define        TCA6424_P15 (TCA6424_GPIO_EXPANDER_BASE + 1*NUM_GROUP + 5)
+#define        TCA6424_P16 (TCA6424_GPIO_EXPANDER_BASE + 1*NUM_GROUP + 6)
+#define        TCA6424_P17 (TCA6424_GPIO_EXPANDER_BASE + 1*NUM_GROUP + 7)
+
+#define        TCA6424_P20 (TCA6424_GPIO_EXPANDER_BASE + 2*NUM_GROUP + 0)
+#define        TCA6424_P21 (TCA6424_GPIO_EXPANDER_BASE + 2*NUM_GROUP + 1)
+#define        TCA6424_P22 (TCA6424_GPIO_EXPANDER_BASE + 2*NUM_GROUP + 2)
+#define        TCA6424_P23 (TCA6424_GPIO_EXPANDER_BASE + 2*NUM_GROUP + 3)
+#define        TCA6424_P24 (TCA6424_GPIO_EXPANDER_BASE + 2*NUM_GROUP + 4)
+#define        TCA6424_P25 (TCA6424_GPIO_EXPANDER_BASE + 2*NUM_GROUP + 5)
+#define        TCA6424_P26 (TCA6424_GPIO_EXPANDER_BASE + 2*NUM_GROUP + 6)
+#define        TCA6424_P27 (TCA6424_GPIO_EXPANDER_BASE + 2*NUM_GROUP + 7)
+#endif
+
+#if defined(CONFIG_GPIO_WM831X)
+#define        WM831X_P01 (WM831X_GPIO_EXPANDER_BASE  + 0*NUM_GROUP + 0)
+#define        WM831X_P02 (WM831X_GPIO_EXPANDER_BASE  + 0*NUM_GROUP + 1)
+#define        WM831X_P03 (WM831X_GPIO_EXPANDER_BASE  + 0*NUM_GROUP + 2)
+#define        WM831X_P04 (WM831X_GPIO_EXPANDER_BASE  + 0*NUM_GROUP + 3)
+#define        WM831X_P05 (WM831X_GPIO_EXPANDER_BASE  + 0*NUM_GROUP + 4)
+#define        WM831X_P06 (WM831X_GPIO_EXPANDER_BASE  + 0*NUM_GROUP + 5)
+#define        WM831X_P07 (WM831X_GPIO_EXPANDER_BASE  + 0*NUM_GROUP + 6)
+#define        WM831X_P08 (WM831X_GPIO_EXPANDER_BASE  + 0*NUM_GROUP + 7)
+
+#define        WM831X_P09 (WM831X_GPIO_EXPANDER_BASE  + 1*NUM_GROUP + 0)
+#define        WM831X_P10 (WM831X_GPIO_EXPANDER_BASE  + 1*NUM_GROUP + 1)
+#define        WM831X_P11 (WM831X_GPIO_EXPANDER_BASE  + 1*NUM_GROUP + 2)
+#define        WM831X_P12 (WM831X_GPIO_EXPANDER_BASE  + 1*NUM_GROUP + 3)
+#endif                                           
+                                           
+extern void __init rk30_gpio_init(void);
+/*-------------------------------------------------------------------------*/
 
-#define ARCH_NR_GPIOS  NR_GPIO_IRQS
-#define PIN_BASE       NR_GIC_IRQS
+/* 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 */
index c579c8bf5dc8d36e4ace84c4a367b876a862697a..441f198aac8630df422a00c9444cab2732df2a3c 100755 (executable)
@@ -46,6 +46,7 @@ obj-$(CONFIG_MACH_U300)               += gpio-u300.o
 obj-$(CONFIG_PLAT_NOMADIK)     += gpio-nomadik.o
 obj-$(CONFIG_GPIO_RDC321X)     += rdc321x-gpio.o
 obj-$(CONFIG_ARCH_RK29)                += gpio-rk29.o
+obj-$(CONFIG_ARCH_RK30)                += gpio-rk30.o
 obj-$(CONFIG_GPIO_JANZ_TTL)    += janz-ttl.o
 obj-$(CONFIG_GPIO_SX150X)      += sx150x.o
 obj-$(CONFIG_GPIO_VX855)       += vx855_gpio.o
diff --git a/drivers/gpio/gpio-rk30.c b/drivers/gpio/gpio-rk30.c
new file mode 100755 (executable)
index 0000000..729ea9f
--- /dev/null
@@ -0,0 +1,483 @@
+/* arch/arm/mach-rk29/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 <linux/syscore_ops.h>
+
+#include <mach/hardware.h>
+#include <mach/gpio.h>
+#include <mach/io.h>
+#include <mach/iomux.h>
+#include <asm/gpio.h>
+#include <asm/mach/irq.h>
+
+#define MAX_PIN        RK30_PIN6_PD7
+
+#define to_rk30_gpio_bank(c) container_of(c, struct rk30_gpio_bank, chip)
+
+struct rk30_gpio_bank {
+       struct gpio_chip chip;
+       unsigned short id;
+       short irq;
+       void __iomem *regbase;  /* Base of register bank */
+       struct clk *clk;
+       u32 suspend_wakeup;
+       u32 saved_wakeup;
+       spinlock_t lock;
+};
+
+static struct lock_class_key gpio_lock_class;
+
+static void rk30_gpiolib_dbg_show(struct seq_file *s, struct gpio_chip *chip);
+static void rk30_gpiolib_set(struct gpio_chip *chip, unsigned offset, int val);
+static int rk30_gpiolib_get(struct gpio_chip *chip, unsigned offset);
+static int rk30_gpiolib_direction_output(struct gpio_chip *chip,unsigned offset, int val);
+static int rk30_gpiolib_direction_input(struct gpio_chip *chip,unsigned offset);
+static int rk30_gpiolib_pull_updown(struct gpio_chip *chip, unsigned offset, unsigned enable);
+static int rk30_gpiolib_to_irq(struct gpio_chip *chip,unsigned offset);
+
+#define RK30_GPIO_BANK(ID)                     \
+       {                                                               \
+               .chip = {                                               \
+                       .label            = "gpio" #ID,                 \
+                       .direction_input  = rk30_gpiolib_direction_input, \
+                       .direction_output = rk30_gpiolib_direction_output, \
+                       .get              = rk30_gpiolib_get,           \
+                       .set              = rk30_gpiolib_set,           \
+                       .pull_updown      = rk30_gpiolib_pull_updown,   \
+                       .dbg_show         = rk30_gpiolib_dbg_show,      \
+                       .to_irq           = rk30_gpiolib_to_irq,        \
+                       .base             = PIN_BASE + ID*NUM_GROUP,    \
+                       .ngpio            = NUM_GROUP,                  \
+               },                                                      \
+               .id = ID, \
+               .irq = IRQ_GPIO##ID, \
+               .regbase = (unsigned char __iomem *) RK30_GPIO##ID##_BASE, \
+       }
+
+static struct rk30_gpio_bank rk30_gpio_banks[] = {
+       RK30_GPIO_BANK(0),
+       RK30_GPIO_BANK(1),
+       RK30_GPIO_BANK(2),
+       RK30_GPIO_BANK(3),
+       RK30_GPIO_BANK(4),
+       RK30_GPIO_BANK(6),
+};
+
+static inline void rk30_gpio_bit_op(void __iomem *regbase, unsigned int offset, u32 bit, unsigned char flag)
+{
+       u32 val = __raw_readl(regbase + offset);
+       if (flag)
+               val |= bit;
+       else
+               val &= ~bit;
+       __raw_writel(val, regbase + offset);
+}
+
+static inline struct gpio_chip *pin_to_gpio_chip(unsigned pin)
+{
+       if (pin < PIN_BASE || pin > MAX_PIN)
+               return NULL;
+
+       pin -= PIN_BASE;
+       pin /= NUM_GROUP;
+       if (likely(pin < ARRAY_SIZE(rk30_gpio_banks)))
+               return &(rk30_gpio_banks[pin].chip);
+       return NULL;
+}
+
+static inline unsigned gpio_to_bit(unsigned gpio)
+{
+       gpio -= PIN_BASE;
+       return 1u << (gpio % NUM_GROUP);
+}
+
+static inline unsigned offset_to_bit(unsigned offset)
+{
+       return 1u << offset;
+}
+
+static void GPIOSetPinLevel(void __iomem *regbase, unsigned int bit, eGPIOPinLevel_t level)
+{
+       rk30_gpio_bit_op(regbase, GPIO_SWPORT_DDR, bit, 1);
+       rk30_gpio_bit_op(regbase, GPIO_SWPORT_DR, bit, level);
+}
+
+static int GPIOGetPinLevel(void __iomem *regbase, unsigned int bit)
+{
+       return ((__raw_readl(regbase + GPIO_EXT_PORT) & bit) != 0);
+}
+
+static void GPIOSetPinDirection(void __iomem *regbase, unsigned int bit, eGPIOPinDirection_t direction)
+{
+       rk30_gpio_bit_op(regbase, GPIO_SWPORT_DDR, bit, direction);
+       /* Enable debounce may halt cpu on wfi, disable it by default */
+       //rk30_gpio_bit_op(regbase, GPIO_DEBOUNCE, bit, 1);
+}
+
+static void GPIOEnableIntr(void __iomem *regbase, unsigned int bit)
+{
+       rk30_gpio_bit_op(regbase, GPIO_INTEN, bit, 1);
+}
+
+static void GPIODisableIntr(void __iomem *regbase, unsigned int bit)
+{
+       rk30_gpio_bit_op(regbase, GPIO_INTEN, bit, 0);
+}
+
+static void GPIOAckIntr(void __iomem *regbase, unsigned int bit)
+{
+       rk30_gpio_bit_op(regbase, GPIO_PORTS_EOI, bit, 1);
+}
+
+static void GPIOSetIntrType(void __iomem *regbase, unsigned int bit, eGPIOIntType_t type)
+{
+       switch (type) {
+       case GPIOLevelLow:
+               rk30_gpio_bit_op(regbase, GPIO_INT_POLARITY, bit, 0);
+               rk30_gpio_bit_op(regbase, GPIO_INTTYPE_LEVEL, bit, 0);
+               break;
+       case GPIOLevelHigh:
+               rk30_gpio_bit_op(regbase, GPIO_INTTYPE_LEVEL, bit, 0);
+               rk30_gpio_bit_op(regbase, GPIO_INT_POLARITY, bit, 1);
+               break;
+       case GPIOEdgelFalling:
+               rk30_gpio_bit_op(regbase, GPIO_INTTYPE_LEVEL, bit, 1);
+               rk30_gpio_bit_op(regbase, GPIO_INT_POLARITY, bit, 0);
+               break;
+       case GPIOEdgelRising:
+               rk30_gpio_bit_op(regbase, GPIO_INTTYPE_LEVEL, bit, 1);
+               rk30_gpio_bit_op(regbase, GPIO_INT_POLARITY, bit, 1);
+               break;
+       }
+}
+
+static int rk30_gpio_irq_set_type(struct irq_data *d, unsigned int type)
+{
+       struct rk30_gpio_bank *bank = irq_data_get_irq_chip_data(d);
+       u32 bit = gpio_to_bit(irq_to_gpio(d->irq));
+       eGPIOIntType_t int_type;
+       unsigned long flags;
+
+       switch (type) {
+       case IRQ_TYPE_EDGE_RISING:
+               int_type = GPIOEdgelRising;
+               break;
+       case IRQ_TYPE_EDGE_FALLING:
+               int_type = GPIOEdgelFalling;
+               break;
+       case IRQ_TYPE_LEVEL_HIGH:
+               int_type = GPIOLevelHigh;
+               break;
+       case IRQ_TYPE_LEVEL_LOW:
+               int_type = GPIOLevelLow;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       spin_lock_irqsave(&bank->lock, flags);
+       //ÉèÖÃΪÖжÏ֮ǰ£¬±ØÐëÏÈÉèÖÃΪÊäÈë״̬
+       GPIOSetPinDirection(bank->regbase, bit, GPIO_IN);
+       GPIOSetIntrType(bank->regbase, bit, int_type);
+       spin_unlock_irqrestore(&bank->lock, flags);
+
+       if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
+               __irq_set_handler_locked(d->irq, handle_level_irq);
+       else if (type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
+               __irq_set_handler_locked(d->irq, handle_edge_irq);
+
+       return 0;
+}
+
+static int rk30_gpio_irq_set_wake(struct irq_data *d, unsigned int on)
+{
+       struct rk30_gpio_bank *bank = irq_data_get_irq_chip_data(d);
+       u32 bit = gpio_to_bit(irq_to_gpio(d->irq));
+       unsigned long flags;
+
+       spin_lock_irqsave(&bank->lock, flags);
+       if (on)
+               bank->suspend_wakeup |= bit;
+       else
+               bank->suspend_wakeup &= ~bit;
+       spin_unlock_irqrestore(&bank->lock, flags);
+
+       return 0;
+}
+
+static void rk30_gpio_irq_unmask(struct irq_data *d)
+{
+       struct rk30_gpio_bank *bank = irq_data_get_irq_chip_data(d);
+       u32 bit = gpio_to_bit(irq_to_gpio(d->irq));
+       unsigned long flags;
+
+       spin_lock_irqsave(&bank->lock, flags);
+       GPIOEnableIntr(bank->regbase, bit);
+       spin_unlock_irqrestore(&bank->lock, flags);
+}
+
+static void rk30_gpio_irq_mask(struct irq_data *d)
+{
+       struct rk30_gpio_bank *bank = irq_data_get_irq_chip_data(d);
+       u32 bit = gpio_to_bit(irq_to_gpio(d->irq));
+       unsigned long flags;
+
+       spin_lock_irqsave(&bank->lock, flags);
+       GPIODisableIntr(bank->regbase, bit);
+       spin_unlock_irqrestore(&bank->lock, flags);
+}
+
+static void rk30_gpio_irq_ack(struct irq_data *d)
+{
+       struct rk30_gpio_bank *bank = irq_data_get_irq_chip_data(d);
+       u32 bit = gpio_to_bit(irq_to_gpio(d->irq));
+
+       GPIOAckIntr(bank->regbase, bit);
+}
+
+static int rk30_gpiolib_direction_output(struct gpio_chip *chip, unsigned offset, int val)
+{
+       struct rk30_gpio_bank *bank = to_rk30_gpio_bank(chip);
+       u32 bit = offset_to_bit(offset);
+       unsigned long flags;
+
+       spin_lock_irqsave(&bank->lock, flags);
+       GPIOSetPinDirection(bank->regbase, bit, GPIO_OUT);
+       GPIOSetPinLevel(bank->regbase, bit, val);
+       spin_unlock_irqrestore(&bank->lock, flags);
+       return 0;
+}
+
+static int rk30_gpiolib_direction_input(struct gpio_chip *chip,unsigned offset)
+{
+       struct rk30_gpio_bank *bank = to_rk30_gpio_bank(chip);
+       unsigned long flags;
+
+       spin_lock_irqsave(&bank->lock, flags);
+       GPIOSetPinDirection(bank->regbase, offset_to_bit(offset), GPIO_IN);
+       spin_unlock_irqrestore(&bank->lock, flags);
+       return 0;
+}
+
+
+static int rk30_gpiolib_get(struct gpio_chip *chip, unsigned offset)
+{
+       return GPIOGetPinLevel(to_rk30_gpio_bank(chip)->regbase, offset_to_bit(offset));
+}
+
+static void rk30_gpiolib_set(struct gpio_chip *chip, unsigned offset, int val)
+{
+       struct rk30_gpio_bank *bank = to_rk30_gpio_bank(chip);
+       unsigned long flags;
+
+       spin_lock_irqsave(&bank->lock, flags);
+       GPIOSetPinLevel(bank->regbase, offset_to_bit(offset), val);
+       spin_unlock_irqrestore(&bank->lock, flags);
+}
+
+static int rk30_gpiolib_pull_updown(struct gpio_chip *chip, unsigned offset, unsigned enable)
+{
+       struct rk30_gpio_bank *bank = to_rk30_gpio_bank(chip);
+       unsigned long flags;
+
+       spin_lock_irqsave(&bank->lock, flags);
+       rk30_gpio_bit_op((void *__iomem) RK30_GRF_BASE, 0x78 + bank->id * 4, offset_to_bit(offset), !enable);
+       spin_unlock_irqrestore(&bank->lock, flags);
+
+       return 0;
+}
+
+static int rk30_gpiolib_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+       return chip->base + offset;
+}
+
+static void rk30_gpiolib_dbg_show(struct seq_file *s, struct gpio_chip *chip)
+{
+#if 0
+       int i;
+
+       for (i = 0; i < chip->ngpio; i++) {
+               unsigned pin = chip->base + i;
+               struct gpio_chip *chip = pin_to_gpioChip(pin);
+               u32 bit = pin_to_bit(pin);
+               const char *gpio_label;
+               
+               if(!chip ||!bit)
+                       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 || !bit)
+                       {
+                               seq_printf(s, "!chip || !bit\t");
+                               return;
+                       }
+                               
+                       GPIOSetPinDirection(chip,bit,GPIO_IN);
+                       seq_printf(s, "pin=%d,level=%d\t", pin,GPIOGetPinLevel(chip,bit));
+                       seq_printf(s, "\t");
+               }
+       }
+#endif
+}
+
+static void rk30_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
+{
+       struct rk30_gpio_bank *bank = irq_get_handler_data(irq);
+       struct irq_chip *chip = irq_desc_get_chip(desc);
+       unsigned gpio_irq;
+       u32 isr, ilr;
+       unsigned pin;
+       unsigned unmasked = 0;
+
+       chained_irq_enter(chip, desc);
+
+       isr = __raw_readl(bank->regbase + GPIO_INT_STATUS);
+       ilr = __raw_readl(bank->regbase + GPIO_INTTYPE_LEVEL);
+
+       gpio_irq = gpio_to_irq(bank->chip.base);
+
+       while (isr) {
+               pin = fls(isr) - 1;
+               /* if gpio is edge triggered, clear condition
+                * before executing the hander so that we don't
+                * miss edges
+                 */
+               if (ilr & (1 << pin)) {
+                       unmasked = 1;
+                       chained_irq_exit(chip, desc);
+               }
+
+               generic_handle_irq(gpio_irq + pin);
+               isr &= ~(1 << pin);
+       }
+
+       if (!unmasked)
+               chained_irq_exit(chip, desc);
+}
+
+static struct irq_chip rk30_gpio_irq_chip = {
+       .name           = "GPIO",
+       .irq_ack        = rk30_gpio_irq_ack,
+       .irq_disable    = rk30_gpio_irq_mask,
+       .irq_mask       = rk30_gpio_irq_mask,
+       .irq_unmask     = rk30_gpio_irq_unmask,
+       .irq_set_type   = rk30_gpio_irq_set_type,
+       .irq_set_wake   = rk30_gpio_irq_set_wake,
+};
+
+void __init rk30_gpio_init(void)
+{
+       unsigned int i, j, pin;
+       struct rk30_gpio_bank *bank;
+
+       bank = rk30_gpio_banks;
+       pin = PIN_BASE;
+
+       for (i = 0; i < ARRAY_SIZE(rk30_gpio_banks); i++, bank++, pin += 32) {
+               spin_lock_init(&bank->lock);
+               bank->clk = clk_get(NULL, bank->chip.label);
+               clk_enable(bank->clk);
+               gpiochip_add(&bank->chip);
+
+               __raw_writel(0, bank->regbase + GPIO_INTEN);
+               for (j = 0; j < 32; j++) {
+                       unsigned int irq = gpio_to_irq(pin + j);
+                       irq_set_lockdep_class(irq, &gpio_lock_class);
+                       irq_set_chip_data(irq, bank);
+                       irq_set_chip_and_handler(irq, &rk30_gpio_irq_chip, handle_level_irq);
+                       set_irq_flags(irq, IRQF_VALID);
+               }
+
+               irq_set_handler_data(bank->irq, bank);
+               irq_set_chained_handler(bank->irq, rk30_gpio_irq_handler);
+       }
+       printk("%s: %d gpio irqs in %d banks\n", __func__, pin - PIN_BASE, ARRAY_SIZE(rk30_gpio_banks));
+}
+
+#ifdef CONFIG_PM
+__weak void rk30_setgpio_suspend_board(void)
+{
+}
+
+__weak void rk30_setgpio_resume_board(void)
+{
+}
+
+static int rk30_gpio_suspend(void)
+{
+       unsigned i;
+       
+       rk30_setgpio_suspend_board();
+
+       for (i = 0; i < ARRAY_SIZE(rk30_gpio_banks); i++) {
+               struct rk30_gpio_bank *bank = &rk30_gpio_banks[i];
+
+               bank->saved_wakeup = __raw_readl(bank->regbase + GPIO_INTEN);
+               __raw_writel(bank->suspend_wakeup, bank->regbase + GPIO_INTEN);
+
+               if (!bank->suspend_wakeup)
+                       clk_disable(bank->clk);
+       }
+
+       return 0;
+}
+
+static void rk30_gpio_resume(void)
+{
+       unsigned i;
+
+       for (i = 0; i < ARRAY_SIZE(rk30_gpio_banks); i++) {
+               struct rk30_gpio_bank *bank = &rk30_gpio_banks[i];
+               u32 isr;
+
+               if (!bank->suspend_wakeup)
+                       clk_enable(bank->clk);
+
+               /* keep enable for resume irq */
+               isr = __raw_readl(bank->regbase + GPIO_INT_STATUS);
+               __raw_writel(bank->saved_wakeup | (bank->suspend_wakeup & isr), bank->regbase + GPIO_INTEN);
+       }
+
+       rk30_setgpio_resume_board();
+}
+
+static struct syscore_ops rk30_gpio_syscore_ops = {
+       .suspend        = rk30_gpio_suspend,
+       .resume         = rk30_gpio_resume,
+};
+
+static int __init rk30_gpio_sysinit(void)
+{
+       register_syscore_ops(&rk30_gpio_syscore_ops);
+        return 0;
+}
+
+arch_initcall(rk30_gpio_sysinit);
+#endif