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