diff options
Diffstat (limited to 'drivers/gpio/gpio-wcove.c')
-rw-r--r-- | drivers/gpio/gpio-wcove.c | 65 |
1 files changed, 33 insertions, 32 deletions
diff --git a/drivers/gpio/gpio-wcove.c b/drivers/gpio/gpio-wcove.c index b5fbba5a783a..a19eeef6cf1e 100644 --- a/drivers/gpio/gpio-wcove.c +++ b/drivers/gpio/gpio-wcove.c @@ -73,6 +73,8 @@ enum ctrl_register { CTRL_IN, CTRL_OUT, + IRQ_STATUS, + IRQ_MASK, }; /* @@ -112,22 +114,29 @@ static inline int to_reg(int gpio, enum ctrl_register reg_type) return reg; } -static void wcove_update_irq_mask(struct wcove_gpio *wg, int gpio) +static inline int to_ireg(int gpio, enum ctrl_register type, unsigned int *mask) { - unsigned int reg, mask; + unsigned int reg = type == IRQ_STATUS ? IRQ_STATUS_BASE : IRQ_MASK_BASE; if (gpio < GROUP0_NR_IRQS) { - reg = IRQ_MASK_BASE; - mask = BIT(gpio % GROUP0_NR_IRQS); + reg += 0; + *mask = BIT(gpio); } else { - reg = IRQ_MASK_BASE + 1; - mask = BIT((gpio - GROUP0_NR_IRQS) % GROUP1_NR_IRQS); + reg += 1; + *mask = BIT(gpio - GROUP0_NR_IRQS); } + return reg; +} + +static void wcove_update_irq_mask(struct wcove_gpio *wg, int gpio) +{ + unsigned int mask, reg = to_ireg(gpio, IRQ_MASK, &mask); + if (wg->set_irq_mask) - regmap_update_bits(wg->regmap, reg, mask, mask); + regmap_set_bits(wg->regmap, reg, mask); else - regmap_update_bits(wg->regmap, reg, mask, 0); + regmap_clear_bits(wg->regmap, reg, mask); } static void wcove_update_irq_ctrl(struct wcove_gpio *wg, int gpio) @@ -207,9 +216,9 @@ static void wcove_gpio_set(struct gpio_chip *chip, unsigned int gpio, int value) return; if (value) - regmap_update_bits(wg->regmap, reg, 1, 1); + regmap_set_bits(wg->regmap, reg, 1); else - regmap_update_bits(wg->regmap, reg, 1, 0); + regmap_clear_bits(wg->regmap, reg, 1); } static int wcove_gpio_set_config(struct gpio_chip *chip, unsigned int gpio, @@ -324,7 +333,8 @@ static struct irq_chip wcove_irqchip = { static irqreturn_t wcove_gpio_irq_handler(int irq, void *data) { struct wcove_gpio *wg = (struct wcove_gpio *)data; - unsigned int pending, virq, gpio, mask, offset; + unsigned int virq, gpio; + unsigned long pending; u8 p[2]; if (regmap_bulk_read(wg->regmap, IRQ_STATUS_BASE, p, 2)) { @@ -339,15 +349,12 @@ static irqreturn_t wcove_gpio_irq_handler(int irq, void *data) /* Iterate until no interrupt is pending */ while (pending) { /* One iteration is for all pending bits */ - for_each_set_bit(gpio, (const unsigned long *)&pending, - WCOVE_GPIO_NUM) { - offset = (gpio > GROUP0_NR_IRQS) ? 1 : 0; - mask = (offset == 1) ? BIT(gpio - GROUP0_NR_IRQS) : - BIT(gpio); + for_each_set_bit(gpio, &pending, WCOVE_GPIO_NUM) { + unsigned int mask, reg = to_ireg(gpio, IRQ_STATUS, &mask); + virq = irq_find_mapping(wg->chip.irq.domain, gpio); handle_nested_irq(virq); - regmap_update_bits(wg->regmap, IRQ_STATUS_BASE + offset, - mask, mask); + regmap_set_bits(wg->regmap, reg, mask); } /* Next iteration */ @@ -367,30 +374,26 @@ static void wcove_gpio_dbg_show(struct seq_file *s, { unsigned int ctlo, ctli, irq_mask, irq_status; struct wcove_gpio *wg = gpiochip_get_data(chip); - int gpio, offset, group, ret = 0; + int gpio, mask, ret = 0; for (gpio = 0; gpio < WCOVE_GPIO_NUM; gpio++) { - group = gpio < GROUP0_NR_IRQS ? 0 : 1; ret += regmap_read(wg->regmap, to_reg(gpio, CTRL_OUT), &ctlo); ret += regmap_read(wg->regmap, to_reg(gpio, CTRL_IN), &ctli); - ret += regmap_read(wg->regmap, IRQ_MASK_BASE + group, - &irq_mask); - ret += regmap_read(wg->regmap, IRQ_STATUS_BASE + group, - &irq_status); + ret += regmap_read(wg->regmap, to_ireg(gpio, IRQ_MASK, &mask), &irq_mask); + ret += regmap_read(wg->regmap, to_ireg(gpio, IRQ_STATUS, &mask), &irq_status); if (ret) { pr_err("Failed to read registers: ctrl out/in or irq status/mask\n"); break; } - offset = gpio % 8; seq_printf(s, " gpio-%-2d %s %s %s %s ctlo=%2x,%s %s\n", gpio, ctlo & CTLO_DIR_OUT ? "out" : "in ", ctli & 0x1 ? "hi" : "lo", ctli & CTLI_INTCNT_NE ? "fall" : " ", ctli & CTLI_INTCNT_PE ? "rise" : " ", ctlo, - irq_mask & BIT(offset) ? "mask " : "unmask", - irq_status & BIT(offset) ? "pending" : " "); + irq_mask & mask ? "mask " : "unmask", + irq_status & mask ? "pending" : " "); } } @@ -434,7 +437,7 @@ static int wcove_gpio_probe(struct platform_device *pdev) wg->chip.get_direction = wcove_gpio_get_direction; wg->chip.get = wcove_gpio_get; wg->chip.set = wcove_gpio_set; - wg->chip.set_config = wcove_gpio_set_config, + wg->chip.set_config = wcove_gpio_set_config; wg->chip.base = -1; wg->chip.ngpio = WCOVE_VGPIO_NUM; wg->chip.can_sleep = true; @@ -473,14 +476,12 @@ static int wcove_gpio_probe(struct platform_device *pdev) } /* Enable GPIO0 interrupts */ - ret = regmap_update_bits(wg->regmap, IRQ_MASK_BASE, GPIO_IRQ0_MASK, - 0x00); + ret = regmap_clear_bits(wg->regmap, IRQ_MASK_BASE + 0, GPIO_IRQ0_MASK); if (ret) return ret; /* Enable GPIO1 interrupts */ - ret = regmap_update_bits(wg->regmap, IRQ_MASK_BASE + 1, GPIO_IRQ1_MASK, - 0x00); + ret = regmap_clear_bits(wg->regmap, IRQ_MASK_BASE + 1, GPIO_IRQ1_MASK); if (ret) return ret; |