Lines Matching +full:gpio +full:- +full:cfg
1 // SPDX-License-Identifier: GPL-2.0
2 // Copyright (c) 2016-2018 Nuvoton Technology corporation.
4 // Copyright (c) 2021-2022 Jonathan Neuschäfer
7 // - Pin mux registers, in the GCR (general control registers) block
8 // - GPIO registers, specific to each GPIO bank
9 // - GPIO event (interrupt) registers, located centrally in the GPIO register
10 // block, shared between all GPIO banks
14 #include <linux/gpio/driver.h>
24 #include <linux/pinctrl/pinconf-generic.h>
35 /* GPIO event (interrupt) registers */
84 u8 num_irqs; /* Number of IRQ-capable GPIOs in this bank */
85 u8 first_irq_gpio; /* First IRQ-capable GPIO in this bank */
100 static int wpcm450_gpio_irq_bitnum(struct wpcm450_gpio *gpio, struct irq_data *d) in wpcm450_gpio_irq_bitnum() argument
102 const struct wpcm450_bank *bank = gpio->bank; in wpcm450_gpio_irq_bitnum()
105 if (hwirq < bank->first_irq_gpio) in wpcm450_gpio_irq_bitnum()
106 return -EINVAL; in wpcm450_gpio_irq_bitnum()
108 if (hwirq - bank->first_irq_gpio >= bank->num_irqs) in wpcm450_gpio_irq_bitnum()
109 return -EINVAL; in wpcm450_gpio_irq_bitnum()
111 return hwirq - bank->first_irq_gpio + bank->first_irq_bit; in wpcm450_gpio_irq_bitnum()
114 static int wpcm450_irq_bitnum_to_gpio(struct wpcm450_gpio *gpio, int bitnum) in wpcm450_irq_bitnum_to_gpio() argument
116 const struct wpcm450_bank *bank = gpio->bank; in wpcm450_irq_bitnum_to_gpio()
118 if (bitnum < bank->first_irq_bit) in wpcm450_irq_bitnum_to_gpio()
119 return -EINVAL; in wpcm450_irq_bitnum_to_gpio()
121 if (bitnum - bank->first_irq_bit > bank->num_irqs) in wpcm450_irq_bitnum_to_gpio()
122 return -EINVAL; in wpcm450_irq_bitnum_to_gpio()
124 return bitnum - bank->first_irq_bit + bank->first_irq_gpio; in wpcm450_irq_bitnum_to_gpio()
129 struct wpcm450_gpio *gpio = gpiochip_get_data(irq_data_get_irq_chip_data(d)); in wpcm450_gpio_irq_ack() local
130 struct wpcm450_pinctrl *pctrl = gpio->pctrl; in wpcm450_gpio_irq_ack()
134 bit = wpcm450_gpio_irq_bitnum(gpio, d); in wpcm450_gpio_irq_ack()
138 raw_spin_lock_irqsave(&pctrl->lock, flags); in wpcm450_gpio_irq_ack()
139 iowrite32(BIT(bit), pctrl->gpio_base + WPCM450_GPEVST); in wpcm450_gpio_irq_ack()
140 raw_spin_unlock_irqrestore(&pctrl->lock, flags); in wpcm450_gpio_irq_ack()
145 struct wpcm450_gpio *gpio = gpiochip_get_data(irq_data_get_irq_chip_data(d)); in wpcm450_gpio_irq_mask() local
146 struct wpcm450_pinctrl *pctrl = gpio->pctrl; in wpcm450_gpio_irq_mask()
151 bit = wpcm450_gpio_irq_bitnum(gpio, d); in wpcm450_gpio_irq_mask()
155 raw_spin_lock_irqsave(&pctrl->lock, flags); in wpcm450_gpio_irq_mask()
156 even = ioread32(pctrl->gpio_base + WPCM450_GPEVEN); in wpcm450_gpio_irq_mask()
158 iowrite32(even, pctrl->gpio_base + WPCM450_GPEVEN); in wpcm450_gpio_irq_mask()
159 raw_spin_unlock_irqrestore(&pctrl->lock, flags); in wpcm450_gpio_irq_mask()
164 struct wpcm450_gpio *gpio = gpiochip_get_data(irq_data_get_irq_chip_data(d)); in wpcm450_gpio_irq_unmask() local
165 struct wpcm450_pinctrl *pctrl = gpio->pctrl; in wpcm450_gpio_irq_unmask()
170 bit = wpcm450_gpio_irq_bitnum(gpio, d); in wpcm450_gpio_irq_unmask()
174 raw_spin_lock_irqsave(&pctrl->lock, flags); in wpcm450_gpio_irq_unmask()
175 even = ioread32(pctrl->gpio_base + WPCM450_GPEVEN); in wpcm450_gpio_irq_unmask()
177 iowrite32(even, pctrl->gpio_base + WPCM450_GPEVEN); in wpcm450_gpio_irq_unmask()
178 raw_spin_unlock_irqrestore(&pctrl->lock, flags); in wpcm450_gpio_irq_unmask()
182 * This is an implementation of the gpio_chip->get() function, for use in
183 * wpcm450_gpio_fix_evpol. Unfortunately, we can't use the bgpio-provided
184 * implementation there, because it would require taking gpio_chip->bgpio_lock,
188 static int wpcm450_gpio_get(struct wpcm450_gpio *gpio, int offset) in wpcm450_gpio_get() argument
190 void __iomem *reg = gpio->pctrl->gpio_base + gpio->bank->datain; in wpcm450_gpio_get()
194 raw_spin_lock_irqsave(&gpio->pctrl->lock, flags); in wpcm450_gpio_get()
196 raw_spin_unlock_irqrestore(&gpio->pctrl->lock, flags); in wpcm450_gpio_get()
202 * Since the GPIO controller does not support dual-edge triggered interrupts
205 * specified emulated dual-edge triggered interrupts, so that the next edge can
208 static void wpcm450_gpio_fix_evpol(struct wpcm450_gpio *gpio, unsigned long all) in wpcm450_gpio_fix_evpol() argument
210 struct wpcm450_pinctrl *pctrl = gpio->pctrl; in wpcm450_gpio_fix_evpol()
214 int offset = wpcm450_irq_bitnum_to_gpio(gpio, bit); in wpcm450_gpio_fix_evpol()
220 level = wpcm450_gpio_get(gpio, offset); in wpcm450_gpio_fix_evpol()
223 raw_spin_lock_irqsave(&pctrl->lock, flags); in wpcm450_gpio_fix_evpol()
224 evpol = ioread32(pctrl->gpio_base + WPCM450_GPEVPOL); in wpcm450_gpio_fix_evpol()
226 iowrite32(evpol, pctrl->gpio_base + WPCM450_GPEVPOL); in wpcm450_gpio_fix_evpol()
227 raw_spin_unlock_irqrestore(&pctrl->lock, flags); in wpcm450_gpio_fix_evpol()
229 } while (wpcm450_gpio_get(gpio, offset) != level); in wpcm450_gpio_fix_evpol()
235 struct wpcm450_gpio *gpio = gpiochip_get_data(irq_data_get_irq_chip_data(d)); in wpcm450_gpio_set_irq_type() local
236 struct wpcm450_pinctrl *pctrl = gpio->pctrl; in wpcm450_gpio_set_irq_type()
242 bit = wpcm450_gpio_irq_bitnum(gpio, d); in wpcm450_gpio_set_irq_type()
248 raw_spin_lock_irqsave(&pctrl->lock, flags); in wpcm450_gpio_set_irq_type()
249 evtype = ioread32(pctrl->gpio_base + WPCM450_GPEVTYPE); in wpcm450_gpio_set_irq_type()
250 evpol = ioread32(pctrl->gpio_base + WPCM450_GPEVPOL); in wpcm450_gpio_set_irq_type()
251 __assign_bit(bit, &pctrl->both_edges, 0); in wpcm450_gpio_set_irq_type()
271 __assign_bit(bit, &pctrl->both_edges, 1); in wpcm450_gpio_set_irq_type()
274 ret = -EINVAL; in wpcm450_gpio_set_irq_type()
276 iowrite32(evtype, pctrl->gpio_base + WPCM450_GPEVTYPE); in wpcm450_gpio_set_irq_type()
277 iowrite32(evpol, pctrl->gpio_base + WPCM450_GPEVPOL); in wpcm450_gpio_set_irq_type()
280 iowrite32(BIT(bit), pctrl->gpio_base + WPCM450_GPEVST); in wpcm450_gpio_set_irq_type()
282 raw_spin_unlock_irqrestore(&pctrl->lock, flags); in wpcm450_gpio_set_irq_type()
285 wpcm450_gpio_fix_evpol(gpio, BIT(bit)); in wpcm450_gpio_set_irq_type()
291 .name = "WPCM450-GPIO-IRQ",
300 struct wpcm450_gpio *gpio = gpiochip_get_data(irq_desc_get_handler_data(desc)); in wpcm450_gpio_irqhandler() local
301 struct wpcm450_pinctrl *pctrl = gpio->pctrl; in wpcm450_gpio_irqhandler()
308 ours = GENMASK(gpio->bank->num_irqs - 1, 0) << gpio->bank->first_irq_bit; in wpcm450_gpio_irqhandler()
310 raw_spin_lock_irqsave(&pctrl->lock, flags); in wpcm450_gpio_irqhandler()
312 pending = ioread32(pctrl->gpio_base + WPCM450_GPEVST); in wpcm450_gpio_irqhandler()
313 pending &= ioread32(pctrl->gpio_base + WPCM450_GPEVEN); in wpcm450_gpio_irqhandler()
316 raw_spin_unlock_irqrestore(&pctrl->lock, flags); in wpcm450_gpio_irqhandler()
318 if (pending & pctrl->both_edges) in wpcm450_gpio_irqhandler()
319 wpcm450_gpio_fix_evpol(gpio, pending & pctrl->both_edges); in wpcm450_gpio_irqhandler()
323 int offset = wpcm450_irq_bitnum_to_gpio(gpio, bit); in wpcm450_gpio_irqhandler()
325 generic_handle_domain_irq(gpio->gc.irq.domain, offset); in wpcm450_gpio_irqhandler()
464 /* add placeholder for none/gpio */
465 WPCM450_GRP(gpio),
548 WPCM450_FUNC(gpio, WPCM450_GRPS);
612 WPCM450_MKFUNC(gpio),
759 #define WPCM450_PIN(n) PINCTRL_PIN(n, "gpio" #n)
800 const struct wpcm450_pincfg *cfg; in wpcm450_setfunc() local
804 cfg = &pincfg[pin[i]]; in wpcm450_setfunc()
805 if (func == fn_gpio || cfg->fn0 == func || cfg->fn1 == func) { in wpcm450_setfunc()
806 if (cfg->reg0) in wpcm450_setfunc()
807 regmap_update_bits(gcr_regmap, cfg->reg0, in wpcm450_setfunc()
808 BIT(cfg->bit0), in wpcm450_setfunc()
809 (cfg->fn0 == func) ? BIT(cfg->bit0) : 0); in wpcm450_setfunc()
810 if (cfg->reg1) in wpcm450_setfunc()
811 regmap_update_bits(gcr_regmap, cfg->reg1, in wpcm450_setfunc()
812 BIT(cfg->bit1), in wpcm450_setfunc()
813 (cfg->fn1 == func) ? BIT(cfg->bit1) : 0); in wpcm450_setfunc()
892 wpcm450_setfunc(pctrl->gcr_regmap, wpcm450_groups[group].pins, in wpcm450_pinmux_set_mux()
905 static int debounce_bitnum(int gpio) in debounce_bitnum() argument
907 if (gpio >= 0 && gpio < 16) in debounce_bitnum()
908 return gpio; in debounce_bitnum()
909 return -EINVAL; in debounce_bitnum()
927 raw_spin_lock_irqsave(&pctrl->lock, flags); in wpcm450_config_get()
928 reg = ioread32(pctrl->gpio_base + WPCM450_GPEVDBNC); in wpcm450_config_get()
929 raw_spin_unlock_irqrestore(&pctrl->lock, flags); in wpcm450_config_get()
934 return -ENOTSUPP; in wpcm450_config_get()
955 raw_spin_lock_irqsave(&pctrl->lock, flags); in wpcm450_config_set_one()
956 reg = ioread32(pctrl->gpio_base + WPCM450_GPEVDBNC); in wpcm450_config_set_one()
958 iowrite32(reg, pctrl->gpio_base + WPCM450_GPEVDBNC); in wpcm450_config_set_one()
959 raw_spin_unlock_irqrestore(&pctrl->lock, flags); in wpcm450_config_set_one()
962 return -ENOTSUPP; in wpcm450_config_set_one()
972 while (num_configs--) { in wpcm450_config_set()
988 .name = "wpcm450-pinctrl",
1000 struct wpcm450_gpio *gpio = gpiochip_get_data(chip); in wpcm450_gpio_set_config() local
1002 return wpcm450_config_set_one(gpio->pctrl, offset, config); in wpcm450_gpio_set_config()
1007 struct wpcm450_gpio *gpio = gpiochip_get_data(chip); in wpcm450_gpio_add_pin_ranges() local
1008 const struct wpcm450_bank *bank = gpio->bank; in wpcm450_gpio_add_pin_ranges()
1010 return gpiochip_add_pin_range(&gpio->gc, dev_name(gpio->pctrl->dev), in wpcm450_gpio_add_pin_ranges()
1011 0, bank->base, bank->length); in wpcm450_gpio_add_pin_ranges()
1017 struct device *dev = &pdev->dev; in wpcm450_gpio_register()
1021 pctrl->gpio_base = devm_platform_ioremap_resource(pdev, 0); in wpcm450_gpio_register()
1022 if (IS_ERR(pctrl->gpio_base)) in wpcm450_gpio_register()
1023 return dev_err_probe(dev, PTR_ERR(pctrl->gpio_base), in wpcm450_gpio_register()
1024 "Resource fail for GPIO controller\n"); in wpcm450_gpio_register()
1032 struct wpcm450_gpio *gpio; in wpcm450_gpio_register() local
1037 if (!fwnode_property_read_bool(child, "gpio-controller")) in wpcm450_gpio_register()
1044 gpio = &pctrl->gpio_bank[reg]; in wpcm450_gpio_register()
1045 gpio->pctrl = pctrl; in wpcm450_gpio_register()
1048 return dev_err_probe(dev, -EINVAL, in wpcm450_gpio_register()
1049 "GPIO index %d out of range!\n", reg); in wpcm450_gpio_register()
1052 gpio->bank = bank; in wpcm450_gpio_register()
1054 dat = pctrl->gpio_base + bank->datain; in wpcm450_gpio_register()
1055 if (bank->dataout) { in wpcm450_gpio_register()
1056 set = pctrl->gpio_base + bank->dataout; in wpcm450_gpio_register()
1057 dirout = pctrl->gpio_base + bank->cfg0; in wpcm450_gpio_register()
1061 ret = bgpio_init(&gpio->gc, dev, 4, in wpcm450_gpio_register()
1064 return dev_err_probe(dev, ret, "GPIO initialization failed\n"); in wpcm450_gpio_register()
1066 gpio->gc.ngpio = bank->length; in wpcm450_gpio_register()
1067 gpio->gc.set_config = wpcm450_gpio_set_config; in wpcm450_gpio_register()
1068 gpio->gc.fwnode = child; in wpcm450_gpio_register()
1069 gpio->gc.add_pin_ranges = wpcm450_gpio_add_pin_ranges; in wpcm450_gpio_register()
1071 gpio->irqc = wpcm450_gpio_irqchip; in wpcm450_gpio_register()
1072 girq = &gpio->gc.irq; in wpcm450_gpio_register()
1073 girq->chip = &gpio->irqc; in wpcm450_gpio_register()
1074 girq->parent_handler = wpcm450_gpio_irqhandler; in wpcm450_gpio_register()
1075 girq->parents = devm_kcalloc(dev, WPCM450_NUM_GPIO_IRQS, in wpcm450_gpio_register()
1076 sizeof(*girq->parents), GFP_KERNEL); in wpcm450_gpio_register()
1077 if (!girq->parents) in wpcm450_gpio_register()
1078 return -ENOMEM; in wpcm450_gpio_register()
1079 girq->default_type = IRQ_TYPE_NONE; in wpcm450_gpio_register()
1080 girq->handler = handle_bad_irq; in wpcm450_gpio_register()
1082 girq->num_parents = 0; in wpcm450_gpio_register()
1092 girq->parents[i] = irq; in wpcm450_gpio_register()
1093 girq->num_parents++; in wpcm450_gpio_register()
1096 ret = devm_gpiochip_add_data(dev, &gpio->gc, gpio); in wpcm450_gpio_register()
1098 return dev_err_probe(dev, ret, "Failed to add GPIO chip\n"); in wpcm450_gpio_register()
1106 struct device *dev = &pdev->dev; in wpcm450_pinctrl_probe()
1112 return -ENOMEM; in wpcm450_pinctrl_probe()
1114 pctrl->dev = &pdev->dev; in wpcm450_pinctrl_probe()
1115 raw_spin_lock_init(&pctrl->lock); in wpcm450_pinctrl_probe()
1118 pctrl->gcr_regmap = in wpcm450_pinctrl_probe()
1119 syscon_regmap_lookup_by_compatible("nuvoton,wpcm450-gcr"); in wpcm450_pinctrl_probe()
1120 if (IS_ERR(pctrl->gcr_regmap)) in wpcm450_pinctrl_probe()
1121 return dev_err_probe(dev, PTR_ERR(pctrl->gcr_regmap), in wpcm450_pinctrl_probe()
1122 "Failed to find nuvoton,wpcm450-gcr\n"); in wpcm450_pinctrl_probe()
1124 pctrl->pctldev = devm_pinctrl_register(dev, in wpcm450_pinctrl_probe()
1126 if (IS_ERR(pctrl->pctldev)) in wpcm450_pinctrl_probe()
1127 return dev_err_probe(dev, PTR_ERR(pctrl->pctldev), in wpcm450_pinctrl_probe()
1138 { .compatible = "nuvoton,wpcm450-pinctrl" },
1146 .name = "wpcm450-pinctrl",
1154 MODULE_DESCRIPTION("Nuvoton WPCM450 Pinctrl and GPIO driver");