Commit | Line | Data |
---|---|---|
611dac1e NA |
1 | /* |
2 | * Oxford Semiconductor OXNAS SoC Family pinctrl driver | |
3 | * | |
4 | * Copyright (C) 2016 Neil Armstrong <narmstrong@baylibre.com> | |
5 | * | |
6 | * Based on pinctrl-pic32.c | |
7 | * Joshua Henderson, <joshua.henderson@microchip.com> | |
8 | * Copyright (C) 2015 Microchip Technology Inc. All rights reserved. | |
9 | * | |
10 | * This program is free software; you can distribute it and/or modify it | |
11 | * under the terms of the GNU General Public License (Version 2) as | |
12 | * published by the Free Software Foundation. | |
13 | * | |
14 | * This program is distributed in the hope it will be useful, but WITHOUT | |
15 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
16 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
17 | * for more details. | |
18 | */ | |
19 | #include <linux/gpio/driver.h> | |
20 | #include <linux/interrupt.h> | |
21 | #include <linux/io.h> | |
22 | #include <linux/irq.h> | |
23 | #include <linux/of.h> | |
24 | #include <linux/of_device.h> | |
25 | #include <linux/pinctrl/pinconf.h> | |
26 | #include <linux/pinctrl/pinconf-generic.h> | |
27 | #include <linux/pinctrl/pinctrl.h> | |
28 | #include <linux/pinctrl/pinmux.h> | |
29 | #include <linux/platform_device.h> | |
30 | #include <linux/slab.h> | |
31 | #include <linux/regmap.h> | |
32 | #include <linux/mfd/syscon.h> | |
33 | ||
34 | #include "pinctrl-utils.h" | |
35 | ||
36 | #define PINS_PER_BANK 32 | |
37 | ||
38 | #define GPIO_BANK_START(bank) ((bank) * PINS_PER_BANK) | |
39 | ||
40 | /* Regmap Offsets */ | |
41 | #define PINMUX_PRIMARY_SEL0 0x0c | |
42 | #define PINMUX_SECONDARY_SEL0 0x14 | |
43 | #define PINMUX_TERTIARY_SEL0 0x8c | |
44 | #define PINMUX_PRIMARY_SEL1 0x10 | |
45 | #define PINMUX_SECONDARY_SEL1 0x18 | |
46 | #define PINMUX_TERTIARY_SEL1 0x90 | |
47 | #define PINMUX_PULLUP_CTRL0 0xac | |
48 | #define PINMUX_PULLUP_CTRL1 0xb0 | |
49 | ||
50 | /* GPIO Registers */ | |
51 | #define INPUT_VALUE 0x00 | |
2f94ced7 | 52 | #define OUTPUT_EN 0x04 |
611dac1e NA |
53 | #define IRQ_PENDING 0x0c |
54 | #define OUTPUT_SET 0x14 | |
55 | #define OUTPUT_CLEAR 0x18 | |
56 | #define OUTPUT_EN_SET 0x1c | |
57 | #define OUTPUT_EN_CLEAR 0x20 | |
58 | #define RE_IRQ_ENABLE 0x28 | |
59 | #define FE_IRQ_ENABLE 0x2c | |
60 | ||
61 | struct oxnas_function { | |
62 | const char *name; | |
63 | const char * const *groups; | |
64 | unsigned int ngroups; | |
65 | }; | |
66 | ||
67 | struct oxnas_pin_group { | |
68 | const char *name; | |
69 | unsigned int pin; | |
70 | unsigned int bank; | |
71 | struct oxnas_desc_function *functions; | |
72 | }; | |
73 | ||
74 | struct oxnas_desc_function { | |
75 | const char *name; | |
76 | unsigned int fct; | |
77 | }; | |
78 | ||
79 | struct oxnas_gpio_bank { | |
80 | void __iomem *reg_base; | |
81 | struct gpio_chip gpio_chip; | |
82 | struct irq_chip irq_chip; | |
83 | unsigned int id; | |
84 | }; | |
85 | ||
86 | struct oxnas_pinctrl { | |
87 | struct regmap *regmap; | |
88 | struct device *dev; | |
89 | struct pinctrl_dev *pctldev; | |
90 | const struct pinctrl_pin_desc *pins; | |
91 | unsigned int npins; | |
92 | const struct oxnas_function *functions; | |
93 | unsigned int nfunctions; | |
94 | const struct oxnas_pin_group *groups; | |
95 | unsigned int ngroups; | |
96 | struct oxnas_gpio_bank *gpio_banks; | |
97 | unsigned int nbanks; | |
98 | }; | |
99 | ||
100 | static const struct pinctrl_pin_desc oxnas_pins[] = { | |
101 | PINCTRL_PIN(0, "gpio0"), | |
102 | PINCTRL_PIN(1, "gpio1"), | |
103 | PINCTRL_PIN(2, "gpio2"), | |
104 | PINCTRL_PIN(3, "gpio3"), | |
105 | PINCTRL_PIN(4, "gpio4"), | |
106 | PINCTRL_PIN(5, "gpio5"), | |
107 | PINCTRL_PIN(6, "gpio6"), | |
108 | PINCTRL_PIN(7, "gpio7"), | |
109 | PINCTRL_PIN(8, "gpio8"), | |
110 | PINCTRL_PIN(9, "gpio9"), | |
111 | PINCTRL_PIN(10, "gpio10"), | |
112 | PINCTRL_PIN(11, "gpio11"), | |
113 | PINCTRL_PIN(12, "gpio12"), | |
114 | PINCTRL_PIN(13, "gpio13"), | |
115 | PINCTRL_PIN(14, "gpio14"), | |
116 | PINCTRL_PIN(15, "gpio15"), | |
117 | PINCTRL_PIN(16, "gpio16"), | |
118 | PINCTRL_PIN(17, "gpio17"), | |
119 | PINCTRL_PIN(18, "gpio18"), | |
120 | PINCTRL_PIN(19, "gpio19"), | |
121 | PINCTRL_PIN(20, "gpio20"), | |
122 | PINCTRL_PIN(21, "gpio21"), | |
123 | PINCTRL_PIN(22, "gpio22"), | |
124 | PINCTRL_PIN(23, "gpio23"), | |
125 | PINCTRL_PIN(24, "gpio24"), | |
126 | PINCTRL_PIN(25, "gpio25"), | |
127 | PINCTRL_PIN(26, "gpio26"), | |
128 | PINCTRL_PIN(27, "gpio27"), | |
129 | PINCTRL_PIN(28, "gpio28"), | |
130 | PINCTRL_PIN(29, "gpio29"), | |
131 | PINCTRL_PIN(30, "gpio30"), | |
132 | PINCTRL_PIN(31, "gpio31"), | |
133 | PINCTRL_PIN(32, "gpio32"), | |
134 | PINCTRL_PIN(33, "gpio33"), | |
135 | PINCTRL_PIN(34, "gpio34"), | |
136 | }; | |
137 | ||
138 | static const char * const oxnas_fct0_group[] = { | |
139 | "gpio0", "gpio1", "gpio2", "gpio3", | |
140 | "gpio4", "gpio5", "gpio6", "gpio7", | |
141 | "gpio8", "gpio9", "gpio10", "gpio11", | |
142 | "gpio12", "gpio13", "gpio14", "gpio15", | |
143 | "gpio16", "gpio17", "gpio18", "gpio19", | |
144 | "gpio20", "gpio21", "gpio22", "gpio23", | |
145 | "gpio24", "gpio25", "gpio26", "gpio27", | |
146 | "gpio28", "gpio29", "gpio30", "gpio31", | |
147 | "gpio32", "gpio33", "gpio34" | |
148 | }; | |
149 | ||
150 | static const char * const oxnas_fct3_group[] = { | |
151 | "gpio0", "gpio1", "gpio2", "gpio3", | |
152 | "gpio4", "gpio5", "gpio6", "gpio7", | |
153 | "gpio8", "gpio9", | |
154 | "gpio20", | |
155 | "gpio22", "gpio23", "gpio24", "gpio25", | |
156 | "gpio26", "gpio27", "gpio28", "gpio29", | |
157 | "gpio30", "gpio31", "gpio32", "gpio33", | |
158 | "gpio34" | |
159 | }; | |
160 | ||
161 | #define FUNCTION(_name, _gr) \ | |
162 | { \ | |
163 | .name = #_name, \ | |
164 | .groups = oxnas_##_gr##_group, \ | |
165 | .ngroups = ARRAY_SIZE(oxnas_##_gr##_group), \ | |
166 | } | |
167 | ||
168 | static const struct oxnas_function oxnas_functions[] = { | |
169 | FUNCTION(gpio, fct0), | |
170 | FUNCTION(fct3, fct3), | |
171 | }; | |
172 | ||
173 | #define OXNAS_PINCTRL_GROUP(_pin, _name, ...) \ | |
174 | { \ | |
175 | .name = #_name, \ | |
176 | .pin = _pin, \ | |
177 | .bank = _pin / PINS_PER_BANK, \ | |
178 | .functions = (struct oxnas_desc_function[]){ \ | |
179 | __VA_ARGS__, { } }, \ | |
180 | } | |
181 | ||
182 | #define OXNAS_PINCTRL_FUNCTION(_name, _fct) \ | |
183 | { \ | |
184 | .name = #_name, \ | |
185 | .fct = _fct, \ | |
186 | } | |
187 | ||
188 | static const struct oxnas_pin_group oxnas_groups[] = { | |
189 | OXNAS_PINCTRL_GROUP(0, gpio0, | |
190 | OXNAS_PINCTRL_FUNCTION(gpio, 0), | |
191 | OXNAS_PINCTRL_FUNCTION(fct3, 3)), | |
192 | OXNAS_PINCTRL_GROUP(1, gpio1, | |
193 | OXNAS_PINCTRL_FUNCTION(gpio, 0), | |
194 | OXNAS_PINCTRL_FUNCTION(fct3, 3)), | |
195 | OXNAS_PINCTRL_GROUP(2, gpio2, | |
196 | OXNAS_PINCTRL_FUNCTION(gpio, 0), | |
197 | OXNAS_PINCTRL_FUNCTION(fct3, 3)), | |
198 | OXNAS_PINCTRL_GROUP(3, gpio3, | |
199 | OXNAS_PINCTRL_FUNCTION(gpio, 0), | |
200 | OXNAS_PINCTRL_FUNCTION(fct3, 3)), | |
201 | OXNAS_PINCTRL_GROUP(4, gpio4, | |
202 | OXNAS_PINCTRL_FUNCTION(gpio, 0), | |
203 | OXNAS_PINCTRL_FUNCTION(fct3, 3)), | |
204 | OXNAS_PINCTRL_GROUP(5, gpio5, | |
205 | OXNAS_PINCTRL_FUNCTION(gpio, 0), | |
206 | OXNAS_PINCTRL_FUNCTION(fct3, 3)), | |
207 | OXNAS_PINCTRL_GROUP(6, gpio6, | |
208 | OXNAS_PINCTRL_FUNCTION(gpio, 0), | |
209 | OXNAS_PINCTRL_FUNCTION(fct3, 3)), | |
210 | OXNAS_PINCTRL_GROUP(7, gpio7, | |
211 | OXNAS_PINCTRL_FUNCTION(gpio, 0), | |
212 | OXNAS_PINCTRL_FUNCTION(fct3, 3)), | |
213 | OXNAS_PINCTRL_GROUP(8, gpio8, | |
214 | OXNAS_PINCTRL_FUNCTION(gpio, 0), | |
215 | OXNAS_PINCTRL_FUNCTION(fct3, 3)), | |
216 | OXNAS_PINCTRL_GROUP(9, gpio9, | |
217 | OXNAS_PINCTRL_FUNCTION(gpio, 0), | |
218 | OXNAS_PINCTRL_FUNCTION(fct3, 3)), | |
219 | OXNAS_PINCTRL_GROUP(10, gpio10, | |
220 | OXNAS_PINCTRL_FUNCTION(gpio, 0)), | |
221 | OXNAS_PINCTRL_GROUP(11, gpio11, | |
222 | OXNAS_PINCTRL_FUNCTION(gpio, 0)), | |
223 | OXNAS_PINCTRL_GROUP(12, gpio12, | |
224 | OXNAS_PINCTRL_FUNCTION(gpio, 0)), | |
225 | OXNAS_PINCTRL_GROUP(13, gpio13, | |
226 | OXNAS_PINCTRL_FUNCTION(gpio, 0)), | |
227 | OXNAS_PINCTRL_GROUP(14, gpio14, | |
228 | OXNAS_PINCTRL_FUNCTION(gpio, 0)), | |
229 | OXNAS_PINCTRL_GROUP(15, gpio15, | |
230 | OXNAS_PINCTRL_FUNCTION(gpio, 0)), | |
231 | OXNAS_PINCTRL_GROUP(16, gpio16, | |
232 | OXNAS_PINCTRL_FUNCTION(gpio, 0)), | |
233 | OXNAS_PINCTRL_GROUP(17, gpio17, | |
234 | OXNAS_PINCTRL_FUNCTION(gpio, 0)), | |
235 | OXNAS_PINCTRL_GROUP(18, gpio18, | |
236 | OXNAS_PINCTRL_FUNCTION(gpio, 0)), | |
237 | OXNAS_PINCTRL_GROUP(19, gpio19, | |
238 | OXNAS_PINCTRL_FUNCTION(gpio, 0)), | |
239 | OXNAS_PINCTRL_GROUP(20, gpio20, | |
240 | OXNAS_PINCTRL_FUNCTION(gpio, 0), | |
241 | OXNAS_PINCTRL_FUNCTION(fct3, 3)), | |
242 | OXNAS_PINCTRL_GROUP(21, gpio21, | |
243 | OXNAS_PINCTRL_FUNCTION(gpio, 0)), | |
244 | OXNAS_PINCTRL_GROUP(22, gpio22, | |
245 | OXNAS_PINCTRL_FUNCTION(gpio, 0), | |
246 | OXNAS_PINCTRL_FUNCTION(fct3, 3)), | |
247 | OXNAS_PINCTRL_GROUP(23, gpio23, | |
248 | OXNAS_PINCTRL_FUNCTION(gpio, 0), | |
249 | OXNAS_PINCTRL_FUNCTION(fct3, 3)), | |
250 | OXNAS_PINCTRL_GROUP(24, gpio24, | |
251 | OXNAS_PINCTRL_FUNCTION(gpio, 0), | |
252 | OXNAS_PINCTRL_FUNCTION(fct3, 3)), | |
253 | OXNAS_PINCTRL_GROUP(25, gpio25, | |
254 | OXNAS_PINCTRL_FUNCTION(gpio, 0), | |
255 | OXNAS_PINCTRL_FUNCTION(fct3, 3)), | |
256 | OXNAS_PINCTRL_GROUP(26, gpio26, | |
257 | OXNAS_PINCTRL_FUNCTION(gpio, 0), | |
258 | OXNAS_PINCTRL_FUNCTION(fct3, 3)), | |
259 | OXNAS_PINCTRL_GROUP(27, gpio27, | |
260 | OXNAS_PINCTRL_FUNCTION(gpio, 0), | |
261 | OXNAS_PINCTRL_FUNCTION(fct3, 3)), | |
262 | OXNAS_PINCTRL_GROUP(28, gpio28, | |
263 | OXNAS_PINCTRL_FUNCTION(gpio, 0), | |
264 | OXNAS_PINCTRL_FUNCTION(fct3, 3)), | |
265 | OXNAS_PINCTRL_GROUP(29, gpio29, | |
266 | OXNAS_PINCTRL_FUNCTION(gpio, 0), | |
267 | OXNAS_PINCTRL_FUNCTION(fct3, 3)), | |
268 | OXNAS_PINCTRL_GROUP(30, gpio30, | |
269 | OXNAS_PINCTRL_FUNCTION(gpio, 0), | |
270 | OXNAS_PINCTRL_FUNCTION(fct3, 3)), | |
271 | OXNAS_PINCTRL_GROUP(31, gpio31, | |
272 | OXNAS_PINCTRL_FUNCTION(gpio, 0), | |
273 | OXNAS_PINCTRL_FUNCTION(fct3, 3)), | |
274 | OXNAS_PINCTRL_GROUP(32, gpio32, | |
275 | OXNAS_PINCTRL_FUNCTION(gpio, 0), | |
276 | OXNAS_PINCTRL_FUNCTION(fct3, 3)), | |
277 | OXNAS_PINCTRL_GROUP(33, gpio33, | |
278 | OXNAS_PINCTRL_FUNCTION(gpio, 0), | |
279 | OXNAS_PINCTRL_FUNCTION(fct3, 3)), | |
280 | OXNAS_PINCTRL_GROUP(34, gpio34, | |
281 | OXNAS_PINCTRL_FUNCTION(gpio, 0), | |
282 | OXNAS_PINCTRL_FUNCTION(fct3, 3)), | |
283 | }; | |
284 | ||
285 | static inline struct oxnas_gpio_bank *pctl_to_bank(struct oxnas_pinctrl *pctl, | |
286 | unsigned int pin) | |
287 | { | |
288 | return &pctl->gpio_banks[pin / PINS_PER_BANK]; | |
289 | } | |
290 | ||
291 | static int oxnas_pinctrl_get_groups_count(struct pinctrl_dev *pctldev) | |
292 | { | |
293 | struct oxnas_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); | |
294 | ||
295 | return pctl->ngroups; | |
296 | } | |
297 | ||
298 | static const char *oxnas_pinctrl_get_group_name(struct pinctrl_dev *pctldev, | |
299 | unsigned int group) | |
300 | { | |
301 | struct oxnas_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); | |
302 | ||
303 | return pctl->groups[group].name; | |
304 | } | |
305 | ||
306 | static int oxnas_pinctrl_get_group_pins(struct pinctrl_dev *pctldev, | |
307 | unsigned int group, | |
308 | const unsigned int **pins, | |
309 | unsigned int *num_pins) | |
310 | { | |
311 | struct oxnas_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); | |
312 | ||
313 | *pins = &pctl->groups[group].pin; | |
314 | *num_pins = 1; | |
315 | ||
316 | return 0; | |
317 | } | |
318 | ||
319 | static const struct pinctrl_ops oxnas_pinctrl_ops = { | |
320 | .get_groups_count = oxnas_pinctrl_get_groups_count, | |
321 | .get_group_name = oxnas_pinctrl_get_group_name, | |
322 | .get_group_pins = oxnas_pinctrl_get_group_pins, | |
323 | .dt_node_to_map = pinconf_generic_dt_node_to_map_pin, | |
4d6ddd3b | 324 | .dt_free_map = pinctrl_utils_free_map, |
611dac1e NA |
325 | }; |
326 | ||
327 | static int oxnas_pinmux_get_functions_count(struct pinctrl_dev *pctldev) | |
328 | { | |
329 | struct oxnas_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); | |
330 | ||
331 | return pctl->nfunctions; | |
332 | } | |
333 | ||
334 | static const char * | |
335 | oxnas_pinmux_get_function_name(struct pinctrl_dev *pctldev, unsigned int func) | |
336 | { | |
337 | struct oxnas_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); | |
338 | ||
339 | return pctl->functions[func].name; | |
340 | } | |
341 | ||
342 | static int oxnas_pinmux_get_function_groups(struct pinctrl_dev *pctldev, | |
343 | unsigned int func, | |
344 | const char * const **groups, | |
345 | unsigned int * const num_groups) | |
346 | { | |
347 | struct oxnas_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); | |
348 | ||
349 | *groups = pctl->functions[func].groups; | |
350 | *num_groups = pctl->functions[func].ngroups; | |
351 | ||
352 | return 0; | |
353 | } | |
354 | ||
355 | static int oxnas_pinmux_enable(struct pinctrl_dev *pctldev, | |
356 | unsigned int func, unsigned int group) | |
357 | { | |
358 | struct oxnas_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); | |
359 | const struct oxnas_pin_group *pg = &pctl->groups[group]; | |
360 | const struct oxnas_function *pf = &pctl->functions[func]; | |
361 | const char *fname = pf->name; | |
362 | struct oxnas_desc_function *functions = pg->functions; | |
363 | u32 mask = BIT(pg->pin); | |
364 | ||
365 | while (functions->name) { | |
366 | if (!strcmp(functions->name, fname)) { | |
367 | dev_dbg(pctl->dev, | |
368 | "setting function %s bank %d pin %d fct %d mask %x\n", | |
369 | fname, pg->bank, pg->pin, | |
370 | functions->fct, mask); | |
371 | ||
372 | regmap_write_bits(pctl->regmap, | |
373 | (pg->bank ? | |
374 | PINMUX_PRIMARY_SEL1 : | |
375 | PINMUX_PRIMARY_SEL0), | |
376 | mask, | |
377 | (functions->fct == 1 ? | |
378 | mask : 0)); | |
379 | regmap_write_bits(pctl->regmap, | |
380 | (pg->bank ? | |
381 | PINMUX_SECONDARY_SEL1 : | |
382 | PINMUX_SECONDARY_SEL0), | |
383 | mask, | |
384 | (functions->fct == 2 ? | |
385 | mask : 0)); | |
386 | regmap_write_bits(pctl->regmap, | |
387 | (pg->bank ? | |
388 | PINMUX_TERTIARY_SEL1 : | |
389 | PINMUX_TERTIARY_SEL0), | |
390 | mask, | |
391 | (functions->fct == 3 ? | |
392 | mask : 0)); | |
393 | ||
394 | return 0; | |
395 | } | |
396 | ||
397 | functions++; | |
398 | } | |
399 | ||
400 | dev_err(pctl->dev, "cannot mux pin %u to function %u\n", group, func); | |
401 | ||
402 | return -EINVAL; | |
403 | } | |
404 | ||
405 | static int oxnas_gpio_request_enable(struct pinctrl_dev *pctldev, | |
406 | struct pinctrl_gpio_range *range, | |
407 | unsigned int offset) | |
408 | { | |
409 | struct oxnas_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); | |
410 | struct oxnas_gpio_bank *bank = gpiochip_get_data(range->gc); | |
411 | u32 mask = BIT(offset - bank->gpio_chip.base); | |
412 | ||
413 | dev_dbg(pctl->dev, "requesting gpio %d in bank %d (id %d) with mask 0x%x\n", | |
414 | offset, bank->gpio_chip.base, bank->id, mask); | |
415 | ||
416 | regmap_write_bits(pctl->regmap, | |
417 | (bank->id ? | |
418 | PINMUX_PRIMARY_SEL1 : | |
419 | PINMUX_PRIMARY_SEL0), | |
420 | mask, 0); | |
421 | regmap_write_bits(pctl->regmap, | |
422 | (bank->id ? | |
423 | PINMUX_SECONDARY_SEL1 : | |
424 | PINMUX_SECONDARY_SEL0), | |
425 | mask, 0); | |
426 | regmap_write_bits(pctl->regmap, | |
427 | (bank->id ? | |
428 | PINMUX_TERTIARY_SEL1 : | |
429 | PINMUX_TERTIARY_SEL0), | |
430 | mask, 0); | |
431 | ||
432 | return 0; | |
433 | } | |
434 | ||
2f94ced7 NA |
435 | static int oxnas_gpio_get_direction(struct gpio_chip *chip, |
436 | unsigned int offset) | |
437 | { | |
438 | struct oxnas_gpio_bank *bank = gpiochip_get_data(chip); | |
439 | u32 mask = BIT(offset); | |
440 | ||
441 | return !(readl_relaxed(bank->reg_base + OUTPUT_EN) & mask); | |
442 | } | |
443 | ||
611dac1e NA |
444 | static int oxnas_gpio_direction_input(struct gpio_chip *chip, |
445 | unsigned int offset) | |
446 | { | |
447 | struct oxnas_gpio_bank *bank = gpiochip_get_data(chip); | |
448 | u32 mask = BIT(offset); | |
449 | ||
450 | writel_relaxed(mask, bank->reg_base + OUTPUT_EN_CLEAR); | |
451 | ||
452 | return 0; | |
453 | } | |
454 | ||
455 | static int oxnas_gpio_get(struct gpio_chip *chip, unsigned int offset) | |
456 | { | |
457 | struct oxnas_gpio_bank *bank = gpiochip_get_data(chip); | |
458 | u32 mask = BIT(offset); | |
459 | ||
460 | return (readl_relaxed(bank->reg_base + INPUT_VALUE) & mask) != 0; | |
461 | } | |
462 | ||
463 | static void oxnas_gpio_set(struct gpio_chip *chip, unsigned int offset, | |
464 | int value) | |
465 | { | |
466 | struct oxnas_gpio_bank *bank = gpiochip_get_data(chip); | |
467 | u32 mask = BIT(offset); | |
468 | ||
469 | if (value) | |
470 | writel_relaxed(mask, bank->reg_base + OUTPUT_SET); | |
471 | else | |
472 | writel_relaxed(mask, bank->reg_base + OUTPUT_CLEAR); | |
473 | } | |
474 | ||
475 | static int oxnas_gpio_direction_output(struct gpio_chip *chip, | |
476 | unsigned int offset, int value) | |
477 | { | |
478 | struct oxnas_gpio_bank *bank = gpiochip_get_data(chip); | |
479 | u32 mask = BIT(offset); | |
480 | ||
481 | oxnas_gpio_set(chip, offset, value); | |
482 | writel_relaxed(mask, bank->reg_base + OUTPUT_EN_SET); | |
483 | ||
484 | return 0; | |
485 | } | |
486 | ||
487 | static int oxnas_gpio_set_direction(struct pinctrl_dev *pctldev, | |
488 | struct pinctrl_gpio_range *range, | |
489 | unsigned int offset, bool input) | |
490 | { | |
491 | struct gpio_chip *chip = range->gc; | |
492 | ||
493 | if (input) | |
494 | oxnas_gpio_direction_input(chip, offset); | |
495 | else | |
496 | oxnas_gpio_direction_output(chip, offset, 0); | |
497 | ||
498 | return 0; | |
499 | } | |
500 | ||
501 | static const struct pinmux_ops oxnas_pinmux_ops = { | |
502 | .get_functions_count = oxnas_pinmux_get_functions_count, | |
503 | .get_function_name = oxnas_pinmux_get_function_name, | |
504 | .get_function_groups = oxnas_pinmux_get_function_groups, | |
505 | .set_mux = oxnas_pinmux_enable, | |
506 | .gpio_request_enable = oxnas_gpio_request_enable, | |
507 | .gpio_set_direction = oxnas_gpio_set_direction, | |
508 | }; | |
509 | ||
510 | static int oxnas_pinconf_get(struct pinctrl_dev *pctldev, unsigned int pin, | |
511 | unsigned long *config) | |
512 | { | |
513 | struct oxnas_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); | |
514 | struct oxnas_gpio_bank *bank = pctl_to_bank(pctl, pin); | |
515 | unsigned int param = pinconf_to_config_param(*config); | |
516 | u32 mask = BIT(pin - bank->gpio_chip.base); | |
517 | int ret; | |
518 | u32 arg; | |
519 | ||
520 | switch (param) { | |
521 | case PIN_CONFIG_BIAS_PULL_UP: | |
522 | ret = regmap_read(pctl->regmap, | |
523 | (bank->id ? | |
524 | PINMUX_PULLUP_CTRL1 : | |
525 | PINMUX_PULLUP_CTRL0), | |
526 | &arg); | |
527 | if (ret) | |
528 | return ret; | |
529 | ||
530 | arg = !!(arg & mask); | |
531 | break; | |
532 | default: | |
533 | return -ENOTSUPP; | |
534 | } | |
535 | ||
536 | *config = pinconf_to_config_packed(param, arg); | |
537 | ||
538 | return 0; | |
539 | } | |
540 | ||
541 | static int oxnas_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin, | |
542 | unsigned long *configs, unsigned int num_configs) | |
543 | { | |
544 | struct oxnas_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); | |
545 | struct oxnas_gpio_bank *bank = pctl_to_bank(pctl, pin); | |
546 | unsigned int param; | |
547 | u32 arg; | |
548 | unsigned int i; | |
549 | u32 offset = pin - bank->gpio_chip.base; | |
550 | u32 mask = BIT(offset); | |
551 | ||
552 | dev_dbg(pctl->dev, "setting pin %d bank %d mask 0x%x\n", | |
553 | pin, bank->gpio_chip.base, mask); | |
554 | ||
555 | for (i = 0; i < num_configs; i++) { | |
556 | param = pinconf_to_config_param(configs[i]); | |
557 | arg = pinconf_to_config_argument(configs[i]); | |
558 | ||
559 | switch (param) { | |
560 | case PIN_CONFIG_BIAS_PULL_UP: | |
561 | dev_dbg(pctl->dev, " pullup\n"); | |
562 | regmap_write_bits(pctl->regmap, | |
563 | (bank->id ? | |
564 | PINMUX_PULLUP_CTRL1 : | |
565 | PINMUX_PULLUP_CTRL0), | |
566 | mask, mask); | |
567 | break; | |
568 | default: | |
569 | dev_err(pctl->dev, "Property %u not supported\n", | |
570 | param); | |
571 | return -ENOTSUPP; | |
572 | } | |
573 | } | |
574 | ||
575 | return 0; | |
576 | } | |
577 | ||
578 | static const struct pinconf_ops oxnas_pinconf_ops = { | |
579 | .pin_config_get = oxnas_pinconf_get, | |
580 | .pin_config_set = oxnas_pinconf_set, | |
581 | .is_generic = true, | |
582 | }; | |
583 | ||
584 | static struct pinctrl_desc oxnas_pinctrl_desc = { | |
585 | .name = "oxnas-pinctrl", | |
586 | .pctlops = &oxnas_pinctrl_ops, | |
587 | .pmxops = &oxnas_pinmux_ops, | |
588 | .confops = &oxnas_pinconf_ops, | |
589 | .owner = THIS_MODULE, | |
590 | }; | |
591 | ||
592 | static void oxnas_gpio_irq_ack(struct irq_data *data) | |
593 | { | |
594 | struct gpio_chip *chip = irq_data_get_irq_chip_data(data); | |
595 | struct oxnas_gpio_bank *bank = gpiochip_get_data(chip); | |
596 | u32 mask = BIT(data->hwirq); | |
597 | ||
598 | writel(mask, bank->reg_base + IRQ_PENDING); | |
599 | } | |
600 | ||
601 | static void oxnas_gpio_irq_mask(struct irq_data *data) | |
602 | { | |
603 | struct gpio_chip *chip = irq_data_get_irq_chip_data(data); | |
604 | struct oxnas_gpio_bank *bank = gpiochip_get_data(chip); | |
605 | unsigned int type = irqd_get_trigger_type(data); | |
606 | u32 mask = BIT(data->hwirq); | |
607 | ||
608 | if (type & IRQ_TYPE_EDGE_RISING) | |
609 | writel(readl(bank->reg_base + RE_IRQ_ENABLE) & ~mask, | |
610 | bank->reg_base + RE_IRQ_ENABLE); | |
611 | ||
612 | if (type & IRQ_TYPE_EDGE_FALLING) | |
613 | writel(readl(bank->reg_base + FE_IRQ_ENABLE) & ~mask, | |
614 | bank->reg_base + FE_IRQ_ENABLE); | |
615 | } | |
616 | ||
617 | static void oxnas_gpio_irq_unmask(struct irq_data *data) | |
618 | { | |
619 | struct gpio_chip *chip = irq_data_get_irq_chip_data(data); | |
620 | struct oxnas_gpio_bank *bank = gpiochip_get_data(chip); | |
621 | unsigned int type = irqd_get_trigger_type(data); | |
622 | u32 mask = BIT(data->hwirq); | |
623 | ||
624 | if (type & IRQ_TYPE_EDGE_RISING) | |
625 | writel(readl(bank->reg_base + RE_IRQ_ENABLE) | mask, | |
626 | bank->reg_base + RE_IRQ_ENABLE); | |
627 | ||
628 | if (type & IRQ_TYPE_EDGE_FALLING) | |
629 | writel(readl(bank->reg_base + FE_IRQ_ENABLE) | mask, | |
630 | bank->reg_base + FE_IRQ_ENABLE); | |
631 | } | |
632 | ||
633 | static unsigned int oxnas_gpio_irq_startup(struct irq_data *data) | |
634 | { | |
635 | struct gpio_chip *chip = irq_data_get_irq_chip_data(data); | |
636 | ||
637 | oxnas_gpio_direction_input(chip, data->hwirq); | |
638 | oxnas_gpio_irq_unmask(data); | |
639 | ||
640 | return 0; | |
641 | } | |
642 | ||
643 | static int oxnas_gpio_irq_set_type(struct irq_data *data, unsigned int type) | |
644 | { | |
645 | if ((type & (IRQ_TYPE_EDGE_RISING|IRQ_TYPE_EDGE_FALLING)) == 0) | |
646 | return -EINVAL; | |
647 | ||
648 | irq_set_handler_locked(data, handle_edge_irq); | |
649 | ||
650 | return 0; | |
651 | } | |
652 | ||
653 | static void oxnas_gpio_irq_handler(struct irq_desc *desc) | |
654 | { | |
655 | struct gpio_chip *gc = irq_desc_get_handler_data(desc); | |
656 | struct oxnas_gpio_bank *bank = gpiochip_get_data(gc); | |
657 | struct irq_chip *chip = irq_desc_get_chip(desc); | |
658 | unsigned long stat; | |
659 | unsigned int pin; | |
660 | ||
661 | chained_irq_enter(chip, desc); | |
662 | ||
663 | stat = readl(bank->reg_base + IRQ_PENDING); | |
664 | ||
665 | for_each_set_bit(pin, &stat, BITS_PER_LONG) | |
666 | generic_handle_irq(irq_linear_revmap(gc->irqdomain, pin)); | |
667 | ||
668 | chained_irq_exit(chip, desc); | |
669 | } | |
670 | ||
671 | #define GPIO_BANK(_bank) \ | |
672 | { \ | |
673 | .gpio_chip = { \ | |
674 | .label = "GPIO" #_bank, \ | |
675 | .request = gpiochip_generic_request, \ | |
676 | .free = gpiochip_generic_free, \ | |
2f94ced7 | 677 | .get_direction = oxnas_gpio_get_direction, \ |
611dac1e NA |
678 | .direction_input = oxnas_gpio_direction_input, \ |
679 | .direction_output = oxnas_gpio_direction_output, \ | |
680 | .get = oxnas_gpio_get, \ | |
681 | .set = oxnas_gpio_set, \ | |
682 | .ngpio = PINS_PER_BANK, \ | |
683 | .base = GPIO_BANK_START(_bank), \ | |
684 | .owner = THIS_MODULE, \ | |
685 | .can_sleep = 0, \ | |
686 | }, \ | |
687 | .irq_chip = { \ | |
688 | .name = "GPIO" #_bank, \ | |
689 | .irq_startup = oxnas_gpio_irq_startup, \ | |
690 | .irq_ack = oxnas_gpio_irq_ack, \ | |
691 | .irq_mask = oxnas_gpio_irq_mask, \ | |
692 | .irq_unmask = oxnas_gpio_irq_unmask, \ | |
693 | .irq_set_type = oxnas_gpio_irq_set_type, \ | |
694 | }, \ | |
695 | } | |
696 | ||
697 | static struct oxnas_gpio_bank oxnas_gpio_banks[] = { | |
698 | GPIO_BANK(0), | |
699 | GPIO_BANK(1), | |
700 | }; | |
701 | ||
702 | static int oxnas_pinctrl_probe(struct platform_device *pdev) | |
703 | { | |
704 | struct oxnas_pinctrl *pctl; | |
705 | ||
706 | pctl = devm_kzalloc(&pdev->dev, sizeof(*pctl), GFP_KERNEL); | |
707 | if (!pctl) | |
708 | return -ENOMEM; | |
709 | pctl->dev = &pdev->dev; | |
710 | dev_set_drvdata(&pdev->dev, pctl); | |
711 | ||
712 | pctl->regmap = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, | |
713 | "oxsemi,sys-ctrl"); | |
714 | if (IS_ERR(pctl->regmap)) { | |
715 | dev_err(&pdev->dev, "failed to get sys ctrl regmap\n"); | |
716 | return -ENODEV; | |
717 | } | |
718 | ||
719 | pctl->pins = oxnas_pins; | |
720 | pctl->npins = ARRAY_SIZE(oxnas_pins); | |
721 | pctl->functions = oxnas_functions; | |
722 | pctl->nfunctions = ARRAY_SIZE(oxnas_functions); | |
723 | pctl->groups = oxnas_groups; | |
724 | pctl->ngroups = ARRAY_SIZE(oxnas_groups); | |
725 | pctl->gpio_banks = oxnas_gpio_banks; | |
726 | pctl->nbanks = ARRAY_SIZE(oxnas_gpio_banks); | |
727 | ||
728 | oxnas_pinctrl_desc.pins = pctl->pins; | |
729 | oxnas_pinctrl_desc.npins = pctl->npins; | |
730 | ||
731 | pctl->pctldev = pinctrl_register(&oxnas_pinctrl_desc, | |
732 | &pdev->dev, pctl); | |
733 | if (IS_ERR(pctl->pctldev)) { | |
734 | dev_err(&pdev->dev, "Failed to register pinctrl device\n"); | |
735 | return PTR_ERR(pctl->pctldev); | |
736 | } | |
737 | ||
738 | return 0; | |
739 | } | |
740 | ||
741 | static int oxnas_gpio_probe(struct platform_device *pdev) | |
742 | { | |
743 | struct device_node *np = pdev->dev.of_node; | |
744 | struct of_phandle_args pinspec; | |
745 | struct oxnas_gpio_bank *bank; | |
746 | unsigned int id, ngpios; | |
747 | int irq, ret; | |
748 | struct resource *res; | |
749 | ||
750 | if (of_parse_phandle_with_fixed_args(np, "gpio-ranges", | |
751 | 3, 0, &pinspec)) { | |
752 | dev_err(&pdev->dev, "gpio-ranges property not found\n"); | |
753 | return -EINVAL; | |
754 | } | |
755 | ||
756 | id = pinspec.args[1] / PINS_PER_BANK; | |
757 | ngpios = pinspec.args[2]; | |
758 | ||
759 | if (id >= ARRAY_SIZE(oxnas_gpio_banks)) { | |
760 | dev_err(&pdev->dev, "invalid gpio-ranges base arg\n"); | |
761 | return -EINVAL; | |
762 | } | |
763 | ||
764 | if (ngpios > PINS_PER_BANK) { | |
765 | dev_err(&pdev->dev, "invalid gpio-ranges count arg\n"); | |
766 | return -EINVAL; | |
767 | } | |
768 | ||
769 | bank = &oxnas_gpio_banks[id]; | |
770 | ||
771 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | |
772 | bank->reg_base = devm_ioremap_resource(&pdev->dev, res); | |
773 | if (IS_ERR(bank->reg_base)) | |
774 | return PTR_ERR(bank->reg_base); | |
775 | ||
776 | irq = platform_get_irq(pdev, 0); | |
777 | if (irq < 0) { | |
778 | dev_err(&pdev->dev, "irq get failed\n"); | |
779 | return irq; | |
780 | } | |
781 | ||
782 | bank->id = id; | |
783 | bank->gpio_chip.parent = &pdev->dev; | |
784 | bank->gpio_chip.of_node = np; | |
785 | bank->gpio_chip.ngpio = ngpios; | |
786 | ret = gpiochip_add_data(&bank->gpio_chip, bank); | |
787 | if (ret < 0) { | |
788 | dev_err(&pdev->dev, "Failed to add GPIO chip %u: %d\n", | |
789 | id, ret); | |
790 | return ret; | |
791 | } | |
792 | ||
793 | ret = gpiochip_irqchip_add(&bank->gpio_chip, &bank->irq_chip, | |
794 | 0, handle_level_irq, IRQ_TYPE_NONE); | |
795 | if (ret < 0) { | |
796 | dev_err(&pdev->dev, "Failed to add IRQ chip %u: %d\n", | |
797 | id, ret); | |
798 | gpiochip_remove(&bank->gpio_chip); | |
799 | return ret; | |
800 | } | |
801 | ||
802 | gpiochip_set_chained_irqchip(&bank->gpio_chip, &bank->irq_chip, | |
803 | irq, oxnas_gpio_irq_handler); | |
804 | ||
805 | return 0; | |
806 | } | |
807 | ||
808 | static const struct of_device_id oxnas_pinctrl_of_match[] = { | |
809 | { .compatible = "oxsemi,ox810se-pinctrl", }, | |
810 | { }, | |
811 | }; | |
812 | ||
813 | static struct platform_driver oxnas_pinctrl_driver = { | |
814 | .driver = { | |
815 | .name = "oxnas-pinctrl", | |
816 | .of_match_table = oxnas_pinctrl_of_match, | |
817 | .suppress_bind_attrs = true, | |
818 | }, | |
819 | .probe = oxnas_pinctrl_probe, | |
820 | }; | |
821 | ||
822 | static const struct of_device_id oxnas_gpio_of_match[] = { | |
823 | { .compatible = "oxsemi,ox810se-gpio", }, | |
824 | { }, | |
825 | }; | |
826 | ||
827 | static struct platform_driver oxnas_gpio_driver = { | |
828 | .driver = { | |
829 | .name = "oxnas-gpio", | |
830 | .of_match_table = oxnas_gpio_of_match, | |
831 | .suppress_bind_attrs = true, | |
832 | }, | |
833 | .probe = oxnas_gpio_probe, | |
834 | }; | |
835 | ||
836 | static int __init oxnas_gpio_register(void) | |
837 | { | |
838 | return platform_driver_register(&oxnas_gpio_driver); | |
839 | } | |
840 | arch_initcall(oxnas_gpio_register); | |
841 | ||
842 | static int __init oxnas_pinctrl_register(void) | |
843 | { | |
844 | return platform_driver_register(&oxnas_pinctrl_driver); | |
845 | } | |
846 | arch_initcall(oxnas_pinctrl_register); |