Linux Audio

Check our new training course

Embedded Linux Audio

Check our new training course
with Creative Commons CC-BY-SA
lecture materials

Bootlin logo

Elixir Cross Referencer

Loading...
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
/* SPDX-License-Identifier: GPL-2.0+ */
#ifndef __ASPEED_VHUB_H
#define __ASPEED_VHUB_H

/*****************************
 *                           *
 * VHUB register definitions *
 *                           *
 *****************************/

#define	AST_VHUB_CTRL		0x00	/* Root Function Control & Status Register */
#define	AST_VHUB_CONF		0x04	/* Root Configuration Setting Register */
#define	AST_VHUB_IER		0x08	/* Interrupt Ctrl Register */
#define	AST_VHUB_ISR		0x0C	/* Interrupt Status Register */
#define	AST_VHUB_EP_ACK_IER	0x10	/* Programmable Endpoint Pool ACK Interrupt Enable Register */
#define	AST_VHUB_EP_NACK_IER	0x14	/* Programmable Endpoint Pool NACK Interrupt Enable Register  */
#define AST_VHUB_EP_ACK_ISR	0x18	/* Programmable Endpoint Pool ACK Interrupt Status Register  */
#define AST_VHUB_EP_NACK_ISR	0x1C	/* Programmable Endpoint Pool NACK Interrupt Status Register  */
#define AST_VHUB_SW_RESET	0x20	/* Device Controller Soft Reset Enable Register */
#define AST_VHUB_USBSTS		0x24	/* USB Status Register */
#define AST_VHUB_EP_TOGGLE	0x28	/* Programmable Endpoint Pool Data Toggle Value Set */
#define AST_VHUB_ISO_FAIL_ACC	0x2C	/* Isochronous Transaction Fail Accumulator */
#define AST_VHUB_EP0_CTRL	0x30	/* Endpoint 0 Contrl/Status Register */
#define AST_VHUB_EP0_DATA	0x34	/* Base Address of Endpoint 0 In/OUT Data Buffer Register */
#define AST_VHUB_EP1_CTRL	0x38	/* Endpoint 1 Contrl/Status Register */
#define AST_VHUB_EP1_STS_CHG	0x3C	/* Endpoint 1 Status Change Bitmap Data */
#define AST_VHUB_SETUP0		0x80	/* Root Device Setup Data Buffer0 */
#define AST_VHUB_SETUP1		0x84	/* Root Device Setup Data Buffer1 */

/* Main control reg */
#define VHUB_CTRL_PHY_CLK			(1 << 31)
#define VHUB_CTRL_PHY_LOOP_TEST			(1 << 25)
#define VHUB_CTRL_DN_PWN			(1 << 24)
#define VHUB_CTRL_DP_PWN			(1 << 23)
#define VHUB_CTRL_LONG_DESC			(1 << 18)
#define VHUB_CTRL_ISO_RSP_CTRL			(1 << 17)
#define VHUB_CTRL_SPLIT_IN			(1 << 16)
#define VHUB_CTRL_LOOP_T_RESULT			(1 << 15)
#define VHUB_CTRL_LOOP_T_STS			(1 << 14)
#define VHUB_CTRL_PHY_BIST_RESULT		(1 << 13)
#define VHUB_CTRL_PHY_BIST_CTRL			(1 << 12)
#define VHUB_CTRL_PHY_RESET_DIS			(1 << 11)
#define VHUB_CTRL_SET_TEST_MODE(x)		((x) << 8)
#define VHUB_CTRL_MANUAL_REMOTE_WAKEUP		(1 << 4)
#define VHUB_CTRL_AUTO_REMOTE_WAKEUP		(1 << 3)
#define VHUB_CTRL_CLK_STOP_SUSPEND		(1 << 2)
#define VHUB_CTRL_FULL_SPEED_ONLY		(1 << 1)
#define VHUB_CTRL_UPSTREAM_CONNECT		(1 << 0)

