musb-new: Fix reset sequence when in host mode

This commit fixes a number of issues with the reset sequence of musb-new
in host mode:

1) Our usb device probe relies on a second device reset being done after the
first descriptors read. Factor the musb reset code into a usb_reset_root_port
function (and add this as an empty define for other controllers), and call
this when a device has no parent.

2) Just like with normal usb controllers there needs to be a delay after
reset, for normal usb controllers, this is handled in hub_port_reset, add a
delay to usb_reset_root_port.

3) Sync the musb reset sequence with the upstream kernel, clear all bits of
power except bits 4-7, and increase the time reset is asserted to 50 ms.

With these fixes an usb keyboard I have now always enumerates properly, where
as earlier it would only enumerare properly once every 5 tries.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
master
Hans de Goede 9 years ago committed by Marek Vasut
parent e8672e3f0e
commit 90cdc1039d
  1. 2
      common/usb.c
  2. 31
      drivers/usb/musb-new/musb_uboot.c
  3. 5
      include/usb.h

@ -970,6 +970,8 @@ int usb_new_device(struct usb_device *dev)
printf("\n Couldn't reset port %i\n", dev->portnr);
return 1;
}
} else {
usb_reset_root_port();
}
#endif

@ -110,9 +110,27 @@ int submit_int_msg(struct usb_device *dev, unsigned long pipe,
return submit_urb(&hcd, urb);
}
int usb_lowlevel_init(int index, enum usb_init_type init, void **controller)
void usb_reset_root_port(void)
{
void *mbase = host->mregs;
u8 power;
power = musb_readb(mbase, MUSB_POWER);
power &= 0xf0;
musb_writeb(mbase, MUSB_POWER, MUSB_POWER_RESET | power);
mdelay(50);
power = musb_readb(mbase, MUSB_POWER);
musb_writeb(mbase, MUSB_POWER, ~MUSB_POWER_RESET & power);
host->isr(0, host);
host_speed = (musb_readb(mbase, MUSB_POWER) & MUSB_POWER_HSMODE) ?
USB_SPEED_HIGH :
(musb_readb(mbase, MUSB_DEVCTL) & MUSB_DEVCTL_FSDEV) ?
USB_SPEED_FULL : USB_SPEED_LOW;
mdelay((host_speed == USB_SPEED_LOW) ? 200 : 50);
}
int usb_lowlevel_init(int index, enum usb_init_type init, void **controller)
{
void *mbase;
/* USB spec says it may take up to 1 second for a device to connect */
unsigned long timeout = get_timer(0) + 1000;
@ -131,16 +149,7 @@ int usb_lowlevel_init(int index, enum usb_init_type init, void **controller)
if (get_timer(0) >= timeout)
return -ENODEV;
power = musb_readb(mbase, MUSB_POWER);
musb_writeb(mbase, MUSB_POWER, MUSB_POWER_RESET | power);
udelay(30000);
power = musb_readb(mbase, MUSB_POWER);
musb_writeb(mbase, MUSB_POWER, ~MUSB_POWER_RESET & power);
host->isr(0, host);
host_speed = (musb_readb(mbase, MUSB_POWER) & MUSB_POWER_HSMODE) ?
USB_SPEED_HIGH :
(musb_readb(mbase, MUSB_DEVCTL) & MUSB_DEVCTL_FSDEV) ?
USB_SPEED_FULL : USB_SPEED_LOW;
usb_reset_root_port();
host->is_active = 1;
hcd.hcd_priv = host;

@ -159,6 +159,11 @@ enum usb_init_type {
int usb_lowlevel_init(int index, enum usb_init_type init, void **controller);
int usb_lowlevel_stop(int index);
#ifdef CONFIG_MUSB_HOST
void usb_reset_root_port(void);
#else
#define usb_reset_root_port()
#endif
int submit_bulk_msg(struct usb_device *dev, unsigned long pipe,
void *buffer, int transfer_len);

Loading…
Cancel
Save