{"body":"From e36419633aeab12a570bc8d4b40e1bf63a745be3 Mon Sep 17 00:00:00 2001\nFrom: Dennis Gilmore <dennis@ausil.us>\nDate: Wed, 19 Aug 2026 11:52:39 -0500\nSubject: [PATCH 6/7] pinctrl: rockchip: implement gpio_request_enable; fix\n rk3588 pcie2x1l2 hang\n\nThe rk3588s-orangepi-5-pro devicetree routes the pcie2x1l2 controller's\nPERST# pin (GPIO3_PD1) two ways at once: the pinctrl \"default\" state\nmuxes it to the controller's dedicated hardware PERST# function\n(pcie20x1m0_perstn), while pcie_dw_rockchip.c also requests the same\npin via reset-gpios and bit-bangs it directly as a GPIO.\n\nU-Boot's DM pinctrl framework applies the \"default\" state automatically\nat probe and has no mechanism to give a consumer driver's later GPIO\nrequest priority over it. As a result the pad stays muxed to the\nhardware PERST# function throughout, and the driver's GPIO writes never\nreach the pin. With nothing actually driving PERST#, the controller's\ninternal PERST# gating logic never releases, and the very first DBI\nregister access on pcie2x1l2 (the Motorcomm YT6801 NIC's root port)\nhangs forever - pci enum on this port hangs silently with no error and\nno timeout.\n\nLinux does not have this problem because gpiod_get() in gpiolib always\nreclaims a requested pin back to GPIO function regardless of what the\n\"default\" pinctrl state selected for it. This same devicetree already\nworks correctly under Linux for exactly that reason, and per the\nproject's \"u-boot and linux dtbs must be the same\" requirement, the\ndevicetree itself must not change - the fix belongs in the pinctrl\ndriver.\n\nAdd support for rockchip_pinctrl_ops.gpio_request_enable, wired up via\nthe existing generic pinctrl_gpio_request() (which U-Boot already had,\nunused by any Rockchip driver) so that a consumer requesting a pin as\na GPIO explicitly forces it to the plain GPIO function, exactly\nmirroring what Linux's gpiolib does. Call it from\npcie_dw_rockchip.c's reset-gpios setup, matching the point in the\ndriver where the pin is first claimed.\n\nWith this fix, both the pcie2x1l1 (NVMe) and pcie2x1l2 (Motorcomm NIC)\nroot ports come up correctly. Confirmed on real Orange Pi 5 Pro\nhardware.\n\nSigned-off-by: Dennis Gilmore <dennis@ausil.us>\n---\n drivers/pci/pcie_dw_rockchip.c                | 21 ++++++++++++\n .../pinctrl/rockchip/pinctrl-rockchip-core.c  | 34 +++++++++++++++++++\n 2 files changed, 55 insertions(+)\n\ndiff --git a/drivers/pci/pcie_dw_rockchip.c b/drivers/pci/pcie_dw_rockchip.c\nindex eb4b7d4d64b..8e769e33533 100644\n--- a/drivers/pci/pcie_dw_rockchip.c\n+++ b/drivers/pci/pcie_dw_rockchip.c\n@@ -16,6 +16,7 @@\n #include <asm/io.h>\n #include <asm-generic/gpio.h>\n #include <dm/device_compat.h>\n+#include <dm/pinctrl.h>\n #include <linux/bitfield.h>\n #include <linux/iopoll.h>\n #include <linux/delay.h>\n@@ -416,6 +417,26 @@ static int rockchip_pcie_parse_dt(struct udevice *dev)\n \t\treturn ret;\n \t}\n \n+\t/*\n+\t * The reset-gpios pin may also be routed to this controller's\n+\t * dedicated hardware PERST# function by the \"default\" pinctrl\n+\t * state (e.g. pcie20x1m0_perstn), rather than left as plain GPIO.\n+\t * On some instances, leaving the pin in that dedicated function\n+\t * while this driver bit-bangs it as a GPIO leaves the pad stuck\n+\t * in hardware-PERST# mode with nothing driving it, which has been\n+\t * observed to wedge the controller's own DBI/AXI interface.\n+\t * Explicitly force the pin to GPIO function, mirroring what\n+\t * Linux's gpiolib does automatically when a driver requests a pin\n+\t * as a GPIO. Not fatal if the pinctrl driver doesn't support this\n+\t * (-ENOSYS) or the pin has no dedicated alternate function to\n+\t * begin with.\n+\t */\n+\tret = pinctrl_gpio_request(priv->rst_gpio.dev, priv->rst_gpio.offset,\n+\t\t\t\t   \"pcie-reset\");\n+\tif (ret && ret != -ENOSYS)\n+\t\tdev_warn(dev, \"failed to force reset-gpios to GPIO function (ret=%d)\\n\",\n+\t\t\t ret);\n+\n \tret = reset_get_bulk(dev, &priv->rsts);\n \tif (ret) {\n \t\tdev_err(dev, \"Can't get reset: %d\\n\", ret);\ndiff --git a/drivers/pinctrl/rockchip/pinctrl-rockchip-core.c b/drivers/pinctrl/rockchip/pinctrl-rockchip-core.c\nindex 957dcb52059..836dda9ce5d 100644\n--- a/drivers/pinctrl/rockchip/pinctrl-rockchip-core.c\n+++ b/drivers/pinctrl/rockchip/pinctrl-rockchip-core.c\n@@ -445,6 +445,39 @@ static int rockchip_pinconf_prop_name_to_param(const char *property,\n \treturn -EPERM;\n }\n \n+/**\n+ * rockchip_pinctrl_gpio_request_enable() - switch a pin to GPIO function\n+ *\n+ * Called via pinctrl_gpio_request() when a consumer explicitly requests a\n+ * pin as a GPIO, mirroring Linux's gpiolib/pinctrl behaviour where a GPIO\n+ * request overrides whatever function a \"default\" pinctrl state selected\n+ * for that pin. Some pins are dual-routed to both a plain GPIO function\n+ * and a peripheral's dedicated hardware function (e.g. a PCIe PERST#\n+ * pin); if the \"default\" state selects the dedicated function but a\n+ * driver still wants to bit-bang the pin manually via the GPIO uclass,\n+ * without this the pin never actually leaves the dedicated function and\n+ * the GPIO writes have no effect on the pad.\n+ *\n+ * @selector: global pin number (bank * pins-per-bank + pin), as resolved\n+ *\t      by the generic pinctrl_gpio_request() via the device's\n+ *\t      \"gpio-ranges\" property.\n+ */\n+static int rockchip_pinctrl_gpio_request_enable(struct udevice *dev,\n+\t\t\t\t\t\tunsigned int selector)\n+{\n+\tstruct rockchip_pinctrl_priv *priv = dev_get_priv(dev);\n+\tstruct rockchip_pin_ctrl *ctrl = priv->ctrl;\n+\tu32 bank = selector / MAX_ROCKCHIP_GPIO_PER_BANK;\n+\tu32 pin = selector % MAX_ROCKCHIP_GPIO_PER_BANK;\n+\tint ret;\n+\n+\tret = rockchip_verify_config(dev, bank, pin);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\treturn rockchip_set_mux(&ctrl->pin_banks[bank], pin, RK_FUNC_GPIO);\n+}\n+\n static int rockchip_pinctrl_set_state(struct udevice *dev,\n \t\t\t\t      struct udevice *config)\n {\n@@ -523,6 +556,7 @@ static int rockchip_pinctrl_set_state(struct udevice *dev,\n const struct pinctrl_ops rockchip_pinctrl_ops = {\n \t.set_state\t\t\t= rockchip_pinctrl_set_state,\n \t.get_gpio_mux\t\t\t= rockchip_pinctrl_get_gpio_mux,\n+\t.gpio_request_enable\t\t= rockchip_pinctrl_gpio_request_enable,\n };\n \n /* retrieve the soc specific data */\n-- \n2.55.0\n","name":"","extension":"txt","url":"https://www.irccloud.com/pastebin/5rp6hAKt","modified":1790872982,"id":"5rp6hAKt","size":6132,"lines":141,"own_paste":false,"theme":"","date":1790872982}