/* IER & ISR */
#define VHUB_IRQ_USB_CMD_DEADLOCK		(1 << 18)
#define VHUB_IRQ_EP_POOL_NAK			(1 << 17)
#define VHUB_IRQ_EP_POOL_ACK_STALL		(1 << 16)
#define VHUB_IRQ_DEVICE5			(1 << 13)
#define VHUB_IRQ_DEVICE4			(1 << 12)
#define VHUB_IRQ_DEVICE3			(1 << 11)
#define VHUB_IRQ_DEVICE2			(1 << 10)
#define VHUB_IRQ_DEVICE1			(1 << 9)
#define VHUB_IRQ_BUS_RESUME			(1 << 8)
#define VHUB_IRQ_BUS_SUSPEND 			(1 << 7)
#define VHUB_IRQ_BUS_RESET 			(1 << 6)
#define VHUB_IRQ_HUB_EP1_IN_DATA_ACK		(1 << 5)
#define VHUB_IRQ_HUB_EP0_IN_DATA_NAK		(1 << 4)
#define VHUB_IRQ_HUB_EP0_IN_ACK_STALL		(1 << 3)
#define VHUB_IRQ_HUB_EP0_OUT_NAK		(1 << 2)
#define VHUB_IRQ_HUB_EP0_OUT_ACK_STALL		(1 << 1)
#define VHUB_IRQ_HUB_EP0_SETUP			(1 << 0)
#define VHUB_IRQ_ACK_ALL			0x1ff

/* SW reset reg */
#define VHUB_SW_RESET_EP_POOL			(1 << 9)
#define VHUB_SW_RESET_DMA_CONTROLLER		(1 << 8)
#define VHUB_SW_RESET_DEVICE5			(1 << 5)
#define VHUB_SW_RESET_DEVICE4			(1 << 4)
#define VHUB_SW_RESET_DEVICE3			(1 << 3)
#define VHUB_SW_RESET_DEVICE2			(1 << 2)
#define VHUB_SW_RESET_DEVICE1			(1 << 1)
#define VHUB_SW_RESET_ROOT_HUB			(1 << 0)
#define VHUB_SW_RESET_ALL			(VHUB_SW_RESET_EP_POOL | \
						 VHUB_SW_RESET_DMA_CONTROLLER | \
						 VHUB_SW_RESET_DEVICE5 | \
						 VHUB_SW_RESET_DEVICE4 | \
						 VHUB_SW_RESET_DEVICE3 | \
						 VHUB_SW_RESET_DEVICE2 | \
						 VHUB_SW_RESET_DEVICE1 | \
						 VHUB_SW_RESET_ROOT_HUB)
/* EP ACK/NACK IRQ masks */
#define VHUB_EP_IRQ(n)				(1 << (n))
#define VHUB_EP_IRQ_ALL				0x7fff	/* 15 EPs */

/* USB status reg */
#define VHUB_USBSTS_HISPEED			(1 << 27)

/* EP toggle */
#define VHUB_EP_TOGGLE_VALUE			(1 << 8)
#define VHUB_EP_TOGGLE_SET_EPNUM(x)		((x) & 0x1f)

/* HUB EP0 control */
#define VHUB_EP0_CTRL_STALL			(1 << 0)
#define VHUB_EP0_TX_BUFF_RDY			(1 << 1)
#define VHUB_EP0_RX_BUFF_RDY			(1 << 2)
#define VHUB_EP0_RX_LEN(x)			(((x) >> 16) & 0x7f)
#define VHUB_EP0_SET_TX_LEN(x)			(((x) & 0x7f) << 8)

/* HUB EP1 control */
#define VHUB_EP1_CTRL_RESET_TOGGLE		(1 << 2)
#define VHUB_EP1_CTRL_STALL			(1 << 1)
#define VHUB_EP1_CTRL_ENABLE			(1 << 0)

/***********************************
 *                                 *
 * per-device register definitions *
 *                                 *
 ***********************************/
#define AST_VHUB_DEV_EN_CTRL		0x00
#define AST_VHUB_DEV_ISR		0x04
#define AST_VHUB_DEV_EP0_CTRL		0x08
#define AST_VHUB_DEV_EP0_DATA		0x0c

/* Device enable control */
#define VHUB_DEV_EN_SET_ADDR(x)			((x) << 8)
#define VHUB_DEV_EN_ADDR_MASK			((0xff) << 8)
#define VHUB_DEV_EN_EP0_NAK_IRQEN		(1 << 6)
#define VHUB_DEV_EN_EP0_IN_ACK_IRQEN		(1 << 5)
#define VHUB_DEV_EN_EP0_OUT_NAK_IRQEN		(1 << 4)
#define VHUB_DEV_EN_EP0_OUT_ACK_IRQEN		(1 << 3)
#define VHUB_DEV_EN_EP0_SETUP_IRQEN		(1 << 2)
#define VHUB_DEV_EN_SPEED_SEL_HIGH		(1 << 1)
#define VHUB_DEV_EN_ENABLE_PORT			(1 << 0)

/* Interrupt status */
#define VHUV_DEV_IRQ_EP0_IN_DATA_NACK		(1 << 4)
#define VHUV_DEV_IRQ_EP0_IN_ACK_STALL		(1 << 3)
#define VHUV_DEV_IRQ_EP0_OUT_DATA_NACK		(1 << 2)
#define VHUV_DEV_IRQ_EP0_OUT_ACK_STALL		(1 << 1)
#define VHUV_DEV_IRQ_EP0_SETUP			(1 << 0)

/* Control bits.
 *
 * Note: The driver relies on the bulk of those bits
 *       matching corresponding vHub EP0 control bits
 */
#define VHUB_DEV_EP0_CTRL_STALL			VHUB_EP0_CTRL_STALL
#define VHUB_DEV_EP0_TX_BUFF_RDY		VHUB_EP0_TX_BUFF_RDY
#define VHUB_DEV_EP0_RX_BUFF_RDY		VHUB_EP0_RX_BUFF_RDY
#define VHUB_DEV_EP0_RX_LEN(x)			VHUB_EP0_RX_LEN(x)
#define VHUB_DEV_EP0_SET_TX_LEN(x)		VHUB_EP0_SET_TX_LEN(x)

/*************************************
 *                                   *
 * per-endpoint register definitions *
 *                                   *
 *************************************/

#define AST_VHUB_EP_CONFIG		0x00
#define AST_VHUB_EP_DMA_CTLSTAT		0x04
#define AST_VHUB_EP_DESC_BASE		0x08
#define AST_VHUB_EP_DESC_STATUS		0x0C

/* EP config reg */
#define VHUB_EP_CFG_SET_MAX_PKT(x)	(((x) & 0x3ff) << 16)
#define VHUB_EP_CFG_AUTO_DATA_DISABLE	(1 << 13)
#define VHUB_EP_CFG_STALL_CTRL		(1 << 12)
#define VHUB_EP_CFG_SET_EP_NUM(x)	(((x) & 0xf) << 8)
#define VHUB_EP_CFG_SET_TYPE(x)		((x) << 5)
#define   EP_TYPE_OFF			0
#define   EP_TYPE_BULK			1
#define   EP_TYPE_INT			2
#define   EP_TYPE_ISO			3
#define VHUB_EP_CFG_DIR_OUT		(1 << 4)
#define VHUB_EP_CFG_SET_DEV(x)		((x) << 1)
#define VHUB_EP_CFG_ENABLE		(1 << 0)

/* EP DMA control */
#define VHUB_EP_DMA_PROC_STATUS(x)	(((x) >> 4) & 0xf)
#define   EP_DMA_PROC_RX_IDLE		0
#define   EP_DMA_PROC_TX_IDLE		8
#define VHUB_EP_DMA_IN_LONG_MODE	(1 << 3)
#define VHUB_EP_DMA_OUT_CONTIG_MODE	(1 << 3)
#define VHUB_EP_DMA_CTRL_RESET		(1 << 2)
#define VHUB_EP_DMA_SINGLE_STAGE	(1 << 1)
#define VHUB_EP_DMA_DESC_MODE		(1 << 0)

/* EP DMA status */
#define VHUB_EP_DMA_SET_TX_SIZE(x)	((x) << 16)
#define VHUB_EP_DMA_TX_SIZE(x)		(((x) >> 16) & 0x7ff)
#define VHUB_EP_DMA_RPTR(x)		(((x) >> 8) & 0xff)
#define VHUB_EP_DMA_SET_RPTR(x)		(((x) & 0xff) << 8)
#define VHUB_EP_DMA_SET_CPU_WPTR(x)	(x)
#define VHUB_EP_DMA_SINGLE_KICK		(1 << 0) /* WPTR = 1 for single mode */

/*******************************
 *                             *
 * DMA descriptors definitions *
 *                             *
 *******************************/

/* Desc W1 IN */
#define VHUB_DSC1_IN_INTERRUPT		(1 << 31)
#define VHUB_DSC1_IN_SPID_DATA0		(0 << 14)
#define VHUB_DSC1_IN_SPID_DATA2		(1 << 14)
#define VHUB_DSC1_IN_SPID_DATA1		(2 << 14)
#define VHUB_DSC1_IN_SPID_MDATA		(3 << 14)
#define VHUB_DSC1_IN_SET_LEN(x)		((x) & 0xfff)
#define VHUB_DSC1_IN_LEN(x)		((x) & 0xfff)

/****************************************
 *                                      *
 * Data structures and misc definitions *
 *                                      *
 ****************************************/

#define AST_VHUB_NUM_GEN_EPs	15	/* Generic non-0 EPs */
#define AST_VHUB_NUM_PORTS	5	/* vHub ports */
#define AST_VHUB_EP0_MAX_PACKET	64	/* EP0's max packet size */
#define AST_VHUB_EPn_MAX_PACKET	1024	/* Generic EPs max packet size */
#define AST_VHUB_DESCS_COUNT	256	/* Use 256 descriptor mode (valid
					 * values are 256 and 32)
					 */

struct ast_vhub;
struct ast_vhub_dev;

/*
 * DMA descriptor (generic EPs only, currently only used
 * for IN endpoints
 */
struct ast_vhub_desc {
	__le32	w0;
	__le32	w1;
};

/* A transfer request, either core-originated or internal */
struct ast_vhub_req {
	struct usb_request	req;
	struct list_head	queue;

	/* Actual count written to descriptors (desc mode only) */
	unsigned int		act_count;

	/*
	 * Desc number of the final packet or -1. For non-desc
	 * mode (or ep0), any >= 0 value means "last packet"
	 */
	int			last_desc;

	/* Request active (pending DMAs) */
	bool			active  : 1;

	/* Internal request (don't call back core) */
	bool			internal : 1;
};
#define to_ast_req(__ureq) container_of(__ureq, struct ast_vhub_req, req)

/* Current state of an EP0 */
enum ep0_state {
	ep0_state_token,
	ep0_state_data,
	ep0_state_status,
	ep0_state_stall,
};

/*
 * An endpoint, either generic, ep0, actual gadget EP
 * or internal use vhub EP0. vhub EP1 doesn't have an
 * associated structure as it's mostly HW managed.
 */
struct ast_vhub_ep {
	struct usb_ep		ep;

	/* Request queue */
	struct list_head	queue;

	/* EP index in the device, 0 means this is an EP0 */
	unsigned int		d_idx;

	/* Dev pointer or NULL for vHub EP0 */
	struct ast_vhub_dev	*dev;

	/* vHub itself */
	struct ast_vhub		*vhub;

	/*
	 * DMA buffer for EP0, fallback DMA buffer for misaligned
	 * OUT transfers for generic EPs
	 */
	void			*buf;
	dma_addr_t		buf_dma;

	/* The rest depends on the EP type */
	union {
		/* EP0 (either device or vhub) */
		struct {
			/*
			 * EP0 registers are "similar" for
			 * vHub and devices but located in
			 * different places.
			 */
			void __iomem		*ctlstat;
			void __iomem		*setup;

			/* Current state & direction */
			enum ep0_state		state;
			bool			dir_in;

			/* Internal use request */
			struct ast_vhub_req	req;
		} ep0;

		/* Generic endpoint (aka EPn) */
		struct {
			/* Registers */
			void __iomem   		*regs;

			/* Index in global pool (0..14) */
			unsigned int		g_idx;

			/* DMA Descriptors */
			struct ast_vhub_desc	*descs;
			dma_addr_t		descs_dma;
			unsigned int		d_next;
			unsigned int		d_last;
			unsigned int		dma_conf;

			/* Max chunk size for IN EPs */
			unsigned int		chunk_max;

			/* State flags */
			bool			is_in :  1;
			bool			is_iso : 1;
			bool			stalled : 1;
			bool			wedged : 1;
			bool			enabled : 1;
			bool			desc_mode : 1;
		} epn;
	};
};
#define to_ast_ep(__uep) container_of(__uep, struct ast_vhub_ep, ep)

/* A device attached to a vHub port */
struct ast_vhub_dev {
	struct ast_vhub			*vhub;
	void __iomem			*regs;

	/* Device index (0...4) and name string */
	unsigned int			index;
	const char			*name;

	/* sysfs enclosure for the gadget gunk */
	struct device			*port_dev;

	/* Link to gadget core */
	struct usb_gadget		gadget;
	struct usb_gadget_driver	*driver;
	bool				registered : 1;
	bool				wakeup_en : 1;
	bool				enabled : 1;

	/* Endpoint structures */
	struct ast_vhub_ep		ep0;
	struct ast_vhub_ep		*epns[AST_VHUB_NUM_GEN_EPs];

};
#define to_ast_dev(__g) container_of(__g, struct ast_vhub_dev, gadget)

/* Per vhub port stateinfo structure */
struct ast_vhub_port {
	/* Port status & status change registers */
	u16			status;
	u16			change;

	/* Associated device slot */
	struct ast_vhub_dev	dev;
};

/* Global vhub structure */
struct ast_vhub {
	struct platform_device		*pdev;
	void __iomem			*regs;
	int				irq;
	spinlock_t			lock;
	struct work_struct		wake_work;
	struct clk			*clk;

	/* EP0 DMA buffers allocated in one chunk */
	void				*ep0_bufs;
	dma_addr_t			ep0_bufs_dma;

	/* EP0 of the vhub itself */
	struct ast_vhub_ep		ep0;

	/* State of vhub ep1 */
	bool				ep1_stalled : 1;

	/* Per-port info */
	struct ast_vhub_port		ports[AST_VHUB_NUM_PORTS];

	/* Generic EP data structures */
	struct ast_vhub_ep		epns[AST_VHUB_NUM_GEN_EPs];

	/* Upstream bus is suspended ? */
	bool				suspended : 1;

	/* Hub itself can signal remote wakeup */
	bool				wakeup_en : 1;

	/* Force full speed only */
	bool				force_usb1 : 1;

	/* Upstream bus speed captured at bus reset */
	unsigned int			speed;
};

/* Standard request handlers result codes */
enum std_req_rc {
	std_req_stall = -1,	/* Stall requested */
	std_req_complete = 0,	/* Request completed with no data */
	std_req_data = 1,	/* Request completed with data */
	std_req_driver = 2,	/* Pass to driver pls */
};

#ifdef CONFIG_USB_GADGET_VERBOSE
#define UDCVDBG(u, fmt...)	dev_dbg(&(u)->pdev->dev, fmt)

#define EPVDBG(ep, fmt, ...)	do {			\
	dev_dbg(&(ep)->vhub->pdev->dev,			\
		"%s:EP%d " fmt,				\
		(ep)->dev ? (ep)->dev->name : "hub",	\
		(ep)->d_idx, ##__VA_ARGS__);		\
	} while(0)

#define DVDBG(d, fmt, ...)	do {			\
	dev_dbg(&(d)->vhub->pdev->dev,			\
		"%s " fmt, (d)->name,			\
		##__VA_ARGS__);				\
	} while(0)

#else
#define UDCVDBG(u, fmt...)	do { } while(0)
#define EPVDBG(ep, fmt, ...)	do { } while(0)
#define DVDBG(d, fmt, ...)	do { } while(0)
#endif

#ifdef CONFIG_USB_GADGET_DEBUG
#define UDCDBG(u, fmt...)	dev_dbg(&(u)->pdev->dev, fmt)

#define EPDBG(ep, fmt, ...)	do {			\
	dev_dbg(&(ep)->vhub->pdev->dev,			\
		"%s:EP%d " fmt,				\
		(ep)->dev ? (ep)->dev->name : "hub",	\
		(ep)->d_idx, ##__VA_ARGS__);		\
	} while(0)

#define DDBG(d, fmt, ...)	do {			\
	dev_dbg(&(d)->vhub->pdev->dev,			\
		"%s " fmt, (d)->name,			\
		##__VA_ARGS__);				\
	} while(0)
#else
#define UDCDBG(u, fmt...)	do { } while(0)
#define EPDBG(ep, fmt, ...)	do { } while(0)
#define DDBG(d, fmt, ...)	do { } while(0)
#endif

static inline void vhub_dma_workaround(void *addr)
{
	/*
	 * This works around a confirmed HW issue with the Aspeed chip.
	 *
	 * The core uses a different bus to memory than the AHB going to
	 * the USB device controller. Due to the latter having a higher
	 * priority than the core for arbitration on that bus, it's
	 * possible for an MMIO to the device, followed by a DMA by the
	 * device from memory to all be performed and services before
	 * a previous store to memory gets completed.
	 *
	 * This the following scenario can happen:
	 *
	 *    - Driver writes to a DMA descriptor (Mbus)
	 *    - Driver writes to the MMIO register to start the DMA (AHB)
	 *    - The gadget sees the second write and sends a read of the
	 *      descriptor to the memory controller (Mbus)
	 *    - The gadget hits memory before the descriptor write
	 *      causing it to read an obsolete value.
	 *
	 * Thankfully the problem is limited to the USB gadget device, other
	 * masters in the SoC all have a lower priority than the core, thus
	 * ensuring that the store by the core arrives first.
	 *
	 * The workaround consists of using a dummy read of the memory before
	 * doing the MMIO writes. This will ensure that the previous writes
	 * have been "pushed out".
	 */
	mb();
	(void)__raw_readl((void __iomem *)addr);
}

/* core.c */
void ast_vhub_done(struct ast_vhub_ep *ep, struct ast_vhub_req *req,
		   int status);
void ast_vhub_nuke(struct ast_vhub_ep *ep, int status);
struct usb_request *ast_vhub_alloc_request(struct usb_ep *u_ep,
					   gfp_t gfp_flags);
void ast_vhub_free_request(struct usb_ep *u_ep, struct usb_request *u_req);
void ast_vhub_init_hw(struct ast_vhub *vhub);

/* ep0.c */
void ast_vhub_ep0_handle_ack(struct ast_vhub_ep *ep, bool in_ack);
void ast_vhub_ep0_handle_setup(struct ast_vhub_ep *ep);
void ast_vhub_reset_ep0(struct ast_vhub_dev *dev);
void ast_vhub_init_ep0(struct ast_vhub *vhub, struct ast_vhub_ep *ep,
		       struct ast_vhub_dev *dev);
int ast_vhub_reply(struct ast_vhub_ep *ep, char *ptr, int len);
int __ast_vhub_simple_reply(struct ast_vhub_ep *ep, int len, ...);
#define ast_vhub_simple_reply(udc, ...)					       \
	__ast_vhub_simple_reply((udc),					       \
			       sizeof((u8[]) { __VA_ARGS__ })/sizeof(u8),      \
			       __VA_ARGS__)

/* hub.c */
void ast_vhub_init_hub(struct ast_vhub *vhub);
enum std_req_rc ast_vhub_std_hub_request(struct ast_vhub_ep *ep,
					 struct usb_ctrlrequest *crq);
enum std_req_rc ast_vhub_class_hub_request(struct ast_vhub_ep *ep,
					   struct usb_ctrlrequest *crq);
void ast_vhub_device_connect(struct ast_vhub *vhub, unsigned int port,
			     bool on);
void ast_vhub_hub_suspend(struct ast_vhub *vhub);
void ast_vhub_hub_resume(struct ast_vhub *vhub);
void ast_vhub_hub_reset(struct ast_vhub *vhub);
void ast_vhub_hub_wake_all(struct ast_vhub *vhub);

/* dev.c */
int ast_vhub_init_dev(struct ast_vhub *vhub, unsigned int idx);
void ast_vhub_del_dev(struct ast_vhub_dev *d);
void ast_vhub_dev_irq(struct ast_vhub_dev *d);
int ast_vhub_std_dev_request(struct ast_vhub_ep *ep,
			     struct usb_ctrlrequest *crq);

/* epn.c */
void ast_vhub_epn_ack_irq(struct ast_vhub_ep *ep);
void ast_vhub_update_epn_stall(struct ast_vhub_ep *ep);
struct ast_vhub_ep *ast_vhub_alloc_epn(struct ast_vhub_dev *d, u8 addr);
void ast_vhub_dev_suspend(struct ast_vhub_dev *d);
void ast_vhub_dev_resume(struct ast_vhub_dev *d);
void ast_vhub_dev_reset(struct ast_vhub_dev *d);

#endif /* __ASPEED_VHUB_H */