1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * ZynqMP pin controller |
4 | * |
5 | * Copyright (C) 2020, 2021 Xilinx, Inc. |
6 | * |
7 | * Sai Krishna Potthuri <lakshmi.sai.krishna.potthuri@xilinx.com> |
8 | * Rajan Vaja <rajan.vaja@xilinx.com> |
9 | */ |
10 | |
11 | #include <dt-bindings/pinctrl/pinctrl-zynqmp.h> |
12 | |
13 | #include <linux/init.h> |
14 | #include <linux/module.h> |
15 | #include <linux/of_address.h> |
16 | #include <linux/platform_device.h> |
17 | |
18 | #include <linux/firmware/xlnx-zynqmp.h> |
19 | |
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 "pinctrl-utils.h" |
27 | |
28 | #define ZYNQMP_PIN_PREFIX "MIO" |
29 | #define PINCTRL_GET_FUNC_NAME_RESP_LEN 16 |
30 | #define MAX_FUNC_NAME_LEN 16 |
31 | #define MAX_GROUP_PIN 50 |
32 | #define MAX_PIN_GROUPS 50 |
33 | #define END_OF_FUNCTIONS "END_OF_FUNCTIONS" |
34 | #define NUM_GROUPS_PER_RESP 6 |
35 | |
36 | #define PINCTRL_GET_FUNC_GROUPS_RESP_LEN 12 |
37 | #define PINCTRL_GET_PIN_GROUPS_RESP_LEN 12 |
38 | #define NA_GROUP 0xFFFF |
39 | #define RESERVED_GROUP 0xFFFE |
40 | |
41 | #define DRIVE_STRENGTH_2MA 2 |
42 | #define DRIVE_STRENGTH_4MA 4 |
43 | #define DRIVE_STRENGTH_8MA 8 |
44 | #define DRIVE_STRENGTH_12MA 12 |
45 | |
46 | /** |
47 | * struct zynqmp_pmux_function - a pinmux function |
48 | * @name: Name of the pin mux function |
49 | * @groups: List of pin groups for this function |
50 | * @ngroups: Number of entries in @groups |
51 | * @node: Firmware node matching with the function |
52 | * |
53 | * This structure holds information about pin control function |
54 | * and function group names supporting that function. |
55 | */ |
56 | struct zynqmp_pmux_function { |
57 | char name[MAX_FUNC_NAME_LEN]; |
58 | const char * const *groups; |
59 | unsigned int ngroups; |
60 | }; |
61 | |
62 | /** |
63 | * struct zynqmp_pinctrl - driver data |
64 | * @pctrl: Pin control device |
65 | * @groups: Pin groups |
66 | * @ngroups: Number of @groups |
67 | * @funcs: Pin mux functions |
68 | * @nfuncs: Number of @funcs |
69 | * |
70 | * This struct is stored as driver data and used to retrieve |
71 | * information regarding pin control functions, groups and |
72 | * group pins. |
73 | */ |
74 | struct zynqmp_pinctrl { |
75 | struct pinctrl_dev *pctrl; |
76 | const struct zynqmp_pctrl_group *groups; |
77 | unsigned int ngroups; |
78 | const struct zynqmp_pmux_function *funcs; |
79 | unsigned int nfuncs; |
80 | }; |
81 | |
82 | /** |
83 | * struct zynqmp_pctrl_group - Pin control group info |
84 | * @name: Group name |
85 | * @pins: Group pin numbers |
86 | * @npins: Number of pins in the group |
87 | */ |
88 | struct zynqmp_pctrl_group { |
89 | const char *name; |
90 | unsigned int pins[MAX_GROUP_PIN]; |
91 | unsigned int npins; |
92 | }; |
93 | |
94 | static struct pinctrl_desc zynqmp_desc; |
95 | |
96 | static int zynqmp_pctrl_get_groups_count(struct pinctrl_dev *pctldev) |
97 | { |
98 | struct zynqmp_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); |
99 | |
100 | return pctrl->ngroups; |
101 | } |
102 | |
103 | static const char *zynqmp_pctrl_get_group_name(struct pinctrl_dev *pctldev, |
104 | unsigned int selector) |
105 | { |
106 | struct zynqmp_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); |
107 | |
108 | return pctrl->groups[selector].name; |
109 | } |
110 | |
111 | static int zynqmp_pctrl_get_group_pins(struct pinctrl_dev *pctldev, |
112 | unsigned int selector, |
113 | const unsigned int **pins, |
114 | unsigned int *npins) |
115 | { |
116 | struct zynqmp_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); |
117 | |
118 | *pins = pctrl->groups[selector].pins; |
119 | *npins = pctrl->groups[selector].npins; |
120 | |
121 | return 0; |
122 | } |
123 | |
124 | static const struct pinctrl_ops zynqmp_pctrl_ops = { |
125 | .get_groups_count = zynqmp_pctrl_get_groups_count, |
126 | .get_group_name = zynqmp_pctrl_get_group_name, |
127 | .get_group_pins = zynqmp_pctrl_get_group_pins, |
128 | .dt_node_to_map = pinconf_generic_dt_node_to_map_all, |
129 | .dt_free_map = pinctrl_utils_free_map, |
130 | }; |
131 | |
132 | static int zynqmp_pinmux_request_pin(struct pinctrl_dev *pctldev, |
133 | unsigned int pin) |
134 | { |
135 | int ret; |
136 | |
137 | ret = zynqmp_pm_pinctrl_request(pin); |
138 | if (ret) { |
139 | dev_err(pctldev->dev, "request failed for pin %u\n" , pin); |
140 | return ret; |
141 | } |
142 | |
143 | return 0; |
144 | } |
145 | |
146 | static int zynqmp_pmux_get_functions_count(struct pinctrl_dev *pctldev) |
147 | { |
148 | struct zynqmp_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); |
149 | |
150 | return pctrl->nfuncs; |
151 | } |
152 | |
153 | static const char *zynqmp_pmux_get_function_name(struct pinctrl_dev *pctldev, |
154 | unsigned int selector) |
155 | { |
156 | struct zynqmp_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); |
157 | |
158 | return pctrl->funcs[selector].name; |
159 | } |
160 | |
161 | /** |
162 | * zynqmp_pmux_get_function_groups() - Get groups for the function |
163 | * @pctldev: Pincontrol device pointer. |
164 | * @selector: Function ID |
165 | * @groups: Group names. |
166 | * @num_groups: Number of function groups. |
167 | * |
168 | * Get function's group count and group names. |
169 | * |
170 | * Return: 0 |
171 | */ |
172 | static int zynqmp_pmux_get_function_groups(struct pinctrl_dev *pctldev, |
173 | unsigned int selector, |
174 | const char * const **groups, |
175 | unsigned * const num_groups) |
176 | { |
177 | struct zynqmp_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); |
178 | |
179 | *groups = pctrl->funcs[selector].groups; |
180 | *num_groups = pctrl->funcs[selector].ngroups; |
181 | |
182 | return 0; |
183 | } |
184 | |
185 | /** |
186 | * zynqmp_pinmux_set_mux() - Set requested function for the group |
187 | * @pctldev: Pincontrol device pointer. |
188 | * @function: Function ID. |
189 | * @group: Group ID. |
190 | * |
191 | * Loop through all pins of the group and call firmware API |
192 | * to set requested function for all pins in the group. |
193 | * |
194 | * Return: 0 on success else error code. |
195 | */ |
196 | static int zynqmp_pinmux_set_mux(struct pinctrl_dev *pctldev, |
197 | unsigned int function, |
198 | unsigned int group) |
199 | { |
200 | struct zynqmp_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); |
201 | const struct zynqmp_pctrl_group *pgrp = &pctrl->groups[group]; |
202 | int ret, i; |
203 | |
204 | for (i = 0; i < pgrp->npins; i++) { |
205 | unsigned int pin = pgrp->pins[i]; |
206 | |
207 | ret = zynqmp_pm_pinctrl_set_function(pin, id: function); |
208 | if (ret) { |
209 | dev_err(pctldev->dev, "set mux failed for pin %u\n" , |
210 | pin); |
211 | return ret; |
212 | } |
213 | } |
214 | |
215 | return 0; |
216 | } |
217 | |
218 | static int zynqmp_pinmux_release_pin(struct pinctrl_dev *pctldev, |
219 | unsigned int pin) |
220 | { |
221 | int ret; |
222 | |
223 | ret = zynqmp_pm_pinctrl_release(pin); |
224 | if (ret) { |
225 | dev_err(pctldev->dev, "free pin failed for pin %u\n" , |
226 | pin); |
227 | return ret; |
228 | } |
229 | |
230 | return 0; |
231 | } |
232 | |
233 | static const struct pinmux_ops zynqmp_pinmux_ops = { |
234 | .request = zynqmp_pinmux_request_pin, |
235 | .get_functions_count = zynqmp_pmux_get_functions_count, |
236 | .get_function_name = zynqmp_pmux_get_function_name, |
237 | .get_function_groups = zynqmp_pmux_get_function_groups, |
238 | .set_mux = zynqmp_pinmux_set_mux, |
239 | .free = zynqmp_pinmux_release_pin, |
240 | }; |
241 | |
242 | /** |
243 | * zynqmp_pinconf_cfg_get() - get config value for the pin |
244 | * @pctldev: Pin control device pointer. |
245 | * @pin: Pin number. |
246 | * @config: Value of config param. |
247 | * |
248 | * Get value of the requested configuration parameter for the |
249 | * given pin. |
250 | * |
251 | * Return: 0 on success else error code. |
252 | */ |
253 | static int zynqmp_pinconf_cfg_get(struct pinctrl_dev *pctldev, |
254 | unsigned int pin, |
255 | unsigned long *config) |
256 | { |
257 | unsigned int arg, param = pinconf_to_config_param(config: *config); |
258 | int ret; |
259 | |
260 | switch (param) { |
261 | case PIN_CONFIG_SLEW_RATE: |
262 | param = PM_PINCTRL_CONFIG_SLEW_RATE; |
263 | ret = zynqmp_pm_pinctrl_get_config(pin, param, value: &arg); |
264 | break; |
265 | case PIN_CONFIG_BIAS_PULL_UP: |
266 | param = PM_PINCTRL_CONFIG_PULL_CTRL; |
267 | ret = zynqmp_pm_pinctrl_get_config(pin, param, value: &arg); |
268 | if (arg != PM_PINCTRL_BIAS_PULL_UP) |
269 | return -EINVAL; |
270 | |
271 | arg = 1; |
272 | break; |
273 | case PIN_CONFIG_BIAS_PULL_DOWN: |
274 | param = PM_PINCTRL_CONFIG_PULL_CTRL; |
275 | ret = zynqmp_pm_pinctrl_get_config(pin, param, value: &arg); |
276 | if (arg != PM_PINCTRL_BIAS_PULL_DOWN) |
277 | return -EINVAL; |
278 | |
279 | arg = 1; |
280 | break; |
281 | case PIN_CONFIG_BIAS_DISABLE: |
282 | param = PM_PINCTRL_CONFIG_BIAS_STATUS; |
283 | ret = zynqmp_pm_pinctrl_get_config(pin, param, value: &arg); |
284 | if (arg != PM_PINCTRL_BIAS_DISABLE) |
285 | return -EINVAL; |
286 | |
287 | arg = 1; |
288 | break; |
289 | case PIN_CONFIG_POWER_SOURCE: |
290 | param = PM_PINCTRL_CONFIG_VOLTAGE_STATUS; |
291 | ret = zynqmp_pm_pinctrl_get_config(pin, param, value: &arg); |
292 | break; |
293 | case PIN_CONFIG_INPUT_SCHMITT_ENABLE: |
294 | param = PM_PINCTRL_CONFIG_SCHMITT_CMOS; |
295 | ret = zynqmp_pm_pinctrl_get_config(pin, param, value: &arg); |
296 | break; |
297 | case PIN_CONFIG_DRIVE_STRENGTH: |
298 | param = PM_PINCTRL_CONFIG_DRIVE_STRENGTH; |
299 | ret = zynqmp_pm_pinctrl_get_config(pin, param, value: &arg); |
300 | switch (arg) { |
301 | case PM_PINCTRL_DRIVE_STRENGTH_2MA: |
302 | arg = DRIVE_STRENGTH_2MA; |
303 | break; |
304 | case PM_PINCTRL_DRIVE_STRENGTH_4MA: |
305 | arg = DRIVE_STRENGTH_4MA; |
306 | break; |
307 | case PM_PINCTRL_DRIVE_STRENGTH_8MA: |
308 | arg = DRIVE_STRENGTH_8MA; |
309 | break; |
310 | case PM_PINCTRL_DRIVE_STRENGTH_12MA: |
311 | arg = DRIVE_STRENGTH_12MA; |
312 | break; |
313 | default: |
314 | /* Invalid drive strength */ |
315 | dev_warn(pctldev->dev, |
316 | "Invalid drive strength for pin %d\n" , |
317 | pin); |
318 | return -EINVAL; |
319 | } |
320 | break; |
321 | default: |
322 | ret = -ENOTSUPP; |
323 | break; |
324 | } |
325 | |
326 | if (ret) |
327 | return ret; |
328 | |
329 | param = pinconf_to_config_param(config: *config); |
330 | *config = pinconf_to_config_packed(param, argument: arg); |
331 | |
332 | return 0; |
333 | } |
334 | |
335 | /** |
336 | * zynqmp_pinconf_cfg_set() - Set requested config for the pin |
337 | * @pctldev: Pincontrol device pointer. |
338 | * @pin: Pin number. |
339 | * @configs: Configuration to set. |
340 | * @num_configs: Number of configurations. |
341 | * |
342 | * Loop through all configurations and call firmware API |
343 | * to set requested configurations for the pin. |
344 | * |
345 | * Return: 0 on success else error code. |
346 | */ |
347 | static int zynqmp_pinconf_cfg_set(struct pinctrl_dev *pctldev, |
348 | unsigned int pin, unsigned long *configs, |
349 | unsigned int num_configs) |
350 | { |
351 | int i, ret; |
352 | |
353 | for (i = 0; i < num_configs; i++) { |
354 | unsigned int param = pinconf_to_config_param(config: configs[i]); |
355 | unsigned int arg = pinconf_to_config_argument(config: configs[i]); |
356 | unsigned int value; |
357 | |
358 | switch (param) { |
359 | case PIN_CONFIG_SLEW_RATE: |
360 | param = PM_PINCTRL_CONFIG_SLEW_RATE; |
361 | ret = zynqmp_pm_pinctrl_set_config(pin, param, value: arg); |
362 | break; |
363 | case PIN_CONFIG_BIAS_PULL_UP: |
364 | param = PM_PINCTRL_CONFIG_PULL_CTRL; |
365 | arg = PM_PINCTRL_BIAS_PULL_UP; |
366 | ret = zynqmp_pm_pinctrl_set_config(pin, param, value: arg); |
367 | break; |
368 | case PIN_CONFIG_BIAS_PULL_DOWN: |
369 | param = PM_PINCTRL_CONFIG_PULL_CTRL; |
370 | arg = PM_PINCTRL_BIAS_PULL_DOWN; |
371 | ret = zynqmp_pm_pinctrl_set_config(pin, param, value: arg); |
372 | break; |
373 | case PIN_CONFIG_BIAS_DISABLE: |
374 | param = PM_PINCTRL_CONFIG_BIAS_STATUS; |
375 | arg = PM_PINCTRL_BIAS_DISABLE; |
376 | ret = zynqmp_pm_pinctrl_set_config(pin, param, value: arg); |
377 | break; |
378 | case PIN_CONFIG_INPUT_SCHMITT_ENABLE: |
379 | param = PM_PINCTRL_CONFIG_SCHMITT_CMOS; |
380 | ret = zynqmp_pm_pinctrl_set_config(pin, param, value: arg); |
381 | break; |
382 | case PIN_CONFIG_DRIVE_STRENGTH: |
383 | switch (arg) { |
384 | case DRIVE_STRENGTH_2MA: |
385 | value = PM_PINCTRL_DRIVE_STRENGTH_2MA; |
386 | break; |
387 | case DRIVE_STRENGTH_4MA: |
388 | value = PM_PINCTRL_DRIVE_STRENGTH_4MA; |
389 | break; |
390 | case DRIVE_STRENGTH_8MA: |
391 | value = PM_PINCTRL_DRIVE_STRENGTH_8MA; |
392 | break; |
393 | case DRIVE_STRENGTH_12MA: |
394 | value = PM_PINCTRL_DRIVE_STRENGTH_12MA; |
395 | break; |
396 | default: |
397 | /* Invalid drive strength */ |
398 | dev_warn(pctldev->dev, |
399 | "Invalid drive strength for pin %d\n" , |
400 | pin); |
401 | return -EINVAL; |
402 | } |
403 | |
404 | param = PM_PINCTRL_CONFIG_DRIVE_STRENGTH; |
405 | ret = zynqmp_pm_pinctrl_set_config(pin, param, value); |
406 | break; |
407 | case PIN_CONFIG_POWER_SOURCE: |
408 | param = PM_PINCTRL_CONFIG_VOLTAGE_STATUS; |
409 | ret = zynqmp_pm_pinctrl_get_config(pin, param, value: &value); |
410 | |
411 | if (arg != value) |
412 | dev_warn(pctldev->dev, |
413 | "Invalid IO Standard requested for pin %d\n" , |
414 | pin); |
415 | |
416 | break; |
417 | case PIN_CONFIG_BIAS_HIGH_IMPEDANCE: |
418 | param = PM_PINCTRL_CONFIG_TRI_STATE; |
419 | arg = PM_PINCTRL_TRI_STATE_ENABLE; |
420 | ret = zynqmp_pm_pinctrl_set_config(pin, param, value: arg); |
421 | break; |
422 | case PIN_CONFIG_MODE_LOW_POWER: |
423 | /* |
424 | * These cases are mentioned in dts but configurable |
425 | * registers are unknown. So falling through to ignore |
426 | * boot time warnings as of now. |
427 | */ |
428 | ret = 0; |
429 | break; |
430 | case PIN_CONFIG_OUTPUT_ENABLE: |
431 | param = PM_PINCTRL_CONFIG_TRI_STATE; |
432 | arg = PM_PINCTRL_TRI_STATE_DISABLE; |
433 | ret = zynqmp_pm_pinctrl_set_config(pin, param, value: arg); |
434 | break; |
435 | default: |
436 | dev_warn(pctldev->dev, |
437 | "unsupported configuration parameter '%u'\n" , |
438 | param); |
439 | ret = -ENOTSUPP; |
440 | break; |
441 | } |
442 | |
443 | param = pinconf_to_config_param(config: configs[i]); |
444 | arg = pinconf_to_config_argument(config: configs[i]); |
445 | if (ret) |
446 | dev_warn(pctldev->dev, |
447 | "failed to set: pin %u param %u value %u\n" , |
448 | pin, param, arg); |
449 | } |
450 | |
451 | return 0; |
452 | } |
453 | |
454 | /** |
455 | * zynqmp_pinconf_group_set() - Set requested config for the group |
456 | * @pctldev: Pincontrol device pointer. |
457 | * @selector: Group ID. |
458 | * @configs: Configuration to set. |
459 | * @num_configs: Number of configurations. |
460 | * |
461 | * Call function to set configs for each pin in the group. |
462 | * |
463 | * Return: 0 on success else error code. |
464 | */ |
465 | static int zynqmp_pinconf_group_set(struct pinctrl_dev *pctldev, |
466 | unsigned int selector, |
467 | unsigned long *configs, |
468 | unsigned int num_configs) |
469 | { |
470 | int i, ret; |
471 | struct zynqmp_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); |
472 | const struct zynqmp_pctrl_group *pgrp = &pctrl->groups[selector]; |
473 | |
474 | for (i = 0; i < pgrp->npins; i++) { |
475 | ret = zynqmp_pinconf_cfg_set(pctldev, pin: pgrp->pins[i], configs, |
476 | num_configs); |
477 | if (ret) |
478 | return ret; |
479 | } |
480 | |
481 | return 0; |
482 | } |
483 | |
484 | static const struct pinconf_ops zynqmp_pinconf_ops = { |
485 | .is_generic = true, |
486 | .pin_config_get = zynqmp_pinconf_cfg_get, |
487 | .pin_config_set = zynqmp_pinconf_cfg_set, |
488 | .pin_config_group_set = zynqmp_pinconf_group_set, |
489 | }; |
490 | |
491 | static struct pinctrl_desc zynqmp_desc = { |
492 | .name = "zynqmp_pinctrl" , |
493 | .owner = THIS_MODULE, |
494 | .pctlops = &zynqmp_pctrl_ops, |
495 | .pmxops = &zynqmp_pinmux_ops, |
496 | .confops = &zynqmp_pinconf_ops, |
497 | }; |
498 | |
499 | static int zynqmp_pinctrl_get_function_groups(u32 fid, u32 index, u16 *groups) |
500 | { |
501 | struct zynqmp_pm_query_data qdata = {0}; |
502 | u32 payload[PAYLOAD_ARG_CNT]; |
503 | int ret; |
504 | |
505 | qdata.qid = PM_QID_PINCTRL_GET_FUNCTION_GROUPS; |
506 | qdata.arg1 = fid; |
507 | qdata.arg2 = index; |
508 | |
509 | ret = zynqmp_pm_query_data(qdata, out: payload); |
510 | if (ret) |
511 | return ret; |
512 | |
513 | memcpy(groups, &payload[1], PINCTRL_GET_FUNC_GROUPS_RESP_LEN); |
514 | |
515 | return 0; |
516 | } |
517 | |
518 | static int zynqmp_pinctrl_get_func_num_groups(u32 fid, unsigned int *ngroups) |
519 | { |
520 | struct zynqmp_pm_query_data qdata = {0}; |
521 | u32 payload[PAYLOAD_ARG_CNT]; |
522 | int ret; |
523 | |
524 | qdata.qid = PM_QID_PINCTRL_GET_NUM_FUNCTION_GROUPS; |
525 | qdata.arg1 = fid; |
526 | |
527 | ret = zynqmp_pm_query_data(qdata, out: payload); |
528 | if (ret) |
529 | return ret; |
530 | |
531 | *ngroups = payload[1]; |
532 | |
533 | return 0; |
534 | } |
535 | |
536 | /** |
537 | * zynqmp_pinctrl_prepare_func_groups() - prepare function and groups data |
538 | * @dev: Device pointer. |
539 | * @fid: Function ID. |
540 | * @func: Function data. |
541 | * @groups: Groups data. |
542 | * |
543 | * Query firmware to get group IDs for each function. Firmware returns |
544 | * group IDs. Based on the group index for the function, group names in |
545 | * the function are stored. For example, the first group in "eth0" function |
546 | * is named as "eth0_0" and the second group as "eth0_1" and so on. |
547 | * |
548 | * Based on the group ID received from the firmware, function stores name of |
549 | * the group for that group ID. For example, if "eth0" first group ID |
550 | * is x, groups[x] name will be stored as "eth0_0". |
551 | * |
552 | * Once done for each function, each function would have its group names |
553 | * and each group would also have their names. |
554 | * |
555 | * Return: 0 on success else error code. |
556 | */ |
557 | static int zynqmp_pinctrl_prepare_func_groups(struct device *dev, u32 fid, |
558 | struct zynqmp_pmux_function *func, |
559 | struct zynqmp_pctrl_group *groups) |
560 | { |
561 | u16 resp[NUM_GROUPS_PER_RESP] = {0}; |
562 | const char **fgroups; |
563 | int ret, index, i; |
564 | |
565 | fgroups = devm_kzalloc(dev, size: sizeof(*fgroups) * func->ngroups, GFP_KERNEL); |
566 | if (!fgroups) |
567 | return -ENOMEM; |
568 | |
569 | for (index = 0; index < func->ngroups; index += NUM_GROUPS_PER_RESP) { |
570 | ret = zynqmp_pinctrl_get_function_groups(fid, index, groups: resp); |
571 | if (ret) |
572 | return ret; |
573 | |
574 | for (i = 0; i < NUM_GROUPS_PER_RESP; i++) { |
575 | if (resp[i] == NA_GROUP) |
576 | goto done; |
577 | |
578 | if (resp[i] == RESERVED_GROUP) |
579 | continue; |
580 | |
581 | fgroups[index + i] = devm_kasprintf(dev, GFP_KERNEL, |
582 | fmt: "%s_%d_grp" , |
583 | func->name, |
584 | index + i); |
585 | if (!fgroups[index + i]) |
586 | return -ENOMEM; |
587 | |
588 | groups[resp[i]].name = devm_kasprintf(dev, GFP_KERNEL, |
589 | fmt: "%s_%d_grp" , |
590 | func->name, |
591 | index + i); |
592 | if (!groups[resp[i]].name) |
593 | return -ENOMEM; |
594 | } |
595 | } |
596 | done: |
597 | func->groups = fgroups; |
598 | |
599 | return 0; |
600 | } |
601 | |
602 | static void zynqmp_pinctrl_get_function_name(u32 fid, char *name) |
603 | { |
604 | struct zynqmp_pm_query_data qdata = {0}; |
605 | u32 payload[PAYLOAD_ARG_CNT]; |
606 | |
607 | qdata.qid = PM_QID_PINCTRL_GET_FUNCTION_NAME; |
608 | qdata.arg1 = fid; |
609 | |
610 | /* |
611 | * Name of the function is maximum 16 bytes and cannot |
612 | * accommodate the return value in SMC buffers, hence ignoring |
613 | * the return value for this specific qid. |
614 | */ |
615 | zynqmp_pm_query_data(qdata, out: payload); |
616 | memcpy(name, payload, PINCTRL_GET_FUNC_NAME_RESP_LEN); |
617 | } |
618 | |
619 | static int zynqmp_pinctrl_get_num_functions(unsigned int *nfuncs) |
620 | { |
621 | struct zynqmp_pm_query_data qdata = {0}; |
622 | u32 payload[PAYLOAD_ARG_CNT]; |
623 | int ret; |
624 | |
625 | qdata.qid = PM_QID_PINCTRL_GET_NUM_FUNCTIONS; |
626 | |
627 | ret = zynqmp_pm_query_data(qdata, out: payload); |
628 | if (ret) |
629 | return ret; |
630 | |
631 | *nfuncs = payload[1]; |
632 | |
633 | return 0; |
634 | } |
635 | |
636 | static int zynqmp_pinctrl_get_pin_groups(u32 pin, u32 index, u16 *groups) |
637 | { |
638 | struct zynqmp_pm_query_data qdata = {0}; |
639 | u32 payload[PAYLOAD_ARG_CNT]; |
640 | int ret; |
641 | |
642 | qdata.qid = PM_QID_PINCTRL_GET_PIN_GROUPS; |
643 | qdata.arg1 = pin; |
644 | qdata.arg2 = index; |
645 | |
646 | ret = zynqmp_pm_query_data(qdata, out: payload); |
647 | if (ret) |
648 | return ret; |
649 | |
650 | memcpy(groups, &payload[1], PINCTRL_GET_PIN_GROUPS_RESP_LEN); |
651 | |
652 | return 0; |
653 | } |
654 | |
655 | static void zynqmp_pinctrl_group_add_pin(struct zynqmp_pctrl_group *group, |
656 | unsigned int pin) |
657 | { |
658 | group->pins[group->npins++] = pin; |
659 | } |
660 | |
661 | /** |
662 | * zynqmp_pinctrl_create_pin_groups() - assign pins to respective groups |
663 | * @dev: Device pointer. |
664 | * @groups: Groups data. |
665 | * @pin: Pin number. |
666 | * |
667 | * Query firmware to get groups available for the given pin. |
668 | * Based on the firmware response(group IDs for the pin), add |
669 | * pin number to the respective group's pin array. |
670 | * |
671 | * Once all pins are queries, each group would have its number |
672 | * of pins and pin numbers data. |
673 | * |
674 | * Return: 0 on success else error code. |
675 | */ |
676 | static int zynqmp_pinctrl_create_pin_groups(struct device *dev, |
677 | struct zynqmp_pctrl_group *groups, |
678 | unsigned int pin) |
679 | { |
680 | u16 resp[NUM_GROUPS_PER_RESP] = {0}; |
681 | int ret, i, index = 0; |
682 | |
683 | do { |
684 | ret = zynqmp_pinctrl_get_pin_groups(pin, index, groups: resp); |
685 | if (ret) |
686 | return ret; |
687 | |
688 | for (i = 0; i < NUM_GROUPS_PER_RESP; i++) { |
689 | if (resp[i] == NA_GROUP) |
690 | return ret; |
691 | |
692 | if (resp[i] == RESERVED_GROUP) |
693 | continue; |
694 | |
695 | zynqmp_pinctrl_group_add_pin(group: &groups[resp[i]], pin); |
696 | } |
697 | index += NUM_GROUPS_PER_RESP; |
698 | } while (index <= MAX_PIN_GROUPS); |
699 | |
700 | return 0; |
701 | } |
702 | |
703 | /** |
704 | * zynqmp_pinctrl_prepare_group_pins() - prepare each group's pin data |
705 | * @dev: Device pointer. |
706 | * @groups: Groups data. |
707 | * @ngroups: Number of groups. |
708 | * |
709 | * Prepare pin number and number of pins data for each pins. |
710 | * |
711 | * Return: 0 on success else error code. |
712 | */ |
713 | static int zynqmp_pinctrl_prepare_group_pins(struct device *dev, |
714 | struct zynqmp_pctrl_group *groups, |
715 | unsigned int ngroups) |
716 | { |
717 | unsigned int pin; |
718 | int ret; |
719 | |
720 | for (pin = 0; pin < zynqmp_desc.npins; pin++) { |
721 | ret = zynqmp_pinctrl_create_pin_groups(dev, groups, pin); |
722 | if (ret) |
723 | return ret; |
724 | } |
725 | |
726 | return 0; |
727 | } |
728 | |
729 | /** |
730 | * zynqmp_pinctrl_prepare_function_info() - prepare function info |
731 | * @dev: Device pointer. |
732 | * @pctrl: Pin control driver data. |
733 | * |
734 | * Query firmware for functions, groups and pin information and |
735 | * prepare pin control driver data. |
736 | * |
737 | * Query number of functions and number of function groups (number |
738 | * of groups in the given function) to allocate required memory buffers |
739 | * for functions and groups. Once buffers are allocated to store |
740 | * functions and groups data, query and store required information |
741 | * (number of groups and group names for each function, number of |
742 | * pins and pin numbers for each group). |
743 | * |
744 | * Return: 0 on success else error code. |
745 | */ |
746 | static int zynqmp_pinctrl_prepare_function_info(struct device *dev, |
747 | struct zynqmp_pinctrl *pctrl) |
748 | { |
749 | struct zynqmp_pmux_function *funcs; |
750 | struct zynqmp_pctrl_group *groups; |
751 | int ret, i; |
752 | |
753 | ret = zynqmp_pinctrl_get_num_functions(nfuncs: &pctrl->nfuncs); |
754 | if (ret) |
755 | return ret; |
756 | |
757 | funcs = devm_kzalloc(dev, size: sizeof(*funcs) * pctrl->nfuncs, GFP_KERNEL); |
758 | if (!funcs) |
759 | return -ENOMEM; |
760 | |
761 | for (i = 0; i < pctrl->nfuncs; i++) { |
762 | zynqmp_pinctrl_get_function_name(fid: i, name: funcs[i].name); |
763 | |
764 | ret = zynqmp_pinctrl_get_func_num_groups(fid: i, ngroups: &funcs[i].ngroups); |
765 | if (ret) |
766 | return ret; |
767 | |
768 | pctrl->ngroups += funcs[i].ngroups; |
769 | } |
770 | |
771 | groups = devm_kzalloc(dev, size: sizeof(*groups) * pctrl->ngroups, GFP_KERNEL); |
772 | if (!groups) |
773 | return -ENOMEM; |
774 | |
775 | for (i = 0; i < pctrl->nfuncs; i++) { |
776 | ret = zynqmp_pinctrl_prepare_func_groups(dev, fid: i, func: &funcs[i], |
777 | groups); |
778 | if (ret) |
779 | return ret; |
780 | } |
781 | |
782 | ret = zynqmp_pinctrl_prepare_group_pins(dev, groups, ngroups: pctrl->ngroups); |
783 | if (ret) |
784 | return ret; |
785 | |
786 | pctrl->funcs = funcs; |
787 | pctrl->groups = groups; |
788 | |
789 | return 0; |
790 | } |
791 | |
792 | static int zynqmp_pinctrl_get_num_pins(unsigned int *npins) |
793 | { |
794 | struct zynqmp_pm_query_data qdata = {0}; |
795 | u32 payload[PAYLOAD_ARG_CNT]; |
796 | int ret; |
797 | |
798 | qdata.qid = PM_QID_PINCTRL_GET_NUM_PINS; |
799 | |
800 | ret = zynqmp_pm_query_data(qdata, out: payload); |
801 | if (ret) |
802 | return ret; |
803 | |
804 | *npins = payload[1]; |
805 | |
806 | return 0; |
807 | } |
808 | |
809 | /** |
810 | * zynqmp_pinctrl_prepare_pin_desc() - prepare pin description info |
811 | * @dev: Device pointer. |
812 | * @zynqmp_pins: Pin information. |
813 | * @npins: Number of pins. |
814 | * |
815 | * Query number of pins information from firmware and prepare pin |
816 | * description containing pin number and pin name. |
817 | * |
818 | * Return: 0 on success else error code. |
819 | */ |
820 | static int zynqmp_pinctrl_prepare_pin_desc(struct device *dev, |
821 | const struct pinctrl_pin_desc |
822 | **zynqmp_pins, |
823 | unsigned int *npins) |
824 | { |
825 | struct pinctrl_pin_desc *pins, *pin; |
826 | int ret; |
827 | int i; |
828 | |
829 | ret = zynqmp_pinctrl_get_num_pins(npins); |
830 | if (ret) |
831 | return ret; |
832 | |
833 | pins = devm_kzalloc(dev, size: sizeof(*pins) * *npins, GFP_KERNEL); |
834 | if (!pins) |
835 | return -ENOMEM; |
836 | |
837 | for (i = 0; i < *npins; i++) { |
838 | pin = &pins[i]; |
839 | pin->number = i; |
840 | pin->name = devm_kasprintf(dev, GFP_KERNEL, fmt: "%s%d" , |
841 | ZYNQMP_PIN_PREFIX, i); |
842 | if (!pin->name) |
843 | return -ENOMEM; |
844 | } |
845 | |
846 | *zynqmp_pins = pins; |
847 | |
848 | return 0; |
849 | } |
850 | |
851 | static int zynqmp_pinctrl_probe(struct platform_device *pdev) |
852 | { |
853 | struct zynqmp_pinctrl *pctrl; |
854 | int ret; |
855 | |
856 | pctrl = devm_kzalloc(dev: &pdev->dev, size: sizeof(*pctrl), GFP_KERNEL); |
857 | if (!pctrl) |
858 | return -ENOMEM; |
859 | |
860 | ret = zynqmp_pinctrl_prepare_pin_desc(dev: &pdev->dev, |
861 | zynqmp_pins: &zynqmp_desc.pins, |
862 | npins: &zynqmp_desc.npins); |
863 | if (ret) { |
864 | dev_err(&pdev->dev, "pin desc prepare fail with %d\n" , ret); |
865 | return ret; |
866 | } |
867 | |
868 | ret = zynqmp_pinctrl_prepare_function_info(dev: &pdev->dev, pctrl); |
869 | if (ret) { |
870 | dev_err(&pdev->dev, "function info prepare fail with %d\n" , ret); |
871 | return ret; |
872 | } |
873 | |
874 | pctrl->pctrl = devm_pinctrl_register(dev: &pdev->dev, pctldesc: &zynqmp_desc, driver_data: pctrl); |
875 | if (IS_ERR(ptr: pctrl->pctrl)) |
876 | return PTR_ERR(ptr: pctrl->pctrl); |
877 | |
878 | platform_set_drvdata(pdev, data: pctrl); |
879 | |
880 | return ret; |
881 | } |
882 | |
883 | static const struct of_device_id zynqmp_pinctrl_of_match[] = { |
884 | { .compatible = "xlnx,zynqmp-pinctrl" }, |
885 | { } |
886 | }; |
887 | MODULE_DEVICE_TABLE(of, zynqmp_pinctrl_of_match); |
888 | |
889 | static struct platform_driver zynqmp_pinctrl_driver = { |
890 | .driver = { |
891 | .name = "zynqmp-pinctrl" , |
892 | .of_match_table = zynqmp_pinctrl_of_match, |
893 | }, |
894 | .probe = zynqmp_pinctrl_probe, |
895 | }; |
896 | module_platform_driver(zynqmp_pinctrl_driver); |
897 | |
898 | MODULE_AUTHOR("Sai Krishna Potthuri <lakshmi.sai.krishna.potthuri@xilinx.com>" ); |
899 | MODULE_DESCRIPTION("ZynqMP Pin Controller Driver" ); |
900 | MODULE_LICENSE("GPL v2" ); |
901 | |