xref: /openbmc/u-boot/drivers/usb/gadget/aspeed_udc.c (revision 93265845)
1*93265845Sneal_liu // SPDX-License-Identifier: GPL-2.0
2*93265845Sneal_liu /*
3*93265845Sneal_liu  * Copyright (C) ASPEED Technology Inc.
4*93265845Sneal_liu  *
5*93265845Sneal_liu  */
6*93265845Sneal_liu 
7*93265845Sneal_liu #include <asm/io.h>
8*93265845Sneal_liu #include <asm/byteorder.h>
9*93265845Sneal_liu #include <common.h>
10*93265845Sneal_liu #include <config.h>
11*93265845Sneal_liu #include <dm.h>
12*93265845Sneal_liu #include <fdtdec.h>
13*93265845Sneal_liu #include <reset.h>
14*93265845Sneal_liu #include <usbdevice.h>
15*93265845Sneal_liu 
16*93265845Sneal_liu #include "ep0.h"
17*93265845Sneal_liu 
18*93265845Sneal_liu #define MIN(_x, _y)		\
19*93265845Sneal_liu 	typeof(_x) (x) = (_x);	\
20*93265845Sneal_liu 	typeof(_y) (y) = (_y);	\
21*93265845Sneal_liu 	((x) < (y) ? (x) : (y))
22*93265845Sneal_liu 
23*93265845Sneal_liu /* number of endpoints on this UDC */
24*93265845Sneal_liu #define UDC_MAX_ENDPOINTS	21
25*93265845Sneal_liu 
26*93265845Sneal_liu static struct urb *ep0_urb;
27*93265845Sneal_liu static struct usb_device_instance *udc_device;
28*93265845Sneal_liu 
29*93265845Sneal_liu struct aspeed_udc_priv {
30*93265845Sneal_liu 	u32 udc_base;
31*93265845Sneal_liu 	int init;
32*93265845Sneal_liu };
33*93265845Sneal_liu 
34*93265845Sneal_liu struct aspeed_udc_priv *aspeed_udc;
35*93265845Sneal_liu 
36*93265845Sneal_liu /*************************************************************************************/
37*93265845Sneal_liu #define AST_VHUB_CTRL				0x00
38*93265845Sneal_liu #define AST_VHUB_CONF				0x04
39*93265845Sneal_liu #define AST_VHUB_IER				0x08
40*93265845Sneal_liu #define AST_VHUB_ISR				0x0C
41*93265845Sneal_liu #define AST_VHUB_EP_ACK_IER			0x10
42*93265845Sneal_liu #define AST_VHUB_EP_NAK_IER			0x14
43*93265845Sneal_liu #define AST_VHUB_EP_ACK_ISR			0x18
44*93265845Sneal_liu #define AST_VHUB_EP_NAK_ISR			0x1C
45*93265845Sneal_liu #define AST_VHUB_DEV_RESET			0x20
46*93265845Sneal_liu #define AST_VHUB_USB_STS			0x24
47*93265845Sneal_liu #define AST_VHUB_EP_DATA			0x28
48*93265845Sneal_liu #define AST_VHUB_ISO_TX_FAIL			0x2C
49*93265845Sneal_liu #define AST_VHUB_EP0_CTRL			0x30
50*93265845Sneal_liu #define AST_VHUB_EP0_DATA_BUFF			0x34
51*93265845Sneal_liu #define AST_VHUB_EP1_CTRL			0x38
52*93265845Sneal_liu #define AST_VHUB_EP1_STS_CHG			0x3C
53*93265845Sneal_liu 
54*93265845Sneal_liu #define AST_VHUB_SETUP_DATA0			0x80
55*93265845Sneal_liu #define AST_VHUB_SETUP_DATA1			0x84
56*93265845Sneal_liu 
57*93265845Sneal_liu /*  ************************************************************************************/
58*93265845Sneal_liu /* AST_VHUB_CTRL				0x00 */
59*93265845Sneal_liu #define ROOT_PHY_CLK_EN				BIT(31)
60*93265845Sneal_liu #define ROOT_PHY_RESET_DIS			BIT(11)
61*93265845Sneal_liu #define ROOT_UPSTREAM_EN			BIT(0)
62*93265845Sneal_liu 
63*93265845Sneal_liu /* AST_VHUB_ISR					0x0C */
64*93265845Sneal_liu #define ISR_EP_NAK				BIT(17)
65*93265845Sneal_liu #define ISR_EP_ACK_STALL			BIT(16)
66*93265845Sneal_liu #define ISR_DEVICE7				BIT(15)
67*93265845Sneal_liu #define ISR_DEVICE6				BIT(14)
68*93265845Sneal_liu #define ISR_DEVICE5				BIT(13)
69*93265845Sneal_liu #define ISR_DEVICE4				BIT(12)
70*93265845Sneal_liu #define ISR_DEVICE3				BIT(11)
71*93265845Sneal_liu #define ISR_DEVICE2				BIT(10)
72*93265845Sneal_liu #define ISR_DEVICE1				BIT(9)
73*93265845Sneal_liu #define ISR_SUSPEND_RESUME			BIT(8)
74*93265845Sneal_liu #define ISR_BUS_SUSPEND				BIT(7)
75*93265845Sneal_liu #define ISR_BUS_RESET				BIT(6)
76*93265845Sneal_liu #define ISR_HUB_EP1_IN_DATA_ACK			BIT(5)
77*93265845Sneal_liu #define ISR_HUB_EP0_IN_DATA_NAK			BIT(4)
78*93265845Sneal_liu #define ISR_HUB_EP0_IN_ACK_STALL		BIT(3)
79*93265845Sneal_liu #define ISR_HUB_EP0_OUT_NAK			BIT(2)
80*93265845Sneal_liu #define ISR_HUB_EP0_OUT_ACK_STALL		BIT(1)
81*93265845Sneal_liu #define ISR_HUB_EP0_SETUP			BIT(0)
82*93265845Sneal_liu 
83*93265845Sneal_liu /* AST_VHUB_USB_STS				0x24 */
84*93265845Sneal_liu #define USB_BUS_HIGH_SPEED			BIT(27)
85*93265845Sneal_liu 
86*93265845Sneal_liu /* AST_VHUB_EP0_CTRL				0x30 */
87*93265845Sneal_liu #define EP0_GET_RX_LEN(x)			(((x) >> 16) & 0x7f)
88*93265845Sneal_liu #define EP0_TX_LEN(x)				(((x) & 0x7f) << 8)
89*93265845Sneal_liu #define EP0_RX_BUFF_RDY				BIT(2)
90*93265845Sneal_liu #define EP0_TX_BUFF_RDY				BIT(1)
91*93265845Sneal_liu #define EP0_STALL				BIT(0)
92*93265845Sneal_liu 
93*93265845Sneal_liu #define AST_UDC_DEV_CTRL			0x00
94*93265845Sneal_liu #define AST_UDC_DEV_ISR				0x04
95*93265845Sneal_liu #define AST_UDC_DEV_EP0_CTRL			0x08
96*93265845Sneal_liu #define AST_UDC_DEV_EP0_DATA_BUFF		0x0C
97*93265845Sneal_liu 
98*93265845Sneal_liu /*************************************************************************************/
99*93265845Sneal_liu #define AST_EP_BASE				0x200
100*93265845Sneal_liu #define AST_EP_OFFSET				0x10
101*93265845Sneal_liu #define AST_EP_CONFIG				0x00
102*93265845Sneal_liu #define AST_EP_DMA_CTRL				0x04
103*93265845Sneal_liu #define AST_EP_DMA_BUFF				0x08
104*93265845Sneal_liu #define AST_EP_DMA_STS				0x0C
105*93265845Sneal_liu 
106*93265845Sneal_liu /*************************************************************************************/
107*93265845Sneal_liu /* AST_EP_CONFIG				0x00 */
108*93265845Sneal_liu #define EP_SET_MAX_PKT(x)			(((x) & 0x3ff) << 16)
109*93265845Sneal_liu #define EP_SET_EP_STALL				BIT(12)
110*93265845Sneal_liu #define EP_SET_EP_NUM(x)			(((x) & 0xf) << 8)
111*93265845Sneal_liu #define EP_TYPE_BULK_IN				(0x2 << 4)
112*93265845Sneal_liu #define EP_TYPE_BULK_OUT			(0x3 << 4)
113*93265845Sneal_liu #define EP_TYPE_INT_IN				(0x4 << 4)
114*93265845Sneal_liu #define EP_TYPE_INT_OUT				(0x5 << 4)
115*93265845Sneal_liu #define EP_TYPE_ISO_IN				(0x6 << 4)
116*93265845Sneal_liu #define EP_TYPE_ISO_OUT				(0x7 << 4)
117*93265845Sneal_liu #define EP_ENABLE				BIT(0)
118*93265845Sneal_liu 
119*93265845Sneal_liu /* AST_EP_DMA_CTRL				0x04 */
120*93265845Sneal_liu #define EP_SINGLE_DESC_MODE			BIT(1)
121*93265845Sneal_liu 
122*93265845Sneal_liu /* AST_EP_DMA_STS				0x0C */
123*93265845Sneal_liu #define AST_EP_TX_DATA_BYTE(x)			(((x) & 0x3ff) << 16)
124*93265845Sneal_liu #define AST_EP_START_TRANS			BIT(0)
125*93265845Sneal_liu 
126*93265845Sneal_liu /*-------------------------------------------------------------------------*/
127*93265845Sneal_liu #define ast_udc_read(offset) \
128*93265845Sneal_liu 	__raw_readl(aspeed_udc->udc_base + (offset))
129*93265845Sneal_liu #define ast_udc_write(val, offset) \
130*93265845Sneal_liu 	__raw_writel((u32)val, aspeed_udc->udc_base + (offset))
131*93265845Sneal_liu 
132*93265845Sneal_liu #define ast_ep_read(ep_reg, reg) \
133*93265845Sneal_liu 	__raw_readl((ep_reg) + (reg))
134*93265845Sneal_liu #define ast_ep_write(ep_reg, val, reg) \
135*93265845Sneal_liu 	__raw_writel((u32)val, (ep_reg) + (reg))
136*93265845Sneal_liu /*-------------------------------------------------------------------------*/
137*93265845Sneal_liu 
138*93265845Sneal_liu int is_usbd_high_speed(void)
139*93265845Sneal_liu {
140*93265845Sneal_liu 	if (ast_udc_read(AST_VHUB_USB_STS) & USB_BUS_HIGH_SPEED)
141*93265845Sneal_liu 		return 1;
142*93265845Sneal_liu 
143*93265845Sneal_liu 	return 0;
144*93265845Sneal_liu }
145*93265845Sneal_liu 
146*93265845Sneal_liu static void udc_stall_ep(u32 ep_num)
147*93265845Sneal_liu {
148*93265845Sneal_liu 	u32 ep_reg;
149*93265845Sneal_liu 
150*93265845Sneal_liu 	usbdbg("stall ep: %d", ep_num);
151*93265845Sneal_liu 
152*93265845Sneal_liu 	if (ep_num) {
153*93265845Sneal_liu 		ep_reg = aspeed_udc->udc_base + AST_EP_BASE +
154*93265845Sneal_liu 			 (AST_EP_OFFSET * (ep_num - 1));
155*93265845Sneal_liu 		ast_ep_write(ep_reg, ast_ep_read(ep_reg, AST_EP_CONFIG) |
156*93265845Sneal_liu 			     EP_SET_EP_STALL,
157*93265845Sneal_liu 			     AST_EP_CONFIG);
158*93265845Sneal_liu 
159*93265845Sneal_liu 	} else {
160*93265845Sneal_liu 		ast_udc_write(ast_udc_read(AST_VHUB_EP0_CTRL) | EP0_STALL,
161*93265845Sneal_liu 			      AST_VHUB_EP0_CTRL);
162*93265845Sneal_liu 	}
163*93265845Sneal_liu }
164*93265845Sneal_liu 
165*93265845Sneal_liu int udc_endpoint_write(struct usb_endpoint_instance *endpoint)
166*93265845Sneal_liu {
167*93265845Sneal_liu 	struct urb *urb = endpoint->tx_urb;
168*93265845Sneal_liu 	u32 remaining_packet;
169*93265845Sneal_liu 	u32 ep_reg, length;
170*93265845Sneal_liu 	int timeout = 2000; // 2ms
171*93265845Sneal_liu 	int ep_num;
172*93265845Sneal_liu 	u8 *data;
173*93265845Sneal_liu 
174*93265845Sneal_liu 	if (!endpoint) {
175*93265845Sneal_liu 		usberr("Error input: endpoint\n");
176*93265845Sneal_liu 		return -1;
177*93265845Sneal_liu 	}
178*93265845Sneal_liu 
179*93265845Sneal_liu 	ep_num = endpoint->endpoint_address & USB_ENDPOINT_NUMBER_MASK;
180*93265845Sneal_liu 	ep_reg = aspeed_udc->udc_base + AST_EP_BASE + (AST_EP_OFFSET * (ep_num - 1));
181*93265845Sneal_liu 	remaining_packet = urb->actual_length - endpoint->sent;
182*93265845Sneal_liu 
183*93265845Sneal_liu 	if (endpoint->tx_packetSize < remaining_packet)
184*93265845Sneal_liu 		length = endpoint->tx_packetSize;
185*93265845Sneal_liu 	else
186*93265845Sneal_liu 		length = remaining_packet;
187*93265845Sneal_liu 
188*93265845Sneal_liu //	usbdbg("ep: %d, trans len: %d, ep sent: %d, urb actual len: %d\n",
189*93265845Sneal_liu //		ep_num, length, endpoint->sent, urb->actual_length);
190*93265845Sneal_liu 
191*93265845Sneal_liu 	data = (u8 *)urb->buffer;
192*93265845Sneal_liu 	data += endpoint->sent;
193*93265845Sneal_liu 
194*93265845Sneal_liu 	// tx trigger
195*93265845Sneal_liu 	ast_ep_write(ep_reg, data, AST_EP_DMA_BUFF);
196*93265845Sneal_liu 	ast_ep_write(ep_reg, AST_EP_TX_DATA_BYTE(length), AST_EP_DMA_STS);
197*93265845Sneal_liu 	ast_ep_write(ep_reg, AST_EP_TX_DATA_BYTE(length) | AST_EP_START_TRANS,
198*93265845Sneal_liu 		     AST_EP_DMA_STS);
199*93265845Sneal_liu 
200*93265845Sneal_liu 	endpoint->last = length;
201*93265845Sneal_liu 
202*93265845Sneal_liu 	// wait for tx complete
203*93265845Sneal_liu 	while (ast_ep_read(ep_reg, AST_EP_DMA_STS) & 0x1) {
204*93265845Sneal_liu 		if (timeout-- == 0)
205*93265845Sneal_liu 			return -1;
206*93265845Sneal_liu 
207*93265845Sneal_liu 		udelay(1);
208*93265845Sneal_liu 	}
209*93265845Sneal_liu 
210*93265845Sneal_liu 	return 0;
211*93265845Sneal_liu }
212*93265845Sneal_liu 
213*93265845Sneal_liu static void ast_udc_ep_handle(struct usb_endpoint_instance *endpoint)
214*93265845Sneal_liu {
215*93265845Sneal_liu 	int ep_isout, ep_num;
216*93265845Sneal_liu 	int nbytes;
217*93265845Sneal_liu 	u32 ep_reg;
218*93265845Sneal_liu 
219*93265845Sneal_liu 	ep_isout = (endpoint->endpoint_address & USB_ENDPOINT_DIR_MASK) ==
220*93265845Sneal_liu 		   USB_DIR_OUT;
221*93265845Sneal_liu 	ep_num = endpoint->endpoint_address & USB_ENDPOINT_NUMBER_MASK;
222*93265845Sneal_liu 
223*93265845Sneal_liu 	ep_reg = aspeed_udc->udc_base + AST_EP_BASE + (AST_EP_OFFSET * (ep_num - 1));
224*93265845Sneal_liu 
225*93265845Sneal_liu 	if (ep_isout) {
226*93265845Sneal_liu 		nbytes = (ast_ep_read(ep_reg, AST_EP_DMA_STS) >> 16) & 0x7ff;
227*93265845Sneal_liu 		usbd_rcv_complete(endpoint, nbytes, 0);
228*93265845Sneal_liu 
229*93265845Sneal_liu 		//trigger next
230*93265845Sneal_liu 		ast_ep_write(ep_reg, AST_EP_START_TRANS, AST_EP_DMA_STS);
231*93265845Sneal_liu 
232*93265845Sneal_liu 	} else {
233*93265845Sneal_liu 		usbd_tx_complete(endpoint);
234*93265845Sneal_liu 	}
235*93265845Sneal_liu }
236*93265845Sneal_liu 
237*93265845Sneal_liu static void ast_udc_ep0_rx(struct usb_endpoint_instance *endpoint)
238*93265845Sneal_liu {
239*93265845Sneal_liu 	struct urb *urb;
240*93265845Sneal_liu 	u8 *buff;
241*93265845Sneal_liu 
242*93265845Sneal_liu 	if (!endpoint) {
243*93265845Sneal_liu 		usberr("Error input: endpoint\n");
244*93265845Sneal_liu 		return;
245*93265845Sneal_liu 	}
246*93265845Sneal_liu 
247*93265845Sneal_liu 	urb = endpoint->rcv_urb;
248*93265845Sneal_liu 	if (!urb) {
249*93265845Sneal_liu 		usberr("Error: rcv_urb is empty\n");
250*93265845Sneal_liu 		return;
251*93265845Sneal_liu 	}
252*93265845Sneal_liu 
253*93265845Sneal_liu 	buff = urb->buffer;
254*93265845Sneal_liu 	ast_udc_write(buff, AST_VHUB_EP0_DATA_BUFF);
255*93265845Sneal_liu 
256*93265845Sneal_liu 	// trigger rx
257*93265845Sneal_liu 	ast_udc_write(EP0_RX_BUFF_RDY, AST_VHUB_EP0_CTRL);
258*93265845Sneal_liu }
259*93265845Sneal_liu 
260*93265845Sneal_liu static void ast_udc_ep0_out(struct usb_endpoint_instance *endpoint)
261*93265845Sneal_liu {
262*93265845Sneal_liu 	u16 rx_len = EP0_GET_RX_LEN(ast_udc_read(AST_VHUB_EP0_CTRL));
263*93265845Sneal_liu 
264*93265845Sneal_liu 	/* Check direction */
265*93265845Sneal_liu 	if ((ep0_urb->device_request.bmRequestType & USB_REQ_DIRECTION_MASK) ==
266*93265845Sneal_liu 		USB_REQ_DEVICE2HOST) {
267*93265845Sneal_liu 		if (rx_len != 0)
268*93265845Sneal_liu 			usberr("Unexpected USB REQ direction: D2H\n");
269*93265845Sneal_liu 
270*93265845Sneal_liu 	} else {
271*93265845Sneal_liu 		usbdbg("EP0 OUT packet ACK, sent zero-length packet");
272*93265845Sneal_liu 		ast_udc_write(EP0_TX_BUFF_RDY, AST_VHUB_EP0_CTRL);
273*93265845Sneal_liu 	}
274*93265845Sneal_liu }
275*93265845Sneal_liu 
276*93265845Sneal_liu static void ast_udc_ep0_tx(struct usb_endpoint_instance *endpoint)
277*93265845Sneal_liu {
278*93265845Sneal_liu 	struct urb *urb;
279*93265845Sneal_liu 	u32 last;
280*93265845Sneal_liu 
281*93265845Sneal_liu 	if (!endpoint) {
282*93265845Sneal_liu 		usberr("Error input: endpoint\n");
283*93265845Sneal_liu 		return;
284*93265845Sneal_liu 	}
285*93265845Sneal_liu 
286*93265845Sneal_liu 	urb = endpoint->tx_urb;
287*93265845Sneal_liu 	if (!urb) {
288*93265845Sneal_liu 		usberr("Error: tx_urb is empty\n");
289*93265845Sneal_liu 		return;
290*93265845Sneal_liu 	}
291*93265845Sneal_liu 
292*93265845Sneal_liu 	usbdbg("urb->buffer: %p, buffer_length: %d, actual_length: %d, sent:%d",
293*93265845Sneal_liu 	       urb->buffer, urb->buffer_length,
294*93265845Sneal_liu 	       urb->actual_length, endpoint->sent);
295*93265845Sneal_liu 
296*93265845Sneal_liu 	last = MIN(urb->actual_length - endpoint->sent,
297*93265845Sneal_liu 		   endpoint->tx_packetSize);
298*93265845Sneal_liu 
299*93265845Sneal_liu 	if (last) {
300*93265845Sneal_liu 		u8 *cp = urb->buffer + endpoint->sent;
301*93265845Sneal_liu 
302*93265845Sneal_liu 		usbdbg("send address %x", (u32)cp);
303*93265845Sneal_liu 
304*93265845Sneal_liu 		/*
305*93265845Sneal_liu 		 * This ensures that USBD packet fifo is accessed
306*93265845Sneal_liu 		 * - through word aligned pointer or
307*93265845Sneal_liu 		 * - through non word aligned pointer but only
308*93265845Sneal_liu 		 *   with a max length to make the next packet
309*93265845Sneal_liu 		 *   word aligned
310*93265845Sneal_liu 		 */
311*93265845Sneal_liu 
312*93265845Sneal_liu 		usbdbg("ep sent: %d, tx_packetSize: %d, last: %d",
313*93265845Sneal_liu 		       endpoint->sent, endpoint->tx_packetSize, last);
314*93265845Sneal_liu 
315*93265845Sneal_liu 		ast_udc_write(cp, AST_VHUB_EP0_DATA_BUFF);
316*93265845Sneal_liu 
317*93265845Sneal_liu 		// trigger tx
318*93265845Sneal_liu 		ast_udc_write(EP0_TX_LEN(last), AST_VHUB_EP0_CTRL);
319*93265845Sneal_liu 		ast_udc_write(EP0_TX_LEN(last) | EP0_TX_BUFF_RDY, AST_VHUB_EP0_CTRL);
320*93265845Sneal_liu 	}
321*93265845Sneal_liu 
322*93265845Sneal_liu 	endpoint->last = last;
323*93265845Sneal_liu }
324*93265845Sneal_liu 
325*93265845Sneal_liu void ast_udc_ep0_in(struct usb_endpoint_instance *endpoint)
326*93265845Sneal_liu {
327*93265845Sneal_liu 	struct usb_device_request *request = &ep0_urb->device_request;
328*93265845Sneal_liu 
329*93265845Sneal_liu 	usbdbg("ast_udc_ep0_in");
330*93265845Sneal_liu 
331*93265845Sneal_liu 	/* Check direction */
332*93265845Sneal_liu 	if ((request->bmRequestType & USB_REQ_DIRECTION_MASK) ==
333*93265845Sneal_liu 	    USB_REQ_HOST2DEVICE) {
334*93265845Sneal_liu 		/*
335*93265845Sneal_liu 		 * This tx interrupt must be for a control write status
336*93265845Sneal_liu 		 * stage packet.
337*93265845Sneal_liu 		 */
338*93265845Sneal_liu 		usbdbg("ACK on EP0 control write status stage packet");
339*93265845Sneal_liu 	} else {
340*93265845Sneal_liu 		/*
341*93265845Sneal_liu 		 * This tx interrupt must be for a control read data
342*93265845Sneal_liu 		 * stage packet.
343*93265845Sneal_liu 		 */
344*93265845Sneal_liu 		int wLength = le16_to_cpu(request->wLength);
345*93265845Sneal_liu 
346*93265845Sneal_liu 		/*
347*93265845Sneal_liu 		 * Update our count of bytes sent so far in this
348*93265845Sneal_liu 		 * transfer.
349*93265845Sneal_liu 		 */
350*93265845Sneal_liu 		endpoint->sent += endpoint->last;
351*93265845Sneal_liu 
352*93265845Sneal_liu 		/*
353*93265845Sneal_liu 		 * We are finished with this transfer if we have sent
354*93265845Sneal_liu 		 * all of the bytes in our tx urb (urb->actual_length)
355*93265845Sneal_liu 		 * unless we need a zero-length terminating packet.  We
356*93265845Sneal_liu 		 * need a zero-length terminating packet if we returned
357*93265845Sneal_liu 		 * fewer bytes than were requested (wLength) by the host,
358*93265845Sneal_liu 		 * and the number of bytes we returned is an exact
359*93265845Sneal_liu 		 * multiple of the packet size endpoint->tx_packetSize.
360*93265845Sneal_liu 		 */
361*93265845Sneal_liu 		if (endpoint->sent == ep0_urb->actual_length &&
362*93265845Sneal_liu 		    (ep0_urb->actual_length == wLength ||
363*93265845Sneal_liu 		     endpoint->last != endpoint->tx_packetSize)) {
364*93265845Sneal_liu 			/* Done with control read data stage. */
365*93265845Sneal_liu 			usbdbg("control read data stage complete");
366*93265845Sneal_liu 			//trigger for rx
367*93265845Sneal_liu 			endpoint->rcv_urb = ep0_urb;
368*93265845Sneal_liu 			endpoint->sent = 0;
369*93265845Sneal_liu 			ast_udc_ep0_rx(endpoint);
370*93265845Sneal_liu 
371*93265845Sneal_liu 		} else {
372*93265845Sneal_liu 			/*
373*93265845Sneal_liu 			 * We still have another packet of data to send
374*93265845Sneal_liu 			 * in this control read data stage or else we
375*93265845Sneal_liu 			 * need a zero-length terminating packet.
376*93265845Sneal_liu 			 */
377*93265845Sneal_liu 			usbdbg("ACK control read data stage packet");
378*93265845Sneal_liu 
379*93265845Sneal_liu 			ast_udc_ep0_tx(endpoint);
380*93265845Sneal_liu 		}
381*93265845Sneal_liu 	}
382*93265845Sneal_liu }
383*93265845Sneal_liu 
384*93265845Sneal_liu static void ast_udc_setup_handle(struct usb_endpoint_instance *endpoint)
385*93265845Sneal_liu {
386*93265845Sneal_liu 	u32 *setup = (u32 *)(aspeed_udc->udc_base + AST_VHUB_SETUP_DATA0);
387*93265845Sneal_liu 	u8 *datap = (u8 *)&ep0_urb->device_request;
388*93265845Sneal_liu 
389*93265845Sneal_liu 	usbdbg("-> Entering device setup");
390*93265845Sneal_liu 
391*93265845Sneal_liu 	/* 8 bytes setup packet */
392*93265845Sneal_liu 	memcpy(datap, setup, sizeof(setup) * 2);
393*93265845Sneal_liu 
394*93265845Sneal_liu 	/* Try to process setup packet */
395*93265845Sneal_liu 	if (ep0_recv_setup(ep0_urb)) {
396*93265845Sneal_liu 		/* Not a setup packet, stall next EP0 transaction */
397*93265845Sneal_liu 		udc_stall_ep(0);
398*93265845Sneal_liu 		usbinfo("Cannot parse setup packet, wait another setup...\n");
399*93265845Sneal_liu 		return;
400*93265845Sneal_liu 	}
401*93265845Sneal_liu 
402*93265845Sneal_liu 	/* Check direction */
403*93265845Sneal_liu 	if ((ep0_urb->device_request.bmRequestType & USB_REQ_DIRECTION_MASK) ==
404*93265845Sneal_liu 	    USB_REQ_HOST2DEVICE) {
405*93265845Sneal_liu 		switch (ep0_urb->device_request.bRequest) {
406*93265845Sneal_liu 		case USB_REQ_SET_ADDRESS:
407*93265845Sneal_liu 			usbdbg("set addr: %x", ep0_urb->device_request.wValue);
408*93265845Sneal_liu 			ast_udc_write(ep0_urb->device_request.wValue,
409*93265845Sneal_liu 				      AST_VHUB_CONF);
410*93265845Sneal_liu 			ast_udc_write(EP0_TX_BUFF_RDY, AST_VHUB_EP0_CTRL);
411*93265845Sneal_liu 			usbd_device_event_irq(udc_device,
412*93265845Sneal_liu 					      DEVICE_ADDRESS_ASSIGNED, 0);
413*93265845Sneal_liu 			break;
414*93265845Sneal_liu 
415*93265845Sneal_liu 		case USB_REQ_SET_CONFIGURATION:
416*93265845Sneal_liu 			usbdbg("set configuration");
417*93265845Sneal_liu 			ast_udc_write(EP0_TX_BUFF_RDY, AST_VHUB_EP0_CTRL);
418*93265845Sneal_liu 			usbd_device_event_irq(udc_device,
419*93265845Sneal_liu 					      DEVICE_CONFIGURED, 0);
420*93265845Sneal_liu 			break;
421*93265845Sneal_liu 
422*93265845Sneal_liu 		default:
423*93265845Sneal_liu 			if (ep0_urb->device_request.wLength) {
424*93265845Sneal_liu 				endpoint->rcv_urb = ep0_urb;
425*93265845Sneal_liu 				endpoint->sent = 0;
426*93265845Sneal_liu 				ast_udc_ep0_rx(endpoint);
427*93265845Sneal_liu 
428*93265845Sneal_liu 			} else {
429*93265845Sneal_liu 				// send zero-length IN packet
430*93265845Sneal_liu 				ast_udc_write(EP0_TX_BUFF_RDY,
431*93265845Sneal_liu 					      AST_VHUB_EP0_CTRL);
432*93265845Sneal_liu 			}
433*93265845Sneal_liu 			break;
434*93265845Sneal_liu 		}
435*93265845Sneal_liu 
436*93265845Sneal_liu 	} else {
437*93265845Sneal_liu 		usbdbg("control read on EP0");
438*93265845Sneal_liu 		/*
439*93265845Sneal_liu 		 * The ep0_recv_setup function has already placed our response
440*93265845Sneal_liu 		 * packet data in ep0_urb->buffer and the packet length in
441*93265845Sneal_liu 		 * ep0_urb->actual_length.
442*93265845Sneal_liu 		 */
443*93265845Sneal_liu 		endpoint->tx_urb = ep0_urb;
444*93265845Sneal_liu 		endpoint->sent = 0;
445*93265845Sneal_liu 		ast_udc_ep0_tx(endpoint);
446*93265845Sneal_liu 	}
447*93265845Sneal_liu 
448*93265845Sneal_liu 	usbdbg("<- Leaving device setup");
449*93265845Sneal_liu }
450*93265845Sneal_liu 
451*93265845Sneal_liu void udc_irq(void)
452*93265845Sneal_liu {
453*93265845Sneal_liu 	u32 isr = ast_udc_read(AST_VHUB_ISR);
454*93265845Sneal_liu 	u32 ep_isr;
455*93265845Sneal_liu 	int i;
456*93265845Sneal_liu 
457*93265845Sneal_liu 	if (!isr)
458*93265845Sneal_liu 		return;
459*93265845Sneal_liu 
460*93265845Sneal_liu 	if (isr & ISR_BUS_RESET) {
461*93265845Sneal_liu 		usbdbg("ISR_BUS_RESET");
462*93265845Sneal_liu 		ast_udc_write(ISR_BUS_RESET, AST_VHUB_ISR);
463*93265845Sneal_liu 		usbd_device_event_irq(udc_device, DEVICE_RESET, 0);
464*93265845Sneal_liu 	}
465*93265845Sneal_liu 
466*93265845Sneal_liu 	if (isr & ISR_BUS_SUSPEND) {
467*93265845Sneal_liu 		usbdbg("ISR_BUS_SUSPEND");
468*93265845Sneal_liu 		ast_udc_write(ISR_BUS_SUSPEND, AST_VHUB_ISR);
469*93265845Sneal_liu 		usbd_device_event_irq(udc_device, DEVICE_BUS_INACTIVE, 0);
470*93265845Sneal_liu 	}
471*93265845Sneal_liu 
472*93265845Sneal_liu 	if (isr & ISR_SUSPEND_RESUME) {
473*93265845Sneal_liu 		usbdbg("ISR_SUSPEND_RESUME");
474*93265845Sneal_liu 		ast_udc_write(ISR_SUSPEND_RESUME, AST_VHUB_ISR);
475*93265845Sneal_liu 		usbd_device_event_irq(udc_device, DEVICE_BUS_ACTIVITY, 0);
476*93265845Sneal_liu 	}
477*93265845Sneal_liu 
478*93265845Sneal_liu 	if (isr & ISR_HUB_EP0_IN_ACK_STALL) {
479*93265845Sneal_liu //		usbdbg("ISR_HUB_EP0_IN_ACK_STALL");
480*93265845Sneal_liu 		ast_udc_write(ISR_HUB_EP0_IN_ACK_STALL, AST_VHUB_ISR);
481*93265845Sneal_liu 		ast_udc_ep0_in(udc_device->bus->endpoint_array);
482*93265845Sneal_liu 	}
483*93265845Sneal_liu 
484*93265845Sneal_liu 	if (isr & ISR_HUB_EP0_OUT_ACK_STALL) {
485*93265845Sneal_liu //		usbdbg("ISR_HUB_EP0_OUT_ACK_STALL");
486*93265845Sneal_liu 		ast_udc_write(ISR_HUB_EP0_OUT_ACK_STALL, AST_VHUB_ISR);
487*93265845Sneal_liu 		ast_udc_ep0_out(udc_device->bus->endpoint_array);
488*93265845Sneal_liu 	}
489*93265845Sneal_liu 
490*93265845Sneal_liu 	if (isr & ISR_HUB_EP0_OUT_NAK) {
491*93265845Sneal_liu //		usbdbg("ISR_HUB_EP0_OUT_NAK");
492*93265845Sneal_liu 		ast_udc_write(ISR_HUB_EP0_OUT_NAK, AST_VHUB_ISR);
493*93265845Sneal_liu 	}
494*93265845Sneal_liu 
495*93265845Sneal_liu 	if (isr & ISR_HUB_EP0_IN_DATA_NAK) {
496*93265845Sneal_liu //		usbdbg("ISR_HUB_EP0_IN_DATA_ACK");
497*93265845Sneal_liu 		ast_udc_write(ISR_HUB_EP0_IN_DATA_NAK, AST_VHUB_ISR);
498*93265845Sneal_liu 	}
499*93265845Sneal_liu 
500*93265845Sneal_liu 	if (isr & ISR_HUB_EP0_SETUP) {
501*93265845Sneal_liu 		usbdbg("SETUP");
502*93265845Sneal_liu 		ast_udc_write(ISR_HUB_EP0_SETUP, AST_VHUB_ISR);
503*93265845Sneal_liu 		ast_udc_setup_handle(udc_device->bus->endpoint_array);
504*93265845Sneal_liu 	}
505*93265845Sneal_liu 
506*93265845Sneal_liu 	if (isr & ISR_HUB_EP1_IN_DATA_ACK) {
507*93265845Sneal_liu 		// HUB Bitmap control
508*93265845Sneal_liu 		usberr("Error: EP1 IN ACK");
509*93265845Sneal_liu 		ast_udc_write(ISR_HUB_EP1_IN_DATA_ACK, AST_VHUB_ISR);
510*93265845Sneal_liu 		ast_udc_write(0x00, AST_VHUB_EP1_STS_CHG);
511*93265845Sneal_liu 	}
512*93265845Sneal_liu 
513*93265845Sneal_liu 	if (isr & ISR_DEVICE1)
514*93265845Sneal_liu 		usberr("ISR_DEVICE1");
515*93265845Sneal_liu 
516*93265845Sneal_liu 	if (isr & ISR_DEVICE2)
517*93265845Sneal_liu 		usberr("ISR_DEVICE2");
518*93265845Sneal_liu 
519*93265845Sneal_liu 	if (isr & ISR_DEVICE3)
520*93265845Sneal_liu 		usberr("ISR_DEVICE3");
521*93265845Sneal_liu 
522*93265845Sneal_liu 	if (isr & ISR_DEVICE4)
523*93265845Sneal_liu 		usberr("ISR_DEVICE4");
524*93265845Sneal_liu 
525*93265845Sneal_liu 	if (isr & ISR_DEVICE5)
526*93265845Sneal_liu 		usberr("ISR_DEVICE5");
527*93265845Sneal_liu 
528*93265845Sneal_liu 	if (isr & ISR_DEVICE6)
529*93265845Sneal_liu 		usberr("ISR_DEVICE6");
530*93265845Sneal_liu 
531*93265845Sneal_liu 	if (isr & ISR_DEVICE7)
532*93265845Sneal_liu 		usberr("ISR_DEVICE7");
533*93265845Sneal_liu 
534*93265845Sneal_liu 	if (isr & ISR_EP_ACK_STALL) {
535*93265845Sneal_liu //		usbdbg("ISR_EP_ACK_STALL");
536*93265845Sneal_liu 		ep_isr = ast_udc_read(AST_VHUB_EP_ACK_ISR);
537*93265845Sneal_liu 		for (i = 0; i < UDC_MAX_ENDPOINTS; i++) {
538*93265845Sneal_liu 			if (ep_isr & (0x1 << i)) {
539*93265845Sneal_liu 				ast_udc_write(BIT(i), AST_VHUB_EP_ACK_ISR);
540*93265845Sneal_liu 				ast_udc_ep_handle(udc_device->bus->endpoint_array + i + 1);
541*93265845Sneal_liu 			}
542*93265845Sneal_liu 		}
543*93265845Sneal_liu 	}
544*93265845Sneal_liu 
545*93265845Sneal_liu 	if (isr & ISR_EP_NAK) {
546*93265845Sneal_liu 		usbdbg("ISR_EP_NAK");
547*93265845Sneal_liu 		ast_udc_write(ISR_EP_NAK, AST_VHUB_ISR);
548*93265845Sneal_liu 	}
549*93265845Sneal_liu }
550*93265845Sneal_liu 
551*93265845Sneal_liu /*
552*93265845Sneal_liu  * udc_unset_nak
553*93265845Sneal_liu  *
554*93265845Sneal_liu  * Suspend sending of NAK tokens for DATA OUT tokens on a given endpoint.
555*93265845Sneal_liu  * Switch off NAKing on this endpoint to accept more data output from host.
556*93265845Sneal_liu  */
557*93265845Sneal_liu void udc_unset_nak(int ep_num)
558*93265845Sneal_liu {
559*93265845Sneal_liu /* Do nothing */
560*93265845Sneal_liu }
561*93265845Sneal_liu 
562*93265845Sneal_liu /*
563*93265845Sneal_liu  * udc_set_nak
564*93265845Sneal_liu  *
565*93265845Sneal_liu  * Allow upper layers to signal lower layers should not accept more RX data
566*93265845Sneal_liu  */
567*93265845Sneal_liu void udc_set_nak(int ep_num)
568*93265845Sneal_liu {
569*93265845Sneal_liu /* Do nothing */
570*93265845Sneal_liu }
571*93265845Sneal_liu 
572*93265845Sneal_liu /* Associate a physical endpoint with endpoint instance */
573*93265845Sneal_liu void udc_setup_ep(struct usb_device_instance *device, unsigned int id,
574*93265845Sneal_liu 		  struct usb_endpoint_instance *endpoint)
575*93265845Sneal_liu {
576*93265845Sneal_liu 	int ep_num, ep_addr, ep_isout, ep_type, ep_size;
577*93265845Sneal_liu 	u32 ep_conf;
578*93265845Sneal_liu 	u32 ep_reg;
579*93265845Sneal_liu 
580*93265845Sneal_liu 	usbdbg("setting up endpoint id: %d", id);
581*93265845Sneal_liu 
582*93265845Sneal_liu 	if (!endpoint) {
583*93265845Sneal_liu 		usberr("Error: invalid endpoint");
584*93265845Sneal_liu 		return;
585*93265845Sneal_liu 	}
586*93265845Sneal_liu 
587*93265845Sneal_liu 	ep_num = endpoint->endpoint_address & USB_ENDPOINT_NUMBER_MASK;
588*93265845Sneal_liu 	if (ep_num >= UDC_MAX_ENDPOINTS) {
589*93265845Sneal_liu 		usberr("Error: ep num is out-of-range %d", ep_num);
590*93265845Sneal_liu 		return;
591*93265845Sneal_liu 	}
592*93265845Sneal_liu 
593*93265845Sneal_liu 	if (ep_num == 0) {
594*93265845Sneal_liu 		/* Done for ep0 */
595*93265845Sneal_liu 		return;
596*93265845Sneal_liu 	}
597*93265845Sneal_liu 
598*93265845Sneal_liu 	ep_addr = endpoint->endpoint_address;
599*93265845Sneal_liu 	ep_isout = (ep_addr & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT;
600*93265845Sneal_liu 	ep_type = ep_isout ? endpoint->rcv_attributes : endpoint->tx_attributes;
601*93265845Sneal_liu 	ep_size = ep_isout ? endpoint->rcv_packetSize : endpoint->tx_packetSize;
602*93265845Sneal_liu 
603*93265845Sneal_liu 	usbdbg("addr %x, num %d, dir %s, type %s, packet size %d",
604*93265845Sneal_liu 	       ep_addr, ep_num,
605*93265845Sneal_liu 	       ep_isout ? "out" : "in",
606*93265845Sneal_liu 	       ep_type == USB_ENDPOINT_XFER_ISOC ? "isoc" :
607*93265845Sneal_liu 	       ep_type == USB_ENDPOINT_XFER_BULK ? "bulk" :
608*93265845Sneal_liu 	       ep_type == USB_ENDPOINT_XFER_INT ? "int" : "???",
609*93265845Sneal_liu 	       ep_size);
610*93265845Sneal_liu 
611*93265845Sneal_liu 	/* Configure EP */
612*93265845Sneal_liu 	if (ep_size == 1024)
613*93265845Sneal_liu 		ep_conf = 0;
614*93265845Sneal_liu 	else
615*93265845Sneal_liu 		ep_conf = EP_SET_MAX_PKT(ep_size);
616*93265845Sneal_liu 
617*93265845Sneal_liu 	ep_conf |= EP_SET_EP_NUM(ep_num);
618*93265845Sneal_liu 
619*93265845Sneal_liu 	switch (ep_type) {
620*93265845Sneal_liu 	case USB_ENDPOINT_XFER_ISOC:
621*93265845Sneal_liu 		if (ep_isout)
622*93265845Sneal_liu 			ep_conf |= EP_TYPE_ISO_OUT;
623*93265845Sneal_liu 		else
624*93265845Sneal_liu 			ep_conf |= EP_TYPE_ISO_IN;
625*93265845Sneal_liu 		break;
626*93265845Sneal_liu 	case USB_ENDPOINT_XFER_BULK:
627*93265845Sneal_liu 		if (ep_isout)
628*93265845Sneal_liu 			ep_conf |= EP_TYPE_BULK_OUT;
629*93265845Sneal_liu 		else
630*93265845Sneal_liu 			ep_conf |= EP_TYPE_BULK_IN;
631*93265845Sneal_liu 		break;
632*93265845Sneal_liu 	case USB_ENDPOINT_XFER_INT:
633*93265845Sneal_liu 		if (ep_isout)
634*93265845Sneal_liu 			ep_conf |= EP_TYPE_INT_OUT;
635*93265845Sneal_liu 		else
636*93265845Sneal_liu 			ep_conf |= EP_TYPE_INT_IN;
637*93265845Sneal_liu 		break;
638*93265845Sneal_liu 	}
639*93265845Sneal_liu 
640*93265845Sneal_liu 	ep_reg = aspeed_udc->udc_base + AST_EP_BASE + (AST_EP_OFFSET * (ep_num - 1));
641*93265845Sneal_liu 
642*93265845Sneal_liu 	ast_ep_write(ep_reg, EP_SINGLE_DESC_MODE, AST_EP_DMA_CTRL);
643*93265845Sneal_liu 	ast_ep_write(ep_reg, 0, AST_EP_DMA_STS);
644*93265845Sneal_liu 	ast_ep_write(ep_reg, ep_conf | EP_ENABLE, AST_EP_CONFIG);
645*93265845Sneal_liu 
646*93265845Sneal_liu 	//also setup dma
647*93265845Sneal_liu 	if (ep_isout) {
648*93265845Sneal_liu 		ast_ep_write(ep_reg, endpoint->rcv_urb->buffer, AST_EP_DMA_BUFF);
649*93265845Sneal_liu 		ast_ep_write(ep_reg, AST_EP_START_TRANS, AST_EP_DMA_STS);
650*93265845Sneal_liu 
651*93265845Sneal_liu 	} else {
652*93265845Sneal_liu 		ast_ep_write(ep_reg, endpoint->tx_urb->buffer, AST_EP_DMA_BUFF);
653*93265845Sneal_liu 	}
654*93265845Sneal_liu }
655*93265845Sneal_liu 
656*93265845Sneal_liu /* Connect the USB device to the bus */
657*93265845Sneal_liu void udc_connect(void)
658*93265845Sneal_liu {
659*93265845Sneal_liu 	usbdbg("UDC connect");
660*93265845Sneal_liu 	ast_udc_write(ast_udc_read(AST_VHUB_CTRL) | ROOT_UPSTREAM_EN,
661*93265845Sneal_liu 		      AST_VHUB_CTRL);
662*93265845Sneal_liu }
663*93265845Sneal_liu 
664*93265845Sneal_liu /* Disconnect the USB device to the bus */
665*93265845Sneal_liu void udc_disconnect(void)
666*93265845Sneal_liu {
667*93265845Sneal_liu 	usbdbg("UDC disconnect");
668*93265845Sneal_liu 	ast_udc_write(ast_udc_read(AST_VHUB_CTRL) & ~ROOT_UPSTREAM_EN,
669*93265845Sneal_liu 		      AST_VHUB_CTRL);
670*93265845Sneal_liu }
671*93265845Sneal_liu 
672*93265845Sneal_liu void udc_enable(struct usb_device_instance *device)
673*93265845Sneal_liu {
674*93265845Sneal_liu 	usbdbg("enable UDC");
675*93265845Sneal_liu 
676*93265845Sneal_liu 	udc_device = device;
677*93265845Sneal_liu 	if (!ep0_urb)
678*93265845Sneal_liu 		ep0_urb = usbd_alloc_urb(udc_device,
679*93265845Sneal_liu 					 udc_device->bus->endpoint_array);
680*93265845Sneal_liu 	else
681*93265845Sneal_liu 		usbinfo("ep0_urb %p already allocated", ep0_urb);
682*93265845Sneal_liu }
683*93265845Sneal_liu 
684*93265845Sneal_liu void udc_disable(void)
685*93265845Sneal_liu {
686*93265845Sneal_liu 	usbdbg("disable UDC");
687*93265845Sneal_liu 
688*93265845Sneal_liu 	/* Free ep0 URB */
689*93265845Sneal_liu 	if (ep0_urb) {
690*93265845Sneal_liu 		usbd_dealloc_urb(ep0_urb);
691*93265845Sneal_liu 		ep0_urb = NULL;
692*93265845Sneal_liu 	}
693*93265845Sneal_liu 
694*93265845Sneal_liu 	/* Reset device pointer */
695*93265845Sneal_liu 	udc_device = NULL;
696*93265845Sneal_liu }
697*93265845Sneal_liu 
698*93265845Sneal_liu /* Allow udc code to do any additional startup */
699*93265845Sneal_liu void udc_startup_events(struct usb_device_instance *device)
700*93265845Sneal_liu {
701*93265845Sneal_liu 	usbdbg("udc_startup_events");
702*93265845Sneal_liu 
703*93265845Sneal_liu 	/* The DEVICE_INIT event puts the USB device in the state STATE_INIT */
704*93265845Sneal_liu 	usbd_device_event_irq(device, DEVICE_INIT, 0);
705*93265845Sneal_liu 
706*93265845Sneal_liu 	/* The DEVICE_CREATE event puts the USB device in the state
707*93265845Sneal_liu 	 * STATE_ATTACHED
708*93265845Sneal_liu 	 */
709*93265845Sneal_liu 	usbd_device_event_irq(device, DEVICE_CREATE, 0);
710*93265845Sneal_liu 
711*93265845Sneal_liu 	udc_enable(device);
712*93265845Sneal_liu }
713*93265845Sneal_liu 
714*93265845Sneal_liu int udc_init(void)
715*93265845Sneal_liu {
716*93265845Sneal_liu 	usbdbg("udc_init");
717*93265845Sneal_liu 
718*93265845Sneal_liu 	if (!aspeed_udc) {
719*93265845Sneal_liu 		usberr("Error: udc driver is not init yet");
720*93265845Sneal_liu 		return -1;
721*93265845Sneal_liu 	}
722*93265845Sneal_liu 
723*93265845Sneal_liu 	// Disable PHY reset
724*93265845Sneal_liu 	ast_udc_write(ROOT_PHY_CLK_EN | ROOT_PHY_RESET_DIS, AST_VHUB_CTRL);
725*93265845Sneal_liu 
726*93265845Sneal_liu 	ast_udc_write(0, AST_VHUB_DEV_RESET);
727*93265845Sneal_liu 
728*93265845Sneal_liu 	ast_udc_write(~BIT(18), AST_VHUB_ISR);
729*93265845Sneal_liu 	ast_udc_write(~BIT(18), AST_VHUB_IER);
730*93265845Sneal_liu 
731*93265845Sneal_liu 	ast_udc_write(~BIT(UDC_MAX_ENDPOINTS), AST_VHUB_EP_ACK_ISR);
732*93265845Sneal_liu 	ast_udc_write(~BIT(UDC_MAX_ENDPOINTS), AST_VHUB_EP_ACK_IER);
733*93265845Sneal_liu 
734*93265845Sneal_liu 	ast_udc_write(0, AST_VHUB_EP0_CTRL);
735*93265845Sneal_liu 	ast_udc_write(0, AST_VHUB_EP1_CTRL);
736*93265845Sneal_liu 
737*93265845Sneal_liu 	return 0;
738*93265845Sneal_liu }
739*93265845Sneal_liu 
740*93265845Sneal_liu static int aspeed_udc_probe(struct udevice *dev)
741*93265845Sneal_liu {
742*93265845Sneal_liu 	struct aspeed_udc_priv *udc = dev_get_priv(dev);
743*93265845Sneal_liu 	struct reset_ctl udc_reset_ctl;
744*93265845Sneal_liu 	int ret;
745*93265845Sneal_liu 
746*93265845Sneal_liu 	ret = reset_get_by_index(dev, 0, &udc_reset_ctl);
747*93265845Sneal_liu 	if (ret) {
748*93265845Sneal_liu 		printf("%s: Failed to get udc reset signal\n", __func__);
749*93265845Sneal_liu 		return ret;
750*93265845Sneal_liu 	}
751*93265845Sneal_liu 
752*93265845Sneal_liu 	reset_assert(&udc_reset_ctl);
753*93265845Sneal_liu 
754*93265845Sneal_liu 	// Wait 10ms for PLL locking
755*93265845Sneal_liu 	mdelay(10);
756*93265845Sneal_liu 	reset_deassert(&udc_reset_ctl);
757*93265845Sneal_liu 
758*93265845Sneal_liu 	udc->init = 1;
759*93265845Sneal_liu 
760*93265845Sneal_liu 	return 0;
761*93265845Sneal_liu }
762*93265845Sneal_liu 
763*93265845Sneal_liu static int aspeed_udc_ofdata_to_platdata(struct udevice *dev)
764*93265845Sneal_liu {
765*93265845Sneal_liu 	aspeed_udc = dev_get_priv(dev);
766*93265845Sneal_liu 
767*93265845Sneal_liu 	/* Get the controller base address */
768*93265845Sneal_liu 	aspeed_udc->udc_base = (u32)devfdt_get_addr_index(dev, 0);
769*93265845Sneal_liu 
770*93265845Sneal_liu 	return 0;
771*93265845Sneal_liu }
772*93265845Sneal_liu 
773*93265845Sneal_liu static const struct udevice_id aspeed_udc_ids[] = {
774*93265845Sneal_liu 	{ .compatible = "aspeed,ast2600-usb-vhub" },
775*93265845Sneal_liu 	{ }
776*93265845Sneal_liu };
777*93265845Sneal_liu 
778*93265845Sneal_liu U_BOOT_DRIVER(aspeed_udc) = {
779*93265845Sneal_liu 	.name			= "aspeed_udc",
780*93265845Sneal_liu 	.id			= UCLASS_MISC,
781*93265845Sneal_liu 	.of_match		= aspeed_udc_ids,
782*93265845Sneal_liu 	.probe			= aspeed_udc_probe,
783*93265845Sneal_liu 	.ofdata_to_platdata	= aspeed_udc_ofdata_to_platdata,
784*93265845Sneal_liu 	.priv_auto_alloc_size	= sizeof(struct aspeed_udc_priv),
785*93265845Sneal_liu };
786