1*4882a593Smuzhiyun /* SPDX-License-Identifier: GPL-2.0+ */
2*4882a593Smuzhiyun #ifndef __ASPEED_VHUB_H
3*4882a593Smuzhiyun #define __ASPEED_VHUB_H
4*4882a593Smuzhiyun
5*4882a593Smuzhiyun #include <linux/usb.h>
6*4882a593Smuzhiyun #include <linux/usb/ch11.h>
7*4882a593Smuzhiyun
8*4882a593Smuzhiyun /*****************************
9*4882a593Smuzhiyun * *
10*4882a593Smuzhiyun * VHUB register definitions *
11*4882a593Smuzhiyun * *
12*4882a593Smuzhiyun *****************************/
13*4882a593Smuzhiyun
14*4882a593Smuzhiyun #define AST_VHUB_CTRL 0x00 /* Root Function Control & Status Register */
15*4882a593Smuzhiyun #define AST_VHUB_CONF 0x04 /* Root Configuration Setting Register */
16*4882a593Smuzhiyun #define AST_VHUB_IER 0x08 /* Interrupt Ctrl Register */
17*4882a593Smuzhiyun #define AST_VHUB_ISR 0x0C /* Interrupt Status Register */
18*4882a593Smuzhiyun #define AST_VHUB_EP_ACK_IER 0x10 /* Programmable Endpoint Pool ACK Interrupt Enable Register */
19*4882a593Smuzhiyun #define AST_VHUB_EP_NACK_IER 0x14 /* Programmable Endpoint Pool NACK Interrupt Enable Register */
20*4882a593Smuzhiyun #define AST_VHUB_EP_ACK_ISR 0x18 /* Programmable Endpoint Pool ACK Interrupt Status Register */
21*4882a593Smuzhiyun #define AST_VHUB_EP_NACK_ISR 0x1C /* Programmable Endpoint Pool NACK Interrupt Status Register */
22*4882a593Smuzhiyun #define AST_VHUB_SW_RESET 0x20 /* Device Controller Soft Reset Enable Register */
23*4882a593Smuzhiyun #define AST_VHUB_USBSTS 0x24 /* USB Status Register */
24*4882a593Smuzhiyun #define AST_VHUB_EP_TOGGLE 0x28 /* Programmable Endpoint Pool Data Toggle Value Set */
25*4882a593Smuzhiyun #define AST_VHUB_ISO_FAIL_ACC 0x2C /* Isochronous Transaction Fail Accumulator */
26*4882a593Smuzhiyun #define AST_VHUB_EP0_CTRL 0x30 /* Endpoint 0 Contrl/Status Register */
27*4882a593Smuzhiyun #define AST_VHUB_EP0_DATA 0x34 /* Base Address of Endpoint 0 In/OUT Data Buffer Register */
28*4882a593Smuzhiyun #define AST_VHUB_EP1_CTRL 0x38 /* Endpoint 1 Contrl/Status Register */
29*4882a593Smuzhiyun #define AST_VHUB_EP1_STS_CHG 0x3C /* Endpoint 1 Status Change Bitmap Data */
30*4882a593Smuzhiyun #define AST_VHUB_SETUP0 0x80 /* Root Device Setup Data Buffer0 */
31*4882a593Smuzhiyun #define AST_VHUB_SETUP1 0x84 /* Root Device Setup Data Buffer1 */
32*4882a593Smuzhiyun
33*4882a593Smuzhiyun /* Main control reg */
34*4882a593Smuzhiyun #define VHUB_CTRL_PHY_CLK (1 << 31)
35*4882a593Smuzhiyun #define VHUB_CTRL_PHY_LOOP_TEST (1 << 25)
36*4882a593Smuzhiyun #define VHUB_CTRL_DN_PWN (1 << 24)
37*4882a593Smuzhiyun #define VHUB_CTRL_DP_PWN (1 << 23)
38*4882a593Smuzhiyun #define VHUB_CTRL_LONG_DESC (1 << 18)
39*4882a593Smuzhiyun #define VHUB_CTRL_ISO_RSP_CTRL (1 << 17)
40*4882a593Smuzhiyun #define VHUB_CTRL_SPLIT_IN (1 << 16)
41*4882a593Smuzhiyun #define VHUB_CTRL_LOOP_T_RESULT (1 << 15)
42*4882a593Smuzhiyun #define VHUB_CTRL_LOOP_T_STS (1 << 14)
43*4882a593Smuzhiyun #define VHUB_CTRL_PHY_BIST_RESULT (1 << 13)
44*4882a593Smuzhiyun #define VHUB_CTRL_PHY_BIST_CTRL (1 << 12)
45*4882a593Smuzhiyun #define VHUB_CTRL_PHY_RESET_DIS (1 << 11)
46*4882a593Smuzhiyun #define VHUB_CTRL_SET_TEST_MODE(x) ((x) << 8)
47*4882a593Smuzhiyun #define VHUB_CTRL_MANUAL_REMOTE_WAKEUP (1 << 4)
48*4882a593Smuzhiyun #define VHUB_CTRL_AUTO_REMOTE_WAKEUP (1 << 3)
49*4882a593Smuzhiyun #define VHUB_CTRL_CLK_STOP_SUSPEND (1 << 2)
50*4882a593Smuzhiyun #define VHUB_CTRL_FULL_SPEED_ONLY (1 << 1)
51*4882a593Smuzhiyun #define VHUB_CTRL_UPSTREAM_CONNECT (1 << 0)
52*4882a593Smuzhiyun
53*4882a593Smuzhiyun /* IER & ISR */
54*4882a593Smuzhiyun #define VHUB_IRQ_DEV1_BIT 9
55*4882a593Smuzhiyun #define VHUB_IRQ_USB_CMD_DEADLOCK (1 << 18)
56*4882a593Smuzhiyun #define VHUB_IRQ_EP_POOL_NAK (1 << 17)
57*4882a593Smuzhiyun #define VHUB_IRQ_EP_POOL_ACK_STALL (1 << 16)
58*4882a593Smuzhiyun #define VHUB_IRQ_DEVICE1 (1 << (VHUB_IRQ_DEV1_BIT))
59*4882a593Smuzhiyun #define VHUB_IRQ_BUS_RESUME (1 << 8)
60*4882a593Smuzhiyun #define VHUB_IRQ_BUS_SUSPEND (1 << 7)
61*4882a593Smuzhiyun #define VHUB_IRQ_BUS_RESET (1 << 6)
62*4882a593Smuzhiyun #define VHUB_IRQ_HUB_EP1_IN_DATA_ACK (1 << 5)
63*4882a593Smuzhiyun #define VHUB_IRQ_HUB_EP0_IN_DATA_NAK (1 << 4)
64*4882a593Smuzhiyun #define VHUB_IRQ_HUB_EP0_IN_ACK_STALL (1 << 3)
65*4882a593Smuzhiyun #define VHUB_IRQ_HUB_EP0_OUT_NAK (1 << 2)
66*4882a593Smuzhiyun #define VHUB_IRQ_HUB_EP0_OUT_ACK_STALL (1 << 1)
67*4882a593Smuzhiyun #define VHUB_IRQ_HUB_EP0_SETUP (1 << 0)
68*4882a593Smuzhiyun #define VHUB_IRQ_ACK_ALL 0x1ff
69*4882a593Smuzhiyun
70*4882a593Smuzhiyun /* Downstream device IRQ mask. */
71*4882a593Smuzhiyun #define VHUB_DEV_IRQ(n) (VHUB_IRQ_DEVICE1 << (n))
72*4882a593Smuzhiyun
73*4882a593Smuzhiyun /* SW reset reg */
74*4882a593Smuzhiyun #define VHUB_SW_RESET_EP_POOL (1 << 9)
75*4882a593Smuzhiyun #define VHUB_SW_RESET_DMA_CONTROLLER (1 << 8)
76*4882a593Smuzhiyun #define VHUB_SW_RESET_DEVICE5 (1 << 5)
77*4882a593Smuzhiyun #define VHUB_SW_RESET_DEVICE4 (1 << 4)
78*4882a593Smuzhiyun #define VHUB_SW_RESET_DEVICE3 (1 << 3)
79*4882a593Smuzhiyun #define VHUB_SW_RESET_DEVICE2 (1 << 2)
80*4882a593Smuzhiyun #define VHUB_SW_RESET_DEVICE1 (1 << 1)
81*4882a593Smuzhiyun #define VHUB_SW_RESET_ROOT_HUB (1 << 0)
82*4882a593Smuzhiyun
83*4882a593Smuzhiyun /* EP ACK/NACK IRQ masks */
84*4882a593Smuzhiyun #define VHUB_EP_IRQ(n) (1 << (n))
85*4882a593Smuzhiyun
86*4882a593Smuzhiyun /* USB status reg */
87*4882a593Smuzhiyun #define VHUB_USBSTS_HISPEED (1 << 27)
88*4882a593Smuzhiyun
89*4882a593Smuzhiyun /* EP toggle */
90*4882a593Smuzhiyun #define VHUB_EP_TOGGLE_VALUE (1 << 8)
91*4882a593Smuzhiyun #define VHUB_EP_TOGGLE_SET_EPNUM(x) ((x) & 0x1f)
92*4882a593Smuzhiyun
93*4882a593Smuzhiyun /* HUB EP0 control */
94*4882a593Smuzhiyun #define VHUB_EP0_CTRL_STALL (1 << 0)
95*4882a593Smuzhiyun #define VHUB_EP0_TX_BUFF_RDY (1 << 1)
96*4882a593Smuzhiyun #define VHUB_EP0_RX_BUFF_RDY (1 << 2)
97*4882a593Smuzhiyun #define VHUB_EP0_RX_LEN(x) (((x) >> 16) & 0x7f)
98*4882a593Smuzhiyun #define VHUB_EP0_SET_TX_LEN(x) (((x) & 0x7f) << 8)
99*4882a593Smuzhiyun
100*4882a593Smuzhiyun /* HUB EP1 control */
101*4882a593Smuzhiyun #define VHUB_EP1_CTRL_RESET_TOGGLE (1 << 2)
102*4882a593Smuzhiyun #define VHUB_EP1_CTRL_STALL (1 << 1)
103*4882a593Smuzhiyun #define VHUB_EP1_CTRL_ENABLE (1 << 0)
104*4882a593Smuzhiyun
105*4882a593Smuzhiyun /***********************************
106*4882a593Smuzhiyun * *
107*4882a593Smuzhiyun * per-device register definitions *
108*4882a593Smuzhiyun * *
109*4882a593Smuzhiyun ***********************************/
110*4882a593Smuzhiyun #define AST_VHUB_DEV_EN_CTRL 0x00
111*4882a593Smuzhiyun #define AST_VHUB_DEV_ISR 0x04
112*4882a593Smuzhiyun #define AST_VHUB_DEV_EP0_CTRL 0x08
113*4882a593Smuzhiyun #define AST_VHUB_DEV_EP0_DATA 0x0c
114*4882a593Smuzhiyun
115*4882a593Smuzhiyun /* Device enable control */
116*4882a593Smuzhiyun #define VHUB_DEV_EN_SET_ADDR(x) ((x) << 8)
117*4882a593Smuzhiyun #define VHUB_DEV_EN_ADDR_MASK ((0xff) << 8)
118*4882a593Smuzhiyun #define VHUB_DEV_EN_EP0_NAK_IRQEN (1 << 6)
119*4882a593Smuzhiyun #define VHUB_DEV_EN_EP0_IN_ACK_IRQEN (1 << 5)
120*4882a593Smuzhiyun #define VHUB_DEV_EN_EP0_OUT_NAK_IRQEN (1 << 4)
121*4882a593Smuzhiyun #define VHUB_DEV_EN_EP0_OUT_ACK_IRQEN (1 << 3)
122*4882a593Smuzhiyun #define VHUB_DEV_EN_EP0_SETUP_IRQEN (1 << 2)
123*4882a593Smuzhiyun #define VHUB_DEV_EN_SPEED_SEL_HIGH (1 << 1)
124*4882a593Smuzhiyun #define VHUB_DEV_EN_ENABLE_PORT (1 << 0)
125*4882a593Smuzhiyun
126*4882a593Smuzhiyun /* Interrupt status */
127*4882a593Smuzhiyun #define VHUV_DEV_IRQ_EP0_IN_DATA_NACK (1 << 4)
128*4882a593Smuzhiyun #define VHUV_DEV_IRQ_EP0_IN_ACK_STALL (1 << 3)
129*4882a593Smuzhiyun #define VHUV_DEV_IRQ_EP0_OUT_DATA_NACK (1 << 2)
130*4882a593Smuzhiyun #define VHUV_DEV_IRQ_EP0_OUT_ACK_STALL (1 << 1)
131*4882a593Smuzhiyun #define VHUV_DEV_IRQ_EP0_SETUP (1 << 0)
132*4882a593Smuzhiyun
133*4882a593Smuzhiyun /* Control bits.
134*4882a593Smuzhiyun *
135*4882a593Smuzhiyun * Note: The driver relies on the bulk of those bits
136*4882a593Smuzhiyun * matching corresponding vHub EP0 control bits
137*4882a593Smuzhiyun */
138*4882a593Smuzhiyun #define VHUB_DEV_EP0_CTRL_STALL VHUB_EP0_CTRL_STALL
139*4882a593Smuzhiyun #define VHUB_DEV_EP0_TX_BUFF_RDY VHUB_EP0_TX_BUFF_RDY
140*4882a593Smuzhiyun #define VHUB_DEV_EP0_RX_BUFF_RDY VHUB_EP0_RX_BUFF_RDY
141*4882a593Smuzhiyun #define VHUB_DEV_EP0_RX_LEN(x) VHUB_EP0_RX_LEN(x)
142*4882a593Smuzhiyun #define VHUB_DEV_EP0_SET_TX_LEN(x) VHUB_EP0_SET_TX_LEN(x)
143*4882a593Smuzhiyun
144*4882a593Smuzhiyun /*************************************
145*4882a593Smuzhiyun * *
146*4882a593Smuzhiyun * per-endpoint register definitions *
147*4882a593Smuzhiyun * *
148*4882a593Smuzhiyun *************************************/
149*4882a593Smuzhiyun
150*4882a593Smuzhiyun #define AST_VHUB_EP_CONFIG 0x00
151*4882a593Smuzhiyun #define AST_VHUB_EP_DMA_CTLSTAT 0x04
152*4882a593Smuzhiyun #define AST_VHUB_EP_DESC_BASE 0x08
153*4882a593Smuzhiyun #define AST_VHUB_EP_DESC_STATUS 0x0C
154*4882a593Smuzhiyun
155*4882a593Smuzhiyun /* EP config reg */
156*4882a593Smuzhiyun #define VHUB_EP_CFG_SET_MAX_PKT(x) (((x) & 0x3ff) << 16)
157*4882a593Smuzhiyun #define VHUB_EP_CFG_AUTO_DATA_DISABLE (1 << 13)
158*4882a593Smuzhiyun #define VHUB_EP_CFG_STALL_CTRL (1 << 12)
159*4882a593Smuzhiyun #define VHUB_EP_CFG_SET_EP_NUM(x) (((x) & 0xf) << 8)
160*4882a593Smuzhiyun #define VHUB_EP_CFG_SET_TYPE(x) ((x) << 5)
161*4882a593Smuzhiyun #define EP_TYPE_OFF 0
162*4882a593Smuzhiyun #define EP_TYPE_BULK 1
163*4882a593Smuzhiyun #define EP_TYPE_INT 2
164*4882a593Smuzhiyun #define EP_TYPE_ISO 3
165*4882a593Smuzhiyun #define VHUB_EP_CFG_DIR_OUT (1 << 4)
166*4882a593Smuzhiyun #define VHUB_EP_CFG_SET_DEV(x) ((x) << 1)
167*4882a593Smuzhiyun #define VHUB_EP_CFG_ENABLE (1 << 0)
168*4882a593Smuzhiyun
169*4882a593Smuzhiyun /* EP DMA control */
170*4882a593Smuzhiyun #define VHUB_EP_DMA_PROC_STATUS(x) (((x) >> 4) & 0xf)
171*4882a593Smuzhiyun #define EP_DMA_PROC_RX_IDLE 0
172*4882a593Smuzhiyun #define EP_DMA_PROC_TX_IDLE 8
173*4882a593Smuzhiyun #define VHUB_EP_DMA_IN_LONG_MODE (1 << 3)
174*4882a593Smuzhiyun #define VHUB_EP_DMA_OUT_CONTIG_MODE (1 << 3)
175*4882a593Smuzhiyun #define VHUB_EP_DMA_CTRL_RESET (1 << 2)
176*4882a593Smuzhiyun #define VHUB_EP_DMA_SINGLE_STAGE (1 << 1)
177*4882a593Smuzhiyun #define VHUB_EP_DMA_DESC_MODE (1 << 0)
178*4882a593Smuzhiyun
179*4882a593Smuzhiyun /* EP DMA status */
180*4882a593Smuzhiyun #define VHUB_EP_DMA_SET_TX_SIZE(x) ((x) << 16)
181*4882a593Smuzhiyun #define VHUB_EP_DMA_TX_SIZE(x) (((x) >> 16) & 0x7ff)
182*4882a593Smuzhiyun #define VHUB_EP_DMA_RPTR(x) (((x) >> 8) & 0xff)
183*4882a593Smuzhiyun #define VHUB_EP_DMA_SET_RPTR(x) (((x) & 0xff) << 8)
184*4882a593Smuzhiyun #define VHUB_EP_DMA_SET_CPU_WPTR(x) (x)
185*4882a593Smuzhiyun #define VHUB_EP_DMA_SINGLE_KICK (1 << 0) /* WPTR = 1 for single mode */
186*4882a593Smuzhiyun
187*4882a593Smuzhiyun /*******************************
188*4882a593Smuzhiyun * *
189*4882a593Smuzhiyun * DMA descriptors definitions *
190*4882a593Smuzhiyun * *
191*4882a593Smuzhiyun *******************************/
192*4882a593Smuzhiyun
193*4882a593Smuzhiyun /* Desc W1 IN */
194*4882a593Smuzhiyun #define VHUB_DSC1_IN_INTERRUPT (1 << 31)
195*4882a593Smuzhiyun #define VHUB_DSC1_IN_SPID_DATA0 (0 << 14)
196*4882a593Smuzhiyun #define VHUB_DSC1_IN_SPID_DATA2 (1 << 14)
197*4882a593Smuzhiyun #define VHUB_DSC1_IN_SPID_DATA1 (2 << 14)
198*4882a593Smuzhiyun #define VHUB_DSC1_IN_SPID_MDATA (3 << 14)
199*4882a593Smuzhiyun #define VHUB_DSC1_IN_SET_LEN(x) ((x) & 0xfff)
200*4882a593Smuzhiyun #define VHUB_DSC1_IN_LEN(x) ((x) & 0xfff)
201*4882a593Smuzhiyun
202*4882a593Smuzhiyun /****************************************
203*4882a593Smuzhiyun * *
204*4882a593Smuzhiyun * Data structures and misc definitions *
205*4882a593Smuzhiyun * *
206*4882a593Smuzhiyun ****************************************/
207*4882a593Smuzhiyun
208*4882a593Smuzhiyun /*
209*4882a593Smuzhiyun * AST_VHUB_NUM_GEN_EPs and AST_VHUB_NUM_PORTS are kept to avoid breaking
210*4882a593Smuzhiyun * existing AST2400/AST2500 platforms. AST2600 and future vhub revisions
211*4882a593Smuzhiyun * should define number of downstream ports and endpoints in device tree.
212*4882a593Smuzhiyun */
213*4882a593Smuzhiyun #define AST_VHUB_NUM_GEN_EPs 15 /* Generic non-0 EPs */
214*4882a593Smuzhiyun #define AST_VHUB_NUM_PORTS 5 /* vHub ports */
215*4882a593Smuzhiyun #define AST_VHUB_EP0_MAX_PACKET 64 /* EP0's max packet size */
216*4882a593Smuzhiyun #define AST_VHUB_EPn_MAX_PACKET 1024 /* Generic EPs max packet size */
217*4882a593Smuzhiyun #define AST_VHUB_DESCS_COUNT 256 /* Use 256 descriptor mode (valid
218*4882a593Smuzhiyun * values are 256 and 32)
219*4882a593Smuzhiyun */
220*4882a593Smuzhiyun
221*4882a593Smuzhiyun struct ast_vhub;
222*4882a593Smuzhiyun struct ast_vhub_dev;
223*4882a593Smuzhiyun
224*4882a593Smuzhiyun /*
225*4882a593Smuzhiyun * DMA descriptor (generic EPs only, currently only used
226*4882a593Smuzhiyun * for IN endpoints
227*4882a593Smuzhiyun */
228*4882a593Smuzhiyun struct ast_vhub_desc {
229*4882a593Smuzhiyun __le32 w0;
230*4882a593Smuzhiyun __le32 w1;
231*4882a593Smuzhiyun };
232*4882a593Smuzhiyun
233*4882a593Smuzhiyun /* A transfer request, either core-originated or internal */
234*4882a593Smuzhiyun struct ast_vhub_req {
235*4882a593Smuzhiyun struct usb_request req;
236*4882a593Smuzhiyun struct list_head queue;
237*4882a593Smuzhiyun
238*4882a593Smuzhiyun /* Actual count written to descriptors (desc mode only) */
239*4882a593Smuzhiyun unsigned int act_count;
240*4882a593Smuzhiyun
241*4882a593Smuzhiyun /*
242*4882a593Smuzhiyun * Desc number of the final packet or -1. For non-desc
243*4882a593Smuzhiyun * mode (or ep0), any >= 0 value means "last packet"
244*4882a593Smuzhiyun */
245*4882a593Smuzhiyun int last_desc;
246*4882a593Smuzhiyun
247*4882a593Smuzhiyun /* Request active (pending DMAs) */
248*4882a593Smuzhiyun bool active : 1;
249*4882a593Smuzhiyun
250*4882a593Smuzhiyun /* Internal request (don't call back core) */
251*4882a593Smuzhiyun bool internal : 1;
252*4882a593Smuzhiyun };
253*4882a593Smuzhiyun #define to_ast_req(__ureq) container_of(__ureq, struct ast_vhub_req, req)
254*4882a593Smuzhiyun
255*4882a593Smuzhiyun /* Current state of an EP0 */
256*4882a593Smuzhiyun enum ep0_state {
257*4882a593Smuzhiyun ep0_state_token,
258*4882a593Smuzhiyun ep0_state_data,
259*4882a593Smuzhiyun ep0_state_status,
260*4882a593Smuzhiyun ep0_state_stall,
261*4882a593Smuzhiyun };
262*4882a593Smuzhiyun
263*4882a593Smuzhiyun /*
264*4882a593Smuzhiyun * An endpoint, either generic, ep0, actual gadget EP
265*4882a593Smuzhiyun * or internal use vhub EP0. vhub EP1 doesn't have an
266*4882a593Smuzhiyun * associated structure as it's mostly HW managed.
267*4882a593Smuzhiyun */
268*4882a593Smuzhiyun struct ast_vhub_ep {
269*4882a593Smuzhiyun struct usb_ep ep;
270*4882a593Smuzhiyun
271*4882a593Smuzhiyun /* Request queue */
272*4882a593Smuzhiyun struct list_head queue;
273*4882a593Smuzhiyun
274*4882a593Smuzhiyun /* EP index in the device, 0 means this is an EP0 */
275*4882a593Smuzhiyun unsigned int d_idx;
276*4882a593Smuzhiyun
277*4882a593Smuzhiyun /* Dev pointer or NULL for vHub EP0 */
278*4882a593Smuzhiyun struct ast_vhub_dev *dev;
279*4882a593Smuzhiyun
280*4882a593Smuzhiyun /* vHub itself */
281*4882a593Smuzhiyun struct ast_vhub *vhub;
282*4882a593Smuzhiyun
283*4882a593Smuzhiyun /*
284*4882a593Smuzhiyun * DMA buffer for EP0, fallback DMA buffer for misaligned
285*4882a593Smuzhiyun * OUT transfers for generic EPs
286*4882a593Smuzhiyun */
287*4882a593Smuzhiyun void *buf;
288*4882a593Smuzhiyun dma_addr_t buf_dma;
289*4882a593Smuzhiyun
290*4882a593Smuzhiyun /* The rest depends on the EP type */
291*4882a593Smuzhiyun union {
292*4882a593Smuzhiyun /* EP0 (either device or vhub) */
293*4882a593Smuzhiyun struct {
294*4882a593Smuzhiyun /*
295*4882a593Smuzhiyun * EP0 registers are "similar" for
296*4882a593Smuzhiyun * vHub and devices but located in
297*4882a593Smuzhiyun * different places.
298*4882a593Smuzhiyun */
299*4882a593Smuzhiyun void __iomem *ctlstat;
300*4882a593Smuzhiyun void __iomem *setup;
301*4882a593Smuzhiyun
302*4882a593Smuzhiyun /* Current state & direction */
303*4882a593Smuzhiyun enum ep0_state state;
304*4882a593Smuzhiyun bool dir_in;
305*4882a593Smuzhiyun
306*4882a593Smuzhiyun /* Internal use request */
307*4882a593Smuzhiyun struct ast_vhub_req req;
308*4882a593Smuzhiyun } ep0;
309*4882a593Smuzhiyun
310*4882a593Smuzhiyun /* Generic endpoint (aka EPn) */
311*4882a593Smuzhiyun struct {
312*4882a593Smuzhiyun /* Registers */
313*4882a593Smuzhiyun void __iomem *regs;
314*4882a593Smuzhiyun
315*4882a593Smuzhiyun /* Index in global pool (zero-based) */
316*4882a593Smuzhiyun unsigned int g_idx;
317*4882a593Smuzhiyun
318*4882a593Smuzhiyun /* DMA Descriptors */
319*4882a593Smuzhiyun struct ast_vhub_desc *descs;
320*4882a593Smuzhiyun dma_addr_t descs_dma;
321*4882a593Smuzhiyun unsigned int d_next;
322*4882a593Smuzhiyun unsigned int d_last;
323*4882a593Smuzhiyun unsigned int dma_conf;
324*4882a593Smuzhiyun
325*4882a593Smuzhiyun /* Max chunk size for IN EPs */
326*4882a593Smuzhiyun unsigned int chunk_max;
327*4882a593Smuzhiyun
328*4882a593Smuzhiyun /* State flags */
329*4882a593Smuzhiyun bool is_in : 1;
330*4882a593Smuzhiyun bool is_iso : 1;
331*4882a593Smuzhiyun bool stalled : 1;
332*4882a593Smuzhiyun bool wedged : 1;
333*4882a593Smuzhiyun bool enabled : 1;
334*4882a593Smuzhiyun bool desc_mode : 1;
335*4882a593Smuzhiyun } epn;
336*4882a593Smuzhiyun };
337*4882a593Smuzhiyun };
338*4882a593Smuzhiyun #define to_ast_ep(__uep) container_of(__uep, struct ast_vhub_ep, ep)
339*4882a593Smuzhiyun
340*4882a593Smuzhiyun /* A device attached to a vHub port */
341*4882a593Smuzhiyun struct ast_vhub_dev {
342*4882a593Smuzhiyun struct ast_vhub *vhub;
343*4882a593Smuzhiyun void __iomem *regs;
344*4882a593Smuzhiyun
345*4882a593Smuzhiyun /* Device index (zero-based) and name string */
346*4882a593Smuzhiyun unsigned int index;
347*4882a593Smuzhiyun const char *name;
348*4882a593Smuzhiyun
349*4882a593Smuzhiyun /* sysfs enclosure for the gadget gunk */
350*4882a593Smuzhiyun struct device *port_dev;
351*4882a593Smuzhiyun
352*4882a593Smuzhiyun /* Link to gadget core */
353*4882a593Smuzhiyun struct usb_gadget gadget;
354*4882a593Smuzhiyun struct usb_gadget_driver *driver;
355*4882a593Smuzhiyun bool registered : 1;
356*4882a593Smuzhiyun bool wakeup_en : 1;
357*4882a593Smuzhiyun bool enabled : 1;
358*4882a593Smuzhiyun
359*4882a593Smuzhiyun /* Endpoint structures */
360*4882a593Smuzhiyun struct ast_vhub_ep ep0;
361*4882a593Smuzhiyun struct ast_vhub_ep **epns;
362*4882a593Smuzhiyun u32 max_epns;
363*4882a593Smuzhiyun
364*4882a593Smuzhiyun };
365*4882a593Smuzhiyun #define to_ast_dev(__g) container_of(__g, struct ast_vhub_dev, gadget)
366*4882a593Smuzhiyun
367*4882a593Smuzhiyun /* Per vhub port stateinfo structure */
368*4882a593Smuzhiyun struct ast_vhub_port {
369*4882a593Smuzhiyun /* Port status & status change registers */
370*4882a593Smuzhiyun u16 status;
371*4882a593Smuzhiyun u16 change;
372*4882a593Smuzhiyun
373*4882a593Smuzhiyun /* Associated device slot */
374*4882a593Smuzhiyun struct ast_vhub_dev dev;
375*4882a593Smuzhiyun };
376*4882a593Smuzhiyun
377*4882a593Smuzhiyun struct ast_vhub_full_cdesc {
378*4882a593Smuzhiyun struct usb_config_descriptor cfg;
379*4882a593Smuzhiyun struct usb_interface_descriptor intf;
380*4882a593Smuzhiyun struct usb_endpoint_descriptor ep;
381*4882a593Smuzhiyun } __packed;
382*4882a593Smuzhiyun
383*4882a593Smuzhiyun /* Global vhub structure */
384*4882a593Smuzhiyun struct ast_vhub {
385*4882a593Smuzhiyun struct platform_device *pdev;
386*4882a593Smuzhiyun void __iomem *regs;
387*4882a593Smuzhiyun int irq;
388*4882a593Smuzhiyun spinlock_t lock;
389*4882a593Smuzhiyun struct work_struct wake_work;
390*4882a593Smuzhiyun struct clk *clk;
391*4882a593Smuzhiyun
392*4882a593Smuzhiyun /* EP0 DMA buffers allocated in one chunk */
393*4882a593Smuzhiyun void *ep0_bufs;
394*4882a593Smuzhiyun dma_addr_t ep0_bufs_dma;
395*4882a593Smuzhiyun
396*4882a593Smuzhiyun /* EP0 of the vhub itself */
397*4882a593Smuzhiyun struct ast_vhub_ep ep0;
398*4882a593Smuzhiyun
399*4882a593Smuzhiyun /* State of vhub ep1 */
400*4882a593Smuzhiyun bool ep1_stalled : 1;
401*4882a593Smuzhiyun
402*4882a593Smuzhiyun /* Per-port info */
403*4882a593Smuzhiyun struct ast_vhub_port *ports;
404*4882a593Smuzhiyun u32 max_ports;
405*4882a593Smuzhiyun u32 port_irq_mask;
406*4882a593Smuzhiyun
407*4882a593Smuzhiyun /* Generic EP data structures */
408*4882a593Smuzhiyun struct ast_vhub_ep *epns;
409*4882a593Smuzhiyun u32 max_epns;
410*4882a593Smuzhiyun
411*4882a593Smuzhiyun /* Upstream bus is suspended ? */
412*4882a593Smuzhiyun bool suspended : 1;
413*4882a593Smuzhiyun
414*4882a593Smuzhiyun /* Hub itself can signal remote wakeup */
415*4882a593Smuzhiyun bool wakeup_en : 1;
416*4882a593Smuzhiyun
417*4882a593Smuzhiyun /* Force full speed only */
418*4882a593Smuzhiyun bool force_usb1 : 1;
419*4882a593Smuzhiyun
420*4882a593Smuzhiyun /* Upstream bus speed captured at bus reset */
421*4882a593Smuzhiyun unsigned int speed;
422*4882a593Smuzhiyun
423*4882a593Smuzhiyun /* Standard USB Descriptors of the vhub. */
424*4882a593Smuzhiyun struct usb_device_descriptor vhub_dev_desc;
425*4882a593Smuzhiyun struct ast_vhub_full_cdesc vhub_conf_desc;
426*4882a593Smuzhiyun struct usb_hub_descriptor vhub_hub_desc;
427*4882a593Smuzhiyun struct list_head vhub_str_desc;
428*4882a593Smuzhiyun };
429*4882a593Smuzhiyun
430*4882a593Smuzhiyun /* Standard request handlers result codes */
431*4882a593Smuzhiyun enum std_req_rc {
432*4882a593Smuzhiyun std_req_stall = -1, /* Stall requested */
433*4882a593Smuzhiyun std_req_complete = 0, /* Request completed with no data */
434*4882a593Smuzhiyun std_req_data = 1, /* Request completed with data */
435*4882a593Smuzhiyun std_req_driver = 2, /* Pass to driver pls */
436*4882a593Smuzhiyun };
437*4882a593Smuzhiyun
438*4882a593Smuzhiyun #ifdef CONFIG_USB_GADGET_VERBOSE
439*4882a593Smuzhiyun #define UDCVDBG(u, fmt...) dev_dbg(&(u)->pdev->dev, fmt)
440*4882a593Smuzhiyun
441*4882a593Smuzhiyun #define EPVDBG(ep, fmt, ...) do { \
442*4882a593Smuzhiyun dev_dbg(&(ep)->vhub->pdev->dev, \
443*4882a593Smuzhiyun "%s:EP%d " fmt, \
444*4882a593Smuzhiyun (ep)->dev ? (ep)->dev->name : "hub", \
445*4882a593Smuzhiyun (ep)->d_idx, ##__VA_ARGS__); \
446*4882a593Smuzhiyun } while(0)
447*4882a593Smuzhiyun
448*4882a593Smuzhiyun #define DVDBG(d, fmt, ...) do { \
449*4882a593Smuzhiyun dev_dbg(&(d)->vhub->pdev->dev, \
450*4882a593Smuzhiyun "%s " fmt, (d)->name, \
451*4882a593Smuzhiyun ##__VA_ARGS__); \
452*4882a593Smuzhiyun } while(0)
453*4882a593Smuzhiyun
454*4882a593Smuzhiyun #else
455*4882a593Smuzhiyun #define UDCVDBG(u, fmt...) do { } while(0)
456*4882a593Smuzhiyun #define EPVDBG(ep, fmt, ...) do { } while(0)
457*4882a593Smuzhiyun #define DVDBG(d, fmt, ...) do { } while(0)
458*4882a593Smuzhiyun #endif
459*4882a593Smuzhiyun
460*4882a593Smuzhiyun #ifdef CONFIG_USB_GADGET_DEBUG
461*4882a593Smuzhiyun #define UDCDBG(u, fmt...) dev_dbg(&(u)->pdev->dev, fmt)
462*4882a593Smuzhiyun
463*4882a593Smuzhiyun #define EPDBG(ep, fmt, ...) do { \
464*4882a593Smuzhiyun dev_dbg(&(ep)->vhub->pdev->dev, \
465*4882a593Smuzhiyun "%s:EP%d " fmt, \
466*4882a593Smuzhiyun (ep)->dev ? (ep)->dev->name : "hub", \
467*4882a593Smuzhiyun (ep)->d_idx, ##__VA_ARGS__); \
468*4882a593Smuzhiyun } while(0)
469*4882a593Smuzhiyun
470*4882a593Smuzhiyun #define DDBG(d, fmt, ...) do { \
471*4882a593Smuzhiyun dev_dbg(&(d)->vhub->pdev->dev, \
472*4882a593Smuzhiyun "%s " fmt, (d)->name, \
473*4882a593Smuzhiyun ##__VA_ARGS__); \
474*4882a593Smuzhiyun } while(0)
475*4882a593Smuzhiyun #else
476*4882a593Smuzhiyun #define UDCDBG(u, fmt...) do { } while(0)
477*4882a593Smuzhiyun #define EPDBG(ep, fmt, ...) do { } while(0)
478*4882a593Smuzhiyun #define DDBG(d, fmt, ...) do { } while(0)
479*4882a593Smuzhiyun #endif
480*4882a593Smuzhiyun
vhub_dma_workaround(void * addr)481*4882a593Smuzhiyun static inline void vhub_dma_workaround(void *addr)
482*4882a593Smuzhiyun {
483*4882a593Smuzhiyun /*
484*4882a593Smuzhiyun * This works around a confirmed HW issue with the Aspeed chip.
485*4882a593Smuzhiyun *
486*4882a593Smuzhiyun * The core uses a different bus to memory than the AHB going to
487*4882a593Smuzhiyun * the USB device controller. Due to the latter having a higher
488*4882a593Smuzhiyun * priority than the core for arbitration on that bus, it's
489*4882a593Smuzhiyun * possible for an MMIO to the device, followed by a DMA by the
490*4882a593Smuzhiyun * device from memory to all be performed and services before
491*4882a593Smuzhiyun * a previous store to memory gets completed.
492*4882a593Smuzhiyun *
493*4882a593Smuzhiyun * This the following scenario can happen:
494*4882a593Smuzhiyun *
495*4882a593Smuzhiyun * - Driver writes to a DMA descriptor (Mbus)
496*4882a593Smuzhiyun * - Driver writes to the MMIO register to start the DMA (AHB)
497*4882a593Smuzhiyun * - The gadget sees the second write and sends a read of the
498*4882a593Smuzhiyun * descriptor to the memory controller (Mbus)
499*4882a593Smuzhiyun * - The gadget hits memory before the descriptor write
500*4882a593Smuzhiyun * causing it to read an obsolete value.
501*4882a593Smuzhiyun *
502*4882a593Smuzhiyun * Thankfully the problem is limited to the USB gadget device, other
503*4882a593Smuzhiyun * masters in the SoC all have a lower priority than the core, thus
504*4882a593Smuzhiyun * ensuring that the store by the core arrives first.
505*4882a593Smuzhiyun *
506*4882a593Smuzhiyun * The workaround consists of using a dummy read of the memory before
507*4882a593Smuzhiyun * doing the MMIO writes. This will ensure that the previous writes
508*4882a593Smuzhiyun * have been "pushed out".
509*4882a593Smuzhiyun */
510*4882a593Smuzhiyun mb();
511*4882a593Smuzhiyun (void)__raw_readl((void __iomem *)addr);
512*4882a593Smuzhiyun }
513*4882a593Smuzhiyun
514*4882a593Smuzhiyun /* core.c */
515*4882a593Smuzhiyun void ast_vhub_done(struct ast_vhub_ep *ep, struct ast_vhub_req *req,
516*4882a593Smuzhiyun int status);
517*4882a593Smuzhiyun void ast_vhub_nuke(struct ast_vhub_ep *ep, int status);
518*4882a593Smuzhiyun struct usb_request *ast_vhub_alloc_request(struct usb_ep *u_ep,
519*4882a593Smuzhiyun gfp_t gfp_flags);
520*4882a593Smuzhiyun void ast_vhub_free_request(struct usb_ep *u_ep, struct usb_request *u_req);
521*4882a593Smuzhiyun void ast_vhub_init_hw(struct ast_vhub *vhub);
522*4882a593Smuzhiyun
523*4882a593Smuzhiyun /* ep0.c */
524*4882a593Smuzhiyun void ast_vhub_ep0_handle_ack(struct ast_vhub_ep *ep, bool in_ack);
525*4882a593Smuzhiyun void ast_vhub_ep0_handle_setup(struct ast_vhub_ep *ep);
526*4882a593Smuzhiyun void ast_vhub_reset_ep0(struct ast_vhub_dev *dev);
527*4882a593Smuzhiyun void ast_vhub_init_ep0(struct ast_vhub *vhub, struct ast_vhub_ep *ep,
528*4882a593Smuzhiyun struct ast_vhub_dev *dev);
529*4882a593Smuzhiyun int ast_vhub_reply(struct ast_vhub_ep *ep, char *ptr, int len);
530*4882a593Smuzhiyun int __ast_vhub_simple_reply(struct ast_vhub_ep *ep, int len, ...);
531*4882a593Smuzhiyun #define ast_vhub_simple_reply(udc, ...) \
532*4882a593Smuzhiyun __ast_vhub_simple_reply((udc), \
533*4882a593Smuzhiyun sizeof((u8[]) { __VA_ARGS__ })/sizeof(u8), \
534*4882a593Smuzhiyun __VA_ARGS__)
535*4882a593Smuzhiyun
536*4882a593Smuzhiyun /* hub.c */
537*4882a593Smuzhiyun int ast_vhub_init_hub(struct ast_vhub *vhub);
538*4882a593Smuzhiyun enum std_req_rc ast_vhub_std_hub_request(struct ast_vhub_ep *ep,
539*4882a593Smuzhiyun struct usb_ctrlrequest *crq);
540*4882a593Smuzhiyun enum std_req_rc ast_vhub_class_hub_request(struct ast_vhub_ep *ep,
541*4882a593Smuzhiyun struct usb_ctrlrequest *crq);
542*4882a593Smuzhiyun void ast_vhub_device_connect(struct ast_vhub *vhub, unsigned int port,
543*4882a593Smuzhiyun bool on);
544*4882a593Smuzhiyun void ast_vhub_hub_suspend(struct ast_vhub *vhub);
545*4882a593Smuzhiyun void ast_vhub_hub_resume(struct ast_vhub *vhub);
546*4882a593Smuzhiyun void ast_vhub_hub_reset(struct ast_vhub *vhub);
547*4882a593Smuzhiyun void ast_vhub_hub_wake_all(struct ast_vhub *vhub);
548*4882a593Smuzhiyun
549*4882a593Smuzhiyun /* dev.c */
550*4882a593Smuzhiyun int ast_vhub_init_dev(struct ast_vhub *vhub, unsigned int idx);
551*4882a593Smuzhiyun void ast_vhub_del_dev(struct ast_vhub_dev *d);
552*4882a593Smuzhiyun void ast_vhub_dev_irq(struct ast_vhub_dev *d);
553*4882a593Smuzhiyun int ast_vhub_std_dev_request(struct ast_vhub_ep *ep,
554*4882a593Smuzhiyun struct usb_ctrlrequest *crq);
555*4882a593Smuzhiyun
556*4882a593Smuzhiyun /* epn.c */
557*4882a593Smuzhiyun void ast_vhub_epn_ack_irq(struct ast_vhub_ep *ep);
558*4882a593Smuzhiyun void ast_vhub_update_epn_stall(struct ast_vhub_ep *ep);
559*4882a593Smuzhiyun struct ast_vhub_ep *ast_vhub_alloc_epn(struct ast_vhub_dev *d, u8 addr);
560*4882a593Smuzhiyun void ast_vhub_dev_suspend(struct ast_vhub_dev *d);
561*4882a593Smuzhiyun void ast_vhub_dev_resume(struct ast_vhub_dev *d);
562*4882a593Smuzhiyun void ast_vhub_dev_reset(struct ast_vhub_dev *d);
563*4882a593Smuzhiyun
564*4882a593Smuzhiyun #endif /* __ASPEED_VHUB_H */
565