pinctrl: msm: fix gpio-hog related boot issues
Subsystems (7)
PATCH 1/1 pinctrl: msm: fix gpio-hog related boot issues
Sven Eckelmann reported an issue with the current IPQ4019 pinctrl. Setting up any gpio-hog in the device-tree for his device would "kill the bootup completely":
| [ 0.477838] msm_serial 78af000.serial: could not find pctldev for node /soc/pinctrl at 1000000/serial_pinmux, deferring probe | [ 0.499828] spi_qup 78b5000.spi: could not find pctldev for node /soc/pinctrl at 1000000/spi_0_pinmux, deferring probe | [ 1.298883] requesting hog GPIO enable USB2 power (chip 1000000.pinctrl, offset 58) failed, -517 | [ 1.299609] gpiochip_add_data: GPIOs 0..99 (1000000.pinctrl) failed to register | [ 1.308589] ipq4019-pinctrl 1000000.pinctrl: Failed register gpiochip | [ 1.316586] msm_serial 78af000.serial: could not find pctldev for node /soc/pinctrl at 1000000/serial_pinmux, deferring probe | [ 1.322415] spi_qup 78b5000.spi: could not find pctldev for node /soc/pinctrl at 1000000/spi_0_pinmux, deferri
This was also verified on a RT-AC58U (IPQ4018) which would no longer boot, if a gpio-hog was specified. (Tried forcing the USB LED PIN (GPIO0) to high.).
The problem is that Pinctrl+GPIO registration is currently peformed in the following order in pinctrl-msm.c:
1. pinctrl_register()
2. gpiochip_add()
3. gpiochip_add_pin_range()
The actual error code -517 == -EPROBE_DEFER is coming from pinctrl_get_device_gpio_range(), which is called through:
gpiochip_add
of_gpiochip_add
of_gpiochip_scan_gpios
gpiod_hog
gpiochip_request_own_desc
__gpiod_request
chip->request
gpiochip_generic_request
pinctrl_gpio_request
pinctrl_get_device_gpio_rangepinctrl_get_device_gpio_range() is unable to find any valid pin ranges, since nothing has been added to the pinctrldev_list yet. so the range can't be found, and the operation fails with -EPROBE_DEFER.
This patch fixes the issue by adding the "gpio-ranges" property to the pinctrl device node of all upstream Qcom SoC, so the ranges are added by of_gpiochip_add_pin_range(), which is called by of_gpiochip_add() before the call to of_gpiochip_scan_gpios() happens.gpiochip_add_pin_range() is longer needed and removed (to prevent adding the same entry to the pinctrldev_list twice).
---
The msm8998 would need something like
gpio-ranges = <&tlmm 0 0 150>; --- arch/arm/boot/dts/qcom-apq8064.dtsi | 1 + arch/arm/boot/dts/qcom-apq8084.dtsi | 1 + arch/arm/boot/dts/qcom-ipq4019.dtsi | 1 + arch/arm/boot/dts/qcom-ipq8064.dtsi | 1 + arch/arm/boot/dts/qcom-mdm9615.dtsi | 1 + arch/arm/boot/dts/qcom-msm8660.dtsi | 1 + arch/arm/boot/dts/qcom-msm8960.dtsi | 1 + arch/arm/boot/dts/qcom-msm8974.dtsi | 1 + arch/arm64/boot/dts/qcom/ipq8074.dtsi | 3 ++- arch/arm64/boot/dts/qcom/msm8916.dtsi | 1 + arch/arm64/boot/dts/qcom/msm8992.dtsi | 1 + arch/arm64/boot/dts/qcom/msm8994.dtsi | 1 + arch/arm64/boot/dts/qcom/msm8996.dtsi | 1 + drivers/pinctrl/qcom/pinctrl-msm.c | 7 ------- 14 files changed, 14 insertions(+), 8 deletions(-)
arch/arm/boot/dts/qcom-apq8064.dtsi +1 -0
@@ -327,6 +327,7 @@ reg = <0x800000 0x4000>; gpio-controller; + gpio-ranges = <&tlmm_pinmux 0 0 90>; #gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>;
arch/arm/boot/dts/qcom-apq8084.dtsi +1 -0
@@ -396,6 +396,7 @@ compatible = "qcom,apq8084-pinctrl"; reg = <0xfd510000 0x4000>; gpio-controller; + gpio-ranges = <&tlmm 0 0 147>; #gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>;
arch/arm/boot/dts/qcom-ipq4019.dtsi +1 -0
@@ -147,6 +147,7 @@ compatible = "qcom,ipq4019-pinctrl"; reg = <0x01000000 0x300000>; gpio-controller; + gpio-ranges = <&tlmm 0 0 100>; #gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>;
arch/arm/boot/dts/qcom-ipq8064.dtsi +1 -0
@@ -108,6 +108,7 @@ reg = <0x800000 0x4000>; gpio-controller; + gpio-ranges = <&qcom_pinmux 0 0 69>; #gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>;
arch/arm/boot/dts/qcom-mdm9615.dtsi +1 -0
@@ -128,6 +128,7 @@ msmgpio: pinctrl at 800000 { compatible = "qcom,mdm9615-pinctrl"; gpio-controller; + gpio-ranges = <&msmgpio 0 0 88>; #gpio-cells = <2>; interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>; interrupt-controller;
arch/arm/boot/dts/qcom-msm8660.dtsi +1 -0
@@ -110,6 +110,7 @@ reg = <0x800000 0x4000>; gpio-controller; + gpio-ranges = <&tlmm 0 0 173>; #gpio-cells = <2>; interrupts = <0 16 0x4>; interrupt-controller;
arch/arm/boot/dts/qcom-msm8960.dtsi +1 -0
@@ -102,6 +102,7 @@ msmgpio: pinctrl at 800000 { compatible = "qcom,msm8960-pinctrl"; gpio-controller; + gpio-ranges = <&msmgpio 0 0 152>; #gpio-cells = <2>; interrupts = <0 16 0x4>; interrupt-controller;
arch/arm/boot/dts/qcom-msm8974.dtsi +1 -0
@@ -696,6 +696,7 @@ compatible = "qcom,msm8974-pinctrl"; reg = <0xfd510000 0x4000>; gpio-controller; + gpio-ranges = <&msmgpio 0 0 146>; #gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>;
arch/arm64/boot/dts/qcom/ipq8074.dtsi +2 -1
@@ -24,11 +24,12 @@ ranges = <0 0 0 0xffffffff>; compatible = "simple-bus"; - pinctrl at 1000000 { + tlmm: pinctrl at 1000000 { compatible = "qcom,ipq8074-pinctrl"; reg = <0x1000000 0x300000>; interrupts = <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>; gpio-controller; + gpio-ranges = <&tlmm 0 0 70>; #gpio-cells = <0x2>; interrupt-controller; #interrupt-cells = <0x2>;
arch/arm64/boot/dts/qcom/msm8916.dtsi +1 -0
@@ -281,6 +281,7 @@ reg = <0x1000000 0x300000>; interrupts = <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>; gpio-controller; + gpio-ranges = <&msmgpio 0 0 122>; #gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>;
arch/arm64/boot/dts/qcom/msm8992.dtsi +1 -0
@@ -179,6 +179,7 @@ reg = <0xfd510000 0x4000>; interrupts = <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>; gpio-controller; + gpio-ranges = <&msmgpio 0 0 146>; #gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>;
arch/arm64/boot/dts/qcom/msm8994.dtsi +1 -0
@@ -141,6 +141,7 @@ reg = <0xfd510000 0x4000>; interrupts = <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>; gpio-controller; + gpio-ranges = <&msmgpio 0 0 146>; #gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>;
arch/arm64/boot/dts/qcom/msm8996.dtsi +1 -0
@@ -530,6 +530,7 @@ reg = <0x01010000 0x300000>; interrupts = <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>; gpio-controller; + gpio-ranges = <&msmgpio 0 0 150>; #gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>;
drivers/pinctrl/qcom/pinctrl-msm.c +0 -7
@@ -831,13 +831,6 @@ static int msm_gpio_init(struct msm_pinctrl *pctrl)return ret; } - ret =gpiochip_add_pin_range (&pctrl->chip,dev_name (pctrl->dev),0 ,0 , chip->ngpio); -if (ret) { -dev_err (pctrl->dev,"Failed to add pin range\n" ); -gpiochip_remove (&pctrl->chip); -return ret; - } - ret = gpiochip_irqchip_add(chip, &msm_gpio_irq_chip, 0,
Signature · 1 line
2.16.3
PATCH 1/1 pinctrl: msm: fix gpio-hog related boot issues
Quoted 12 lines · Christian Lamparter
Sven Eckelmann reported an issue with the current IPQ4019 pinctrl. Setting up any gpio-hog in the device-tree for his device would "kill the bootup completely":
| [ 0.477838] msm_serial 78af000.serial: could not find pctldev for node /soc/pinctrl at 1000000/serial_pinmux, deferring probe | [ 0.499828] spi_qup 78b5000.spi: could not find pctldev for node /soc/pinctrl at 1000000/spi_0_pinmux, deferring probe | [ 1.298883] requesting hog GPIO enable USB2 power (chip 1000000.pinctrl, offset 58) failed, -517 | [ 1.299609] gpiochip_add_data: GPIOs 0..99 (1000000.pinctrl) failed to register | [ 1.308589] ipq4019-pinctrl 1000000.pinctrl: Failed register gpiochip | [ 1.316586] msm_serial 78af000.serial: could not find pctldev for node /soc/pinctrl at 1000000/serial_pinmux, deferring probe | [ 1.322415] spi_qup 78b5000.spi: could not find pctldev for node /soc/pinctrl at 1000000/spi_0_pinmux, deferri
Quoted 4 lines
This was also verified on a RT-AC58U (IPQ4018) which would no longer boot, if a gpio-hog was specified. (Tried forcing the USB LED PIN (GPIO0) to high.).
It's quite clear that this is a generic issue with the msm pinctrl driver.
For the cases where I've been in need of static configuration of certain pins I've simply made the pinctrl node itself have a pinctrl-0 that refer to a state that I want to hold. This has worked well and I didn't even know about the gpio-hog property.
[..]
arch/arm/boot/dts/qcom-apq8064.dtsi line 330
Quoted 9 lines
arch/arm/boot/dts/qcom-apq8064.dtsi +1
-0@@ -327,6 +327,7 @@ reg = <0x800000 0x4000>; gpio-controller; + gpio-ranges = <&tlmm_pinmux 0 0 90>;
This seems reasonable.
Quoted 3 lines
arch/arm/boot/dts/qcom-apq8064.dtsi +0
-0#gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>;
[..]
Quoted 5 lines
drivers/pinctrl/qcom/pinctrl-msm.c +0
-0
drivers/pinctrl/qcom/pinctrl-msm.c static int msm_gpio_init(struct msm_pinctrl *pctrl) · line 840
Quoted 10 lines
drivers/pinctrl/qcom/pinctrl-msm.c +0
-7@@ -831,13 +831,6 @@ static int msm_gpio_init(struct msm_pinctrl *pctrl)return ret; } - ret =gpiochip_add_pin_range (&pctrl->chip,dev_name (pctrl->dev),0 ,0 , chip->ngpio); -if (ret) { -dev_err (pctrl->dev,"Failed to add pin range\n" ); -gpiochip_remove (&pctrl->chip); -return ret; - } -
But, this will break backwards compatibility with existing DTBs and I don't see how this would work with the ACPI based platforms using this driver.
Iirc this driver follows the same pattern as several other pinctrl drivers providing gpios, how are they handling this?
Regards,
Bjorn
PATCH 1/1 pinctrl: msm: fix gpio-hog related boot issues
Quoted 14 lines · On Thu 29 Mar 2018 02:27:23 CEST Bjorn Andersson wrote:
Quoted 12 lines · Christian Lamparter
Sven Eckelmann reported an issue with the current IPQ4019 pinctrl. Setting up any gpio-hog in the device-tree for his device would "kill the bootup completely":
| [ 0.477838] msm_serial 78af000.serial: could not find pctldev for node /soc/pinctrl at 1000000/serial_pinmux, deferring probe | [ 0.499828] spi_qup 78b5000.spi: could not find pctldev for node /soc/pinctrl at 1000000/spi_0_pinmux, deferring probe | [ 1.298883] requesting hog GPIO enable USB2 power (chip 1000000.pinctrl, offset 58) failed, -517 | [ 1.299609] gpiochip_add_data: GPIOs 0..99 (1000000.pinctrl) failed to register | [ 1.308589] ipq4019-pinctrl 1000000.pinctrl: Failed register gpiochip | [ 1.316586] msm_serial 78af000.serial: could not find pctldev for node /soc/pinctrl at 1000000/serial_pinmux, deferring probe | [ 1.322415] spi_qup 78b5000.spi: could not find pctldev for node /soc/pinctrl at 1000000/spi_0_pinmux, deferri
Quoted 8 lines
Quoted 4 lines
This was also verified on a RT-AC58U (IPQ4018) which would no longer boot, if a gpio-hog was specified. (Tried forcing the USB LED PIN (GPIO0) to high.).
It's quite clear that this is a generic issue with the msm pinctrl driver.
From what I understand it's not only the msm-pinctrl. All pinctrl and gpio
drivers that support a DT binding but use gpiochip_add_pin_range as the sole way to add the ranges. I made a (probably incomplete) list in the thread by Sven: <https://lkml.kernel.org/r/46130418.GjRpGRXmAF@debian64>
Quoted 4 lines
For the cases where I've been in need of static configuration of certain pins I've simply made the pinctrl node itself have a pinctrl-0 that refer to a state that I want to hold. This has worked well and I didn't even know about the gpio-hog property.
yes, that will work too.
One advantage of the gpio-hog is that it will also request the gpio properly. So it cannot be exported (and changed) without getting rid of the gpio-hog first. It also allows to specify a user-friendly line-name that shows up in various places.
i.e.:
|root at mbl:/# cat /sys/kernel/debug/gpio |gpiochip1: GPIOs 472-479, parent: platform/4e0000000.gpio1, 4e0000000.gpio1: | gpio-472 ( |enable EMAC PHY ) out hi | gpio-475 ( |Power Drive Port 1 ) out hi |
Quoted 25 lines
[..]
arch/arm/boot/dts/qcom-apq8064.dtsi line 330
Quoted 9 lines
arch/arm/boot/dts/qcom-apq8064.dtsi +1
-0@@ -327,6 +327,7 @@ reg = <0x800000 0x4000>; gpio-controller; + gpio-ranges = <&tlmm_pinmux 0 0 90>;This seems reasonable.
Quoted 3 lines
arch/arm/boot/dts/qcom-apq8064.dtsi +0
-0#gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>;[..]
Quoted 8 lines
drivers/pinctrl/qcom/pinctrl-msm.c +0
-0@@ -831,13 +831,6 @@ static int msm_gpio_init(struct msm_pinctrl *pctrl)return ret; }
Quoted 11 lines
drivers/pinctrl/qcom/pinctrl-msm.c static int msm_gpio_init(struct msm_pinctrl *pctrl) · line 840
Quoted 7 lines
drivers/pinctrl/qcom/pinctrl-msm.c +0
-7- ret =gpiochip_add_pin_range (&pctrl->chip,dev_name (pctrl->dev),0 ,0 , chip->ngpio); -if (ret) { -dev_err (pctrl->dev,"Failed to add pin range\n" ); -gpiochip_remove (&pctrl->chip); -return ret; - } -But, this will break backwards compatibility with existing DTBs and I don't see how this would work with the ACPI based platforms using this driver.
Ok I see, I was aware of ACPI but not that a pinctrl-msm based driver is using it. Well, I thinks is possible to use is_acpi_device_node() or !is_of_node() to detect whenever we are dealing with a OF or not:
would it be ok to do something like this?
| if (!is_of_node(chip->of_node)) {
| /*
| * (lengthy note about gpiochip_add_pin_range and OF with
| * reference to Documentation/devicetree/bindings/gpio/gpio.txt
| * - TBD)
| */
| ret = gpiochip_add_pin_range(&pctrl->chip,
| [...]
| }Quoted 2 lines
Iirc this driver follows the same pattern as several other pinctrl drivers providing gpios, how are they handling this?
Well, my commit message was based on a similar patch done by Geert Uytterhoeven <[email protected]> for the sh73a0:
<https://marc.info/?l=git-commits-head&m=144114029919118&w=2>
Another one was this patch from Linus:
<https://patches.linaro.org/patch/51382/>
and there are many more (basically git blame on every .dts* in arch/ that already has a gpio-ranges property.)
Regards,
Christian
PATCH 1/1 pinctrl: msm: fix gpio-hog related boot issues
Quoted 7 lines · On Thu 29 Mar 2018 14:23:35 CEST Christian Lamparter wrote:
Ok I see, I was aware of ACPI but not that a pinctrl-msm based driver is using it. Well, I thinks is possible to use
is_acpi_device_node()or !is_of_node() to detect whenever we are dealing with a OF or not:would it be ok to do something like this?
| if (!is_of_node(chip->of_node)) {
oops, this should be:
if (!is_of_node(pctrl->dev->fwnode)) {Quoted 8 lines
| /* | * (lengthy note about gpiochip_add_pin_range and OF with | * reference to Documentation/devicetree/bindings/gpio/gpio.txt | * - TBD) | */ | ret = gpiochip_add_pin_range(&pctrl->chip, | [...] | }
PATCH 1/1 pinctrl: msm: fix gpio-hog related boot issues
In reply to Christian LamparterQuoted 7 lines · Christian Lamparter
This patch fixes the issue by adding the "gpio-ranges" property to the pinctrl device node of all upstream Qcom SoC, so the ranges are added by
of_gpiochip_add_pin_range(), which is called byof_gpiochip_add()before the call toof_gpiochip_scan_gpios()happens.gpiochip_add_pin_range()is longer needed and removed (to prevent adding the same entry to thepinctrldev_listtwice).
That's pretty neat!
Quoted 2 lines
gpio-controller;+ gpio-ranges = <
&tlmm_pinmux0 0 90>;
nice!
drivers/pinctrl/qcom/pinctrl-msm.c static int msm_gpio_init(struct msm_pinctrl *pctrl) · line 839
Quoted 6 lines
drivers/pinctrl/qcom/pinctrl-msm.c +0
-6- ret =gpiochip_add_pin_range (&pctrl->chip,dev_name (pctrl->dev),0 ,0 , chip->ngpio); -if (ret) { -dev_err (pctrl->dev,"Failed to add pin range\n" ); -gpiochip_remove (&pctrl->chip); -return ret; - }
If you instead of deleteing this, just wrap it inside something like:
if (!of_property_read_bool(np, "gpio-ranges") {
(...)
}
You will stay compatible with elder device trees, solving Bj?rns issue. You will only be adding hogs to newer device trees with the ranges defined anyway.
Be genereous with comments in the code if you choose this approach so everyone realize what is going on.
Yours,
Linus Walleij
PATCH 1/1 pinctrl: msm: fix gpio-hog related boot issues
Quoted 16 lines · On Donnerstag, 12. April 2018 14:48:56 CEST Linus Walleij wrote:
drivers/pinctrl/qcom/pinctrl-msm.c static int msm_gpio_init(struct msm_pinctrl *pctrl) · line 839
Quoted 6 lines · Christian Lamparter
drivers/pinctrl/qcom/pinctrl-msm.c +0
-6- ret =gpiochip_add_pin_range (&pctrl->chip,dev_name (pctrl->dev),0 ,0 , chip->ngpio); -if (ret) { -dev_err (pctrl->dev,"Failed to add pin range\n" ); -gpiochip_remove (&pctrl->chip); -return ret; - }If you instead of deleteing this, just wrap it inside something like:
if (!of_property_read_bool(np, "gpio-ranges") {
(...)
}
Quoted 6 lines
You will stay compatible with elder device trees, solving Bj?rns issue. You will only be adding hogs to newer device trees with the ranges defined anyway.
Be genereous with comments in the code if you choose this approach so everyone realize what is going on.
Thank you for your insightful advice. I just sent out v4 which goes the of_property_read_bool route. Let's wait and see what kbuilt-bot has to say.
Best Regards,
Christian