mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-29 08:01:08 +00:00
Merge branch 'master' of git://source.denx.de/u-boot-usb
This commit is contained in:
commit
b627718939
3 changed files with 60 additions and 5 deletions
|
@ -706,6 +706,14 @@ static void dwc3_gadget_run(struct dwc3 *dwc)
|
|||
mdelay(100);
|
||||
}
|
||||
|
||||
static void dwc3_core_stop(struct dwc3 *dwc)
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
reg = dwc3_readl(dwc->regs, DWC3_DCTL);
|
||||
dwc3_writel(dwc->regs, DWC3_DCTL, reg & ~(DWC3_DCTL_RUN_STOP));
|
||||
}
|
||||
|
||||
static void dwc3_core_exit_mode(struct dwc3 *dwc)
|
||||
{
|
||||
switch (dwc->dr_mode) {
|
||||
|
@ -1128,6 +1136,7 @@ void dwc3_remove(struct dwc3 *dwc)
|
|||
dwc3_core_exit_mode(dwc);
|
||||
dwc3_event_buffers_cleanup(dwc);
|
||||
dwc3_free_event_buffers(dwc);
|
||||
dwc3_core_stop(dwc);
|
||||
dwc3_core_exit(dwc);
|
||||
kfree(dwc->mem);
|
||||
}
|
||||
|
|
|
@ -110,7 +110,12 @@ static int dwc3_generic_of_to_plat(struct udevice *dev)
|
|||
struct dwc3_generic_plat *plat = dev_get_plat(dev);
|
||||
ofnode node = dev_ofnode(dev);
|
||||
|
||||
plat->base = dev_read_addr(dev);
|
||||
if (!strncmp(dev->name, "port", 4) || !strncmp(dev->name, "hub", 3)) {
|
||||
/* This is a leaf so check the parent */
|
||||
plat->base = dev_read_addr(dev->parent);
|
||||
} else {
|
||||
plat->base = dev_read_addr(dev);
|
||||
}
|
||||
|
||||
plat->maximum_speed = usb_get_maximum_speed(node);
|
||||
if (plat->maximum_speed == USB_SPEED_UNKNOWN) {
|
||||
|
@ -120,8 +125,13 @@ static int dwc3_generic_of_to_plat(struct udevice *dev)
|
|||
|
||||
plat->dr_mode = usb_get_dr_mode(node);
|
||||
if (plat->dr_mode == USB_DR_MODE_UNKNOWN) {
|
||||
pr_err("Invalid usb mode setup\n");
|
||||
return -ENODEV;
|
||||
/* might be a leaf so check the parent for mode */
|
||||
node = dev_ofnode(dev->parent);
|
||||
plat->dr_mode = usb_get_dr_mode(node);
|
||||
if (plat->dr_mode == USB_DR_MODE_UNKNOWN) {
|
||||
pr_err("Invalid usb mode setup\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -301,16 +311,20 @@ static int dwc3_glue_bind(struct udevice *parent)
|
|||
{
|
||||
ofnode node;
|
||||
int ret;
|
||||
enum usb_dr_mode dr_mode;
|
||||
|
||||
dr_mode = usb_get_dr_mode(dev_ofnode(parent));
|
||||
|
||||
ofnode_for_each_subnode(node, dev_ofnode(parent)) {
|
||||
const char *name = ofnode_get_name(node);
|
||||
enum usb_dr_mode dr_mode;
|
||||
struct udevice *dev;
|
||||
const char *driver = NULL;
|
||||
|
||||
debug("%s: subnode name: %s\n", __func__, name);
|
||||
|
||||
dr_mode = usb_get_dr_mode(node);
|
||||
/* if the parent node doesn't have a mode check the leaf */
|
||||
if (!dr_mode)
|
||||
dr_mode = usb_get_dr_mode(node);
|
||||
|
||||
switch (dr_mode) {
|
||||
case USB_DR_MODE_PERIPHERAL:
|
||||
|
@ -450,6 +464,7 @@ static const struct udevice_id dwc3_glue_ids[] = {
|
|||
{ .compatible = "rockchip,rk3328-dwc3" },
|
||||
{ .compatible = "rockchip,rk3399-dwc3" },
|
||||
{ .compatible = "qcom,dwc3" },
|
||||
{ .compatible = "fsl,imx8mq-dwc3" },
|
||||
{ .compatible = "intel,tangier-dwc3" },
|
||||
{ }
|
||||
};
|
||||
|
|
|
@ -481,6 +481,33 @@ union xhci_trb *xhci_wait_for_event(struct xhci_ctrl *ctrl, trb_type expected)
|
|||
BUG();
|
||||
}
|
||||
|
||||
/*
|
||||
* Send reset endpoint command for given endpoint. This recovers from a
|
||||
* halted endpoint (e.g. due to a stall error).
|
||||
*/
|
||||
static void reset_ep(struct usb_device *udev, int ep_index)
|
||||
{
|
||||
struct xhci_ctrl *ctrl = xhci_get_ctrl(udev);
|
||||
struct xhci_ring *ring = ctrl->devs[udev->slot_id]->eps[ep_index].ring;
|
||||
union xhci_trb *event;
|
||||
u32 field;
|
||||
|
||||
printf("Resetting EP %d...\n", ep_index);
|
||||
xhci_queue_command(ctrl, NULL, udev->slot_id, ep_index, TRB_RESET_EP);
|
||||
event = xhci_wait_for_event(ctrl, TRB_COMPLETION);
|
||||
field = le32_to_cpu(event->trans_event.flags);
|
||||
BUG_ON(TRB_TO_SLOT_ID(field) != udev->slot_id);
|
||||
xhci_acknowledge_event(ctrl);
|
||||
|
||||
xhci_queue_command(ctrl, (void *)((uintptr_t)ring->enqueue |
|
||||
ring->cycle_state), udev->slot_id, ep_index, TRB_SET_DEQ);
|
||||
event = xhci_wait_for_event(ctrl, TRB_COMPLETION);
|
||||
BUG_ON(TRB_TO_SLOT_ID(le32_to_cpu(event->event_cmd.flags))
|
||||
!= udev->slot_id || GET_COMP_CODE(le32_to_cpu(
|
||||
event->event_cmd.status)) != COMP_SUCCESS);
|
||||
xhci_acknowledge_event(ctrl);
|
||||
}
|
||||
|
||||
/*
|
||||
* Stops transfer processing for an endpoint and throws away all unprocessed
|
||||
* TRBs by setting the xHC's dequeue pointer to our enqueue pointer. The next
|
||||
|
@ -928,6 +955,10 @@ int xhci_ctrl_tx(struct usb_device *udev, unsigned long pipe,
|
|||
|
||||
record_transfer_result(udev, event, length);
|
||||
xhci_acknowledge_event(ctrl);
|
||||
if (udev->status == USB_ST_STALLED) {
|
||||
reset_ep(udev, ep_index);
|
||||
return -EPIPE;
|
||||
}
|
||||
|
||||
/* Invalidate buffer to make it available to usb-core */
|
||||
if (length > 0)
|
||||
|
|
Loading…
Reference in a new issue