Lines Matching +full:pctrl +full:- +full:syscon
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
17 #include <linux/mfd/syscon.h>
24 #include <linux/pinctrl/pinconf-generic.h>
51 struct wpcm450_pinctrl *pctrl; member
83 u8 num_irqs; /* Number of IRQ-capable GPIOs in this bank */
84 u8 first_irq_gpio; /* First IRQ-capable GPIO in this bank */
101 const struct wpcm450_bank *bank = gpio->bank; in wpcm450_gpio_irq_bitnum()
104 if (hwirq < bank->first_irq_gpio) in wpcm450_gpio_irq_bitnum()
105 return -EINVAL; in wpcm450_gpio_irq_bitnum()
107 if (hwirq - bank->first_irq_gpio >= bank->num_irqs) in wpcm450_gpio_irq_bitnum()
108 return -EINVAL; in wpcm450_gpio_irq_bitnum()
110 return hwirq - bank->first_irq_gpio + bank->first_irq_bit; in wpcm450_gpio_irq_bitnum()
115 const struct wpcm450_bank *bank = gpio->bank; in wpcm450_irq_bitnum_to_gpio()
117 if (bitnum < bank->first_irq_bit) in wpcm450_irq_bitnum_to_gpio()
118 return -EINVAL; in wpcm450_irq_bitnum_to_gpio()
120 if (bitnum - bank->first_irq_bit > bank->num_irqs) in wpcm450_irq_bitnum_to_gpio()
121 return -EINVAL; in wpcm450_irq_bitnum_to_gpio()
123 return bitnum - bank->first_irq_bit + bank->first_irq_gpio; in wpcm450_irq_bitnum_to_gpio()
129 struct wpcm450_pinctrl *pctrl = gpio->pctrl; in wpcm450_gpio_irq_ack() local
137 raw_spin_lock_irqsave(&pctrl->lock, flags); in wpcm450_gpio_irq_ack()
138 iowrite32(BIT(bit), pctrl->gpio_base + WPCM450_GPEVST); in wpcm450_gpio_irq_ack()
139 raw_spin_unlock_irqrestore(&pctrl->lock, flags); in wpcm450_gpio_irq_ack()
146 struct wpcm450_pinctrl *pctrl = gpio->pctrl; in wpcm450_gpio_irq_mask() local
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()
168 struct wpcm450_pinctrl *pctrl = gpio->pctrl; in wpcm450_gpio_irq_unmask() local
179 raw_spin_lock_irqsave(&pctrl->lock, flags); in wpcm450_gpio_irq_unmask()
180 even = ioread32(pctrl->gpio_base + WPCM450_GPEVEN); in wpcm450_gpio_irq_unmask()
182 iowrite32(even, pctrl->gpio_base + WPCM450_GPEVEN); in wpcm450_gpio_irq_unmask()
183 raw_spin_unlock_irqrestore(&pctrl->lock, flags); in wpcm450_gpio_irq_unmask()
187 * This is an implementation of the gpio_chip->get() function, for use in
188 * wpcm450_gpio_fix_evpol. Unfortunately, we can't use the bgpio-provided
189 * implementation there, because it would require taking gpio_chip->bgpio_lock,
195 void __iomem *reg = gpio->pctrl->gpio_base + gpio->bank->datain; in wpcm450_gpio_get()
199 raw_spin_lock_irqsave(&gpio->pctrl->lock, flags); in wpcm450_gpio_get()
201 raw_spin_unlock_irqrestore(&gpio->pctrl->lock, flags); in wpcm450_gpio_get()
207 * Since the GPIO controller does not support dual-edge triggered interrupts
210 * specified emulated dual-edge triggered interrupts, so that the next edge can
215 struct wpcm450_pinctrl *pctrl = gpio->pctrl; in wpcm450_gpio_fix_evpol() local
228 raw_spin_lock_irqsave(&pctrl->lock, flags); in wpcm450_gpio_fix_evpol()
229 evpol = ioread32(pctrl->gpio_base + WPCM450_GPEVPOL); in wpcm450_gpio_fix_evpol()
231 iowrite32(evpol, pctrl->gpio_base + WPCM450_GPEVPOL); in wpcm450_gpio_fix_evpol()
232 raw_spin_unlock_irqrestore(&pctrl->lock, flags); in wpcm450_gpio_fix_evpol()
241 struct wpcm450_pinctrl *pctrl = gpio->pctrl; in wpcm450_gpio_set_irq_type() local
253 raw_spin_lock_irqsave(&pctrl->lock, flags); in wpcm450_gpio_set_irq_type()
254 evtype = ioread32(pctrl->gpio_base + WPCM450_GPEVTYPE); in wpcm450_gpio_set_irq_type()
255 evpol = ioread32(pctrl->gpio_base + WPCM450_GPEVPOL); in wpcm450_gpio_set_irq_type()
256 __assign_bit(bit, &pctrl->both_edges, 0); in wpcm450_gpio_set_irq_type()
276 __assign_bit(bit, &pctrl->both_edges, 1); in wpcm450_gpio_set_irq_type()
279 ret = -EINVAL; in wpcm450_gpio_set_irq_type()
281 iowrite32(evtype, pctrl->gpio_base + WPCM450_GPEVTYPE); in wpcm450_gpio_set_irq_type()
282 iowrite32(evpol, pctrl->gpio_base + WPCM450_GPEVPOL); in wpcm450_gpio_set_irq_type()
285 iowrite32(BIT(bit), pctrl->gpio_base + WPCM450_GPEVST); in wpcm450_gpio_set_irq_type()
287 raw_spin_unlock_irqrestore(&pctrl->lock, flags); in wpcm450_gpio_set_irq_type()
296 .name = "WPCM450-GPIO-IRQ",
308 struct wpcm450_pinctrl *pctrl = gpio->pctrl; in wpcm450_gpio_irqhandler() local
315 ours = GENMASK(gpio->bank->num_irqs - 1, 0) << gpio->bank->first_irq_bit; in wpcm450_gpio_irqhandler()
317 raw_spin_lock_irqsave(&pctrl->lock, flags); in wpcm450_gpio_irqhandler()
319 pending = ioread32(pctrl->gpio_base + WPCM450_GPEVST); in wpcm450_gpio_irqhandler()
320 pending &= ioread32(pctrl->gpio_base + WPCM450_GPEVEN); in wpcm450_gpio_irqhandler()
323 raw_spin_unlock_irqrestore(&pctrl->lock, flags); in wpcm450_gpio_irqhandler()
325 if (pending & pctrl->both_edges) in wpcm450_gpio_irqhandler()
326 wpcm450_gpio_fix_evpol(gpio, pending & pctrl->both_edges); in wpcm450_gpio_irqhandler()
332 generic_handle_domain_irq(gpio->gc.irq.domain, offset); in wpcm450_gpio_irqhandler()
827 if (func == fn_gpio || cfg->fn0 == func || cfg->fn1 == func) { in wpcm450_setfunc()
828 if (cfg->reg0) in wpcm450_setfunc()
829 wpcm450_update_mfsel(gcr_regmap, cfg->reg0, in wpcm450_setfunc()
830 cfg->bit0, cfg->fn0, func); in wpcm450_setfunc()
831 if (cfg->reg1) in wpcm450_setfunc()
832 wpcm450_update_mfsel(gcr_regmap, cfg->reg1, in wpcm450_setfunc()
833 cfg->bit1, cfg->fn1, func); in wpcm450_setfunc()
900 struct wpcm450_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); in wpcm450_pinmux_set_mux() local
902 wpcm450_setfunc(pctrl->gcr_regmap, wpcm450_groups[group].pins, in wpcm450_pinmux_set_mux()
919 return -EINVAL; in debounce_bitnum()
925 struct wpcm450_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); in wpcm450_config_get() local
937 raw_spin_lock_irqsave(&pctrl->lock, flags); in wpcm450_config_get()
938 reg = ioread32(pctrl->gpio_base + WPCM450_GPEVDBNC); in wpcm450_config_get()
939 raw_spin_unlock_irqrestore(&pctrl->lock, flags); in wpcm450_config_get()
944 return -ENOTSUPP; in wpcm450_config_get()
948 static int wpcm450_config_set_one(struct wpcm450_pinctrl *pctrl, in wpcm450_config_set_one() argument
965 raw_spin_lock_irqsave(&pctrl->lock, flags); in wpcm450_config_set_one()
966 reg = ioread32(pctrl->gpio_base + WPCM450_GPEVDBNC); in wpcm450_config_set_one()
968 iowrite32(reg, pctrl->gpio_base + WPCM450_GPEVDBNC); in wpcm450_config_set_one()
969 raw_spin_unlock_irqrestore(&pctrl->lock, flags); in wpcm450_config_set_one()
972 return -ENOTSUPP; in wpcm450_config_set_one()
979 struct wpcm450_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); in wpcm450_config_set() local
982 while (num_configs--) { in wpcm450_config_set()
983 ret = wpcm450_config_set_one(pctrl, pin, *configs++); in wpcm450_config_set()
998 .name = "wpcm450-pinctrl",
1012 return wpcm450_config_set_one(gpio->pctrl, offset, config); in wpcm450_gpio_set_config()
1018 const struct wpcm450_bank *bank = gpio->bank; in wpcm450_gpio_add_pin_ranges()
1020 return gpiochip_add_pin_range(&gpio->gc, dev_name(gpio->pctrl->dev), in wpcm450_gpio_add_pin_ranges()
1021 0, bank->base, bank->length); in wpcm450_gpio_add_pin_ranges()
1025 struct wpcm450_pinctrl *pctrl) in wpcm450_gpio_register() argument
1027 struct device *dev = &pdev->dev; in wpcm450_gpio_register()
1031 pctrl->gpio_base = devm_platform_ioremap_resource(pdev, 0); in wpcm450_gpio_register()
1032 if (IS_ERR(pctrl->gpio_base)) in wpcm450_gpio_register()
1033 return dev_err_probe(dev, PTR_ERR(pctrl->gpio_base), in wpcm450_gpio_register()
1047 if (!fwnode_property_read_bool(child, "gpio-controller")) in wpcm450_gpio_register()
1055 return dev_err_probe(dev, -EINVAL, in wpcm450_gpio_register()
1058 gpio = &pctrl->gpio_bank[reg]; in wpcm450_gpio_register()
1059 gpio->pctrl = pctrl; in wpcm450_gpio_register()
1062 gpio->bank = bank; in wpcm450_gpio_register()
1064 dat = pctrl->gpio_base + bank->datain; in wpcm450_gpio_register()
1065 if (bank->dataout) { in wpcm450_gpio_register()
1066 set = pctrl->gpio_base + bank->dataout; in wpcm450_gpio_register()
1067 dirout = pctrl->gpio_base + bank->cfg0; in wpcm450_gpio_register()
1071 ret = bgpio_init(&gpio->gc, dev, 4, in wpcm450_gpio_register()
1076 gpio->gc.ngpio = bank->length; in wpcm450_gpio_register()
1077 gpio->gc.set_config = wpcm450_gpio_set_config; in wpcm450_gpio_register()
1078 gpio->gc.fwnode = child; in wpcm450_gpio_register()
1079 gpio->gc.add_pin_ranges = wpcm450_gpio_add_pin_ranges; in wpcm450_gpio_register()
1081 girq = &gpio->gc.irq; in wpcm450_gpio_register()
1083 girq->parent_handler = wpcm450_gpio_irqhandler; in wpcm450_gpio_register()
1084 girq->parents = devm_kcalloc(dev, WPCM450_NUM_GPIO_IRQS, in wpcm450_gpio_register()
1085 sizeof(*girq->parents), GFP_KERNEL); in wpcm450_gpio_register()
1086 if (!girq->parents) in wpcm450_gpio_register()
1087 return -ENOMEM; in wpcm450_gpio_register()
1088 girq->default_type = IRQ_TYPE_NONE; in wpcm450_gpio_register()
1089 girq->handler = handle_bad_irq; in wpcm450_gpio_register()
1091 girq->num_parents = 0; in wpcm450_gpio_register()
1101 girq->parents[i] = irq; in wpcm450_gpio_register()
1102 girq->num_parents++; in wpcm450_gpio_register()
1105 ret = devm_gpiochip_add_data(dev, &gpio->gc, gpio); in wpcm450_gpio_register()
1115 struct device *dev = &pdev->dev; in wpcm450_pinctrl_probe()
1116 struct wpcm450_pinctrl *pctrl; in wpcm450_pinctrl_probe() local
1119 pctrl = devm_kzalloc(dev, sizeof(*pctrl), GFP_KERNEL); in wpcm450_pinctrl_probe()
1120 if (!pctrl) in wpcm450_pinctrl_probe()
1121 return -ENOMEM; in wpcm450_pinctrl_probe()
1123 pctrl->dev = &pdev->dev; in wpcm450_pinctrl_probe()
1124 raw_spin_lock_init(&pctrl->lock); in wpcm450_pinctrl_probe()
1125 dev_set_drvdata(dev, pctrl); in wpcm450_pinctrl_probe()
1127 pctrl->gcr_regmap = in wpcm450_pinctrl_probe()
1128 syscon_regmap_lookup_by_compatible("nuvoton,wpcm450-gcr"); in wpcm450_pinctrl_probe()
1129 if (IS_ERR(pctrl->gcr_regmap)) in wpcm450_pinctrl_probe()
1130 return dev_err_probe(dev, PTR_ERR(pctrl->gcr_regmap), in wpcm450_pinctrl_probe()
1131 "Failed to find nuvoton,wpcm450-gcr\n"); in wpcm450_pinctrl_probe()
1133 pctrl->pctldev = devm_pinctrl_register(dev, in wpcm450_pinctrl_probe()
1134 &wpcm450_pinctrl_desc, pctrl); in wpcm450_pinctrl_probe()
1135 if (IS_ERR(pctrl->pctldev)) in wpcm450_pinctrl_probe()
1136 return dev_err_probe(dev, PTR_ERR(pctrl->pctldev), in wpcm450_pinctrl_probe()
1139 ret = wpcm450_gpio_register(pdev, pctrl); in wpcm450_pinctrl_probe()
1147 { .compatible = "nuvoton,wpcm450-pinctrl" },
1155 .name = "wpcm450-pinctrl",