diff options
Diffstat (limited to 'drivers/pinctrl/nuvoton/pinctrl-wpcm450.c')
-rw-r--r-- | drivers/pinctrl/nuvoton/pinctrl-wpcm450.c | 48 |
1 files changed, 34 insertions, 14 deletions
diff --git a/drivers/pinctrl/nuvoton/pinctrl-wpcm450.c b/drivers/pinctrl/nuvoton/pinctrl-wpcm450.c index 8193b92da403..2d1c1652cfd9 100644 --- a/drivers/pinctrl/nuvoton/pinctrl-wpcm450.c +++ b/drivers/pinctrl/nuvoton/pinctrl-wpcm450.c @@ -49,7 +49,6 @@ struct wpcm450_bank; struct wpcm450_gpio { struct gpio_chip gc; struct wpcm450_pinctrl *pctrl; - struct irq_chip irqc; const struct wpcm450_bank *bank; }; @@ -142,7 +141,8 @@ static void wpcm450_gpio_irq_ack(struct irq_data *d) static void wpcm450_gpio_irq_mask(struct irq_data *d) { - struct wpcm450_gpio *gpio = gpiochip_get_data(irq_data_get_irq_chip_data(d)); + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct wpcm450_gpio *gpio = gpiochip_get_data(gc); struct wpcm450_pinctrl *pctrl = gpio->pctrl; unsigned long flags; unsigned long even; @@ -157,11 +157,14 @@ static void wpcm450_gpio_irq_mask(struct irq_data *d) __assign_bit(bit, &even, 0); iowrite32(even, pctrl->gpio_base + WPCM450_GPEVEN); raw_spin_unlock_irqrestore(&pctrl->lock, flags); + + gpiochip_disable_irq(gc, irqd_to_hwirq(d)); } static void wpcm450_gpio_irq_unmask(struct irq_data *d) { - struct wpcm450_gpio *gpio = gpiochip_get_data(irq_data_get_irq_chip_data(d)); + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct wpcm450_gpio *gpio = gpiochip_get_data(gc); struct wpcm450_pinctrl *pctrl = gpio->pctrl; unsigned long flags; unsigned long even; @@ -171,6 +174,8 @@ static void wpcm450_gpio_irq_unmask(struct irq_data *d) if (bit < 0) return; + gpiochip_enable_irq(gc, irqd_to_hwirq(d)); + raw_spin_lock_irqsave(&pctrl->lock, flags); even = ioread32(pctrl->gpio_base + WPCM450_GPEVEN); __assign_bit(bit, &even, 1); @@ -293,6 +298,8 @@ static const struct irq_chip wpcm450_gpio_irqchip = { .irq_unmask = wpcm450_gpio_irq_unmask, .irq_mask = wpcm450_gpio_irq_mask, .irq_set_type = wpcm450_gpio_set_irq_type, + .flags = IRQCHIP_IMMUTABLE, + GPIOCHIP_IRQ_RESOURCE_HELPERS, }; static void wpcm450_gpio_irqhandler(struct irq_desc *desc) @@ -621,6 +628,9 @@ struct wpcm450_pincfg { int fn1, reg1, bit1; }; +/* Add this value to bit0 or bit1 to indicate that the MFSEL bit is inverted */ +#define INV BIT(5) + static const struct wpcm450_pincfg pincfg[] = { /* PIN FUNCTION 1 FUNCTION 2 */ WPCM450_PINCFG(0, none, NONE, 0, none, NONE, 0), @@ -658,7 +668,7 @@ static const struct wpcm450_pincfg pincfg[] = { WPCM450_PINCFG(32, scs1, MFSEL1, 3, none, NONE, 0), WPCM450_PINCFG(33, scs2, MFSEL1, 4, none, NONE, 0), - WPCM450_PINCFG(34, scs3, MFSEL1, 5, none, NONE, 0), + WPCM450_PINCFG(34, scs3, MFSEL1, 5 | INV, none, NONE, 0), WPCM450_PINCFG(35, xcs1, MFSEL1, 29, none, NONE, 0), WPCM450_PINCFG(36, xcs2, MFSEL1, 28, none, NONE, 0), WPCM450_PINCFG(37, none, NONE, 0, none, NONE, 0), /* DVO */ @@ -718,8 +728,8 @@ static const struct wpcm450_pincfg pincfg[] = { WPCM450_PINCFG(90, r2err, MFSEL1, 15, none, NONE, 0), WPCM450_PINCFG(91, r2md, MFSEL1, 16, none, NONE, 0), WPCM450_PINCFG(92, r2md, MFSEL1, 16, none, NONE, 0), - WPCM450_PINCFG(93, kbcc, MFSEL1, 17, none, NONE, 0), - WPCM450_PINCFG(94, kbcc, MFSEL1, 17, none, NONE, 0), + WPCM450_PINCFG(93, kbcc, MFSEL1, 17 | INV, none, NONE, 0), + WPCM450_PINCFG(94, kbcc, MFSEL1, 17 | INV, none, NONE, 0), WPCM450_PINCFG(95, none, NONE, 0, none, NONE, 0), WPCM450_PINCFG(96, none, NONE, 0, none, NONE, 0), @@ -793,6 +803,19 @@ static const struct pinctrl_pin_desc wpcm450_pins[] = { WPCM450_PIN(124), WPCM450_PIN(125), WPCM450_PIN(126), WPCM450_PIN(127), }; +/* Helper function to update MFSEL field according to the selected function */ +static void wpcm450_update_mfsel(struct regmap *gcr_regmap, int reg, int bit, int fn, int fn_selected) +{ + bool value = (fn == fn_selected); + + if (bit & INV) { + value = !value; + bit &= ~INV; + } + + regmap_update_bits(gcr_regmap, reg, BIT(bit), value ? BIT(bit) : 0); +} + /* Enable mode in pin group */ static void wpcm450_setfunc(struct regmap *gcr_regmap, const unsigned int *pin, int npins, int func) @@ -804,13 +827,11 @@ static void wpcm450_setfunc(struct regmap *gcr_regmap, const unsigned int *pin, cfg = &pincfg[pin[i]]; if (func == fn_gpio || cfg->fn0 == func || cfg->fn1 == func) { if (cfg->reg0) - regmap_update_bits(gcr_regmap, cfg->reg0, - BIT(cfg->bit0), - (cfg->fn0 == func) ? BIT(cfg->bit0) : 0); + wpcm450_update_mfsel(gcr_regmap, cfg->reg0, + cfg->bit0, cfg->fn0, func); if (cfg->reg1) - regmap_update_bits(gcr_regmap, cfg->reg1, - BIT(cfg->bit1), - (cfg->fn1 == func) ? BIT(cfg->bit1) : 0); + wpcm450_update_mfsel(gcr_regmap, cfg->reg1, + cfg->bit1, cfg->fn1, func); } } } @@ -1068,9 +1089,8 @@ static int wpcm450_gpio_register(struct platform_device *pdev, gpio->gc.fwnode = child; gpio->gc.add_pin_ranges = wpcm450_gpio_add_pin_ranges; - gpio->irqc = wpcm450_gpio_irqchip; girq = &gpio->gc.irq; - girq->chip = &gpio->irqc; + gpio_irq_chip_set_chip(girq, &wpcm450_gpio_irqchip); girq->parent_handler = wpcm450_gpio_irqhandler; girq->parents = devm_kcalloc(dev, WPCM450_NUM_GPIO_IRQS, sizeof(*girq->parents), GFP_KERNEL); |