1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * Spreadtrum pin controller driver |
4 | * Copyright (C) 2017 Spreadtrum - http://www.spreadtrum.com |
5 | */ |
6 | |
7 | #include <linux/debugfs.h> |
8 | #include <linux/err.h> |
9 | #include <linux/init.h> |
10 | #include <linux/io.h> |
11 | #include <linux/kernel.h> |
12 | #include <linux/module.h> |
13 | #include <linux/of.h> |
14 | #include <linux/platform_device.h> |
15 | #include <linux/seq_file.h> |
16 | #include <linux/slab.h> |
17 | |
18 | #include <linux/pinctrl/consumer.h> |
19 | #include <linux/pinctrl/machine.h> |
20 | #include <linux/pinctrl/pinconf-generic.h> |
21 | #include <linux/pinctrl/pinconf.h> |
22 | #include <linux/pinctrl/pinctrl.h> |
23 | #include <linux/pinctrl/pinmux.h> |
24 | |
25 | #include "../core.h" |
26 | #include "../pinmux.h" |
27 | #include "../pinconf.h" |
28 | #include "../pinctrl-utils.h" |
29 | #include "pinctrl-sprd.h" |
30 | |
31 | #define PINCTRL_BIT_MASK(width) (~(~0UL << (width))) |
32 | #define PINCTRL_REG_OFFSET 0x20 |
33 | #define PINCTRL_REG_MISC_OFFSET 0x4020 |
34 | #define PINCTRL_REG_LEN 0x4 |
35 | |
36 | #define PIN_FUNC_MASK (BIT(4) | BIT(5)) |
37 | #define PIN_FUNC_SEL_1 ~PIN_FUNC_MASK |
38 | #define PIN_FUNC_SEL_2 BIT(4) |
39 | #define PIN_FUNC_SEL_3 BIT(5) |
40 | #define PIN_FUNC_SEL_4 PIN_FUNC_MASK |
41 | |
42 | #define AP_SLEEP_MODE BIT(13) |
43 | #define PUBCP_SLEEP_MODE BIT(14) |
44 | #define TGLDSP_SLEEP_MODE BIT(15) |
45 | #define AGDSP_SLEEP_MODE BIT(16) |
46 | #define CM4_SLEEP_MODE BIT(17) |
47 | #define SLEEP_MODE_MASK GENMASK(5, 0) |
48 | #define SLEEP_MODE_SHIFT 13 |
49 | |
50 | #define SLEEP_INPUT BIT(1) |
51 | #define SLEEP_INPUT_MASK 0x1 |
52 | #define SLEEP_INPUT_SHIFT 1 |
53 | |
54 | #define SLEEP_OUTPUT BIT(0) |
55 | #define SLEEP_OUTPUT_MASK 0x1 |
56 | #define SLEEP_OUTPUT_SHIFT 0 |
57 | |
58 | #define DRIVE_STRENGTH_MASK GENMASK(3, 0) |
59 | #define DRIVE_STRENGTH_SHIFT 19 |
60 | |
61 | #define SLEEP_PULL_DOWN BIT(2) |
62 | #define SLEEP_PULL_DOWN_MASK 0x1 |
63 | #define SLEEP_PULL_DOWN_SHIFT 2 |
64 | |
65 | #define PULL_DOWN BIT(6) |
66 | #define PULL_DOWN_MASK 0x1 |
67 | #define PULL_DOWN_SHIFT 6 |
68 | |
69 | #define SLEEP_PULL_UP BIT(3) |
70 | #define SLEEP_PULL_UP_MASK 0x1 |
71 | #define SLEEP_PULL_UP_SHIFT 3 |
72 | |
73 | #define PULL_UP_4_7K (BIT(12) | BIT(7)) |
74 | #define PULL_UP_20K BIT(7) |
75 | #define PULL_UP_MASK 0x21 |
76 | #define PULL_UP_SHIFT 7 |
77 | |
78 | #define INPUT_SCHMITT BIT(11) |
79 | #define INPUT_SCHMITT_MASK 0x1 |
80 | #define INPUT_SCHMITT_SHIFT 11 |
81 | |
82 | enum pin_sleep_mode { |
83 | AP_SLEEP = BIT(0), |
84 | PUBCP_SLEEP = BIT(1), |
85 | TGLDSP_SLEEP = BIT(2), |
86 | AGDSP_SLEEP = BIT(3), |
87 | CM4_SLEEP = BIT(4), |
88 | }; |
89 | |
90 | enum pin_func_sel { |
91 | PIN_FUNC_1, |
92 | PIN_FUNC_2, |
93 | PIN_FUNC_3, |
94 | PIN_FUNC_4, |
95 | PIN_FUNC_MAX, |
96 | }; |
97 | |
98 | /** |
99 | * struct sprd_pin: represent one pin's description |
100 | * @name: pin name |
101 | * @number: pin number |
102 | * @type: pin type, can be GLOBAL_CTRL_PIN/COMMON_PIN/MISC_PIN |
103 | * @reg: pin register address |
104 | * @bit_offset: bit offset in pin register |
105 | * @bit_width: bit width in pin register |
106 | */ |
107 | struct sprd_pin { |
108 | const char *name; |
109 | unsigned int number; |
110 | enum pin_type type; |
111 | unsigned long reg; |
112 | unsigned long bit_offset; |
113 | unsigned long bit_width; |
114 | }; |
115 | |
116 | /** |
117 | * struct sprd_pin_group: represent one group's description |
118 | * @name: group name |
119 | * @npins: pin numbers of this group |
120 | * @pins: pointer to pins array |
121 | */ |
122 | struct sprd_pin_group { |
123 | const char *name; |
124 | unsigned int npins; |
125 | unsigned int *pins; |
126 | }; |
127 | |
128 | /** |
129 | * struct sprd_pinctrl_soc_info: represent the SoC's pins description |
130 | * @groups: pointer to groups of pins |
131 | * @ngroups: group numbers of the whole SoC |
132 | * @pins: pointer to pins description |
133 | * @npins: pin numbers of the whole SoC |
134 | * @grp_names: pointer to group names array |
135 | */ |
136 | struct sprd_pinctrl_soc_info { |
137 | struct sprd_pin_group *groups; |
138 | unsigned int ngroups; |
139 | struct sprd_pin *pins; |
140 | unsigned int npins; |
141 | const char **grp_names; |
142 | }; |
143 | |
144 | /** |
145 | * struct sprd_pinctrl: represent the pin controller device |
146 | * @dev: pointer to the device structure |
147 | * @pctl: pointer to the pinctrl handle |
148 | * @base: base address of the controller |
149 | * @info: pointer to SoC's pins description information |
150 | */ |
151 | struct sprd_pinctrl { |
152 | struct device *dev; |
153 | struct pinctrl_dev *pctl; |
154 | void __iomem *base; |
155 | struct sprd_pinctrl_soc_info *info; |
156 | }; |
157 | |
158 | #define SPRD_PIN_CONFIG_CONTROL (PIN_CONFIG_END + 1) |
159 | #define SPRD_PIN_CONFIG_SLEEP_MODE (PIN_CONFIG_END + 2) |
160 | |
161 | static int sprd_pinctrl_get_id_by_name(struct sprd_pinctrl *sprd_pctl, |
162 | const char *name) |
163 | { |
164 | struct sprd_pinctrl_soc_info *info = sprd_pctl->info; |
165 | int i; |
166 | |
167 | for (i = 0; i < info->npins; i++) { |
168 | if (!strcmp(info->pins[i].name, name)) |
169 | return info->pins[i].number; |
170 | } |
171 | |
172 | return -ENODEV; |
173 | } |
174 | |
175 | static struct sprd_pin * |
176 | sprd_pinctrl_get_pin_by_id(struct sprd_pinctrl *sprd_pctl, unsigned int id) |
177 | { |
178 | struct sprd_pinctrl_soc_info *info = sprd_pctl->info; |
179 | struct sprd_pin *pin = NULL; |
180 | int i; |
181 | |
182 | for (i = 0; i < info->npins; i++) { |
183 | if (info->pins[i].number == id) { |
184 | pin = &info->pins[i]; |
185 | break; |
186 | } |
187 | } |
188 | |
189 | return pin; |
190 | } |
191 | |
192 | static const struct sprd_pin_group * |
193 | sprd_pinctrl_find_group_by_name(struct sprd_pinctrl *sprd_pctl, |
194 | const char *name) |
195 | { |
196 | struct sprd_pinctrl_soc_info *info = sprd_pctl->info; |
197 | const struct sprd_pin_group *grp = NULL; |
198 | int i; |
199 | |
200 | for (i = 0; i < info->ngroups; i++) { |
201 | if (!strcmp(info->groups[i].name, name)) { |
202 | grp = &info->groups[i]; |
203 | break; |
204 | } |
205 | } |
206 | |
207 | return grp; |
208 | } |
209 | |
210 | static int sprd_pctrl_group_count(struct pinctrl_dev *pctldev) |
211 | { |
212 | struct sprd_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); |
213 | struct sprd_pinctrl_soc_info *info = pctl->info; |
214 | |
215 | return info->ngroups; |
216 | } |
217 | |
218 | static const char *sprd_pctrl_group_name(struct pinctrl_dev *pctldev, |
219 | unsigned int selector) |
220 | { |
221 | struct sprd_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); |
222 | struct sprd_pinctrl_soc_info *info = pctl->info; |
223 | |
224 | return info->groups[selector].name; |
225 | } |
226 | |
227 | static int sprd_pctrl_group_pins(struct pinctrl_dev *pctldev, |
228 | unsigned int selector, |
229 | const unsigned int **pins, |
230 | unsigned int *npins) |
231 | { |
232 | struct sprd_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); |
233 | struct sprd_pinctrl_soc_info *info = pctl->info; |
234 | |
235 | if (selector >= info->ngroups) |
236 | return -EINVAL; |
237 | |
238 | *pins = info->groups[selector].pins; |
239 | *npins = info->groups[selector].npins; |
240 | |
241 | return 0; |
242 | } |
243 | |
244 | static int sprd_dt_node_to_map(struct pinctrl_dev *pctldev, |
245 | struct device_node *np, |
246 | struct pinctrl_map **map, |
247 | unsigned int *num_maps) |
248 | { |
249 | struct sprd_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); |
250 | const struct sprd_pin_group *grp; |
251 | unsigned long *configs = NULL; |
252 | unsigned int num_configs = 0; |
253 | unsigned int reserved_maps = 0; |
254 | unsigned int reserve = 0; |
255 | const char *function; |
256 | enum pinctrl_map_type type; |
257 | int ret; |
258 | |
259 | grp = sprd_pinctrl_find_group_by_name(sprd_pctl: pctl, name: np->name); |
260 | if (!grp) { |
261 | dev_err(pctl->dev, "unable to find group for node %s\n" , |
262 | of_node_full_name(np)); |
263 | return -EINVAL; |
264 | } |
265 | |
266 | ret = of_property_count_strings(np, propname: "pins" ); |
267 | if (ret < 0) |
268 | return ret; |
269 | |
270 | if (ret == 1) |
271 | type = PIN_MAP_TYPE_CONFIGS_PIN; |
272 | else |
273 | type = PIN_MAP_TYPE_CONFIGS_GROUP; |
274 | |
275 | ret = of_property_read_string(np, propname: "function" , out_string: &function); |
276 | if (ret < 0) { |
277 | if (ret != -EINVAL) |
278 | dev_err(pctl->dev, |
279 | "%s: could not parse property function\n" , |
280 | of_node_full_name(np)); |
281 | function = NULL; |
282 | } |
283 | |
284 | ret = pinconf_generic_parse_dt_config(np, pctldev, configs: &configs, |
285 | nconfigs: &num_configs); |
286 | if (ret < 0) { |
287 | dev_err(pctl->dev, "%s: could not parse node property\n" , |
288 | of_node_full_name(np)); |
289 | return ret; |
290 | } |
291 | |
292 | *map = NULL; |
293 | *num_maps = 0; |
294 | |
295 | if (function != NULL) |
296 | reserve++; |
297 | if (num_configs) |
298 | reserve++; |
299 | |
300 | ret = pinctrl_utils_reserve_map(pctldev, map, reserved_maps: &reserved_maps, |
301 | num_maps, reserve); |
302 | if (ret < 0) |
303 | goto out; |
304 | |
305 | if (function) { |
306 | ret = pinctrl_utils_add_map_mux(pctldev, map, |
307 | reserved_maps: &reserved_maps, num_maps, |
308 | group: grp->name, function); |
309 | if (ret < 0) |
310 | goto out; |
311 | } |
312 | |
313 | if (num_configs) { |
314 | const char *group_or_pin; |
315 | unsigned int pin_id; |
316 | |
317 | if (type == PIN_MAP_TYPE_CONFIGS_PIN) { |
318 | pin_id = grp->pins[0]; |
319 | group_or_pin = pin_get_name(pctldev, pin: pin_id); |
320 | } else { |
321 | group_or_pin = grp->name; |
322 | } |
323 | |
324 | ret = pinctrl_utils_add_map_configs(pctldev, map, |
325 | reserved_maps: &reserved_maps, num_maps, |
326 | group: group_or_pin, configs, |
327 | num_configs, type); |
328 | } |
329 | |
330 | out: |
331 | kfree(objp: configs); |
332 | return ret; |
333 | } |
334 | |
335 | static void sprd_pctrl_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s, |
336 | unsigned int offset) |
337 | { |
338 | seq_printf(m: s, fmt: "%s" , dev_name(dev: pctldev->dev)); |
339 | } |
340 | |
341 | static const struct pinctrl_ops sprd_pctrl_ops = { |
342 | .get_groups_count = sprd_pctrl_group_count, |
343 | .get_group_name = sprd_pctrl_group_name, |
344 | .get_group_pins = sprd_pctrl_group_pins, |
345 | .pin_dbg_show = sprd_pctrl_dbg_show, |
346 | .dt_node_to_map = sprd_dt_node_to_map, |
347 | .dt_free_map = pinctrl_utils_free_map, |
348 | }; |
349 | |
350 | static int sprd_pmx_get_function_count(struct pinctrl_dev *pctldev) |
351 | { |
352 | return PIN_FUNC_MAX; |
353 | } |
354 | |
355 | static const char *sprd_pmx_get_function_name(struct pinctrl_dev *pctldev, |
356 | unsigned int selector) |
357 | { |
358 | switch (selector) { |
359 | case PIN_FUNC_1: |
360 | return "func1" ; |
361 | case PIN_FUNC_2: |
362 | return "func2" ; |
363 | case PIN_FUNC_3: |
364 | return "func3" ; |
365 | case PIN_FUNC_4: |
366 | return "func4" ; |
367 | default: |
368 | return "null" ; |
369 | } |
370 | } |
371 | |
372 | static int sprd_pmx_get_function_groups(struct pinctrl_dev *pctldev, |
373 | unsigned int selector, |
374 | const char * const **groups, |
375 | unsigned int * const num_groups) |
376 | { |
377 | struct sprd_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); |
378 | struct sprd_pinctrl_soc_info *info = pctl->info; |
379 | |
380 | *groups = info->grp_names; |
381 | *num_groups = info->ngroups; |
382 | |
383 | return 0; |
384 | } |
385 | |
386 | static int sprd_pmx_set_mux(struct pinctrl_dev *pctldev, |
387 | unsigned int func_selector, |
388 | unsigned int group_selector) |
389 | { |
390 | struct sprd_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); |
391 | struct sprd_pinctrl_soc_info *info = pctl->info; |
392 | struct sprd_pin_group *grp = &info->groups[group_selector]; |
393 | unsigned int i, grp_pins = grp->npins; |
394 | unsigned long reg; |
395 | unsigned int val = 0; |
396 | |
397 | if (group_selector >= info->ngroups) |
398 | return -EINVAL; |
399 | |
400 | switch (func_selector) { |
401 | case PIN_FUNC_1: |
402 | val &= PIN_FUNC_SEL_1; |
403 | break; |
404 | case PIN_FUNC_2: |
405 | val |= PIN_FUNC_SEL_2; |
406 | break; |
407 | case PIN_FUNC_3: |
408 | val |= PIN_FUNC_SEL_3; |
409 | break; |
410 | case PIN_FUNC_4: |
411 | val |= PIN_FUNC_SEL_4; |
412 | break; |
413 | default: |
414 | break; |
415 | } |
416 | |
417 | for (i = 0; i < grp_pins; i++) { |
418 | unsigned int pin_id = grp->pins[i]; |
419 | struct sprd_pin *pin = sprd_pinctrl_get_pin_by_id(sprd_pctl: pctl, id: pin_id); |
420 | |
421 | if (!pin || pin->type != COMMON_PIN) |
422 | continue; |
423 | |
424 | reg = readl(addr: (void __iomem *)pin->reg); |
425 | reg &= ~PIN_FUNC_MASK; |
426 | reg |= val; |
427 | writel(val: reg, addr: (void __iomem *)pin->reg); |
428 | } |
429 | |
430 | return 0; |
431 | } |
432 | |
433 | static const struct pinmux_ops sprd_pmx_ops = { |
434 | .get_functions_count = sprd_pmx_get_function_count, |
435 | .get_function_name = sprd_pmx_get_function_name, |
436 | .get_function_groups = sprd_pmx_get_function_groups, |
437 | .set_mux = sprd_pmx_set_mux, |
438 | }; |
439 | |
440 | static int sprd_pinconf_get(struct pinctrl_dev *pctldev, unsigned int pin_id, |
441 | unsigned long *config) |
442 | { |
443 | struct sprd_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); |
444 | struct sprd_pin *pin = sprd_pinctrl_get_pin_by_id(sprd_pctl: pctl, id: pin_id); |
445 | unsigned int param = pinconf_to_config_param(config: *config); |
446 | unsigned int reg, arg; |
447 | |
448 | if (!pin) |
449 | return -EINVAL; |
450 | |
451 | if (pin->type == GLOBAL_CTRL_PIN) { |
452 | reg = (readl(addr: (void __iomem *)pin->reg) >> |
453 | pin->bit_offset) & PINCTRL_BIT_MASK(pin->bit_width); |
454 | } else { |
455 | reg = readl(addr: (void __iomem *)pin->reg); |
456 | } |
457 | |
458 | if (pin->type == GLOBAL_CTRL_PIN && |
459 | param == SPRD_PIN_CONFIG_CONTROL) { |
460 | arg = reg; |
461 | } else if (pin->type == COMMON_PIN || pin->type == MISC_PIN) { |
462 | switch (param) { |
463 | case SPRD_PIN_CONFIG_SLEEP_MODE: |
464 | arg = (reg >> SLEEP_MODE_SHIFT) & SLEEP_MODE_MASK; |
465 | break; |
466 | case PIN_CONFIG_INPUT_ENABLE: |
467 | arg = (reg >> SLEEP_INPUT_SHIFT) & SLEEP_INPUT_MASK; |
468 | break; |
469 | case PIN_CONFIG_OUTPUT_ENABLE: |
470 | arg = reg & SLEEP_OUTPUT_MASK; |
471 | break; |
472 | case PIN_CONFIG_BIAS_HIGH_IMPEDANCE: |
473 | if ((reg & SLEEP_OUTPUT) || (reg & SLEEP_INPUT)) |
474 | return -EINVAL; |
475 | |
476 | arg = 1; |
477 | break; |
478 | case PIN_CONFIG_DRIVE_STRENGTH: |
479 | arg = (reg >> DRIVE_STRENGTH_SHIFT) & |
480 | DRIVE_STRENGTH_MASK; |
481 | break; |
482 | case PIN_CONFIG_BIAS_PULL_DOWN: |
483 | /* combine sleep pull down and pull down config */ |
484 | arg = ((reg >> SLEEP_PULL_DOWN_SHIFT) & |
485 | SLEEP_PULL_DOWN_MASK) << 16; |
486 | arg |= (reg >> PULL_DOWN_SHIFT) & PULL_DOWN_MASK; |
487 | break; |
488 | case PIN_CONFIG_INPUT_SCHMITT_ENABLE: |
489 | arg = (reg >> INPUT_SCHMITT_SHIFT) & INPUT_SCHMITT_MASK; |
490 | break; |
491 | case PIN_CONFIG_BIAS_PULL_UP: |
492 | /* combine sleep pull up and pull up config */ |
493 | arg = ((reg >> SLEEP_PULL_UP_SHIFT) & |
494 | SLEEP_PULL_UP_MASK) << 16; |
495 | arg |= (reg >> PULL_UP_SHIFT) & PULL_UP_MASK; |
496 | break; |
497 | case PIN_CONFIG_BIAS_DISABLE: |
498 | if ((reg & (SLEEP_PULL_DOWN | SLEEP_PULL_UP)) || |
499 | (reg & (PULL_DOWN | PULL_UP_4_7K | PULL_UP_20K))) |
500 | return -EINVAL; |
501 | |
502 | arg = 1; |
503 | break; |
504 | case PIN_CONFIG_SLEEP_HARDWARE_STATE: |
505 | arg = 0; |
506 | break; |
507 | default: |
508 | return -ENOTSUPP; |
509 | } |
510 | } else { |
511 | return -ENOTSUPP; |
512 | } |
513 | |
514 | *config = pinconf_to_config_packed(param, argument: arg); |
515 | return 0; |
516 | } |
517 | |
518 | static unsigned int sprd_pinconf_drive(unsigned int mA) |
519 | { |
520 | unsigned int val = 0; |
521 | |
522 | switch (mA) { |
523 | case 2: |
524 | break; |
525 | case 4: |
526 | val |= BIT(19); |
527 | break; |
528 | case 6: |
529 | val |= BIT(20); |
530 | break; |
531 | case 8: |
532 | val |= BIT(19) | BIT(20); |
533 | break; |
534 | case 10: |
535 | val |= BIT(21); |
536 | break; |
537 | case 12: |
538 | val |= BIT(21) | BIT(19); |
539 | break; |
540 | case 14: |
541 | val |= BIT(21) | BIT(20); |
542 | break; |
543 | case 16: |
544 | val |= BIT(19) | BIT(20) | BIT(21); |
545 | break; |
546 | case 20: |
547 | val |= BIT(22); |
548 | break; |
549 | case 21: |
550 | val |= BIT(22) | BIT(19); |
551 | break; |
552 | case 24: |
553 | val |= BIT(22) | BIT(20); |
554 | break; |
555 | case 25: |
556 | val |= BIT(22) | BIT(20) | BIT(19); |
557 | break; |
558 | case 27: |
559 | val |= BIT(22) | BIT(21); |
560 | break; |
561 | case 29: |
562 | val |= BIT(22) | BIT(21) | BIT(19); |
563 | break; |
564 | case 31: |
565 | val |= BIT(22) | BIT(21) | BIT(20); |
566 | break; |
567 | case 33: |
568 | val |= BIT(22) | BIT(21) | BIT(20) | BIT(19); |
569 | break; |
570 | default: |
571 | break; |
572 | } |
573 | |
574 | return val; |
575 | } |
576 | |
577 | static bool sprd_pinctrl_check_sleep_config(unsigned long *configs, |
578 | unsigned int num_configs) |
579 | { |
580 | unsigned int param; |
581 | int i; |
582 | |
583 | for (i = 0; i < num_configs; i++) { |
584 | param = pinconf_to_config_param(config: configs[i]); |
585 | if (param == PIN_CONFIG_SLEEP_HARDWARE_STATE) |
586 | return true; |
587 | } |
588 | |
589 | return false; |
590 | } |
591 | |
592 | static int sprd_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin_id, |
593 | unsigned long *configs, unsigned int num_configs) |
594 | { |
595 | struct sprd_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); |
596 | struct sprd_pin *pin = sprd_pinctrl_get_pin_by_id(sprd_pctl: pctl, id: pin_id); |
597 | bool is_sleep_config; |
598 | unsigned long reg; |
599 | int i; |
600 | |
601 | if (!pin) |
602 | return -EINVAL; |
603 | |
604 | is_sleep_config = sprd_pinctrl_check_sleep_config(configs, num_configs); |
605 | |
606 | for (i = 0; i < num_configs; i++) { |
607 | unsigned int param, arg, shift, mask, val; |
608 | |
609 | param = pinconf_to_config_param(config: configs[i]); |
610 | arg = pinconf_to_config_argument(config: configs[i]); |
611 | |
612 | val = 0; |
613 | shift = 0; |
614 | mask = 0; |
615 | if (pin->type == GLOBAL_CTRL_PIN && |
616 | param == SPRD_PIN_CONFIG_CONTROL) { |
617 | val = arg; |
618 | } else if (pin->type == COMMON_PIN || pin->type == MISC_PIN) { |
619 | switch (param) { |
620 | case SPRD_PIN_CONFIG_SLEEP_MODE: |
621 | if (arg & AP_SLEEP) |
622 | val |= AP_SLEEP_MODE; |
623 | if (arg & PUBCP_SLEEP) |
624 | val |= PUBCP_SLEEP_MODE; |
625 | if (arg & TGLDSP_SLEEP) |
626 | val |= TGLDSP_SLEEP_MODE; |
627 | if (arg & AGDSP_SLEEP) |
628 | val |= AGDSP_SLEEP_MODE; |
629 | if (arg & CM4_SLEEP) |
630 | val |= CM4_SLEEP_MODE; |
631 | |
632 | mask = SLEEP_MODE_MASK; |
633 | shift = SLEEP_MODE_SHIFT; |
634 | break; |
635 | case PIN_CONFIG_INPUT_ENABLE: |
636 | if (is_sleep_config == true) { |
637 | if (arg > 0) |
638 | val |= SLEEP_INPUT; |
639 | else |
640 | val &= ~SLEEP_INPUT; |
641 | |
642 | mask = SLEEP_INPUT_MASK; |
643 | shift = SLEEP_INPUT_SHIFT; |
644 | } |
645 | break; |
646 | case PIN_CONFIG_OUTPUT_ENABLE: |
647 | if (is_sleep_config == true) { |
648 | if (arg > 0) |
649 | val |= SLEEP_OUTPUT; |
650 | else |
651 | val &= ~SLEEP_OUTPUT; |
652 | |
653 | mask = SLEEP_OUTPUT_MASK; |
654 | shift = SLEEP_OUTPUT_SHIFT; |
655 | } |
656 | break; |
657 | case PIN_CONFIG_BIAS_HIGH_IMPEDANCE: |
658 | if (is_sleep_config == true) { |
659 | val = shift = 0; |
660 | mask = SLEEP_OUTPUT | SLEEP_INPUT; |
661 | } |
662 | break; |
663 | case PIN_CONFIG_DRIVE_STRENGTH: |
664 | if (arg < 2 || arg > 60) |
665 | return -EINVAL; |
666 | |
667 | val = sprd_pinconf_drive(mA: arg); |
668 | mask = DRIVE_STRENGTH_MASK; |
669 | shift = DRIVE_STRENGTH_SHIFT; |
670 | break; |
671 | case PIN_CONFIG_BIAS_PULL_DOWN: |
672 | if (is_sleep_config == true) { |
673 | val |= SLEEP_PULL_DOWN; |
674 | mask = SLEEP_PULL_DOWN_MASK; |
675 | shift = SLEEP_PULL_DOWN_SHIFT; |
676 | } else { |
677 | val |= PULL_DOWN; |
678 | mask = PULL_DOWN_MASK; |
679 | shift = PULL_DOWN_SHIFT; |
680 | } |
681 | break; |
682 | case PIN_CONFIG_INPUT_SCHMITT_ENABLE: |
683 | if (arg > 0) |
684 | val |= INPUT_SCHMITT; |
685 | else |
686 | val &= ~INPUT_SCHMITT; |
687 | |
688 | mask = INPUT_SCHMITT_MASK; |
689 | shift = INPUT_SCHMITT_SHIFT; |
690 | break; |
691 | case PIN_CONFIG_BIAS_PULL_UP: |
692 | if (is_sleep_config) { |
693 | val |= SLEEP_PULL_UP; |
694 | mask = SLEEP_PULL_UP_MASK; |
695 | shift = SLEEP_PULL_UP_SHIFT; |
696 | } else { |
697 | if (arg == 20000) |
698 | val |= PULL_UP_20K; |
699 | else if (arg == 4700) |
700 | val |= PULL_UP_4_7K; |
701 | |
702 | mask = PULL_UP_MASK; |
703 | shift = PULL_UP_SHIFT; |
704 | } |
705 | break; |
706 | case PIN_CONFIG_BIAS_DISABLE: |
707 | if (is_sleep_config == true) { |
708 | val = shift = 0; |
709 | mask = SLEEP_PULL_DOWN | SLEEP_PULL_UP; |
710 | } else { |
711 | val = shift = 0; |
712 | mask = PULL_DOWN | PULL_UP_20K | |
713 | PULL_UP_4_7K; |
714 | } |
715 | break; |
716 | case PIN_CONFIG_SLEEP_HARDWARE_STATE: |
717 | continue; |
718 | default: |
719 | return -ENOTSUPP; |
720 | } |
721 | } else { |
722 | return -ENOTSUPP; |
723 | } |
724 | |
725 | if (pin->type == GLOBAL_CTRL_PIN) { |
726 | reg = readl(addr: (void __iomem *)pin->reg); |
727 | reg &= ~(PINCTRL_BIT_MASK(pin->bit_width) |
728 | << pin->bit_offset); |
729 | reg |= (val & PINCTRL_BIT_MASK(pin->bit_width)) |
730 | << pin->bit_offset; |
731 | writel(val: reg, addr: (void __iomem *)pin->reg); |
732 | } else { |
733 | reg = readl(addr: (void __iomem *)pin->reg); |
734 | reg &= ~(mask << shift); |
735 | reg |= val; |
736 | writel(val: reg, addr: (void __iomem *)pin->reg); |
737 | } |
738 | } |
739 | |
740 | return 0; |
741 | } |
742 | |
743 | static int sprd_pinconf_group_get(struct pinctrl_dev *pctldev, |
744 | unsigned int selector, unsigned long *config) |
745 | { |
746 | struct sprd_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); |
747 | struct sprd_pinctrl_soc_info *info = pctl->info; |
748 | struct sprd_pin_group *grp; |
749 | unsigned int pin_id; |
750 | |
751 | if (selector >= info->ngroups) |
752 | return -EINVAL; |
753 | |
754 | grp = &info->groups[selector]; |
755 | pin_id = grp->pins[0]; |
756 | |
757 | return sprd_pinconf_get(pctldev, pin_id, config); |
758 | } |
759 | |
760 | static int sprd_pinconf_group_set(struct pinctrl_dev *pctldev, |
761 | unsigned int selector, |
762 | unsigned long *configs, |
763 | unsigned int num_configs) |
764 | { |
765 | struct sprd_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); |
766 | struct sprd_pinctrl_soc_info *info = pctl->info; |
767 | struct sprd_pin_group *grp; |
768 | int ret, i; |
769 | |
770 | if (selector >= info->ngroups) |
771 | return -EINVAL; |
772 | |
773 | grp = &info->groups[selector]; |
774 | |
775 | for (i = 0; i < grp->npins; i++) { |
776 | unsigned int pin_id = grp->pins[i]; |
777 | |
778 | ret = sprd_pinconf_set(pctldev, pin_id, configs, num_configs); |
779 | if (ret) |
780 | return ret; |
781 | } |
782 | |
783 | return 0; |
784 | } |
785 | |
786 | static int sprd_pinconf_get_config(struct pinctrl_dev *pctldev, |
787 | unsigned int pin_id, |
788 | unsigned long *config) |
789 | { |
790 | struct sprd_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); |
791 | struct sprd_pin *pin = sprd_pinctrl_get_pin_by_id(sprd_pctl: pctl, id: pin_id); |
792 | |
793 | if (!pin) |
794 | return -EINVAL; |
795 | |
796 | if (pin->type == GLOBAL_CTRL_PIN) { |
797 | *config = (readl(addr: (void __iomem *)pin->reg) >> |
798 | pin->bit_offset) & PINCTRL_BIT_MASK(pin->bit_width); |
799 | } else { |
800 | *config = readl(addr: (void __iomem *)pin->reg); |
801 | } |
802 | |
803 | return 0; |
804 | } |
805 | |
806 | static void sprd_pinconf_dbg_show(struct pinctrl_dev *pctldev, |
807 | struct seq_file *s, unsigned int pin_id) |
808 | { |
809 | unsigned long config; |
810 | int ret; |
811 | |
812 | ret = sprd_pinconf_get_config(pctldev, pin_id, config: &config); |
813 | if (ret) |
814 | return; |
815 | |
816 | seq_printf(m: s, fmt: "0x%lx" , config); |
817 | } |
818 | |
819 | static void sprd_pinconf_group_dbg_show(struct pinctrl_dev *pctldev, |
820 | struct seq_file *s, |
821 | unsigned int selector) |
822 | { |
823 | struct sprd_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); |
824 | struct sprd_pinctrl_soc_info *info = pctl->info; |
825 | struct sprd_pin_group *grp; |
826 | unsigned long config; |
827 | const char *name; |
828 | int i, ret; |
829 | |
830 | if (selector >= info->ngroups) |
831 | return; |
832 | |
833 | grp = &info->groups[selector]; |
834 | |
835 | seq_putc(m: s, c: '\n'); |
836 | for (i = 0; i < grp->npins; i++, config++) { |
837 | unsigned int pin_id = grp->pins[i]; |
838 | |
839 | name = pin_get_name(pctldev, pin: pin_id); |
840 | ret = sprd_pinconf_get_config(pctldev, pin_id, config: &config); |
841 | if (ret) |
842 | return; |
843 | |
844 | seq_printf(m: s, fmt: "%s: 0x%lx " , name, config); |
845 | } |
846 | } |
847 | |
848 | static const struct pinconf_ops sprd_pinconf_ops = { |
849 | .is_generic = true, |
850 | .pin_config_get = sprd_pinconf_get, |
851 | .pin_config_set = sprd_pinconf_set, |
852 | .pin_config_group_get = sprd_pinconf_group_get, |
853 | .pin_config_group_set = sprd_pinconf_group_set, |
854 | .pin_config_dbg_show = sprd_pinconf_dbg_show, |
855 | .pin_config_group_dbg_show = sprd_pinconf_group_dbg_show, |
856 | }; |
857 | |
858 | static const struct pinconf_generic_params sprd_dt_params[] = { |
859 | {"sprd,control" , SPRD_PIN_CONFIG_CONTROL, 0}, |
860 | {"sprd,sleep-mode" , SPRD_PIN_CONFIG_SLEEP_MODE, 0}, |
861 | }; |
862 | |
863 | #ifdef CONFIG_DEBUG_FS |
864 | static const struct pin_config_item sprd_conf_items[] = { |
865 | PCONFDUMP(SPRD_PIN_CONFIG_CONTROL, "global control" , NULL, true), |
866 | PCONFDUMP(SPRD_PIN_CONFIG_SLEEP_MODE, "sleep mode" , NULL, true), |
867 | }; |
868 | #endif |
869 | |
870 | static struct pinctrl_desc sprd_pinctrl_desc = { |
871 | .pctlops = &sprd_pctrl_ops, |
872 | .pmxops = &sprd_pmx_ops, |
873 | .confops = &sprd_pinconf_ops, |
874 | .num_custom_params = ARRAY_SIZE(sprd_dt_params), |
875 | .custom_params = sprd_dt_params, |
876 | #ifdef CONFIG_DEBUG_FS |
877 | .custom_conf_items = sprd_conf_items, |
878 | #endif |
879 | .owner = THIS_MODULE, |
880 | }; |
881 | |
882 | static int sprd_pinctrl_parse_groups(struct device_node *np, |
883 | struct sprd_pinctrl *sprd_pctl, |
884 | struct sprd_pin_group *grp) |
885 | { |
886 | struct property *prop; |
887 | const char *pin_name; |
888 | int ret, i = 0; |
889 | |
890 | ret = of_property_count_strings(np, propname: "pins" ); |
891 | if (ret < 0) |
892 | return ret; |
893 | |
894 | grp->name = np->name; |
895 | grp->npins = ret; |
896 | grp->pins = devm_kcalloc(dev: sprd_pctl->dev, |
897 | n: grp->npins, size: sizeof(unsigned int), |
898 | GFP_KERNEL); |
899 | if (!grp->pins) |
900 | return -ENOMEM; |
901 | |
902 | of_property_for_each_string(np, "pins" , prop, pin_name) { |
903 | ret = sprd_pinctrl_get_id_by_name(sprd_pctl, name: pin_name); |
904 | if (ret >= 0) |
905 | grp->pins[i++] = ret; |
906 | } |
907 | |
908 | for (i = 0; i < grp->npins; i++) { |
909 | dev_dbg(sprd_pctl->dev, |
910 | "Group[%s] contains [%d] pins: id = %d\n" , |
911 | grp->name, grp->npins, grp->pins[i]); |
912 | } |
913 | |
914 | return 0; |
915 | } |
916 | |
917 | static unsigned int sprd_pinctrl_get_groups(struct device_node *np) |
918 | { |
919 | struct device_node *child; |
920 | unsigned int group_cnt, cnt; |
921 | |
922 | group_cnt = of_get_child_count(np); |
923 | |
924 | for_each_child_of_node(np, child) { |
925 | cnt = of_get_child_count(np: child); |
926 | if (cnt > 0) |
927 | group_cnt += cnt; |
928 | } |
929 | |
930 | return group_cnt; |
931 | } |
932 | |
933 | static int sprd_pinctrl_parse_dt(struct sprd_pinctrl *sprd_pctl) |
934 | { |
935 | struct sprd_pinctrl_soc_info *info = sprd_pctl->info; |
936 | struct device_node *np = sprd_pctl->dev->of_node; |
937 | struct device_node *child, *sub_child; |
938 | struct sprd_pin_group *grp; |
939 | const char **temp; |
940 | int ret; |
941 | |
942 | if (!np) |
943 | return -ENODEV; |
944 | |
945 | info->ngroups = sprd_pinctrl_get_groups(np); |
946 | if (!info->ngroups) |
947 | return 0; |
948 | |
949 | info->groups = devm_kcalloc(dev: sprd_pctl->dev, |
950 | n: info->ngroups, |
951 | size: sizeof(struct sprd_pin_group), |
952 | GFP_KERNEL); |
953 | if (!info->groups) |
954 | return -ENOMEM; |
955 | |
956 | info->grp_names = devm_kcalloc(dev: sprd_pctl->dev, |
957 | n: info->ngroups, size: sizeof(char *), |
958 | GFP_KERNEL); |
959 | if (!info->grp_names) |
960 | return -ENOMEM; |
961 | |
962 | temp = info->grp_names; |
963 | grp = info->groups; |
964 | |
965 | for_each_child_of_node(np, child) { |
966 | ret = sprd_pinctrl_parse_groups(np: child, sprd_pctl, grp); |
967 | if (ret) { |
968 | of_node_put(node: child); |
969 | return ret; |
970 | } |
971 | |
972 | *temp++ = grp->name; |
973 | grp++; |
974 | |
975 | if (of_get_child_count(np: child) > 0) { |
976 | for_each_child_of_node(child, sub_child) { |
977 | ret = sprd_pinctrl_parse_groups(np: sub_child, |
978 | sprd_pctl, grp); |
979 | if (ret) { |
980 | of_node_put(node: sub_child); |
981 | of_node_put(node: child); |
982 | return ret; |
983 | } |
984 | |
985 | *temp++ = grp->name; |
986 | grp++; |
987 | } |
988 | } |
989 | } |
990 | |
991 | return 0; |
992 | } |
993 | |
994 | static int sprd_pinctrl_add_pins(struct sprd_pinctrl *sprd_pctl, |
995 | struct sprd_pins_info *sprd_soc_pin_info, |
996 | int pins_cnt) |
997 | { |
998 | struct sprd_pinctrl_soc_info *info = sprd_pctl->info; |
999 | unsigned int ctrl_pin = 0, com_pin = 0; |
1000 | struct sprd_pin *pin; |
1001 | int i; |
1002 | |
1003 | info->npins = pins_cnt; |
1004 | info->pins = devm_kcalloc(dev: sprd_pctl->dev, |
1005 | n: info->npins, size: sizeof(struct sprd_pin), |
1006 | GFP_KERNEL); |
1007 | if (!info->pins) |
1008 | return -ENOMEM; |
1009 | |
1010 | for (i = 0, pin = info->pins; i < info->npins; i++, pin++) { |
1011 | unsigned int reg; |
1012 | |
1013 | pin->name = sprd_soc_pin_info[i].name; |
1014 | pin->type = sprd_soc_pin_info[i].type; |
1015 | pin->number = sprd_soc_pin_info[i].num; |
1016 | reg = sprd_soc_pin_info[i].reg; |
1017 | if (pin->type == GLOBAL_CTRL_PIN) { |
1018 | pin->reg = (unsigned long)sprd_pctl->base + |
1019 | PINCTRL_REG_LEN * reg; |
1020 | pin->bit_offset = sprd_soc_pin_info[i].bit_offset; |
1021 | pin->bit_width = sprd_soc_pin_info[i].bit_width; |
1022 | ctrl_pin++; |
1023 | } else if (pin->type == COMMON_PIN) { |
1024 | pin->reg = (unsigned long)sprd_pctl->base + |
1025 | PINCTRL_REG_OFFSET + PINCTRL_REG_LEN * |
1026 | (i - ctrl_pin); |
1027 | com_pin++; |
1028 | } else if (pin->type == MISC_PIN) { |
1029 | pin->reg = (unsigned long)sprd_pctl->base + |
1030 | PINCTRL_REG_MISC_OFFSET + PINCTRL_REG_LEN * |
1031 | (i - ctrl_pin - com_pin); |
1032 | } |
1033 | } |
1034 | |
1035 | for (i = 0, pin = info->pins; i < info->npins; pin++, i++) { |
1036 | dev_dbg(sprd_pctl->dev, "pin name[%s-%d], type = %d, " |
1037 | "bit offset = %ld, bit width = %ld, reg = 0x%lx\n" , |
1038 | pin->name, pin->number, pin->type, |
1039 | pin->bit_offset, pin->bit_width, pin->reg); |
1040 | } |
1041 | |
1042 | return 0; |
1043 | } |
1044 | |
1045 | int sprd_pinctrl_core_probe(struct platform_device *pdev, |
1046 | struct sprd_pins_info *sprd_soc_pin_info, |
1047 | int pins_cnt) |
1048 | { |
1049 | struct sprd_pinctrl *sprd_pctl; |
1050 | struct sprd_pinctrl_soc_info *pinctrl_info; |
1051 | struct pinctrl_pin_desc *pin_desc; |
1052 | int ret, i; |
1053 | |
1054 | sprd_pctl = devm_kzalloc(dev: &pdev->dev, size: sizeof(struct sprd_pinctrl), |
1055 | GFP_KERNEL); |
1056 | if (!sprd_pctl) |
1057 | return -ENOMEM; |
1058 | |
1059 | sprd_pctl->base = devm_platform_ioremap_resource(pdev, index: 0); |
1060 | if (IS_ERR(ptr: sprd_pctl->base)) |
1061 | return PTR_ERR(ptr: sprd_pctl->base); |
1062 | |
1063 | pinctrl_info = devm_kzalloc(dev: &pdev->dev, |
1064 | size: sizeof(struct sprd_pinctrl_soc_info), |
1065 | GFP_KERNEL); |
1066 | if (!pinctrl_info) |
1067 | return -ENOMEM; |
1068 | |
1069 | sprd_pctl->info = pinctrl_info; |
1070 | sprd_pctl->dev = &pdev->dev; |
1071 | platform_set_drvdata(pdev, data: sprd_pctl); |
1072 | |
1073 | ret = sprd_pinctrl_add_pins(sprd_pctl, sprd_soc_pin_info, pins_cnt); |
1074 | if (ret) { |
1075 | dev_err(&pdev->dev, "fail to add pins information\n" ); |
1076 | return ret; |
1077 | } |
1078 | |
1079 | ret = sprd_pinctrl_parse_dt(sprd_pctl); |
1080 | if (ret) { |
1081 | dev_err(&pdev->dev, "fail to parse dt properties\n" ); |
1082 | return ret; |
1083 | } |
1084 | |
1085 | pin_desc = devm_kcalloc(dev: &pdev->dev, |
1086 | n: pinctrl_info->npins, |
1087 | size: sizeof(struct pinctrl_pin_desc), |
1088 | GFP_KERNEL); |
1089 | if (!pin_desc) |
1090 | return -ENOMEM; |
1091 | |
1092 | for (i = 0; i < pinctrl_info->npins; i++) { |
1093 | pin_desc[i].number = pinctrl_info->pins[i].number; |
1094 | pin_desc[i].name = pinctrl_info->pins[i].name; |
1095 | pin_desc[i].drv_data = pinctrl_info; |
1096 | } |
1097 | |
1098 | sprd_pinctrl_desc.pins = pin_desc; |
1099 | sprd_pinctrl_desc.name = dev_name(dev: &pdev->dev); |
1100 | sprd_pinctrl_desc.npins = pinctrl_info->npins; |
1101 | |
1102 | sprd_pctl->pctl = pinctrl_register(pctldesc: &sprd_pinctrl_desc, |
1103 | dev: &pdev->dev, driver_data: (void *)sprd_pctl); |
1104 | if (IS_ERR(ptr: sprd_pctl->pctl)) { |
1105 | dev_err(&pdev->dev, "could not register pinctrl driver\n" ); |
1106 | return PTR_ERR(ptr: sprd_pctl->pctl); |
1107 | } |
1108 | |
1109 | return 0; |
1110 | } |
1111 | EXPORT_SYMBOL_GPL(sprd_pinctrl_core_probe); |
1112 | |
1113 | void sprd_pinctrl_remove(struct platform_device *pdev) |
1114 | { |
1115 | struct sprd_pinctrl *sprd_pctl = platform_get_drvdata(pdev); |
1116 | |
1117 | pinctrl_unregister(pctldev: sprd_pctl->pctl); |
1118 | } |
1119 | EXPORT_SYMBOL_GPL(sprd_pinctrl_remove); |
1120 | |
1121 | void sprd_pinctrl_shutdown(struct platform_device *pdev) |
1122 | { |
1123 | struct pinctrl *pinctl; |
1124 | struct pinctrl_state *state; |
1125 | |
1126 | pinctl = devm_pinctrl_get(dev: &pdev->dev); |
1127 | if (IS_ERR(ptr: pinctl)) |
1128 | return; |
1129 | state = pinctrl_lookup_state(p: pinctl, name: "shutdown" ); |
1130 | if (IS_ERR(ptr: state)) |
1131 | return; |
1132 | pinctrl_select_state(p: pinctl, s: state); |
1133 | } |
1134 | EXPORT_SYMBOL_GPL(sprd_pinctrl_shutdown); |
1135 | |
1136 | MODULE_DESCRIPTION("SPREADTRUM Pin Controller Driver" ); |
1137 | MODULE_AUTHOR("Baolin Wang <baolin.wang@spreadtrum.com>" ); |
1138 | MODULE_LICENSE("GPL v2" ); |
1139 | |