port - 1);
reg |= EHCI_PS_PO;
ehci_writel(status_reg, reg);
- break;
+ return -ENXIO;
} else {
int ret;
*/
ret = handshake(status_reg, EHCI_PS_PR, 0,
2 * 1000);
- if (!ret)
- ctrl->portreset |= 1 << port;
- else
+ if (!ret) {
+ reg = ehci_readl(status_reg);
+ if ((reg & (EHCI_PS_PE | EHCI_PS_CS))
+ == EHCI_PS_CS && !ehci_is_TDI()) {
+ debug("port %d full speed --> companion\n", port - 1);
+ reg &= ~EHCI_PS_CLEAR;
+ reg |= EHCI_PS_PO;
+ ehci_writel(status_reg, reg);
+ return -ENXIO;
+ } else {
+ ctrl->portreset |= 1 << port;
+ }
+ } else {
printf("port(%d) reset error\n",
port - 1);
+ }
}
break;
case USB_PORT_FEAT_TEST:
return 0;
}
-struct int_queue *
-create_int_queue(struct usb_device *dev, unsigned long pipe, int queuesize,
- int elementsize, void *buffer, int interval)
+static struct int_queue *_ehci_create_int_queue(struct usb_device *dev,
+ unsigned long pipe, int queuesize, int elementsize,
+ void *buffer, int interval)
{
struct ehci_ctrl *ctrl = ehci_get_ctrl(dev);
struct int_queue *result = NULL;
return NULL;
}
-void *poll_int_queue(struct usb_device *dev, struct int_queue *queue)
+static void *_ehci_poll_int_queue(struct usb_device *dev,
+ struct int_queue *queue)
{
struct QH *cur = queue->current;
struct qTD *cur_td;
}
/* Do not free buffers associated with QHs, they're owned by someone else */
-int
-destroy_int_queue(struct usb_device *dev, struct int_queue *queue)
+static int _ehci_destroy_int_queue(struct usb_device *dev,
+ struct int_queue *queue)
{
struct ehci_ctrl *ctrl = ehci_get_ctrl(dev);
int result = -1;
debug("dev=%p, pipe=%lu, buffer=%p, length=%d, interval=%d",
dev, pipe, buffer, length, interval);
- queue = create_int_queue(dev, pipe, 1, length, buffer, interval);
+ queue = _ehci_create_int_queue(dev, pipe, 1, length, buffer, interval);
if (!queue)
return -1;
timeout = get_timer(0) + USB_TIMEOUT_MS(pipe);
- while ((backbuffer = poll_int_queue(dev, queue)) == NULL)
+ while ((backbuffer = _ehci_poll_int_queue(dev, queue)) == NULL)
if (get_timer(0) > timeout) {
printf("Timeout poll on interrupt endpoint\n");
result = -ETIMEDOUT;
return -EINVAL;
}
- ret = destroy_int_queue(dev, queue);
+ ret = _ehci_destroy_int_queue(dev, queue);
if (ret < 0)
return ret;
{
return _ehci_submit_int_msg(dev, pipe, buffer, length, interval);
}
+
+struct int_queue *create_int_queue(struct usb_device *dev,
+ unsigned long pipe, int queuesize, int elementsize,
+ void *buffer, int interval)
+{
+ return _ehci_create_int_queue(dev, pipe, queuesize, elementsize,
+ buffer, interval);
+}
+
+void *poll_int_queue(struct usb_device *dev, struct int_queue *queue)
+{
+ return _ehci_poll_int_queue(dev, queue);
+}
+
+int destroy_int_queue(struct usb_device *dev, struct int_queue *queue)
+{
+ return _ehci_destroy_int_queue(dev, queue);
+}
#endif
#ifdef CONFIG_DM_USB
return _ehci_submit_int_msg(udev, pipe, buffer, length, interval);
}
+static struct int_queue *ehci_create_int_queue(struct udevice *dev,
+ struct usb_device *udev, unsigned long pipe, int queuesize,
+ int elementsize, void *buffer, int interval)
+{
+ debug("%s: dev='%s', udev=%p\n", __func__, dev->name, udev);
+ return _ehci_create_int_queue(udev, pipe, queuesize, elementsize,
+ buffer, interval);
+}
+
+static void *ehci_poll_int_queue(struct udevice *dev, struct usb_device *udev,
+ struct int_queue *queue)
+{
+ debug("%s: dev='%s', udev=%p\n", __func__, dev->name, udev);
+ return _ehci_poll_int_queue(udev, queue);
+}
+
+static int ehci_destroy_int_queue(struct udevice *dev, struct usb_device *udev,
+ struct int_queue *queue)
+{
+ debug("%s: dev='%s', udev=%p\n", __func__, dev->name, udev);
+ return _ehci_destroy_int_queue(udev, queue);
+}
+
int ehci_register(struct udevice *dev, struct ehci_hccr *hccr,
struct ehci_hcor *hcor, const struct ehci_ops *ops,
uint tweaks, enum usb_init_type init)
.control = ehci_submit_control_msg,
.bulk = ehci_submit_bulk_msg,
.interrupt = ehci_submit_int_msg,
+ .create_int_queue = ehci_create_int_queue,
+ .poll_int_queue = ehci_poll_int_queue,
+ .destroy_int_queue = ehci_destroy_int_queue,
};
#endif