1 // SPDX-License-Identifier: GPL-2.0
3 * Xilinx pinctrl driver for ZynqMP
8 * Copyright (C) 2021 Xilinx, Inc. All rights reserved.
15 #include <zynqmp_firmware.h>
16 #include <asm/arch/sys_proto.h>
18 #include <dm/device_compat.h>
19 #include <dm/pinctrl.h>
20 #include <linux/compat.h>
21 #include <dt-bindings/pinctrl/pinctrl-zynqmp.h>
23 #define PINCTRL_GET_FUNC_GROUPS_RESP_LEN 12
24 #define PINCTRL_GET_PIN_GROUPS_RESP_LEN 12
25 #define NUM_GROUPS_PER_RESP 6
27 #define RESERVED_GROUP -2
28 #define MAX_GROUP_PIN 50
29 #define MAX_PIN_GROUPS 50
30 #define MAX_GROUP_NAME_LEN 32
31 #define MAX_FUNC_NAME_LEN 16
33 #define DRIVE_STRENGTH_2MA 2
34 #define DRIVE_STRENGTH_4MA 4
35 #define DRIVE_STRENGTH_8MA 8
36 #define DRIVE_STRENGTH_12MA 12
39 * This driver works with very simple configuration that has the same name
40 * for group and function. This way it is compatible with the Linux Kernel
43 struct zynqmp_pinctrl_priv {
47 struct zynqmp_pmux_function *funcs;
48 struct zynqmp_pctrl_group *groups;
52 * struct zynqmp_pinctrl_config - pinconfig parameters
53 * @slew: Slew rate slow or fast
54 * @bias: Bias enabled or disabled
55 * @pull_ctrl: Pull control pull up or pull down
56 * @input_type: CMOS or Schmitt
57 * @drive_strength: Drive strength 2mA/4mA/8mA/12mA
58 * @volt_sts: Voltage status 1.8V or 3.3V
59 * @tri_state: Tristate enabled or disabled
61 * This structure holds information about pin control config
62 * option that can be set for each pin.
64 struct zynqmp_pinctrl_config {
75 * enum zynqmp_pin_config_param - possible pin configuration parameters
76 * @PIN_CFG_IOSTANDARD: if the pin can select an IO standard,
77 * the argument to this parameter (on a
78 * custom format) tells the driver which
79 * alternative IO standard to use
80 * @PIN_CONFIG_SCHMITTCMOS: this parameter (on a custom format) allows
81 * to select schmitt or cmos input for MIO pins
83 enum zynqmp_pin_config_param {
84 PIN_CFG_IOSTANDARD = PIN_CONFIG_END + 1,
85 PIN_CONFIG_SCHMITTCMOS,
89 * struct zynqmp_pmux_function - a pinmux function
90 * @name: Name of the pinmux function
91 * @groups: List of pingroups for this function
92 * @ngroups: Number of entries in @groups
94 * This structure holds information about pin control function
95 * and function group names supporting that function.
97 struct zynqmp_pmux_function {
98 char name[MAX_FUNC_NAME_LEN];
99 const char * const *groups;
100 unsigned int ngroups;
104 * struct zynqmp_pctrl_group - Pin control group info
106 * @pins: Group pin numbers
107 * @npins: Number of pins in group
109 struct zynqmp_pctrl_group {
111 unsigned int pins[MAX_GROUP_PIN];
115 static char pin_name[PINNAME_SIZE];
118 * zynqmp_pm_query_data() - Get query data from firmware
119 * @qid: Value of enum pm_query_id
122 * @out: Returned output value
124 * Return: Returns status, either success or error+reason
126 static int zynqmp_pm_query_data(enum pm_query_id qid, u32 arg1, u32 arg2, u32 *out)
129 u32 ret_payload[PAYLOAD_ARG_CNT];
131 ret = xilinx_pm_request(PM_QUERY_DATA, qid, arg1, arg2, 0, ret_payload);
135 *out = ret_payload[1];
140 static int zynqmp_pm_pinctrl_get_config(const u32 pin, const u32 param, u32 *value)
143 u32 ret_payload[PAYLOAD_ARG_CNT];
145 /* Get config for the pin */
146 ret = xilinx_pm_request(PM_PINCTRL_CONFIG_PARAM_GET, pin, param, 0, 0, ret_payload);
148 printf("%s failed\n", __func__);
152 *value = ret_payload[1];
157 static int zynqmp_pm_pinctrl_set_config(const u32 pin, const u32 param, u32 value)
161 if (param == PM_PINCTRL_CONFIG_TRI_STATE) {
162 ret = zynqmp_pm_feature(PM_PINCTRL_CONFIG_PARAM_SET);
163 if (ret < PM_PINCTRL_PARAM_SET_VERSION)
167 /* Request the pin first */
168 ret = xilinx_pm_request(PM_PINCTRL_REQUEST, pin, 0, 0, 0, NULL);
170 printf("%s: pin request failed\n", __func__);
174 /* Set config for the pin */
175 ret = xilinx_pm_request(PM_PINCTRL_CONFIG_PARAM_SET, pin, param, value, 0, NULL);
177 printf("%s failed\n", __func__);
184 static int zynqmp_pinctrl_get_function_groups(u32 fid, u32 index, u16 *groups)
187 u32 ret_payload[PAYLOAD_ARG_CNT];
189 ret = xilinx_pm_request(PM_QUERY_DATA, PM_QID_PINCTRL_GET_FUNCTION_GROUPS,
190 fid, index, 0, ret_payload);
192 printf("%s failed\n", __func__);
196 memcpy(groups, &ret_payload[1], PINCTRL_GET_FUNC_GROUPS_RESP_LEN);
201 static int zynqmp_pinctrl_prepare_func_groups(u32 fid,
202 struct zynqmp_pmux_function *func,
203 struct zynqmp_pctrl_group *groups)
205 const char **fgroups;
206 char name[MAX_GROUP_NAME_LEN];
207 u16 resp[NUM_GROUPS_PER_RESP] = {0};
210 fgroups = kcalloc(func->ngroups, sizeof(*fgroups), GFP_KERNEL);
214 for (index = 0; index < func->ngroups; index += NUM_GROUPS_PER_RESP) {
215 ret = zynqmp_pinctrl_get_function_groups(fid, index, resp);
219 for (i = 0; i < NUM_GROUPS_PER_RESP; i++) {
220 if (resp[i] == (u16)NA_GROUP)
222 if (resp[i] == (u16)RESERVED_GROUP)
225 snprintf(name, MAX_GROUP_NAME_LEN, "%s_%d_grp",
226 func->name, index + i);
227 fgroups[index + i] = strdup(name);
229 snprintf(name, MAX_GROUP_NAME_LEN, "%s_%d_grp",
230 func->name, index + i);
231 groups[resp[i]].name = strdup(name);
235 func->groups = fgroups;
240 static int zynqmp_pinctrl_get_pin_groups(u32 pin, u32 index, u16 *groups)
243 u32 ret_payload[PAYLOAD_ARG_CNT];
245 ret = xilinx_pm_request(PM_QUERY_DATA, PM_QID_PINCTRL_GET_PIN_GROUPS,
246 pin, index, 0, ret_payload);
248 printf("%s failed to get pin groups\n", __func__);
252 memcpy(groups, &ret_payload[1], PINCTRL_GET_PIN_GROUPS_RESP_LEN);
257 static void zynqmp_pinctrl_group_add_pin(struct zynqmp_pctrl_group *group,
260 group->pins[group->npins++] = pin;
263 static int zynqmp_pinctrl_create_pin_groups(struct zynqmp_pctrl_group *groups,
266 u16 resp[NUM_GROUPS_PER_RESP] = {0};
267 int ret, i, index = 0;
270 ret = zynqmp_pinctrl_get_pin_groups(pin, index, resp);
274 for (i = 0; i < NUM_GROUPS_PER_RESP; i++) {
275 if (resp[i] == (u16)NA_GROUP)
277 if (resp[i] == (u16)RESERVED_GROUP)
279 zynqmp_pinctrl_group_add_pin(&groups[resp[i]], pin);
281 index += NUM_GROUPS_PER_RESP;
282 } while (index <= MAX_PIN_GROUPS);
288 static int zynqmp_pinctrl_probe(struct udevice *dev)
290 struct zynqmp_pinctrl_priv *priv = dev_get_priv(dev);
293 u32 ret_payload[PAYLOAD_ARG_CNT];
295 /* Get number of pins first */
296 ret = zynqmp_pm_query_data(PM_QID_PINCTRL_GET_NUM_PINS, 0, 0, &priv->npins);
298 printf("%s failed to get no of pins\n", __func__);
302 /* Get number of functions available */
303 ret = zynqmp_pm_query_data(PM_QID_PINCTRL_GET_NUM_FUNCTIONS, 0, 0, &priv->nfuncs);
305 printf("%s failed to get no of functions\n", __func__);
309 /* Allocating structures for functions and its groups */
310 priv->funcs = kzalloc(sizeof(*priv->funcs) * priv->nfuncs, GFP_KERNEL);
314 for (i = 0; i < priv->nfuncs; i++) {
315 /* Get function name for the function and fill */
316 xilinx_pm_request(PM_QUERY_DATA, PM_QID_PINCTRL_GET_FUNCTION_NAME,
317 i, 0, 0, ret_payload);
319 memcpy((void *)priv->funcs[i].name, ret_payload, MAX_FUNC_NAME_LEN);
321 /* And fill number of groups available for certain function */
322 xilinx_pm_request(PM_QUERY_DATA, PM_QID_PINCTRL_GET_NUM_FUNCTION_GROUPS,
323 i, 0, 0, ret_payload);
325 priv->funcs[i].ngroups = ret_payload[1];
326 priv->ngroups += priv->funcs[i].ngroups;
329 /* Prepare all groups */
330 priv->groups = kzalloc(sizeof(*priv->groups) * priv->ngroups,
335 for (i = 0; i < priv->nfuncs; i++) {
336 ret = zynqmp_pinctrl_prepare_func_groups(i, &priv->funcs[i],
339 printf("Failed to prepare_func_groups\n");
344 for (pin = 0; pin < priv->npins; pin++) {
345 ret = zynqmp_pinctrl_create_pin_groups(priv->groups, pin);
353 static int zynqmp_pinctrl_get_functions_count(struct udevice *dev)
355 struct zynqmp_pinctrl_priv *priv = dev_get_priv(dev);
360 static const char *zynqmp_pinctrl_get_function_name(struct udevice *dev,
361 unsigned int selector)
363 struct zynqmp_pinctrl_priv *priv = dev_get_priv(dev);
365 return priv->funcs[selector].name;
368 static int zynqmp_pinmux_set(struct udevice *dev, unsigned int selector,
369 unsigned int func_selector)
373 /* Request the pin first */
374 ret = xilinx_pm_request(PM_PINCTRL_REQUEST, selector, 0, 0, 0, NULL);
376 printf("%s: pin request failed\n", __func__);
380 /* Set the pin function */
381 ret = xilinx_pm_request(PM_PINCTRL_SET_FUNCTION, selector, func_selector,
384 printf("%s: Failed to set pinmux function\n", __func__);
391 static int zynqmp_pinmux_group_set(struct udevice *dev, unsigned int selector,
392 unsigned int func_selector)
395 struct zynqmp_pinctrl_priv *priv = dev_get_priv(dev);
396 const struct zynqmp_pctrl_group *pgrp = &priv->groups[selector];
398 for (i = 0; i < pgrp->npins; i++)
399 zynqmp_pinmux_set(dev, pgrp->pins[i], func_selector);
404 static int zynqmp_pinconf_set(struct udevice *dev, unsigned int pin,
405 unsigned int param, unsigned int arg)
411 case PIN_CONFIG_SLEW_RATE:
412 param = PM_PINCTRL_CONFIG_SLEW_RATE;
413 ret = zynqmp_pm_pinctrl_set_config(pin, param, arg);
415 case PIN_CONFIG_BIAS_PULL_UP:
416 param = PM_PINCTRL_CONFIG_PULL_CTRL;
417 arg = PM_PINCTRL_BIAS_PULL_UP;
418 ret = zynqmp_pm_pinctrl_set_config(pin, param, arg);
420 case PIN_CONFIG_BIAS_PULL_DOWN:
421 param = PM_PINCTRL_CONFIG_PULL_CTRL;
422 arg = PM_PINCTRL_BIAS_PULL_DOWN;
423 ret = zynqmp_pm_pinctrl_set_config(pin, param, arg);
425 case PIN_CONFIG_BIAS_DISABLE:
426 param = PM_PINCTRL_CONFIG_BIAS_STATUS;
427 arg = PM_PINCTRL_BIAS_DISABLE;
428 ret = zynqmp_pm_pinctrl_set_config(pin, param, arg);
430 case PIN_CONFIG_SCHMITTCMOS:
431 param = PM_PINCTRL_CONFIG_SCHMITT_CMOS;
432 ret = zynqmp_pm_pinctrl_set_config(pin, param, arg);
434 case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
435 param = PM_PINCTRL_CONFIG_SCHMITT_CMOS;
436 ret = zynqmp_pm_pinctrl_set_config(pin, param, arg);
438 case PIN_CONFIG_DRIVE_STRENGTH:
440 case DRIVE_STRENGTH_2MA:
441 value = PM_PINCTRL_DRIVE_STRENGTH_2MA;
443 case DRIVE_STRENGTH_4MA:
444 value = PM_PINCTRL_DRIVE_STRENGTH_4MA;
446 case DRIVE_STRENGTH_8MA:
447 value = PM_PINCTRL_DRIVE_STRENGTH_8MA;
449 case DRIVE_STRENGTH_12MA:
450 value = PM_PINCTRL_DRIVE_STRENGTH_12MA;
453 /* Invalid drive strength */
454 dev_warn(dev, "Invalid drive strength for pin %d\n", pin);
458 param = PM_PINCTRL_CONFIG_DRIVE_STRENGTH;
459 ret = zynqmp_pm_pinctrl_set_config(pin, param, value);
461 case PIN_CFG_IOSTANDARD:
462 param = PM_PINCTRL_CONFIG_VOLTAGE_STATUS;
463 ret = zynqmp_pm_pinctrl_get_config(pin, param, &value);
465 dev_warn(dev, "Invalid IO Standard requested for pin %d\n",
468 case PIN_CONFIG_POWER_SOURCE:
469 param = PM_PINCTRL_CONFIG_VOLTAGE_STATUS;
470 ret = zynqmp_pm_pinctrl_get_config(pin, param, &value);
472 dev_warn(dev, "Invalid IO Standard requested for pin %d\n",
475 case PIN_CONFIG_BIAS_HIGH_IMPEDANCE:
476 param = PM_PINCTRL_CONFIG_TRI_STATE;
477 arg = PM_PINCTRL_TRI_STATE_ENABLE;
478 ret = zynqmp_pm_pinctrl_set_config(pin, param, arg);
480 case PIN_CONFIG_LOW_POWER_MODE:
482 * This cases are mentioned in dts but configurable
483 * registers are unknown. So falling through to ignore
484 * boot time warnings as of now.
488 case PIN_CONFIG_OUTPUT_ENABLE:
489 param = PM_PINCTRL_CONFIG_TRI_STATE;
490 arg = PM_PINCTRL_TRI_STATE_DISABLE;
491 ret = zynqmp_pm_pinctrl_set_config(pin, param, arg);
494 dev_warn(dev, "unsupported configuration parameter '%u'\n",
503 static int zynqmp_pinconf_group_set(struct udevice *dev,
504 unsigned int group_selector,
505 unsigned int param, unsigned int arg)
508 struct zynqmp_pinctrl_priv *priv = dev_get_priv(dev);
509 const struct zynqmp_pctrl_group *pgrp = &priv->groups[group_selector];
511 for (i = 0; i < pgrp->npins; i++)
512 zynqmp_pinconf_set(dev, pgrp->pins[i], param, arg);
517 static int zynqmp_pinctrl_get_pins_count(struct udevice *dev)
519 struct zynqmp_pinctrl_priv *priv = dev_get_priv(dev);
524 static const char *zynqmp_pinctrl_get_pin_name(struct udevice *dev,
525 unsigned int selector)
527 snprintf(pin_name, PINNAME_SIZE, "MIO%d", selector);
532 static int zynqmp_pinctrl_get_pin_muxing(struct udevice *dev,
533 unsigned int selector,
537 struct zynqmp_pinctrl_config pinmux;
539 zynqmp_pm_pinctrl_get_config(selector, PM_PINCTRL_CONFIG_SLEW_RATE,
541 zynqmp_pm_pinctrl_get_config(selector, PM_PINCTRL_CONFIG_BIAS_STATUS,
543 zynqmp_pm_pinctrl_get_config(selector, PM_PINCTRL_CONFIG_PULL_CTRL,
545 zynqmp_pm_pinctrl_get_config(selector, PM_PINCTRL_CONFIG_SCHMITT_CMOS,
547 zynqmp_pm_pinctrl_get_config(selector, PM_PINCTRL_CONFIG_DRIVE_STRENGTH,
548 &pinmux.drive_strength);
549 zynqmp_pm_pinctrl_get_config(selector, PM_PINCTRL_CONFIG_VOLTAGE_STATUS,
551 zynqmp_pm_pinctrl_get_config(selector, PM_PINCTRL_CONFIG_TRI_STATE,
554 switch (pinmux.drive_strength) {
555 case PM_PINCTRL_DRIVE_STRENGTH_2MA:
556 pinmux.drive_strength = DRIVE_STRENGTH_2MA;
558 case PM_PINCTRL_DRIVE_STRENGTH_4MA:
559 pinmux.drive_strength = DRIVE_STRENGTH_4MA;
561 case PM_PINCTRL_DRIVE_STRENGTH_8MA:
562 pinmux.drive_strength = DRIVE_STRENGTH_8MA;
564 case PM_PINCTRL_DRIVE_STRENGTH_12MA:
565 pinmux.drive_strength = DRIVE_STRENGTH_12MA;
568 /* Invalid drive strength */
569 dev_warn(dev, "Invalid drive strength\n");
574 "slew:%s\tbias:%s\tpull:%s\tinput:%s\tdrive:%dmA\tvolt:%s\ttri_state:%s",
575 pinmux.slew ? "slow" : "fast",
576 pinmux.bias ? "enabled" : "disabled",
577 pinmux.pull_ctrl ? "up" : "down",
578 pinmux.input_type ? "schmitt" : "cmos",
579 pinmux.drive_strength,
580 pinmux.volt_sts ? "1.8" : "3.3",
581 pinmux.tri_state ? "enabled" : "disabled");
586 static int zynqmp_pinctrl_get_groups_count(struct udevice *dev)
588 struct zynqmp_pinctrl_priv *priv = dev_get_priv(dev);
590 return priv->ngroups;
593 static const char *zynqmp_pinctrl_get_group_name(struct udevice *dev,
594 unsigned int selector)
596 struct zynqmp_pinctrl_priv *priv = dev_get_priv(dev);
598 return priv->groups[selector].name;
601 static const struct pinconf_param zynqmp_conf_params[] = {
602 { "bias-bus-hold", PIN_CONFIG_BIAS_BUS_HOLD, 0 },
603 { "bias-disable", PIN_CONFIG_BIAS_DISABLE, 0 },
604 { "bias-high-impedance", PIN_CONFIG_BIAS_HIGH_IMPEDANCE, 0 },
605 { "bias-pull-up", PIN_CONFIG_BIAS_PULL_UP, 1 },
606 { "bias-pull-pin-default", PIN_CONFIG_BIAS_PULL_PIN_DEFAULT, 1 },
607 { "bias-pull-down", PIN_CONFIG_BIAS_PULL_DOWN, 1 },
608 { "drive-open-drain", PIN_CONFIG_DRIVE_OPEN_DRAIN, 0 },
609 { "drive-open-source", PIN_CONFIG_DRIVE_OPEN_SOURCE, 0 },
610 { "drive-push-pull", PIN_CONFIG_DRIVE_PUSH_PULL, 0 },
611 { "drive-strength", PIN_CONFIG_DRIVE_STRENGTH, 0 },
612 { "drive-strength-microamp", PIN_CONFIG_DRIVE_STRENGTH_UA, 0 },
613 { "input-debounce", PIN_CONFIG_INPUT_DEBOUNCE, 0 },
614 { "input-disable", PIN_CONFIG_INPUT_ENABLE, 0 },
615 { "input-enable", PIN_CONFIG_INPUT_ENABLE, 1 },
616 { "input-schmitt", PIN_CONFIG_INPUT_SCHMITT, 0 },
617 { "input-schmitt-disable", PIN_CONFIG_INPUT_SCHMITT_ENABLE, 0 },
618 { "input-schmitt-enable", PIN_CONFIG_INPUT_SCHMITT_ENABLE, 1 },
619 { "low-power-disable", PIN_CONFIG_LOW_POWER_MODE, 0 },
620 { "low-power-enable", PIN_CONFIG_LOW_POWER_MODE, 1 },
621 { "output-disable", PIN_CONFIG_OUTPUT_ENABLE, 0 },
622 { "output-enable", PIN_CONFIG_OUTPUT_ENABLE, 1 },
623 { "output-high", PIN_CONFIG_OUTPUT, 1, },
624 { "output-low", PIN_CONFIG_OUTPUT, 0, },
625 { "power-source", PIN_CONFIG_POWER_SOURCE, 0 },
626 { "sleep-hardware-state", PIN_CONFIG_SLEEP_HARDWARE_STATE, 0 },
627 { "slew-rate", PIN_CONFIG_SLEW_RATE, 0 },
628 { "skew-delay", PIN_CONFIG_SKEW_DELAY, 0 },
629 /* zynqmp specific */
630 {"io-standard", PIN_CFG_IOSTANDARD, IO_STANDARD_LVCMOS18},
631 {"schmitt-cmos", PIN_CONFIG_SCHMITTCMOS, PM_PINCTRL_INPUT_TYPE_SCHMITT},
634 static struct pinctrl_ops zynqmp_pinctrl_ops = {
635 .get_pins_count = zynqmp_pinctrl_get_pins_count,
636 .get_pin_name = zynqmp_pinctrl_get_pin_name,
637 .get_pin_muxing = zynqmp_pinctrl_get_pin_muxing,
638 .set_state = pinctrl_generic_set_state,
639 .get_groups_count = zynqmp_pinctrl_get_groups_count,
640 .get_group_name = zynqmp_pinctrl_get_group_name,
641 .get_functions_count = zynqmp_pinctrl_get_functions_count,
642 .get_function_name = zynqmp_pinctrl_get_function_name,
643 .pinmux_group_set = zynqmp_pinmux_group_set,
644 .pinmux_set = zynqmp_pinmux_set,
645 .pinconf_params = zynqmp_conf_params,
646 .pinconf_group_set = zynqmp_pinconf_group_set,
647 .pinconf_set = zynqmp_pinconf_set,
648 .pinconf_num_params = ARRAY_SIZE(zynqmp_conf_params),
651 static const struct udevice_id zynqmp_pinctrl_ids[] = {
652 { .compatible = "xlnx,zynqmp-pinctrl" },
656 U_BOOT_DRIVER(pinctrl_zynqmp) = {
657 .name = "zynqmp-pinctrl",
658 .id = UCLASS_PINCTRL,
659 .of_match = zynqmp_pinctrl_ids,
660 .priv_auto = sizeof(struct zynqmp_pinctrl_priv),
661 .ops = &zynqmp_pinctrl_ops,
662 .probe = zynqmp_pinctrl_probe,