1*4882a593Smuzhiyun /*-
2*4882a593Smuzhiyun * Copyright (c) 2007-2008, Juniper Networks, Inc.
3*4882a593Smuzhiyun * Copyright (c) 2008, Excito Elektronik i Skåne AB
4*4882a593Smuzhiyun * Copyright (c) 2008, Michael Trimarchi <trimarchimichael@yahoo.it>
5*4882a593Smuzhiyun *
6*4882a593Smuzhiyun * All rights reserved.
7*4882a593Smuzhiyun *
8*4882a593Smuzhiyun * SPDX-License-Identifier: GPL-2.0
9*4882a593Smuzhiyun */
10*4882a593Smuzhiyun #include <common.h>
11*4882a593Smuzhiyun #include <dm.h>
12*4882a593Smuzhiyun #include <errno.h>
13*4882a593Smuzhiyun #include <asm/byteorder.h>
14*4882a593Smuzhiyun #include <asm/unaligned.h>
15*4882a593Smuzhiyun #include <usb.h>
16*4882a593Smuzhiyun #include <asm/io.h>
17*4882a593Smuzhiyun #include <malloc.h>
18*4882a593Smuzhiyun #include <memalign.h>
19*4882a593Smuzhiyun #include <watchdog.h>
20*4882a593Smuzhiyun #include <linux/compiler.h>
21*4882a593Smuzhiyun
22*4882a593Smuzhiyun #include "ehci.h"
23*4882a593Smuzhiyun
24*4882a593Smuzhiyun #ifndef CONFIG_USB_MAX_CONTROLLER_COUNT
25*4882a593Smuzhiyun #define CONFIG_USB_MAX_CONTROLLER_COUNT 1
26*4882a593Smuzhiyun #endif
27*4882a593Smuzhiyun
28*4882a593Smuzhiyun /*
29*4882a593Smuzhiyun * EHCI spec page 20 says that the HC may take up to 16 uFrames (= 4ms) to halt.
30*4882a593Smuzhiyun * Let's time out after 8 to have a little safety margin on top of that.
31*4882a593Smuzhiyun */
32*4882a593Smuzhiyun #define HCHALT_TIMEOUT (8 * 1000)
33*4882a593Smuzhiyun
34*4882a593Smuzhiyun #if !CONFIG_IS_ENABLED(DM_USB)
35*4882a593Smuzhiyun static struct ehci_ctrl ehcic[CONFIG_USB_MAX_CONTROLLER_COUNT];
36*4882a593Smuzhiyun #endif
37*4882a593Smuzhiyun
38*4882a593Smuzhiyun #define ALIGN_END_ADDR(type, ptr, size) \
39*4882a593Smuzhiyun ((unsigned long)(ptr) + roundup((size) * sizeof(type), USB_DMA_MINALIGN))
40*4882a593Smuzhiyun
41*4882a593Smuzhiyun static struct descriptor {
42*4882a593Smuzhiyun struct usb_hub_descriptor hub;
43*4882a593Smuzhiyun struct usb_device_descriptor device;
44*4882a593Smuzhiyun struct usb_linux_config_descriptor config;
45*4882a593Smuzhiyun struct usb_linux_interface_descriptor interface;
46*4882a593Smuzhiyun struct usb_endpoint_descriptor endpoint;
47*4882a593Smuzhiyun } __attribute__ ((packed)) descriptor = {
48*4882a593Smuzhiyun {
49*4882a593Smuzhiyun 0x8, /* bDescLength */
50*4882a593Smuzhiyun 0x29, /* bDescriptorType: hub descriptor */
51*4882a593Smuzhiyun 2, /* bNrPorts -- runtime modified */
52*4882a593Smuzhiyun 0, /* wHubCharacteristics */
53*4882a593Smuzhiyun 10, /* bPwrOn2PwrGood */
54*4882a593Smuzhiyun 0, /* bHubCntrCurrent */
55*4882a593Smuzhiyun { /* Device removable */
56*4882a593Smuzhiyun } /* at most 7 ports! XXX */
57*4882a593Smuzhiyun },
58*4882a593Smuzhiyun {
59*4882a593Smuzhiyun 0x12, /* bLength */
60*4882a593Smuzhiyun 1, /* bDescriptorType: UDESC_DEVICE */
61*4882a593Smuzhiyun cpu_to_le16(0x0200), /* bcdUSB: v2.0 */
62*4882a593Smuzhiyun 9, /* bDeviceClass: UDCLASS_HUB */
63*4882a593Smuzhiyun 0, /* bDeviceSubClass: UDSUBCLASS_HUB */
64*4882a593Smuzhiyun 1, /* bDeviceProtocol: UDPROTO_HSHUBSTT */
65*4882a593Smuzhiyun 64, /* bMaxPacketSize: 64 bytes */
66*4882a593Smuzhiyun 0x0000, /* idVendor */
67*4882a593Smuzhiyun 0x0000, /* idProduct */
68*4882a593Smuzhiyun cpu_to_le16(0x0100), /* bcdDevice */
69*4882a593Smuzhiyun 1, /* iManufacturer */
70*4882a593Smuzhiyun 2, /* iProduct */
71*4882a593Smuzhiyun 0, /* iSerialNumber */
72*4882a593Smuzhiyun 1 /* bNumConfigurations: 1 */
73*4882a593Smuzhiyun },
74*4882a593Smuzhiyun {
75*4882a593Smuzhiyun 0x9,
76*4882a593Smuzhiyun 2, /* bDescriptorType: UDESC_CONFIG */
77*4882a593Smuzhiyun cpu_to_le16(0x19),
78*4882a593Smuzhiyun 1, /* bNumInterface */
79*4882a593Smuzhiyun 1, /* bConfigurationValue */
80*4882a593Smuzhiyun 0, /* iConfiguration */
81*4882a593Smuzhiyun 0x40, /* bmAttributes: UC_SELF_POWER */
82*4882a593Smuzhiyun 0 /* bMaxPower */
83*4882a593Smuzhiyun },
84*4882a593Smuzhiyun {
85*4882a593Smuzhiyun 0x9, /* bLength */
86*4882a593Smuzhiyun 4, /* bDescriptorType: UDESC_INTERFACE */
87*4882a593Smuzhiyun 0, /* bInterfaceNumber */
88*4882a593Smuzhiyun 0, /* bAlternateSetting */
89*4882a593Smuzhiyun 1, /* bNumEndpoints */
90*4882a593Smuzhiyun 9, /* bInterfaceClass: UICLASS_HUB */
91*4882a593Smuzhiyun 0, /* bInterfaceSubClass: UISUBCLASS_HUB */
92*4882a593Smuzhiyun 0, /* bInterfaceProtocol: UIPROTO_HSHUBSTT */
93*4882a593Smuzhiyun 0 /* iInterface */
94*4882a593Smuzhiyun },
95*4882a593Smuzhiyun {
96*4882a593Smuzhiyun 0x7, /* bLength */
97*4882a593Smuzhiyun 5, /* bDescriptorType: UDESC_ENDPOINT */
98*4882a593Smuzhiyun 0x81, /* bEndpointAddress:
99*4882a593Smuzhiyun * UE_DIR_IN | EHCI_INTR_ENDPT
100*4882a593Smuzhiyun */
101*4882a593Smuzhiyun 3, /* bmAttributes: UE_INTERRUPT */
102*4882a593Smuzhiyun 8, /* wMaxPacketSize */
103*4882a593Smuzhiyun 255 /* bInterval */
104*4882a593Smuzhiyun },
105*4882a593Smuzhiyun };
106*4882a593Smuzhiyun
107*4882a593Smuzhiyun #if defined(CONFIG_EHCI_IS_TDI)
108*4882a593Smuzhiyun #define ehci_is_TDI() (1)
109*4882a593Smuzhiyun #else
110*4882a593Smuzhiyun #define ehci_is_TDI() (0)
111*4882a593Smuzhiyun #endif
112*4882a593Smuzhiyun
ehci_get_ctrl(struct usb_device * udev)113*4882a593Smuzhiyun static struct ehci_ctrl *ehci_get_ctrl(struct usb_device *udev)
114*4882a593Smuzhiyun {
115*4882a593Smuzhiyun #if CONFIG_IS_ENABLED(DM_USB)
116*4882a593Smuzhiyun return dev_get_priv(usb_get_bus(udev->dev));
117*4882a593Smuzhiyun #else
118*4882a593Smuzhiyun return udev->controller;
119*4882a593Smuzhiyun #endif
120*4882a593Smuzhiyun }
121*4882a593Smuzhiyun
ehci_get_port_speed(struct ehci_ctrl * ctrl,uint32_t reg)122*4882a593Smuzhiyun static int ehci_get_port_speed(struct ehci_ctrl *ctrl, uint32_t reg)
123*4882a593Smuzhiyun {
124*4882a593Smuzhiyun return PORTSC_PSPD(reg);
125*4882a593Smuzhiyun }
126*4882a593Smuzhiyun
ehci_set_usbmode(struct ehci_ctrl * ctrl)127*4882a593Smuzhiyun static void ehci_set_usbmode(struct ehci_ctrl *ctrl)
128*4882a593Smuzhiyun {
129*4882a593Smuzhiyun uint32_t tmp;
130*4882a593Smuzhiyun uint32_t *reg_ptr;
131*4882a593Smuzhiyun
132*4882a593Smuzhiyun reg_ptr = (uint32_t *)((u8 *)&ctrl->hcor->or_usbcmd + USBMODE);
133*4882a593Smuzhiyun tmp = ehci_readl(reg_ptr);
134*4882a593Smuzhiyun tmp |= USBMODE_CM_HC;
135*4882a593Smuzhiyun #if defined(CONFIG_EHCI_MMIO_BIG_ENDIAN)
136*4882a593Smuzhiyun tmp |= USBMODE_BE;
137*4882a593Smuzhiyun #else
138*4882a593Smuzhiyun tmp &= ~USBMODE_BE;
139*4882a593Smuzhiyun #endif
140*4882a593Smuzhiyun ehci_writel(reg_ptr, tmp);
141*4882a593Smuzhiyun }
142*4882a593Smuzhiyun
ehci_powerup_fixup(struct ehci_ctrl * ctrl,uint32_t * status_reg,uint32_t * reg)143*4882a593Smuzhiyun static void ehci_powerup_fixup(struct ehci_ctrl *ctrl, uint32_t *status_reg,
144*4882a593Smuzhiyun uint32_t *reg)
145*4882a593Smuzhiyun {
146*4882a593Smuzhiyun mdelay(50);
147*4882a593Smuzhiyun }
148*4882a593Smuzhiyun
ehci_get_portsc_register(struct ehci_ctrl * ctrl,int port)149*4882a593Smuzhiyun static uint32_t *ehci_get_portsc_register(struct ehci_ctrl *ctrl, int port)
150*4882a593Smuzhiyun {
151*4882a593Smuzhiyun int max_ports = HCS_N_PORTS(ehci_readl(&ctrl->hccr->cr_hcsparams));
152*4882a593Smuzhiyun
153*4882a593Smuzhiyun if (port < 0 || port >= max_ports) {
154*4882a593Smuzhiyun /* Printing the message would cause a scan failure! */
155*4882a593Smuzhiyun debug("The request port(%u) exceeds maximum port number\n",
156*4882a593Smuzhiyun port);
157*4882a593Smuzhiyun return NULL;
158*4882a593Smuzhiyun }
159*4882a593Smuzhiyun
160*4882a593Smuzhiyun return (uint32_t *)&ctrl->hcor->or_portsc[port];
161*4882a593Smuzhiyun }
162*4882a593Smuzhiyun
handshake(uint32_t * ptr,uint32_t mask,uint32_t done,int usec)163*4882a593Smuzhiyun static int handshake(uint32_t *ptr, uint32_t mask, uint32_t done, int usec)
164*4882a593Smuzhiyun {
165*4882a593Smuzhiyun uint32_t result;
166*4882a593Smuzhiyun do {
167*4882a593Smuzhiyun result = ehci_readl(ptr);
168*4882a593Smuzhiyun udelay(5);
169*4882a593Smuzhiyun if (result == ~(uint32_t)0)
170*4882a593Smuzhiyun return -1;
171*4882a593Smuzhiyun result &= mask;
172*4882a593Smuzhiyun if (result == done)
173*4882a593Smuzhiyun return 0;
174*4882a593Smuzhiyun usec--;
175*4882a593Smuzhiyun } while (usec > 0);
176*4882a593Smuzhiyun return -1;
177*4882a593Smuzhiyun }
178*4882a593Smuzhiyun
ehci_reset(struct ehci_ctrl * ctrl)179*4882a593Smuzhiyun static int ehci_reset(struct ehci_ctrl *ctrl)
180*4882a593Smuzhiyun {
181*4882a593Smuzhiyun uint32_t cmd;
182*4882a593Smuzhiyun int ret = 0;
183*4882a593Smuzhiyun
184*4882a593Smuzhiyun cmd = ehci_readl(&ctrl->hcor->or_usbcmd);
185*4882a593Smuzhiyun cmd = (cmd & ~CMD_RUN) | CMD_RESET;
186*4882a593Smuzhiyun ehci_writel(&ctrl->hcor->or_usbcmd, cmd);
187*4882a593Smuzhiyun ret = handshake((uint32_t *)&ctrl->hcor->or_usbcmd,
188*4882a593Smuzhiyun CMD_RESET, 0, 250 * 1000);
189*4882a593Smuzhiyun if (ret < 0) {
190*4882a593Smuzhiyun printf("EHCI fail to reset\n");
191*4882a593Smuzhiyun goto out;
192*4882a593Smuzhiyun }
193*4882a593Smuzhiyun
194*4882a593Smuzhiyun if (ehci_is_TDI())
195*4882a593Smuzhiyun ctrl->ops.set_usb_mode(ctrl);
196*4882a593Smuzhiyun
197*4882a593Smuzhiyun #ifdef CONFIG_USB_EHCI_TXFIFO_THRESH
198*4882a593Smuzhiyun cmd = ehci_readl(&ctrl->hcor->or_txfilltuning);
199*4882a593Smuzhiyun cmd &= ~TXFIFO_THRESH_MASK;
200*4882a593Smuzhiyun cmd |= TXFIFO_THRESH(CONFIG_USB_EHCI_TXFIFO_THRESH);
201*4882a593Smuzhiyun ehci_writel(&ctrl->hcor->or_txfilltuning, cmd);
202*4882a593Smuzhiyun #endif
203*4882a593Smuzhiyun out:
204*4882a593Smuzhiyun return ret;
205*4882a593Smuzhiyun }
206*4882a593Smuzhiyun
ehci_shutdown(struct ehci_ctrl * ctrl)207*4882a593Smuzhiyun static int ehci_shutdown(struct ehci_ctrl *ctrl)
208*4882a593Smuzhiyun {
209*4882a593Smuzhiyun int i, ret = 0;
210*4882a593Smuzhiyun uint32_t cmd, reg;
211*4882a593Smuzhiyun int max_ports = HCS_N_PORTS(ehci_readl(&ctrl->hccr->cr_hcsparams));
212*4882a593Smuzhiyun
213*4882a593Smuzhiyun cmd = ehci_readl(&ctrl->hcor->or_usbcmd);
214*4882a593Smuzhiyun /* If not run, directly return */
215*4882a593Smuzhiyun if (!(cmd & CMD_RUN))
216*4882a593Smuzhiyun return 0;
217*4882a593Smuzhiyun cmd &= ~(CMD_PSE | CMD_ASE);
218*4882a593Smuzhiyun ehci_writel(&ctrl->hcor->or_usbcmd, cmd);
219*4882a593Smuzhiyun ret = handshake(&ctrl->hcor->or_usbsts, STS_ASS | STS_PSS, 0,
220*4882a593Smuzhiyun 100 * 1000);
221*4882a593Smuzhiyun
222*4882a593Smuzhiyun if (!ret) {
223*4882a593Smuzhiyun for (i = 0; i < max_ports; i++) {
224*4882a593Smuzhiyun reg = ehci_readl(&ctrl->hcor->or_portsc[i]);
225*4882a593Smuzhiyun reg |= EHCI_PS_SUSP;
226*4882a593Smuzhiyun ehci_writel(&ctrl->hcor->or_portsc[i], reg);
227*4882a593Smuzhiyun }
228*4882a593Smuzhiyun
229*4882a593Smuzhiyun cmd &= ~CMD_RUN;
230*4882a593Smuzhiyun ehci_writel(&ctrl->hcor->or_usbcmd, cmd);
231*4882a593Smuzhiyun ret = handshake(&ctrl->hcor->or_usbsts, STS_HALT, STS_HALT,
232*4882a593Smuzhiyun HCHALT_TIMEOUT);
233*4882a593Smuzhiyun }
234*4882a593Smuzhiyun
235*4882a593Smuzhiyun if (ret)
236*4882a593Smuzhiyun puts("EHCI failed to shut down host controller.\n");
237*4882a593Smuzhiyun
238*4882a593Smuzhiyun return ret;
239*4882a593Smuzhiyun }
240*4882a593Smuzhiyun
ehci_td_buffer(struct qTD * td,void * buf,size_t sz)241*4882a593Smuzhiyun static int ehci_td_buffer(struct qTD *td, void *buf, size_t sz)
242*4882a593Smuzhiyun {
243*4882a593Smuzhiyun uint32_t delta, next;
244*4882a593Smuzhiyun unsigned long addr = (unsigned long)buf;
245*4882a593Smuzhiyun int idx;
246*4882a593Smuzhiyun
247*4882a593Smuzhiyun if (addr != ALIGN(addr, ARCH_DMA_MINALIGN))
248*4882a593Smuzhiyun debug("EHCI-HCD: Misaligned buffer address (%p)\n", buf);
249*4882a593Smuzhiyun
250*4882a593Smuzhiyun flush_dcache_range(addr, ALIGN(addr + sz, ARCH_DMA_MINALIGN));
251*4882a593Smuzhiyun
252*4882a593Smuzhiyun idx = 0;
253*4882a593Smuzhiyun while (idx < QT_BUFFER_CNT) {
254*4882a593Smuzhiyun td->qt_buffer[idx] = cpu_to_hc32(virt_to_phys((void *)addr));
255*4882a593Smuzhiyun td->qt_buffer_hi[idx] = 0;
256*4882a593Smuzhiyun next = (addr + EHCI_PAGE_SIZE) & ~(EHCI_PAGE_SIZE - 1);
257*4882a593Smuzhiyun delta = next - addr;
258*4882a593Smuzhiyun if (delta >= sz)
259*4882a593Smuzhiyun break;
260*4882a593Smuzhiyun sz -= delta;
261*4882a593Smuzhiyun addr = next;
262*4882a593Smuzhiyun idx++;
263*4882a593Smuzhiyun }
264*4882a593Smuzhiyun
265*4882a593Smuzhiyun if (idx == QT_BUFFER_CNT) {
266*4882a593Smuzhiyun printf("out of buffer pointers (%zu bytes left)\n", sz);
267*4882a593Smuzhiyun return -1;
268*4882a593Smuzhiyun }
269*4882a593Smuzhiyun
270*4882a593Smuzhiyun return 0;
271*4882a593Smuzhiyun }
272*4882a593Smuzhiyun
ehci_encode_speed(enum usb_device_speed speed)273*4882a593Smuzhiyun static inline u8 ehci_encode_speed(enum usb_device_speed speed)
274*4882a593Smuzhiyun {
275*4882a593Smuzhiyun #define QH_HIGH_SPEED 2
276*4882a593Smuzhiyun #define QH_FULL_SPEED 0
277*4882a593Smuzhiyun #define QH_LOW_SPEED 1
278*4882a593Smuzhiyun if (speed == USB_SPEED_HIGH)
279*4882a593Smuzhiyun return QH_HIGH_SPEED;
280*4882a593Smuzhiyun if (speed == USB_SPEED_LOW)
281*4882a593Smuzhiyun return QH_LOW_SPEED;
282*4882a593Smuzhiyun return QH_FULL_SPEED;
283*4882a593Smuzhiyun }
284*4882a593Smuzhiyun
ehci_update_endpt2_dev_n_port(struct usb_device * udev,struct QH * qh)285*4882a593Smuzhiyun static void ehci_update_endpt2_dev_n_port(struct usb_device *udev,
286*4882a593Smuzhiyun struct QH *qh)
287*4882a593Smuzhiyun {
288*4882a593Smuzhiyun uint8_t portnr = 0;
289*4882a593Smuzhiyun uint8_t hubaddr = 0;
290*4882a593Smuzhiyun
291*4882a593Smuzhiyun if (udev->speed != USB_SPEED_LOW && udev->speed != USB_SPEED_FULL)
292*4882a593Smuzhiyun return;
293*4882a593Smuzhiyun
294*4882a593Smuzhiyun usb_find_usb2_hub_address_port(udev, &hubaddr, &portnr);
295*4882a593Smuzhiyun
296*4882a593Smuzhiyun qh->qh_endpt2 |= cpu_to_hc32(QH_ENDPT2_PORTNUM(portnr) |
297*4882a593Smuzhiyun QH_ENDPT2_HUBADDR(hubaddr));
298*4882a593Smuzhiyun }
299*4882a593Smuzhiyun
300*4882a593Smuzhiyun static int
ehci_submit_async(struct usb_device * dev,unsigned long pipe,void * buffer,int length,struct devrequest * req)301*4882a593Smuzhiyun ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
302*4882a593Smuzhiyun int length, struct devrequest *req)
303*4882a593Smuzhiyun {
304*4882a593Smuzhiyun ALLOC_ALIGN_BUFFER(struct QH, qh, 1, USB_DMA_MINALIGN);
305*4882a593Smuzhiyun struct qTD *qtd;
306*4882a593Smuzhiyun int qtd_count = 0;
307*4882a593Smuzhiyun int qtd_counter = 0;
308*4882a593Smuzhiyun volatile struct qTD *vtd;
309*4882a593Smuzhiyun unsigned long ts;
310*4882a593Smuzhiyun uint32_t *tdp;
311*4882a593Smuzhiyun uint32_t endpt, maxpacket, token, usbsts, qhtoken;
312*4882a593Smuzhiyun uint32_t c, toggle;
313*4882a593Smuzhiyun uint32_t cmd;
314*4882a593Smuzhiyun int timeout;
315*4882a593Smuzhiyun int ret = 0;
316*4882a593Smuzhiyun struct ehci_ctrl *ctrl = ehci_get_ctrl(dev);
317*4882a593Smuzhiyun
318*4882a593Smuzhiyun debug("dev=%p, pipe=%lx, buffer=%p, length=%d, req=%p\n", dev, pipe,
319*4882a593Smuzhiyun buffer, length, req);
320*4882a593Smuzhiyun if (req != NULL)
321*4882a593Smuzhiyun debug("req=%u (%#x), type=%u (%#x), value=%u (%#x), index=%u\n",
322*4882a593Smuzhiyun req->request, req->request,
323*4882a593Smuzhiyun req->requesttype, req->requesttype,
324*4882a593Smuzhiyun le16_to_cpu(req->value), le16_to_cpu(req->value),
325*4882a593Smuzhiyun le16_to_cpu(req->index));
326*4882a593Smuzhiyun
327*4882a593Smuzhiyun #define PKT_ALIGN 512
328*4882a593Smuzhiyun /*
329*4882a593Smuzhiyun * The USB transfer is split into qTD transfers. Eeach qTD transfer is
330*4882a593Smuzhiyun * described by a transfer descriptor (the qTD). The qTDs form a linked
331*4882a593Smuzhiyun * list with a queue head (QH).
332*4882a593Smuzhiyun *
333*4882a593Smuzhiyun * Each qTD transfer starts with a new USB packet, i.e. a packet cannot
334*4882a593Smuzhiyun * have its beginning in a qTD transfer and its end in the following
335*4882a593Smuzhiyun * one, so the qTD transfer lengths have to be chosen accordingly.
336*4882a593Smuzhiyun *
337*4882a593Smuzhiyun * Each qTD transfer uses up to QT_BUFFER_CNT data buffers, mapped to
338*4882a593Smuzhiyun * single pages. The first data buffer can start at any offset within a
339*4882a593Smuzhiyun * page (not considering the cache-line alignment issues), while the
340*4882a593Smuzhiyun * following buffers must be page-aligned. There is no alignment
341*4882a593Smuzhiyun * constraint on the size of a qTD transfer.
342*4882a593Smuzhiyun */
343*4882a593Smuzhiyun if (req != NULL)
344*4882a593Smuzhiyun /* 1 qTD will be needed for SETUP, and 1 for ACK. */
345*4882a593Smuzhiyun qtd_count += 1 + 1;
346*4882a593Smuzhiyun if (length > 0 || req == NULL) {
347*4882a593Smuzhiyun /*
348*4882a593Smuzhiyun * Determine the qTD transfer size that will be used for the
349*4882a593Smuzhiyun * data payload (not considering the first qTD transfer, which
350*4882a593Smuzhiyun * may be longer or shorter, and the final one, which may be
351*4882a593Smuzhiyun * shorter).
352*4882a593Smuzhiyun *
353*4882a593Smuzhiyun * In order to keep each packet within a qTD transfer, the qTD
354*4882a593Smuzhiyun * transfer size is aligned to PKT_ALIGN, which is a multiple of
355*4882a593Smuzhiyun * wMaxPacketSize (except in some cases for interrupt transfers,
356*4882a593Smuzhiyun * see comment in submit_int_msg()).
357*4882a593Smuzhiyun *
358*4882a593Smuzhiyun * By default, i.e. if the input buffer is aligned to PKT_ALIGN,
359*4882a593Smuzhiyun * QT_BUFFER_CNT full pages will be used.
360*4882a593Smuzhiyun */
361*4882a593Smuzhiyun int xfr_sz = QT_BUFFER_CNT;
362*4882a593Smuzhiyun /*
363*4882a593Smuzhiyun * However, if the input buffer is not aligned to PKT_ALIGN, the
364*4882a593Smuzhiyun * qTD transfer size will be one page shorter, and the first qTD
365*4882a593Smuzhiyun * data buffer of each transfer will be page-unaligned.
366*4882a593Smuzhiyun */
367*4882a593Smuzhiyun if ((unsigned long)buffer & (PKT_ALIGN - 1))
368*4882a593Smuzhiyun xfr_sz--;
369*4882a593Smuzhiyun /* Convert the qTD transfer size to bytes. */
370*4882a593Smuzhiyun xfr_sz *= EHCI_PAGE_SIZE;
371*4882a593Smuzhiyun /*
372*4882a593Smuzhiyun * Approximate by excess the number of qTDs that will be
373*4882a593Smuzhiyun * required for the data payload. The exact formula is way more
374*4882a593Smuzhiyun * complicated and saves at most 2 qTDs, i.e. a total of 128
375*4882a593Smuzhiyun * bytes.
376*4882a593Smuzhiyun */
377*4882a593Smuzhiyun qtd_count += 2 + length / xfr_sz;
378*4882a593Smuzhiyun }
379*4882a593Smuzhiyun /*
380*4882a593Smuzhiyun * Threshold value based on the worst-case total size of the allocated qTDs for
381*4882a593Smuzhiyun * a mass-storage transfer of 65535 blocks of 512 bytes.
382*4882a593Smuzhiyun */
383*4882a593Smuzhiyun #if CONFIG_SYS_MALLOC_LEN <= 64 + 128 * 1024
384*4882a593Smuzhiyun #warning CONFIG_SYS_MALLOC_LEN may be too small for EHCI
385*4882a593Smuzhiyun #endif
386*4882a593Smuzhiyun qtd = memalign(USB_DMA_MINALIGN, qtd_count * sizeof(struct qTD));
387*4882a593Smuzhiyun if (qtd == NULL) {
388*4882a593Smuzhiyun printf("unable to allocate TDs\n");
389*4882a593Smuzhiyun return -1;
390*4882a593Smuzhiyun }
391*4882a593Smuzhiyun
392*4882a593Smuzhiyun memset(qh, 0, sizeof(struct QH));
393*4882a593Smuzhiyun memset(qtd, 0, qtd_count * sizeof(*qtd));
394*4882a593Smuzhiyun
395*4882a593Smuzhiyun toggle = usb_gettoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe));
396*4882a593Smuzhiyun
397*4882a593Smuzhiyun /*
398*4882a593Smuzhiyun * Setup QH (3.6 in ehci-r10.pdf)
399*4882a593Smuzhiyun *
400*4882a593Smuzhiyun * qh_link ................. 03-00 H
401*4882a593Smuzhiyun * qh_endpt1 ............... 07-04 H
402*4882a593Smuzhiyun * qh_endpt2 ............... 0B-08 H
403*4882a593Smuzhiyun * - qh_curtd
404*4882a593Smuzhiyun * qh_overlay.qt_next ...... 13-10 H
405*4882a593Smuzhiyun * - qh_overlay.qt_altnext
406*4882a593Smuzhiyun */
407*4882a593Smuzhiyun qh->qh_link = cpu_to_hc32(virt_to_phys(&ctrl->qh_list) | QH_LINK_TYPE_QH);
408*4882a593Smuzhiyun c = (dev->speed != USB_SPEED_HIGH) && !usb_pipeendpoint(pipe);
409*4882a593Smuzhiyun maxpacket = usb_maxpacket(dev, pipe);
410*4882a593Smuzhiyun endpt = QH_ENDPT1_RL(8) | QH_ENDPT1_C(c) |
411*4882a593Smuzhiyun QH_ENDPT1_MAXPKTLEN(maxpacket) | QH_ENDPT1_H(0) |
412*4882a593Smuzhiyun QH_ENDPT1_DTC(QH_ENDPT1_DTC_DT_FROM_QTD) |
413*4882a593Smuzhiyun QH_ENDPT1_EPS(ehci_encode_speed(dev->speed)) |
414*4882a593Smuzhiyun QH_ENDPT1_ENDPT(usb_pipeendpoint(pipe)) | QH_ENDPT1_I(0) |
415*4882a593Smuzhiyun QH_ENDPT1_DEVADDR(usb_pipedevice(pipe));
416*4882a593Smuzhiyun qh->qh_endpt1 = cpu_to_hc32(endpt);
417*4882a593Smuzhiyun endpt = QH_ENDPT2_MULT(1) | QH_ENDPT2_UFCMASK(0) | QH_ENDPT2_UFSMASK(0);
418*4882a593Smuzhiyun qh->qh_endpt2 = cpu_to_hc32(endpt);
419*4882a593Smuzhiyun ehci_update_endpt2_dev_n_port(dev, qh);
420*4882a593Smuzhiyun qh->qh_overlay.qt_next = cpu_to_hc32(QT_NEXT_TERMINATE);
421*4882a593Smuzhiyun qh->qh_overlay.qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE);
422*4882a593Smuzhiyun
423*4882a593Smuzhiyun tdp = &qh->qh_overlay.qt_next;
424*4882a593Smuzhiyun if (req != NULL) {
425*4882a593Smuzhiyun /*
426*4882a593Smuzhiyun * Setup request qTD (3.5 in ehci-r10.pdf)
427*4882a593Smuzhiyun *
428*4882a593Smuzhiyun * qt_next ................ 03-00 H
429*4882a593Smuzhiyun * qt_altnext ............. 07-04 H
430*4882a593Smuzhiyun * qt_token ............... 0B-08 H
431*4882a593Smuzhiyun *
432*4882a593Smuzhiyun * [ buffer, buffer_hi ] loaded with "req".
433*4882a593Smuzhiyun */
434*4882a593Smuzhiyun qtd[qtd_counter].qt_next = cpu_to_hc32(QT_NEXT_TERMINATE);
435*4882a593Smuzhiyun qtd[qtd_counter].qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE);
436*4882a593Smuzhiyun token = QT_TOKEN_DT(0) | QT_TOKEN_TOTALBYTES(sizeof(*req)) |
437*4882a593Smuzhiyun QT_TOKEN_IOC(0) | QT_TOKEN_CPAGE(0) | QT_TOKEN_CERR(3) |
438*4882a593Smuzhiyun QT_TOKEN_PID(QT_TOKEN_PID_SETUP) |
439*4882a593Smuzhiyun QT_TOKEN_STATUS(QT_TOKEN_STATUS_ACTIVE);
440*4882a593Smuzhiyun qtd[qtd_counter].qt_token = cpu_to_hc32(token);
441*4882a593Smuzhiyun if (ehci_td_buffer(&qtd[qtd_counter], req, sizeof(*req))) {
442*4882a593Smuzhiyun printf("unable to construct SETUP TD\n");
443*4882a593Smuzhiyun goto fail;
444*4882a593Smuzhiyun }
445*4882a593Smuzhiyun /* Update previous qTD! */
446*4882a593Smuzhiyun *tdp = cpu_to_hc32(virt_to_phys(&qtd[qtd_counter]));
447*4882a593Smuzhiyun tdp = &qtd[qtd_counter++].qt_next;
448*4882a593Smuzhiyun toggle = 1;
449*4882a593Smuzhiyun }
450*4882a593Smuzhiyun
451*4882a593Smuzhiyun if (length > 0 || req == NULL) {
452*4882a593Smuzhiyun uint8_t *buf_ptr = buffer;
453*4882a593Smuzhiyun int left_length = length;
454*4882a593Smuzhiyun
455*4882a593Smuzhiyun do {
456*4882a593Smuzhiyun /*
457*4882a593Smuzhiyun * Determine the size of this qTD transfer. By default,
458*4882a593Smuzhiyun * QT_BUFFER_CNT full pages can be used.
459*4882a593Smuzhiyun */
460*4882a593Smuzhiyun int xfr_bytes = QT_BUFFER_CNT * EHCI_PAGE_SIZE;
461*4882a593Smuzhiyun /*
462*4882a593Smuzhiyun * However, if the input buffer is not page-aligned, the
463*4882a593Smuzhiyun * portion of the first page before the buffer start
464*4882a593Smuzhiyun * offset within that page is unusable.
465*4882a593Smuzhiyun */
466*4882a593Smuzhiyun xfr_bytes -= (unsigned long)buf_ptr & (EHCI_PAGE_SIZE - 1);
467*4882a593Smuzhiyun /*
468*4882a593Smuzhiyun * In order to keep each packet within a qTD transfer,
469*4882a593Smuzhiyun * align the qTD transfer size to PKT_ALIGN.
470*4882a593Smuzhiyun */
471*4882a593Smuzhiyun xfr_bytes &= ~(PKT_ALIGN - 1);
472*4882a593Smuzhiyun /*
473*4882a593Smuzhiyun * This transfer may be shorter than the available qTD
474*4882a593Smuzhiyun * transfer size that has just been computed.
475*4882a593Smuzhiyun */
476*4882a593Smuzhiyun xfr_bytes = min(xfr_bytes, left_length);
477*4882a593Smuzhiyun
478*4882a593Smuzhiyun /*
479*4882a593Smuzhiyun * Setup request qTD (3.5 in ehci-r10.pdf)
480*4882a593Smuzhiyun *
481*4882a593Smuzhiyun * qt_next ................ 03-00 H
482*4882a593Smuzhiyun * qt_altnext ............. 07-04 H
483*4882a593Smuzhiyun * qt_token ............... 0B-08 H
484*4882a593Smuzhiyun *
485*4882a593Smuzhiyun * [ buffer, buffer_hi ] loaded with "buffer".
486*4882a593Smuzhiyun */
487*4882a593Smuzhiyun qtd[qtd_counter].qt_next =
488*4882a593Smuzhiyun cpu_to_hc32(QT_NEXT_TERMINATE);
489*4882a593Smuzhiyun qtd[qtd_counter].qt_altnext =
490*4882a593Smuzhiyun cpu_to_hc32(QT_NEXT_TERMINATE);
491*4882a593Smuzhiyun token = QT_TOKEN_DT(toggle) |
492*4882a593Smuzhiyun QT_TOKEN_TOTALBYTES(xfr_bytes) |
493*4882a593Smuzhiyun QT_TOKEN_IOC(req == NULL) | QT_TOKEN_CPAGE(0) |
494*4882a593Smuzhiyun QT_TOKEN_CERR(3) |
495*4882a593Smuzhiyun QT_TOKEN_PID(usb_pipein(pipe) ?
496*4882a593Smuzhiyun QT_TOKEN_PID_IN : QT_TOKEN_PID_OUT) |
497*4882a593Smuzhiyun QT_TOKEN_STATUS(QT_TOKEN_STATUS_ACTIVE);
498*4882a593Smuzhiyun qtd[qtd_counter].qt_token = cpu_to_hc32(token);
499*4882a593Smuzhiyun if (ehci_td_buffer(&qtd[qtd_counter], buf_ptr,
500*4882a593Smuzhiyun xfr_bytes)) {
501*4882a593Smuzhiyun printf("unable to construct DATA TD\n");
502*4882a593Smuzhiyun goto fail;
503*4882a593Smuzhiyun }
504*4882a593Smuzhiyun /* Update previous qTD! */
505*4882a593Smuzhiyun *tdp = cpu_to_hc32(virt_to_phys(&qtd[qtd_counter]));
506*4882a593Smuzhiyun tdp = &qtd[qtd_counter++].qt_next;
507*4882a593Smuzhiyun /*
508*4882a593Smuzhiyun * Data toggle has to be adjusted since the qTD transfer
509*4882a593Smuzhiyun * size is not always an even multiple of
510*4882a593Smuzhiyun * wMaxPacketSize.
511*4882a593Smuzhiyun */
512*4882a593Smuzhiyun if ((xfr_bytes / maxpacket) & 1)
513*4882a593Smuzhiyun toggle ^= 1;
514*4882a593Smuzhiyun buf_ptr += xfr_bytes;
515*4882a593Smuzhiyun left_length -= xfr_bytes;
516*4882a593Smuzhiyun } while (left_length > 0);
517*4882a593Smuzhiyun }
518*4882a593Smuzhiyun
519*4882a593Smuzhiyun if (req != NULL) {
520*4882a593Smuzhiyun /*
521*4882a593Smuzhiyun * Setup request qTD (3.5 in ehci-r10.pdf)
522*4882a593Smuzhiyun *
523*4882a593Smuzhiyun * qt_next ................ 03-00 H
524*4882a593Smuzhiyun * qt_altnext ............. 07-04 H
525*4882a593Smuzhiyun * qt_token ............... 0B-08 H
526*4882a593Smuzhiyun */
527*4882a593Smuzhiyun qtd[qtd_counter].qt_next = cpu_to_hc32(QT_NEXT_TERMINATE);
528*4882a593Smuzhiyun qtd[qtd_counter].qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE);
529*4882a593Smuzhiyun token = QT_TOKEN_DT(1) | QT_TOKEN_TOTALBYTES(0) |
530*4882a593Smuzhiyun QT_TOKEN_IOC(1) | QT_TOKEN_CPAGE(0) | QT_TOKEN_CERR(3) |
531*4882a593Smuzhiyun QT_TOKEN_PID(usb_pipein(pipe) ?
532*4882a593Smuzhiyun QT_TOKEN_PID_OUT : QT_TOKEN_PID_IN) |
533*4882a593Smuzhiyun QT_TOKEN_STATUS(QT_TOKEN_STATUS_ACTIVE);
534*4882a593Smuzhiyun qtd[qtd_counter].qt_token = cpu_to_hc32(token);
535*4882a593Smuzhiyun /* Update previous qTD! */
536*4882a593Smuzhiyun *tdp = cpu_to_hc32(virt_to_phys(&qtd[qtd_counter]));
537*4882a593Smuzhiyun tdp = &qtd[qtd_counter++].qt_next;
538*4882a593Smuzhiyun }
539*4882a593Smuzhiyun
540*4882a593Smuzhiyun ctrl->qh_list.qh_link = cpu_to_hc32(virt_to_phys(qh) | QH_LINK_TYPE_QH);
541*4882a593Smuzhiyun
542*4882a593Smuzhiyun /* Flush dcache */
543*4882a593Smuzhiyun flush_dcache_range((unsigned long)&ctrl->qh_list,
544*4882a593Smuzhiyun ALIGN_END_ADDR(struct QH, &ctrl->qh_list, 1));
545*4882a593Smuzhiyun flush_dcache_range((unsigned long)qh, ALIGN_END_ADDR(struct QH, qh, 1));
546*4882a593Smuzhiyun flush_dcache_range((unsigned long)qtd,
547*4882a593Smuzhiyun ALIGN_END_ADDR(struct qTD, qtd, qtd_count));
548*4882a593Smuzhiyun
549*4882a593Smuzhiyun usbsts = ehci_readl(&ctrl->hcor->or_usbsts);
550*4882a593Smuzhiyun ehci_writel(&ctrl->hcor->or_usbsts, (usbsts & 0x3f));
551*4882a593Smuzhiyun
552*4882a593Smuzhiyun /* Enable async. schedule. */
553*4882a593Smuzhiyun cmd = ehci_readl(&ctrl->hcor->or_usbcmd);
554*4882a593Smuzhiyun if (!(cmd & CMD_ASE)) {
555*4882a593Smuzhiyun cmd |= CMD_ASE;
556*4882a593Smuzhiyun ehci_writel(&ctrl->hcor->or_usbcmd, cmd);
557*4882a593Smuzhiyun
558*4882a593Smuzhiyun ret = handshake((uint32_t *)&ctrl->hcor->or_usbsts, STS_ASS, STS_ASS,
559*4882a593Smuzhiyun 100 * 1000);
560*4882a593Smuzhiyun if (ret < 0) {
561*4882a593Smuzhiyun printf("EHCI fail timeout STS_ASS set\n");
562*4882a593Smuzhiyun goto fail;
563*4882a593Smuzhiyun }
564*4882a593Smuzhiyun }
565*4882a593Smuzhiyun
566*4882a593Smuzhiyun /* Wait for TDs to be processed. */
567*4882a593Smuzhiyun ts = get_timer(0);
568*4882a593Smuzhiyun vtd = &qtd[qtd_counter - 1];
569*4882a593Smuzhiyun timeout = USB_TIMEOUT_MS(pipe);
570*4882a593Smuzhiyun do {
571*4882a593Smuzhiyun /* Invalidate dcache */
572*4882a593Smuzhiyun invalidate_dcache_range((unsigned long)&ctrl->qh_list,
573*4882a593Smuzhiyun ALIGN_END_ADDR(struct QH, &ctrl->qh_list, 1));
574*4882a593Smuzhiyun invalidate_dcache_range((unsigned long)qh,
575*4882a593Smuzhiyun ALIGN_END_ADDR(struct QH, qh, 1));
576*4882a593Smuzhiyun invalidate_dcache_range((unsigned long)qtd,
577*4882a593Smuzhiyun ALIGN_END_ADDR(struct qTD, qtd, qtd_count));
578*4882a593Smuzhiyun
579*4882a593Smuzhiyun token = hc32_to_cpu(vtd->qt_token);
580*4882a593Smuzhiyun if (!(QT_TOKEN_GET_STATUS(token) & QT_TOKEN_STATUS_ACTIVE))
581*4882a593Smuzhiyun break;
582*4882a593Smuzhiyun WATCHDOG_RESET();
583*4882a593Smuzhiyun } while (get_timer(ts) < timeout);
584*4882a593Smuzhiyun qhtoken = hc32_to_cpu(qh->qh_overlay.qt_token);
585*4882a593Smuzhiyun
586*4882a593Smuzhiyun ctrl->qh_list.qh_link = cpu_to_hc32(virt_to_phys(&ctrl->qh_list) | QH_LINK_TYPE_QH);
587*4882a593Smuzhiyun flush_dcache_range((unsigned long)&ctrl->qh_list,
588*4882a593Smuzhiyun ALIGN_END_ADDR(struct QH, &ctrl->qh_list, 1));
589*4882a593Smuzhiyun
590*4882a593Smuzhiyun /*
591*4882a593Smuzhiyun * Invalidate the memory area occupied by buffer
592*4882a593Smuzhiyun * Don't try to fix the buffer alignment, if it isn't properly
593*4882a593Smuzhiyun * aligned it's upper layer's fault so let invalidate_dcache_range()
594*4882a593Smuzhiyun * vow about it. But we have to fix the length as it's actual
595*4882a593Smuzhiyun * transfer length and can be unaligned. This is potentially
596*4882a593Smuzhiyun * dangerous operation, it's responsibility of the calling
597*4882a593Smuzhiyun * code to make sure enough space is reserved.
598*4882a593Smuzhiyun */
599*4882a593Smuzhiyun if (buffer != NULL && length > 0)
600*4882a593Smuzhiyun invalidate_dcache_range((unsigned long)buffer,
601*4882a593Smuzhiyun ALIGN((unsigned long)buffer + length, ARCH_DMA_MINALIGN));
602*4882a593Smuzhiyun
603*4882a593Smuzhiyun /* Check that the TD processing happened */
604*4882a593Smuzhiyun if (QT_TOKEN_GET_STATUS(token) & QT_TOKEN_STATUS_ACTIVE)
605*4882a593Smuzhiyun printf("EHCI timed out on TD - token=%#x\n", token);
606*4882a593Smuzhiyun
607*4882a593Smuzhiyun if (!(QT_TOKEN_GET_STATUS(qhtoken) & QT_TOKEN_STATUS_ACTIVE)) {
608*4882a593Smuzhiyun debug("TOKEN=%#x\n", qhtoken);
609*4882a593Smuzhiyun switch (QT_TOKEN_GET_STATUS(qhtoken) &
610*4882a593Smuzhiyun ~(QT_TOKEN_STATUS_SPLITXSTATE | QT_TOKEN_STATUS_PERR)) {
611*4882a593Smuzhiyun case 0:
612*4882a593Smuzhiyun toggle = QT_TOKEN_GET_DT(qhtoken);
613*4882a593Smuzhiyun usb_settoggle(dev, usb_pipeendpoint(pipe),
614*4882a593Smuzhiyun usb_pipeout(pipe), toggle);
615*4882a593Smuzhiyun dev->status = 0;
616*4882a593Smuzhiyun break;
617*4882a593Smuzhiyun case QT_TOKEN_STATUS_HALTED:
618*4882a593Smuzhiyun dev->status = USB_ST_STALLED;
619*4882a593Smuzhiyun break;
620*4882a593Smuzhiyun case QT_TOKEN_STATUS_ACTIVE | QT_TOKEN_STATUS_DATBUFERR:
621*4882a593Smuzhiyun case QT_TOKEN_STATUS_DATBUFERR:
622*4882a593Smuzhiyun dev->status = USB_ST_BUF_ERR;
623*4882a593Smuzhiyun break;
624*4882a593Smuzhiyun case QT_TOKEN_STATUS_HALTED | QT_TOKEN_STATUS_BABBLEDET:
625*4882a593Smuzhiyun case QT_TOKEN_STATUS_BABBLEDET:
626*4882a593Smuzhiyun dev->status = USB_ST_BABBLE_DET;
627*4882a593Smuzhiyun break;
628*4882a593Smuzhiyun default:
629*4882a593Smuzhiyun dev->status = USB_ST_CRC_ERR;
630*4882a593Smuzhiyun if (QT_TOKEN_GET_STATUS(qhtoken) & QT_TOKEN_STATUS_HALTED)
631*4882a593Smuzhiyun dev->status |= USB_ST_STALLED;
632*4882a593Smuzhiyun break;
633*4882a593Smuzhiyun }
634*4882a593Smuzhiyun dev->act_len = length - QT_TOKEN_GET_TOTALBYTES(qhtoken);
635*4882a593Smuzhiyun } else {
636*4882a593Smuzhiyun dev->act_len = 0;
637*4882a593Smuzhiyun #ifndef CONFIG_USB_EHCI_FARADAY
638*4882a593Smuzhiyun debug("dev=%u, usbsts=%#x, p[1]=%#x, p[2]=%#x\n",
639*4882a593Smuzhiyun dev->devnum, ehci_readl(&ctrl->hcor->or_usbsts),
640*4882a593Smuzhiyun ehci_readl(&ctrl->hcor->or_portsc[0]),
641*4882a593Smuzhiyun ehci_readl(&ctrl->hcor->or_portsc[1]));
642*4882a593Smuzhiyun #endif
643*4882a593Smuzhiyun }
644*4882a593Smuzhiyun
645*4882a593Smuzhiyun free(qtd);
646*4882a593Smuzhiyun return (dev->status != USB_ST_NOT_PROC) ? 0 : -1;
647*4882a593Smuzhiyun
648*4882a593Smuzhiyun fail:
649*4882a593Smuzhiyun free(qtd);
650*4882a593Smuzhiyun return -1;
651*4882a593Smuzhiyun }
652*4882a593Smuzhiyun
ehci_submit_root(struct usb_device * dev,unsigned long pipe,void * buffer,int length,struct devrequest * req)653*4882a593Smuzhiyun static int ehci_submit_root(struct usb_device *dev, unsigned long pipe,
654*4882a593Smuzhiyun void *buffer, int length, struct devrequest *req)
655*4882a593Smuzhiyun {
656*4882a593Smuzhiyun uint8_t tmpbuf[4];
657*4882a593Smuzhiyun u16 typeReq;
658*4882a593Smuzhiyun void *srcptr = NULL;
659*4882a593Smuzhiyun int len, srclen;
660*4882a593Smuzhiyun uint32_t reg;
661*4882a593Smuzhiyun uint32_t *status_reg;
662*4882a593Smuzhiyun int port = le16_to_cpu(req->index) & 0xff;
663*4882a593Smuzhiyun struct ehci_ctrl *ctrl = ehci_get_ctrl(dev);
664*4882a593Smuzhiyun
665*4882a593Smuzhiyun srclen = 0;
666*4882a593Smuzhiyun
667*4882a593Smuzhiyun debug("req=%u (%#x), type=%u (%#x), value=%u, index=%u\n",
668*4882a593Smuzhiyun req->request, req->request,
669*4882a593Smuzhiyun req->requesttype, req->requesttype,
670*4882a593Smuzhiyun le16_to_cpu(req->value), le16_to_cpu(req->index));
671*4882a593Smuzhiyun
672*4882a593Smuzhiyun typeReq = req->request | req->requesttype << 8;
673*4882a593Smuzhiyun
674*4882a593Smuzhiyun switch (typeReq) {
675*4882a593Smuzhiyun case USB_REQ_GET_STATUS | ((USB_RT_PORT | USB_DIR_IN) << 8):
676*4882a593Smuzhiyun case USB_REQ_SET_FEATURE | ((USB_DIR_OUT | USB_RT_PORT) << 8):
677*4882a593Smuzhiyun case USB_REQ_CLEAR_FEATURE | ((USB_DIR_OUT | USB_RT_PORT) << 8):
678*4882a593Smuzhiyun status_reg = ctrl->ops.get_portsc_register(ctrl, port - 1);
679*4882a593Smuzhiyun if (!status_reg)
680*4882a593Smuzhiyun return -1;
681*4882a593Smuzhiyun break;
682*4882a593Smuzhiyun default:
683*4882a593Smuzhiyun status_reg = NULL;
684*4882a593Smuzhiyun break;
685*4882a593Smuzhiyun }
686*4882a593Smuzhiyun
687*4882a593Smuzhiyun switch (typeReq) {
688*4882a593Smuzhiyun case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
689*4882a593Smuzhiyun switch (le16_to_cpu(req->value) >> 8) {
690*4882a593Smuzhiyun case USB_DT_DEVICE:
691*4882a593Smuzhiyun debug("USB_DT_DEVICE request\n");
692*4882a593Smuzhiyun srcptr = &descriptor.device;
693*4882a593Smuzhiyun srclen = descriptor.device.bLength;
694*4882a593Smuzhiyun break;
695*4882a593Smuzhiyun case USB_DT_CONFIG:
696*4882a593Smuzhiyun debug("USB_DT_CONFIG config\n");
697*4882a593Smuzhiyun srcptr = &descriptor.config;
698*4882a593Smuzhiyun srclen = descriptor.config.bLength +
699*4882a593Smuzhiyun descriptor.interface.bLength +
700*4882a593Smuzhiyun descriptor.endpoint.bLength;
701*4882a593Smuzhiyun break;
702*4882a593Smuzhiyun case USB_DT_STRING:
703*4882a593Smuzhiyun debug("USB_DT_STRING config\n");
704*4882a593Smuzhiyun switch (le16_to_cpu(req->value) & 0xff) {
705*4882a593Smuzhiyun case 0: /* Language */
706*4882a593Smuzhiyun srcptr = "\4\3\1\0";
707*4882a593Smuzhiyun srclen = 4;
708*4882a593Smuzhiyun break;
709*4882a593Smuzhiyun case 1: /* Vendor */
710*4882a593Smuzhiyun srcptr = "\16\3u\0-\0b\0o\0o\0t\0";
711*4882a593Smuzhiyun srclen = 14;
712*4882a593Smuzhiyun break;
713*4882a593Smuzhiyun case 2: /* Product */
714*4882a593Smuzhiyun srcptr = "\52\3E\0H\0C\0I\0 "
715*4882a593Smuzhiyun "\0H\0o\0s\0t\0 "
716*4882a593Smuzhiyun "\0C\0o\0n\0t\0r\0o\0l\0l\0e\0r\0";
717*4882a593Smuzhiyun srclen = 42;
718*4882a593Smuzhiyun break;
719*4882a593Smuzhiyun default:
720*4882a593Smuzhiyun debug("unknown value DT_STRING %x\n",
721*4882a593Smuzhiyun le16_to_cpu(req->value));
722*4882a593Smuzhiyun goto unknown;
723*4882a593Smuzhiyun }
724*4882a593Smuzhiyun break;
725*4882a593Smuzhiyun default:
726*4882a593Smuzhiyun debug("unknown value %x\n", le16_to_cpu(req->value));
727*4882a593Smuzhiyun goto unknown;
728*4882a593Smuzhiyun }
729*4882a593Smuzhiyun break;
730*4882a593Smuzhiyun case USB_REQ_GET_DESCRIPTOR | ((USB_DIR_IN | USB_RT_HUB) << 8):
731*4882a593Smuzhiyun switch (le16_to_cpu(req->value) >> 8) {
732*4882a593Smuzhiyun case USB_DT_HUB:
733*4882a593Smuzhiyun debug("USB_DT_HUB config\n");
734*4882a593Smuzhiyun srcptr = &ctrl->hub;
735*4882a593Smuzhiyun srclen = ctrl->hub.bLength;
736*4882a593Smuzhiyun break;
737*4882a593Smuzhiyun default:
738*4882a593Smuzhiyun debug("unknown value %x\n", le16_to_cpu(req->value));
739*4882a593Smuzhiyun goto unknown;
740*4882a593Smuzhiyun }
741*4882a593Smuzhiyun break;
742*4882a593Smuzhiyun case USB_REQ_SET_ADDRESS | (USB_RECIP_DEVICE << 8):
743*4882a593Smuzhiyun debug("USB_REQ_SET_ADDRESS\n");
744*4882a593Smuzhiyun ctrl->rootdev = le16_to_cpu(req->value);
745*4882a593Smuzhiyun break;
746*4882a593Smuzhiyun case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
747*4882a593Smuzhiyun debug("USB_REQ_SET_CONFIGURATION\n");
748*4882a593Smuzhiyun /* Nothing to do */
749*4882a593Smuzhiyun break;
750*4882a593Smuzhiyun case USB_REQ_GET_STATUS | ((USB_DIR_IN | USB_RT_HUB) << 8):
751*4882a593Smuzhiyun tmpbuf[0] = 1; /* USB_STATUS_SELFPOWERED */
752*4882a593Smuzhiyun tmpbuf[1] = 0;
753*4882a593Smuzhiyun srcptr = tmpbuf;
754*4882a593Smuzhiyun srclen = 2;
755*4882a593Smuzhiyun break;
756*4882a593Smuzhiyun case USB_REQ_GET_STATUS | ((USB_RT_PORT | USB_DIR_IN) << 8):
757*4882a593Smuzhiyun memset(tmpbuf, 0, 4);
758*4882a593Smuzhiyun reg = ehci_readl(status_reg);
759*4882a593Smuzhiyun if (reg & EHCI_PS_CS)
760*4882a593Smuzhiyun tmpbuf[0] |= USB_PORT_STAT_CONNECTION;
761*4882a593Smuzhiyun if (reg & EHCI_PS_PE)
762*4882a593Smuzhiyun tmpbuf[0] |= USB_PORT_STAT_ENABLE;
763*4882a593Smuzhiyun if (reg & EHCI_PS_SUSP)
764*4882a593Smuzhiyun tmpbuf[0] |= USB_PORT_STAT_SUSPEND;
765*4882a593Smuzhiyun if (reg & EHCI_PS_OCA)
766*4882a593Smuzhiyun tmpbuf[0] |= USB_PORT_STAT_OVERCURRENT;
767*4882a593Smuzhiyun if (reg & EHCI_PS_PR)
768*4882a593Smuzhiyun tmpbuf[0] |= USB_PORT_STAT_RESET;
769*4882a593Smuzhiyun if (reg & EHCI_PS_PP)
770*4882a593Smuzhiyun tmpbuf[1] |= USB_PORT_STAT_POWER >> 8;
771*4882a593Smuzhiyun
772*4882a593Smuzhiyun if (ehci_is_TDI()) {
773*4882a593Smuzhiyun switch (ctrl->ops.get_port_speed(ctrl, reg)) {
774*4882a593Smuzhiyun case PORTSC_PSPD_FS:
775*4882a593Smuzhiyun break;
776*4882a593Smuzhiyun case PORTSC_PSPD_LS:
777*4882a593Smuzhiyun tmpbuf[1] |= USB_PORT_STAT_LOW_SPEED >> 8;
778*4882a593Smuzhiyun break;
779*4882a593Smuzhiyun case PORTSC_PSPD_HS:
780*4882a593Smuzhiyun default:
781*4882a593Smuzhiyun tmpbuf[1] |= USB_PORT_STAT_HIGH_SPEED >> 8;
782*4882a593Smuzhiyun break;
783*4882a593Smuzhiyun }
784*4882a593Smuzhiyun } else {
785*4882a593Smuzhiyun tmpbuf[1] |= USB_PORT_STAT_HIGH_SPEED >> 8;
786*4882a593Smuzhiyun }
787*4882a593Smuzhiyun
788*4882a593Smuzhiyun if (reg & EHCI_PS_CSC)
789*4882a593Smuzhiyun tmpbuf[2] |= USB_PORT_STAT_C_CONNECTION;
790*4882a593Smuzhiyun if (reg & EHCI_PS_PEC)
791*4882a593Smuzhiyun tmpbuf[2] |= USB_PORT_STAT_C_ENABLE;
792*4882a593Smuzhiyun if (reg & EHCI_PS_OCC)
793*4882a593Smuzhiyun tmpbuf[2] |= USB_PORT_STAT_C_OVERCURRENT;
794*4882a593Smuzhiyun if (ctrl->portreset & (1 << port))
795*4882a593Smuzhiyun tmpbuf[2] |= USB_PORT_STAT_C_RESET;
796*4882a593Smuzhiyun
797*4882a593Smuzhiyun srcptr = tmpbuf;
798*4882a593Smuzhiyun srclen = 4;
799*4882a593Smuzhiyun break;
800*4882a593Smuzhiyun case USB_REQ_SET_FEATURE | ((USB_DIR_OUT | USB_RT_PORT) << 8):
801*4882a593Smuzhiyun reg = ehci_readl(status_reg);
802*4882a593Smuzhiyun reg &= ~EHCI_PS_CLEAR;
803*4882a593Smuzhiyun switch (le16_to_cpu(req->value)) {
804*4882a593Smuzhiyun case USB_PORT_FEAT_ENABLE:
805*4882a593Smuzhiyun reg |= EHCI_PS_PE;
806*4882a593Smuzhiyun ehci_writel(status_reg, reg);
807*4882a593Smuzhiyun break;
808*4882a593Smuzhiyun case USB_PORT_FEAT_POWER:
809*4882a593Smuzhiyun if (HCS_PPC(ehci_readl(&ctrl->hccr->cr_hcsparams))) {
810*4882a593Smuzhiyun reg |= EHCI_PS_PP;
811*4882a593Smuzhiyun ehci_writel(status_reg, reg);
812*4882a593Smuzhiyun }
813*4882a593Smuzhiyun break;
814*4882a593Smuzhiyun case USB_PORT_FEAT_RESET:
815*4882a593Smuzhiyun if ((reg & (EHCI_PS_PE | EHCI_PS_CS)) == EHCI_PS_CS &&
816*4882a593Smuzhiyun !ehci_is_TDI() &&
817*4882a593Smuzhiyun EHCI_PS_IS_LOWSPEED(reg)) {
818*4882a593Smuzhiyun /* Low speed device, give up ownership. */
819*4882a593Smuzhiyun debug("port %d low speed --> companion\n",
820*4882a593Smuzhiyun port - 1);
821*4882a593Smuzhiyun reg |= EHCI_PS_PO;
822*4882a593Smuzhiyun ehci_writel(status_reg, reg);
823*4882a593Smuzhiyun return -ENXIO;
824*4882a593Smuzhiyun } else {
825*4882a593Smuzhiyun int ret;
826*4882a593Smuzhiyun
827*4882a593Smuzhiyun reg |= EHCI_PS_PR;
828*4882a593Smuzhiyun reg &= ~EHCI_PS_PE;
829*4882a593Smuzhiyun ehci_writel(status_reg, reg);
830*4882a593Smuzhiyun /*
831*4882a593Smuzhiyun * caller must wait, then call GetPortStatus
832*4882a593Smuzhiyun * usb 2.0 specification say 50 ms resets on
833*4882a593Smuzhiyun * root
834*4882a593Smuzhiyun */
835*4882a593Smuzhiyun ctrl->ops.powerup_fixup(ctrl, status_reg, ®);
836*4882a593Smuzhiyun
837*4882a593Smuzhiyun ehci_writel(status_reg, reg & ~EHCI_PS_PR);
838*4882a593Smuzhiyun /*
839*4882a593Smuzhiyun * A host controller must terminate the reset
840*4882a593Smuzhiyun * and stabilize the state of the port within
841*4882a593Smuzhiyun * 2 milliseconds
842*4882a593Smuzhiyun */
843*4882a593Smuzhiyun ret = handshake(status_reg, EHCI_PS_PR, 0,
844*4882a593Smuzhiyun 2 * 1000);
845*4882a593Smuzhiyun if (!ret) {
846*4882a593Smuzhiyun reg = ehci_readl(status_reg);
847*4882a593Smuzhiyun if ((reg & (EHCI_PS_PE | EHCI_PS_CS))
848*4882a593Smuzhiyun == EHCI_PS_CS && !ehci_is_TDI()) {
849*4882a593Smuzhiyun debug("port %d full speed --> companion\n", port - 1);
850*4882a593Smuzhiyun reg &= ~EHCI_PS_CLEAR;
851*4882a593Smuzhiyun reg |= EHCI_PS_PO;
852*4882a593Smuzhiyun ehci_writel(status_reg, reg);
853*4882a593Smuzhiyun return -ENXIO;
854*4882a593Smuzhiyun } else {
855*4882a593Smuzhiyun ctrl->portreset |= 1 << port;
856*4882a593Smuzhiyun }
857*4882a593Smuzhiyun } else {
858*4882a593Smuzhiyun printf("port(%d) reset error\n",
859*4882a593Smuzhiyun port - 1);
860*4882a593Smuzhiyun }
861*4882a593Smuzhiyun }
862*4882a593Smuzhiyun break;
863*4882a593Smuzhiyun case USB_PORT_FEAT_TEST:
864*4882a593Smuzhiyun ehci_shutdown(ctrl);
865*4882a593Smuzhiyun reg &= ~(0xf << 16);
866*4882a593Smuzhiyun reg |= ((le16_to_cpu(req->index) >> 8) & 0xf) << 16;
867*4882a593Smuzhiyun ehci_writel(status_reg, reg);
868*4882a593Smuzhiyun break;
869*4882a593Smuzhiyun default:
870*4882a593Smuzhiyun debug("unknown feature %x\n", le16_to_cpu(req->value));
871*4882a593Smuzhiyun goto unknown;
872*4882a593Smuzhiyun }
873*4882a593Smuzhiyun /* unblock posted writes */
874*4882a593Smuzhiyun (void) ehci_readl(&ctrl->hcor->or_usbcmd);
875*4882a593Smuzhiyun break;
876*4882a593Smuzhiyun case USB_REQ_CLEAR_FEATURE | ((USB_DIR_OUT | USB_RT_PORT) << 8):
877*4882a593Smuzhiyun reg = ehci_readl(status_reg);
878*4882a593Smuzhiyun reg &= ~EHCI_PS_CLEAR;
879*4882a593Smuzhiyun switch (le16_to_cpu(req->value)) {
880*4882a593Smuzhiyun case USB_PORT_FEAT_ENABLE:
881*4882a593Smuzhiyun reg &= ~EHCI_PS_PE;
882*4882a593Smuzhiyun break;
883*4882a593Smuzhiyun case USB_PORT_FEAT_C_ENABLE:
884*4882a593Smuzhiyun reg |= EHCI_PS_PE;
885*4882a593Smuzhiyun break;
886*4882a593Smuzhiyun case USB_PORT_FEAT_POWER:
887*4882a593Smuzhiyun if (HCS_PPC(ehci_readl(&ctrl->hccr->cr_hcsparams)))
888*4882a593Smuzhiyun reg &= ~EHCI_PS_PP;
889*4882a593Smuzhiyun break;
890*4882a593Smuzhiyun case USB_PORT_FEAT_C_CONNECTION:
891*4882a593Smuzhiyun reg |= EHCI_PS_CSC;
892*4882a593Smuzhiyun break;
893*4882a593Smuzhiyun case USB_PORT_FEAT_OVER_CURRENT:
894*4882a593Smuzhiyun reg |= EHCI_PS_OCC;
895*4882a593Smuzhiyun break;
896*4882a593Smuzhiyun case USB_PORT_FEAT_C_RESET:
897*4882a593Smuzhiyun ctrl->portreset &= ~(1 << port);
898*4882a593Smuzhiyun break;
899*4882a593Smuzhiyun default:
900*4882a593Smuzhiyun debug("unknown feature %x\n", le16_to_cpu(req->value));
901*4882a593Smuzhiyun goto unknown;
902*4882a593Smuzhiyun }
903*4882a593Smuzhiyun ehci_writel(status_reg, reg);
904*4882a593Smuzhiyun /* unblock posted write */
905*4882a593Smuzhiyun (void) ehci_readl(&ctrl->hcor->or_usbcmd);
906*4882a593Smuzhiyun break;
907*4882a593Smuzhiyun default:
908*4882a593Smuzhiyun debug("Unknown request\n");
909*4882a593Smuzhiyun goto unknown;
910*4882a593Smuzhiyun }
911*4882a593Smuzhiyun
912*4882a593Smuzhiyun mdelay(1);
913*4882a593Smuzhiyun len = min3(srclen, (int)le16_to_cpu(req->length), length);
914*4882a593Smuzhiyun if (srcptr != NULL && len > 0)
915*4882a593Smuzhiyun memcpy(buffer, srcptr, len);
916*4882a593Smuzhiyun else
917*4882a593Smuzhiyun debug("Len is 0\n");
918*4882a593Smuzhiyun
919*4882a593Smuzhiyun dev->act_len = len;
920*4882a593Smuzhiyun dev->status = 0;
921*4882a593Smuzhiyun return 0;
922*4882a593Smuzhiyun
923*4882a593Smuzhiyun unknown:
924*4882a593Smuzhiyun debug("requesttype=%x, request=%x, value=%x, index=%x, length=%x\n",
925*4882a593Smuzhiyun req->requesttype, req->request, le16_to_cpu(req->value),
926*4882a593Smuzhiyun le16_to_cpu(req->index), le16_to_cpu(req->length));
927*4882a593Smuzhiyun
928*4882a593Smuzhiyun dev->act_len = 0;
929*4882a593Smuzhiyun dev->status = USB_ST_STALLED;
930*4882a593Smuzhiyun return -1;
931*4882a593Smuzhiyun }
932*4882a593Smuzhiyun
933*4882a593Smuzhiyun static const struct ehci_ops default_ehci_ops = {
934*4882a593Smuzhiyun .set_usb_mode = ehci_set_usbmode,
935*4882a593Smuzhiyun .get_port_speed = ehci_get_port_speed,
936*4882a593Smuzhiyun .powerup_fixup = ehci_powerup_fixup,
937*4882a593Smuzhiyun .get_portsc_register = ehci_get_portsc_register,
938*4882a593Smuzhiyun };
939*4882a593Smuzhiyun
ehci_setup_ops(struct ehci_ctrl * ctrl,const struct ehci_ops * ops)940*4882a593Smuzhiyun static void ehci_setup_ops(struct ehci_ctrl *ctrl, const struct ehci_ops *ops)
941*4882a593Smuzhiyun {
942*4882a593Smuzhiyun if (!ops) {
943*4882a593Smuzhiyun ctrl->ops = default_ehci_ops;
944*4882a593Smuzhiyun } else {
945*4882a593Smuzhiyun ctrl->ops = *ops;
946*4882a593Smuzhiyun if (!ctrl->ops.set_usb_mode)
947*4882a593Smuzhiyun ctrl->ops.set_usb_mode = ehci_set_usbmode;
948*4882a593Smuzhiyun if (!ctrl->ops.get_port_speed)
949*4882a593Smuzhiyun ctrl->ops.get_port_speed = ehci_get_port_speed;
950*4882a593Smuzhiyun if (!ctrl->ops.powerup_fixup)
951*4882a593Smuzhiyun ctrl->ops.powerup_fixup = ehci_powerup_fixup;
952*4882a593Smuzhiyun if (!ctrl->ops.get_portsc_register)
953*4882a593Smuzhiyun ctrl->ops.get_portsc_register =
954*4882a593Smuzhiyun ehci_get_portsc_register;
955*4882a593Smuzhiyun }
956*4882a593Smuzhiyun }
957*4882a593Smuzhiyun
958*4882a593Smuzhiyun #if !CONFIG_IS_ENABLED(DM_USB)
ehci_set_controller_priv(int index,void * priv,const struct ehci_ops * ops)959*4882a593Smuzhiyun void ehci_set_controller_priv(int index, void *priv, const struct ehci_ops *ops)
960*4882a593Smuzhiyun {
961*4882a593Smuzhiyun struct ehci_ctrl *ctrl = &ehcic[index];
962*4882a593Smuzhiyun
963*4882a593Smuzhiyun ctrl->priv = priv;
964*4882a593Smuzhiyun ehci_setup_ops(ctrl, ops);
965*4882a593Smuzhiyun }
966*4882a593Smuzhiyun
ehci_get_controller_priv(int index)967*4882a593Smuzhiyun void *ehci_get_controller_priv(int index)
968*4882a593Smuzhiyun {
969*4882a593Smuzhiyun return ehcic[index].priv;
970*4882a593Smuzhiyun }
971*4882a593Smuzhiyun #endif
972*4882a593Smuzhiyun
ehci_common_init(struct ehci_ctrl * ctrl,uint tweaks)973*4882a593Smuzhiyun static int ehci_common_init(struct ehci_ctrl *ctrl, uint tweaks)
974*4882a593Smuzhiyun {
975*4882a593Smuzhiyun struct QH *qh_list;
976*4882a593Smuzhiyun struct QH *periodic;
977*4882a593Smuzhiyun uint32_t reg;
978*4882a593Smuzhiyun uint32_t cmd;
979*4882a593Smuzhiyun int i;
980*4882a593Smuzhiyun
981*4882a593Smuzhiyun /* Set the high address word (aka segment) for 64-bit controller */
982*4882a593Smuzhiyun if (ehci_readl(&ctrl->hccr->cr_hccparams) & 1)
983*4882a593Smuzhiyun ehci_writel(&ctrl->hcor->or_ctrldssegment, 0);
984*4882a593Smuzhiyun
985*4882a593Smuzhiyun qh_list = &ctrl->qh_list;
986*4882a593Smuzhiyun
987*4882a593Smuzhiyun /* Set head of reclaim list */
988*4882a593Smuzhiyun memset(qh_list, 0, sizeof(*qh_list));
989*4882a593Smuzhiyun qh_list->qh_link = cpu_to_hc32(virt_to_phys(qh_list) | QH_LINK_TYPE_QH);
990*4882a593Smuzhiyun qh_list->qh_endpt1 = cpu_to_hc32(QH_ENDPT1_H(1) |
991*4882a593Smuzhiyun QH_ENDPT1_EPS(USB_SPEED_HIGH));
992*4882a593Smuzhiyun qh_list->qh_overlay.qt_next = cpu_to_hc32(QT_NEXT_TERMINATE);
993*4882a593Smuzhiyun qh_list->qh_overlay.qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE);
994*4882a593Smuzhiyun qh_list->qh_overlay.qt_token =
995*4882a593Smuzhiyun cpu_to_hc32(QT_TOKEN_STATUS(QT_TOKEN_STATUS_HALTED));
996*4882a593Smuzhiyun
997*4882a593Smuzhiyun flush_dcache_range((unsigned long)qh_list,
998*4882a593Smuzhiyun ALIGN_END_ADDR(struct QH, qh_list, 1));
999*4882a593Smuzhiyun
1000*4882a593Smuzhiyun /* Set async. queue head pointer. */
1001*4882a593Smuzhiyun ehci_writel(&ctrl->hcor->or_asynclistaddr, virt_to_phys(qh_list));
1002*4882a593Smuzhiyun
1003*4882a593Smuzhiyun /*
1004*4882a593Smuzhiyun * Set up periodic list
1005*4882a593Smuzhiyun * Step 1: Parent QH for all periodic transfers.
1006*4882a593Smuzhiyun */
1007*4882a593Smuzhiyun ctrl->periodic_schedules = 0;
1008*4882a593Smuzhiyun periodic = &ctrl->periodic_queue;
1009*4882a593Smuzhiyun memset(periodic, 0, sizeof(*periodic));
1010*4882a593Smuzhiyun periodic->qh_link = cpu_to_hc32(QH_LINK_TERMINATE);
1011*4882a593Smuzhiyun periodic->qh_overlay.qt_next = cpu_to_hc32(QT_NEXT_TERMINATE);
1012*4882a593Smuzhiyun periodic->qh_overlay.qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE);
1013*4882a593Smuzhiyun
1014*4882a593Smuzhiyun flush_dcache_range((unsigned long)periodic,
1015*4882a593Smuzhiyun ALIGN_END_ADDR(struct QH, periodic, 1));
1016*4882a593Smuzhiyun
1017*4882a593Smuzhiyun /*
1018*4882a593Smuzhiyun * Step 2: Setup frame-list: Every microframe, USB tries the same list.
1019*4882a593Smuzhiyun * In particular, device specifications on polling frequency
1020*4882a593Smuzhiyun * are disregarded. Keyboards seem to send NAK/NYet reliably
1021*4882a593Smuzhiyun * when polled with an empty buffer.
1022*4882a593Smuzhiyun *
1023*4882a593Smuzhiyun * Split Transactions will be spread across microframes using
1024*4882a593Smuzhiyun * S-mask and C-mask.
1025*4882a593Smuzhiyun */
1026*4882a593Smuzhiyun if (ctrl->periodic_list == NULL)
1027*4882a593Smuzhiyun ctrl->periodic_list = memalign(4096, 1024 * 4);
1028*4882a593Smuzhiyun
1029*4882a593Smuzhiyun if (!ctrl->periodic_list)
1030*4882a593Smuzhiyun return -ENOMEM;
1031*4882a593Smuzhiyun for (i = 0; i < 1024; i++) {
1032*4882a593Smuzhiyun ctrl->periodic_list[i] = cpu_to_hc32((unsigned long)periodic
1033*4882a593Smuzhiyun | QH_LINK_TYPE_QH);
1034*4882a593Smuzhiyun }
1035*4882a593Smuzhiyun
1036*4882a593Smuzhiyun flush_dcache_range((unsigned long)ctrl->periodic_list,
1037*4882a593Smuzhiyun ALIGN_END_ADDR(uint32_t, ctrl->periodic_list,
1038*4882a593Smuzhiyun 1024));
1039*4882a593Smuzhiyun
1040*4882a593Smuzhiyun /* Set periodic list base address */
1041*4882a593Smuzhiyun ehci_writel(&ctrl->hcor->or_periodiclistbase,
1042*4882a593Smuzhiyun (unsigned long)ctrl->periodic_list);
1043*4882a593Smuzhiyun
1044*4882a593Smuzhiyun reg = ehci_readl(&ctrl->hccr->cr_hcsparams);
1045*4882a593Smuzhiyun descriptor.hub.bNbrPorts = HCS_N_PORTS(reg);
1046*4882a593Smuzhiyun debug("Register %x NbrPorts %d\n", reg, descriptor.hub.bNbrPorts);
1047*4882a593Smuzhiyun /* Port Indicators */
1048*4882a593Smuzhiyun if (HCS_INDICATOR(reg))
1049*4882a593Smuzhiyun put_unaligned(get_unaligned(&descriptor.hub.wHubCharacteristics)
1050*4882a593Smuzhiyun | 0x80, &descriptor.hub.wHubCharacteristics);
1051*4882a593Smuzhiyun /* Port Power Control */
1052*4882a593Smuzhiyun if (HCS_PPC(reg))
1053*4882a593Smuzhiyun put_unaligned(get_unaligned(&descriptor.hub.wHubCharacteristics)
1054*4882a593Smuzhiyun | 0x01, &descriptor.hub.wHubCharacteristics);
1055*4882a593Smuzhiyun
1056*4882a593Smuzhiyun memcpy(&ctrl->hub, &descriptor, sizeof(struct usb_hub_descriptor));
1057*4882a593Smuzhiyun
1058*4882a593Smuzhiyun /* Start the host controller. */
1059*4882a593Smuzhiyun cmd = ehci_readl(&ctrl->hcor->or_usbcmd);
1060*4882a593Smuzhiyun /*
1061*4882a593Smuzhiyun * Philips, Intel, and maybe others need CMD_RUN before the
1062*4882a593Smuzhiyun * root hub will detect new devices (why?); NEC doesn't
1063*4882a593Smuzhiyun */
1064*4882a593Smuzhiyun cmd &= ~(CMD_LRESET|CMD_IAAD|CMD_PSE|CMD_ASE|CMD_RESET);
1065*4882a593Smuzhiyun cmd |= CMD_RUN;
1066*4882a593Smuzhiyun ehci_writel(&ctrl->hcor->or_usbcmd, cmd);
1067*4882a593Smuzhiyun
1068*4882a593Smuzhiyun if (!(tweaks & EHCI_TWEAK_NO_INIT_CF)) {
1069*4882a593Smuzhiyun /* take control over the ports */
1070*4882a593Smuzhiyun cmd = ehci_readl(&ctrl->hcor->or_configflag);
1071*4882a593Smuzhiyun cmd |= FLAG_CF;
1072*4882a593Smuzhiyun ehci_writel(&ctrl->hcor->or_configflag, cmd);
1073*4882a593Smuzhiyun }
1074*4882a593Smuzhiyun
1075*4882a593Smuzhiyun /* unblock posted write */
1076*4882a593Smuzhiyun cmd = ehci_readl(&ctrl->hcor->or_usbcmd);
1077*4882a593Smuzhiyun mdelay(5);
1078*4882a593Smuzhiyun reg = HC_VERSION(ehci_readl(&ctrl->hccr->cr_capbase));
1079*4882a593Smuzhiyun printf("USB EHCI %x.%02x\n", reg >> 8, reg & 0xff);
1080*4882a593Smuzhiyun
1081*4882a593Smuzhiyun return 0;
1082*4882a593Smuzhiyun }
1083*4882a593Smuzhiyun
1084*4882a593Smuzhiyun #if !CONFIG_IS_ENABLED(DM_USB)
usb_lowlevel_stop(int index)1085*4882a593Smuzhiyun int usb_lowlevel_stop(int index)
1086*4882a593Smuzhiyun {
1087*4882a593Smuzhiyun ehci_shutdown(&ehcic[index]);
1088*4882a593Smuzhiyun return ehci_hcd_stop(index);
1089*4882a593Smuzhiyun }
1090*4882a593Smuzhiyun
usb_lowlevel_init(int index,enum usb_init_type init,void ** controller)1091*4882a593Smuzhiyun int usb_lowlevel_init(int index, enum usb_init_type init, void **controller)
1092*4882a593Smuzhiyun {
1093*4882a593Smuzhiyun struct ehci_ctrl *ctrl = &ehcic[index];
1094*4882a593Smuzhiyun uint tweaks = 0;
1095*4882a593Smuzhiyun int rc;
1096*4882a593Smuzhiyun
1097*4882a593Smuzhiyun /**
1098*4882a593Smuzhiyun * Set ops to default_ehci_ops, ehci_hcd_init should call
1099*4882a593Smuzhiyun * ehci_set_controller_priv to change any of these function pointers.
1100*4882a593Smuzhiyun */
1101*4882a593Smuzhiyun ctrl->ops = default_ehci_ops;
1102*4882a593Smuzhiyun
1103*4882a593Smuzhiyun rc = ehci_hcd_init(index, init, &ctrl->hccr, &ctrl->hcor);
1104*4882a593Smuzhiyun if (rc)
1105*4882a593Smuzhiyun return rc;
1106*4882a593Smuzhiyun if (!ctrl->hccr || !ctrl->hcor)
1107*4882a593Smuzhiyun return -1;
1108*4882a593Smuzhiyun if (init == USB_INIT_DEVICE)
1109*4882a593Smuzhiyun goto done;
1110*4882a593Smuzhiyun
1111*4882a593Smuzhiyun /* EHCI spec section 4.1 */
1112*4882a593Smuzhiyun if (ehci_reset(ctrl))
1113*4882a593Smuzhiyun return -1;
1114*4882a593Smuzhiyun
1115*4882a593Smuzhiyun #if defined(CONFIG_EHCI_HCD_INIT_AFTER_RESET)
1116*4882a593Smuzhiyun rc = ehci_hcd_init(index, init, &ctrl->hccr, &ctrl->hcor);
1117*4882a593Smuzhiyun if (rc)
1118*4882a593Smuzhiyun return rc;
1119*4882a593Smuzhiyun #endif
1120*4882a593Smuzhiyun #ifdef CONFIG_USB_EHCI_FARADAY
1121*4882a593Smuzhiyun tweaks |= EHCI_TWEAK_NO_INIT_CF;
1122*4882a593Smuzhiyun #endif
1123*4882a593Smuzhiyun rc = ehci_common_init(ctrl, tweaks);
1124*4882a593Smuzhiyun if (rc)
1125*4882a593Smuzhiyun return rc;
1126*4882a593Smuzhiyun
1127*4882a593Smuzhiyun ctrl->rootdev = 0;
1128*4882a593Smuzhiyun done:
1129*4882a593Smuzhiyun *controller = &ehcic[index];
1130*4882a593Smuzhiyun return 0;
1131*4882a593Smuzhiyun }
1132*4882a593Smuzhiyun #endif
1133*4882a593Smuzhiyun
_ehci_submit_bulk_msg(struct usb_device * dev,unsigned long pipe,void * buffer,int length)1134*4882a593Smuzhiyun static int _ehci_submit_bulk_msg(struct usb_device *dev, unsigned long pipe,
1135*4882a593Smuzhiyun void *buffer, int length)
1136*4882a593Smuzhiyun {
1137*4882a593Smuzhiyun
1138*4882a593Smuzhiyun if (usb_pipetype(pipe) != PIPE_BULK) {
1139*4882a593Smuzhiyun debug("non-bulk pipe (type=%lu)", usb_pipetype(pipe));
1140*4882a593Smuzhiyun return -1;
1141*4882a593Smuzhiyun }
1142*4882a593Smuzhiyun return ehci_submit_async(dev, pipe, buffer, length, NULL);
1143*4882a593Smuzhiyun }
1144*4882a593Smuzhiyun
_ehci_submit_control_msg(struct usb_device * dev,unsigned long pipe,void * buffer,int length,struct devrequest * setup)1145*4882a593Smuzhiyun static int _ehci_submit_control_msg(struct usb_device *dev, unsigned long pipe,
1146*4882a593Smuzhiyun void *buffer, int length,
1147*4882a593Smuzhiyun struct devrequest *setup)
1148*4882a593Smuzhiyun {
1149*4882a593Smuzhiyun struct ehci_ctrl *ctrl = ehci_get_ctrl(dev);
1150*4882a593Smuzhiyun
1151*4882a593Smuzhiyun if (usb_pipetype(pipe) != PIPE_CONTROL) {
1152*4882a593Smuzhiyun debug("non-control pipe (type=%lu)", usb_pipetype(pipe));
1153*4882a593Smuzhiyun return -1;
1154*4882a593Smuzhiyun }
1155*4882a593Smuzhiyun
1156*4882a593Smuzhiyun if (usb_pipedevice(pipe) == ctrl->rootdev) {
1157*4882a593Smuzhiyun if (!ctrl->rootdev)
1158*4882a593Smuzhiyun dev->speed = USB_SPEED_HIGH;
1159*4882a593Smuzhiyun return ehci_submit_root(dev, pipe, buffer, length, setup);
1160*4882a593Smuzhiyun }
1161*4882a593Smuzhiyun return ehci_submit_async(dev, pipe, buffer, length, setup);
1162*4882a593Smuzhiyun }
1163*4882a593Smuzhiyun
1164*4882a593Smuzhiyun struct int_queue {
1165*4882a593Smuzhiyun int elementsize;
1166*4882a593Smuzhiyun unsigned long pipe;
1167*4882a593Smuzhiyun struct QH *first;
1168*4882a593Smuzhiyun struct QH *current;
1169*4882a593Smuzhiyun struct QH *last;
1170*4882a593Smuzhiyun struct qTD *tds;
1171*4882a593Smuzhiyun };
1172*4882a593Smuzhiyun
1173*4882a593Smuzhiyun #define NEXT_QH(qh) (struct QH *)((unsigned long)hc32_to_cpu((qh)->qh_link) & ~0x1f)
1174*4882a593Smuzhiyun
1175*4882a593Smuzhiyun static int
enable_periodic(struct ehci_ctrl * ctrl)1176*4882a593Smuzhiyun enable_periodic(struct ehci_ctrl *ctrl)
1177*4882a593Smuzhiyun {
1178*4882a593Smuzhiyun uint32_t cmd;
1179*4882a593Smuzhiyun struct ehci_hcor *hcor = ctrl->hcor;
1180*4882a593Smuzhiyun int ret;
1181*4882a593Smuzhiyun
1182*4882a593Smuzhiyun cmd = ehci_readl(&hcor->or_usbcmd);
1183*4882a593Smuzhiyun cmd |= CMD_PSE;
1184*4882a593Smuzhiyun ehci_writel(&hcor->or_usbcmd, cmd);
1185*4882a593Smuzhiyun
1186*4882a593Smuzhiyun ret = handshake((uint32_t *)&hcor->or_usbsts,
1187*4882a593Smuzhiyun STS_PSS, STS_PSS, 100 * 1000);
1188*4882a593Smuzhiyun if (ret < 0) {
1189*4882a593Smuzhiyun printf("EHCI failed: timeout when enabling periodic list\n");
1190*4882a593Smuzhiyun return -ETIMEDOUT;
1191*4882a593Smuzhiyun }
1192*4882a593Smuzhiyun udelay(1000);
1193*4882a593Smuzhiyun return 0;
1194*4882a593Smuzhiyun }
1195*4882a593Smuzhiyun
1196*4882a593Smuzhiyun static int
disable_periodic(struct ehci_ctrl * ctrl)1197*4882a593Smuzhiyun disable_periodic(struct ehci_ctrl *ctrl)
1198*4882a593Smuzhiyun {
1199*4882a593Smuzhiyun uint32_t cmd;
1200*4882a593Smuzhiyun struct ehci_hcor *hcor = ctrl->hcor;
1201*4882a593Smuzhiyun int ret;
1202*4882a593Smuzhiyun
1203*4882a593Smuzhiyun cmd = ehci_readl(&hcor->or_usbcmd);
1204*4882a593Smuzhiyun cmd &= ~CMD_PSE;
1205*4882a593Smuzhiyun ehci_writel(&hcor->or_usbcmd, cmd);
1206*4882a593Smuzhiyun
1207*4882a593Smuzhiyun ret = handshake((uint32_t *)&hcor->or_usbsts,
1208*4882a593Smuzhiyun STS_PSS, 0, 100 * 1000);
1209*4882a593Smuzhiyun if (ret < 0) {
1210*4882a593Smuzhiyun printf("EHCI failed: timeout when disabling periodic list\n");
1211*4882a593Smuzhiyun return -ETIMEDOUT;
1212*4882a593Smuzhiyun }
1213*4882a593Smuzhiyun return 0;
1214*4882a593Smuzhiyun }
1215*4882a593Smuzhiyun
_ehci_create_int_queue(struct usb_device * dev,unsigned long pipe,int queuesize,int elementsize,void * buffer,int interval)1216*4882a593Smuzhiyun static struct int_queue *_ehci_create_int_queue(struct usb_device *dev,
1217*4882a593Smuzhiyun unsigned long pipe, int queuesize, int elementsize,
1218*4882a593Smuzhiyun void *buffer, int interval)
1219*4882a593Smuzhiyun {
1220*4882a593Smuzhiyun struct ehci_ctrl *ctrl = ehci_get_ctrl(dev);
1221*4882a593Smuzhiyun struct int_queue *result = NULL;
1222*4882a593Smuzhiyun uint32_t i, toggle;
1223*4882a593Smuzhiyun
1224*4882a593Smuzhiyun /*
1225*4882a593Smuzhiyun * Interrupt transfers requiring several transactions are not supported
1226*4882a593Smuzhiyun * because bInterval is ignored.
1227*4882a593Smuzhiyun *
1228*4882a593Smuzhiyun * Also, ehci_submit_async() relies on wMaxPacketSize being a power of 2
1229*4882a593Smuzhiyun * <= PKT_ALIGN if several qTDs are required, while the USB
1230*4882a593Smuzhiyun * specification does not constrain this for interrupt transfers. That
1231*4882a593Smuzhiyun * means that ehci_submit_async() would support interrupt transfers
1232*4882a593Smuzhiyun * requiring several transactions only as long as the transfer size does
1233*4882a593Smuzhiyun * not require more than a single qTD.
1234*4882a593Smuzhiyun */
1235*4882a593Smuzhiyun if (elementsize > usb_maxpacket(dev, pipe)) {
1236*4882a593Smuzhiyun printf("%s: xfers requiring several transactions are not supported.\n",
1237*4882a593Smuzhiyun __func__);
1238*4882a593Smuzhiyun return NULL;
1239*4882a593Smuzhiyun }
1240*4882a593Smuzhiyun
1241*4882a593Smuzhiyun debug("Enter create_int_queue\n");
1242*4882a593Smuzhiyun if (usb_pipetype(pipe) != PIPE_INTERRUPT) {
1243*4882a593Smuzhiyun debug("non-interrupt pipe (type=%lu)", usb_pipetype(pipe));
1244*4882a593Smuzhiyun return NULL;
1245*4882a593Smuzhiyun }
1246*4882a593Smuzhiyun
1247*4882a593Smuzhiyun /* limit to 4 full pages worth of data -
1248*4882a593Smuzhiyun * we can safely fit them in a single TD,
1249*4882a593Smuzhiyun * no matter the alignment
1250*4882a593Smuzhiyun */
1251*4882a593Smuzhiyun if (elementsize >= 16384) {
1252*4882a593Smuzhiyun debug("too large elements for interrupt transfers\n");
1253*4882a593Smuzhiyun return NULL;
1254*4882a593Smuzhiyun }
1255*4882a593Smuzhiyun
1256*4882a593Smuzhiyun result = malloc(sizeof(*result));
1257*4882a593Smuzhiyun if (!result) {
1258*4882a593Smuzhiyun debug("ehci intr queue: out of memory\n");
1259*4882a593Smuzhiyun goto fail1;
1260*4882a593Smuzhiyun }
1261*4882a593Smuzhiyun result->elementsize = elementsize;
1262*4882a593Smuzhiyun result->pipe = pipe;
1263*4882a593Smuzhiyun result->first = memalign(USB_DMA_MINALIGN,
1264*4882a593Smuzhiyun sizeof(struct QH) * queuesize);
1265*4882a593Smuzhiyun if (!result->first) {
1266*4882a593Smuzhiyun debug("ehci intr queue: out of memory\n");
1267*4882a593Smuzhiyun goto fail2;
1268*4882a593Smuzhiyun }
1269*4882a593Smuzhiyun result->current = result->first;
1270*4882a593Smuzhiyun result->last = result->first + queuesize - 1;
1271*4882a593Smuzhiyun result->tds = memalign(USB_DMA_MINALIGN,
1272*4882a593Smuzhiyun sizeof(struct qTD) * queuesize);
1273*4882a593Smuzhiyun if (!result->tds) {
1274*4882a593Smuzhiyun debug("ehci intr queue: out of memory\n");
1275*4882a593Smuzhiyun goto fail3;
1276*4882a593Smuzhiyun }
1277*4882a593Smuzhiyun memset(result->first, 0, sizeof(struct QH) * queuesize);
1278*4882a593Smuzhiyun memset(result->tds, 0, sizeof(struct qTD) * queuesize);
1279*4882a593Smuzhiyun
1280*4882a593Smuzhiyun toggle = usb_gettoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe));
1281*4882a593Smuzhiyun
1282*4882a593Smuzhiyun for (i = 0; i < queuesize; i++) {
1283*4882a593Smuzhiyun struct QH *qh = result->first + i;
1284*4882a593Smuzhiyun struct qTD *td = result->tds + i;
1285*4882a593Smuzhiyun void **buf = &qh->buffer;
1286*4882a593Smuzhiyun
1287*4882a593Smuzhiyun qh->qh_link = cpu_to_hc32((unsigned long)(qh+1) | QH_LINK_TYPE_QH);
1288*4882a593Smuzhiyun if (i == queuesize - 1)
1289*4882a593Smuzhiyun qh->qh_link = cpu_to_hc32(QH_LINK_TERMINATE);
1290*4882a593Smuzhiyun
1291*4882a593Smuzhiyun qh->qh_overlay.qt_next = cpu_to_hc32((unsigned long)td);
1292*4882a593Smuzhiyun qh->qh_overlay.qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE);
1293*4882a593Smuzhiyun qh->qh_endpt1 =
1294*4882a593Smuzhiyun cpu_to_hc32((0 << 28) | /* No NAK reload (ehci 4.9) */
1295*4882a593Smuzhiyun (usb_maxpacket(dev, pipe) << 16) | /* MPS */
1296*4882a593Smuzhiyun (1 << 14) |
1297*4882a593Smuzhiyun QH_ENDPT1_EPS(ehci_encode_speed(dev->speed)) |
1298*4882a593Smuzhiyun (usb_pipeendpoint(pipe) << 8) | /* Endpoint Number */
1299*4882a593Smuzhiyun (usb_pipedevice(pipe) << 0));
1300*4882a593Smuzhiyun qh->qh_endpt2 = cpu_to_hc32((1 << 30) | /* 1 Tx per mframe */
1301*4882a593Smuzhiyun (1 << 0)); /* S-mask: microframe 0 */
1302*4882a593Smuzhiyun if (dev->speed == USB_SPEED_LOW ||
1303*4882a593Smuzhiyun dev->speed == USB_SPEED_FULL) {
1304*4882a593Smuzhiyun /* C-mask: microframes 2-4 */
1305*4882a593Smuzhiyun qh->qh_endpt2 |= cpu_to_hc32((0x1c << 8));
1306*4882a593Smuzhiyun }
1307*4882a593Smuzhiyun ehci_update_endpt2_dev_n_port(dev, qh);
1308*4882a593Smuzhiyun
1309*4882a593Smuzhiyun td->qt_next = cpu_to_hc32(QT_NEXT_TERMINATE);
1310*4882a593Smuzhiyun td->qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE);
1311*4882a593Smuzhiyun debug("communication direction is '%s'\n",
1312*4882a593Smuzhiyun usb_pipein(pipe) ? "in" : "out");
1313*4882a593Smuzhiyun td->qt_token = cpu_to_hc32(
1314*4882a593Smuzhiyun QT_TOKEN_DT(toggle) |
1315*4882a593Smuzhiyun (elementsize << 16) |
1316*4882a593Smuzhiyun ((usb_pipein(pipe) ? 1 : 0) << 8) | /* IN/OUT token */
1317*4882a593Smuzhiyun 0x80); /* active */
1318*4882a593Smuzhiyun td->qt_buffer[0] =
1319*4882a593Smuzhiyun cpu_to_hc32((unsigned long)buffer + i * elementsize);
1320*4882a593Smuzhiyun td->qt_buffer[1] =
1321*4882a593Smuzhiyun cpu_to_hc32((td->qt_buffer[0] + 0x1000) & ~0xfff);
1322*4882a593Smuzhiyun td->qt_buffer[2] =
1323*4882a593Smuzhiyun cpu_to_hc32((td->qt_buffer[0] + 0x2000) & ~0xfff);
1324*4882a593Smuzhiyun td->qt_buffer[3] =
1325*4882a593Smuzhiyun cpu_to_hc32((td->qt_buffer[0] + 0x3000) & ~0xfff);
1326*4882a593Smuzhiyun td->qt_buffer[4] =
1327*4882a593Smuzhiyun cpu_to_hc32((td->qt_buffer[0] + 0x4000) & ~0xfff);
1328*4882a593Smuzhiyun
1329*4882a593Smuzhiyun *buf = buffer + i * elementsize;
1330*4882a593Smuzhiyun toggle ^= 1;
1331*4882a593Smuzhiyun }
1332*4882a593Smuzhiyun
1333*4882a593Smuzhiyun flush_dcache_range((unsigned long)buffer,
1334*4882a593Smuzhiyun ALIGN_END_ADDR(char, buffer,
1335*4882a593Smuzhiyun queuesize * elementsize));
1336*4882a593Smuzhiyun flush_dcache_range((unsigned long)result->first,
1337*4882a593Smuzhiyun ALIGN_END_ADDR(struct QH, result->first,
1338*4882a593Smuzhiyun queuesize));
1339*4882a593Smuzhiyun flush_dcache_range((unsigned long)result->tds,
1340*4882a593Smuzhiyun ALIGN_END_ADDR(struct qTD, result->tds,
1341*4882a593Smuzhiyun queuesize));
1342*4882a593Smuzhiyun
1343*4882a593Smuzhiyun if (ctrl->periodic_schedules > 0) {
1344*4882a593Smuzhiyun if (disable_periodic(ctrl) < 0) {
1345*4882a593Smuzhiyun debug("FATAL: periodic should never fail, but did");
1346*4882a593Smuzhiyun goto fail3;
1347*4882a593Smuzhiyun }
1348*4882a593Smuzhiyun }
1349*4882a593Smuzhiyun
1350*4882a593Smuzhiyun /* hook up to periodic list */
1351*4882a593Smuzhiyun struct QH *list = &ctrl->periodic_queue;
1352*4882a593Smuzhiyun result->last->qh_link = list->qh_link;
1353*4882a593Smuzhiyun list->qh_link = cpu_to_hc32((unsigned long)result->first | QH_LINK_TYPE_QH);
1354*4882a593Smuzhiyun
1355*4882a593Smuzhiyun flush_dcache_range((unsigned long)result->last,
1356*4882a593Smuzhiyun ALIGN_END_ADDR(struct QH, result->last, 1));
1357*4882a593Smuzhiyun flush_dcache_range((unsigned long)list,
1358*4882a593Smuzhiyun ALIGN_END_ADDR(struct QH, list, 1));
1359*4882a593Smuzhiyun
1360*4882a593Smuzhiyun if (enable_periodic(ctrl) < 0) {
1361*4882a593Smuzhiyun debug("FATAL: periodic should never fail, but did");
1362*4882a593Smuzhiyun goto fail3;
1363*4882a593Smuzhiyun }
1364*4882a593Smuzhiyun ctrl->periodic_schedules++;
1365*4882a593Smuzhiyun
1366*4882a593Smuzhiyun debug("Exit create_int_queue\n");
1367*4882a593Smuzhiyun return result;
1368*4882a593Smuzhiyun fail3:
1369*4882a593Smuzhiyun if (result->tds)
1370*4882a593Smuzhiyun free(result->tds);
1371*4882a593Smuzhiyun fail2:
1372*4882a593Smuzhiyun if (result->first)
1373*4882a593Smuzhiyun free(result->first);
1374*4882a593Smuzhiyun if (result)
1375*4882a593Smuzhiyun free(result);
1376*4882a593Smuzhiyun fail1:
1377*4882a593Smuzhiyun return NULL;
1378*4882a593Smuzhiyun }
1379*4882a593Smuzhiyun
_ehci_poll_int_queue(struct usb_device * dev,struct int_queue * queue)1380*4882a593Smuzhiyun static void *_ehci_poll_int_queue(struct usb_device *dev,
1381*4882a593Smuzhiyun struct int_queue *queue)
1382*4882a593Smuzhiyun {
1383*4882a593Smuzhiyun struct QH *cur = queue->current;
1384*4882a593Smuzhiyun struct qTD *cur_td;
1385*4882a593Smuzhiyun uint32_t token, toggle;
1386*4882a593Smuzhiyun unsigned long pipe = queue->pipe;
1387*4882a593Smuzhiyun
1388*4882a593Smuzhiyun /* depleted queue */
1389*4882a593Smuzhiyun if (cur == NULL) {
1390*4882a593Smuzhiyun debug("Exit poll_int_queue with completed queue\n");
1391*4882a593Smuzhiyun return NULL;
1392*4882a593Smuzhiyun }
1393*4882a593Smuzhiyun /* still active */
1394*4882a593Smuzhiyun cur_td = &queue->tds[queue->current - queue->first];
1395*4882a593Smuzhiyun invalidate_dcache_range((unsigned long)cur_td,
1396*4882a593Smuzhiyun ALIGN_END_ADDR(struct qTD, cur_td, 1));
1397*4882a593Smuzhiyun token = hc32_to_cpu(cur_td->qt_token);
1398*4882a593Smuzhiyun if (QT_TOKEN_GET_STATUS(token) & QT_TOKEN_STATUS_ACTIVE) {
1399*4882a593Smuzhiyun debug("Exit poll_int_queue with no completed intr transfer. token is %x\n", token);
1400*4882a593Smuzhiyun return NULL;
1401*4882a593Smuzhiyun }
1402*4882a593Smuzhiyun
1403*4882a593Smuzhiyun toggle = QT_TOKEN_GET_DT(token);
1404*4882a593Smuzhiyun usb_settoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe), toggle);
1405*4882a593Smuzhiyun
1406*4882a593Smuzhiyun if (!(cur->qh_link & QH_LINK_TERMINATE))
1407*4882a593Smuzhiyun queue->current++;
1408*4882a593Smuzhiyun else
1409*4882a593Smuzhiyun queue->current = NULL;
1410*4882a593Smuzhiyun
1411*4882a593Smuzhiyun invalidate_dcache_range((unsigned long)cur->buffer,
1412*4882a593Smuzhiyun ALIGN_END_ADDR(char, cur->buffer,
1413*4882a593Smuzhiyun queue->elementsize));
1414*4882a593Smuzhiyun
1415*4882a593Smuzhiyun debug("Exit poll_int_queue with completed intr transfer. token is %x at %p (first at %p)\n",
1416*4882a593Smuzhiyun token, cur, queue->first);
1417*4882a593Smuzhiyun return cur->buffer;
1418*4882a593Smuzhiyun }
1419*4882a593Smuzhiyun
1420*4882a593Smuzhiyun /* Do not free buffers associated with QHs, they're owned by someone else */
_ehci_destroy_int_queue(struct usb_device * dev,struct int_queue * queue)1421*4882a593Smuzhiyun static int _ehci_destroy_int_queue(struct usb_device *dev,
1422*4882a593Smuzhiyun struct int_queue *queue)
1423*4882a593Smuzhiyun {
1424*4882a593Smuzhiyun struct ehci_ctrl *ctrl = ehci_get_ctrl(dev);
1425*4882a593Smuzhiyun int result = -1;
1426*4882a593Smuzhiyun unsigned long timeout;
1427*4882a593Smuzhiyun
1428*4882a593Smuzhiyun if (disable_periodic(ctrl) < 0) {
1429*4882a593Smuzhiyun debug("FATAL: periodic should never fail, but did");
1430*4882a593Smuzhiyun goto out;
1431*4882a593Smuzhiyun }
1432*4882a593Smuzhiyun ctrl->periodic_schedules--;
1433*4882a593Smuzhiyun
1434*4882a593Smuzhiyun struct QH *cur = &ctrl->periodic_queue;
1435*4882a593Smuzhiyun timeout = get_timer(0) + 500; /* abort after 500ms */
1436*4882a593Smuzhiyun while (!(cur->qh_link & cpu_to_hc32(QH_LINK_TERMINATE))) {
1437*4882a593Smuzhiyun debug("considering %p, with qh_link %x\n", cur, cur->qh_link);
1438*4882a593Smuzhiyun if (NEXT_QH(cur) == queue->first) {
1439*4882a593Smuzhiyun debug("found candidate. removing from chain\n");
1440*4882a593Smuzhiyun cur->qh_link = queue->last->qh_link;
1441*4882a593Smuzhiyun flush_dcache_range((unsigned long)cur,
1442*4882a593Smuzhiyun ALIGN_END_ADDR(struct QH, cur, 1));
1443*4882a593Smuzhiyun result = 0;
1444*4882a593Smuzhiyun break;
1445*4882a593Smuzhiyun }
1446*4882a593Smuzhiyun cur = NEXT_QH(cur);
1447*4882a593Smuzhiyun if (get_timer(0) > timeout) {
1448*4882a593Smuzhiyun printf("Timeout destroying interrupt endpoint queue\n");
1449*4882a593Smuzhiyun result = -1;
1450*4882a593Smuzhiyun goto out;
1451*4882a593Smuzhiyun }
1452*4882a593Smuzhiyun }
1453*4882a593Smuzhiyun
1454*4882a593Smuzhiyun if (ctrl->periodic_schedules > 0) {
1455*4882a593Smuzhiyun result = enable_periodic(ctrl);
1456*4882a593Smuzhiyun if (result < 0)
1457*4882a593Smuzhiyun debug("FATAL: periodic should never fail, but did");
1458*4882a593Smuzhiyun }
1459*4882a593Smuzhiyun
1460*4882a593Smuzhiyun out:
1461*4882a593Smuzhiyun free(queue->tds);
1462*4882a593Smuzhiyun free(queue->first);
1463*4882a593Smuzhiyun free(queue);
1464*4882a593Smuzhiyun
1465*4882a593Smuzhiyun return result;
1466*4882a593Smuzhiyun }
1467*4882a593Smuzhiyun
_ehci_submit_int_msg(struct usb_device * dev,unsigned long pipe,void * buffer,int length,int interval,bool nonblock)1468*4882a593Smuzhiyun static int _ehci_submit_int_msg(struct usb_device *dev, unsigned long pipe,
1469*4882a593Smuzhiyun void *buffer, int length, int interval,
1470*4882a593Smuzhiyun bool nonblock)
1471*4882a593Smuzhiyun {
1472*4882a593Smuzhiyun void *backbuffer;
1473*4882a593Smuzhiyun struct int_queue *queue;
1474*4882a593Smuzhiyun unsigned long timeout;
1475*4882a593Smuzhiyun int result = 0, ret;
1476*4882a593Smuzhiyun
1477*4882a593Smuzhiyun debug("dev=%p, pipe=%lu, buffer=%p, length=%d, interval=%d",
1478*4882a593Smuzhiyun dev, pipe, buffer, length, interval);
1479*4882a593Smuzhiyun
1480*4882a593Smuzhiyun queue = _ehci_create_int_queue(dev, pipe, 1, length, buffer, interval);
1481*4882a593Smuzhiyun if (!queue)
1482*4882a593Smuzhiyun return -1;
1483*4882a593Smuzhiyun
1484*4882a593Smuzhiyun timeout = get_timer(0) + USB_TIMEOUT_MS(pipe);
1485*4882a593Smuzhiyun while ((backbuffer = _ehci_poll_int_queue(dev, queue)) == NULL)
1486*4882a593Smuzhiyun if (get_timer(0) > timeout) {
1487*4882a593Smuzhiyun printf("Timeout poll on interrupt endpoint\n");
1488*4882a593Smuzhiyun result = -ETIMEDOUT;
1489*4882a593Smuzhiyun break;
1490*4882a593Smuzhiyun }
1491*4882a593Smuzhiyun
1492*4882a593Smuzhiyun if (backbuffer != buffer) {
1493*4882a593Smuzhiyun debug("got wrong buffer back (%p instead of %p)\n",
1494*4882a593Smuzhiyun backbuffer, buffer);
1495*4882a593Smuzhiyun return -EINVAL;
1496*4882a593Smuzhiyun }
1497*4882a593Smuzhiyun
1498*4882a593Smuzhiyun ret = _ehci_destroy_int_queue(dev, queue);
1499*4882a593Smuzhiyun if (ret < 0)
1500*4882a593Smuzhiyun return ret;
1501*4882a593Smuzhiyun
1502*4882a593Smuzhiyun /* everything worked out fine */
1503*4882a593Smuzhiyun return result;
1504*4882a593Smuzhiyun }
1505*4882a593Smuzhiyun
1506*4882a593Smuzhiyun #if !CONFIG_IS_ENABLED(DM_USB)
submit_bulk_msg(struct usb_device * dev,unsigned long pipe,void * buffer,int length)1507*4882a593Smuzhiyun int submit_bulk_msg(struct usb_device *dev, unsigned long pipe,
1508*4882a593Smuzhiyun void *buffer, int length)
1509*4882a593Smuzhiyun {
1510*4882a593Smuzhiyun return _ehci_submit_bulk_msg(dev, pipe, buffer, length);
1511*4882a593Smuzhiyun }
1512*4882a593Smuzhiyun
submit_control_msg(struct usb_device * dev,unsigned long pipe,void * buffer,int length,struct devrequest * setup)1513*4882a593Smuzhiyun int submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
1514*4882a593Smuzhiyun int length, struct devrequest *setup)
1515*4882a593Smuzhiyun {
1516*4882a593Smuzhiyun return _ehci_submit_control_msg(dev, pipe, buffer, length, setup);
1517*4882a593Smuzhiyun }
1518*4882a593Smuzhiyun
submit_int_msg(struct usb_device * dev,unsigned long pipe,void * buffer,int length,int interval,bool nonblock)1519*4882a593Smuzhiyun int submit_int_msg(struct usb_device *dev, unsigned long pipe,
1520*4882a593Smuzhiyun void *buffer, int length, int interval, bool nonblock)
1521*4882a593Smuzhiyun {
1522*4882a593Smuzhiyun return _ehci_submit_int_msg(dev, pipe, buffer, length, interval,
1523*4882a593Smuzhiyun nonblock);
1524*4882a593Smuzhiyun }
1525*4882a593Smuzhiyun
create_int_queue(struct usb_device * dev,unsigned long pipe,int queuesize,int elementsize,void * buffer,int interval)1526*4882a593Smuzhiyun struct int_queue *create_int_queue(struct usb_device *dev,
1527*4882a593Smuzhiyun unsigned long pipe, int queuesize, int elementsize,
1528*4882a593Smuzhiyun void *buffer, int interval)
1529*4882a593Smuzhiyun {
1530*4882a593Smuzhiyun return _ehci_create_int_queue(dev, pipe, queuesize, elementsize,
1531*4882a593Smuzhiyun buffer, interval);
1532*4882a593Smuzhiyun }
1533*4882a593Smuzhiyun
poll_int_queue(struct usb_device * dev,struct int_queue * queue)1534*4882a593Smuzhiyun void *poll_int_queue(struct usb_device *dev, struct int_queue *queue)
1535*4882a593Smuzhiyun {
1536*4882a593Smuzhiyun return _ehci_poll_int_queue(dev, queue);
1537*4882a593Smuzhiyun }
1538*4882a593Smuzhiyun
destroy_int_queue(struct usb_device * dev,struct int_queue * queue)1539*4882a593Smuzhiyun int destroy_int_queue(struct usb_device *dev, struct int_queue *queue)
1540*4882a593Smuzhiyun {
1541*4882a593Smuzhiyun return _ehci_destroy_int_queue(dev, queue);
1542*4882a593Smuzhiyun }
1543*4882a593Smuzhiyun #endif
1544*4882a593Smuzhiyun
1545*4882a593Smuzhiyun #if CONFIG_IS_ENABLED(DM_USB)
ehci_submit_control_msg(struct udevice * dev,struct usb_device * udev,unsigned long pipe,void * buffer,int length,struct devrequest * setup)1546*4882a593Smuzhiyun static int ehci_submit_control_msg(struct udevice *dev, struct usb_device *udev,
1547*4882a593Smuzhiyun unsigned long pipe, void *buffer, int length,
1548*4882a593Smuzhiyun struct devrequest *setup)
1549*4882a593Smuzhiyun {
1550*4882a593Smuzhiyun debug("%s: dev='%s', udev=%p, udev->dev='%s', portnr=%d\n", __func__,
1551*4882a593Smuzhiyun dev->name, udev, udev->dev->name, udev->portnr);
1552*4882a593Smuzhiyun
1553*4882a593Smuzhiyun return _ehci_submit_control_msg(udev, pipe, buffer, length, setup);
1554*4882a593Smuzhiyun }
1555*4882a593Smuzhiyun
ehci_submit_bulk_msg(struct udevice * dev,struct usb_device * udev,unsigned long pipe,void * buffer,int length)1556*4882a593Smuzhiyun static int ehci_submit_bulk_msg(struct udevice *dev, struct usb_device *udev,
1557*4882a593Smuzhiyun unsigned long pipe, void *buffer, int length)
1558*4882a593Smuzhiyun {
1559*4882a593Smuzhiyun debug("%s: dev='%s', udev=%p\n", __func__, dev->name, udev);
1560*4882a593Smuzhiyun return _ehci_submit_bulk_msg(udev, pipe, buffer, length);
1561*4882a593Smuzhiyun }
1562*4882a593Smuzhiyun
ehci_submit_int_msg(struct udevice * dev,struct usb_device * udev,unsigned long pipe,void * buffer,int length,int interval,bool nonblock)1563*4882a593Smuzhiyun static int ehci_submit_int_msg(struct udevice *dev, struct usb_device *udev,
1564*4882a593Smuzhiyun unsigned long pipe, void *buffer, int length,
1565*4882a593Smuzhiyun int interval, bool nonblock)
1566*4882a593Smuzhiyun {
1567*4882a593Smuzhiyun debug("%s: dev='%s', udev=%p\n", __func__, dev->name, udev);
1568*4882a593Smuzhiyun return _ehci_submit_int_msg(udev, pipe, buffer, length, interval,
1569*4882a593Smuzhiyun nonblock);
1570*4882a593Smuzhiyun }
1571*4882a593Smuzhiyun
ehci_create_int_queue(struct udevice * dev,struct usb_device * udev,unsigned long pipe,int queuesize,int elementsize,void * buffer,int interval)1572*4882a593Smuzhiyun static struct int_queue *ehci_create_int_queue(struct udevice *dev,
1573*4882a593Smuzhiyun struct usb_device *udev, unsigned long pipe, int queuesize,
1574*4882a593Smuzhiyun int elementsize, void *buffer, int interval)
1575*4882a593Smuzhiyun {
1576*4882a593Smuzhiyun debug("%s: dev='%s', udev=%p\n", __func__, dev->name, udev);
1577*4882a593Smuzhiyun return _ehci_create_int_queue(udev, pipe, queuesize, elementsize,
1578*4882a593Smuzhiyun buffer, interval);
1579*4882a593Smuzhiyun }
1580*4882a593Smuzhiyun
ehci_poll_int_queue(struct udevice * dev,struct usb_device * udev,struct int_queue * queue)1581*4882a593Smuzhiyun static void *ehci_poll_int_queue(struct udevice *dev, struct usb_device *udev,
1582*4882a593Smuzhiyun struct int_queue *queue)
1583*4882a593Smuzhiyun {
1584*4882a593Smuzhiyun debug("%s: dev='%s', udev=%p\n", __func__, dev->name, udev);
1585*4882a593Smuzhiyun return _ehci_poll_int_queue(udev, queue);
1586*4882a593Smuzhiyun }
1587*4882a593Smuzhiyun
ehci_destroy_int_queue(struct udevice * dev,struct usb_device * udev,struct int_queue * queue)1588*4882a593Smuzhiyun static int ehci_destroy_int_queue(struct udevice *dev, struct usb_device *udev,
1589*4882a593Smuzhiyun struct int_queue *queue)
1590*4882a593Smuzhiyun {
1591*4882a593Smuzhiyun debug("%s: dev='%s', udev=%p\n", __func__, dev->name, udev);
1592*4882a593Smuzhiyun return _ehci_destroy_int_queue(udev, queue);
1593*4882a593Smuzhiyun }
1594*4882a593Smuzhiyun
ehci_get_max_xfer_size(struct udevice * dev,size_t * size)1595*4882a593Smuzhiyun static int ehci_get_max_xfer_size(struct udevice *dev, size_t *size)
1596*4882a593Smuzhiyun {
1597*4882a593Smuzhiyun /*
1598*4882a593Smuzhiyun * EHCD can handle any transfer length as long as there is enough
1599*4882a593Smuzhiyun * free heap space left, hence set the theoretical max number here.
1600*4882a593Smuzhiyun */
1601*4882a593Smuzhiyun *size = SIZE_MAX;
1602*4882a593Smuzhiyun
1603*4882a593Smuzhiyun return 0;
1604*4882a593Smuzhiyun }
1605*4882a593Smuzhiyun
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)1606*4882a593Smuzhiyun int ehci_register(struct udevice *dev, struct ehci_hccr *hccr,
1607*4882a593Smuzhiyun struct ehci_hcor *hcor, const struct ehci_ops *ops,
1608*4882a593Smuzhiyun uint tweaks, enum usb_init_type init)
1609*4882a593Smuzhiyun {
1610*4882a593Smuzhiyun struct usb_bus_priv *priv = dev_get_uclass_priv(dev);
1611*4882a593Smuzhiyun struct ehci_ctrl *ctrl = dev_get_priv(dev);
1612*4882a593Smuzhiyun int ret = -1;
1613*4882a593Smuzhiyun
1614*4882a593Smuzhiyun debug("%s: dev='%s', ctrl=%p, hccr=%p, hcor=%p, init=%d\n", __func__,
1615*4882a593Smuzhiyun dev->name, ctrl, hccr, hcor, init);
1616*4882a593Smuzhiyun
1617*4882a593Smuzhiyun if (!ctrl || !hccr || !hcor)
1618*4882a593Smuzhiyun goto err;
1619*4882a593Smuzhiyun
1620*4882a593Smuzhiyun priv->desc_before_addr = true;
1621*4882a593Smuzhiyun
1622*4882a593Smuzhiyun ehci_setup_ops(ctrl, ops);
1623*4882a593Smuzhiyun ctrl->hccr = hccr;
1624*4882a593Smuzhiyun ctrl->hcor = hcor;
1625*4882a593Smuzhiyun ctrl->priv = ctrl;
1626*4882a593Smuzhiyun
1627*4882a593Smuzhiyun ctrl->init = init;
1628*4882a593Smuzhiyun if (ctrl->init == USB_INIT_DEVICE)
1629*4882a593Smuzhiyun goto done;
1630*4882a593Smuzhiyun
1631*4882a593Smuzhiyun ret = ehci_reset(ctrl);
1632*4882a593Smuzhiyun if (ret)
1633*4882a593Smuzhiyun goto err;
1634*4882a593Smuzhiyun
1635*4882a593Smuzhiyun if (ctrl->ops.init_after_reset) {
1636*4882a593Smuzhiyun ret = ctrl->ops.init_after_reset(ctrl);
1637*4882a593Smuzhiyun if (ret)
1638*4882a593Smuzhiyun goto err;
1639*4882a593Smuzhiyun }
1640*4882a593Smuzhiyun
1641*4882a593Smuzhiyun ret = ehci_common_init(ctrl, tweaks);
1642*4882a593Smuzhiyun if (ret)
1643*4882a593Smuzhiyun goto err;
1644*4882a593Smuzhiyun done:
1645*4882a593Smuzhiyun return 0;
1646*4882a593Smuzhiyun err:
1647*4882a593Smuzhiyun free(ctrl);
1648*4882a593Smuzhiyun debug("%s: failed, ret=%d\n", __func__, ret);
1649*4882a593Smuzhiyun return ret;
1650*4882a593Smuzhiyun }
1651*4882a593Smuzhiyun
ehci_deregister(struct udevice * dev)1652*4882a593Smuzhiyun int ehci_deregister(struct udevice *dev)
1653*4882a593Smuzhiyun {
1654*4882a593Smuzhiyun struct ehci_ctrl *ctrl = dev_get_priv(dev);
1655*4882a593Smuzhiyun
1656*4882a593Smuzhiyun if (ctrl->init == USB_INIT_DEVICE)
1657*4882a593Smuzhiyun return 0;
1658*4882a593Smuzhiyun
1659*4882a593Smuzhiyun ehci_shutdown(ctrl);
1660*4882a593Smuzhiyun
1661*4882a593Smuzhiyun return 0;
1662*4882a593Smuzhiyun }
1663*4882a593Smuzhiyun
1664*4882a593Smuzhiyun struct dm_usb_ops ehci_usb_ops = {
1665*4882a593Smuzhiyun .control = ehci_submit_control_msg,
1666*4882a593Smuzhiyun .bulk = ehci_submit_bulk_msg,
1667*4882a593Smuzhiyun .interrupt = ehci_submit_int_msg,
1668*4882a593Smuzhiyun .create_int_queue = ehci_create_int_queue,
1669*4882a593Smuzhiyun .poll_int_queue = ehci_poll_int_queue,
1670*4882a593Smuzhiyun .destroy_int_queue = ehci_destroy_int_queue,
1671*4882a593Smuzhiyun .get_max_xfer_size = ehci_get_max_xfer_size,
1672*4882a593Smuzhiyun };
1673*4882a593Smuzhiyun
1674*4882a593Smuzhiyun #endif
1675*4882a593Smuzhiyun
1676*4882a593Smuzhiyun #ifdef CONFIG_PHY
ehci_setup_phy(struct udevice * dev,struct phy * phy,int index)1677*4882a593Smuzhiyun int ehci_setup_phy(struct udevice *dev, struct phy *phy, int index)
1678*4882a593Smuzhiyun {
1679*4882a593Smuzhiyun int ret;
1680*4882a593Smuzhiyun
1681*4882a593Smuzhiyun if (!phy)
1682*4882a593Smuzhiyun return 0;
1683*4882a593Smuzhiyun
1684*4882a593Smuzhiyun ret = generic_phy_get_by_index(dev, index, phy);
1685*4882a593Smuzhiyun if (ret) {
1686*4882a593Smuzhiyun if (ret != -ENOENT) {
1687*4882a593Smuzhiyun dev_err(dev, "failed to get usb phy\n");
1688*4882a593Smuzhiyun return ret;
1689*4882a593Smuzhiyun }
1690*4882a593Smuzhiyun } else {
1691*4882a593Smuzhiyun ret = generic_phy_init(phy);
1692*4882a593Smuzhiyun if (ret) {
1693*4882a593Smuzhiyun dev_err(dev, "failed to init usb phy\n");
1694*4882a593Smuzhiyun return ret;
1695*4882a593Smuzhiyun }
1696*4882a593Smuzhiyun
1697*4882a593Smuzhiyun ret = generic_phy_power_on(phy);
1698*4882a593Smuzhiyun if (ret) {
1699*4882a593Smuzhiyun dev_err(dev, "failed to power on usb phy\n");
1700*4882a593Smuzhiyun return generic_phy_exit(phy);
1701*4882a593Smuzhiyun }
1702*4882a593Smuzhiyun }
1703*4882a593Smuzhiyun
1704*4882a593Smuzhiyun return 0;
1705*4882a593Smuzhiyun }
1706*4882a593Smuzhiyun
ehci_shutdown_phy(struct udevice * dev,struct phy * phy)1707*4882a593Smuzhiyun int ehci_shutdown_phy(struct udevice *dev, struct phy *phy)
1708*4882a593Smuzhiyun {
1709*4882a593Smuzhiyun int ret = 0;
1710*4882a593Smuzhiyun
1711*4882a593Smuzhiyun if (!phy)
1712*4882a593Smuzhiyun return 0;
1713*4882a593Smuzhiyun
1714*4882a593Smuzhiyun if (generic_phy_valid(phy)) {
1715*4882a593Smuzhiyun ret = generic_phy_power_off(phy);
1716*4882a593Smuzhiyun if (ret) {
1717*4882a593Smuzhiyun dev_err(dev, "failed to power off usb phy\n");
1718*4882a593Smuzhiyun return ret;
1719*4882a593Smuzhiyun }
1720*4882a593Smuzhiyun
1721*4882a593Smuzhiyun ret = generic_phy_exit(phy);
1722*4882a593Smuzhiyun if (ret) {
1723*4882a593Smuzhiyun dev_err(dev, "failed to power off usb phy\n");
1724*4882a593Smuzhiyun return ret;
1725*4882a593Smuzhiyun }
1726*4882a593Smuzhiyun }
1727*4882a593Smuzhiyun
1728*4882a593Smuzhiyun return 0;
1729*4882a593Smuzhiyun }
1730*4882a593Smuzhiyun #else
ehci_setup_phy(struct udevice * dev,struct phy * phy,int index)1731*4882a593Smuzhiyun int ehci_setup_phy(struct udevice *dev, struct phy *phy, int index)
1732*4882a593Smuzhiyun {
1733*4882a593Smuzhiyun return 0;
1734*4882a593Smuzhiyun }
1735*4882a593Smuzhiyun
ehci_shutdown_phy(struct udevice * dev,struct phy * phy)1736*4882a593Smuzhiyun int ehci_shutdown_phy(struct udevice *dev, struct phy *phy)
1737*4882a593Smuzhiyun {
1738*4882a593Smuzhiyun return 0;
1739*4882a593Smuzhiyun }
1740*4882a593Smuzhiyun #endif
1741