mirror of
https://xff.cz/git/u-boot/
synced 2025-09-02 01:02:19 +02:00
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>
This commit is contained in:
committed by
Marek Vasut
parent
e8672e3f0e
commit
90cdc1039d
@@ -970,6 +970,8 @@ int usb_new_device(struct usb_device *dev)
|
|||||||
printf("\n Couldn't reset port %i\n", dev->portnr);
|
printf("\n Couldn't reset port %i\n", dev->portnr);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
usb_reset_root_port();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@@ -110,9 +110,27 @@ int submit_int_msg(struct usb_device *dev, unsigned long pipe,
|
|||||||
return submit_urb(&hcd, urb);
|
return submit_urb(&hcd, urb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
int usb_lowlevel_init(int index, enum usb_init_type init, void **controller)
|
||||||
{
|
{
|
||||||
u8 power;
|
|
||||||
void *mbase;
|
void *mbase;
|
||||||
/* USB spec says it may take up to 1 second for a device to connect */
|
/* USB spec says it may take up to 1 second for a device to connect */
|
||||||
unsigned long timeout = get_timer(0) + 1000;
|
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)
|
if (get_timer(0) >= timeout)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
power = musb_readb(mbase, MUSB_POWER);
|
usb_reset_root_port();
|
||||||
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;
|
|
||||||
host->is_active = 1;
|
host->is_active = 1;
|
||||||
hcd.hcd_priv = host;
|
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_init(int index, enum usb_init_type init, void **controller);
|
||||||
int usb_lowlevel_stop(int index);
|
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,
|
int submit_bulk_msg(struct usb_device *dev, unsigned long pipe,
|
||||||
void *buffer, int transfer_len);
|
void *buffer, int transfer_len);
|
||||||
|
Reference in New Issue
Block a user