Commit be7ed2533d4acb9bc67989c4ffddb5814202ba02
1 parent
b959655f18
Exists in
master
and in
55 other branches
usb: mv_udc: Make use of struct ehci_ctrl
The usb_lowlevel_init() call already fills and passes back struct ehci_ctrl , which readily contains correctly determined address of the port register block address computed from values from controller configuration registers. Leverage this and make use of this value as this makes the code mode universal, but also gets us rid of the CONFIG_USB_REG_BASE configuration option. Moreover, this patch cleans up the usb_gadget_register_driver() call a little by correcting the error handling. Note the usb_lowlevel_init() and mvudc_probe() are now called in reversed order, but this has no impact on the code. Signed-off-by: Marek Vasut <marex@denx.de> Cc: Fabio Estevam <fabio.estevam@freescale.com> Cc: Lei Wen <leiwen@marvell.com> Cc: Otavio Salvador <otavio@ossystems.com.br> Cc: Stefano Babic <sbabic@denx.de>
Showing 2 changed files with 26 additions and 21 deletions Inline Diff
drivers/usb/gadget/mv_udc.c
1 | /* | 1 | /* |
2 | * Copyright 2011, Marvell Semiconductor Inc. | 2 | * Copyright 2011, Marvell Semiconductor Inc. |
3 | * Lei Wen <leiwen@marvell.com> | 3 | * Lei Wen <leiwen@marvell.com> |
4 | * | 4 | * |
5 | * SPDX-License-Identifier: GPL-2.0+ | 5 | * SPDX-License-Identifier: GPL-2.0+ |
6 | * | 6 | * |
7 | * Back ported to the 8xx platform (from the 8260 platform) by | 7 | * Back ported to the 8xx platform (from the 8260 platform) by |
8 | * Murray.Jensen@cmst.csiro.au, 27-Jan-01. | 8 | * Murray.Jensen@cmst.csiro.au, 27-Jan-01. |
9 | */ | 9 | */ |
10 | 10 | ||
11 | #include <common.h> | 11 | #include <common.h> |
12 | #include <command.h> | 12 | #include <command.h> |
13 | #include <config.h> | 13 | #include <config.h> |
14 | #include <net.h> | 14 | #include <net.h> |
15 | #include <malloc.h> | 15 | #include <malloc.h> |
16 | #include <asm/io.h> | 16 | #include <asm/io.h> |
17 | #include <linux/types.h> | 17 | #include <linux/types.h> |
18 | #include <usb/mv_udc.h> | 18 | #include <usb/mv_udc.h> |
19 | 19 | ||
20 | #if CONFIG_USB_MAX_CONTROLLER_COUNT > 1 | 20 | #if CONFIG_USB_MAX_CONTROLLER_COUNT > 1 |
21 | #error This driver only supports one single controller. | 21 | #error This driver only supports one single controller. |
22 | #endif | 22 | #endif |
23 | 23 | ||
24 | #ifndef DEBUG | 24 | #ifndef DEBUG |
25 | #define DBG(x...) do {} while (0) | 25 | #define DBG(x...) do {} while (0) |
26 | #else | 26 | #else |
27 | #define DBG(x...) printf(x) | 27 | #define DBG(x...) printf(x) |
28 | static const char *reqname(unsigned r) | 28 | static const char *reqname(unsigned r) |
29 | { | 29 | { |
30 | switch (r) { | 30 | switch (r) { |
31 | case USB_REQ_GET_STATUS: return "GET_STATUS"; | 31 | case USB_REQ_GET_STATUS: return "GET_STATUS"; |
32 | case USB_REQ_CLEAR_FEATURE: return "CLEAR_FEATURE"; | 32 | case USB_REQ_CLEAR_FEATURE: return "CLEAR_FEATURE"; |
33 | case USB_REQ_SET_FEATURE: return "SET_FEATURE"; | 33 | case USB_REQ_SET_FEATURE: return "SET_FEATURE"; |
34 | case USB_REQ_SET_ADDRESS: return "SET_ADDRESS"; | 34 | case USB_REQ_SET_ADDRESS: return "SET_ADDRESS"; |
35 | case USB_REQ_GET_DESCRIPTOR: return "GET_DESCRIPTOR"; | 35 | case USB_REQ_GET_DESCRIPTOR: return "GET_DESCRIPTOR"; |
36 | case USB_REQ_SET_DESCRIPTOR: return "SET_DESCRIPTOR"; | 36 | case USB_REQ_SET_DESCRIPTOR: return "SET_DESCRIPTOR"; |
37 | case USB_REQ_GET_CONFIGURATION: return "GET_CONFIGURATION"; | 37 | case USB_REQ_GET_CONFIGURATION: return "GET_CONFIGURATION"; |
38 | case USB_REQ_SET_CONFIGURATION: return "SET_CONFIGURATION"; | 38 | case USB_REQ_SET_CONFIGURATION: return "SET_CONFIGURATION"; |
39 | case USB_REQ_GET_INTERFACE: return "GET_INTERFACE"; | 39 | case USB_REQ_GET_INTERFACE: return "GET_INTERFACE"; |
40 | case USB_REQ_SET_INTERFACE: return "SET_INTERFACE"; | 40 | case USB_REQ_SET_INTERFACE: return "SET_INTERFACE"; |
41 | default: return "*UNKNOWN*"; | 41 | default: return "*UNKNOWN*"; |
42 | } | 42 | } |
43 | } | 43 | } |
44 | #endif | 44 | #endif |
45 | 45 | ||
46 | #define PAGE_SIZE 4096 | 46 | #define PAGE_SIZE 4096 |
47 | #define QH_MAXNUM 32 | 47 | #define QH_MAXNUM 32 |
48 | static struct usb_endpoint_descriptor ep0_out_desc = { | 48 | static struct usb_endpoint_descriptor ep0_out_desc = { |
49 | .bLength = sizeof(struct usb_endpoint_descriptor), | 49 | .bLength = sizeof(struct usb_endpoint_descriptor), |
50 | .bDescriptorType = USB_DT_ENDPOINT, | 50 | .bDescriptorType = USB_DT_ENDPOINT, |
51 | .bEndpointAddress = 0, | 51 | .bEndpointAddress = 0, |
52 | .bmAttributes = USB_ENDPOINT_XFER_CONTROL, | 52 | .bmAttributes = USB_ENDPOINT_XFER_CONTROL, |
53 | }; | 53 | }; |
54 | 54 | ||
55 | static struct usb_endpoint_descriptor ep0_in_desc = { | 55 | static struct usb_endpoint_descriptor ep0_in_desc = { |
56 | .bLength = sizeof(struct usb_endpoint_descriptor), | 56 | .bLength = sizeof(struct usb_endpoint_descriptor), |
57 | .bDescriptorType = USB_DT_ENDPOINT, | 57 | .bDescriptorType = USB_DT_ENDPOINT, |
58 | .bEndpointAddress = USB_DIR_IN, | 58 | .bEndpointAddress = USB_DIR_IN, |
59 | .bmAttributes = USB_ENDPOINT_XFER_CONTROL, | 59 | .bmAttributes = USB_ENDPOINT_XFER_CONTROL, |
60 | }; | 60 | }; |
61 | 61 | ||
62 | struct ept_queue_head *epts; | 62 | struct ept_queue_head *epts; |
63 | struct ept_queue_item *items[2 * NUM_ENDPOINTS]; | 63 | struct ept_queue_item *items[2 * NUM_ENDPOINTS]; |
64 | static int mv_pullup(struct usb_gadget *gadget, int is_on); | 64 | static int mv_pullup(struct usb_gadget *gadget, int is_on); |
65 | static int mv_ep_enable(struct usb_ep *ep, | 65 | static int mv_ep_enable(struct usb_ep *ep, |
66 | const struct usb_endpoint_descriptor *desc); | 66 | const struct usb_endpoint_descriptor *desc); |
67 | static int mv_ep_disable(struct usb_ep *ep); | 67 | static int mv_ep_disable(struct usb_ep *ep); |
68 | static int mv_ep_queue(struct usb_ep *ep, | 68 | static int mv_ep_queue(struct usb_ep *ep, |
69 | struct usb_request *req, gfp_t gfp_flags); | 69 | struct usb_request *req, gfp_t gfp_flags); |
70 | static struct usb_request * | 70 | static struct usb_request * |
71 | mv_ep_alloc_request(struct usb_ep *ep, unsigned int gfp_flags); | 71 | mv_ep_alloc_request(struct usb_ep *ep, unsigned int gfp_flags); |
72 | static void mv_ep_free_request(struct usb_ep *ep, struct usb_request *_req); | 72 | static void mv_ep_free_request(struct usb_ep *ep, struct usb_request *_req); |
73 | 73 | ||
74 | static struct usb_gadget_ops mv_udc_ops = { | 74 | static struct usb_gadget_ops mv_udc_ops = { |
75 | .pullup = mv_pullup, | 75 | .pullup = mv_pullup, |
76 | }; | 76 | }; |
77 | 77 | ||
78 | static struct usb_ep_ops mv_ep_ops = { | 78 | static struct usb_ep_ops mv_ep_ops = { |
79 | .enable = mv_ep_enable, | 79 | .enable = mv_ep_enable, |
80 | .disable = mv_ep_disable, | 80 | .disable = mv_ep_disable, |
81 | .queue = mv_ep_queue, | 81 | .queue = mv_ep_queue, |
82 | .alloc_request = mv_ep_alloc_request, | 82 | .alloc_request = mv_ep_alloc_request, |
83 | .free_request = mv_ep_free_request, | 83 | .free_request = mv_ep_free_request, |
84 | }; | 84 | }; |
85 | 85 | ||
86 | /* Init values for USB endpoints. */ | 86 | /* Init values for USB endpoints. */ |
87 | static const struct usb_ep mv_ep_init[2] = { | 87 | static const struct usb_ep mv_ep_init[2] = { |
88 | [0] = { /* EP 0 */ | 88 | [0] = { /* EP 0 */ |
89 | .maxpacket = 64, | 89 | .maxpacket = 64, |
90 | .name = "ep0", | 90 | .name = "ep0", |
91 | .ops = &mv_ep_ops, | 91 | .ops = &mv_ep_ops, |
92 | }, | 92 | }, |
93 | [1] = { /* EP 1..n */ | 93 | [1] = { /* EP 1..n */ |
94 | .maxpacket = 512, | 94 | .maxpacket = 512, |
95 | .name = "ep-", | 95 | .name = "ep-", |
96 | .ops = &mv_ep_ops, | 96 | .ops = &mv_ep_ops, |
97 | }, | 97 | }, |
98 | }; | 98 | }; |
99 | 99 | ||
100 | static struct mv_drv controller = { | 100 | static struct mv_drv controller = { |
101 | .gadget = { | 101 | .gadget = { |
102 | .name = "mv_udc", | 102 | .name = "mv_udc", |
103 | }, | 103 | }, |
104 | }; | 104 | }; |
105 | 105 | ||
106 | static struct usb_request * | 106 | static struct usb_request * |
107 | mv_ep_alloc_request(struct usb_ep *ep, unsigned int gfp_flags) | 107 | mv_ep_alloc_request(struct usb_ep *ep, unsigned int gfp_flags) |
108 | { | 108 | { |
109 | struct mv_ep *mv_ep = container_of(ep, struct mv_ep, ep); | 109 | struct mv_ep *mv_ep = container_of(ep, struct mv_ep, ep); |
110 | return &mv_ep->req; | 110 | return &mv_ep->req; |
111 | } | 111 | } |
112 | 112 | ||
113 | static void mv_ep_free_request(struct usb_ep *ep, struct usb_request *_req) | 113 | static void mv_ep_free_request(struct usb_ep *ep, struct usb_request *_req) |
114 | { | 114 | { |
115 | return; | 115 | return; |
116 | } | 116 | } |
117 | 117 | ||
118 | static void ep_enable(int num, int in) | 118 | static void ep_enable(int num, int in) |
119 | { | 119 | { |
120 | struct ept_queue_head *head; | 120 | struct ept_queue_head *head; |
121 | struct mv_udc *udc = controller.udc; | 121 | struct mv_udc *udc = (struct mv_udc *)controller.ctrl->hcor; |
122 | unsigned n; | 122 | unsigned n; |
123 | head = epts + 2*num + in; | 123 | head = epts + 2*num + in; |
124 | 124 | ||
125 | n = readl(&udc->epctrl[num]); | 125 | n = readl(&udc->epctrl[num]); |
126 | if (in) | 126 | if (in) |
127 | n |= (CTRL_TXE | CTRL_TXR | CTRL_TXT_BULK); | 127 | n |= (CTRL_TXE | CTRL_TXR | CTRL_TXT_BULK); |
128 | else | 128 | else |
129 | n |= (CTRL_RXE | CTRL_RXR | CTRL_RXT_BULK); | 129 | n |= (CTRL_RXE | CTRL_RXR | CTRL_RXT_BULK); |
130 | 130 | ||
131 | if (num != 0) | 131 | if (num != 0) |
132 | head->config = CONFIG_MAX_PKT(EP_MAX_PACKET_SIZE) | CONFIG_ZLT; | 132 | head->config = CONFIG_MAX_PKT(EP_MAX_PACKET_SIZE) | CONFIG_ZLT; |
133 | writel(n, &udc->epctrl[num]); | 133 | writel(n, &udc->epctrl[num]); |
134 | } | 134 | } |
135 | 135 | ||
136 | static int mv_ep_enable(struct usb_ep *ep, | 136 | static int mv_ep_enable(struct usb_ep *ep, |
137 | const struct usb_endpoint_descriptor *desc) | 137 | const struct usb_endpoint_descriptor *desc) |
138 | { | 138 | { |
139 | struct mv_ep *mv_ep = container_of(ep, struct mv_ep, ep); | 139 | struct mv_ep *mv_ep = container_of(ep, struct mv_ep, ep); |
140 | int num, in; | 140 | int num, in; |
141 | num = desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; | 141 | num = desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; |
142 | in = (desc->bEndpointAddress & USB_DIR_IN) != 0; | 142 | in = (desc->bEndpointAddress & USB_DIR_IN) != 0; |
143 | ep_enable(num, in); | 143 | ep_enable(num, in); |
144 | mv_ep->desc = desc; | 144 | mv_ep->desc = desc; |
145 | return 0; | 145 | return 0; |
146 | } | 146 | } |
147 | 147 | ||
148 | static int mv_ep_disable(struct usb_ep *ep) | 148 | static int mv_ep_disable(struct usb_ep *ep) |
149 | { | 149 | { |
150 | return 0; | 150 | return 0; |
151 | } | 151 | } |
152 | 152 | ||
153 | static int mv_ep_queue(struct usb_ep *ep, | 153 | static int mv_ep_queue(struct usb_ep *ep, |
154 | struct usb_request *req, gfp_t gfp_flags) | 154 | struct usb_request *req, gfp_t gfp_flags) |
155 | { | 155 | { |
156 | struct mv_ep *mv_ep = container_of(ep, struct mv_ep, ep); | 156 | struct mv_ep *mv_ep = container_of(ep, struct mv_ep, ep); |
157 | struct mv_udc *udc = controller.udc; | 157 | struct mv_udc *udc = (struct mv_udc *)controller.ctrl->hcor; |
158 | struct ept_queue_item *item; | 158 | struct ept_queue_item *item; |
159 | struct ept_queue_head *head; | 159 | struct ept_queue_head *head; |
160 | unsigned phys; | 160 | unsigned phys; |
161 | int bit, num, len, in; | 161 | int bit, num, len, in; |
162 | num = mv_ep->desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; | 162 | num = mv_ep->desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; |
163 | in = (mv_ep->desc->bEndpointAddress & USB_DIR_IN) != 0; | 163 | in = (mv_ep->desc->bEndpointAddress & USB_DIR_IN) != 0; |
164 | item = items[2 * num + in]; | 164 | item = items[2 * num + in]; |
165 | head = epts + 2 * num + in; | 165 | head = epts + 2 * num + in; |
166 | phys = (unsigned)req->buf; | 166 | phys = (unsigned)req->buf; |
167 | len = req->length; | 167 | len = req->length; |
168 | 168 | ||
169 | item->next = TERMINATE; | 169 | item->next = TERMINATE; |
170 | item->info = INFO_BYTES(len) | INFO_IOC | INFO_ACTIVE; | 170 | item->info = INFO_BYTES(len) | INFO_IOC | INFO_ACTIVE; |
171 | item->page0 = phys; | 171 | item->page0 = phys; |
172 | item->page1 = (phys & 0xfffff000) + 0x1000; | 172 | item->page1 = (phys & 0xfffff000) + 0x1000; |
173 | 173 | ||
174 | head->next = (unsigned) item; | 174 | head->next = (unsigned) item; |
175 | head->info = 0; | 175 | head->info = 0; |
176 | 176 | ||
177 | DBG("ept%d %s queue len %x, buffer %x\n", | 177 | DBG("ept%d %s queue len %x, buffer %x\n", |
178 | num, in ? "in" : "out", len, phys); | 178 | num, in ? "in" : "out", len, phys); |
179 | 179 | ||
180 | if (in) | 180 | if (in) |
181 | bit = EPT_TX(num); | 181 | bit = EPT_TX(num); |
182 | else | 182 | else |
183 | bit = EPT_RX(num); | 183 | bit = EPT_RX(num); |
184 | 184 | ||
185 | flush_cache(phys, len); | 185 | flush_cache(phys, len); |
186 | flush_cache((unsigned long)item, sizeof(struct ept_queue_item)); | 186 | flush_cache((unsigned long)item, sizeof(struct ept_queue_item)); |
187 | writel(bit, &udc->epprime); | 187 | writel(bit, &udc->epprime); |
188 | 188 | ||
189 | return 0; | 189 | return 0; |
190 | } | 190 | } |
191 | 191 | ||
192 | static void handle_ep_complete(struct mv_ep *ep) | 192 | static void handle_ep_complete(struct mv_ep *ep) |
193 | { | 193 | { |
194 | struct ept_queue_item *item; | 194 | struct ept_queue_item *item; |
195 | int num, in, len; | 195 | int num, in, len; |
196 | num = ep->desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; | 196 | num = ep->desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; |
197 | in = (ep->desc->bEndpointAddress & USB_DIR_IN) != 0; | 197 | in = (ep->desc->bEndpointAddress & USB_DIR_IN) != 0; |
198 | if (num == 0) | 198 | if (num == 0) |
199 | ep->desc = &ep0_out_desc; | 199 | ep->desc = &ep0_out_desc; |
200 | item = items[2 * num + in]; | 200 | item = items[2 * num + in]; |
201 | 201 | ||
202 | if (item->info & 0xff) | 202 | if (item->info & 0xff) |
203 | printf("EP%d/%s FAIL nfo=%x pg0=%x\n", | 203 | printf("EP%d/%s FAIL nfo=%x pg0=%x\n", |
204 | num, in ? "in" : "out", item->info, item->page0); | 204 | num, in ? "in" : "out", item->info, item->page0); |
205 | 205 | ||
206 | len = (item->info >> 16) & 0x7fff; | 206 | len = (item->info >> 16) & 0x7fff; |
207 | ep->req.length -= len; | 207 | ep->req.length -= len; |
208 | DBG("ept%d %s complete %x\n", | 208 | DBG("ept%d %s complete %x\n", |
209 | num, in ? "in" : "out", len); | 209 | num, in ? "in" : "out", len); |
210 | ep->req.complete(&ep->ep, &ep->req); | 210 | ep->req.complete(&ep->ep, &ep->req); |
211 | if (num == 0) { | 211 | if (num == 0) { |
212 | ep->req.length = 0; | 212 | ep->req.length = 0; |
213 | usb_ep_queue(&ep->ep, &ep->req, 0); | 213 | usb_ep_queue(&ep->ep, &ep->req, 0); |
214 | ep->desc = &ep0_in_desc; | 214 | ep->desc = &ep0_in_desc; |
215 | } | 215 | } |
216 | } | 216 | } |
217 | 217 | ||
218 | #define SETUP(type, request) (((type) << 8) | (request)) | 218 | #define SETUP(type, request) (((type) << 8) | (request)) |
219 | 219 | ||
220 | static void handle_setup(void) | 220 | static void handle_setup(void) |
221 | { | 221 | { |
222 | struct usb_request *req = &controller.ep[0].req; | 222 | struct usb_request *req = &controller.ep[0].req; |
223 | struct mv_udc *udc = controller.udc; | 223 | struct mv_udc *udc = (struct mv_udc *)controller.ctrl->hcor; |
224 | struct ept_queue_head *head; | 224 | struct ept_queue_head *head; |
225 | struct usb_ctrlrequest r; | 225 | struct usb_ctrlrequest r; |
226 | int status = 0; | 226 | int status = 0; |
227 | int num, in, _num, _in, i; | 227 | int num, in, _num, _in, i; |
228 | char *buf; | 228 | char *buf; |
229 | head = epts; | 229 | head = epts; |
230 | 230 | ||
231 | flush_cache((unsigned long)head, sizeof(struct ept_queue_head)); | 231 | flush_cache((unsigned long)head, sizeof(struct ept_queue_head)); |
232 | memcpy(&r, head->setup_data, sizeof(struct usb_ctrlrequest)); | 232 | memcpy(&r, head->setup_data, sizeof(struct usb_ctrlrequest)); |
233 | writel(EPT_RX(0), &udc->epstat); | 233 | writel(EPT_RX(0), &udc->epstat); |
234 | DBG("handle setup %s, %x, %x index %x value %x\n", reqname(r.bRequest), | 234 | DBG("handle setup %s, %x, %x index %x value %x\n", reqname(r.bRequest), |
235 | r.bRequestType, r.bRequest, r.wIndex, r.wValue); | 235 | r.bRequestType, r.bRequest, r.wIndex, r.wValue); |
236 | 236 | ||
237 | switch (SETUP(r.bRequestType, r.bRequest)) { | 237 | switch (SETUP(r.bRequestType, r.bRequest)) { |
238 | case SETUP(USB_RECIP_ENDPOINT, USB_REQ_CLEAR_FEATURE): | 238 | case SETUP(USB_RECIP_ENDPOINT, USB_REQ_CLEAR_FEATURE): |
239 | _num = r.wIndex & 15; | 239 | _num = r.wIndex & 15; |
240 | _in = !!(r.wIndex & 0x80); | 240 | _in = !!(r.wIndex & 0x80); |
241 | 241 | ||
242 | if ((r.wValue == 0) && (r.wLength == 0)) { | 242 | if ((r.wValue == 0) && (r.wLength == 0)) { |
243 | req->length = 0; | 243 | req->length = 0; |
244 | for (i = 0; i < NUM_ENDPOINTS; i++) { | 244 | for (i = 0; i < NUM_ENDPOINTS; i++) { |
245 | if (!controller.ep[i].desc) | 245 | if (!controller.ep[i].desc) |
246 | continue; | 246 | continue; |
247 | num = controller.ep[i].desc->bEndpointAddress | 247 | num = controller.ep[i].desc->bEndpointAddress |
248 | & USB_ENDPOINT_NUMBER_MASK; | 248 | & USB_ENDPOINT_NUMBER_MASK; |
249 | in = (controller.ep[i].desc->bEndpointAddress | 249 | in = (controller.ep[i].desc->bEndpointAddress |
250 | & USB_DIR_IN) != 0; | 250 | & USB_DIR_IN) != 0; |
251 | if ((num == _num) && (in == _in)) { | 251 | if ((num == _num) && (in == _in)) { |
252 | ep_enable(num, in); | 252 | ep_enable(num, in); |
253 | usb_ep_queue(controller.gadget.ep0, | 253 | usb_ep_queue(controller.gadget.ep0, |
254 | req, 0); | 254 | req, 0); |
255 | break; | 255 | break; |
256 | } | 256 | } |
257 | } | 257 | } |
258 | } | 258 | } |
259 | return; | 259 | return; |
260 | 260 | ||
261 | case SETUP(USB_RECIP_DEVICE, USB_REQ_SET_ADDRESS): | 261 | case SETUP(USB_RECIP_DEVICE, USB_REQ_SET_ADDRESS): |
262 | /* | 262 | /* |
263 | * write address delayed (will take effect | 263 | * write address delayed (will take effect |
264 | * after the next IN txn) | 264 | * after the next IN txn) |
265 | */ | 265 | */ |
266 | writel((r.wValue << 25) | (1 << 24), &udc->devaddr); | 266 | writel((r.wValue << 25) | (1 << 24), &udc->devaddr); |
267 | req->length = 0; | 267 | req->length = 0; |
268 | usb_ep_queue(controller.gadget.ep0, req, 0); | 268 | usb_ep_queue(controller.gadget.ep0, req, 0); |
269 | return; | 269 | return; |
270 | 270 | ||
271 | case SETUP(USB_DIR_IN | USB_RECIP_DEVICE, USB_REQ_GET_STATUS): | 271 | case SETUP(USB_DIR_IN | USB_RECIP_DEVICE, USB_REQ_GET_STATUS): |
272 | req->length = 2; | 272 | req->length = 2; |
273 | buf = (char *)req->buf; | 273 | buf = (char *)req->buf; |
274 | buf[0] = 1 << USB_DEVICE_SELF_POWERED; | 274 | buf[0] = 1 << USB_DEVICE_SELF_POWERED; |
275 | buf[1] = 0; | 275 | buf[1] = 0; |
276 | usb_ep_queue(controller.gadget.ep0, req, 0); | 276 | usb_ep_queue(controller.gadget.ep0, req, 0); |
277 | return; | 277 | return; |
278 | } | 278 | } |
279 | /* pass request up to the gadget driver */ | 279 | /* pass request up to the gadget driver */ |
280 | if (controller.driver) | 280 | if (controller.driver) |
281 | status = controller.driver->setup(&controller.gadget, &r); | 281 | status = controller.driver->setup(&controller.gadget, &r); |
282 | else | 282 | else |
283 | status = -ENODEV; | 283 | status = -ENODEV; |
284 | 284 | ||
285 | if (!status) | 285 | if (!status) |
286 | return; | 286 | return; |
287 | DBG("STALL reqname %s type %x value %x, index %x\n", | 287 | DBG("STALL reqname %s type %x value %x, index %x\n", |
288 | reqname(r.bRequest), r.bRequestType, r.wValue, r.wIndex); | 288 | reqname(r.bRequest), r.bRequestType, r.wValue, r.wIndex); |
289 | writel((1<<16) | (1 << 0), &udc->epctrl[0]); | 289 | writel((1<<16) | (1 << 0), &udc->epctrl[0]); |
290 | } | 290 | } |
291 | 291 | ||
292 | static void stop_activity(void) | 292 | static void stop_activity(void) |
293 | { | 293 | { |
294 | int i, num, in; | 294 | int i, num, in; |
295 | struct ept_queue_head *head; | 295 | struct ept_queue_head *head; |
296 | struct mv_udc *udc = controller.udc; | 296 | struct mv_udc *udc = (struct mv_udc *)controller.ctrl->hcor; |
297 | writel(readl(&udc->epcomp), &udc->epcomp); | 297 | writel(readl(&udc->epcomp), &udc->epcomp); |
298 | writel(readl(&udc->epstat), &udc->epstat); | 298 | writel(readl(&udc->epstat), &udc->epstat); |
299 | writel(0xffffffff, &udc->epflush); | 299 | writel(0xffffffff, &udc->epflush); |
300 | 300 | ||
301 | /* error out any pending reqs */ | 301 | /* error out any pending reqs */ |
302 | for (i = 0; i < NUM_ENDPOINTS; i++) { | 302 | for (i = 0; i < NUM_ENDPOINTS; i++) { |
303 | if (i != 0) | 303 | if (i != 0) |
304 | writel(0, &udc->epctrl[i]); | 304 | writel(0, &udc->epctrl[i]); |
305 | if (controller.ep[i].desc) { | 305 | if (controller.ep[i].desc) { |
306 | num = controller.ep[i].desc->bEndpointAddress | 306 | num = controller.ep[i].desc->bEndpointAddress |
307 | & USB_ENDPOINT_NUMBER_MASK; | 307 | & USB_ENDPOINT_NUMBER_MASK; |
308 | in = (controller.ep[i].desc->bEndpointAddress | 308 | in = (controller.ep[i].desc->bEndpointAddress |
309 | & USB_DIR_IN) != 0; | 309 | & USB_DIR_IN) != 0; |
310 | head = epts + (num * 2) + (in); | 310 | head = epts + (num * 2) + (in); |
311 | head->info = INFO_ACTIVE; | 311 | head->info = INFO_ACTIVE; |
312 | } | 312 | } |
313 | } | 313 | } |
314 | } | 314 | } |
315 | 315 | ||
316 | void udc_irq(void) | 316 | void udc_irq(void) |
317 | { | 317 | { |
318 | struct mv_udc *udc = controller.udc; | 318 | struct mv_udc *udc = (struct mv_udc *)controller.ctrl->hcor; |
319 | unsigned n = readl(&udc->usbsts); | 319 | unsigned n = readl(&udc->usbsts); |
320 | writel(n, &udc->usbsts); | 320 | writel(n, &udc->usbsts); |
321 | int bit, i, num, in; | 321 | int bit, i, num, in; |
322 | 322 | ||
323 | n &= (STS_SLI | STS_URI | STS_PCI | STS_UI | STS_UEI); | 323 | n &= (STS_SLI | STS_URI | STS_PCI | STS_UI | STS_UEI); |
324 | if (n == 0) | 324 | if (n == 0) |
325 | return; | 325 | return; |
326 | 326 | ||
327 | if (n & STS_URI) { | 327 | if (n & STS_URI) { |
328 | DBG("-- reset --\n"); | 328 | DBG("-- reset --\n"); |
329 | stop_activity(); | 329 | stop_activity(); |
330 | } | 330 | } |
331 | if (n & STS_SLI) | 331 | if (n & STS_SLI) |
332 | DBG("-- suspend --\n"); | 332 | DBG("-- suspend --\n"); |
333 | 333 | ||
334 | if (n & STS_PCI) { | 334 | if (n & STS_PCI) { |
335 | DBG("-- portchange --\n"); | 335 | DBG("-- portchange --\n"); |
336 | bit = (readl(&udc->portsc) >> 26) & 3; | 336 | bit = (readl(&udc->portsc) >> 26) & 3; |
337 | if (bit == 2) { | 337 | if (bit == 2) { |
338 | controller.gadget.speed = USB_SPEED_HIGH; | 338 | controller.gadget.speed = USB_SPEED_HIGH; |
339 | for (i = 1; i < NUM_ENDPOINTS && n; i++) | 339 | for (i = 1; i < NUM_ENDPOINTS && n; i++) |
340 | if (controller.ep[i].desc) | 340 | if (controller.ep[i].desc) |
341 | controller.ep[i].ep.maxpacket = 512; | 341 | controller.ep[i].ep.maxpacket = 512; |
342 | } else { | 342 | } else { |
343 | controller.gadget.speed = USB_SPEED_FULL; | 343 | controller.gadget.speed = USB_SPEED_FULL; |
344 | } | 344 | } |
345 | } | 345 | } |
346 | 346 | ||
347 | if (n & STS_UEI) | 347 | if (n & STS_UEI) |
348 | printf("<UEI %x>\n", readl(&udc->epcomp)); | 348 | printf("<UEI %x>\n", readl(&udc->epcomp)); |
349 | 349 | ||
350 | if ((n & STS_UI) || (n & STS_UEI)) { | 350 | if ((n & STS_UI) || (n & STS_UEI)) { |
351 | n = readl(&udc->epstat); | 351 | n = readl(&udc->epstat); |
352 | if (n & EPT_RX(0)) | 352 | if (n & EPT_RX(0)) |
353 | handle_setup(); | 353 | handle_setup(); |
354 | 354 | ||
355 | n = readl(&udc->epcomp); | 355 | n = readl(&udc->epcomp); |
356 | if (n != 0) | 356 | if (n != 0) |
357 | writel(n, &udc->epcomp); | 357 | writel(n, &udc->epcomp); |
358 | 358 | ||
359 | for (i = 0; i < NUM_ENDPOINTS && n; i++) { | 359 | for (i = 0; i < NUM_ENDPOINTS && n; i++) { |
360 | if (controller.ep[i].desc) { | 360 | if (controller.ep[i].desc) { |
361 | num = controller.ep[i].desc->bEndpointAddress | 361 | num = controller.ep[i].desc->bEndpointAddress |
362 | & USB_ENDPOINT_NUMBER_MASK; | 362 | & USB_ENDPOINT_NUMBER_MASK; |
363 | in = (controller.ep[i].desc->bEndpointAddress | 363 | in = (controller.ep[i].desc->bEndpointAddress |
364 | & USB_DIR_IN) != 0; | 364 | & USB_DIR_IN) != 0; |
365 | bit = (in) ? EPT_TX(num) : EPT_RX(num); | 365 | bit = (in) ? EPT_TX(num) : EPT_RX(num); |
366 | if (n & bit) | 366 | if (n & bit) |
367 | handle_ep_complete(&controller.ep[i]); | 367 | handle_ep_complete(&controller.ep[i]); |
368 | } | 368 | } |
369 | } | 369 | } |
370 | } | 370 | } |
371 | } | 371 | } |
372 | 372 | ||
373 | int usb_gadget_handle_interrupts(void) | 373 | int usb_gadget_handle_interrupts(void) |
374 | { | 374 | { |
375 | u32 value; | 375 | u32 value; |
376 | struct mv_udc *udc = controller.udc; | 376 | struct mv_udc *udc = (struct mv_udc *)controller.ctrl->hcor; |
377 | 377 | ||
378 | value = readl(&udc->usbsts); | 378 | value = readl(&udc->usbsts); |
379 | if (value) | 379 | if (value) |
380 | udc_irq(); | 380 | udc_irq(); |
381 | 381 | ||
382 | return value; | 382 | return value; |
383 | } | 383 | } |
384 | 384 | ||
385 | static int mv_pullup(struct usb_gadget *gadget, int is_on) | 385 | static int mv_pullup(struct usb_gadget *gadget, int is_on) |
386 | { | 386 | { |
387 | struct mv_udc *udc = controller.udc; | 387 | struct mv_udc *udc = (struct mv_udc *)controller.ctrl->hcor; |
388 | if (is_on) { | 388 | if (is_on) { |
389 | /* RESET */ | 389 | /* RESET */ |
390 | writel(USBCMD_ITC(MICRO_8FRAME) | USBCMD_RST, &udc->usbcmd); | 390 | writel(USBCMD_ITC(MICRO_8FRAME) | USBCMD_RST, &udc->usbcmd); |
391 | udelay(200); | 391 | udelay(200); |
392 | 392 | ||
393 | writel((unsigned) epts, &udc->epinitaddr); | 393 | writel((unsigned) epts, &udc->epinitaddr); |
394 | 394 | ||
395 | /* select DEVICE mode */ | 395 | /* select DEVICE mode */ |
396 | writel(USBMODE_DEVICE, &udc->usbmode); | 396 | writel(USBMODE_DEVICE, &udc->usbmode); |
397 | 397 | ||
398 | writel(0xffffffff, &udc->epflush); | 398 | writel(0xffffffff, &udc->epflush); |
399 | 399 | ||
400 | /* Turn on the USB connection by enabling the pullup resistor */ | 400 | /* Turn on the USB connection by enabling the pullup resistor */ |
401 | writel(USBCMD_ITC(MICRO_8FRAME) | USBCMD_RUN, &udc->usbcmd); | 401 | writel(USBCMD_ITC(MICRO_8FRAME) | USBCMD_RUN, &udc->usbcmd); |
402 | } else { | 402 | } else { |
403 | stop_activity(); | 403 | stop_activity(); |
404 | writel(USBCMD_FS2, &udc->usbcmd); | 404 | writel(USBCMD_FS2, &udc->usbcmd); |
405 | udelay(800); | 405 | udelay(800); |
406 | if (controller.driver) | 406 | if (controller.driver) |
407 | controller.driver->disconnect(gadget); | 407 | controller.driver->disconnect(gadget); |
408 | } | 408 | } |
409 | 409 | ||
410 | return 0; | 410 | return 0; |
411 | } | 411 | } |
412 | 412 | ||
413 | void udc_disconnect(void) | 413 | void udc_disconnect(void) |
414 | { | 414 | { |
415 | struct mv_udc *udc = controller.udc; | 415 | struct mv_udc *udc = (struct mv_udc *)controller.ctrl->hcor; |
416 | /* disable pullup */ | 416 | /* disable pullup */ |
417 | stop_activity(); | 417 | stop_activity(); |
418 | writel(USBCMD_FS2, &udc->usbcmd); | 418 | writel(USBCMD_FS2, &udc->usbcmd); |
419 | udelay(800); | 419 | udelay(800); |
420 | if (controller.driver) | 420 | if (controller.driver) |
421 | controller.driver->disconnect(&controller.gadget); | 421 | controller.driver->disconnect(&controller.gadget); |
422 | } | 422 | } |
423 | 423 | ||
424 | static int mvudc_probe(void) | 424 | static int mvudc_probe(void) |
425 | { | 425 | { |
426 | struct ept_queue_head *head; | 426 | struct ept_queue_head *head; |
427 | int i; | 427 | int i; |
428 | 428 | ||
429 | controller.gadget.ops = &mv_udc_ops; | 429 | controller.gadget.ops = &mv_udc_ops; |
430 | controller.udc = (struct mv_udc *)CONFIG_USB_REG_BASE; | ||
431 | epts = memalign(PAGE_SIZE, QH_MAXNUM * sizeof(struct ept_queue_head)); | 430 | epts = memalign(PAGE_SIZE, QH_MAXNUM * sizeof(struct ept_queue_head)); |
432 | memset(epts, 0, QH_MAXNUM * sizeof(struct ept_queue_head)); | 431 | memset(epts, 0, QH_MAXNUM * sizeof(struct ept_queue_head)); |
433 | for (i = 0; i < 2 * NUM_ENDPOINTS; i++) { | 432 | for (i = 0; i < 2 * NUM_ENDPOINTS; i++) { |
434 | /* | 433 | /* |
435 | * For item0 and item1, they are served as ep0 | 434 | * For item0 and item1, they are served as ep0 |
436 | * out&in seperately | 435 | * out&in seperately |
437 | */ | 436 | */ |
438 | head = epts + i; | 437 | head = epts + i; |
439 | if (i < 2) | 438 | if (i < 2) |
440 | head->config = CONFIG_MAX_PKT(EP0_MAX_PACKET_SIZE) | 439 | head->config = CONFIG_MAX_PKT(EP0_MAX_PACKET_SIZE) |
441 | | CONFIG_ZLT | CONFIG_IOS; | 440 | | CONFIG_ZLT | CONFIG_IOS; |
442 | else | 441 | else |
443 | head->config = CONFIG_MAX_PKT(EP_MAX_PACKET_SIZE) | 442 | head->config = CONFIG_MAX_PKT(EP_MAX_PACKET_SIZE) |
444 | | CONFIG_ZLT; | 443 | | CONFIG_ZLT; |
445 | head->next = TERMINATE; | 444 | head->next = TERMINATE; |
446 | head->info = 0; | 445 | head->info = 0; |
447 | 446 | ||
448 | items[i] = memalign(PAGE_SIZE, sizeof(struct ept_queue_item)); | 447 | items[i] = memalign(PAGE_SIZE, sizeof(struct ept_queue_item)); |
449 | } | 448 | } |
450 | 449 | ||
451 | INIT_LIST_HEAD(&controller.gadget.ep_list); | 450 | INIT_LIST_HEAD(&controller.gadget.ep_list); |
452 | 451 | ||
453 | /* Init EP 0 */ | 452 | /* Init EP 0 */ |
454 | memcpy(&controller.ep[0].ep, &mv_ep_init[0], sizeof(*mv_ep_init)); | 453 | memcpy(&controller.ep[0].ep, &mv_ep_init[0], sizeof(*mv_ep_init)); |
455 | controller.ep[0].desc = &ep0_in_desc; | 454 | controller.ep[0].desc = &ep0_in_desc; |
456 | controller.gadget.ep0 = &controller.ep[0].ep; | 455 | controller.gadget.ep0 = &controller.ep[0].ep; |
457 | INIT_LIST_HEAD(&controller.gadget.ep0->ep_list); | 456 | INIT_LIST_HEAD(&controller.gadget.ep0->ep_list); |
458 | 457 | ||
459 | /* Init EP 1..n */ | 458 | /* Init EP 1..n */ |
460 | for (i = 1; i < NUM_ENDPOINTS; i++) { | 459 | for (i = 1; i < NUM_ENDPOINTS; i++) { |
461 | memcpy(&controller.ep[i].ep, &mv_ep_init[1], | 460 | memcpy(&controller.ep[i].ep, &mv_ep_init[1], |
462 | sizeof(*mv_ep_init)); | 461 | sizeof(*mv_ep_init)); |
463 | list_add_tail(&controller.ep[i].ep.ep_list, | 462 | list_add_tail(&controller.ep[i].ep.ep_list, |
464 | &controller.gadget.ep_list); | 463 | &controller.gadget.ep_list); |
465 | } | 464 | } |
466 | 465 | ||
467 | return 0; | 466 | return 0; |
468 | } | 467 | } |
469 | 468 | ||
470 | int usb_gadget_register_driver(struct usb_gadget_driver *driver) | 469 | int usb_gadget_register_driver(struct usb_gadget_driver *driver) |
471 | { | 470 | { |
472 | struct mv_udc *udc = controller.udc; | 471 | struct mv_udc *udc; |
473 | int retval; | 472 | int ret; |
474 | void *ctrl; | ||
475 | 473 | ||
476 | if (!driver | 474 | if (!driver |
477 | || driver->speed < USB_SPEED_FULL | 475 | || driver->speed < USB_SPEED_FULL |
478 | || !driver->bind | 476 | || !driver->bind |
479 | || !driver->setup) { | 477 | || !driver->setup) { |
480 | DBG("bad parameter.\n"); | 478 | DBG("bad parameter.\n"); |
481 | return -EINVAL; | 479 | return -EINVAL; |
482 | } | 480 | } |
483 | 481 | ||
484 | if (!mvudc_probe()) { | 482 | ret = usb_lowlevel_init(0, (void **)&controller.ctrl); |
485 | usb_lowlevel_init(0, &ctrl); | 483 | if (ret) |
484 | return ret; | ||
485 | |||
486 | ret = mvudc_probe(); | ||
487 | if (!ret) { | ||
488 | udc = (struct mv_udc *)controller.ctrl->hcor; | ||
489 | |||
486 | /* select ULPI phy */ | 490 | /* select ULPI phy */ |
487 | writel(PTS(PTS_ENABLE) | PFSC, &udc->portsc); | 491 | writel(PTS(PTS_ENABLE) | PFSC, &udc->portsc); |
488 | } | 492 | } |
489 | retval = driver->bind(&controller.gadget); | 493 | |
490 | if (retval) { | 494 | ret = driver->bind(&controller.gadget); |
491 | DBG("driver->bind() returned %d\n", retval); | 495 | if (ret) { |
492 | return retval; | 496 | DBG("driver->bind() returned %d\n", ret); |
497 | return ret; | ||
493 | } | 498 | } |
494 | controller.driver = driver; | 499 | controller.driver = driver; |
495 | 500 | ||
496 | return 0; | 501 | return 0; |
497 | } | 502 | } |
498 | 503 | ||
499 | int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) | 504 | int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) |
500 | { | 505 | { |
501 | return 0; | 506 | return 0; |
include/usb/mv_udc.h
1 | /* | 1 | /* |
2 | * Copyright 2011, Marvell Semiconductor Inc. | 2 | * Copyright 2011, Marvell Semiconductor Inc. |
3 | * Lei Wen <leiwen@marvell.com> | 3 | * Lei Wen <leiwen@marvell.com> |
4 | * | 4 | * |
5 | * SPDX-License-Identifier: GPL-2.0+ | 5 | * SPDX-License-Identifier: GPL-2.0+ |
6 | */ | 6 | */ |
7 | 7 | ||
8 | 8 | ||
9 | #ifndef __MV_UDC_H__ | 9 | #ifndef __MV_UDC_H__ |
10 | #define __MV_UDC_H__ | 10 | #define __MV_UDC_H__ |
11 | 11 | ||
12 | #include <asm/byteorder.h> | 12 | #include <asm/byteorder.h> |
13 | #include <asm/errno.h> | 13 | #include <asm/errno.h> |
14 | #include <linux/usb/ch9.h> | 14 | #include <linux/usb/ch9.h> |
15 | #include <linux/usb/gadget.h> | 15 | #include <linux/usb/gadget.h> |
16 | 16 | ||
17 | #include "../../drivers/usb/host/ehci.h" | ||
18 | |||
17 | #define NUM_ENDPOINTS 6 | 19 | #define NUM_ENDPOINTS 6 |
18 | 20 | ||
19 | /* Endpoint parameters */ | 21 | /* Endpoint parameters */ |
20 | #define MAX_ENDPOINTS 4 | 22 | #define MAX_ENDPOINTS 4 |
21 | 23 | ||
22 | #define EP_MAX_PACKET_SIZE 0x200 | 24 | #define EP_MAX_PACKET_SIZE 0x200 |
23 | #define EP0_MAX_PACKET_SIZE 64 | 25 | #define EP0_MAX_PACKET_SIZE 64 |
24 | 26 | ||
25 | struct mv_udc { | 27 | struct mv_udc { |
26 | u32 pad0[80]; | ||
27 | #define MICRO_8FRAME 0x8 | 28 | #define MICRO_8FRAME 0x8 |
28 | #define USBCMD_ITC(x) ((((x) > 0xff) ? 0xff : x) << 16) | 29 | #define USBCMD_ITC(x) ((((x) > 0xff) ? 0xff : x) << 16) |
29 | #define USBCMD_FS2 (1 << 15) | 30 | #define USBCMD_FS2 (1 << 15) |
30 | #define USBCMD_RST (1 << 1) | 31 | #define USBCMD_RST (1 << 1) |
31 | #define USBCMD_RUN (1) | 32 | #define USBCMD_RUN (1) |
32 | u32 usbcmd; /* 0x140 */ | 33 | u32 usbcmd; /* 0x140 */ |
33 | #define STS_SLI (1 << 8) | 34 | #define STS_SLI (1 << 8) |
34 | #define STS_URI (1 << 6) | 35 | #define STS_URI (1 << 6) |
35 | #define STS_PCI (1 << 2) | 36 | #define STS_PCI (1 << 2) |
36 | #define STS_UEI (1 << 1) | 37 | #define STS_UEI (1 << 1) |
37 | #define STS_UI (1 << 0) | 38 | #define STS_UI (1 << 0) |
38 | u32 usbsts; /* 0x144 */ | 39 | u32 usbsts; /* 0x144 */ |
39 | u32 pad1[3]; | 40 | u32 pad1[3]; |
40 | u32 devaddr; /* 0x154 */ | 41 | u32 devaddr; /* 0x154 */ |
41 | u32 epinitaddr; /* 0x158 */ | 42 | u32 epinitaddr; /* 0x158 */ |
42 | u32 pad2[10]; | 43 | u32 pad2[10]; |
43 | #define PTS_ENABLE 2 | 44 | #define PTS_ENABLE 2 |
44 | #define PTS(x) (((x) & 0x3) << 30) | 45 | #define PTS(x) (((x) & 0x3) << 30) |
45 | #define PFSC (1 << 24) | 46 | #define PFSC (1 << 24) |
46 | u32 portsc; /* 0x184 */ | 47 | u32 portsc; /* 0x184 */ |
47 | u32 pad3[8]; | 48 | u32 pad3[8]; |
48 | #define USBMODE_DEVICE 2 | 49 | #define USBMODE_DEVICE 2 |
49 | u32 usbmode; /* 0x1a8 */ | 50 | u32 usbmode; /* 0x1a8 */ |
50 | u32 epstat; /* 0x1ac */ | 51 | u32 epstat; /* 0x1ac */ |
51 | #define EPT_TX(x) (1 << (((x) & 0xffff) + 16)) | 52 | #define EPT_TX(x) (1 << (((x) & 0xffff) + 16)) |
52 | #define EPT_RX(x) (1 << ((x) & 0xffff)) | 53 | #define EPT_RX(x) (1 << ((x) & 0xffff)) |
53 | u32 epprime; /* 0x1b0 */ | 54 | u32 epprime; /* 0x1b0 */ |
54 | u32 epflush; /* 0x1b4 */ | 55 | u32 epflush; /* 0x1b4 */ |
55 | u32 pad4; | 56 | u32 pad4; |
56 | u32 epcomp; /* 0x1bc */ | 57 | u32 epcomp; /* 0x1bc */ |
57 | #define CTRL_TXE (1 << 23) | 58 | #define CTRL_TXE (1 << 23) |
58 | #define CTRL_TXR (1 << 22) | 59 | #define CTRL_TXR (1 << 22) |
59 | #define CTRL_RXE (1 << 7) | 60 | #define CTRL_RXE (1 << 7) |
60 | #define CTRL_RXR (1 << 6) | 61 | #define CTRL_RXR (1 << 6) |
61 | #define CTRL_TXT_BULK (2 << 18) | 62 | #define CTRL_TXT_BULK (2 << 18) |
62 | #define CTRL_RXT_BULK (2 << 2) | 63 | #define CTRL_RXT_BULK (2 << 2) |
63 | u32 epctrl[16]; /* 0x1c0 */ | 64 | u32 epctrl[16]; /* 0x1c0 */ |
64 | }; | 65 | }; |
65 | 66 | ||
66 | struct mv_ep { | 67 | struct mv_ep { |
67 | struct usb_ep ep; | 68 | struct usb_ep ep; |
68 | struct usb_request req; | 69 | struct usb_request req; |
69 | struct list_head queue; | 70 | struct list_head queue; |
70 | const struct usb_endpoint_descriptor *desc; | 71 | const struct usb_endpoint_descriptor *desc; |
71 | }; | 72 | }; |
72 | 73 | ||
73 | struct mv_drv { | 74 | struct mv_drv { |
74 | struct usb_gadget gadget; | 75 | struct usb_gadget gadget; |
75 | struct usb_gadget_driver *driver; | 76 | struct usb_gadget_driver *driver; |
76 | struct mv_udc *udc; | 77 | struct ehci_ctrl *ctrl; |
77 | struct mv_ep ep[NUM_ENDPOINTS]; | 78 | struct mv_ep ep[NUM_ENDPOINTS]; |
78 | }; | 79 | }; |
79 | 80 | ||
80 | struct ept_queue_head { | 81 | struct ept_queue_head { |
81 | unsigned config; | 82 | unsigned config; |
82 | unsigned current; /* read-only */ | 83 | unsigned current; /* read-only */ |
83 | 84 | ||
84 | unsigned next; | 85 | unsigned next; |
85 | unsigned info; | 86 | unsigned info; |
86 | unsigned page0; | 87 | unsigned page0; |
87 | unsigned page1; | 88 | unsigned page1; |
88 | unsigned page2; | 89 | unsigned page2; |
89 | unsigned page3; | 90 | unsigned page3; |
90 | unsigned page4; | 91 | unsigned page4; |
91 | unsigned reserved_0; | 92 | unsigned reserved_0; |
92 | 93 | ||
93 | unsigned char setup_data[8]; | 94 | unsigned char setup_data[8]; |
94 | 95 | ||
95 | unsigned reserved_1; | 96 | unsigned reserved_1; |
96 | unsigned reserved_2; | 97 | unsigned reserved_2; |
97 | unsigned reserved_3; | 98 | unsigned reserved_3; |
98 | unsigned reserved_4; | 99 | unsigned reserved_4; |
99 | }; | 100 | }; |
100 | 101 | ||
101 | #define CONFIG_MAX_PKT(n) ((n) << 16) | 102 | #define CONFIG_MAX_PKT(n) ((n) << 16) |
102 | #define CONFIG_ZLT (1 << 29) /* stop on zero-len xfer */ | 103 | #define CONFIG_ZLT (1 << 29) /* stop on zero-len xfer */ |
103 | #define CONFIG_IOS (1 << 15) /* IRQ on setup */ | 104 | #define CONFIG_IOS (1 << 15) /* IRQ on setup */ |
104 | 105 | ||
105 | struct ept_queue_item { | 106 | struct ept_queue_item { |
106 | unsigned next; | 107 | unsigned next; |
107 | unsigned info; | 108 | unsigned info; |
108 | unsigned page0; | 109 | unsigned page0; |
109 | unsigned page1; | 110 | unsigned page1; |
110 | unsigned page2; | 111 | unsigned page2; |
111 | unsigned page3; | 112 | unsigned page3; |
112 | unsigned page4; | 113 | unsigned page4; |
113 | unsigned reserved; | 114 | unsigned reserved; |
114 | }; | 115 | }; |
115 | 116 | ||
116 | #define TERMINATE 1 | 117 | #define TERMINATE 1 |
117 | #define INFO_BYTES(n) ((n) << 16) | 118 | #define INFO_BYTES(n) ((n) << 16) |
118 | #define INFO_IOC (1 << 15) | 119 | #define INFO_IOC (1 << 15) |
119 | #define INFO_ACTIVE (1 << 7) | 120 | #define INFO_ACTIVE (1 << 7) |
120 | #define INFO_HALTED (1 << 6) | 121 | #define INFO_HALTED (1 << 6) |
121 | #define INFO_BUFFER_ERROR (1 << 5) | 122 | #define INFO_BUFFER_ERROR (1 << 5) |
122 | #define INFO_TX_ERROR (1 << 3) | 123 | #define INFO_TX_ERROR (1 << 3) |
123 | 124 | ||
124 | extern int usb_lowlevel_init(int index, void **controller); |