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 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_gpio_chip(pin); u32 bit = gpio_to_bit(pin); //pin_to_bit 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); printk("[%s] GPIO%s%d: ", gpio_label, chip->label, i); if (!chip || !bit) { //seq_printf(s, "!chip || !bit\t"); printk("!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"); printk("pin=%d,level=%d\t", pin, GPIOGetPinLevel(chip,bit)); printk("\t"); } } //#endif }
int nmk_gpio_get(int gpio) { unsigned long base = gpio_to_base(gpio); u32 bit = gpio_to_bit(gpio); return readl(base + GPIO_DAT) & bit; }
static inline void pad_set_mode(int gpio_index, int sfio_or_gpio) { struct gpio_bank * const regs = get_gpio_bank_regs(gpio_index); int port = gpio_index_to_port(gpio_index); int bit = gpio_to_bit(gpio_index); write32((1 << (bit + GPIO_GPIOS_PER_PORT)) | (sfio_or_gpio << bit), ®s->config_mask[port]); }
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); }
void nmk_gpio_set(int gpio, int val) { unsigned long base = gpio_to_base(gpio); u32 bit = gpio_to_bit(gpio); if (val) writel(bit, base + GPIO_DATS); else writel(bit, base + GPIO_DATC); }
void nmk_gpio_dir(int gpio, int dir) { unsigned long base = gpio_to_base(gpio); u32 bit = gpio_to_bit(gpio); if (dir) writel(bit, base + GPIO_DIRS); else writel(bit, base + GPIO_DIRC); }
static inline void pad_set_gpio_out(int gpio_index, int val) { struct gpio_bank * const regs = get_gpio_bank_regs(gpio_index); int port = gpio_index_to_port(gpio_index); int bit = gpio_to_bit(gpio_index); write32((1 << (bit + GPIO_GPIOS_PER_PORT)) | (val << bit), ®s->out_value_mask[port]); write32((1 << (bit + GPIO_GPIOS_PER_PORT)) | (1 << bit), ®s->out_enable_mask[port]); }
void nmk_gpio_af(int gpio, int alternate_function) { unsigned long base = gpio_to_base(gpio); u32 bit = gpio_to_bit(gpio); u32 afunc, bfunc; /* alternate function is 0..3, with one bit per register */ afunc = readl(base + GPIO_AFSLA) & ~bit; bfunc = readl(base + GPIO_AFSLB) & ~bit; if (alternate_function & 1) afunc |= bit; if (alternate_function & 2) bfunc |= bit; writel(afunc, base + GPIO_AFSLA); writel(bfunc, base + GPIO_AFSLB); }
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 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; }