[PATCH v2] usb: phy: phy-generic: Fix USB PHY gpio reset

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Since commit e9f2cefb0cdc2ae ("usb: phy: generic: migrate to gpio_desc") a 
kernel hang is observed on imx51-babbage board:

[    1.392824] ci_hdrc ci_hdrc.1: doesn't support gadget
[    1.397975] ci_hdrc ci_hdrc.1: EHCI Host Controller
[    1.403205] ci_hdrc ci_hdrc.1: new USB bus registered, assigned bus number 1
[    1.422335] ci_hdrc ci_hdrc.1: USB 2.0 started, EHCI 1.00
[    1.432962] hub 1-0:1.0: USB hub found
[    1.437119] hub 1-0:1.0: 1 port detected

This hang happens because the reset GPIO stays at logic level 0.

The USB PHY reset gpio is defined in the dts file as:

reset-gpios = <&gpio2 5 GPIO_ACTIVE_LOW>;

, which means it is active low, so what the gpio reset pin needs to do in this
case is the following:

- Go to logic level 0 to reset the USB PHY
- Stay at 0 for a bit
- Go back to logic level 1

When switching to gpiod API we need to following according to 
Documentation/gpio/consumer.txt:

"The first thing a driver must do with a GPIO is setting its direction. If no
direction-setting flags have been given to gpiod_get*(), this is done by
invoking one of the gpiod_direction_*() functions:

	int gpiod_direction_input(struct gpio_desc *desc)
	int gpiod_direction_output(struct gpio_desc *desc, int value)"

Since no direction-setting flags have been given to devm_gpiod_get_optional()
in our case, we need to use gpiod_direction_output to comply with the gpiod API.

With this change the USB PHY reset performs a proper reset, the kernel boots
fine and USB host is functional.

Signed-off-by: Fabio Estevam <fabio.estevam@xxxxxxxxxxxxx>
---
Change since v1:
- Explain the need for using gpiod_direction_output()

 drivers/usb/phy/phy-generic.c | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/drivers/usb/phy/phy-generic.c b/drivers/usb/phy/phy-generic.c
index ef82711..433bf6d 100644
--- a/drivers/usb/phy/phy-generic.c
+++ b/drivers/usb/phy/phy-generic.c
@@ -63,11 +63,12 @@ static int nop_set_suspend(struct usb_phy *x, int suspend)
 
 static void nop_reset_set(struct usb_phy_generic *nop, int asserted)
 {
-	if (nop->gpiod_reset)
-		gpiod_set_value(nop->gpiod_reset, asserted);
+	if (!nop->gpiod_reset)
+		return;
 
-	if (!asserted)
-		usleep_range(10000, 20000);
+	gpiod_direction_output(nop->gpiod_reset, !asserted);
+	usleep_range(10000, 20000);
+	gpiod_set_value(nop->gpiod_reset, asserted);
 }
 
 /* interface to regulator framework */
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux