1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * Based on drivers/usb/gadget/omap1510_udc.c
3*4882a593Smuzhiyun * TI OMAP1510 USB bus interface driver
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * (C) Copyright 2009
6*4882a593Smuzhiyun * Vipin Kumar, ST Micoelectronics, vipin.kumar@st.com.
7*4882a593Smuzhiyun *
8*4882a593Smuzhiyun * SPDX-License-Identifier: GPL-2.0+
9*4882a593Smuzhiyun */
10*4882a593Smuzhiyun
11*4882a593Smuzhiyun #include <common.h>
12*4882a593Smuzhiyun #include <asm/io.h>
13*4882a593Smuzhiyun
14*4882a593Smuzhiyun #include <usbdevice.h>
15*4882a593Smuzhiyun #include "ep0.h"
16*4882a593Smuzhiyun #include <usb/designware_udc.h>
17*4882a593Smuzhiyun #include <usb/udc.h>
18*4882a593Smuzhiyun #include <asm/arch/hardware.h>
19*4882a593Smuzhiyun
20*4882a593Smuzhiyun #define UDC_INIT_MDELAY 80 /* Device settle delay */
21*4882a593Smuzhiyun
22*4882a593Smuzhiyun /* Some kind of debugging output... */
23*4882a593Smuzhiyun #ifndef DEBUG_DWUSBTTY
24*4882a593Smuzhiyun #define UDCDBG(str)
25*4882a593Smuzhiyun #define UDCDBGA(fmt, args...)
26*4882a593Smuzhiyun #else
27*4882a593Smuzhiyun #define UDCDBG(str) serial_printf(str "\n")
28*4882a593Smuzhiyun #define UDCDBGA(fmt, args...) serial_printf(fmt "\n", ##args)
29*4882a593Smuzhiyun #endif
30*4882a593Smuzhiyun
31*4882a593Smuzhiyun static struct urb *ep0_urb;
32*4882a593Smuzhiyun static struct usb_device_instance *udc_device;
33*4882a593Smuzhiyun
34*4882a593Smuzhiyun static struct plug_regs *const plug_regs_p =
35*4882a593Smuzhiyun (struct plug_regs * const)CONFIG_SYS_PLUG_BASE;
36*4882a593Smuzhiyun static struct udc_regs *const udc_regs_p =
37*4882a593Smuzhiyun (struct udc_regs * const)CONFIG_SYS_USBD_BASE;
38*4882a593Smuzhiyun static struct udc_endp_regs *const outep_regs_p =
39*4882a593Smuzhiyun &((struct udc_regs * const)CONFIG_SYS_USBD_BASE)->out_regs[0];
40*4882a593Smuzhiyun static struct udc_endp_regs *const inep_regs_p =
41*4882a593Smuzhiyun &((struct udc_regs * const)CONFIG_SYS_USBD_BASE)->in_regs[0];
42*4882a593Smuzhiyun
43*4882a593Smuzhiyun /*
44*4882a593Smuzhiyun * udc_state_transition - Write the next packet to TxFIFO.
45*4882a593Smuzhiyun * @initial: Initial state.
46*4882a593Smuzhiyun * @final: Final state.
47*4882a593Smuzhiyun *
48*4882a593Smuzhiyun * Helper function to implement device state changes. The device states and
49*4882a593Smuzhiyun * the events that transition between them are:
50*4882a593Smuzhiyun *
51*4882a593Smuzhiyun * STATE_ATTACHED
52*4882a593Smuzhiyun * || /\
53*4882a593Smuzhiyun * \/ ||
54*4882a593Smuzhiyun * DEVICE_HUB_CONFIGURED DEVICE_HUB_RESET
55*4882a593Smuzhiyun * || /\
56*4882a593Smuzhiyun * \/ ||
57*4882a593Smuzhiyun * STATE_POWERED
58*4882a593Smuzhiyun * || /\
59*4882a593Smuzhiyun * \/ ||
60*4882a593Smuzhiyun * DEVICE_RESET DEVICE_POWER_INTERRUPTION
61*4882a593Smuzhiyun * || /\
62*4882a593Smuzhiyun * \/ ||
63*4882a593Smuzhiyun * STATE_DEFAULT
64*4882a593Smuzhiyun * || /\
65*4882a593Smuzhiyun * \/ ||
66*4882a593Smuzhiyun * DEVICE_ADDRESS_ASSIGNED DEVICE_RESET
67*4882a593Smuzhiyun * || /\
68*4882a593Smuzhiyun * \/ ||
69*4882a593Smuzhiyun * STATE_ADDRESSED
70*4882a593Smuzhiyun * || /\
71*4882a593Smuzhiyun * \/ ||
72*4882a593Smuzhiyun * DEVICE_CONFIGURED DEVICE_DE_CONFIGURED
73*4882a593Smuzhiyun * || /\
74*4882a593Smuzhiyun * \/ ||
75*4882a593Smuzhiyun * STATE_CONFIGURED
76*4882a593Smuzhiyun *
77*4882a593Smuzhiyun * udc_state_transition transitions up (in the direction from STATE_ATTACHED
78*4882a593Smuzhiyun * to STATE_CONFIGURED) from the specified initial state to the specified final
79*4882a593Smuzhiyun * state, passing through each intermediate state on the way. If the initial
80*4882a593Smuzhiyun * state is at or above (i.e. nearer to STATE_CONFIGURED) the final state, then
81*4882a593Smuzhiyun * no state transitions will take place.
82*4882a593Smuzhiyun *
83*4882a593Smuzhiyun * udc_state_transition also transitions down (in the direction from
84*4882a593Smuzhiyun * STATE_CONFIGURED to STATE_ATTACHED) from the specified initial state to the
85*4882a593Smuzhiyun * specified final state, passing through each intermediate state on the way.
86*4882a593Smuzhiyun * If the initial state is at or below (i.e. nearer to STATE_ATTACHED) the final
87*4882a593Smuzhiyun * state, then no state transitions will take place.
88*4882a593Smuzhiyun *
89*4882a593Smuzhiyun * This function must only be called with interrupts disabled.
90*4882a593Smuzhiyun */
udc_state_transition(usb_device_state_t initial,usb_device_state_t final)91*4882a593Smuzhiyun static void udc_state_transition(usb_device_state_t initial,
92*4882a593Smuzhiyun usb_device_state_t final)
93*4882a593Smuzhiyun {
94*4882a593Smuzhiyun if (initial < final) {
95*4882a593Smuzhiyun switch (initial) {
96*4882a593Smuzhiyun case STATE_ATTACHED:
97*4882a593Smuzhiyun usbd_device_event_irq(udc_device,
98*4882a593Smuzhiyun DEVICE_HUB_CONFIGURED, 0);
99*4882a593Smuzhiyun if (final == STATE_POWERED)
100*4882a593Smuzhiyun break;
101*4882a593Smuzhiyun case STATE_POWERED:
102*4882a593Smuzhiyun usbd_device_event_irq(udc_device, DEVICE_RESET, 0);
103*4882a593Smuzhiyun if (final == STATE_DEFAULT)
104*4882a593Smuzhiyun break;
105*4882a593Smuzhiyun case STATE_DEFAULT:
106*4882a593Smuzhiyun usbd_device_event_irq(udc_device,
107*4882a593Smuzhiyun DEVICE_ADDRESS_ASSIGNED, 0);
108*4882a593Smuzhiyun if (final == STATE_ADDRESSED)
109*4882a593Smuzhiyun break;
110*4882a593Smuzhiyun case STATE_ADDRESSED:
111*4882a593Smuzhiyun usbd_device_event_irq(udc_device, DEVICE_CONFIGURED, 0);
112*4882a593Smuzhiyun case STATE_CONFIGURED:
113*4882a593Smuzhiyun break;
114*4882a593Smuzhiyun default:
115*4882a593Smuzhiyun break;
116*4882a593Smuzhiyun }
117*4882a593Smuzhiyun } else if (initial > final) {
118*4882a593Smuzhiyun switch (initial) {
119*4882a593Smuzhiyun case STATE_CONFIGURED:
120*4882a593Smuzhiyun usbd_device_event_irq(udc_device,
121*4882a593Smuzhiyun DEVICE_DE_CONFIGURED, 0);
122*4882a593Smuzhiyun if (final == STATE_ADDRESSED)
123*4882a593Smuzhiyun break;
124*4882a593Smuzhiyun case STATE_ADDRESSED:
125*4882a593Smuzhiyun usbd_device_event_irq(udc_device, DEVICE_RESET, 0);
126*4882a593Smuzhiyun if (final == STATE_DEFAULT)
127*4882a593Smuzhiyun break;
128*4882a593Smuzhiyun case STATE_DEFAULT:
129*4882a593Smuzhiyun usbd_device_event_irq(udc_device,
130*4882a593Smuzhiyun DEVICE_POWER_INTERRUPTION, 0);
131*4882a593Smuzhiyun if (final == STATE_POWERED)
132*4882a593Smuzhiyun break;
133*4882a593Smuzhiyun case STATE_POWERED:
134*4882a593Smuzhiyun usbd_device_event_irq(udc_device, DEVICE_HUB_RESET, 0);
135*4882a593Smuzhiyun case STATE_ATTACHED:
136*4882a593Smuzhiyun break;
137*4882a593Smuzhiyun default:
138*4882a593Smuzhiyun break;
139*4882a593Smuzhiyun }
140*4882a593Smuzhiyun }
141*4882a593Smuzhiyun }
142*4882a593Smuzhiyun
143*4882a593Smuzhiyun /* Stall endpoint */
udc_stall_ep(u32 ep_num)144*4882a593Smuzhiyun static void udc_stall_ep(u32 ep_num)
145*4882a593Smuzhiyun {
146*4882a593Smuzhiyun writel(readl(&inep_regs_p[ep_num].endp_cntl) | ENDP_CNTL_STALL,
147*4882a593Smuzhiyun &inep_regs_p[ep_num].endp_cntl);
148*4882a593Smuzhiyun
149*4882a593Smuzhiyun writel(readl(&outep_regs_p[ep_num].endp_cntl) | ENDP_CNTL_STALL,
150*4882a593Smuzhiyun &outep_regs_p[ep_num].endp_cntl);
151*4882a593Smuzhiyun }
152*4882a593Smuzhiyun
get_fifo(int ep_num,int in)153*4882a593Smuzhiyun static void *get_fifo(int ep_num, int in)
154*4882a593Smuzhiyun {
155*4882a593Smuzhiyun u32 *fifo_ptr = (u32 *)CONFIG_SYS_FIFO_BASE;
156*4882a593Smuzhiyun
157*4882a593Smuzhiyun switch (ep_num) {
158*4882a593Smuzhiyun case UDC_EP3:
159*4882a593Smuzhiyun fifo_ptr += readl(&inep_regs_p[1].endp_bsorfn);
160*4882a593Smuzhiyun /* break intentionally left out */
161*4882a593Smuzhiyun
162*4882a593Smuzhiyun case UDC_EP1:
163*4882a593Smuzhiyun fifo_ptr += readl(&inep_regs_p[0].endp_bsorfn);
164*4882a593Smuzhiyun /* break intentionally left out */
165*4882a593Smuzhiyun
166*4882a593Smuzhiyun case UDC_EP0:
167*4882a593Smuzhiyun default:
168*4882a593Smuzhiyun if (in) {
169*4882a593Smuzhiyun fifo_ptr +=
170*4882a593Smuzhiyun readl(&outep_regs_p[2].endp_maxpacksize) >> 16;
171*4882a593Smuzhiyun /* break intentionally left out */
172*4882a593Smuzhiyun } else {
173*4882a593Smuzhiyun break;
174*4882a593Smuzhiyun }
175*4882a593Smuzhiyun
176*4882a593Smuzhiyun case UDC_EP2:
177*4882a593Smuzhiyun fifo_ptr += readl(&outep_regs_p[0].endp_maxpacksize) >> 16;
178*4882a593Smuzhiyun /* break intentionally left out */
179*4882a593Smuzhiyun }
180*4882a593Smuzhiyun
181*4882a593Smuzhiyun return (void *)fifo_ptr;
182*4882a593Smuzhiyun }
183*4882a593Smuzhiyun
usbgetpckfromfifo(int epNum,u8 * bufp,u32 len)184*4882a593Smuzhiyun static int usbgetpckfromfifo(int epNum, u8 *bufp, u32 len)
185*4882a593Smuzhiyun {
186*4882a593Smuzhiyun u8 *fifo_ptr = (u8 *)get_fifo(epNum, 0);
187*4882a593Smuzhiyun u32 i, nw, nb;
188*4882a593Smuzhiyun u32 *wrdp;
189*4882a593Smuzhiyun u8 *bytp;
190*4882a593Smuzhiyun u32 tmp[128];
191*4882a593Smuzhiyun
192*4882a593Smuzhiyun if (readl(&udc_regs_p->dev_stat) & DEV_STAT_RXFIFO_EMPTY)
193*4882a593Smuzhiyun return -1;
194*4882a593Smuzhiyun
195*4882a593Smuzhiyun nw = len / sizeof(u32);
196*4882a593Smuzhiyun nb = len % sizeof(u32);
197*4882a593Smuzhiyun
198*4882a593Smuzhiyun /* use tmp buf if bufp is not word aligned */
199*4882a593Smuzhiyun if ((int)bufp & 0x3)
200*4882a593Smuzhiyun wrdp = (u32 *)&tmp[0];
201*4882a593Smuzhiyun else
202*4882a593Smuzhiyun wrdp = (u32 *)bufp;
203*4882a593Smuzhiyun
204*4882a593Smuzhiyun for (i = 0; i < nw; i++) {
205*4882a593Smuzhiyun writel(readl(fifo_ptr), wrdp);
206*4882a593Smuzhiyun wrdp++;
207*4882a593Smuzhiyun }
208*4882a593Smuzhiyun
209*4882a593Smuzhiyun bytp = (u8 *)wrdp;
210*4882a593Smuzhiyun for (i = 0; i < nb; i++) {
211*4882a593Smuzhiyun writeb(readb(fifo_ptr), bytp);
212*4882a593Smuzhiyun fifo_ptr++;
213*4882a593Smuzhiyun bytp++;
214*4882a593Smuzhiyun }
215*4882a593Smuzhiyun readl(&outep_regs_p[epNum].write_done);
216*4882a593Smuzhiyun
217*4882a593Smuzhiyun /* copy back tmp buffer to bufp if bufp is not word aligned */
218*4882a593Smuzhiyun if ((int)bufp & 0x3)
219*4882a593Smuzhiyun memcpy(bufp, tmp, len);
220*4882a593Smuzhiyun
221*4882a593Smuzhiyun return 0;
222*4882a593Smuzhiyun }
223*4882a593Smuzhiyun
usbputpcktofifo(int epNum,u8 * bufp,u32 len)224*4882a593Smuzhiyun static void usbputpcktofifo(int epNum, u8 *bufp, u32 len)
225*4882a593Smuzhiyun {
226*4882a593Smuzhiyun u32 i, nw, nb;
227*4882a593Smuzhiyun u32 *wrdp;
228*4882a593Smuzhiyun u8 *bytp;
229*4882a593Smuzhiyun u8 *fifo_ptr = get_fifo(epNum, 1);
230*4882a593Smuzhiyun
231*4882a593Smuzhiyun nw = len / sizeof(int);
232*4882a593Smuzhiyun nb = len % sizeof(int);
233*4882a593Smuzhiyun wrdp = (u32 *)bufp;
234*4882a593Smuzhiyun for (i = 0; i < nw; i++) {
235*4882a593Smuzhiyun writel(*wrdp, fifo_ptr);
236*4882a593Smuzhiyun wrdp++;
237*4882a593Smuzhiyun }
238*4882a593Smuzhiyun
239*4882a593Smuzhiyun bytp = (u8 *)wrdp;
240*4882a593Smuzhiyun for (i = 0; i < nb; i++) {
241*4882a593Smuzhiyun writeb(*bytp, fifo_ptr);
242*4882a593Smuzhiyun fifo_ptr++;
243*4882a593Smuzhiyun bytp++;
244*4882a593Smuzhiyun }
245*4882a593Smuzhiyun }
246*4882a593Smuzhiyun
247*4882a593Smuzhiyun /*
248*4882a593Smuzhiyun * dw_write_noniso_tx_fifo - Write the next packet to TxFIFO.
249*4882a593Smuzhiyun * @endpoint: Endpoint pointer.
250*4882a593Smuzhiyun *
251*4882a593Smuzhiyun * If the endpoint has an active tx_urb, then the next packet of data from the
252*4882a593Smuzhiyun * URB is written to the tx FIFO. The total amount of data in the urb is given
253*4882a593Smuzhiyun * by urb->actual_length. The maximum amount of data that can be sent in any
254*4882a593Smuzhiyun * one packet is given by endpoint->tx_packetSize. The number of data bytes
255*4882a593Smuzhiyun * from this URB that have already been transmitted is given by endpoint->sent.
256*4882a593Smuzhiyun * endpoint->last is updated by this routine with the number of data bytes
257*4882a593Smuzhiyun * transmitted in this packet.
258*4882a593Smuzhiyun *
259*4882a593Smuzhiyun */
dw_write_noniso_tx_fifo(struct usb_endpoint_instance * endpoint)260*4882a593Smuzhiyun static void dw_write_noniso_tx_fifo(struct usb_endpoint_instance
261*4882a593Smuzhiyun *endpoint)
262*4882a593Smuzhiyun {
263*4882a593Smuzhiyun struct urb *urb = endpoint->tx_urb;
264*4882a593Smuzhiyun int align;
265*4882a593Smuzhiyun
266*4882a593Smuzhiyun if (urb) {
267*4882a593Smuzhiyun u32 last;
268*4882a593Smuzhiyun
269*4882a593Smuzhiyun UDCDBGA("urb->buffer %p, buffer_length %d, actual_length %d",
270*4882a593Smuzhiyun urb->buffer, urb->buffer_length, urb->actual_length);
271*4882a593Smuzhiyun
272*4882a593Smuzhiyun last = min_t(u32, urb->actual_length - endpoint->sent,
273*4882a593Smuzhiyun endpoint->tx_packetSize);
274*4882a593Smuzhiyun
275*4882a593Smuzhiyun if (last) {
276*4882a593Smuzhiyun u8 *cp = urb->buffer + endpoint->sent;
277*4882a593Smuzhiyun
278*4882a593Smuzhiyun /*
279*4882a593Smuzhiyun * This ensures that USBD packet fifo is accessed
280*4882a593Smuzhiyun * - through word aligned pointer or
281*4882a593Smuzhiyun * - through non word aligned pointer but only
282*4882a593Smuzhiyun * with a max length to make the next packet
283*4882a593Smuzhiyun * word aligned
284*4882a593Smuzhiyun */
285*4882a593Smuzhiyun
286*4882a593Smuzhiyun align = ((ulong)cp % sizeof(int));
287*4882a593Smuzhiyun if (align)
288*4882a593Smuzhiyun last = min(last, sizeof(int) - align);
289*4882a593Smuzhiyun
290*4882a593Smuzhiyun UDCDBGA("endpoint->sent %d, tx_packetSize %d, last %d",
291*4882a593Smuzhiyun endpoint->sent, endpoint->tx_packetSize, last);
292*4882a593Smuzhiyun
293*4882a593Smuzhiyun usbputpcktofifo(endpoint->endpoint_address &
294*4882a593Smuzhiyun USB_ENDPOINT_NUMBER_MASK, cp, last);
295*4882a593Smuzhiyun }
296*4882a593Smuzhiyun endpoint->last = last;
297*4882a593Smuzhiyun }
298*4882a593Smuzhiyun }
299*4882a593Smuzhiyun
300*4882a593Smuzhiyun /*
301*4882a593Smuzhiyun * Handle SETUP USB interrupt.
302*4882a593Smuzhiyun * This function implements TRM Figure 14-14.
303*4882a593Smuzhiyun */
dw_udc_setup(struct usb_endpoint_instance * endpoint)304*4882a593Smuzhiyun static void dw_udc_setup(struct usb_endpoint_instance *endpoint)
305*4882a593Smuzhiyun {
306*4882a593Smuzhiyun u8 *datap = (u8 *)&ep0_urb->device_request;
307*4882a593Smuzhiyun int ep_addr = endpoint->endpoint_address;
308*4882a593Smuzhiyun
309*4882a593Smuzhiyun UDCDBG("-> Entering device setup");
310*4882a593Smuzhiyun usbgetpckfromfifo(ep_addr, datap, 8);
311*4882a593Smuzhiyun
312*4882a593Smuzhiyun /* Try to process setup packet */
313*4882a593Smuzhiyun if (ep0_recv_setup(ep0_urb)) {
314*4882a593Smuzhiyun /* Not a setup packet, stall next EP0 transaction */
315*4882a593Smuzhiyun udc_stall_ep(0);
316*4882a593Smuzhiyun UDCDBG("can't parse setup packet, still waiting for setup");
317*4882a593Smuzhiyun return;
318*4882a593Smuzhiyun }
319*4882a593Smuzhiyun
320*4882a593Smuzhiyun /* Check direction */
321*4882a593Smuzhiyun if ((ep0_urb->device_request.bmRequestType & USB_REQ_DIRECTION_MASK)
322*4882a593Smuzhiyun == USB_REQ_HOST2DEVICE) {
323*4882a593Smuzhiyun UDCDBG("control write on EP0");
324*4882a593Smuzhiyun if (le16_to_cpu(ep0_urb->device_request.wLength)) {
325*4882a593Smuzhiyun /* Stall this request */
326*4882a593Smuzhiyun UDCDBG("Stalling unsupported EP0 control write data "
327*4882a593Smuzhiyun "stage.");
328*4882a593Smuzhiyun udc_stall_ep(0);
329*4882a593Smuzhiyun }
330*4882a593Smuzhiyun } else {
331*4882a593Smuzhiyun
332*4882a593Smuzhiyun UDCDBG("control read on EP0");
333*4882a593Smuzhiyun /*
334*4882a593Smuzhiyun * The ep0_recv_setup function has already placed our response
335*4882a593Smuzhiyun * packet data in ep0_urb->buffer and the packet length in
336*4882a593Smuzhiyun * ep0_urb->actual_length.
337*4882a593Smuzhiyun */
338*4882a593Smuzhiyun endpoint->tx_urb = ep0_urb;
339*4882a593Smuzhiyun endpoint->sent = 0;
340*4882a593Smuzhiyun /*
341*4882a593Smuzhiyun * Write packet data to the FIFO. dw_write_noniso_tx_fifo
342*4882a593Smuzhiyun * will update endpoint->last with the number of bytes written
343*4882a593Smuzhiyun * to the FIFO.
344*4882a593Smuzhiyun */
345*4882a593Smuzhiyun dw_write_noniso_tx_fifo(endpoint);
346*4882a593Smuzhiyun
347*4882a593Smuzhiyun writel(0x0, &inep_regs_p[ep_addr].write_done);
348*4882a593Smuzhiyun }
349*4882a593Smuzhiyun
350*4882a593Smuzhiyun udc_unset_nak(endpoint->endpoint_address);
351*4882a593Smuzhiyun
352*4882a593Smuzhiyun UDCDBG("<- Leaving device setup");
353*4882a593Smuzhiyun }
354*4882a593Smuzhiyun
355*4882a593Smuzhiyun /*
356*4882a593Smuzhiyun * Handle endpoint 0 RX interrupt
357*4882a593Smuzhiyun */
dw_udc_ep0_rx(struct usb_endpoint_instance * endpoint)358*4882a593Smuzhiyun static void dw_udc_ep0_rx(struct usb_endpoint_instance *endpoint)
359*4882a593Smuzhiyun {
360*4882a593Smuzhiyun u8 dummy[64];
361*4882a593Smuzhiyun
362*4882a593Smuzhiyun UDCDBG("RX on EP0");
363*4882a593Smuzhiyun
364*4882a593Smuzhiyun /* Check direction */
365*4882a593Smuzhiyun if ((ep0_urb->device_request.bmRequestType
366*4882a593Smuzhiyun & USB_REQ_DIRECTION_MASK) == USB_REQ_HOST2DEVICE) {
367*4882a593Smuzhiyun /*
368*4882a593Smuzhiyun * This rx interrupt must be for a control write data
369*4882a593Smuzhiyun * stage packet.
370*4882a593Smuzhiyun *
371*4882a593Smuzhiyun * We don't support control write data stages.
372*4882a593Smuzhiyun * We should never end up here.
373*4882a593Smuzhiyun */
374*4882a593Smuzhiyun
375*4882a593Smuzhiyun UDCDBG("Stalling unexpected EP0 control write "
376*4882a593Smuzhiyun "data stage packet");
377*4882a593Smuzhiyun udc_stall_ep(0);
378*4882a593Smuzhiyun } else {
379*4882a593Smuzhiyun /*
380*4882a593Smuzhiyun * This rx interrupt must be for a control read status
381*4882a593Smuzhiyun * stage packet.
382*4882a593Smuzhiyun */
383*4882a593Smuzhiyun UDCDBG("ACK on EP0 control read status stage packet");
384*4882a593Smuzhiyun u32 len = (readl(&outep_regs_p[0].endp_status) >> 11) & 0xfff;
385*4882a593Smuzhiyun usbgetpckfromfifo(0, dummy, len);
386*4882a593Smuzhiyun }
387*4882a593Smuzhiyun }
388*4882a593Smuzhiyun
389*4882a593Smuzhiyun /*
390*4882a593Smuzhiyun * Handle endpoint 0 TX interrupt
391*4882a593Smuzhiyun */
dw_udc_ep0_tx(struct usb_endpoint_instance * endpoint)392*4882a593Smuzhiyun static void dw_udc_ep0_tx(struct usb_endpoint_instance *endpoint)
393*4882a593Smuzhiyun {
394*4882a593Smuzhiyun struct usb_device_request *request = &ep0_urb->device_request;
395*4882a593Smuzhiyun int ep_addr;
396*4882a593Smuzhiyun
397*4882a593Smuzhiyun UDCDBG("TX on EP0");
398*4882a593Smuzhiyun
399*4882a593Smuzhiyun /* Check direction */
400*4882a593Smuzhiyun if ((request->bmRequestType & USB_REQ_DIRECTION_MASK) ==
401*4882a593Smuzhiyun USB_REQ_HOST2DEVICE) {
402*4882a593Smuzhiyun /*
403*4882a593Smuzhiyun * This tx interrupt must be for a control write status
404*4882a593Smuzhiyun * stage packet.
405*4882a593Smuzhiyun */
406*4882a593Smuzhiyun UDCDBG("ACK on EP0 control write status stage packet");
407*4882a593Smuzhiyun } else {
408*4882a593Smuzhiyun /*
409*4882a593Smuzhiyun * This tx interrupt must be for a control read data
410*4882a593Smuzhiyun * stage packet.
411*4882a593Smuzhiyun */
412*4882a593Smuzhiyun int wLength = le16_to_cpu(request->wLength);
413*4882a593Smuzhiyun
414*4882a593Smuzhiyun /*
415*4882a593Smuzhiyun * Update our count of bytes sent so far in this
416*4882a593Smuzhiyun * transfer.
417*4882a593Smuzhiyun */
418*4882a593Smuzhiyun endpoint->sent += endpoint->last;
419*4882a593Smuzhiyun
420*4882a593Smuzhiyun /*
421*4882a593Smuzhiyun * We are finished with this transfer if we have sent
422*4882a593Smuzhiyun * all of the bytes in our tx urb (urb->actual_length)
423*4882a593Smuzhiyun * unless we need a zero-length terminating packet. We
424*4882a593Smuzhiyun * need a zero-length terminating packet if we returned
425*4882a593Smuzhiyun * fewer bytes than were requested (wLength) by the host,
426*4882a593Smuzhiyun * and the number of bytes we returned is an exact
427*4882a593Smuzhiyun * multiple of the packet size endpoint->tx_packetSize.
428*4882a593Smuzhiyun */
429*4882a593Smuzhiyun if ((endpoint->sent == ep0_urb->actual_length) &&
430*4882a593Smuzhiyun ((ep0_urb->actual_length == wLength) ||
431*4882a593Smuzhiyun (endpoint->last != endpoint->tx_packetSize))) {
432*4882a593Smuzhiyun /* Done with control read data stage. */
433*4882a593Smuzhiyun UDCDBG("control read data stage complete");
434*4882a593Smuzhiyun } else {
435*4882a593Smuzhiyun /*
436*4882a593Smuzhiyun * We still have another packet of data to send
437*4882a593Smuzhiyun * in this control read data stage or else we
438*4882a593Smuzhiyun * need a zero-length terminating packet.
439*4882a593Smuzhiyun */
440*4882a593Smuzhiyun UDCDBG("ACK control read data stage packet");
441*4882a593Smuzhiyun dw_write_noniso_tx_fifo(endpoint);
442*4882a593Smuzhiyun
443*4882a593Smuzhiyun ep_addr = endpoint->endpoint_address;
444*4882a593Smuzhiyun writel(0x0, &inep_regs_p[ep_addr].write_done);
445*4882a593Smuzhiyun }
446*4882a593Smuzhiyun }
447*4882a593Smuzhiyun }
448*4882a593Smuzhiyun
dw_find_ep(int ep)449*4882a593Smuzhiyun static struct usb_endpoint_instance *dw_find_ep(int ep)
450*4882a593Smuzhiyun {
451*4882a593Smuzhiyun int i;
452*4882a593Smuzhiyun
453*4882a593Smuzhiyun for (i = 0; i < udc_device->bus->max_endpoints; i++) {
454*4882a593Smuzhiyun if ((udc_device->bus->endpoint_array[i].endpoint_address &
455*4882a593Smuzhiyun USB_ENDPOINT_NUMBER_MASK) == ep)
456*4882a593Smuzhiyun return &udc_device->bus->endpoint_array[i];
457*4882a593Smuzhiyun }
458*4882a593Smuzhiyun return NULL;
459*4882a593Smuzhiyun }
460*4882a593Smuzhiyun
461*4882a593Smuzhiyun /*
462*4882a593Smuzhiyun * Handle RX transaction on non-ISO endpoint.
463*4882a593Smuzhiyun * The ep argument is a physical endpoint number for a non-ISO IN endpoint
464*4882a593Smuzhiyun * in the range 1 to 15.
465*4882a593Smuzhiyun */
dw_udc_epn_rx(int ep)466*4882a593Smuzhiyun static void dw_udc_epn_rx(int ep)
467*4882a593Smuzhiyun {
468*4882a593Smuzhiyun int nbytes = 0;
469*4882a593Smuzhiyun struct urb *urb;
470*4882a593Smuzhiyun struct usb_endpoint_instance *endpoint = dw_find_ep(ep);
471*4882a593Smuzhiyun
472*4882a593Smuzhiyun if (endpoint) {
473*4882a593Smuzhiyun urb = endpoint->rcv_urb;
474*4882a593Smuzhiyun
475*4882a593Smuzhiyun if (urb) {
476*4882a593Smuzhiyun u8 *cp = urb->buffer + urb->actual_length;
477*4882a593Smuzhiyun
478*4882a593Smuzhiyun nbytes = (readl(&outep_regs_p[ep].endp_status) >> 11) &
479*4882a593Smuzhiyun 0xfff;
480*4882a593Smuzhiyun usbgetpckfromfifo(ep, cp, nbytes);
481*4882a593Smuzhiyun usbd_rcv_complete(endpoint, nbytes, 0);
482*4882a593Smuzhiyun }
483*4882a593Smuzhiyun }
484*4882a593Smuzhiyun }
485*4882a593Smuzhiyun
486*4882a593Smuzhiyun /*
487*4882a593Smuzhiyun * Handle TX transaction on non-ISO endpoint.
488*4882a593Smuzhiyun * The ep argument is a physical endpoint number for a non-ISO IN endpoint
489*4882a593Smuzhiyun * in the range 16 to 30.
490*4882a593Smuzhiyun */
dw_udc_epn_tx(int ep)491*4882a593Smuzhiyun static void dw_udc_epn_tx(int ep)
492*4882a593Smuzhiyun {
493*4882a593Smuzhiyun struct usb_endpoint_instance *endpoint = dw_find_ep(ep);
494*4882a593Smuzhiyun
495*4882a593Smuzhiyun if (!endpoint)
496*4882a593Smuzhiyun return;
497*4882a593Smuzhiyun
498*4882a593Smuzhiyun /*
499*4882a593Smuzhiyun * We need to transmit a terminating zero-length packet now if
500*4882a593Smuzhiyun * we have sent all of the data in this URB and the transfer
501*4882a593Smuzhiyun * size was an exact multiple of the packet size.
502*4882a593Smuzhiyun */
503*4882a593Smuzhiyun if (endpoint->tx_urb &&
504*4882a593Smuzhiyun (endpoint->last == endpoint->tx_packetSize) &&
505*4882a593Smuzhiyun (endpoint->tx_urb->actual_length - endpoint->sent -
506*4882a593Smuzhiyun endpoint->last == 0)) {
507*4882a593Smuzhiyun /* handle zero length packet here */
508*4882a593Smuzhiyun writel(0x0, &inep_regs_p[ep].write_done);
509*4882a593Smuzhiyun
510*4882a593Smuzhiyun }
511*4882a593Smuzhiyun
512*4882a593Smuzhiyun if (endpoint->tx_urb && endpoint->tx_urb->actual_length) {
513*4882a593Smuzhiyun /* retire the data that was just sent */
514*4882a593Smuzhiyun usbd_tx_complete(endpoint);
515*4882a593Smuzhiyun /*
516*4882a593Smuzhiyun * Check to see if we have more data ready to transmit
517*4882a593Smuzhiyun * now.
518*4882a593Smuzhiyun */
519*4882a593Smuzhiyun if (endpoint->tx_urb && endpoint->tx_urb->actual_length) {
520*4882a593Smuzhiyun /* write data to FIFO */
521*4882a593Smuzhiyun dw_write_noniso_tx_fifo(endpoint);
522*4882a593Smuzhiyun writel(0x0, &inep_regs_p[ep].write_done);
523*4882a593Smuzhiyun
524*4882a593Smuzhiyun } else if (endpoint->tx_urb
525*4882a593Smuzhiyun && (endpoint->tx_urb->actual_length == 0)) {
526*4882a593Smuzhiyun /* udc_set_nak(ep); */
527*4882a593Smuzhiyun }
528*4882a593Smuzhiyun }
529*4882a593Smuzhiyun }
530*4882a593Smuzhiyun
531*4882a593Smuzhiyun /*
532*4882a593Smuzhiyun * Start of public functions.
533*4882a593Smuzhiyun */
534*4882a593Smuzhiyun
535*4882a593Smuzhiyun /* Called to start packet transmission. */
udc_endpoint_write(struct usb_endpoint_instance * endpoint)536*4882a593Smuzhiyun int udc_endpoint_write(struct usb_endpoint_instance *endpoint)
537*4882a593Smuzhiyun {
538*4882a593Smuzhiyun udc_unset_nak(endpoint->endpoint_address & USB_ENDPOINT_NUMBER_MASK);
539*4882a593Smuzhiyun return 0;
540*4882a593Smuzhiyun }
541*4882a593Smuzhiyun
542*4882a593Smuzhiyun /* Start to initialize h/w stuff */
udc_init(void)543*4882a593Smuzhiyun int udc_init(void)
544*4882a593Smuzhiyun {
545*4882a593Smuzhiyun int i;
546*4882a593Smuzhiyun u32 plug_st;
547*4882a593Smuzhiyun
548*4882a593Smuzhiyun udc_device = NULL;
549*4882a593Smuzhiyun
550*4882a593Smuzhiyun UDCDBG("starting");
551*4882a593Smuzhiyun
552*4882a593Smuzhiyun readl(&plug_regs_p->plug_pending);
553*4882a593Smuzhiyun
554*4882a593Smuzhiyun for (i = 0; i < UDC_INIT_MDELAY; i++)
555*4882a593Smuzhiyun udelay(1000);
556*4882a593Smuzhiyun
557*4882a593Smuzhiyun plug_st = readl(&plug_regs_p->plug_state);
558*4882a593Smuzhiyun writel(plug_st | PLUG_STATUS_EN, &plug_regs_p->plug_state);
559*4882a593Smuzhiyun
560*4882a593Smuzhiyun writel(~0x0, &udc_regs_p->endp_int);
561*4882a593Smuzhiyun writel(~0x0, &udc_regs_p->dev_int_mask);
562*4882a593Smuzhiyun writel(~0x0, &udc_regs_p->endp_int_mask);
563*4882a593Smuzhiyun
564*4882a593Smuzhiyun #ifndef CONFIG_USBD_HS
565*4882a593Smuzhiyun writel(DEV_CONF_FS_SPEED | DEV_CONF_REMWAKEUP | DEV_CONF_SELFPOW |
566*4882a593Smuzhiyun DEV_CONF_PHYINT_16, &udc_regs_p->dev_conf);
567*4882a593Smuzhiyun #else
568*4882a593Smuzhiyun writel(DEV_CONF_HS_SPEED | DEV_CONF_REMWAKEUP | DEV_CONF_SELFPOW |
569*4882a593Smuzhiyun DEV_CONF_PHYINT_16, &udc_regs_p->dev_conf);
570*4882a593Smuzhiyun #endif
571*4882a593Smuzhiyun
572*4882a593Smuzhiyun writel(DEV_CNTL_SOFTDISCONNECT, &udc_regs_p->dev_cntl);
573*4882a593Smuzhiyun
574*4882a593Smuzhiyun /* Clear all interrupts pending */
575*4882a593Smuzhiyun writel(DEV_INT_MSK, &udc_regs_p->dev_int);
576*4882a593Smuzhiyun
577*4882a593Smuzhiyun return 0;
578*4882a593Smuzhiyun }
579*4882a593Smuzhiyun
is_usbd_high_speed(void)580*4882a593Smuzhiyun int is_usbd_high_speed(void)
581*4882a593Smuzhiyun {
582*4882a593Smuzhiyun return (readl(&udc_regs_p->dev_stat) & DEV_STAT_ENUM) ? 0 : 1;
583*4882a593Smuzhiyun }
584*4882a593Smuzhiyun
585*4882a593Smuzhiyun /*
586*4882a593Smuzhiyun * udc_setup_ep - setup endpoint
587*4882a593Smuzhiyun * Associate a physical endpoint with endpoint_instance
588*4882a593Smuzhiyun */
udc_setup_ep(struct usb_device_instance * device,u32 ep,struct usb_endpoint_instance * endpoint)589*4882a593Smuzhiyun void udc_setup_ep(struct usb_device_instance *device,
590*4882a593Smuzhiyun u32 ep, struct usb_endpoint_instance *endpoint)
591*4882a593Smuzhiyun {
592*4882a593Smuzhiyun UDCDBGA("setting up endpoint addr %x", endpoint->endpoint_address);
593*4882a593Smuzhiyun int ep_addr;
594*4882a593Smuzhiyun int ep_num, ep_type;
595*4882a593Smuzhiyun int packet_size;
596*4882a593Smuzhiyun int buffer_size;
597*4882a593Smuzhiyun int attributes;
598*4882a593Smuzhiyun char *tt;
599*4882a593Smuzhiyun u32 endp_intmask;
600*4882a593Smuzhiyun
601*4882a593Smuzhiyun if ((ep != 0) && (udc_device->device_state < STATE_ADDRESSED))
602*4882a593Smuzhiyun return;
603*4882a593Smuzhiyun
604*4882a593Smuzhiyun tt = env_get("usbtty");
605*4882a593Smuzhiyun if (!tt)
606*4882a593Smuzhiyun tt = "generic";
607*4882a593Smuzhiyun
608*4882a593Smuzhiyun ep_addr = endpoint->endpoint_address;
609*4882a593Smuzhiyun ep_num = ep_addr & USB_ENDPOINT_NUMBER_MASK;
610*4882a593Smuzhiyun
611*4882a593Smuzhiyun if ((ep_addr & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) {
612*4882a593Smuzhiyun /* IN endpoint */
613*4882a593Smuzhiyun packet_size = endpoint->tx_packetSize;
614*4882a593Smuzhiyun buffer_size = packet_size * 2;
615*4882a593Smuzhiyun attributes = endpoint->tx_attributes;
616*4882a593Smuzhiyun } else {
617*4882a593Smuzhiyun /* OUT endpoint */
618*4882a593Smuzhiyun packet_size = endpoint->rcv_packetSize;
619*4882a593Smuzhiyun buffer_size = packet_size * 2;
620*4882a593Smuzhiyun attributes = endpoint->rcv_attributes;
621*4882a593Smuzhiyun }
622*4882a593Smuzhiyun
623*4882a593Smuzhiyun switch (attributes & USB_ENDPOINT_XFERTYPE_MASK) {
624*4882a593Smuzhiyun case USB_ENDPOINT_XFER_CONTROL:
625*4882a593Smuzhiyun ep_type = ENDP_EPTYPE_CNTL;
626*4882a593Smuzhiyun break;
627*4882a593Smuzhiyun case USB_ENDPOINT_XFER_BULK:
628*4882a593Smuzhiyun default:
629*4882a593Smuzhiyun ep_type = ENDP_EPTYPE_BULK;
630*4882a593Smuzhiyun break;
631*4882a593Smuzhiyun case USB_ENDPOINT_XFER_INT:
632*4882a593Smuzhiyun ep_type = ENDP_EPTYPE_INT;
633*4882a593Smuzhiyun break;
634*4882a593Smuzhiyun case USB_ENDPOINT_XFER_ISOC:
635*4882a593Smuzhiyun ep_type = ENDP_EPTYPE_ISO;
636*4882a593Smuzhiyun break;
637*4882a593Smuzhiyun }
638*4882a593Smuzhiyun
639*4882a593Smuzhiyun struct udc_endp_regs *out_p = &outep_regs_p[ep_num];
640*4882a593Smuzhiyun struct udc_endp_regs *in_p = &inep_regs_p[ep_num];
641*4882a593Smuzhiyun
642*4882a593Smuzhiyun if (!ep_addr) {
643*4882a593Smuzhiyun /* Setup endpoint 0 */
644*4882a593Smuzhiyun buffer_size = packet_size;
645*4882a593Smuzhiyun
646*4882a593Smuzhiyun writel(readl(&in_p->endp_cntl) | ENDP_CNTL_CNAK,
647*4882a593Smuzhiyun &in_p->endp_cntl);
648*4882a593Smuzhiyun
649*4882a593Smuzhiyun writel(readl(&out_p->endp_cntl) | ENDP_CNTL_CNAK,
650*4882a593Smuzhiyun &out_p->endp_cntl);
651*4882a593Smuzhiyun
652*4882a593Smuzhiyun writel(ENDP_CNTL_CONTROL | ENDP_CNTL_FLUSH, &in_p->endp_cntl);
653*4882a593Smuzhiyun
654*4882a593Smuzhiyun writel(buffer_size / sizeof(int), &in_p->endp_bsorfn);
655*4882a593Smuzhiyun
656*4882a593Smuzhiyun writel(packet_size, &in_p->endp_maxpacksize);
657*4882a593Smuzhiyun
658*4882a593Smuzhiyun writel(ENDP_CNTL_CONTROL | ENDP_CNTL_RRDY, &out_p->endp_cntl);
659*4882a593Smuzhiyun
660*4882a593Smuzhiyun writel(packet_size | ((buffer_size / sizeof(int)) << 16),
661*4882a593Smuzhiyun &out_p->endp_maxpacksize);
662*4882a593Smuzhiyun
663*4882a593Smuzhiyun } else if ((ep_addr & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) {
664*4882a593Smuzhiyun /* Setup the IN endpoint */
665*4882a593Smuzhiyun writel(0x0, &in_p->endp_status);
666*4882a593Smuzhiyun writel((ep_type << 4) | ENDP_CNTL_RRDY, &in_p->endp_cntl);
667*4882a593Smuzhiyun writel(buffer_size / sizeof(int), &in_p->endp_bsorfn);
668*4882a593Smuzhiyun writel(packet_size, &in_p->endp_maxpacksize);
669*4882a593Smuzhiyun
670*4882a593Smuzhiyun if (!strcmp(tt, "cdc_acm")) {
671*4882a593Smuzhiyun if (ep_type == ENDP_EPTYPE_INT) {
672*4882a593Smuzhiyun /* Conf no. 1 Interface no. 0 */
673*4882a593Smuzhiyun writel((packet_size << 19) |
674*4882a593Smuzhiyun ENDP_EPDIR_IN | (1 << 7) |
675*4882a593Smuzhiyun (0 << 11) | (ep_type << 5) | ep_num,
676*4882a593Smuzhiyun &udc_regs_p->udc_endp_reg[ep_num]);
677*4882a593Smuzhiyun } else {
678*4882a593Smuzhiyun /* Conf no. 1 Interface no. 1 */
679*4882a593Smuzhiyun writel((packet_size << 19) |
680*4882a593Smuzhiyun ENDP_EPDIR_IN | (1 << 7) |
681*4882a593Smuzhiyun (1 << 11) | (ep_type << 5) | ep_num,
682*4882a593Smuzhiyun &udc_regs_p->udc_endp_reg[ep_num]);
683*4882a593Smuzhiyun }
684*4882a593Smuzhiyun } else {
685*4882a593Smuzhiyun /* Conf no. 1 Interface no. 0 */
686*4882a593Smuzhiyun writel((packet_size << 19) |
687*4882a593Smuzhiyun ENDP_EPDIR_IN | (1 << 7) |
688*4882a593Smuzhiyun (0 << 11) | (ep_type << 5) | ep_num,
689*4882a593Smuzhiyun &udc_regs_p->udc_endp_reg[ep_num]);
690*4882a593Smuzhiyun }
691*4882a593Smuzhiyun
692*4882a593Smuzhiyun } else {
693*4882a593Smuzhiyun /* Setup the OUT endpoint */
694*4882a593Smuzhiyun writel(0x0, &out_p->endp_status);
695*4882a593Smuzhiyun writel((ep_type << 4) | ENDP_CNTL_RRDY, &out_p->endp_cntl);
696*4882a593Smuzhiyun writel(packet_size | ((buffer_size / sizeof(int)) << 16),
697*4882a593Smuzhiyun &out_p->endp_maxpacksize);
698*4882a593Smuzhiyun
699*4882a593Smuzhiyun if (!strcmp(tt, "cdc_acm")) {
700*4882a593Smuzhiyun writel((packet_size << 19) |
701*4882a593Smuzhiyun ENDP_EPDIR_OUT | (1 << 7) |
702*4882a593Smuzhiyun (1 << 11) | (ep_type << 5) | ep_num,
703*4882a593Smuzhiyun &udc_regs_p->udc_endp_reg[ep_num]);
704*4882a593Smuzhiyun } else {
705*4882a593Smuzhiyun writel((packet_size << 19) |
706*4882a593Smuzhiyun ENDP_EPDIR_OUT | (1 << 7) |
707*4882a593Smuzhiyun (0 << 11) | (ep_type << 5) | ep_num,
708*4882a593Smuzhiyun &udc_regs_p->udc_endp_reg[ep_num]);
709*4882a593Smuzhiyun }
710*4882a593Smuzhiyun
711*4882a593Smuzhiyun }
712*4882a593Smuzhiyun
713*4882a593Smuzhiyun endp_intmask = readl(&udc_regs_p->endp_int_mask);
714*4882a593Smuzhiyun endp_intmask &= ~((1 << ep_num) | 0x10000 << ep_num);
715*4882a593Smuzhiyun writel(endp_intmask, &udc_regs_p->endp_int_mask);
716*4882a593Smuzhiyun }
717*4882a593Smuzhiyun
718*4882a593Smuzhiyun /* Turn on the USB connection by enabling the pullup resistor */
udc_connect(void)719*4882a593Smuzhiyun void udc_connect(void)
720*4882a593Smuzhiyun {
721*4882a593Smuzhiyun u32 plug_st, dev_cntl;
722*4882a593Smuzhiyun
723*4882a593Smuzhiyun dev_cntl = readl(&udc_regs_p->dev_cntl);
724*4882a593Smuzhiyun dev_cntl |= DEV_CNTL_SOFTDISCONNECT;
725*4882a593Smuzhiyun writel(dev_cntl, &udc_regs_p->dev_cntl);
726*4882a593Smuzhiyun
727*4882a593Smuzhiyun udelay(1000);
728*4882a593Smuzhiyun
729*4882a593Smuzhiyun dev_cntl = readl(&udc_regs_p->dev_cntl);
730*4882a593Smuzhiyun dev_cntl &= ~DEV_CNTL_SOFTDISCONNECT;
731*4882a593Smuzhiyun writel(dev_cntl, &udc_regs_p->dev_cntl);
732*4882a593Smuzhiyun
733*4882a593Smuzhiyun plug_st = readl(&plug_regs_p->plug_state);
734*4882a593Smuzhiyun plug_st &= ~(PLUG_STATUS_PHY_RESET | PLUG_STATUS_PHY_MODE);
735*4882a593Smuzhiyun writel(plug_st, &plug_regs_p->plug_state);
736*4882a593Smuzhiyun }
737*4882a593Smuzhiyun
738*4882a593Smuzhiyun /* Turn off the USB connection by disabling the pullup resistor */
udc_disconnect(void)739*4882a593Smuzhiyun void udc_disconnect(void)
740*4882a593Smuzhiyun {
741*4882a593Smuzhiyun u32 plug_st;
742*4882a593Smuzhiyun
743*4882a593Smuzhiyun writel(DEV_CNTL_SOFTDISCONNECT, &udc_regs_p->dev_cntl);
744*4882a593Smuzhiyun
745*4882a593Smuzhiyun plug_st = readl(&plug_regs_p->plug_state);
746*4882a593Smuzhiyun plug_st |= (PLUG_STATUS_PHY_RESET | PLUG_STATUS_PHY_MODE);
747*4882a593Smuzhiyun writel(plug_st, &plug_regs_p->plug_state);
748*4882a593Smuzhiyun }
749*4882a593Smuzhiyun
750*4882a593Smuzhiyun /* Switch on the UDC */
udc_enable(struct usb_device_instance * device)751*4882a593Smuzhiyun void udc_enable(struct usb_device_instance *device)
752*4882a593Smuzhiyun {
753*4882a593Smuzhiyun UDCDBGA("enable device %p, status %d", device, device->status);
754*4882a593Smuzhiyun
755*4882a593Smuzhiyun /* Save the device structure pointer */
756*4882a593Smuzhiyun udc_device = device;
757*4882a593Smuzhiyun
758*4882a593Smuzhiyun /* Setup ep0 urb */
759*4882a593Smuzhiyun if (!ep0_urb) {
760*4882a593Smuzhiyun ep0_urb =
761*4882a593Smuzhiyun usbd_alloc_urb(udc_device, udc_device->bus->endpoint_array);
762*4882a593Smuzhiyun } else {
763*4882a593Smuzhiyun serial_printf("udc_enable: ep0_urb already allocated %p\n",
764*4882a593Smuzhiyun ep0_urb);
765*4882a593Smuzhiyun }
766*4882a593Smuzhiyun
767*4882a593Smuzhiyun writel(DEV_INT_SOF, &udc_regs_p->dev_int_mask);
768*4882a593Smuzhiyun }
769*4882a593Smuzhiyun
770*4882a593Smuzhiyun /**
771*4882a593Smuzhiyun * udc_startup - allow udc code to do any additional startup
772*4882a593Smuzhiyun */
udc_startup_events(struct usb_device_instance * device)773*4882a593Smuzhiyun void udc_startup_events(struct usb_device_instance *device)
774*4882a593Smuzhiyun {
775*4882a593Smuzhiyun /* The DEVICE_INIT event puts the USB device in the state STATE_INIT. */
776*4882a593Smuzhiyun usbd_device_event_irq(device, DEVICE_INIT, 0);
777*4882a593Smuzhiyun
778*4882a593Smuzhiyun /*
779*4882a593Smuzhiyun * The DEVICE_CREATE event puts the USB device in the state
780*4882a593Smuzhiyun * STATE_ATTACHED.
781*4882a593Smuzhiyun */
782*4882a593Smuzhiyun usbd_device_event_irq(device, DEVICE_CREATE, 0);
783*4882a593Smuzhiyun
784*4882a593Smuzhiyun /*
785*4882a593Smuzhiyun * Some USB controller driver implementations signal
786*4882a593Smuzhiyun * DEVICE_HUB_CONFIGURED and DEVICE_RESET events here.
787*4882a593Smuzhiyun * DEVICE_HUB_CONFIGURED causes a transition to the state STATE_POWERED,
788*4882a593Smuzhiyun * and DEVICE_RESET causes a transition to the state STATE_DEFAULT.
789*4882a593Smuzhiyun * The DW USB client controller has the capability to detect when the
790*4882a593Smuzhiyun * USB cable is connected to a powered USB bus, so we will defer the
791*4882a593Smuzhiyun * DEVICE_HUB_CONFIGURED and DEVICE_RESET events until later.
792*4882a593Smuzhiyun */
793*4882a593Smuzhiyun
794*4882a593Smuzhiyun udc_enable(device);
795*4882a593Smuzhiyun }
796*4882a593Smuzhiyun
797*4882a593Smuzhiyun /*
798*4882a593Smuzhiyun * Plug detection interrupt handling
799*4882a593Smuzhiyun */
dw_udc_plug_irq(void)800*4882a593Smuzhiyun static void dw_udc_plug_irq(void)
801*4882a593Smuzhiyun {
802*4882a593Smuzhiyun if (readl(&plug_regs_p->plug_state) & PLUG_STATUS_ATTACHED) {
803*4882a593Smuzhiyun /*
804*4882a593Smuzhiyun * USB cable attached
805*4882a593Smuzhiyun * Turn off PHY reset bit (PLUG detect).
806*4882a593Smuzhiyun * Switch PHY opmode to normal operation (PLUG detect).
807*4882a593Smuzhiyun */
808*4882a593Smuzhiyun udc_connect();
809*4882a593Smuzhiyun writel(DEV_INT_SOF, &udc_regs_p->dev_int_mask);
810*4882a593Smuzhiyun
811*4882a593Smuzhiyun UDCDBG("device attached and powered");
812*4882a593Smuzhiyun udc_state_transition(udc_device->device_state, STATE_POWERED);
813*4882a593Smuzhiyun } else {
814*4882a593Smuzhiyun writel(~0x0, &udc_regs_p->dev_int_mask);
815*4882a593Smuzhiyun
816*4882a593Smuzhiyun UDCDBG("device detached or unpowered");
817*4882a593Smuzhiyun udc_state_transition(udc_device->device_state, STATE_ATTACHED);
818*4882a593Smuzhiyun }
819*4882a593Smuzhiyun }
820*4882a593Smuzhiyun
821*4882a593Smuzhiyun /*
822*4882a593Smuzhiyun * Device interrupt handling
823*4882a593Smuzhiyun */
dw_udc_dev_irq(void)824*4882a593Smuzhiyun static void dw_udc_dev_irq(void)
825*4882a593Smuzhiyun {
826*4882a593Smuzhiyun if (readl(&udc_regs_p->dev_int) & DEV_INT_USBRESET) {
827*4882a593Smuzhiyun writel(~0x0, &udc_regs_p->endp_int_mask);
828*4882a593Smuzhiyun
829*4882a593Smuzhiyun writel(readl(&inep_regs_p[0].endp_cntl) | ENDP_CNTL_FLUSH,
830*4882a593Smuzhiyun &inep_regs_p[0].endp_cntl);
831*4882a593Smuzhiyun
832*4882a593Smuzhiyun writel(DEV_INT_USBRESET, &udc_regs_p->dev_int);
833*4882a593Smuzhiyun
834*4882a593Smuzhiyun /*
835*4882a593Smuzhiyun * This endpoint0 specific register can be programmed only
836*4882a593Smuzhiyun * after the phy clock is initialized
837*4882a593Smuzhiyun */
838*4882a593Smuzhiyun writel((EP0_MAX_PACKET_SIZE << 19) | ENDP_EPTYPE_CNTL,
839*4882a593Smuzhiyun &udc_regs_p->udc_endp_reg[0]);
840*4882a593Smuzhiyun
841*4882a593Smuzhiyun UDCDBG("device reset in progess");
842*4882a593Smuzhiyun udc_state_transition(udc_device->device_state, STATE_DEFAULT);
843*4882a593Smuzhiyun }
844*4882a593Smuzhiyun
845*4882a593Smuzhiyun /* Device Enumeration completed */
846*4882a593Smuzhiyun if (readl(&udc_regs_p->dev_int) & DEV_INT_ENUM) {
847*4882a593Smuzhiyun writel(DEV_INT_ENUM, &udc_regs_p->dev_int);
848*4882a593Smuzhiyun
849*4882a593Smuzhiyun /* Endpoint interrupt enabled for Ctrl IN & Ctrl OUT */
850*4882a593Smuzhiyun writel(readl(&udc_regs_p->endp_int_mask) & ~0x10001,
851*4882a593Smuzhiyun &udc_regs_p->endp_int_mask);
852*4882a593Smuzhiyun
853*4882a593Smuzhiyun UDCDBG("default -> addressed");
854*4882a593Smuzhiyun udc_state_transition(udc_device->device_state, STATE_ADDRESSED);
855*4882a593Smuzhiyun }
856*4882a593Smuzhiyun
857*4882a593Smuzhiyun /* The USB will be in SUSPEND in 3 ms */
858*4882a593Smuzhiyun if (readl(&udc_regs_p->dev_int) & DEV_INT_INACTIVE) {
859*4882a593Smuzhiyun writel(DEV_INT_INACTIVE, &udc_regs_p->dev_int);
860*4882a593Smuzhiyun
861*4882a593Smuzhiyun UDCDBG("entering inactive state");
862*4882a593Smuzhiyun /* usbd_device_event_irq(udc_device, DEVICE_BUS_INACTIVE, 0); */
863*4882a593Smuzhiyun }
864*4882a593Smuzhiyun
865*4882a593Smuzhiyun /* SetConfiguration command received */
866*4882a593Smuzhiyun if (readl(&udc_regs_p->dev_int) & DEV_INT_SETCFG) {
867*4882a593Smuzhiyun writel(DEV_INT_SETCFG, &udc_regs_p->dev_int);
868*4882a593Smuzhiyun
869*4882a593Smuzhiyun UDCDBG("entering configured state");
870*4882a593Smuzhiyun udc_state_transition(udc_device->device_state,
871*4882a593Smuzhiyun STATE_CONFIGURED);
872*4882a593Smuzhiyun }
873*4882a593Smuzhiyun
874*4882a593Smuzhiyun /* SetInterface command received */
875*4882a593Smuzhiyun if (readl(&udc_regs_p->dev_int) & DEV_INT_SETINTF)
876*4882a593Smuzhiyun writel(DEV_INT_SETINTF, &udc_regs_p->dev_int);
877*4882a593Smuzhiyun
878*4882a593Smuzhiyun /* USB Suspend detected on cable */
879*4882a593Smuzhiyun if (readl(&udc_regs_p->dev_int) & DEV_INT_SUSPUSB) {
880*4882a593Smuzhiyun writel(DEV_INT_SUSPUSB, &udc_regs_p->dev_int);
881*4882a593Smuzhiyun
882*4882a593Smuzhiyun UDCDBG("entering suspended state");
883*4882a593Smuzhiyun usbd_device_event_irq(udc_device, DEVICE_BUS_INACTIVE, 0);
884*4882a593Smuzhiyun }
885*4882a593Smuzhiyun
886*4882a593Smuzhiyun /* USB Start-Of-Frame detected on cable */
887*4882a593Smuzhiyun if (readl(&udc_regs_p->dev_int) & DEV_INT_SOF)
888*4882a593Smuzhiyun writel(DEV_INT_SOF, &udc_regs_p->dev_int);
889*4882a593Smuzhiyun }
890*4882a593Smuzhiyun
891*4882a593Smuzhiyun /*
892*4882a593Smuzhiyun * Endpoint interrupt handling
893*4882a593Smuzhiyun */
dw_udc_endpoint_irq(void)894*4882a593Smuzhiyun static void dw_udc_endpoint_irq(void)
895*4882a593Smuzhiyun {
896*4882a593Smuzhiyun while (readl(&udc_regs_p->endp_int) & ENDP0_INT_CTRLOUT) {
897*4882a593Smuzhiyun
898*4882a593Smuzhiyun writel(ENDP0_INT_CTRLOUT, &udc_regs_p->endp_int);
899*4882a593Smuzhiyun
900*4882a593Smuzhiyun if ((readl(&outep_regs_p[0].endp_status) & ENDP_STATUS_OUTMSK)
901*4882a593Smuzhiyun == ENDP_STATUS_OUT_SETUP) {
902*4882a593Smuzhiyun dw_udc_setup(udc_device->bus->endpoint_array + 0);
903*4882a593Smuzhiyun writel(ENDP_STATUS_OUT_SETUP,
904*4882a593Smuzhiyun &outep_regs_p[0].endp_status);
905*4882a593Smuzhiyun
906*4882a593Smuzhiyun } else if ((readl(&outep_regs_p[0].endp_status) &
907*4882a593Smuzhiyun ENDP_STATUS_OUTMSK) == ENDP_STATUS_OUT_DATA) {
908*4882a593Smuzhiyun dw_udc_ep0_rx(udc_device->bus->endpoint_array + 0);
909*4882a593Smuzhiyun writel(ENDP_STATUS_OUT_DATA,
910*4882a593Smuzhiyun &outep_regs_p[0].endp_status);
911*4882a593Smuzhiyun
912*4882a593Smuzhiyun } else if ((readl(&outep_regs_p[0].endp_status) &
913*4882a593Smuzhiyun ENDP_STATUS_OUTMSK) == ENDP_STATUS_OUT_NONE) {
914*4882a593Smuzhiyun /* NONE received */
915*4882a593Smuzhiyun }
916*4882a593Smuzhiyun
917*4882a593Smuzhiyun writel(0x0, &outep_regs_p[0].endp_status);
918*4882a593Smuzhiyun }
919*4882a593Smuzhiyun
920*4882a593Smuzhiyun if (readl(&udc_regs_p->endp_int) & ENDP0_INT_CTRLIN) {
921*4882a593Smuzhiyun dw_udc_ep0_tx(udc_device->bus->endpoint_array + 0);
922*4882a593Smuzhiyun
923*4882a593Smuzhiyun writel(ENDP_STATUS_IN, &inep_regs_p[0].endp_status);
924*4882a593Smuzhiyun writel(ENDP0_INT_CTRLIN, &udc_regs_p->endp_int);
925*4882a593Smuzhiyun }
926*4882a593Smuzhiyun
927*4882a593Smuzhiyun if (readl(&udc_regs_p->endp_int) & ENDP_INT_NONISOOUT_MSK) {
928*4882a593Smuzhiyun u32 epnum = 0;
929*4882a593Smuzhiyun u32 ep_int = readl(&udc_regs_p->endp_int) &
930*4882a593Smuzhiyun ENDP_INT_NONISOOUT_MSK;
931*4882a593Smuzhiyun
932*4882a593Smuzhiyun ep_int >>= 16;
933*4882a593Smuzhiyun while (0x0 == (ep_int & 0x1)) {
934*4882a593Smuzhiyun ep_int >>= 1;
935*4882a593Smuzhiyun epnum++;
936*4882a593Smuzhiyun }
937*4882a593Smuzhiyun
938*4882a593Smuzhiyun writel((1 << 16) << epnum, &udc_regs_p->endp_int);
939*4882a593Smuzhiyun
940*4882a593Smuzhiyun if ((readl(&outep_regs_p[epnum].endp_status) &
941*4882a593Smuzhiyun ENDP_STATUS_OUTMSK) == ENDP_STATUS_OUT_DATA) {
942*4882a593Smuzhiyun
943*4882a593Smuzhiyun dw_udc_epn_rx(epnum);
944*4882a593Smuzhiyun writel(ENDP_STATUS_OUT_DATA,
945*4882a593Smuzhiyun &outep_regs_p[epnum].endp_status);
946*4882a593Smuzhiyun } else if ((readl(&outep_regs_p[epnum].endp_status) &
947*4882a593Smuzhiyun ENDP_STATUS_OUTMSK) == ENDP_STATUS_OUT_NONE) {
948*4882a593Smuzhiyun writel(0x0, &outep_regs_p[epnum].endp_status);
949*4882a593Smuzhiyun }
950*4882a593Smuzhiyun }
951*4882a593Smuzhiyun
952*4882a593Smuzhiyun if (readl(&udc_regs_p->endp_int) & ENDP_INT_NONISOIN_MSK) {
953*4882a593Smuzhiyun u32 epnum = 0;
954*4882a593Smuzhiyun u32 ep_int = readl(&udc_regs_p->endp_int) &
955*4882a593Smuzhiyun ENDP_INT_NONISOIN_MSK;
956*4882a593Smuzhiyun
957*4882a593Smuzhiyun while (0x0 == (ep_int & 0x1)) {
958*4882a593Smuzhiyun ep_int >>= 1;
959*4882a593Smuzhiyun epnum++;
960*4882a593Smuzhiyun }
961*4882a593Smuzhiyun
962*4882a593Smuzhiyun if (readl(&inep_regs_p[epnum].endp_status) & ENDP_STATUS_IN) {
963*4882a593Smuzhiyun writel(ENDP_STATUS_IN,
964*4882a593Smuzhiyun &outep_regs_p[epnum].endp_status);
965*4882a593Smuzhiyun dw_udc_epn_tx(epnum);
966*4882a593Smuzhiyun
967*4882a593Smuzhiyun writel(ENDP_STATUS_IN,
968*4882a593Smuzhiyun &outep_regs_p[epnum].endp_status);
969*4882a593Smuzhiyun }
970*4882a593Smuzhiyun
971*4882a593Smuzhiyun writel((1 << epnum), &udc_regs_p->endp_int);
972*4882a593Smuzhiyun }
973*4882a593Smuzhiyun }
974*4882a593Smuzhiyun
975*4882a593Smuzhiyun /*
976*4882a593Smuzhiyun * UDC interrupts
977*4882a593Smuzhiyun */
udc_irq(void)978*4882a593Smuzhiyun void udc_irq(void)
979*4882a593Smuzhiyun {
980*4882a593Smuzhiyun /*
981*4882a593Smuzhiyun * Loop while we have interrupts.
982*4882a593Smuzhiyun * If we don't do this, the input chain
983*4882a593Smuzhiyun * polling delay is likely to miss
984*4882a593Smuzhiyun * host requests.
985*4882a593Smuzhiyun */
986*4882a593Smuzhiyun while (readl(&plug_regs_p->plug_pending))
987*4882a593Smuzhiyun dw_udc_plug_irq();
988*4882a593Smuzhiyun
989*4882a593Smuzhiyun while (readl(&udc_regs_p->dev_int))
990*4882a593Smuzhiyun dw_udc_dev_irq();
991*4882a593Smuzhiyun
992*4882a593Smuzhiyun if (readl(&udc_regs_p->endp_int))
993*4882a593Smuzhiyun dw_udc_endpoint_irq();
994*4882a593Smuzhiyun }
995*4882a593Smuzhiyun
996*4882a593Smuzhiyun /* Flow control */
udc_set_nak(int epid)997*4882a593Smuzhiyun void udc_set_nak(int epid)
998*4882a593Smuzhiyun {
999*4882a593Smuzhiyun writel(readl(&inep_regs_p[epid].endp_cntl) | ENDP_CNTL_SNAK,
1000*4882a593Smuzhiyun &inep_regs_p[epid].endp_cntl);
1001*4882a593Smuzhiyun
1002*4882a593Smuzhiyun writel(readl(&outep_regs_p[epid].endp_cntl) | ENDP_CNTL_SNAK,
1003*4882a593Smuzhiyun &outep_regs_p[epid].endp_cntl);
1004*4882a593Smuzhiyun }
1005*4882a593Smuzhiyun
udc_unset_nak(int epid)1006*4882a593Smuzhiyun void udc_unset_nak(int epid)
1007*4882a593Smuzhiyun {
1008*4882a593Smuzhiyun u32 val;
1009*4882a593Smuzhiyun
1010*4882a593Smuzhiyun val = readl(&inep_regs_p[epid].endp_cntl);
1011*4882a593Smuzhiyun val &= ~ENDP_CNTL_SNAK;
1012*4882a593Smuzhiyun val |= ENDP_CNTL_CNAK;
1013*4882a593Smuzhiyun writel(val, &inep_regs_p[epid].endp_cntl);
1014*4882a593Smuzhiyun
1015*4882a593Smuzhiyun val = readl(&outep_regs_p[epid].endp_cntl);
1016*4882a593Smuzhiyun val &= ~ENDP_CNTL_SNAK;
1017*4882a593Smuzhiyun val |= ENDP_CNTL_CNAK;
1018*4882a593Smuzhiyun writel(val, &outep_regs_p[epid].endp_cntl);
1019*4882a593Smuzhiyun }
1020