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