summaryrefslogtreecommitdiff
path: root/drivers/gpio/gpio-wcove.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpio/gpio-wcove.c')
-rw-r--r--drivers/gpio/gpio-wcove.c65
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;