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>
Acked-by: Ian Campbell <ijc@hellion.org.uk>
gpio_set_value(phy->gpio_vbus, 0);
}
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];
int sunxi_usb_phy_vbus_detect(int index)
{
struct sunxi_usb_phy *phy = &sunxi_usb_phy[index];
void sunxi_usb_phy_exit(int index);
void sunxi_usb_phy_power_on(int index);
void sunxi_usb_phy_power_off(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);
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);
- sunxi_usb_phy_power_off(priv->phy_index);
sunxi_usb_phy_exit(priv->phy_index);
#ifdef CONFIG_SUNXI_GEN_SUN6I
sunxi_usb_phy_exit(priv->phy_index);
#ifdef CONFIG_SUNXI_GEN_SUN6I
- sunxi_usb_phy_power_off(priv->phy_index);
sunxi_usb_phy_exit(priv->phy_index);
#ifdef CONFIG_SUNXI_GEN_SUN6I
sunxi_usb_phy_exit(priv->phy_index);
#ifdef CONFIG_SUNXI_GEN_SUN6I
static int sunxi_musb_enable(struct musb *musb)
{
static int sunxi_musb_enable(struct musb *musb)
{
pr_debug("%s():\n", __func__);
musb_ep_select(musb->mregs, 0);
pr_debug("%s():\n", __func__);
musb_ep_select(musb->mregs, 0);
musb_writeb(musb->mregs, USBC_REG_o_VEND0, 0);
if (is_host_enabled(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) {
printf("No host cable detected: ");
return -ENODEV;
}
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);
}
USBC_ForceVbusValidToHigh(musb->mregs);
- 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 */
USBC_ForceVbusValidToLow(musb->mregs);
mdelay(200); /* Wait for the current session to timeout */