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