From d37628c897fb42a9e365ea44df9503b3607e0945 Mon Sep 17 00:00:00 2001 From: kfx Date: Thu, 12 Jul 2012 10:50:10 +0800 Subject: [PATCH] rk2928: gpio enable & iomux enable & fpga keypad init --- arch/arm/mach-rk2928/Makefile | 2 +- arch/arm/mach-rk2928/board-rk2928-fpga-key.c | 53 ++ arch/arm/mach-rk2928/common.c | 4 +- arch/arm/mach-rk2928/devices.c | 13 + arch/arm/mach-rk2928/include/mach/board.h | 1 + arch/arm/mach-rk2928/include/mach/gpio.h | 1 + arch/arm/mach-rk2928/iomux.c | 2 +- drivers/gpio/Makefile | 1 + drivers/gpio/gpio-rk2928.c | 487 +++++++++++++++++++ 9 files changed, 560 insertions(+), 4 deletions(-) create mode 100755 arch/arm/mach-rk2928/board-rk2928-fpga-key.c create mode 100755 drivers/gpio/gpio-rk2928.c diff --git a/arch/arm/mach-rk2928/Makefile b/arch/arm/mach-rk2928/Makefile index 81ab4330f097..6a734d2980e3 100644 --- a/arch/arm/mach-rk2928/Makefile +++ b/arch/arm/mach-rk2928/Makefile @@ -6,4 +6,4 @@ obj-y += devices.o obj-y += iomux.o obj-$(CONFIG_PM) += pm.o -obj-$(CONFIG_MACH_RK2928_FPGA) += board-rk2928-fpga.o +obj-$(CONFIG_MACH_RK2928_FPGA) += board-rk2928-fpga.o board-rk2928-fpga-key.o diff --git a/arch/arm/mach-rk2928/board-rk2928-fpga-key.c b/arch/arm/mach-rk2928/board-rk2928-fpga-key.c new file mode 100755 index 000000000000..8a86e544c1dd --- /dev/null +++ b/arch/arm/mach-rk2928/board-rk2928-fpga-key.c @@ -0,0 +1,53 @@ +#include +#include + +#define EV_ENCALL KEY_F4 +#define EV_MENU KEY_F1 + +#define PRESS_LEV_LOW 1 +#define PRESS_LEV_HIGH 0 + +static struct rk29_keys_button key_button[] = { + { + .desc = "menu", + .code = EV_MENU, + .gpio = RK2928_PIN3_PB2, + .active_low = PRESS_LEV_LOW, + }, + { + .desc = "vol+", + .code = KEY_VOLUMEUP, + .gpio = RK2928_PIN3_PB1, + .active_low = PRESS_LEV_LOW, + }, + { + .desc = "vol-", + .code = KEY_VOLUMEDOWN, + .gpio = RK2928_PIN3_PB0, + .active_low = PRESS_LEV_LOW, + }, + { + .desc = "home", + .code = KEY_HOME, + .gpio = RK2928_PIN3_PB3, + .active_low = PRESS_LEV_LOW, + }, + { + .desc = "esc", + .code = KEY_BACK, + .gpio = RK2928_PIN3_PB4, + .active_low = PRESS_LEV_LOW, + }, + { + .desc = "key6", + .code = KEY_CAMERA, + .gpio = RK2928_PIN3_PB5, + .active_low = PRESS_LEV_LOW, + }, +}; +struct rk29_keys_platform_data rk29_keys_pdata = { + .buttons = key_button, + .nbuttons = ARRAY_SIZE(key_button), + .chn = -1, //chn: 0-7, if do not use ADC,set 'chn' -1 +}; + diff --git a/arch/arm/mach-rk2928/common.c b/arch/arm/mach-rk2928/common.c index 170cc3cf715c..6f8d458fad64 100644 --- a/arch/arm/mach-rk2928/common.c +++ b/arch/arm/mach-rk2928/common.c @@ -118,7 +118,7 @@ void __init rk2928_init_irq(void) #ifdef CONFIG_FIQ rk_fiq_init(); #endif -// rk30_gpio_init(); + rk2928_gpio_init(); } extern void __init rk2928_map_common_io(void); @@ -134,7 +134,7 @@ void __init rk2928_map_io(void) rk2928_l2_cache_init(); // ddr_init(DDR_TYPE, DDR_FREQ); // clk_disable_unused(); -// rk2928_iomux_init(); + rk2928_iomux_init(); rk2928_boot_mode_init(); } diff --git a/arch/arm/mach-rk2928/devices.c b/arch/arm/mach-rk2928/devices.c index 6b72f1019092..bbc9868cf2a6 100755 --- a/arch/arm/mach-rk2928/devices.c +++ b/arch/arm/mach-rk2928/devices.c @@ -490,12 +490,25 @@ static void __init rk2928_init_spim(void) platform_device_register(&rk29xx_device_spi0m); #endif } +#ifdef CONFIG_KEYS_RK29 +extern struct rk29_keys_platform_data rk29_keys_pdata; +static struct platform_device device_keys = { + .name = "rk29-keypad", + .id = -1, + .dev = { + .platform_data = &rk29_keys_pdata, + }, +}; +#endif static int __init rk2928_init_devices(void) { rk2928_init_dma(); rk2928_init_uart(); rk2928_init_i2c(); rk2928_init_spim(); +#ifdef CONFIG_KEYS_RK29 + platform_device_register(&device_keys); +#endif #if defined(CONFIG_FIQ_DEBUGGER) && defined(DEBUG_UART_PHYS) rk_serial_debug_init(DEBUG_UART_BASE, IRQ_DEBUG_UART, IRQ_UART_SIGNAL, -1); #endif diff --git a/arch/arm/mach-rk2928/include/mach/board.h b/arch/arm/mach-rk2928/include/mach/board.h index d4ec846e7d76..fad769ca8b30 100644 --- a/arch/arm/mach-rk2928/include/mach/board.h +++ b/arch/arm/mach-rk2928/include/mach/board.h @@ -24,6 +24,7 @@ struct machine_desc; void __init rk2928_fixup(struct machine_desc *desc, struct tag *tags, char **cmdline, struct meminfo *mi); void __init rk2928_clock_data_init(unsigned long gpll,unsigned long cpll,u32 flags); void __init board_clock_init(void); +void __init rk2928_iomux_init(void); void board_gpio_suspend(void); void board_gpio_resume(void); void __sramfunc board_pmu_suspend(void); diff --git a/arch/arm/mach-rk2928/include/mach/gpio.h b/arch/arm/mach-rk2928/include/mach/gpio.h index 913896953b09..d7e713e035ce 100644 --- a/arch/arm/mach-rk2928/include/mach/gpio.h +++ b/arch/arm/mach-rk2928/include/mach/gpio.h @@ -353,6 +353,7 @@ #include #ifndef __ASSEMBLY__ +extern void __init rk2928_gpio_init(void); static inline int gpio_to_irq(unsigned gpio) { return gpio - PIN_BASE + NR_GIC_IRQS; diff --git a/arch/arm/mach-rk2928/iomux.c b/arch/arm/mach-rk2928/iomux.c index 44968e1b25b9..11b2dcaf7b8a 100755 --- a/arch/arm/mach-rk2928/iomux.c +++ b/arch/arm/mach-rk2928/iomux.c @@ -164,7 +164,7 @@ void rk30_mux_set(struct mux_config *cfg) } -int __init rk30_iomux_init(void) +int __init rk2928_iomux_init(void) { int i; printk("%s\n",__func__); diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 441f198aac86..402c46f345c9 100755 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -47,6 +47,7 @@ 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_ARCH_RK2928) += gpio-rk2928.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-rk2928.c b/drivers/gpio/gpio-rk2928.c new file mode 100755 index 000000000000..8726c7e7035c --- /dev/null +++ b/drivers/gpio/gpio-rk2928.c @@ -0,0 +1,487 @@ +/* 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#define MAX_PIN RK2928_PIN3_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 = ID < 6 ? PIN_BASE + ID*NUM_GROUP : PIN_BASE + 5*NUM_GROUP, \ + .ngpio = ID < 6 ? NUM_GROUP : 16, \ + }, \ + .id = ID, \ + .irq = IRQ_GPIO##ID, \ + .regbase = (unsigned char __iomem *) RK2928_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), +}; + +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); + if(offset>=16) + rk30_gpio_bit_op((void *__iomem) RK2928_GRF_BASE, GRF_GPIO0H_PULL + bank->id * 8, (1<id * 8, (1<<(offset+16)) | 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 rk2928_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++) { + 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); + if (pin > MAX_PIN) + break; + 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); + pin++; + } + + 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 -- 2.34.1