st 23. 2. 2022 v 15:23 odesÃlatel Michal Simek <michal.si...@xilinx.com> napsal: > > From: Ashok Reddy Soma <ashok.reddy.s...@xilinx.com> > > Add pinctrl driver for Xilinx ZynqMP SOC. This driver is compatible with > linux device tree parameters for configuring pinmux and pinconf. > > Signed-off-by: Ashok Reddy Soma <ashok.reddy.s...@xilinx.com> > Signed-off-by: Michal Simek <michal.si...@xilinx.com> > --- > > MAINTAINERS | 1 + > drivers/pinctrl/Kconfig | 10 + > drivers/pinctrl/Makefile | 1 + > drivers/pinctrl/pinctrl-zynqmp.c | 644 +++++++++++++++++++++++++++++++ > include/zynqmp_firmware.h | 43 +++ > 5 files changed, 699 insertions(+) > create mode 100644 drivers/pinctrl/pinctrl-zynqmp.c > > diff --git a/MAINTAINERS b/MAINTAINERS > index fb171e0c687b..c1a5ac95f295 100644 > --- a/MAINTAINERS > +++ b/MAINTAINERS > @@ -619,6 +619,7 @@ F: drivers/mmc/zynq_sdhci.c > F: drivers/mtd/nand/raw/zynq_nand.c > F: drivers/net/phy/xilinx_phy.c > F: drivers/net/zynq_gem.c > +F: drivers/pinctrl/pinctrl-zynqmp.c > F: drivers/serial/serial_zynq.c > F: drivers/spi/zynq_qspi.c > F: drivers/spi/zynq_spi.c > diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig > index 03946245c7d5..d7477d7c3364 100644 > --- a/drivers/pinctrl/Kconfig > +++ b/drivers/pinctrl/Kconfig > @@ -318,6 +318,16 @@ config PINCTRL_K210 > Support pin multiplexing on the K210. The "FPIOA" can remap any > supported function to any multifunctional IO pin. It can also > perform > basic GPIO functions, such as reading the current value of a pin. > + > +config PINCTRL_ZYNQMP > + bool "Xilinx ZynqMP pin control driver" > + depends on DM && PINCTRL_GENERIC && ARCH_ZYNQMP > + default y > + help > + Support pin multiplexing control on Xilinx ZynqMP. The driver uses > + Generic Pinctrl framework and is compatible with the Linux driver, > + i.e. it uses the same device tree configuration. > + > endif > > source "drivers/pinctrl/broadcom/Kconfig" > diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile > index fd736a7f640a..ddddd13433c5 100644 > --- a/drivers/pinctrl/Makefile > +++ b/drivers/pinctrl/Makefile > @@ -30,3 +30,4 @@ obj-$(CONFIG_PINCTRL_STI) += pinctrl-sti.o > obj-$(CONFIG_PINCTRL_STM32) += pinctrl_stm32.o > obj-$(CONFIG_$(SPL_)PINCTRL_STMFX) += pinctrl-stmfx.o > obj-y += broadcom/ > +obj-$(CONFIG_PINCTRL_ZYNQMP) += pinctrl-zynqmp.o > diff --git a/drivers/pinctrl/pinctrl-zynqmp.c > b/drivers/pinctrl/pinctrl-zynqmp.c > new file mode 100644 > index 000000000000..7c5a02db1b98 > --- /dev/null > +++ b/drivers/pinctrl/pinctrl-zynqmp.c > @@ -0,0 +1,644 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * Xilinx pinctrl driver for ZynqMP > + * > + * Author(s): Ashok Reddy Soma <ashok.reddy.s...@xilinx.com> > + * Michal Simek <michal.si...@xilinx.com> > + * > + * Copyright (C) 2021 Xilinx, Inc. All rights reserved. > + */ > + > +#include <common.h> > +#include <dm.h> > +#include <errno.h> > +#include <malloc.h> > +#include <zynqmp_firmware.h> > +#include <asm/arch/sys_proto.h> > +#include <asm/io.h> > +#include <dm/device_compat.h> > +#include <dm/pinctrl.h> > +#include <linux/compat.h> > +#include <dt-bindings/pinctrl/pinctrl-zynqmp.h> > + > +#define PINCTRL_GET_FUNC_GROUPS_RESP_LEN 12 > +#define PINCTRL_GET_PIN_GROUPS_RESP_LEN 12 > +#define NUM_GROUPS_PER_RESP 6 > +#define NA_GROUP -1 > +#define RESERVED_GROUP -2 > +#define MAX_GROUP_PIN 50 > +#define MAX_PIN_GROUPS 50 > +#define MAX_GROUP_NAME_LEN 32 > +#define MAX_FUNC_NAME_LEN 16 > + > +#define DRIVE_STRENGTH_2MA 2 > +#define DRIVE_STRENGTH_4MA 4 > +#define DRIVE_STRENGTH_8MA 8 > +#define DRIVE_STRENGTH_12MA 12 > + > +/* > + * This driver works with very simple configuration that has the same name > + * for group and function. This way it is compatible with the Linux Kernel > + * driver. > + */ > +struct zynqmp_pinctrl_priv { > + u32 npins; > + u32 nfuncs; > + u32 ngroups; > + struct zynqmp_pmux_function *funcs; > + struct zynqmp_pctrl_group *groups; > +}; > + > +/** > + * struct zynqmp_pinctrl_config - pinconfig parameters > + * @slew: Slew rate slow or fast > + * @bias: Bias enabled or disabled > + * @pull_ctrl: Pull control pull up or pull down > + * @input_type: CMOS or Schmitt > + * @drive_strength: Drive strength 2mA/4mA/8mA/12mA > + * @volt_sts: Voltage status 1.8V or 3.3V > + * @tri_state: Tristate enabled or disabled > + * > + * This structure holds information about pin control config > + * option that can be set for each pin. > + */ > +struct zynqmp_pinctrl_config { > + u32 slew; > + u32 bias; > + u32 pull_ctrl; > + u32 input_type; > + u32 drive_strength; > + u32 volt_sts; > + u32 tri_state; > +}; > + > +/** > + * enum zynqmp_pin_config_param - possible pin configuration parameters > + * @PIN_CONFIG_IOSTANDARD: if the pin can select an IO standard, > + * the argument to this parameter (on a > + * custom format) tells the driver which > + * alternative IO standard to use > + * @PIN_CONFIG_SCHMITTCMOS: this parameter (on a custom format) allows > + * to select schmitt or cmos input for MIO pins > + */ > +enum zynqmp_pin_config_param { > + PIN_CONFIG_IOSTANDARD = PIN_CONFIG_END + 1, > + PIN_CONFIG_SCHMITTCMOS, > +}; > + > +/** > + * struct zynqmp_pmux_function - a pinmux function > + * @name: Name of the pinmux function > + * @groups: List of pingroups for this function > + * @ngroups: Number of entries in @groups > + * > + * This structure holds information about pin control function > + * and function group names supporting that function. > + */ > +struct zynqmp_pmux_function { > + char name[MAX_FUNC_NAME_LEN]; > + const char * const *groups; > + unsigned int ngroups; > +}; > + > +/** > + * struct zynqmp_pctrl_group - Pin control group info > + * @name: Group name > + * @pins: Group pin numbers > + * @npins: Number of pins in group > + */ > +struct zynqmp_pctrl_group { > + const char *name; > + unsigned int pins[MAX_GROUP_PIN]; > + unsigned int npins; > +}; > + > +static char pin_name[PINNAME_SIZE]; > + > +/** > + * zynqmp_pm_query_data() - Get query data from firmware > + * @qid: Value of enum pm_query_id > + * @arg1: Argument 1 > + * @arg2: Argument 2 > + * @out: Returned output value > + * > + * Return: Returns status, either success or error+reason > + */ > +static int zynqmp_pm_query_data(enum pm_query_id qid, u32 arg1, u32 arg2, > u32 *out) > +{ > + int ret; > + u32 ret_payload[PAYLOAD_ARG_CNT]; > + > + ret = xilinx_pm_request(PM_QUERY_DATA, qid, arg1, arg2, 0, > ret_payload); > + if (ret) > + return ret; > + > + *out = ret_payload[1]; > + > + return ret; > +} > + > +static int zynqmp_pm_pinctrl_get_config(const u32 pin, const u32 param, u32 > *value) > +{ > + int ret; > + u32 ret_payload[PAYLOAD_ARG_CNT]; > + > + /* Get config for the pin */ > + ret = xilinx_pm_request(PM_PINCTRL_CONFIG_PARAM_GET, pin, param, 0, > 0, ret_payload); > + if (ret) { > + printf("%s failed\n", __func__); > + return ret; > + } > + > + *value = ret_payload[1]; > + > + return ret; > +} > + > +static int zynqmp_pm_pinctrl_set_config(const u32 pin, const u32 param, u32 > value) > +{ > + int ret; > + > + /* Request the pin first */ > + ret = xilinx_pm_request(PM_PINCTRL_REQUEST, pin, 0, 0, 0, NULL); > + if (ret) { > + printf("%s: pin request failed\n", __func__); > + return ret; > + } > + > + /* Set config for the pin */ > + ret = xilinx_pm_request(PM_PINCTRL_CONFIG_PARAM_SET, pin, param, > value, 0, NULL); > + if (ret) { > + printf("%s failed\n", __func__); > + return ret; > + } > + > + return ret; > +} > + > +static int zynqmp_pinctrl_get_function_groups(u32 fid, u32 index, u16 > *groups) > +{ > + int ret; > + u32 ret_payload[PAYLOAD_ARG_CNT]; > + > + ret = xilinx_pm_request(PM_QUERY_DATA, > PM_QID_PINCTRL_GET_FUNCTION_GROUPS, > + fid, index, 0, ret_payload); > + if (ret) { > + printf("%s failed\n", __func__); > + return ret; > + } > + > + memcpy(groups, &ret_payload[1], PINCTRL_GET_FUNC_GROUPS_RESP_LEN); > + > + return ret; > +} > + > +static int zynqmp_pinctrl_prepare_func_groups(u32 fid, > + struct zynqmp_pmux_function > *func, > + struct zynqmp_pctrl_group > *groups) > +{ > + const char **fgroups; > + char name[MAX_GROUP_NAME_LEN]; > + u16 resp[NUM_GROUPS_PER_RESP] = {0}; > + int ret, index, i; > + > + fgroups = kcalloc(func->ngroups, sizeof(*fgroups), GFP_KERNEL); > + if (!fgroups) > + return -ENOMEM; > + > + for (index = 0; index < func->ngroups; index += NUM_GROUPS_PER_RESP) { > + ret = zynqmp_pinctrl_get_function_groups(fid, index, resp); > + if (ret) > + return ret; > + > + for (i = 0; i < NUM_GROUPS_PER_RESP; i++) { > + if (resp[i] == (u16)NA_GROUP) > + goto done; > + if (resp[i] == (u16)RESERVED_GROUP) > + continue; > + > + snprintf(name, MAX_GROUP_NAME_LEN, "%s_%d_grp", > + func->name, index + i); > + fgroups[index + i] = strdup(name); > + > + snprintf(name, MAX_GROUP_NAME_LEN, "%s_%d_grp", > + func->name, index + i); > + groups[resp[i]].name = strdup(name); > + } > + } > +done: > + func->groups = fgroups; > + > + return ret; > +} > + > +static int zynqmp_pinctrl_get_pin_groups(u32 pin, u32 index, u16 *groups) > +{ > + int ret; > + u32 ret_payload[PAYLOAD_ARG_CNT]; > + > + ret = xilinx_pm_request(PM_QUERY_DATA, PM_QID_PINCTRL_GET_PIN_GROUPS, > + pin, index, 0, ret_payload); > + if (ret) { > + printf("%s failed to get pin groups\n", __func__); > + return ret; > + } > + > + memcpy(groups, &ret_payload[1], PINCTRL_GET_PIN_GROUPS_RESP_LEN); > + > + return ret; > +} > + > +static void zynqmp_pinctrl_group_add_pin(struct zynqmp_pctrl_group *group, > + unsigned int pin) > +{ > + group->pins[group->npins++] = pin; > +} > + > +static int zynqmp_pinctrl_create_pin_groups(struct zynqmp_pctrl_group > *groups, > + unsigned int pin) > +{ > + u16 resp[NUM_GROUPS_PER_RESP] = {0}; > + int ret, i, index = 0; > + > + do { > + ret = zynqmp_pinctrl_get_pin_groups(pin, index, resp); > + if (ret) > + return ret; > + > + for (i = 0; i < NUM_GROUPS_PER_RESP; i++) { > + if (resp[i] == (u16)NA_GROUP) > + goto done; > + if (resp[i] == (u16)RESERVED_GROUP) > + continue; > + zynqmp_pinctrl_group_add_pin(&groups[resp[i]], pin); > + } > + index += NUM_GROUPS_PER_RESP; > + } while (index <= MAX_PIN_GROUPS); > + > +done: > + return ret; > +} > + > +static int zynqmp_pinctrl_probe(struct udevice *dev) > +{ > + struct zynqmp_pinctrl_priv *priv = dev_get_priv(dev); > + int ret, i; > + u32 pin; > + u32 ret_payload[PAYLOAD_ARG_CNT]; > + > + /* Get number of pins first */ > + ret = zynqmp_pm_query_data(PM_QID_PINCTRL_GET_NUM_PINS, 0, 0, > &priv->npins); > + if (ret) { > + printf("%s failed to get no of pins\n", __func__); > + return ret; > + } > + > + /* Get number of functions available */ > + ret = zynqmp_pm_query_data(PM_QID_PINCTRL_GET_NUM_FUNCTIONS, 0, 0, > &priv->nfuncs); > + if (ret) { > + printf("%s failed to get no of functions\n", __func__); > + return ret; > + } > + > + /* Allocating structures for functions and its groups */ > + priv->funcs = kzalloc(sizeof(*priv->funcs) * priv->nfuncs, > GFP_KERNEL); > + if (!priv->funcs) > + return -ENOMEM; > + > + for (i = 0; i < priv->nfuncs; i++) { > + /* Get function name for the function and fill */ > + xilinx_pm_request(PM_QUERY_DATA, > PM_QID_PINCTRL_GET_FUNCTION_NAME, > + i, 0, 0, ret_payload); > + > + memcpy((void *)priv->funcs[i].name, ret_payload, > MAX_FUNC_NAME_LEN); > + > + /* And fill number of groups available for certain function */ > + xilinx_pm_request(PM_QUERY_DATA, > PM_QID_PINCTRL_GET_NUM_FUNCTION_GROUPS, > + i, 0, 0, ret_payload); > + > + priv->funcs[i].ngroups = ret_payload[1]; > + priv->ngroups += priv->funcs[i].ngroups; > + } > + > + /* Prepare all groups */ > + priv->groups = kzalloc(sizeof(*priv->groups) * priv->ngroups, > + GFP_KERNEL); > + if (!priv->groups) > + return -ENOMEM; > + > + for (i = 0; i < priv->nfuncs; i++) { > + ret = zynqmp_pinctrl_prepare_func_groups(i, &priv->funcs[i], > + priv->groups); > + if (ret) { > + printf("Failed to prepare_func_groups\n"); > + return ret; > + } > + } > + > + for (pin = 0; pin < priv->npins; pin++) { > + ret = zynqmp_pinctrl_create_pin_groups(priv->groups, pin); > + if (ret) > + return ret; > + } > + > + return 0; > +} > + > +static int zynqmp_pinctrl_get_functions_count(struct udevice *dev) > +{ > + struct zynqmp_pinctrl_priv *priv = dev_get_priv(dev); > + > + return priv->nfuncs; > +} > + > +static const char *zynqmp_pinctrl_get_function_name(struct udevice *dev, > + unsigned int selector) > +{ > + struct zynqmp_pinctrl_priv *priv = dev_get_priv(dev); > + > + return priv->funcs[selector].name; > +} > + > +static int zynqmp_pinmux_set(struct udevice *dev, unsigned int selector, > + unsigned int func_selector) > +{ > + int ret; > + > + /* Request the pin first */ > + ret = xilinx_pm_request(PM_PINCTRL_REQUEST, selector, 0, 0, 0, NULL); > + if (ret) { > + printf("%s: pin request failed\n", __func__); > + return ret; > + } > + > + /* Set the pin function */ > + ret = xilinx_pm_request(PM_PINCTRL_SET_FUNCTION, selector, > func_selector, > + 0, 0, NULL); > + if (ret) { > + printf("%s: Failed to set pinmux function\n", __func__); > + return ret; > + } > + > + return 0; > +} > + > +static int zynqmp_pinmux_group_set(struct udevice *dev, unsigned int > selector, > + unsigned int func_selector) > +{ > + int i; > + struct zynqmp_pinctrl_priv *priv = dev_get_priv(dev); > + const struct zynqmp_pctrl_group *pgrp = &priv->groups[selector]; > + > + for (i = 0; i < pgrp->npins; i++) > + zynqmp_pinmux_set(dev, pgrp->pins[i], func_selector); > + > + return 0; > +} > + > +static int zynqmp_pinconf_set(struct udevice *dev, unsigned int pin, > + unsigned int param, unsigned int arg) > +{ > + int ret = 0; > + unsigned int value; > + > + switch (param) { > + case PIN_CONFIG_SLEW_RATE: > + param = PM_PINCTRL_CONFIG_SLEW_RATE; > + ret = zynqmp_pm_pinctrl_set_config(pin, param, arg); > + break; > + case PIN_CONFIG_BIAS_PULL_UP: > + param = PM_PINCTRL_CONFIG_PULL_CTRL; > + arg = PM_PINCTRL_BIAS_PULL_UP; > + ret = zynqmp_pm_pinctrl_set_config(pin, param, arg); > + break; > + case PIN_CONFIG_BIAS_PULL_DOWN: > + param = PM_PINCTRL_CONFIG_PULL_CTRL; > + arg = PM_PINCTRL_BIAS_PULL_DOWN; > + ret = zynqmp_pm_pinctrl_set_config(pin, param, arg); > + break; > + case PIN_CONFIG_BIAS_DISABLE: > + param = PM_PINCTRL_CONFIG_BIAS_STATUS; > + arg = PM_PINCTRL_BIAS_DISABLE; > + ret = zynqmp_pm_pinctrl_set_config(pin, param, arg); > + break; > + case PIN_CONFIG_SCHMITTCMOS: > + param = PM_PINCTRL_CONFIG_SCHMITT_CMOS; > + ret = zynqmp_pm_pinctrl_set_config(pin, param, arg); > + break; > + case PIN_CONFIG_INPUT_SCHMITT_ENABLE: > + param = PM_PINCTRL_CONFIG_SCHMITT_CMOS; > + ret = zynqmp_pm_pinctrl_set_config(pin, param, arg); > + break; > + case PIN_CONFIG_DRIVE_STRENGTH: > + switch (arg) { > + case DRIVE_STRENGTH_2MA: > + value = PM_PINCTRL_DRIVE_STRENGTH_2MA; > + break; > + case DRIVE_STRENGTH_4MA: > + value = PM_PINCTRL_DRIVE_STRENGTH_4MA; > + break; > + case DRIVE_STRENGTH_8MA: > + value = PM_PINCTRL_DRIVE_STRENGTH_8MA; > + break; > + case DRIVE_STRENGTH_12MA: > + value = PM_PINCTRL_DRIVE_STRENGTH_12MA; > + break; > + default: > + /* Invalid drive strength */ > + dev_warn(dev, "Invalid drive strength for pin %d\n", > pin); > + return -EINVAL; > + } > + > + param = PM_PINCTRL_CONFIG_DRIVE_STRENGTH; > + ret = zynqmp_pm_pinctrl_set_config(pin, param, value); > + break; > + case PIN_CONFIG_IOSTANDARD: > + param = PM_PINCTRL_CONFIG_VOLTAGE_STATUS; > + ret = zynqmp_pm_pinctrl_get_config(pin, param, &value); > + if (arg != value) > + dev_warn(dev, "Invalid IO Standard requested for pin > %d\n", > + pin); > + break; > + case PIN_CONFIG_POWER_SOURCE: > + param = PM_PINCTRL_CONFIG_VOLTAGE_STATUS; > + ret = zynqmp_pm_pinctrl_get_config(pin, param, &value); > + if (arg != value) > + dev_warn(dev, "Invalid IO Standard requested for pin > %d\n", > + pin); > + break; > + case PIN_CONFIG_BIAS_HIGH_IMPEDANCE: > + case PIN_CONFIG_LOW_POWER_MODE: > + /* > + * This cases are mentioned in dts but configurable > + * registers are unknown. So falling through to ignore > + * boot time warnings as of now. > + */ > + ret = 0; > + break; > + default: > + dev_warn(dev, "unsupported configuration parameter '%u'\n", > + param); > + ret = -ENOTSUPP; > + break; > + } > + > + return ret; > +} > + > +static int zynqmp_pinconf_group_set(struct udevice *dev, > + unsigned int group_selector, > + unsigned int param, unsigned int arg) > +{ > + int i; > + struct zynqmp_pinctrl_priv *priv = dev_get_priv(dev); > + const struct zynqmp_pctrl_group *pgrp = &priv->groups[group_selector]; > + > + for (i = 0; i < pgrp->npins; i++) > + zynqmp_pinconf_set(dev, pgrp->pins[i], param, arg); > + > + return 0; > +} > + > +static int zynqmp_pinctrl_get_pins_count(struct udevice *dev) > +{ > + struct zynqmp_pinctrl_priv *priv = dev_get_priv(dev); > + > + return priv->npins; > +} > + > +static const char *zynqmp_pinctrl_get_pin_name(struct udevice *dev, > + unsigned int selector) > +{ > + snprintf(pin_name, PINNAME_SIZE, "MIO%d", selector); > + > + return pin_name; > +} > + > +static int zynqmp_pinctrl_get_pin_muxing(struct udevice *dev, > + unsigned int selector, > + char *buf, > + int size) > +{ > + struct zynqmp_pinctrl_config pinmux; > + > + zynqmp_pm_pinctrl_get_config(selector, PM_PINCTRL_CONFIG_SLEW_RATE, > + &pinmux.slew); > + zynqmp_pm_pinctrl_get_config(selector, PM_PINCTRL_CONFIG_BIAS_STATUS, > + &pinmux.bias); > + zynqmp_pm_pinctrl_get_config(selector, PM_PINCTRL_CONFIG_PULL_CTRL, > + &pinmux.pull_ctrl); > + zynqmp_pm_pinctrl_get_config(selector, PM_PINCTRL_CONFIG_SCHMITT_CMOS, > + &pinmux.input_type); > + zynqmp_pm_pinctrl_get_config(selector, > PM_PINCTRL_CONFIG_DRIVE_STRENGTH, > + &pinmux.drive_strength); > + zynqmp_pm_pinctrl_get_config(selector, > PM_PINCTRL_CONFIG_VOLTAGE_STATUS, > + &pinmux.volt_sts); > + > + switch (pinmux.drive_strength) { > + case PM_PINCTRL_DRIVE_STRENGTH_2MA: > + pinmux.drive_strength = DRIVE_STRENGTH_2MA; > + break; > + case PM_PINCTRL_DRIVE_STRENGTH_4MA: > + pinmux.drive_strength = DRIVE_STRENGTH_4MA; > + break; > + case PM_PINCTRL_DRIVE_STRENGTH_8MA: > + pinmux.drive_strength = DRIVE_STRENGTH_8MA; > + break; > + case PM_PINCTRL_DRIVE_STRENGTH_12MA: > + pinmux.drive_strength = DRIVE_STRENGTH_12MA; > + break; > + default: > + /* Invalid drive strength */ > + dev_warn(dev, "Invalid drive strength\n"); > + return -EINVAL; > + } > + > + snprintf(buf, size, > "slew:%s\tbias:%s\tpull:%s\tinput:%s\tdrive:%dmA\tvolt:%s", > + pinmux.slew ? "slow" : "fast", > + pinmux.bias ? "enabled" : "disabled", > + pinmux.pull_ctrl ? "up" : "down", > + pinmux.input_type ? "schmitt" : "cmos", > + pinmux.drive_strength, > + pinmux.volt_sts ? "1.8" : "3.3"); > + > + return 0; > +} > + > +static int zynqmp_pinctrl_get_groups_count(struct udevice *dev) > +{ > + struct zynqmp_pinctrl_priv *priv = dev_get_priv(dev); > + > + return priv->ngroups; > +} > + > +static const char *zynqmp_pinctrl_get_group_name(struct udevice *dev, > + unsigned int selector) > +{ > + struct zynqmp_pinctrl_priv *priv = dev_get_priv(dev); > + > + return priv->groups[selector].name; > +} > + > +static const struct pinconf_param zynqmp_conf_params[] = { > + { "bias-bus-hold", PIN_CONFIG_BIAS_BUS_HOLD, 0 }, > + { "bias-disable", PIN_CONFIG_BIAS_DISABLE, 0 }, > + { "bias-high-impedance", PIN_CONFIG_BIAS_HIGH_IMPEDANCE, 0 }, > + { "bias-pull-up", PIN_CONFIG_BIAS_PULL_UP, 1 }, > + { "bias-pull-pin-default", PIN_CONFIG_BIAS_PULL_PIN_DEFAULT, 1 }, > + { "bias-pull-down", PIN_CONFIG_BIAS_PULL_DOWN, 1 }, > + { "drive-open-drain", PIN_CONFIG_DRIVE_OPEN_DRAIN, 0 }, > + { "drive-open-source", PIN_CONFIG_DRIVE_OPEN_SOURCE, 0 }, > + { "drive-push-pull", PIN_CONFIG_DRIVE_PUSH_PULL, 0 }, > + { "drive-strength", PIN_CONFIG_DRIVE_STRENGTH, 0 }, > + { "drive-strength-microamp", PIN_CONFIG_DRIVE_STRENGTH_UA, 0 }, > + { "input-debounce", PIN_CONFIG_INPUT_DEBOUNCE, 0 }, > + { "input-disable", PIN_CONFIG_INPUT_ENABLE, 0 }, > + { "input-enable", PIN_CONFIG_INPUT_ENABLE, 1 }, > + { "input-schmitt", PIN_CONFIG_INPUT_SCHMITT, 0 }, > + { "input-schmitt-disable", PIN_CONFIG_INPUT_SCHMITT_ENABLE, 0 }, > + { "input-schmitt-enable", PIN_CONFIG_INPUT_SCHMITT_ENABLE, 1 }, > + { "low-power-disable", PIN_CONFIG_LOW_POWER_MODE, 0 }, > + { "low-power-enable", PIN_CONFIG_LOW_POWER_MODE, 1 }, > + { "output-disable", PIN_CONFIG_OUTPUT_ENABLE, 0 }, > + { "output-enable", PIN_CONFIG_OUTPUT_ENABLE, 1 }, > + { "output-high", PIN_CONFIG_OUTPUT, 1, }, > + { "output-low", PIN_CONFIG_OUTPUT, 0, }, > + { "power-source", PIN_CONFIG_POWER_SOURCE, 0 }, > + { "sleep-hardware-state", PIN_CONFIG_SLEEP_HARDWARE_STATE, 0 }, > + { "slew-rate", PIN_CONFIG_SLEW_RATE, 0 }, > + { "skew-delay", PIN_CONFIG_SKEW_DELAY, 0 }, > + /* zynqmp specific */ > + {"io-standard", PIN_CONFIG_IOSTANDARD, IO_STANDARD_LVCMOS18}, > + {"schmitt-cmos", PIN_CONFIG_SCHMITTCMOS, > PM_PINCTRL_INPUT_TYPE_SCHMITT}, > +}; > + > +static struct pinctrl_ops zynqmp_pinctrl_ops = { > + .get_pins_count = zynqmp_pinctrl_get_pins_count, > + .get_pin_name = zynqmp_pinctrl_get_pin_name, > + .get_pin_muxing = zynqmp_pinctrl_get_pin_muxing, > + .set_state = pinctrl_generic_set_state, > + .get_groups_count = zynqmp_pinctrl_get_groups_count, > + .get_group_name = zynqmp_pinctrl_get_group_name, > + .get_functions_count = zynqmp_pinctrl_get_functions_count, > + .get_function_name = zynqmp_pinctrl_get_function_name, > + .pinmux_group_set = zynqmp_pinmux_group_set, > + .pinmux_set = zynqmp_pinmux_set, > + .pinconf_params = zynqmp_conf_params, > + .pinconf_group_set = zynqmp_pinconf_group_set, > + .pinconf_set = zynqmp_pinconf_set, > + .pinconf_num_params = ARRAY_SIZE(zynqmp_conf_params), > +}; > + > +static const struct udevice_id zynqmp_pinctrl_ids[] = { > + { .compatible = "xlnx,zynqmp-pinctrl" }, > + { } > +}; > + > +U_BOOT_DRIVER(pinctrl_zynqmp) = { > + .name = "zynqmp-pinctrl", > + .id = UCLASS_PINCTRL, > + .of_match = zynqmp_pinctrl_ids, > + .priv_auto = sizeof(struct zynqmp_pinctrl_priv), > + .ops = &zynqmp_pinctrl_ops, > + .probe = zynqmp_pinctrl_probe, > +}; > diff --git a/include/zynqmp_firmware.h b/include/zynqmp_firmware.h > index 50bf4ef39535..41abc2eee951 100644 > --- a/include/zynqmp_firmware.h > +++ b/include/zynqmp_firmware.h > @@ -177,6 +177,49 @@ enum pm_query_id { > PM_QID_CLOCK_GET_MAX_DIVISOR = 13, > }; > > +enum pm_pinctrl_config_param { > + PM_PINCTRL_CONFIG_SLEW_RATE = 0, > + PM_PINCTRL_CONFIG_BIAS_STATUS = 1, > + PM_PINCTRL_CONFIG_PULL_CTRL = 2, > + PM_PINCTRL_CONFIG_SCHMITT_CMOS = 3, > + PM_PINCTRL_CONFIG_DRIVE_STRENGTH = 4, > + PM_PINCTRL_CONFIG_VOLTAGE_STATUS = 5, > + PM_PINCTRL_CONFIG_TRI_STATE = 6, > + PM_PINCTRL_CONFIG_MAX = 7, > +}; > + > +enum pm_pinctrl_slew_rate { > + PM_PINCTRL_SLEW_RATE_FAST = 0, > + PM_PINCTRL_SLEW_RATE_SLOW = 1, > +}; > + > +enum pm_pinctrl_bias_status { > + PM_PINCTRL_BIAS_DISABLE = 0, > + PM_PINCTRL_BIAS_ENABLE = 1, > +}; > + > +enum pm_pinctrl_pull_ctrl { > + PM_PINCTRL_BIAS_PULL_DOWN = 0, > + PM_PINCTRL_BIAS_PULL_UP = 1, > +}; > + > +enum pm_pinctrl_schmitt_cmos { > + PM_PINCTRL_INPUT_TYPE_CMOS = 0, > + PM_PINCTRL_INPUT_TYPE_SCHMITT = 1, > +}; > + > +enum pm_pinctrl_drive_strength { > + PM_PINCTRL_DRIVE_STRENGTH_2MA = 0, > + PM_PINCTRL_DRIVE_STRENGTH_4MA = 1, > + PM_PINCTRL_DRIVE_STRENGTH_8MA = 2, > + PM_PINCTRL_DRIVE_STRENGTH_12MA = 3, > +}; > + > +enum pm_pinctrl_tri_state { > + PM_PINCTRL_TRI_STATE_DISABLE = 0, > + PM_PINCTRL_TRI_STATE_ENABLE = 1, > +}; > + > enum zynqmp_pm_reset_action { > PM_RESET_ACTION_RELEASE = 0, > PM_RESET_ACTION_ASSERT = 1, > -- > 2.35.1 >
Applied. M -- Michal Simek, Ing. (M.Eng), OpenPGP -> KeyID: FE3D1F91 w: www.monstr.eu p: +42-0-721842854 Maintainer of Linux kernel - Xilinx Microblaze Maintainer of Linux kernel - Xilinx Zynq ARM and ZynqMP ARM64 SoCs U-Boot custodian - Xilinx Microblaze/Zynq/ZynqMP/Versal SoCs