[U-Boot] [PATCH 1/3] sunxi: usb-phy: Never power off the usb ports

USB devices are not really designed to get the power bounced off and on at them. Esp. USB powered harddisks do not like this.
Currently we power off the USB ports both on a "usb reset" and when booting the kernel, causing the usb-power to bounce off and then back on again.
This patch removes the powering off calls, fixing the undesirable power bouncing.
Note this requires some special handling for the OTG port: 1) We must skip the external vbus check if we've already enabled our own vbus to avoid false positives 2) If on an usb reset we no longer detect that the id-pin is grounded, turn off vbus as that means an external vbus may be present now
Signed-off-by: Hans de Goede hdegoede@redhat.com --- Changes in v2: -Skip the vbus detect for the otg port if we've already turned the power on, otherwise we get a false positive for having an external vbus and the otg port is not usable after an usb reset --- arch/arm/cpu/armv7/sunxi/usb_phy.c | 7 +++++++ arch/arm/include/asm/arch-sunxi/usb_phy.h | 1 + drivers/usb/host/ehci-sunxi.c | 1 - drivers/usb/host/ohci-sunxi.c | 1 - drivers/usb/musb-new/sunxi.c | 28 ++++++++++++++++------------ 5 files changed, 24 insertions(+), 14 deletions(-)
diff --git a/arch/arm/cpu/armv7/sunxi/usb_phy.c b/arch/arm/cpu/armv7/sunxi/usb_phy.c index 4d63a74..b7ca5d4 100644 --- a/arch/arm/cpu/armv7/sunxi/usb_phy.c +++ b/arch/arm/cpu/armv7/sunxi/usb_phy.c @@ -232,6 +232,13 @@ void sunxi_usb_phy_power_off(int index) gpio_set_value(phy->gpio_vbus, 0); }
+int sunxi_usb_phy_power_is_on(int index) +{ + struct sunxi_usb_phy *phy = &sunxi_usb_phy[index]; + + return phy->power_on_count > 0; +} + int sunxi_usb_phy_vbus_detect(int index) { struct sunxi_usb_phy *phy = &sunxi_usb_phy[index]; diff --git a/arch/arm/include/asm/arch-sunxi/usb_phy.h b/arch/arm/include/asm/arch-sunxi/usb_phy.h index cef6c98..6a14cad 100644 --- a/arch/arm/include/asm/arch-sunxi/usb_phy.h +++ b/arch/arm/include/asm/arch-sunxi/usb_phy.h @@ -16,6 +16,7 @@ void sunxi_usb_phy_init(int index); void sunxi_usb_phy_exit(int index); void sunxi_usb_phy_power_on(int index); void sunxi_usb_phy_power_off(int index); +int sunxi_usb_phy_power_is_on(int index); int sunxi_usb_phy_vbus_detect(int index); int sunxi_usb_phy_id_detect(int index); void sunxi_usb_phy_enable_squelch_detect(int index, int enable); diff --git a/drivers/usb/host/ehci-sunxi.c b/drivers/usb/host/ehci-sunxi.c index 34130f8..38d5f92 100644 --- a/drivers/usb/host/ehci-sunxi.c +++ b/drivers/usb/host/ehci-sunxi.c @@ -67,7 +67,6 @@ static int ehci_usb_remove(struct udevice *dev) if (ret) return ret;
- sunxi_usb_phy_power_off(priv->phy_index); sunxi_usb_phy_exit(priv->phy_index);
#ifdef CONFIG_SUNXI_GEN_SUN6I diff --git a/drivers/usb/host/ohci-sunxi.c b/drivers/usb/host/ohci-sunxi.c index e33a8f7..6079272 100644 --- a/drivers/usb/host/ohci-sunxi.c +++ b/drivers/usb/host/ohci-sunxi.c @@ -69,7 +69,6 @@ static int ohci_usb_remove(struct udevice *dev) if (ret) return ret;
- sunxi_usb_phy_power_off(priv->phy_index); sunxi_usb_phy_exit(priv->phy_index);
#ifdef CONFIG_SUNXI_GEN_SUN6I diff --git a/drivers/usb/musb-new/sunxi.c b/drivers/usb/musb-new/sunxi.c index 16a264a..a146c08 100644 --- a/drivers/usb/musb-new/sunxi.c +++ b/drivers/usb/musb-new/sunxi.c @@ -196,8 +196,6 @@ static bool enabled = false;
static int sunxi_musb_enable(struct musb *musb) { - int ret; - pr_debug("%s():\n", __func__);
musb_ep_select(musb->mregs, 0); @@ -210,17 +208,26 @@ static int sunxi_musb_enable(struct musb *musb) musb_writeb(musb->mregs, USBC_REG_o_VEND0, 0);
if (is_host_enabled(musb)) { - ret = sunxi_usb_phy_vbus_detect(0); - if (ret == 1) { - printf("A charger is plugged into the OTG: "); - return -ENODEV; + int id = sunxi_usb_phy_id_detect(0); + + if (id == 1 && sunxi_usb_phy_power_is_on(0)) + sunxi_usb_phy_power_off(0); + + if (!sunxi_usb_phy_power_is_on(0)) { + int vbus = sunxi_usb_phy_vbus_detect(0); + if (vbus == 1) { + printf("A charger is plugged into the OTG: "); + return -ENODEV; + } } - ret = sunxi_usb_phy_id_detect(0); - if (ret == 1) { + + if (id == 1) { printf("No host cable detected: "); return -ENODEV; } - sunxi_usb_phy_power_on(0); /* port power on */ + + if (!sunxi_usb_phy_power_is_on(0)) + sunxi_usb_phy_power_on(0); }
USBC_ForceVbusValidToHigh(musb->mregs); @@ -236,9 +243,6 @@ static void sunxi_musb_disable(struct musb *musb) if (!enabled) return;
- if (is_host_enabled(musb)) - sunxi_usb_phy_power_off(0); /* port power off */ - USBC_ForceVbusValidToLow(musb->mregs); mdelay(200); /* Wait for the current session to timeout */

Now that we have code to check the id-pin and detect usb-host adapters plugged into the otg port that way, enable it on the tablets which I own.
Signed-off-by: Hans de Goede hdegoede@redhat.com --- configs/Chuwi_V7_CW0825_defconfig | 1 + configs/UTOO_P66_defconfig | 1 + 2 files changed, 2 insertions(+)
diff --git a/configs/Chuwi_V7_CW0825_defconfig b/configs/Chuwi_V7_CW0825_defconfig index 4011351..f44aede 100644 --- a/configs/Chuwi_V7_CW0825_defconfig +++ b/configs/Chuwi_V7_CW0825_defconfig @@ -5,6 +5,7 @@ CONFIG_DRAM_CLK=408 CONFIG_DRAM_EMR1=4 CONFIG_USB0_VBUS_PIN="PB9" CONFIG_USB0_VBUS_DET="PH5" +CONFIG_USB0_ID_DET="PH4" CONFIG_VIDEO_LCD_MODE="x:1024,y:768,depth:24,pclk_khz:51000,le:19,ri:300,up:6,lo:31,hs:1,vs:1,sync:3,vmode:0" CONFIG_VIDEO_LCD_POWER="PH8" CONFIG_VIDEO_LCD_BL_EN="PH7" diff --git a/configs/UTOO_P66_defconfig b/configs/UTOO_P66_defconfig index 0266299..169c2e8 100644 --- a/configs/UTOO_P66_defconfig +++ b/configs/UTOO_P66_defconfig @@ -7,6 +7,7 @@ CONFIG_MMC0_CD_PIN="PG0" CONFIG_MMC_SUNXI_SLOT_EXTRA=2 CONFIG_USB0_VBUS_PIN="PB04" CONFIG_USB0_VBUS_DET="PG01" +CONFIG_USB0_ID_DET="PG2" CONFIG_AXP_GPIO=y CONFIG_VIDEO_LCD_MODE="x:480,y:800,depth:18,pclk_khz:25000,le:2,ri:93,up:2,lo:93,hs:1,vs:1,sync:3,vmode:0" CONFIG_VIDEO_LCD_DCLK_PHASE=0

On Sat, 2015-08-01 at 14:50 +0200, Hans de Goede wrote:
Now that we have code to check the id-pin and detect usb-host adapters plugged into the otg port that way, enable it on the tablets which I own.
Signed-off-by: Hans de Goede hdegoede@redhat.com
Acked-by: Ian Campbell ijc@hellion.org.uk

Do not add a bogus (pointing to a non existing serial port) stdout-path alias to dts on boards without a serial port.
Signed-off-by: Hans de Goede hdegoede@redhat.com --- include/configs/sunxi-common.h | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/include/configs/sunxi-common.h b/include/configs/sunxi-common.h index 71b2368..a2cbcf5 100644 --- a/include/configs/sunxi-common.h +++ b/include/configs/sunxi-common.h @@ -262,6 +262,7 @@ extern int soft_i2c_gpio_scl; #define CONFIG_CONS_INDEX 1 /* UART0 */ #endif
+#ifdef CONFIG_REQUIRE_SERIAL_CONSOLE #if CONFIG_CONS_INDEX == 1 #ifdef CONFIG_MACH_SUN9I #define OF_STDOUT_PATH "/soc/serial@07000000:115200" @@ -277,6 +278,7 @@ extern int soft_i2c_gpio_scl; #else #error Unsupported console port nr. Please fix stdout-path in sunxi-common.h. #endif +#endif /* ifdef CONFIG_REQUIRE_SERIAL_CONSOLE */
/* GPIO */ #define CONFIG_SUNXI_GPIO

On Sat, 2015-08-01 at 14:50 +0200, Hans de Goede wrote:
Do not add a bogus (pointing to a non existing serial port) stdout-path alias to dts on boards without a serial port.
Signed-off-by: Hans de Goede hdegoede@redhat.com
include/configs/sunxi-common.h | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/include/configs/sunxi-common.h b/include/configs/sunxi -common.h index 71b2368..a2cbcf5 100644 --- a/include/configs/sunxi-common.h +++ b/include/configs/sunxi-common.h @@ -262,6 +262,7 @@ extern int soft_i2c_gpio_scl; #define CONFIG_CONS_INDEX 1 /* UART0 */ #endif
Should this defaulting of CONFIG_CONS_INDEX not be gated as well (or even instead)? Perhaps incorporate an ifndef CONFIG_CONS_INDEX into the chain of #elseif below (making the #error only hit for defined-but -unknown values) to achieve what this patch wants to do?
+#ifdef CONFIG_REQUIRE_SERIAL_CONSOLE #if CONFIG_CONS_INDEX == 1 #ifdef CONFIG_MACH_SUN9I #define OF_STDOUT_PATH "/soc/serial@07000000:115200" @@ -277,6 +278,7 @@ extern int soft_i2c_gpio_scl; #else #error Unsupported console port nr. Please fix stdout-path in sunxi -common.h. #endif +#endif /* ifdef CONFIG_REQUIRE_SERIAL_CONSOLE */
/* GPIO */ #define CONFIG_SUNXI_GPIO

Hi,
On 02-08-15 18:28, Ian Campbell wrote:
On Sat, 2015-08-01 at 14:50 +0200, Hans de Goede wrote:
Do not add a bogus (pointing to a non existing serial port) stdout-path alias to dts on boards without a serial port.
Signed-off-by: Hans de Goede hdegoede@redhat.com
include/configs/sunxi-common.h | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/include/configs/sunxi-common.h b/include/configs/sunxi -common.h index 71b2368..a2cbcf5 100644 --- a/include/configs/sunxi-common.h +++ b/include/configs/sunxi-common.h @@ -262,6 +262,7 @@ extern int soft_i2c_gpio_scl; #define CONFIG_CONS_INDEX 1 /* UART0 */ #endif
Should this defaulting of CONFIG_CONS_INDEX not be gated as well
That is a good question, unfortunately we still need this for the SPL, where we do not use DM_SERIAL and thus CONFIG_REQUIRE_SERIAL_CONSOLE is not used.
We are getting away with this because the sun5i die actually has an uart0, which in the A13 package is not routed to the outside, so we are simply sending SPL bootup messages to the tx pin at the edge of the die, and they go no further from there...
And sofar we only have one A13 board which does not have a serial port, all others do have a serial port. This kinda makes sense since the A13 is a much lower pincount package compared to all the other sunxi SoCs.
Actually before we moved most things including serial over to the device-model, we were (ab)using the present but not wired uart0 for both the SPL, u-boot proper.
So for now to keep things working we need CONFIG_CONS_INDEX 1 even on the 1 board we have which does not have a serial port (the uart1 pins which are routed to the outside on the A13 are used as gpio-s by the lcd.
Regards,
Hans
(or even instead)? Perhaps incorporate an ifndef CONFIG_CONS_INDEX into the chain of #elseif below (making the #error only hit for defined-but -unknown values) to achieve what this patch wants to do?
+#ifdef CONFIG_REQUIRE_SERIAL_CONSOLE #if CONFIG_CONS_INDEX == 1 #ifdef CONFIG_MACH_SUN9I #define OF_STDOUT_PATH "/soc/serial@07000000:115200" @@ -277,6 +278,7 @@ extern int soft_i2c_gpio_scl; #else #error Unsupported console port nr. Please fix stdout-path in sunxi -common.h. #endif +#endif /* ifdef CONFIG_REQUIRE_SERIAL_CONSOLE */
/* GPIO */ #define CONFIG_SUNXI_GPIO

On Sun, 2015-08-02 at 20:45 +0200, Hans de Goede wrote:
[...]
So for now to keep things working we need CONFIG_CONS_INDEX 1 even on the 1 board we have which does not have a serial port (the uart1 pins which are routed to the outside on the A13 are used as gpio-s by the lcd.
Makes sense, thanks.
Acked-by: Ian Campbell ijc@hellion.org.uk
Is it worth pasting some of your longer description into the commit message?
Ian.

Hi,
On 02-08-15 20:57, Ian Campbell wrote:
On Sun, 2015-08-02 at 20:45 +0200, Hans de Goede wrote:
[...]
So for now to keep things working we need CONFIG_CONS_INDEX 1 even on the 1 board we have which does not have a serial port (the uart1 pins which are routed to the outside on the A13 are used as gpio-s by the lcd.
Makes sense, thanks.
Acked-by: Ian Campbell ijc@hellion.org.uk
Is it worth pasting some of your longer description into the commit message?
Probably I'll improve the commit msg a bit before submitting a pull-req for this.
Regards,
Hans

On Sat, 2015-08-01 at 14:50 +0200, Hans de Goede wrote:
USB devices are not really designed to get the power bounced off and on at them. Esp. USB powered harddisks do not like this.
Currently we power off the USB ports both on a "usb reset" and when booting the kernel, causing the usb-power to bounce off and then back on again.
This patch removes the powering off calls, fixing the undesirable power bouncing.
Note this requires some special handling for the OTG port:
- We must skip the external vbus check if we've already enabled our own
vbus to avoid false positives 2) If on an usb reset we no longer detect that the id-pin is grounded, turn off vbus as that means an external vbus may be present now
Signed-off-by: Hans de Goede hdegoede@redhat.com
Acked-by: Ian Campbell ijc@hellion.org.uk
participants (2)
-
Hans de Goede
-
Ian Campbell