RE: [PATCH 3/3] pinctrl: pinctrl-zynqmp: Add support for Versal platform

From: Buddhabhatti, Jay
Date: Thu Jul 11 2024 - 07:24:30 EST


Hi Sai,

>-----Original Message-----
>From: Sai Krishna Potthuri <sai.krishna.potthuri@xxxxxxx>
>Sent: Thursday, July 11, 2024 4:03 PM
>To: Linus Walleij <linus.walleij@xxxxxxxxxx>; Simek, Michal
><michal.simek@xxxxxxx>; Rob Herring <robh+dt@xxxxxxxxxx>; Krzysztof
>Kozlowski <krzysztof.kozlowski+dt@xxxxxxxxxx>; Conor Dooley
><conor+dt@xxxxxxxxxx>; Buddhabhatti, Jay <jay.buddhabhatti@xxxxxxx>;
>Dhaval Shah <dhaval.r.shah@xxxxxxx>; Kundanala, Praveen Teja
><praveen.teja.kundanala@xxxxxxx>; Greg Kroah-Hartman
><gregkh@xxxxxxxxxxxxxxxxxxx>
>Cc: linux-arm-kernel@xxxxxxxxxxxxxxxxxxx; linux-kernel@xxxxxxxxxxxxxxx; linux-
>gpio@xxxxxxxxxxxxxxx; devicetree@xxxxxxxxxxxxxxx; saikrishna12468@xxxxxxxxx;
>git (AMD-Xilinx) <git@xxxxxxx>; Potthuri, Sai Krishna
><sai.krishna.potthuri@xxxxxxx>
>Subject: [PATCH 3/3] pinctrl: pinctrl-zynqmp: Add support for Versal platform
>
>Add Pinctrl support for Xilinx Versal platform.
>Driver checks for firmware support to retrieve the Pin information, if it
>is supported then proceed further otherwise it returns error saying
>operation not supported. Latest Xilinx Platform Management Firmware must
>be used to make use of the Pinctrl driver for Versal platform.
>
>Signed-off-by: Sai Krishna Potthuri <sai.krishna.potthuri@xxxxxxx>
>---
> drivers/pinctrl/pinctrl-zynqmp.c | 91 ++++++++++++++++++++++++++++++--
> 1 file changed, 86 insertions(+), 5 deletions(-)
>
>diff --git a/drivers/pinctrl/pinctrl-zynqmp.c b/drivers/pinctrl/pinctrl-zynqmp.c
>index 3c6d56fdb8c9..e2cfd3d512e8 100644
>--- a/drivers/pinctrl/pinctrl-zynqmp.c
>+++ b/drivers/pinctrl/pinctrl-zynqmp.c
>@@ -10,6 +10,7 @@
>
> #include <dt-bindings/pinctrl/pinctrl-zynqmp.h>
>
>+#include <linux/bitfield.h>
> #include <linux/bitmap.h>
> #include <linux/init.h>
> #include <linux/module.h>
>@@ -44,6 +45,12 @@
> #define DRIVE_STRENGTH_8MA 8
> #define DRIVE_STRENGTH_12MA 12
>
>+#define VERSAL_LPD_PIN_PREFIX "LPD_MIO"
>+#define VERSAL_PMC_PIN_PREFIX "PMC_MIO"
>+
>+#define VERSAL_PINCTRL_ATTR_NODETYPE_MASK GENMASK(19, 14)
>+#define VERSAL_PINCTRL_NODETYPE_LPD_MIO BIT(0)
>+
> /**
> * struct zynqmp_pmux_function - a pinmux function
> * @name: Name of the pin mux function
>@@ -596,8 +603,12 @@ static int zynqmp_pinctrl_prepare_func_groups(struct
>device *dev, u32 fid,
> if (!groups[resp[i]].name)
> return -ENOMEM;
>
>- for (pin = 0; pin < groups[resp[i]].npins; pin++)
>- __set_bit(groups[resp[i]].pins[pin], used_pins);
>+ for (pin = 0; pin < groups[resp[i]].npins; pin++) {
>+ if (of_device_is_compatible(dev->of_node,
>"xlnx,zynqmp-pinctrl"))

Use zynqmp_pm_get_family_info() to distinguish ZynqMP or Versal platform instead of depending on compatible string.
Refer drivers/firmware/xilinx/zynqmp.c for more info.

>+ __set_bit(groups[resp[i]].pins[pin],
>used_pins);
>+ else
>+ __set_bit((u8)groups[resp[i]].pins[pin] -
>1, used_pins);
>+ }
> }
> }
> done:
>@@ -873,6 +884,70 @@ static int zynqmp_pinctrl_prepare_pin_desc(struct
>device *dev,
> return 0;
> }
>
>+static int versal_pinctrl_get_attributes(u32 pin_idx, u32 *response)
>+{
>+ struct zynqmp_pm_query_data qdata = {0};
>+ u32 payload[PAYLOAD_ARG_CNT];
>+ int ret;
>+
>+ qdata.qid = PM_QID_PINCTRL_GET_ATTRIBUTES;
>+ qdata.arg1 = pin_idx;
>+
>+ ret = zynqmp_pm_query_data(qdata, payload);
>+ if (ret)
>+ return ret;
>+
>+ memcpy(response, &payload[1], sizeof(*response));
>+
>+ return 0;
>+}
>+
>+static int versal_pinctrl_prepare_pin_desc(struct device *dev,
>+ const struct pinctrl_pin_desc
>**zynqmp_pins,
>+ unsigned int *npins)
>+{
>+ u32 lpd_mio_pins = 0, attr, nodetype;
>+ struct pinctrl_pin_desc *pins, *pin;
>+ int ret, i;
>+
>+ ret = zynqmp_pm_is_function_supported(PM_QUERY_DATA,
>PM_QID_PINCTRL_GET_ATTRIBUTES);
>+ if (ret)
>+ return ret;
>+
>+ ret = zynqmp_pinctrl_get_num_pins(npins);
>+ if (ret)
>+ return ret;
>+
>+ pins = devm_kzalloc(dev, sizeof(*pins) * *npins, GFP_KERNEL);
>+ if (!pins)
>+ return -ENOMEM;
>+
>+ for (i = 0; i < *npins; i++) {
>+ ret = versal_pinctrl_get_attributes(i, &attr);
>+ if (ret)
>+ return ret;
>+
>+ pin = &pins[i];
>+ pin->number = attr;
>+ nodetype =
>FIELD_GET(VERSAL_PINCTRL_ATTR_NODETYPE_MASK, attr);
>+ if (nodetype == VERSAL_PINCTRL_NODETYPE_LPD_MIO) {
>+ pin->name = devm_kasprintf(dev, GFP_KERNEL, "%s%d",
>+ VERSAL_LPD_PIN_PREFIX, i);
>+ lpd_mio_pins++;
>+ } else {
>+ pin->name = devm_kasprintf(dev, GFP_KERNEL, "%s%d",
>+ VERSAL_PMC_PIN_PREFIX, i -
>lpd_mio_pins);
>+ }
>+
>+ if (!pin->name)
>+ return -ENOMEM;
>+ }
>+
>+ *zynqmp_pins = pins;
>+
>+ return 0;
>+}
>+
> static int zynqmp_pinctrl_probe(struct platform_device *pdev)
> {
> struct zynqmp_pinctrl *pctrl;
>@@ -882,9 +957,14 @@ static int zynqmp_pinctrl_probe(struct platform_device
>*pdev)
> if (!pctrl)
> return -ENOMEM;
>
>- ret = zynqmp_pinctrl_prepare_pin_desc(&pdev->dev,
>- &zynqmp_desc.pins,
>- &zynqmp_desc.npins);
>+ if (of_device_is_compatible(pdev->dev.of_node, "xlnx,versal-pinctrl")) {

Same as above.

>+ ret = versal_pinctrl_prepare_pin_desc(&pdev->dev,
>&zynqmp_desc.pins,
>+ &zynqmp_desc.npins);
>+ } else {
>+ ret = zynqmp_pinctrl_prepare_pin_desc(&pdev->dev,
>&zynqmp_desc.pins,
>+ &zynqmp_desc.npins);
>+ }
>+
> if (ret) {
> dev_err(&pdev->dev, "pin desc prepare fail with %d\n", ret);
> return ret;
>@@ -907,6 +987,7 @@ static int zynqmp_pinctrl_probe(struct platform_device
>*pdev)
>
> static const struct of_device_id zynqmp_pinctrl_of_match[] = {
> { .compatible = "xlnx,zynqmp-pinctrl" },
>+ { .compatible = "xlnx,versal-pinctrl" },
> { }
> };
> MODULE_DEVICE_TABLE(of, zynqmp_pinctrl_of_match);
>--
>2.25.1