1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * Pinctrl / GPIO driver for StarFive JH7110 SoC |
4 | * |
5 | * Copyright (C) 2022 Emil Renner Berthing <kernel@esmil.dk> |
6 | * Copyright (C) 2022 StarFive Technology Co., Ltd. |
7 | */ |
8 | |
9 | #include <linux/bits.h> |
10 | #include <linux/clk.h> |
11 | #include <linux/gpio/driver.h> |
12 | #include <linux/io.h> |
13 | #include <linux/mod_devicetable.h> |
14 | #include <linux/module.h> |
15 | #include <linux/mutex.h> |
16 | #include <linux/of.h> |
17 | #include <linux/platform_device.h> |
18 | #include <linux/reset.h> |
19 | #include <linux/seq_file.h> |
20 | #include <linux/spinlock.h> |
21 | |
22 | #include <linux/pinctrl/consumer.h> |
23 | #include <linux/pinctrl/pinconf.h> |
24 | #include <linux/pinctrl/pinctrl.h> |
25 | #include <linux/pinctrl/pinmux.h> |
26 | |
27 | #include <dt-bindings/pinctrl/starfive,jh7110-pinctrl.h> |
28 | |
29 | #include "../core.h" |
30 | #include "../pinctrl-utils.h" |
31 | #include "../pinmux.h" |
32 | #include "../pinconf.h" |
33 | #include "pinctrl-starfive-jh7110.h" |
34 | |
35 | /* pad control bits */ |
36 | #define JH7110_PADCFG_POS BIT(7) |
37 | #define JH7110_PADCFG_SMT BIT(6) |
38 | #define JH7110_PADCFG_SLEW BIT(5) |
39 | #define JH7110_PADCFG_PD BIT(4) |
40 | #define JH7110_PADCFG_PU BIT(3) |
41 | #define JH7110_PADCFG_BIAS (JH7110_PADCFG_PD | JH7110_PADCFG_PU) |
42 | #define JH7110_PADCFG_DS_MASK GENMASK(2, 1) |
43 | #define JH7110_PADCFG_DS_2MA (0U << 1) |
44 | #define JH7110_PADCFG_DS_4MA BIT(1) |
45 | #define JH7110_PADCFG_DS_8MA (2U << 1) |
46 | #define JH7110_PADCFG_DS_12MA (3U << 1) |
47 | #define JH7110_PADCFG_IE BIT(0) |
48 | |
49 | /* |
50 | * The packed pinmux values from the device tree look like this: |
51 | * |
52 | * | 31 - 24 | 23 - 16 | 15 - 10 | 9 - 8 | 7 - 0 | |
53 | * | din | dout | doen | function | pin | |
54 | */ |
55 | static unsigned int jh7110_pinmux_din(u32 v) |
56 | { |
57 | return (v & GENMASK(31, 24)) >> 24; |
58 | } |
59 | |
60 | static u32 jh7110_pinmux_dout(u32 v) |
61 | { |
62 | return (v & GENMASK(23, 16)) >> 16; |
63 | } |
64 | |
65 | static u32 jh7110_pinmux_doen(u32 v) |
66 | { |
67 | return (v & GENMASK(15, 10)) >> 10; |
68 | } |
69 | |
70 | static u32 jh7110_pinmux_function(u32 v) |
71 | { |
72 | return (v & GENMASK(9, 8)) >> 8; |
73 | } |
74 | |
75 | static unsigned int jh7110_pinmux_pin(u32 v) |
76 | { |
77 | return v & GENMASK(7, 0); |
78 | } |
79 | |
80 | static struct jh7110_pinctrl *jh7110_from_irq_data(struct irq_data *d) |
81 | { |
82 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); |
83 | |
84 | return container_of(gc, struct jh7110_pinctrl, gc); |
85 | } |
86 | |
87 | struct jh7110_pinctrl *jh7110_from_irq_desc(struct irq_desc *desc) |
88 | { |
89 | struct gpio_chip *gc = irq_desc_get_handler_data(desc); |
90 | |
91 | return container_of(gc, struct jh7110_pinctrl, gc); |
92 | } |
93 | EXPORT_SYMBOL_GPL(jh7110_from_irq_desc); |
94 | |
95 | #ifdef CONFIG_DEBUG_FS |
96 | static void jh7110_pin_dbg_show(struct pinctrl_dev *pctldev, |
97 | struct seq_file *s, unsigned int pin) |
98 | { |
99 | struct jh7110_pinctrl *sfp = pinctrl_dev_get_drvdata(pctldev); |
100 | const struct jh7110_pinctrl_soc_info *info = sfp->info; |
101 | |
102 | seq_printf(m: s, fmt: "%s" , dev_name(dev: pctldev->dev)); |
103 | |
104 | if (pin < sfp->gc.ngpio) { |
105 | unsigned int offset = 4 * (pin / 4); |
106 | unsigned int shift = 8 * (pin % 4); |
107 | u32 dout = readl_relaxed(sfp->base + info->dout_reg_base + offset); |
108 | u32 doen = readl_relaxed(sfp->base + info->doen_reg_base + offset); |
109 | u32 gpi = readl_relaxed(sfp->base + info->gpi_reg_base + offset); |
110 | |
111 | dout = (dout >> shift) & info->dout_mask; |
112 | doen = (doen >> shift) & info->doen_mask; |
113 | gpi = ((gpi >> shift) - 2) & info->gpi_mask; |
114 | |
115 | seq_printf(m: s, fmt: " dout=%u doen=%u din=%u" , dout, doen, gpi); |
116 | } |
117 | } |
118 | #else |
119 | #define jh7110_pin_dbg_show NULL |
120 | #endif |
121 | |
122 | static int jh7110_dt_node_to_map(struct pinctrl_dev *pctldev, |
123 | struct device_node *np, |
124 | struct pinctrl_map **maps, |
125 | unsigned int *num_maps) |
126 | { |
127 | struct jh7110_pinctrl *sfp = pinctrl_dev_get_drvdata(pctldev); |
128 | struct device *dev = sfp->gc.parent; |
129 | struct device_node *child; |
130 | struct pinctrl_map *map; |
131 | const char **pgnames; |
132 | const char *grpname; |
133 | int ngroups; |
134 | int nmaps; |
135 | int ret; |
136 | |
137 | ngroups = 0; |
138 | for_each_available_child_of_node(np, child) |
139 | ngroups += 1; |
140 | nmaps = 2 * ngroups; |
141 | |
142 | pgnames = devm_kcalloc(dev, n: ngroups, size: sizeof(*pgnames), GFP_KERNEL); |
143 | if (!pgnames) |
144 | return -ENOMEM; |
145 | |
146 | map = kcalloc(n: nmaps, size: sizeof(*map), GFP_KERNEL); |
147 | if (!map) |
148 | return -ENOMEM; |
149 | |
150 | nmaps = 0; |
151 | ngroups = 0; |
152 | mutex_lock(&sfp->mutex); |
153 | for_each_available_child_of_node(np, child) { |
154 | int npins = of_property_count_u32_elems(np: child, propname: "pinmux" ); |
155 | int *pins; |
156 | u32 *pinmux; |
157 | int i; |
158 | |
159 | if (npins < 1) { |
160 | dev_err(dev, |
161 | "invalid pinctrl group %pOFn.%pOFn: pinmux not set\n" , |
162 | np, child); |
163 | ret = -EINVAL; |
164 | goto put_child; |
165 | } |
166 | |
167 | grpname = devm_kasprintf(dev, GFP_KERNEL, fmt: "%pOFn.%pOFn" , np, child); |
168 | if (!grpname) { |
169 | ret = -ENOMEM; |
170 | goto put_child; |
171 | } |
172 | |
173 | pgnames[ngroups++] = grpname; |
174 | |
175 | pins = devm_kcalloc(dev, n: npins, size: sizeof(*pins), GFP_KERNEL); |
176 | if (!pins) { |
177 | ret = -ENOMEM; |
178 | goto put_child; |
179 | } |
180 | |
181 | pinmux = devm_kcalloc(dev, n: npins, size: sizeof(*pinmux), GFP_KERNEL); |
182 | if (!pinmux) { |
183 | ret = -ENOMEM; |
184 | goto put_child; |
185 | } |
186 | |
187 | ret = of_property_read_u32_array(np: child, propname: "pinmux" , out_values: pinmux, sz: npins); |
188 | if (ret) |
189 | goto put_child; |
190 | |
191 | for (i = 0; i < npins; i++) |
192 | pins[i] = jh7110_pinmux_pin(v: pinmux[i]); |
193 | |
194 | map[nmaps].type = PIN_MAP_TYPE_MUX_GROUP; |
195 | map[nmaps].data.mux.function = np->name; |
196 | map[nmaps].data.mux.group = grpname; |
197 | nmaps += 1; |
198 | |
199 | ret = pinctrl_generic_add_group(pctldev, name: grpname, |
200 | pins, num_pins: npins, data: pinmux); |
201 | if (ret < 0) { |
202 | dev_err(dev, "error adding group %s: %d\n" , grpname, ret); |
203 | goto put_child; |
204 | } |
205 | |
206 | ret = pinconf_generic_parse_dt_config(np: child, pctldev, |
207 | configs: &map[nmaps].data.configs.configs, |
208 | nconfigs: &map[nmaps].data.configs.num_configs); |
209 | if (ret) { |
210 | dev_err(dev, "error parsing pin config of group %s: %d\n" , |
211 | grpname, ret); |
212 | goto put_child; |
213 | } |
214 | |
215 | /* don't create a map if there are no pinconf settings */ |
216 | if (map[nmaps].data.configs.num_configs == 0) |
217 | continue; |
218 | |
219 | map[nmaps].type = PIN_MAP_TYPE_CONFIGS_GROUP; |
220 | map[nmaps].data.configs.group_or_pin = grpname; |
221 | nmaps += 1; |
222 | } |
223 | |
224 | ret = pinmux_generic_add_function(pctldev, name: np->name, |
225 | groups: pgnames, num_groups: ngroups, NULL); |
226 | if (ret < 0) { |
227 | dev_err(dev, "error adding function %s: %d\n" , np->name, ret); |
228 | goto free_map; |
229 | } |
230 | mutex_unlock(lock: &sfp->mutex); |
231 | |
232 | *maps = map; |
233 | *num_maps = nmaps; |
234 | return 0; |
235 | |
236 | put_child: |
237 | of_node_put(node: child); |
238 | free_map: |
239 | pinctrl_utils_free_map(pctldev, map, num_maps: nmaps); |
240 | mutex_unlock(lock: &sfp->mutex); |
241 | return ret; |
242 | } |
243 | |
244 | static const struct pinctrl_ops jh7110_pinctrl_ops = { |
245 | .get_groups_count = pinctrl_generic_get_group_count, |
246 | .get_group_name = pinctrl_generic_get_group_name, |
247 | .get_group_pins = pinctrl_generic_get_group_pins, |
248 | .pin_dbg_show = jh7110_pin_dbg_show, |
249 | .dt_node_to_map = jh7110_dt_node_to_map, |
250 | .dt_free_map = pinctrl_utils_free_map, |
251 | }; |
252 | |
253 | void jh7110_set_gpiomux(struct jh7110_pinctrl *sfp, unsigned int pin, |
254 | unsigned int din, u32 dout, u32 doen) |
255 | { |
256 | const struct jh7110_pinctrl_soc_info *info = sfp->info; |
257 | |
258 | unsigned int offset = 4 * (pin / 4); |
259 | unsigned int shift = 8 * (pin % 4); |
260 | u32 dout_mask = info->dout_mask << shift; |
261 | u32 done_mask = info->doen_mask << shift; |
262 | u32 ival, imask; |
263 | void __iomem *reg_dout; |
264 | void __iomem *reg_doen; |
265 | void __iomem *reg_din; |
266 | unsigned long flags; |
267 | |
268 | reg_dout = sfp->base + info->dout_reg_base + offset; |
269 | reg_doen = sfp->base + info->doen_reg_base + offset; |
270 | dout <<= shift; |
271 | doen <<= shift; |
272 | if (din != GPI_NONE) { |
273 | unsigned int ioffset = 4 * (din / 4); |
274 | unsigned int ishift = 8 * (din % 4); |
275 | |
276 | reg_din = sfp->base + info->gpi_reg_base + ioffset; |
277 | ival = (pin + 2) << ishift; |
278 | imask = info->gpi_mask << ishift; |
279 | } else { |
280 | reg_din = NULL; |
281 | } |
282 | |
283 | raw_spin_lock_irqsave(&sfp->lock, flags); |
284 | dout |= readl_relaxed(reg_dout) & ~dout_mask; |
285 | writel_relaxed(dout, reg_dout); |
286 | doen |= readl_relaxed(reg_doen) & ~done_mask; |
287 | writel_relaxed(doen, reg_doen); |
288 | if (reg_din) { |
289 | ival |= readl_relaxed(reg_din) & ~imask; |
290 | writel_relaxed(ival, reg_din); |
291 | } |
292 | raw_spin_unlock_irqrestore(&sfp->lock, flags); |
293 | } |
294 | EXPORT_SYMBOL_GPL(jh7110_set_gpiomux); |
295 | |
296 | static int jh7110_set_mux(struct pinctrl_dev *pctldev, |
297 | unsigned int fsel, unsigned int gsel) |
298 | { |
299 | struct jh7110_pinctrl *sfp = pinctrl_dev_get_drvdata(pctldev); |
300 | const struct jh7110_pinctrl_soc_info *info = sfp->info; |
301 | const struct group_desc *group; |
302 | const u32 *pinmux; |
303 | unsigned int i; |
304 | |
305 | group = pinctrl_generic_get_group(pctldev, group_selector: gsel); |
306 | if (!group) |
307 | return -EINVAL; |
308 | |
309 | pinmux = group->data; |
310 | for (i = 0; i < group->grp.npins; i++) { |
311 | u32 v = pinmux[i]; |
312 | |
313 | if (info->jh7110_set_one_pin_mux) |
314 | info->jh7110_set_one_pin_mux(sfp, |
315 | jh7110_pinmux_pin(v), |
316 | jh7110_pinmux_din(v), |
317 | jh7110_pinmux_dout(v), |
318 | jh7110_pinmux_doen(v), |
319 | jh7110_pinmux_function(v)); |
320 | } |
321 | |
322 | return 0; |
323 | } |
324 | |
325 | static const struct pinmux_ops jh7110_pinmux_ops = { |
326 | .get_functions_count = pinmux_generic_get_function_count, |
327 | .get_function_name = pinmux_generic_get_function_name, |
328 | .get_function_groups = pinmux_generic_get_function_groups, |
329 | .set_mux = jh7110_set_mux, |
330 | .strict = true, |
331 | }; |
332 | |
333 | static const u8 jh7110_drive_strength_mA[4] = { 2, 4, 8, 12 }; |
334 | |
335 | static u32 jh7110_padcfg_ds_to_mA(u32 padcfg) |
336 | { |
337 | return jh7110_drive_strength_mA[(padcfg >> 1) & 3U]; |
338 | } |
339 | |
340 | static u32 jh7110_padcfg_ds_from_mA(u32 v) |
341 | { |
342 | int i; |
343 | |
344 | for (i = 0; i < 3; i++) { |
345 | if (v <= jh7110_drive_strength_mA[i]) |
346 | break; |
347 | } |
348 | return i << 1; |
349 | } |
350 | |
351 | static void jh7110_padcfg_rmw(struct jh7110_pinctrl *sfp, |
352 | unsigned int pin, u32 mask, u32 value) |
353 | { |
354 | const struct jh7110_pinctrl_soc_info *info = sfp->info; |
355 | void __iomem *reg; |
356 | unsigned long flags; |
357 | int padcfg_base; |
358 | |
359 | if (!info->jh7110_get_padcfg_base) |
360 | return; |
361 | |
362 | padcfg_base = info->jh7110_get_padcfg_base(sfp, pin); |
363 | if (padcfg_base < 0) |
364 | return; |
365 | |
366 | reg = sfp->base + padcfg_base + 4 * pin; |
367 | value &= mask; |
368 | |
369 | raw_spin_lock_irqsave(&sfp->lock, flags); |
370 | value |= readl_relaxed(reg) & ~mask; |
371 | writel_relaxed(value, reg); |
372 | raw_spin_unlock_irqrestore(&sfp->lock, flags); |
373 | } |
374 | |
375 | static int jh7110_pinconf_get(struct pinctrl_dev *pctldev, |
376 | unsigned int pin, unsigned long *config) |
377 | { |
378 | struct jh7110_pinctrl *sfp = pinctrl_dev_get_drvdata(pctldev); |
379 | const struct jh7110_pinctrl_soc_info *info = sfp->info; |
380 | int param = pinconf_to_config_param(config: *config); |
381 | u32 padcfg, arg; |
382 | bool enabled; |
383 | int padcfg_base; |
384 | |
385 | if (!info->jh7110_get_padcfg_base) |
386 | return 0; |
387 | |
388 | padcfg_base = info->jh7110_get_padcfg_base(sfp, pin); |
389 | if (padcfg_base < 0) |
390 | return 0; |
391 | |
392 | padcfg = readl_relaxed(sfp->base + padcfg_base + 4 * pin); |
393 | switch (param) { |
394 | case PIN_CONFIG_BIAS_DISABLE: |
395 | enabled = !(padcfg & JH7110_PADCFG_BIAS); |
396 | arg = 0; |
397 | break; |
398 | case PIN_CONFIG_BIAS_PULL_DOWN: |
399 | enabled = padcfg & JH7110_PADCFG_PD; |
400 | arg = 1; |
401 | break; |
402 | case PIN_CONFIG_BIAS_PULL_UP: |
403 | enabled = padcfg & JH7110_PADCFG_PU; |
404 | arg = 1; |
405 | break; |
406 | case PIN_CONFIG_DRIVE_STRENGTH: |
407 | enabled = true; |
408 | arg = jh7110_padcfg_ds_to_mA(padcfg); |
409 | break; |
410 | case PIN_CONFIG_INPUT_ENABLE: |
411 | enabled = padcfg & JH7110_PADCFG_IE; |
412 | arg = enabled; |
413 | break; |
414 | case PIN_CONFIG_INPUT_SCHMITT_ENABLE: |
415 | enabled = padcfg & JH7110_PADCFG_SMT; |
416 | arg = enabled; |
417 | break; |
418 | case PIN_CONFIG_SLEW_RATE: |
419 | enabled = true; |
420 | arg = !!(padcfg & JH7110_PADCFG_SLEW); |
421 | break; |
422 | default: |
423 | return -ENOTSUPP; |
424 | } |
425 | |
426 | *config = pinconf_to_config_packed(param, argument: arg); |
427 | return enabled ? 0 : -EINVAL; |
428 | } |
429 | |
430 | static int jh7110_pinconf_group_get(struct pinctrl_dev *pctldev, |
431 | unsigned int gsel, |
432 | unsigned long *config) |
433 | { |
434 | const struct group_desc *group; |
435 | |
436 | group = pinctrl_generic_get_group(pctldev, group_selector: gsel); |
437 | if (!group) |
438 | return -EINVAL; |
439 | |
440 | return jh7110_pinconf_get(pctldev, pin: group->grp.pins[0], config); |
441 | } |
442 | |
443 | static int jh7110_pinconf_group_set(struct pinctrl_dev *pctldev, |
444 | unsigned int gsel, |
445 | unsigned long *configs, |
446 | unsigned int num_configs) |
447 | { |
448 | struct jh7110_pinctrl *sfp = pinctrl_dev_get_drvdata(pctldev); |
449 | const struct group_desc *group; |
450 | u16 mask, value; |
451 | int i; |
452 | |
453 | group = pinctrl_generic_get_group(pctldev, group_selector: gsel); |
454 | if (!group) |
455 | return -EINVAL; |
456 | |
457 | mask = 0; |
458 | value = 0; |
459 | for (i = 0; i < num_configs; i++) { |
460 | int param = pinconf_to_config_param(config: configs[i]); |
461 | u32 arg = pinconf_to_config_argument(config: configs[i]); |
462 | |
463 | switch (param) { |
464 | case PIN_CONFIG_BIAS_DISABLE: |
465 | mask |= JH7110_PADCFG_BIAS; |
466 | value &= ~JH7110_PADCFG_BIAS; |
467 | break; |
468 | case PIN_CONFIG_BIAS_PULL_DOWN: |
469 | if (arg == 0) |
470 | return -ENOTSUPP; |
471 | mask |= JH7110_PADCFG_BIAS; |
472 | value = (value & ~JH7110_PADCFG_BIAS) | JH7110_PADCFG_PD; |
473 | break; |
474 | case PIN_CONFIG_BIAS_PULL_UP: |
475 | if (arg == 0) |
476 | return -ENOTSUPP; |
477 | mask |= JH7110_PADCFG_BIAS; |
478 | value = (value & ~JH7110_PADCFG_BIAS) | JH7110_PADCFG_PU; |
479 | break; |
480 | case PIN_CONFIG_DRIVE_STRENGTH: |
481 | mask |= JH7110_PADCFG_DS_MASK; |
482 | value = (value & ~JH7110_PADCFG_DS_MASK) | |
483 | jh7110_padcfg_ds_from_mA(v: arg); |
484 | break; |
485 | case PIN_CONFIG_INPUT_ENABLE: |
486 | mask |= JH7110_PADCFG_IE; |
487 | if (arg) |
488 | value |= JH7110_PADCFG_IE; |
489 | else |
490 | value &= ~JH7110_PADCFG_IE; |
491 | break; |
492 | case PIN_CONFIG_INPUT_SCHMITT_ENABLE: |
493 | mask |= JH7110_PADCFG_SMT; |
494 | if (arg) |
495 | value |= JH7110_PADCFG_SMT; |
496 | else |
497 | value &= ~JH7110_PADCFG_SMT; |
498 | break; |
499 | case PIN_CONFIG_SLEW_RATE: |
500 | mask |= JH7110_PADCFG_SLEW; |
501 | if (arg) |
502 | value |= JH7110_PADCFG_SLEW; |
503 | else |
504 | value &= ~JH7110_PADCFG_SLEW; |
505 | break; |
506 | default: |
507 | return -ENOTSUPP; |
508 | } |
509 | } |
510 | |
511 | for (i = 0; i < group->grp.npins; i++) |
512 | jh7110_padcfg_rmw(sfp, pin: group->grp.pins[i], mask, value); |
513 | |
514 | return 0; |
515 | } |
516 | |
517 | #ifdef CONFIG_DEBUG_FS |
518 | static void jh7110_pinconf_dbg_show(struct pinctrl_dev *pctldev, |
519 | struct seq_file *s, unsigned int pin) |
520 | { |
521 | struct jh7110_pinctrl *sfp = pinctrl_dev_get_drvdata(pctldev); |
522 | const struct jh7110_pinctrl_soc_info *info = sfp->info; |
523 | u32 value; |
524 | int padcfg_base; |
525 | |
526 | if (!info->jh7110_get_padcfg_base) |
527 | return; |
528 | |
529 | padcfg_base = info->jh7110_get_padcfg_base(sfp, pin); |
530 | if (padcfg_base < 0) |
531 | return; |
532 | |
533 | value = readl_relaxed(sfp->base + padcfg_base + 4 * pin); |
534 | seq_printf(m: s, fmt: " (0x%02x)" , value); |
535 | } |
536 | #else |
537 | #define jh7110_pinconf_dbg_show NULL |
538 | #endif |
539 | |
540 | static const struct pinconf_ops jh7110_pinconf_ops = { |
541 | .pin_config_get = jh7110_pinconf_get, |
542 | .pin_config_group_get = jh7110_pinconf_group_get, |
543 | .pin_config_group_set = jh7110_pinconf_group_set, |
544 | .pin_config_dbg_show = jh7110_pinconf_dbg_show, |
545 | .is_generic = true, |
546 | }; |
547 | |
548 | static int jh7110_gpio_get_direction(struct gpio_chip *gc, |
549 | unsigned int gpio) |
550 | { |
551 | struct jh7110_pinctrl *sfp = container_of(gc, |
552 | struct jh7110_pinctrl, gc); |
553 | const struct jh7110_pinctrl_soc_info *info = sfp->info; |
554 | unsigned int offset = 4 * (gpio / 4); |
555 | unsigned int shift = 8 * (gpio % 4); |
556 | u32 doen = readl_relaxed(sfp->base + info->doen_reg_base + offset); |
557 | |
558 | doen = (doen >> shift) & info->doen_mask; |
559 | |
560 | return doen == GPOEN_ENABLE ? |
561 | GPIO_LINE_DIRECTION_OUT : GPIO_LINE_DIRECTION_IN; |
562 | } |
563 | |
564 | static int jh7110_gpio_direction_input(struct gpio_chip *gc, |
565 | unsigned int gpio) |
566 | { |
567 | struct jh7110_pinctrl *sfp = container_of(gc, |
568 | struct jh7110_pinctrl, gc); |
569 | const struct jh7110_pinctrl_soc_info *info = sfp->info; |
570 | |
571 | /* enable input and schmitt trigger */ |
572 | jh7110_padcfg_rmw(sfp, pin: gpio, |
573 | JH7110_PADCFG_IE | JH7110_PADCFG_SMT, |
574 | JH7110_PADCFG_IE | JH7110_PADCFG_SMT); |
575 | |
576 | if (info->jh7110_set_one_pin_mux) |
577 | info->jh7110_set_one_pin_mux(sfp, gpio, |
578 | GPI_NONE, GPOUT_LOW, GPOEN_DISABLE, 0); |
579 | |
580 | return 0; |
581 | } |
582 | |
583 | static int jh7110_gpio_direction_output(struct gpio_chip *gc, |
584 | unsigned int gpio, int value) |
585 | { |
586 | struct jh7110_pinctrl *sfp = container_of(gc, |
587 | struct jh7110_pinctrl, gc); |
588 | const struct jh7110_pinctrl_soc_info *info = sfp->info; |
589 | |
590 | if (info->jh7110_set_one_pin_mux) |
591 | info->jh7110_set_one_pin_mux(sfp, gpio, |
592 | GPI_NONE, value ? GPOUT_HIGH : GPOUT_LOW, |
593 | GPOEN_ENABLE, 0); |
594 | |
595 | /* disable input, schmitt trigger and bias */ |
596 | jh7110_padcfg_rmw(sfp, pin: gpio, |
597 | JH7110_PADCFG_IE | JH7110_PADCFG_SMT | |
598 | JH7110_PADCFG_BIAS, value: 0); |
599 | return 0; |
600 | } |
601 | |
602 | static int jh7110_gpio_get(struct gpio_chip *gc, unsigned int gpio) |
603 | { |
604 | struct jh7110_pinctrl *sfp = container_of(gc, |
605 | struct jh7110_pinctrl, gc); |
606 | const struct jh7110_pinctrl_soc_info *info = sfp->info; |
607 | void __iomem *reg = sfp->base + info->gpioin_reg_base |
608 | + 4 * (gpio / 32); |
609 | |
610 | return !!(readl_relaxed(reg) & BIT(gpio % 32)); |
611 | } |
612 | |
613 | static void jh7110_gpio_set(struct gpio_chip *gc, |
614 | unsigned int gpio, int value) |
615 | { |
616 | struct jh7110_pinctrl *sfp = container_of(gc, |
617 | struct jh7110_pinctrl, gc); |
618 | const struct jh7110_pinctrl_soc_info *info = sfp->info; |
619 | unsigned int offset = 4 * (gpio / 4); |
620 | unsigned int shift = 8 * (gpio % 4); |
621 | void __iomem *reg_dout = sfp->base + info->dout_reg_base + offset; |
622 | u32 dout = (value ? GPOUT_HIGH : GPOUT_LOW) << shift; |
623 | u32 mask = info->dout_mask << shift; |
624 | unsigned long flags; |
625 | |
626 | raw_spin_lock_irqsave(&sfp->lock, flags); |
627 | dout |= readl_relaxed(reg_dout) & ~mask; |
628 | writel_relaxed(dout, reg_dout); |
629 | raw_spin_unlock_irqrestore(&sfp->lock, flags); |
630 | } |
631 | |
632 | static int jh7110_gpio_set_config(struct gpio_chip *gc, |
633 | unsigned int gpio, unsigned long config) |
634 | { |
635 | struct jh7110_pinctrl *sfp = container_of(gc, |
636 | struct jh7110_pinctrl, gc); |
637 | u32 arg = pinconf_to_config_argument(config); |
638 | u32 value; |
639 | u32 mask; |
640 | |
641 | switch (pinconf_to_config_param(config)) { |
642 | case PIN_CONFIG_BIAS_DISABLE: |
643 | mask = JH7110_PADCFG_BIAS; |
644 | value = 0; |
645 | break; |
646 | case PIN_CONFIG_BIAS_PULL_DOWN: |
647 | if (arg == 0) |
648 | return -ENOTSUPP; |
649 | mask = JH7110_PADCFG_BIAS; |
650 | value = JH7110_PADCFG_PD; |
651 | break; |
652 | case PIN_CONFIG_BIAS_PULL_UP: |
653 | if (arg == 0) |
654 | return -ENOTSUPP; |
655 | mask = JH7110_PADCFG_BIAS; |
656 | value = JH7110_PADCFG_PU; |
657 | break; |
658 | case PIN_CONFIG_DRIVE_PUSH_PULL: |
659 | return 0; |
660 | case PIN_CONFIG_INPUT_ENABLE: |
661 | mask = JH7110_PADCFG_IE; |
662 | value = arg ? JH7110_PADCFG_IE : 0; |
663 | break; |
664 | case PIN_CONFIG_INPUT_SCHMITT_ENABLE: |
665 | mask = JH7110_PADCFG_SMT; |
666 | value = arg ? JH7110_PADCFG_SMT : 0; |
667 | break; |
668 | default: |
669 | return -ENOTSUPP; |
670 | } |
671 | |
672 | jh7110_padcfg_rmw(sfp, pin: gpio, mask, value); |
673 | return 0; |
674 | } |
675 | |
676 | static int jh7110_gpio_add_pin_ranges(struct gpio_chip *gc) |
677 | { |
678 | struct jh7110_pinctrl *sfp = container_of(gc, |
679 | struct jh7110_pinctrl, gc); |
680 | |
681 | sfp->gpios.name = sfp->gc.label; |
682 | sfp->gpios.base = sfp->gc.base; |
683 | sfp->gpios.pin_base = 0; |
684 | sfp->gpios.npins = sfp->gc.ngpio; |
685 | sfp->gpios.gc = &sfp->gc; |
686 | pinctrl_add_gpio_range(pctldev: sfp->pctl, range: &sfp->gpios); |
687 | return 0; |
688 | } |
689 | |
690 | static void jh7110_irq_ack(struct irq_data *d) |
691 | { |
692 | struct jh7110_pinctrl *sfp = jh7110_from_irq_data(d); |
693 | const struct jh7110_gpio_irq_reg *irq_reg = sfp->info->irq_reg; |
694 | irq_hw_number_t gpio = irqd_to_hwirq(d); |
695 | void __iomem *ic = sfp->base + irq_reg->ic_reg_base |
696 | + 4 * (gpio / 32); |
697 | u32 mask = BIT(gpio % 32); |
698 | unsigned long flags; |
699 | u32 value; |
700 | |
701 | raw_spin_lock_irqsave(&sfp->lock, flags); |
702 | value = readl_relaxed(ic) & ~mask; |
703 | writel_relaxed(value, ic); |
704 | writel_relaxed(value | mask, ic); |
705 | raw_spin_unlock_irqrestore(&sfp->lock, flags); |
706 | } |
707 | |
708 | static void jh7110_irq_mask(struct irq_data *d) |
709 | { |
710 | struct jh7110_pinctrl *sfp = jh7110_from_irq_data(d); |
711 | const struct jh7110_gpio_irq_reg *irq_reg = sfp->info->irq_reg; |
712 | irq_hw_number_t gpio = irqd_to_hwirq(d); |
713 | void __iomem *ie = sfp->base + irq_reg->ie_reg_base |
714 | + 4 * (gpio / 32); |
715 | u32 mask = BIT(gpio % 32); |
716 | unsigned long flags; |
717 | u32 value; |
718 | |
719 | raw_spin_lock_irqsave(&sfp->lock, flags); |
720 | value = readl_relaxed(ie) & ~mask; |
721 | writel_relaxed(value, ie); |
722 | raw_spin_unlock_irqrestore(&sfp->lock, flags); |
723 | |
724 | gpiochip_disable_irq(gc: &sfp->gc, offset: d->hwirq); |
725 | } |
726 | |
727 | static void jh7110_irq_mask_ack(struct irq_data *d) |
728 | { |
729 | struct jh7110_pinctrl *sfp = jh7110_from_irq_data(d); |
730 | const struct jh7110_gpio_irq_reg *irq_reg = sfp->info->irq_reg; |
731 | irq_hw_number_t gpio = irqd_to_hwirq(d); |
732 | void __iomem *ie = sfp->base + irq_reg->ie_reg_base |
733 | + 4 * (gpio / 32); |
734 | void __iomem *ic = sfp->base + irq_reg->ic_reg_base |
735 | + 4 * (gpio / 32); |
736 | u32 mask = BIT(gpio % 32); |
737 | unsigned long flags; |
738 | u32 value; |
739 | |
740 | raw_spin_lock_irqsave(&sfp->lock, flags); |
741 | value = readl_relaxed(ie) & ~mask; |
742 | writel_relaxed(value, ie); |
743 | |
744 | value = readl_relaxed(ic) & ~mask; |
745 | writel_relaxed(value, ic); |
746 | writel_relaxed(value | mask, ic); |
747 | raw_spin_unlock_irqrestore(&sfp->lock, flags); |
748 | } |
749 | |
750 | static void jh7110_irq_unmask(struct irq_data *d) |
751 | { |
752 | struct jh7110_pinctrl *sfp = jh7110_from_irq_data(d); |
753 | const struct jh7110_gpio_irq_reg *irq_reg = sfp->info->irq_reg; |
754 | irq_hw_number_t gpio = irqd_to_hwirq(d); |
755 | void __iomem *ie = sfp->base + irq_reg->ie_reg_base |
756 | + 4 * (gpio / 32); |
757 | u32 mask = BIT(gpio % 32); |
758 | unsigned long flags; |
759 | u32 value; |
760 | |
761 | gpiochip_enable_irq(gc: &sfp->gc, offset: d->hwirq); |
762 | |
763 | raw_spin_lock_irqsave(&sfp->lock, flags); |
764 | value = readl_relaxed(ie) | mask; |
765 | writel_relaxed(value, ie); |
766 | raw_spin_unlock_irqrestore(&sfp->lock, flags); |
767 | } |
768 | |
769 | static int jh7110_irq_set_type(struct irq_data *d, unsigned int trigger) |
770 | { |
771 | struct jh7110_pinctrl *sfp = jh7110_from_irq_data(d); |
772 | const struct jh7110_gpio_irq_reg *irq_reg = sfp->info->irq_reg; |
773 | irq_hw_number_t gpio = irqd_to_hwirq(d); |
774 | void __iomem *base = sfp->base + 4 * (gpio / 32); |
775 | u32 mask = BIT(gpio % 32); |
776 | u32 irq_type, edge_both, polarity; |
777 | unsigned long flags; |
778 | |
779 | switch (trigger) { |
780 | case IRQ_TYPE_EDGE_RISING: |
781 | irq_type = mask; /* 1: edge triggered */ |
782 | edge_both = 0; /* 0: single edge */ |
783 | polarity = mask; /* 1: rising edge */ |
784 | break; |
785 | case IRQ_TYPE_EDGE_FALLING: |
786 | irq_type = mask; /* 1: edge triggered */ |
787 | edge_both = 0; /* 0: single edge */ |
788 | polarity = 0; /* 0: falling edge */ |
789 | break; |
790 | case IRQ_TYPE_EDGE_BOTH: |
791 | irq_type = mask; /* 1: edge triggered */ |
792 | edge_both = mask; /* 1: both edges */ |
793 | polarity = 0; /* 0: ignored */ |
794 | break; |
795 | case IRQ_TYPE_LEVEL_HIGH: |
796 | irq_type = 0; /* 0: level triggered */ |
797 | edge_both = 0; /* 0: ignored */ |
798 | polarity = mask; /* 1: high level */ |
799 | break; |
800 | case IRQ_TYPE_LEVEL_LOW: |
801 | irq_type = 0; /* 0: level triggered */ |
802 | edge_both = 0; /* 0: ignored */ |
803 | polarity = 0; /* 0: low level */ |
804 | break; |
805 | default: |
806 | return -EINVAL; |
807 | } |
808 | |
809 | if (trigger & IRQ_TYPE_EDGE_BOTH) |
810 | irq_set_handler_locked(data: d, handler: handle_edge_irq); |
811 | else |
812 | irq_set_handler_locked(data: d, handler: handle_level_irq); |
813 | |
814 | raw_spin_lock_irqsave(&sfp->lock, flags); |
815 | irq_type |= readl_relaxed(base + irq_reg->is_reg_base) & ~mask; |
816 | writel_relaxed(irq_type, base + irq_reg->is_reg_base); |
817 | |
818 | edge_both |= readl_relaxed(base + irq_reg->ibe_reg_base) & ~mask; |
819 | writel_relaxed(edge_both, base + irq_reg->ibe_reg_base); |
820 | |
821 | polarity |= readl_relaxed(base + irq_reg->iev_reg_base) & ~mask; |
822 | writel_relaxed(polarity, base + irq_reg->iev_reg_base); |
823 | raw_spin_unlock_irqrestore(&sfp->lock, flags); |
824 | return 0; |
825 | } |
826 | |
827 | static struct irq_chip jh7110_irq_chip = { |
828 | .irq_ack = jh7110_irq_ack, |
829 | .irq_mask = jh7110_irq_mask, |
830 | .irq_mask_ack = jh7110_irq_mask_ack, |
831 | .irq_unmask = jh7110_irq_unmask, |
832 | .irq_set_type = jh7110_irq_set_type, |
833 | .flags = IRQCHIP_IMMUTABLE | IRQCHIP_SET_TYPE_MASKED, |
834 | GPIOCHIP_IRQ_RESOURCE_HELPERS, |
835 | }; |
836 | |
837 | static void jh7110_disable_clock(void *data) |
838 | { |
839 | clk_disable_unprepare(clk: data); |
840 | } |
841 | |
842 | int jh7110_pinctrl_probe(struct platform_device *pdev) |
843 | { |
844 | struct device *dev = &pdev->dev; |
845 | const struct jh7110_pinctrl_soc_info *info; |
846 | struct jh7110_pinctrl *sfp; |
847 | struct pinctrl_desc *jh7110_pinctrl_desc; |
848 | struct reset_control *rst; |
849 | struct clk *clk; |
850 | int ret; |
851 | |
852 | info = of_device_get_match_data(dev: &pdev->dev); |
853 | if (!info) |
854 | return -ENODEV; |
855 | |
856 | if (!info->pins || !info->npins) { |
857 | dev_err(dev, "wrong pinctrl info\n" ); |
858 | return -EINVAL; |
859 | } |
860 | |
861 | sfp = devm_kzalloc(dev, size: sizeof(*sfp), GFP_KERNEL); |
862 | if (!sfp) |
863 | return -ENOMEM; |
864 | |
865 | #if IS_ENABLED(CONFIG_PM_SLEEP) |
866 | sfp->saved_regs = devm_kcalloc(dev, n: info->nsaved_regs, |
867 | size: sizeof(*sfp->saved_regs), GFP_KERNEL); |
868 | if (!sfp->saved_regs) |
869 | return -ENOMEM; |
870 | #endif |
871 | |
872 | sfp->base = devm_platform_ioremap_resource(pdev, index: 0); |
873 | if (IS_ERR(ptr: sfp->base)) |
874 | return PTR_ERR(ptr: sfp->base); |
875 | |
876 | clk = devm_clk_get_optional(dev, NULL); |
877 | if (IS_ERR(ptr: clk)) |
878 | return dev_err_probe(dev, err: PTR_ERR(ptr: clk), fmt: "could not get clock\n" ); |
879 | |
880 | rst = devm_reset_control_get_exclusive(dev, NULL); |
881 | if (IS_ERR(ptr: rst)) |
882 | return dev_err_probe(dev, err: PTR_ERR(ptr: rst), fmt: "could not get reset\n" ); |
883 | |
884 | /* |
885 | * we don't want to assert reset and risk undoing pin muxing for the |
886 | * early boot serial console, but let's make sure the reset line is |
887 | * deasserted in case someone runs a really minimal bootloader. |
888 | */ |
889 | ret = reset_control_deassert(rstc: rst); |
890 | if (ret) |
891 | return dev_err_probe(dev, err: ret, fmt: "could not deassert reset\n" ); |
892 | |
893 | if (clk) { |
894 | ret = clk_prepare_enable(clk); |
895 | if (ret) |
896 | return dev_err_probe(dev, err: ret, fmt: "could not enable clock\n" ); |
897 | |
898 | ret = devm_add_action_or_reset(dev, jh7110_disable_clock, clk); |
899 | if (ret) |
900 | return ret; |
901 | } |
902 | |
903 | jh7110_pinctrl_desc = devm_kzalloc(dev: &pdev->dev, |
904 | size: sizeof(*jh7110_pinctrl_desc), |
905 | GFP_KERNEL); |
906 | if (!jh7110_pinctrl_desc) |
907 | return -ENOMEM; |
908 | |
909 | jh7110_pinctrl_desc->name = dev_name(dev); |
910 | jh7110_pinctrl_desc->pins = info->pins; |
911 | jh7110_pinctrl_desc->npins = info->npins; |
912 | jh7110_pinctrl_desc->pctlops = &jh7110_pinctrl_ops; |
913 | jh7110_pinctrl_desc->pmxops = &jh7110_pinmux_ops; |
914 | jh7110_pinctrl_desc->confops = &jh7110_pinconf_ops; |
915 | jh7110_pinctrl_desc->owner = THIS_MODULE; |
916 | |
917 | sfp->info = info; |
918 | sfp->dev = dev; |
919 | platform_set_drvdata(pdev, data: sfp); |
920 | sfp->gc.parent = dev; |
921 | raw_spin_lock_init(&sfp->lock); |
922 | mutex_init(&sfp->mutex); |
923 | |
924 | ret = devm_pinctrl_register_and_init(dev, |
925 | pctldesc: jh7110_pinctrl_desc, |
926 | driver_data: sfp, pctldev: &sfp->pctl); |
927 | if (ret) |
928 | return dev_err_probe(dev, err: ret, |
929 | fmt: "could not register pinctrl driver\n" ); |
930 | |
931 | sfp->gc.label = dev_name(dev); |
932 | sfp->gc.owner = THIS_MODULE; |
933 | sfp->gc.request = pinctrl_gpio_request; |
934 | sfp->gc.free = pinctrl_gpio_free; |
935 | sfp->gc.get_direction = jh7110_gpio_get_direction; |
936 | sfp->gc.direction_input = jh7110_gpio_direction_input; |
937 | sfp->gc.direction_output = jh7110_gpio_direction_output; |
938 | sfp->gc.get = jh7110_gpio_get; |
939 | sfp->gc.set = jh7110_gpio_set; |
940 | sfp->gc.set_config = jh7110_gpio_set_config; |
941 | sfp->gc.add_pin_ranges = jh7110_gpio_add_pin_ranges; |
942 | sfp->gc.base = info->gc_base; |
943 | sfp->gc.ngpio = info->ngpios; |
944 | |
945 | jh7110_irq_chip.name = sfp->gc.label; |
946 | gpio_irq_chip_set_chip(girq: &sfp->gc.irq, chip: &jh7110_irq_chip); |
947 | sfp->gc.irq.parent_handler = info->jh7110_gpio_irq_handler; |
948 | sfp->gc.irq.num_parents = 1; |
949 | sfp->gc.irq.parents = devm_kcalloc(dev, n: sfp->gc.irq.num_parents, |
950 | size: sizeof(*sfp->gc.irq.parents), |
951 | GFP_KERNEL); |
952 | if (!sfp->gc.irq.parents) |
953 | return -ENOMEM; |
954 | sfp->gc.irq.default_type = IRQ_TYPE_NONE; |
955 | sfp->gc.irq.handler = handle_bad_irq; |
956 | sfp->gc.irq.init_hw = info->jh7110_gpio_init_hw; |
957 | |
958 | ret = platform_get_irq(pdev, 0); |
959 | if (ret < 0) |
960 | return ret; |
961 | sfp->gc.irq.parents[0] = ret; |
962 | |
963 | ret = devm_gpiochip_add_data(dev, &sfp->gc, sfp); |
964 | if (ret) |
965 | return dev_err_probe(dev, err: ret, fmt: "could not register gpiochip\n" ); |
966 | |
967 | dev_info(dev, "StarFive GPIO chip registered %d GPIOs\n" , sfp->gc.ngpio); |
968 | |
969 | return pinctrl_enable(pctldev: sfp->pctl); |
970 | } |
971 | EXPORT_SYMBOL_GPL(jh7110_pinctrl_probe); |
972 | |
973 | static int jh7110_pinctrl_suspend(struct device *dev) |
974 | { |
975 | struct jh7110_pinctrl *sfp = dev_get_drvdata(dev); |
976 | unsigned long flags; |
977 | unsigned int i; |
978 | |
979 | raw_spin_lock_irqsave(&sfp->lock, flags); |
980 | for (i = 0 ; i < sfp->info->nsaved_regs ; i++) |
981 | sfp->saved_regs[i] = readl_relaxed(sfp->base + 4 * i); |
982 | |
983 | raw_spin_unlock_irqrestore(&sfp->lock, flags); |
984 | return 0; |
985 | } |
986 | |
987 | static int jh7110_pinctrl_resume(struct device *dev) |
988 | { |
989 | struct jh7110_pinctrl *sfp = dev_get_drvdata(dev); |
990 | unsigned long flags; |
991 | unsigned int i; |
992 | |
993 | raw_spin_lock_irqsave(&sfp->lock, flags); |
994 | for (i = 0 ; i < sfp->info->nsaved_regs ; i++) |
995 | writel_relaxed(sfp->saved_regs[i], sfp->base + 4 * i); |
996 | |
997 | raw_spin_unlock_irqrestore(&sfp->lock, flags); |
998 | return 0; |
999 | } |
1000 | |
1001 | const struct dev_pm_ops jh7110_pinctrl_pm_ops = { |
1002 | LATE_SYSTEM_SLEEP_PM_OPS(jh7110_pinctrl_suspend, jh7110_pinctrl_resume) |
1003 | }; |
1004 | EXPORT_SYMBOL_GPL(jh7110_pinctrl_pm_ops); |
1005 | |
1006 | MODULE_DESCRIPTION("Pinctrl driver for the StarFive JH7110 SoC" ); |
1007 | MODULE_AUTHOR("Emil Renner Berthing <kernel@esmil.dk>" ); |
1008 | MODULE_AUTHOR("Jianlong Huang <jianlong.huang@starfivetech.com>" ); |
1009 | MODULE_LICENSE("GPL" ); |
1010 | |