blob: 1e378bfff345c930fac024c260669a8b39d54c13 [file] [log] [blame]
Runmin Wang60ed4b82016-11-18 11:49:37 -08001/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
Amol Jadif3d5a892013-07-23 16:09:44 -07002 *
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are
5 * met:
6 * * Redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer.
8 * * Redistributions in binary form must reproduce the above
9 * copyright notice, this list of conditions and the following
10 * disclaimer in the documentation and/or other materials provided
11 * with the distribution.
12 * * Neither the name of The Linux Foundation nor the names of its
13 * contributors may be used to endorse or promote products derived
14 * from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/* This file implements the UDC (usb device controller) layer to be used with
30 * the new dwc controller.
31 * It exposes APIs to initialize UDC (and thus usb) and perform data transfer
32 * over usb.
33 */
34
35#include <reg.h>
36#include <debug.h>
37#include <string.h>
38#include <malloc.h>
39#include <stdlib.h>
40#include <arch/defines.h>
41#include <dev/udc.h>
42#include <platform/iomap.h>
43#include <usb30_dwc.h>
44#include <usb30_wrapper.h>
45#include <usb30_udc.h>
Amol Jadi5418da32013-10-11 14:14:47 -070046#include <smem.h>
47#include <board.h>
48#include <platform/timer.h>
Channagoud Kadabi1f24f8a2015-02-11 15:43:10 -080049#include <qmp_phy.h>
Channagoud Kadabi363e7402015-06-16 11:44:20 -070050#include <usb30_dwc_hw.h>
Amol Jadif3d5a892013-07-23 16:09:44 -070051
52//#define DEBUG_USB
53
54#ifdef DEBUG_USB
55#define DBG(...) dprintf(ALWAYS, __VA_ARGS__)
56#else
57#define DBG(...)
58#endif
59
60#define ERR(...) dprintf(ALWAYS, __VA_ARGS__)
61
62/* control data transfer is max 512 bytes */
63#define UDC_CONTROL_RX_BUF_SIZE 512
64#define UDC_CONTROL_TX_BUF_SIZE 512
65
66/* Buffer used by dwc driver to process events.
67 * Must be multiple of 4: snps 6.2.7.2.
68 */
69#define UDC_DWC_EVENT_BUF_SIZE 4096
70
71/* macro to parse setup request */
72#define SETUP(type,request) (((type) << 8) | (request))
73
74/* macro to generate bit representation of an EP */
75#define EPT_TX(n) (1 << ((n) + 16))
76#define EPT_RX(n) (1 << (n))
77
Channagoud Kadabi4ec44212014-11-03 14:54:12 -080078/* Macro for bulk SS EP descriptors */
79#define EP_BULK_IN_INDEX 21
80#define EP_BULK_OUT_INDEX 34
81
Amol Jadif3d5a892013-07-23 16:09:44 -070082/* Local functions */
83static struct udc_descriptor *udc_descriptor_alloc(uint32_t type,
84 uint32_t num,
85 uint32_t len,
86 udc_desc_spec_t spec);
87static uint8_t udc_string_desc_alloc(udc_t *udc, const char *str);
88
89static void udc_descriptor_register(udc_t *udc, struct udc_descriptor *desc);
90static void udc_register_language_desc(udc_t *udc);
91static void udc_register_bos_desc(udc_t *udc);
92static void udc_register_device_desc_usb_20(udc_t *udc, struct udc_device *dev_info);
93static void udc_register_device_desc_usb_30(udc_t *udc, struct udc_device *dev_info);
Channagoud Kadabi363e7402015-06-16 11:44:20 -070094static void udc_register_config_desc_usb20(udc_t *udc, struct udc_gadget *gadget, uint8_t type);
Amol Jadif3d5a892013-07-23 16:09:44 -070095static void udc_register_config_desc_usb30(udc_t *udc, struct udc_gadget *gadget);
96
Channagoud Kadabi363e7402015-06-16 11:44:20 -070097static void udc_ept_desc_fill(struct udc_endpoint *ept, uint8_t *data, uint8_t type);
Amol Jadif3d5a892013-07-23 16:09:44 -070098static void udc_ept_comp_desc_fill(struct udc_endpoint *ept, uint8_t *data);
99
100static void udc_dwc_notify(void *context, dwc_notify_event_t event);
101static int udc_handle_setup(void *context, uint8_t *data);
Channagoud Kadabi363e7402015-06-16 11:44:20 -0700102static bool stall_ep;
103static bool udc_other_speed_cfg;
104static bool udc_ss_capable;
Amol Jadif3d5a892013-07-23 16:09:44 -0700105
106/* TODO: This must be the only global var in this file, for now.
107 * Ideally, all APIs should be sending
108 * this to us and this ptr should be kept outside of this code.
109 * This needs change in the common udc APIs and thus keeping it here until that
110 * is done.
111 */
112static udc_t *udc_dev = NULL;
113
114
Amol Jadi5418da32013-10-11 14:14:47 -0700115__WEAK int platform_is_8974()
Amol Jadif3d5a892013-07-23 16:09:44 -0700116{
Amol Jadi5418da32013-10-11 14:14:47 -0700117 return 0;
Amol Jadif3d5a892013-07-23 16:09:44 -0700118}
119
Amol Jadi5418da32013-10-11 14:14:47 -0700120__WEAK int platform_is_8974Pro()
Amol Jadif3d5a892013-07-23 16:09:44 -0700121{
Amol Jadi5418da32013-10-11 14:14:47 -0700122 return 0;
123}
124
Channagoud Kadabi9a8062e2014-02-04 17:09:10 -0800125static void phy_reset(usb_wrapper_dev_t *wrapper, struct udc_device *dev_info)
Amol Jadi5418da32013-10-11 14:14:47 -0700126{
127 /* phy reset is different for some platforms. */
Channagoud Kadabi7bb866c2014-02-18 11:53:06 -0800128 if (platform_is_8974() || platform_is_8974Pro())
Amol Jadi5418da32013-10-11 14:14:47 -0700129 {
130 /* SS PHY */
131 usb_wrapper_ss_phy_reset(wrapper);
132
133 /* For 8974: hs phy is reset as part of soft reset.
134 * No need for explicit reset.
135 */
136 }
Channagoud Kadabi9a8062e2014-02-04 17:09:10 -0800137 else
Amol Jadi5418da32013-10-11 14:14:47 -0700138 {
Channagoud Kadabi9a8062e2014-02-04 17:09:10 -0800139 if (dev_info->t_usb_if->phy_reset)
140 dev_info->t_usb_if->phy_reset();
Channagoud Kadabi685337e2013-11-13 13:53:24 -0800141
142 /* On some CDPs PHY_COMMON reset does not set
143 * reset values in the phy_ctrl_common register.
144 * Due to this USB does not get enumerated in fastboot
145 * Force write the reset value
146 */
Channagoud Kadabi9a8062e2014-02-04 17:09:10 -0800147 if (board_platform_id() == APQ8084)
148 usb_wrapper_hs_phy_ctrl_force_write(wrapper);
Amol Jadi5418da32013-10-11 14:14:47 -0700149 }
150}
151
152/* Initialize HS phy */
153void hs_phy_init(udc_t *dev)
154{
155 /* only for 8974 */
Channagoud Kadabi7bb866c2014-02-18 11:53:06 -0800156 if (platform_is_8974() || platform_is_8974Pro())
Amol Jadi5418da32013-10-11 14:14:47 -0700157 {
158 /* 5.a, 5.b */
159 usb_wrapper_hs_phy_init(dev->wrapper_dev);
160
161 /* 5.d */
162 dwc_usb2_phy_soft_reset(dev->dwc);
163 }
164}
165
166/* vbus override */
167void vbus_override(udc_t *dev)
168{
169 /* when vbus signal is not available directly to the controller,
170 * simulate vbus presense.
171 */
Channagoud Kadabi9a8062e2014-02-04 17:09:10 -0800172 usb_wrapper_vbus_override(dev->wrapper_dev);
Amol Jadif3d5a892013-07-23 16:09:44 -0700173}
174
175
176/* Initialize usb wrapper and dwc h/w blocks. */
Channagoud Kadabi9a8062e2014-02-04 17:09:10 -0800177static void usb30_init(struct udc_device *dev_info)
Amol Jadif3d5a892013-07-23 16:09:44 -0700178{
179 usb_wrapper_dev_t* wrapper;
180 usb_wrapper_config_t wrapper_config;
181
182 dwc_dev_t *dwc;
183 dwc_config_t dwc_config;
184
Channagoud Kadabi9a8062e2014-02-04 17:09:10 -0800185 /* initialize usb clocks */
186 if (dev_info->t_usb_if->clock_init)
187 dev_info->t_usb_if->clock_init();
188
Amol Jadif3d5a892013-07-23 16:09:44 -0700189 /* initialize the usb wrapper h/w block */
190 wrapper_config.qscratch_base = (void*) MSM_USB30_QSCRATCH_BASE;
191
192 wrapper = usb_wrapper_init(&wrapper_config);
193 ASSERT(wrapper);
194
195 /* save the wrapper ptr */
196 udc_dev->wrapper_dev = wrapper;
197
198 /* initialize the dwc device block */
199 dwc_config.base = (void*) MSM_USB30_BASE;
200
201 /* buffer must be aligned to buf size. snps 8.2.2 */
202 dwc_config.event_buf = memalign(lcm(CACHE_LINE, UDC_DWC_EVENT_BUF_SIZE),
203 ROUNDUP(UDC_DWC_EVENT_BUF_SIZE, CACHE_LINE));
204 ASSERT(dwc_config.event_buf);
205
206 dwc_config.event_buf_size = UDC_DWC_EVENT_BUF_SIZE;
207
208 /* notify handler */
209 dwc_config.notify_context = udc_dev;
210 dwc_config.notify = udc_dwc_notify;
211
212 /* setup handler */
213 dwc_config.setup_context = udc_dev;
214 dwc_config.setup_handler = udc_handle_setup;
215
216 dwc = dwc_init(&dwc_config);
217 ASSERT(dwc);
218
219 /* save the dwc dev ptr */
220 udc_dev->dwc = dwc;
221
222
223 /* USB3.0 core and phy initialization as described in HPG */
224
225 /* section 4.4.1 Control sequence */
226 usb_wrapper_dbm_mode(wrapper, DBM_MODE_BYPASS);
227
228 /* section 4.4.1: use config 0 - all of RAM1 */
229 usb_wrapper_ram_configure(wrapper);
230
231 /* section 4.4.2: Initialization and configuration sequences */
232
Amol Jadif3d5a892013-07-23 16:09:44 -0700233 /* 2. Put controller in reset */
234 dwc_reset(dwc, 1);
235
Channagoud Kadabic14b2a52015-01-06 15:05:12 -0800236
Amol Jadi5418da32013-10-11 14:14:47 -0700237 /* Steps 3 - 7 must be done while dwc is in reset condition */
Amol Jadif3d5a892013-07-23 16:09:44 -0700238
Amol Jadi5418da32013-10-11 14:14:47 -0700239 /* 3. Reset PHY */
Channagoud Kadabi9a8062e2014-02-04 17:09:10 -0800240 phy_reset(wrapper, dev_info);
Amol Jadif3d5a892013-07-23 16:09:44 -0700241
Runmin Wang60ed4b82016-11-18 11:49:37 -0800242 /* 3.1 UTMI Mux configuration */
243 if (dev_info->t_usb_if->mux_config)
244 dev_info->t_usb_if->mux_config();
245
Amol Jadif3d5a892013-07-23 16:09:44 -0700246 /* 4. SS phy config */
Channagoud Kadabi1f24f8a2015-02-11 15:43:10 -0800247 if (!use_hsonly_mode())
248 usb_wrapper_ss_phy_configure(wrapper);
Amol Jadif3d5a892013-07-23 16:09:44 -0700249
250 /* 5. HS phy init */
251 usb_wrapper_hs_phy_init(wrapper);
252
Amol Jadif3d5a892013-07-23 16:09:44 -0700253 /* 6. hs phy config */
254 usb_wrapper_hs_phy_configure(wrapper);
255
256 /* 7. Reset PHY digital interface */
257 dwc_phy_digital_reset(dwc);
258
259 /* 8. Bring dwc controller out of reset */
260 dwc_reset(dwc, 0);
261
262 /* 9. */
263 usb_wrapper_ss_phy_electrical_config(wrapper);
264
Channagoud Kadabi9a8062e2014-02-04 17:09:10 -0800265 /* Perform phy init */
266 if (dev_info->t_usb_if->phy_init)
267 dev_info->t_usb_if->phy_init();
268
Channagoud Kadabi1f24f8a2015-02-11 15:43:10 -0800269 /* HS only mode support */
270 if (use_hsonly_mode())
271 usb_wrapper_hsonly_mode(wrapper);
272
Amol Jadif3d5a892013-07-23 16:09:44 -0700273 /* 10. */
274 usb_wrapper_workaround_10(wrapper);
275
276 /* 11. */
277 usb_wrapper_workaround_11(wrapper);
278
279 /* 12. */
280 dwc_ss_phy_workaround_12(dwc);
281
282 /* 13. */
283 usb_wrapper_workaround_13(wrapper);
284
285 /* 14. needed only for host mode. ignored. */
286
Amol Jadi5418da32013-10-11 14:14:47 -0700287 /* If the target does not support vbus detection in controller,
288 * simulate vbus presence.
289 */
Channagoud Kadabi9a8062e2014-02-04 17:09:10 -0800290 if (dev_info->t_usb_if->vbus_override)
291 vbus_override(udc_dev);
Amol Jadi5418da32013-10-11 14:14:47 -0700292
Amol Jadif3d5a892013-07-23 16:09:44 -0700293 /* 15 - 20 */
294 dwc_device_init(dwc);
295}
296
297/* udc_init: creates and registers various usb descriptor */
Amol Jadi151f2a52013-10-07 12:39:11 -0700298int usb30_udc_init(struct udc_device *dev_info)
Amol Jadif3d5a892013-07-23 16:09:44 -0700299{
300 /* create and initialize udc instance */
301 udc_dev = (udc_t*) malloc(sizeof(udc_t));
302 ASSERT(udc_dev);
303
304 /* initialize everything to 0 */
305 memset(udc_dev, 0 , sizeof(udc_t));
306
307 /* malloc control data buffers */
308 udc_dev->ctrl_rx_buf = memalign(CACHE_LINE, ROUNDUP(UDC_CONTROL_RX_BUF_SIZE, CACHE_LINE));
309 ASSERT(udc_dev->ctrl_rx_buf);
310
311 udc_dev->ctrl_tx_buf = memalign(CACHE_LINE, ROUNDUP(UDC_CONTROL_TX_BUF_SIZE, CACHE_LINE));
312 ASSERT(udc_dev->ctrl_tx_buf);
313
314 /* initialize string id */
315 udc_dev->next_string_id = 1;
316
317 /* Initialize ept data */
318 /* alloc table to assume EP0 In/OUT are already allocated.*/
319 udc_dev->ept_alloc_table = EPT_TX(0) | EPT_RX(0);
320 udc_dev->ept_list = NULL;
321
Channagoud Kadabi9a8062e2014-02-04 17:09:10 -0800322 usb30_init(dev_info);
Amol Jadif3d5a892013-07-23 16:09:44 -0700323
324 /* register descriptors */
325 udc_register_language_desc(udc_dev);
326 udc_register_device_desc_usb_20(udc_dev, dev_info);
327 udc_register_device_desc_usb_30(udc_dev, dev_info);
328 udc_register_bos_desc(udc_dev);
329
330 return 0;
331}
332
333/* application registers its gadget by calling this func.
334 * gadget == interface descriptor
335 */
Amol Jadi151f2a52013-10-07 12:39:11 -0700336int usb30_udc_register_gadget(struct udc_gadget *gadget)
Amol Jadif3d5a892013-07-23 16:09:44 -0700337{
338 ASSERT(gadget);
339
340 /* check if already registered */
341 if (udc_dev->gadget)
342 {
343 ERR("\nonly one gadget supported\n");
344 return -1;
345 }
346
347 /* create our configuration descriptors based on this gadget data */
Channagoud Kadabi363e7402015-06-16 11:44:20 -0700348 udc_register_config_desc_usb20(udc_dev, gadget, TYPE_CONFIGURATION);
Amol Jadif3d5a892013-07-23 16:09:44 -0700349 udc_register_config_desc_usb30(udc_dev, gadget);
350
351 /* save the gadget */
352 udc_dev->gadget = gadget;
353
354 return 0;
355}
356
357/* udc_start: */
Amol Jadi151f2a52013-10-07 12:39:11 -0700358int usb30_udc_start(void)
Amol Jadif3d5a892013-07-23 16:09:44 -0700359{
360 /* 19. run
361 * enable device to receive SOF packets and
362 * respond to control transfers on EP0 and generate events.
363 */
364 dwc_device_run(udc_dev->dwc, 1);
365
366 return 0;
367}
368
369/* Control data rx callback. Called by DWC layer when it receives control
370 * data from host.
371 */
372void udc_control_rx_callback(void *context, unsigned actual, int status)
373{
374 udc_t *udc = (udc_t *) context;
375
376 /* Force reload of buffer update by controller from memory */
377 arch_invalidate_cache_range((addr_t) udc->ctrl_rx_buf, actual);
378
379 /* TODO: for now, there is only one 3-stage write during 3.0 enumeration
380 * (SET_SEL), which causes this callback. Ideally, set_periodic() must
381 * be based on which control rx just happened.
382 * Also, the value of 0x65 should depend on the data received for SET_SEL.
383 * For now, this value works just fine.
384 */
385 dwc_device_set_periodic_param(udc->dwc, 0x65);
386}
387
388/* lookup request name for debug purposes */
389static const char *reqname(uint32_t r)
390{
391 switch (r) {
392 case GET_STATUS:
393 return "GET_STATUS";
394 case CLEAR_FEATURE:
395 return "CLEAR_FEATURE";
396 case SET_FEATURE:
397 return "SET_FEATURE";
398 case SET_ADDRESS:
399 return "SET_ADDRESS";
400 case GET_DESCRIPTOR:
401 return "GET_DESCRIPTOR";
402 case SET_DESCRIPTOR:
403 return "SET_DESCRIPTOR";
404 case GET_CONFIGURATION:
405 return "GET_CONFIGURATION";
406 case SET_CONFIGURATION:
407 return "SET_CONFIGURATION";
408 case GET_INTERFACE:
409 return "GET_INTERFACE";
410 case SET_INTERFACE:
411 return "SET_INTERFACE";
412 case SET_SEL:
413 return "SET_SEL";
414 default:
415 return "*UNKNOWN*";
416 }
417}
418
419/* callback function called by DWC layer when a setup packed is received.
420 * the return value tells dwc layer whether this setup pkt results in
421 * a 2-stage or a 3-stage control transfer or stall.
422 */
423static int udc_handle_setup(void *context, uint8_t *data)
424{
425 udc_t *udc = (udc_t *) context;
426 uint32_t len;
427
428 ASSERT(udc);
429
430 dwc_dev_t *dwc = udc->dwc;
431 ASSERT(dwc);
432
433 struct setup_packet s = *((struct setup_packet*) data);
434
435 DBG("\n SETUP request: \n type = 0x%x \n request = 0x%x \n value = 0x%x"
436 " \n index = 0x%x \n length = 0x%x\n",
437 s.type, s.request, s.value, s.index, s.length);
438
439 switch (SETUP(s.type, s.request))
440 {
Channagoud Kadabi363e7402015-06-16 11:44:20 -0700441 case SETUP(ENDPOINT_READ, GET_STATUS):
442 case SETUP(INTERFACE_READ, GET_STATUS):
Amol Jadif3d5a892013-07-23 16:09:44 -0700443 case SETUP(DEVICE_READ, GET_STATUS):
444 {
Amol Jadif3d5a892013-07-23 16:09:44 -0700445 if (s.length == 2) {
446
Channagoud Kadabi363e7402015-06-16 11:44:20 -0700447 uint16_t status = 0;
448 if (s.type == DEVICE_READ || (s.type == ENDPOINT_READ && stall_ep == true))
449 status = 1; /* Self-powered is set for device read and Halt bit set for end point read */
450
Amol Jadif3d5a892013-07-23 16:09:44 -0700451 len = 2;
452
Channagoud Kadabi363e7402015-06-16 11:44:20 -0700453 if (udc->usb_state == UDC_CONFIGURED_STATE && udc->speed == UDC_SPEED_SS)
454 {
455 if (s.type == DEVICE_READ && dwc_device_u1_enabled(dwc))
456 status |= (1 << 2); /* Set D2 to indicate U1 is enabled */
457 if (s.type == DEVICE_READ && dwc_device_u2_enabled(dwc))
458 status |= (1 << 3); /* Set D3 to indicate U3 is enabled */
459 }
460
Amol Jadif3d5a892013-07-23 16:09:44 -0700461 /* copy to tx buffer */
Channagoud Kadabi363e7402015-06-16 11:44:20 -0700462 memcpy(udc->ctrl_tx_buf, &status, len);
Amol Jadif3d5a892013-07-23 16:09:44 -0700463
464 /* flush buffer to main memory before queueing the request */
465 arch_clean_invalidate_cache_range((addr_t) udc->ctrl_tx_buf, len);
466
467 dwc_transfer_request(udc->dwc,
468 0,
469 DWC_EP_DIRECTION_IN,
470 udc->ctrl_tx_buf,
471 len,
472 NULL,
473 NULL);
474
475 return DWC_SETUP_3_STAGE;
476 }
477 }
478 break;
479 case SETUP(DEVICE_READ, GET_DESCRIPTOR):
480 {
Channagoud Kadabi363e7402015-06-16 11:44:20 -0700481 DBG("\n DEVICE_READ : GET_DESCRIPTOR: value = %x\n", s.value);
Amol Jadif3d5a892013-07-23 16:09:44 -0700482
483 /* setup usb ep0-IN to send our device descriptor */
484 struct udc_descriptor *desc;
Channagoud Kadabi363e7402015-06-16 11:44:20 -0700485 /* Device Qualifier */
486 if (((s.value >> 8) == TYPE_DEVICE_QUALIFIER) && (udc->speed != UDC_SPEED_SS))
487 {
488 struct usb_qualifier_desc qual = {0};
489 qual.bLength = sizeof(qual);
490 qual.bDescriptorType = TYPE_DEVICE_QUALIFIER;
491 qual.bcdUSB = 0x0200; /* USB2.0 version */
492 qual.bDeviceClass = udc_dev->gadget->ifc_class;
493 qual.bDeviceSubClass = udc_dev->gadget->ifc_subclass;
494 qual.bDeviceProtocol = udc_dev->gadget->ifc_protocol;
495 qual.bMaxPacketSize0 = (udc_dev->speed == UDC_SPEED_HS) ? 64 : 512;
496 qual.bNumConfigurations = 1;
497 qual.bReserved = 0;
498
499 if (sizeof(qual) > s.length)
500 len = s.length;
501 else
502 len = sizeof(qual);
503
504 /* copy to tx buffer */
505 memcpy(udc->ctrl_tx_buf, (void *)&qual, len);
506
507 /* flush buffer to main memory before queueing the request */
508 arch_clean_invalidate_cache_range((addr_t) udc->ctrl_tx_buf, len);
509
510 dwc_transfer_request(udc->dwc,
511 0,
512 DWC_EP_DIRECTION_IN,
513 udc->ctrl_tx_buf,
514 len,
515 NULL,
516 NULL);
517
518 return DWC_SETUP_3_STAGE;
519 }
520 if (((s.value >> 8) == TYPE_OTHER_SPEED_CONFIG) && (udc->speed != UDC_SPEED_SS)) /* Other speed config */
521 {
522 if (!udc_other_speed_cfg)
523 {
524 udc_register_config_desc_usb20(udc, udc->gadget, TYPE_OTHER_SPEED_CONFIG);
525 udc_other_speed_cfg = true;
526 }
527 }
Amol Jadif3d5a892013-07-23 16:09:44 -0700528
529 for (desc = udc->desc_list; desc; desc = desc->next)
530 {
531 /* tag must match the value AND
532 * if speed is SS, desc must comply with 30 spec OR
533 * if speed is not SS, desc must comply with 20 spec.
534 */
535 if ((desc->tag == s.value) &&
536 (((udc->speed == UDC_SPEED_SS) && (desc->spec & UDC_DESC_SPEC_30)) ||
537 ((udc->speed != UDC_SPEED_SS) && (desc->spec & UDC_DESC_SPEC_20)))
538 )
539 {
540 if (desc->len > s.length)
541 len = s.length;
542 else
543 len = desc->len;
544
545 /* copy to tx buffer */
546 memcpy(udc->ctrl_tx_buf, desc->data, len);
547
548 /* flush buffer to main memory before queueing the request */
549 arch_clean_invalidate_cache_range((addr_t) udc->ctrl_tx_buf, len);
550
551 dwc_transfer_request(udc->dwc,
552 0,
553 DWC_EP_DIRECTION_IN,
554 udc->ctrl_tx_buf,
555 len,
556 NULL,
557 NULL);
558
559 return DWC_SETUP_3_STAGE;
560 }
561 }
562 DBG("\n Did not find matching descriptor: = 0x%x", s.value);
563 }
564 break;
565 case SETUP(DEVICE_READ, GET_CONFIGURATION):
566 {
567 DBG("\n DEVICE_READ : GET_CONFIGURATION");
568
569 if ((s.value == 0) && (s.index == 0) && (s.length == 1)) {
570
571 len = 1;
572
573 /* copy to tx buffer */
574 memcpy(udc->ctrl_tx_buf, &udc->config_selected, len);
575
576 /* flush buffer to main memory before queueing the request */
577 arch_clean_invalidate_cache_range((addr_t) udc->ctrl_tx_buf, len);
578
579 dwc_transfer_request(udc->dwc,
580 0,
581 DWC_EP_DIRECTION_IN,
582 udc->ctrl_tx_buf,
583 len,
584 NULL,
585 NULL);
586
587 return DWC_SETUP_3_STAGE;
588 }
589 else
590 {
591 ASSERT(0);
592 }
593 }
594 break;
595 case SETUP(DEVICE_WRITE, SET_CONFIGURATION):
596 {
597 DBG("\n DEVICE_WRITE : SET_CONFIGURATION");
598
599 /* select configuration 1 */
Channagoud Kadabi363e7402015-06-16 11:44:20 -0700600 /* Return the config if configuration value is not 0 and move the state to
601 * configured state
602 */
603 if (s.value) {
Amol Jadif3d5a892013-07-23 16:09:44 -0700604 struct udc_endpoint *ept;
605 /* enable endpoints */
606 for (ept = udc->ept_list; ept; ept = ept->next) {
607 if (ept->num == 0)
608 continue;
609 else
610 {
611 /* add this ep to dwc ep list */
Sundarajan Srinivasan1c421912014-03-31 17:55:31 -0700612 dwc_ep_t *ep = (dwc_ep_t *) malloc(sizeof(dwc_ep_t));
Amol Jadif3d5a892013-07-23 16:09:44 -0700613
Sundarajan Srinivasan1c421912014-03-31 17:55:31 -0700614 if(!ep)
615 {
616 dprintf(CRITICAL, "udc_handle_setup: DEVICE_WRITE : SET_CONFIGURATION malloc failed for ep\n");
617 ASSERT(0);
618 }
619
620 ep->number = ept->num;
621 ep->dir = ept->in;
Channagoud Kadabi5f8f1c42015-03-25 14:35:05 -0700622 ep->type = ept->type;
Sundarajan Srinivasan1c421912014-03-31 17:55:31 -0700623 ep->max_pkt_size = ept->maxpkt;
624 ep->burst_size = ept->maxburst;
Channagoud Kadabi363e7402015-06-16 11:44:20 -0700625 ep->zlp = 0;
Sundarajan Srinivasan1c421912014-03-31 17:55:31 -0700626 ep->trb_count = ept->trb_count;
627 ep->trb = ept->trb;
Amol Jadif3d5a892013-07-23 16:09:44 -0700628
629 dwc_device_add_ep(dwc, ep);
Sundarajan Srinivasan1c421912014-03-31 17:55:31 -0700630
631 if(ep)
632 free(ep);
Amol Jadif3d5a892013-07-23 16:09:44 -0700633 }
634 }
635
636 /* now that we have saved the non-control EP details, set config */
637 dwc_device_set_configuration(dwc);
Channagoud Kadabi363e7402015-06-16 11:44:20 -0700638 if (udc->speed == UDC_SPEED_SS)
639 dwc_device_accept_u1u2(dwc);
Amol Jadif3d5a892013-07-23 16:09:44 -0700640
641 /* inform client that we are configured. */
642 udc->gadget->notify(udc_dev->gadget, UDC_EVENT_ONLINE);
643
644 udc->config_selected = 1;
Channagoud Kadabi363e7402015-06-16 11:44:20 -0700645 udc->usb_state = UDC_CONFIGURED_STATE;
Amol Jadif3d5a892013-07-23 16:09:44 -0700646 return DWC_SETUP_2_STAGE;
647 }
648 else if (s.value == 0)
649 {
650 /* 0 == de-configure. */
651 udc->config_selected = 0;
652 DBG("\n\n CONFIG = 0 !!!!!!!!!\n\n");
Channagoud Kadabi363e7402015-06-16 11:44:20 -0700653 /* If config value is '0' change the state to addressed state */
654 udc->usb_state = UDC_ADDRESSED_STATE;
Amol Jadif3d5a892013-07-23 16:09:44 -0700655 return DWC_SETUP_2_STAGE;
Amol Jadif3d5a892013-07-23 16:09:44 -0700656 }
657 }
658 break;
659 case SETUP(DEVICE_WRITE, SET_ADDRESS):
660 {
661 DBG("\n DEVICE_WRITE : SET_ADDRESS");
662
663 dwc_device_set_addr(dwc, s.value);
Channagoud Kadabi363e7402015-06-16 11:44:20 -0700664 udc->usb_state = UDC_ADDRESSED_STATE;
Amol Jadif3d5a892013-07-23 16:09:44 -0700665 return DWC_SETUP_2_STAGE;
666 }
667 break;
668 case SETUP(INTERFACE_WRITE, SET_INTERFACE):
669 {
Channagoud Kadabi363e7402015-06-16 11:44:20 -0700670 DBG("\n INTERFACE_WRITE : SET_INTERFACE");
Amol Jadif3d5a892013-07-23 16:09:44 -0700671 /* if we ack this everything hangs */
672 /* per spec, STALL is valid if there is not alt func */
673 goto stall;
674 }
675 break;
Channagoud Kadabi363e7402015-06-16 11:44:20 -0700676 case SETUP(INTERFACE_WRITE, SET_FEATURE):
677 {
678 DBG("\n INTERFACE_WRITE : SET_FEATURE");
679 if (s.value == FUNCTION_SUSPEND && udc->speed == UDC_SPEED_SS)
680 return DWC_SETUP_2_STAGE;
681 }
682 break;
683 case SETUP(INTERFACE_READ, GET_INTERFACE):
684 {
685 DBG("\n INTERFACE_READ : GET_INTERFACE");
686 /* per spec, STALL is valid if there is not alt func */
687 goto stall;
688 }
689 break;
690 case SETUP(ENDPOINT_WRITE, SET_FEATURE):
691 {
692 DBG("\n ENDPOINT_WRITE : SET_FEATURE");
693 if (s.value == ENDPOINT_HALT)
694 {
695 uint8_t usb_epnum;
696 uint8_t dir;
697
698 usb_epnum = (s.index & USB_EP_NUM_MASK);
699 dir = ((s.index & USB_EP_DIR_MASK) == USB_EP_DIR_IN) ? 0x1 : 0x0;
700 dwc_ep_cmd_stall(dwc, DWC_EP_PHY_NUM(usb_epnum, dir));
701 stall_ep = true;
702 return DWC_SETUP_2_STAGE;
703 }
704 else
705 goto stall;
706 }
Amol Jadif3d5a892013-07-23 16:09:44 -0700707 case SETUP(DEVICE_WRITE, SET_FEATURE):
708 {
709 DBG("\n DEVICE_WRITE : SET_FEATURE");
Channagoud Kadabi363e7402015-06-16 11:44:20 -0700710
711 if (s.value == TEST_MODE)
712 {
713 dwc->test_mode = s.index;
714
715 switch(dwc->test_mode)
716 {
717 case TEST_J:
718 case TEST_K:
719 case TEST_SE0_NAK:
720 case TEST_PACKET:
721 case TEST_FORCE_ENABLE:
722 /* Upper byte of Windex contain test mode */
723 dwc->test_mode >>= 8;
724 dwc->is_test_mode = true;
725 break;
726 default:
727 DBG("\n Unknown test mode: %x\n", dwc->test_mode);
728 }
729 return DWC_SETUP_2_STAGE;
730 }
731 if (udc->usb_state == UDC_CONFIGURED_STATE && udc->speed == UDC_SPEED_SS)
732 {
733 /* Set U1 & U2 only in configured state */
734 if (s.value == U1_ENABLE)
735 {
736 dwc_device_enable_u1(dwc, 1);
737 return DWC_SETUP_2_STAGE;
738 }
739 if (s.value == U2_ENABLE)
740 {
741 dwc_device_enable_u2(dwc, 1);
742 return DWC_SETUP_2_STAGE;
743 }
744 }
Amol Jadif3d5a892013-07-23 16:09:44 -0700745 goto stall;
746 }
747 break;
748 case SETUP(DEVICE_WRITE, CLEAR_FEATURE):
749 {
750 DBG("\n DEVICE_WRITE : CLEAR_FEATURE");
Channagoud Kadabi363e7402015-06-16 11:44:20 -0700751 /* Clear U1 & U2 only in configured state */
752 if (udc->usb_state == UDC_CONFIGURED_STATE && udc->speed == UDC_SPEED_SS)
753 {
754 if (s.value == U1_ENABLE)
755 {
756 dwc_device_enable_u1(dwc, 0);
757 return DWC_SETUP_2_STAGE;
758 }
759 if (s.value == U2_ENABLE)
760 {
761 dwc_device_enable_u2(dwc, 0);
762 return DWC_SETUP_2_STAGE;
763 }
764 }
Amol Jadif3d5a892013-07-23 16:09:44 -0700765 goto stall;
766 }
767 break;
768 case SETUP(ENDPOINT_WRITE, CLEAR_FEATURE):
769 {
Channagoud Kadabide1c1622014-01-13 11:39:06 -0800770 uint8_t usb_epnum;
771 uint8_t dir;
772
773 DBG("\n ENDPOINT_WRITE : CLEAR_FEATURE");
774
775 /*
776 * setup packet received from the host has
777 * index field containing information about the USB
778 * endpoint as below:
779 * __________________________________
780 * | (7) | (6 - 4) | (3 - 0) |
781 * |DIR | Reserved | EP number |
782 * |______|_____________|_____________|
783 */
784 usb_epnum = (s.index & USB_EP_NUM_MASK);
Channagoud Kadabica641d42014-11-21 16:58:51 -0800785 dir = ((s.index & USB_EP_DIR_MASK) == USB_EP_DIR_IN) ? 0x1 : 0x0;
Channagoud Kadabide1c1622014-01-13 11:39:06 -0800786
787 /*
788 * Convert the logical ep number to physical before
789 * sending the clear stall command.
790 * As per the data book we use fixed mapping as
791 * below:
792 * physical ep 0 --> logical ep0 OUT
793 * physical ep 1 --> logical ep0 IN
794 * physical ep 2 --> logical ep 1 OUT
795 * physical ep 3 --> logical ep 1 IN
796 * :
797 * :
798 * physical ep 30 --> logical ep 15 OUT
799 * physical ep 31 --> logical ep 15 IN
800 */
801 dwc_ep_cmd_clear_stall(dwc, DWC_EP_PHY_NUM(usb_epnum, dir));
Channagoud Kadabi363e7402015-06-16 11:44:20 -0700802 stall_ep = false;
Channagoud Kadabide1c1622014-01-13 11:39:06 -0800803
804 return DWC_SETUP_2_STAGE;
Amol Jadif3d5a892013-07-23 16:09:44 -0700805 }
806 break;
807 case SETUP(DEVICE_WRITE, SET_SEL):
808 {
809 DBG("\n DEVICE_WRITE : SET_SEL");
810
811 /* this is 3-stage write. need to receive data of s.length size. */
812 if (s.length > 0) {
813 dwc_transfer_request(udc->dwc,
814 0,
815 DWC_EP_DIRECTION_OUT,
816 udc->ctrl_rx_buf,
817 UDC_CONTROL_RX_BUF_SIZE,
818 udc_control_rx_callback,
819 (void *) udc);
820 return DWC_SETUP_3_STAGE;
821 }
822 else
823 {
824 /* length must be non-zero */
825 ASSERT(0);
826 }
827 }
828 break;
Channagoud Kadabi363e7402015-06-16 11:44:20 -0700829 case SETUP(DEVICE_WRITE, SET_ISOCH_DELAY):
830 {
831 DBG("\n DEVICE_WRITE: SET_ISOCH_DELAY\n");
832 return DWC_SETUP_2_STAGE;
833 }
834 break;
Amol Jadif3d5a892013-07-23 16:09:44 -0700835 default:
Channagoud Kadabi4ec44212014-11-03 14:54:12 -0800836 /* some of the requests from host are not handled, add a debug
837 * for the command not being handled, this is not fatal
838 */
839 DBG("\n Unknown setup req.\n type = 0x%x value = %d index = %d"
Amol Jadif3d5a892013-07-23 16:09:44 -0700840 " length = %d\n", s.type, s.value, s.index, s.length);
Amol Jadif3d5a892013-07-23 16:09:44 -0700841 }
842
843stall:
844 ERR("\nSTALL. Unsupported setup req: %s %d %d %d %d %d\n",
845 reqname(s.request), s.type, s.request, s.value, s.index, s.length);
846
847 return DWC_SETUP_ERROR;
848}
849
850/* Callback function called by DWC layer when a request to transfer data
851 * on non-control EP is completed.
852 */
853void udc_request_complete(void *context, uint32_t actual, int status)
854{
855 struct udc_request *req = ((udc_t *) context)->queued_req;
856
857 DBG("\n UDC: udc_request_callback: xferred %d bytes status = %d\n",
858 actual, status);
859
860 /* clear the queued request. */
861 ((udc_t *) context)->queued_req = NULL;
862
863 if (req->complete)
864 {
865 req->complete(req, actual, status);
866 }
867
868 DBG("\n UDC: udc_request_callback: done fastboot callback\n");
869}
870
871/* App interface to queue in data transfer requests for control and data ep */
Amol Jadi151f2a52013-10-07 12:39:11 -0700872int usb30_udc_request_queue(struct udc_endpoint *ept, struct udc_request *req)
Amol Jadif3d5a892013-07-23 16:09:44 -0700873{
874 int ret;
875 dwc_dev_t *dwc_dev = udc_dev->dwc;
876
877 /* ensure device is initialized before queuing request */
878 ASSERT(dwc_dev);
879
880 /* if device is not configured, return error */
881 if(udc_dev->config_selected == 0)
882 {
883 return -1;
884 }
885
886 /* only one request at a time is supported.
887 * check if a request is already queued.
888 */
889 if(udc_dev->queued_req)
890 {
891 return -1;
892 }
893
894 DBG("\n udc_request_queue: entry: ep_usb_num = %d", ept->num);
895
896 /* save the queued request. */
897 udc_dev->queued_req = req;
898
899 ret = dwc_transfer_request(dwc_dev,
900 ept->num,
901 ept->in ? DWC_EP_DIRECTION_IN : DWC_EP_DIRECTION_OUT,
902 req->buf,
903 req->length,
904 udc_request_complete,
905 (void *) udc_dev);
906
907 DBG("\n udc_request_queue: exit: ep_usb_num = %d", ept->num);
908
909 return ret;
910}
911
Channagoud Kadabi363e7402015-06-16 11:44:20 -0700912/* For HS device should have the version number as 0x0200.
913 * Update the minor version to 0x00 when we receive the connect
914 * event with HS or FS mode
915 */
916static void udc_update_usb20_desc(udc_t *udc)
917{
918 struct udc_descriptor *desc= NULL;
919 if (udc_ss_capable)
920 return;
921
922 for (desc = udc->desc_list; desc; desc = desc->next)
923 {
924 if (desc->spec == UDC_DESC_SPEC_20 && desc->data[1] == TYPE_DEVICE)
925 desc->data[2] = 0x00; /* usb spec minor rev */
926 }
927}
928
Channagoud Kadabi4ec44212014-11-03 14:54:12 -0800929static void udc_update_ep_desc(udc_t *udc, uint16_t max_pkt_sz_bulk)
930{
931 struct udc_descriptor *desc= NULL;
932 struct udc_endpoint *ept = NULL;
933
934 /*
935 * By default the bulk EP are registered with 512 Bytes
936 * as the max packet size. As per SS spec the max packet
937 * size for bulk is 1024. Some hosts treat the descriptor
938 * as invalid if the packet size is < 1024. Update the
939 * descriptors once we are notifed with SS connect event
940 */
941 for (desc = udc->desc_list; desc; desc = desc->next)
942 {
943 if (desc->data[EP_BULK_IN_INDEX] == EP_TYPE_BULK)
944 {
945 desc->data[EP_BULK_IN_INDEX + 1] = max_pkt_sz_bulk;
946 desc->data[EP_BULK_IN_INDEX + 2] = max_pkt_sz_bulk >> 8;
947 }
948
949 if (desc->data[EP_BULK_OUT_INDEX] == EP_TYPE_BULK)
950 {
951 desc->data[EP_BULK_OUT_INDEX + 1] = max_pkt_sz_bulk;
952 desc->data[EP_BULK_OUT_INDEX + 2] = max_pkt_sz_bulk >> 8;
953 }
954 }
955
956 for (ept = udc->ept_list; ept; ept = ept->next)
957 {
958 ept->maxpkt = max_pkt_sz_bulk;
959 }
960}
961
Amol Jadif3d5a892013-07-23 16:09:44 -0700962/* callback function called by dwc layer if any dwc event occurs */
963void udc_dwc_notify(void *context, dwc_notify_event_t event)
964{
965 udc_t *udc = (udc_t *) context;
Channagoud Kadabi4ec44212014-11-03 14:54:12 -0800966 uint32_t max_pkt_size = 0;
Amol Jadif3d5a892013-07-23 16:09:44 -0700967
968 switch (event)
969 {
970 case DWC_NOTIFY_EVENT_CONNECTED_LS:
971 udc->speed = UDC_SPEED_LS;
972 break;
973 case DWC_NOTIFY_EVENT_CONNECTED_FS:
974 udc->speed = UDC_SPEED_FS;
Channagoud Kadabi4ec44212014-11-03 14:54:12 -0800975 /* For FS connection update the ep descriptor
976 * with FS max packet size
977 */
978 max_pkt_size = 64;
979 udc_update_ep_desc(udc, max_pkt_size);
Channagoud Kadabi363e7402015-06-16 11:44:20 -0700980 /* Update the spec version for FS */
981 udc_update_usb20_desc(udc);
Amol Jadif3d5a892013-07-23 16:09:44 -0700982 break;
983 case DWC_NOTIFY_EVENT_CONNECTED_HS:
984 udc->speed = UDC_SPEED_HS;
Channagoud Kadabi4ec44212014-11-03 14:54:12 -0800985 /* For HS connection update the ep descriptor
986 * with HS max packet size
987 */
988 max_pkt_size = 512;
989 udc_update_ep_desc(udc, max_pkt_size);
Channagoud Kadabi363e7402015-06-16 11:44:20 -0700990 /* Update the spec version for HS */
991 udc_update_usb20_desc(udc);
Amol Jadif3d5a892013-07-23 16:09:44 -0700992 break;
993 case DWC_NOTIFY_EVENT_CONNECTED_SS:
994 udc->speed = UDC_SPEED_SS;
Channagoud Kadabi4ec44212014-11-03 14:54:12 -0800995 /* For SS connection update the ep descriptor
996 * with SS max packet size
997 */
998 max_pkt_size = 1024;
Channagoud Kadabi363e7402015-06-16 11:44:20 -0700999 udc_ss_capable = true;
Channagoud Kadabi4ec44212014-11-03 14:54:12 -08001000 udc_update_ep_desc(udc, max_pkt_size);
Amol Jadif3d5a892013-07-23 16:09:44 -07001001 break;
1002 case DWC_NOTIFY_EVENT_DISCONNECTED:
1003 case DWC_NOTIFY_EVENT_OFFLINE:
1004 udc->config_selected = 0;
1005 if (udc->gadget && udc->gadget->notify)
1006 udc->gadget->notify(udc->gadget, UDC_EVENT_OFFLINE);
1007 break;
1008 default:
1009 ASSERT(0);
1010 }
1011}
1012
1013
1014/******************* Function related to descriptor allocation etc.************/
1015
1016static struct udc_endpoint *_udc_endpoint_alloc(uint8_t num,
1017 uint8_t in,
Channagoud Kadabi5f8f1c42015-03-25 14:35:05 -07001018 uint8_t type,
Amol Jadif3d5a892013-07-23 16:09:44 -07001019 uint16_t max_pkt)
1020{
1021 struct udc_endpoint *ept;
1022 udc_t *udc = udc_dev;
1023
1024 ept = malloc(sizeof(*ept));
1025 ASSERT(ept);
1026
1027 ept->maxpkt = max_pkt;
1028 ept->num = num;
Channagoud Kadabi5f8f1c42015-03-25 14:35:05 -07001029 ept->type = type;
Amol Jadif3d5a892013-07-23 16:09:44 -07001030 ept->in = !!in;
1031 ept->maxburst = 4; /* no performance improvement is seen beyond burst size of 4 */
1032 ept->trb_count = 66; /* each trb can transfer (16MB - 1). 65 for 1GB transfer + 1 for roundup/zero length pkt. */
1033 ept->trb = memalign(lcm(CACHE_LINE, 16), ROUNDUP(ept->trb_count*sizeof(dwc_trb_t), CACHE_LINE)); /* TRB must be aligned to 16 */
1034 ASSERT(ept->trb);
1035
1036 /* push it on top of ept_list */
1037 ept->next = udc->ept_list;
1038 udc->ept_list = ept;
1039
1040 return ept;
1041}
1042
1043/* Called to create non-control in/out End Point structures by the APP */
Amol Jadi151f2a52013-10-07 12:39:11 -07001044struct udc_endpoint *usb30_udc_endpoint_alloc(unsigned type, unsigned maxpkt)
Amol Jadif3d5a892013-07-23 16:09:44 -07001045{
1046 struct udc_endpoint *ept;
1047 uint8_t in;
1048 uint8_t n;
1049 udc_t *udc = udc_dev;
1050
1051 if (type == UDC_TYPE_BULK_IN) {
1052 in = 1;
Channagoud Kadabi5f8f1c42015-03-25 14:35:05 -07001053 type = EP_TYPE_BULK;
Amol Jadif3d5a892013-07-23 16:09:44 -07001054 } else if (type == UDC_TYPE_BULK_OUT) {
1055 in = 0;
Channagoud Kadabi5f8f1c42015-03-25 14:35:05 -07001056 type = EP_TYPE_BULK;
1057 } else if (type == UDC_TYPE_INTR_IN) {
1058 in = 1;
1059 type = EP_TYPE_INTERRUPT;
1060 } else if (type == UDC_TYPE_INTR_OUT){
1061 in = 0;
1062 type = EP_TYPE_INTERRUPT;
Amol Jadif3d5a892013-07-23 16:09:44 -07001063 } else {
1064 return 0;
1065 }
1066
1067 for (n = 1; n < 16; n++) {
1068 uint32_t bit = in ? EPT_TX(n) : EPT_RX(n);
1069 if (udc->ept_alloc_table & bit)
1070 continue;
Channagoud Kadabi5f8f1c42015-03-25 14:35:05 -07001071 ept = _udc_endpoint_alloc(n, in, type, maxpkt);
Amol Jadif3d5a892013-07-23 16:09:44 -07001072 if (ept)
1073 udc->ept_alloc_table |= bit;
1074 return ept;
1075 }
1076 return 0;
1077}
1078
1079
1080/* create config + interface + ep desc for 2.0 */
1081static void udc_register_config_desc_usb20(udc_t *udc,
Channagoud Kadabi363e7402015-06-16 11:44:20 -07001082 struct udc_gadget *gadget, uint8_t type)
Amol Jadif3d5a892013-07-23 16:09:44 -07001083{
1084 uint8_t *data;
1085 uint16_t size;
1086 struct udc_descriptor *desc;
1087
1088 ASSERT(udc);
1089 ASSERT(gadget);
1090
1091 /* create our configuration descriptor */
1092
1093 /* size is the total size of (config + interface + all EPs) descriptor */
1094 size = UDC_DESC_SIZE_CONFIGURATION +
1095 UDC_DESC_SIZE_INTERFACE +
1096 (gadget->ifc_endpoints*UDC_DESC_SIZE_ENDPOINT);
1097
Channagoud Kadabi363e7402015-06-16 11:44:20 -07001098 desc = udc_descriptor_alloc(type, 0, size, UDC_DESC_SPEC_20);
Amol Jadif3d5a892013-07-23 16:09:44 -07001099
1100 data = desc->data;
1101
1102 /* Config desc */
1103 data[0] = 0x09;
Channagoud Kadabi363e7402015-06-16 11:44:20 -07001104 data[1] = type;
Amol Jadif3d5a892013-07-23 16:09:44 -07001105 data[2] = size;
1106 data[3] = size >> 8;
1107 data[4] = 0x01; /* number of interfaces */
1108 data[5] = 0x01; /* configuration value */
1109 data[6] = 0x00; /* configuration string */
1110 data[7] = 0xC0; /* attributes: reserved and self-powered set */
1111 data[8] = 0x00; /* max power: 0ma since we are self powered */
1112 data += 9;
1113
1114 /* Interface desc */
1115 data[0] = 0x09;
1116 data[1] = TYPE_INTERFACE;
1117 data[2] = 0x00; /* ifc number */
1118 data[3] = 0x00; /* alt number */
1119 data[4] = gadget->ifc_endpoints;
1120 data[5] = gadget->ifc_class;
1121 data[6] = gadget->ifc_subclass;
1122 data[7] = gadget->ifc_protocol;
1123 data[8] = udc_string_desc_alloc(udc, gadget->ifc_string);
1124 data += 9;
1125
1126 for (uint8_t n = 0; n < gadget->ifc_endpoints; n++) {
Channagoud Kadabi363e7402015-06-16 11:44:20 -07001127 udc_ept_desc_fill(gadget->ept[n], data, type);
Amol Jadif3d5a892013-07-23 16:09:44 -07001128 data += UDC_DESC_SIZE_ENDPOINT;
1129 }
1130
1131 udc_descriptor_register(udc, desc);
1132}
1133
1134/* create config + interface + ep desc for 3.0 */
1135static void udc_register_config_desc_usb30(udc_t *udc,
1136 struct udc_gadget *gadget)
1137{
1138 uint8_t *data;
1139 uint16_t size;
1140 struct udc_descriptor *desc;
1141
1142 ASSERT(udc);
1143 ASSERT(gadget);
1144
1145 /* create our configuration descriptor */
1146
1147 /* size is the total size of (config + interface + all EPs) descriptor */
1148 size = UDC_DESC_SIZE_CONFIGURATION +
1149 UDC_DESC_SIZE_INTERFACE +
1150 (gadget->ifc_endpoints*(UDC_DESC_SIZE_ENDPOINT + UDC_DESC_SIZE_ENDPOINT_COMP));
1151
1152 desc = udc_descriptor_alloc(TYPE_CONFIGURATION, 0, size, UDC_DESC_SPEC_30);
1153
1154 data = desc->data;
1155
1156 /* Config desc */
1157 data[0] = 0x09;
1158 data[1] = TYPE_CONFIGURATION;
1159 data[2] = size;
1160 data[3] = size >> 8;
1161 data[4] = 0x01; /* number of interfaces */
1162 data[5] = 0x01; /* configuration value */
1163 data[6] = 0x00; /* configuration string */
1164 data[7] = 0xC0; /* attributes: reserved and self-powered set */
1165 data[8] = 0x00; /* max power: 0ma since we are self powered */
1166 data += 9;
1167
1168 /* Interface desc */
1169 data[0] = 0x09;
1170 data[1] = TYPE_INTERFACE;
1171 data[2] = 0x00; /* ifc number */
1172 data[3] = 0x00; /* alt number */
1173 data[4] = gadget->ifc_endpoints;
1174 data[5] = gadget->ifc_class;
1175 data[6] = gadget->ifc_subclass;
1176 data[7] = gadget->ifc_protocol;
1177 data[8] = udc_string_desc_alloc(udc, gadget->ifc_string);
1178 data += 9;
1179
1180 for (uint8_t n = 0; n < gadget->ifc_endpoints; n++)
1181 {
1182 /* fill EP desc */
Channagoud Kadabi363e7402015-06-16 11:44:20 -07001183 udc_ept_desc_fill(gadget->ept[n], data, 0);
Amol Jadif3d5a892013-07-23 16:09:44 -07001184 data += UDC_DESC_SIZE_ENDPOINT;
1185
1186 /* fill EP companion desc */
1187 udc_ept_comp_desc_fill(gadget->ept[n], data);
1188 data += UDC_DESC_SIZE_ENDPOINT_COMP;
1189 }
1190
1191 udc_descriptor_register(udc, desc);
1192}
1193
1194
1195static void udc_register_device_desc_usb_20(udc_t *udc,
1196 struct udc_device *dev_info)
1197{
1198 uint8_t *data;
1199 struct udc_descriptor *desc;
1200
1201 /* create our device descriptor */
1202 desc = udc_descriptor_alloc(TYPE_DEVICE, 0, 18, UDC_DESC_SPEC_20);
1203 data = desc->data;
1204
1205 /* data 0 and 1 is filled by descriptor alloc routine.
1206 * fill in the remaining entries.
1207 */
Channagoud Kadabi363e7402015-06-16 11:44:20 -07001208 data[2] = 0x10; /* usb spec minor rev */
Amol Jadif3d5a892013-07-23 16:09:44 -07001209 data[3] = 0x02; /* usb spec major rev */
1210 data[4] = 0x00; /* class */
1211 data[5] = 0x00; /* subclass */
1212 data[6] = 0x00; /* protocol */
1213 data[7] = 0x40; /* max packet size on ept 0 */
1214
1215 memcpy(data + 8, &dev_info->vendor_id, sizeof(short));
1216 memcpy(data + 10, &dev_info->product_id, sizeof(short));
1217 memcpy(data + 12, &dev_info->version_id, sizeof(short));
1218
1219 data[14] = udc_string_desc_alloc(udc, dev_info->manufacturer);
1220 data[15] = udc_string_desc_alloc(udc, dev_info->product);
1221 data[16] = udc_string_desc_alloc(udc, dev_info->serialno);
1222 data[17] = 1; /* number of configurations */
1223
1224 udc_descriptor_register(udc, desc);
1225}
1226
1227static void udc_register_device_desc_usb_30(udc_t *udc, struct udc_device *dev_info)
1228{
1229 uint8_t *data;
1230 struct udc_descriptor *desc;
1231
1232 /* create our device descriptor */
1233 desc = udc_descriptor_alloc(TYPE_DEVICE, 0, 18, UDC_DESC_SPEC_30);
1234 data = desc->data;
1235
1236 /* data 0 and 1 is filled by descriptor alloc routine.
1237 * fill in the remaining entries.
1238 */
1239 data[2] = 0x00; /* usb spec minor rev */
1240 data[3] = 0x03; /* usb spec major rev */
1241 data[4] = 0x00; /* class */
1242 data[5] = 0x00; /* subclass */
1243 data[6] = 0x00; /* protocol */
1244 data[7] = 0x09; /* max packet size on ept 0 */
1245 memcpy(data + 8, &dev_info->vendor_id, sizeof(short));
1246 memcpy(data + 10, &dev_info->product_id, sizeof(short));
1247 memcpy(data + 12, &dev_info->version_id, sizeof(short));
1248 data[14] = udc_string_desc_alloc(udc, dev_info->manufacturer);
1249 data[15] = udc_string_desc_alloc(udc, dev_info->product);
1250 data[16] = udc_string_desc_alloc(udc, dev_info->serialno);
1251 data[17] = 1; /* number of configurations */
1252
1253 udc_descriptor_register(udc, desc);
1254}
1255
1256static void udc_register_bos_desc(udc_t *udc)
1257{
1258 uint8_t *data;
1259 struct udc_descriptor *desc;
1260
1261 /* create our device descriptor */
Channagoud Kadabi363e7402015-06-16 11:44:20 -07001262 desc = udc_descriptor_alloc(TYPE_BOS, 0, 0x16, UDC_DESC_SPEC_30); /* 22 is total length of bos + other descriptors inside it */
Amol Jadif3d5a892013-07-23 16:09:44 -07001263 data = desc->data;
1264
1265 /* data 0 and 1 is filled by descriptor alloc routine.
1266 * fill in the remaining entries.
1267 */
1268 data[0] = 0x05; /* BOS desc len */
1269 data[1] = TYPE_BOS; /* BOS desc type */
Channagoud Kadabi363e7402015-06-16 11:44:20 -07001270 data[2] = 0x16; /* total len of bos desc and its sub desc */
Amol Jadif3d5a892013-07-23 16:09:44 -07001271 data[3] = 0x00; /* total len of bos desc and its sub desc */
Channagoud Kadabi363e7402015-06-16 11:44:20 -07001272 data[4] = 0x02; /* num of sub desc inside bos */
Amol Jadif3d5a892013-07-23 16:09:44 -07001273
Channagoud Kadabi363e7402015-06-16 11:44:20 -07001274 /* USB2.0 extension Descriptor */
1275 data[5] = 0x07; /* Size of USB2.0 extension desc */
1276 data[6] = 0x10; /* Device capability desc */
1277 data[7] = 0x02; /* USB2.0 extension descriptor */
1278 data[8] = 0x02; /* LPM mode */
1279 data[9] = 0x00; /* Reserved */
1280 data[10] = 0x00; /* Reserved */
1281 data[11] = 0x00; /* Reserved */
1282
1283 /* Super Speed device capability */
1284 data[12] = 0x0A; /* desc len */
1285 data[13] = 0x10; /* Device Capability desc */
1286 data[14] = 0x03; /* 3 == SuperSpeed capable */
1287 data[15] = 0x00; /* Attribute: latency tolerance msg: No */
1288 data[16] = 0x0F; /* Supported Speeds (bit mask): LS, FS, HS, SS */
1289 data[17] = 0x00; /* Reserved part of supported wSupportedSpeeds */
1290 data[18] = 0x01; /* lowest supported speed with full functionality: FS */
1291 data[19] = 0x00; /* U1 device exit latency */
1292 data[20] = 0x00; /* U2 device exit latency (lsb) */
1293 data[21] = 0x00; /* U2 device exit latency (msb) */
Amol Jadif3d5a892013-07-23 16:09:44 -07001294
1295 udc_descriptor_register(udc, desc);
1296}
1297
1298static void udc_register_language_desc(udc_t *udc)
1299{
1300 /* create and register a language table descriptor */
1301 /* language 0x0409 is US English */
1302 struct udc_descriptor *desc = udc_descriptor_alloc(TYPE_STRING,
1303 0,
1304 4,
1305 UDC_DESC_SPEC_20 | UDC_DESC_SPEC_30);
1306 desc->data[2] = 0x09;
1307 desc->data[3] = 0x04;
1308 udc_descriptor_register(udc, desc);
1309}
1310
Channagoud Kadabi363e7402015-06-16 11:44:20 -07001311static void udc_ept_desc_fill(struct udc_endpoint *ept, uint8_t *data, uint8_t type)
Amol Jadif3d5a892013-07-23 16:09:44 -07001312{
Channagoud Kadabi363e7402015-06-16 11:44:20 -07001313 uint16_t max_pkt_sz = 0;
1314
1315 /* For other speed configuration, populate the max packet size for the other speed
1316 * mode. For eg: if currently host is operating in HS mode, return the configuration
1317 * for FS mode
1318 */
1319 if (type == TYPE_OTHER_SPEED_CONFIG && udc_dev->speed != UDC_SPEED_SS)
1320 max_pkt_sz = (udc_dev->speed == UDC_SPEED_FS) ? 512 : 64;
1321 else
1322 max_pkt_sz = ept->maxpkt;
1323
Amol Jadif3d5a892013-07-23 16:09:44 -07001324 data[0] = 7;
1325 data[1] = TYPE_ENDPOINT;
1326 data[2] = ept->num | (ept->in ? 0x80 : 0x00);
1327 data[3] = 0x02; /* bulk -- the only kind we support */
Channagoud Kadabi363e7402015-06-16 11:44:20 -07001328 data[4] = max_pkt_sz;
1329 data[5] = max_pkt_sz >> 8;
Amol Jadif3d5a892013-07-23 16:09:44 -07001330 data[6] = 0; /* bInterval: must be 0 for bulk. */
1331}
1332
1333static void udc_ept_comp_desc_fill(struct udc_endpoint *ept, uint8_t *data)
1334{
1335 data[0] = 6; /* bLength */
1336 data[1] = TYPE_SS_EP_COMP; /* ep type */
1337 data[2] = ept->maxburst; /* maxBurst */
1338 data[3] = 0x0; /* maxStreams */
1339 data[4] = 0x0; /* wBytesPerInterval */
1340 data[5] = 0x0; /* wBytesPerInterval */
1341}
1342
1343static uint8_t udc_string_desc_alloc(udc_t *udc, const char *str)
1344{
1345 uint32_t len;
1346 struct udc_descriptor *desc;
1347 uint8_t *data;
1348
1349 if (udc->next_string_id > 255)
1350 return 0;
1351
1352 if (!str)
1353 return 0;
1354
1355 len = strlen(str);
1356 desc = udc_descriptor_alloc(TYPE_STRING,
1357 udc->next_string_id,
1358 len * 2 + 2,
1359 UDC_DESC_SPEC_20 | UDC_DESC_SPEC_30);
1360 if (!desc)
1361 return 0;
1362 udc->next_string_id++;
1363
1364 /* expand ascii string to utf16 */
1365 data = desc->data + 2;
1366 while (len-- > 0) {
1367 *data++ = *str++;
1368 *data++ = 0;
1369 }
1370
1371 udc_descriptor_register(udc, desc);
1372 return desc->tag & 0xff;
1373}
1374
1375
1376static struct udc_descriptor *udc_descriptor_alloc(uint32_t type,
1377 uint32_t num,
1378 uint32_t len,
1379 udc_desc_spec_t spec)
1380{
1381 struct udc_descriptor *desc;
1382 if ((len > 255) || (len < 2) || (num > 255) || (type > 255))
Gaurav Nebhwanief60f402016-05-25 11:53:01 +05301383 {
1384 dprintf(CRITICAL, "Invalid parameters for descriptor allocation\n");
1385 ASSERT(0);
1386 }
Amol Jadif3d5a892013-07-23 16:09:44 -07001387
Channagoud Kadabid4e24512015-07-22 11:30:47 -07001388 desc = malloc(sizeof(struct udc_descriptor) + len);
1389 ASSERT(desc);
Amol Jadif3d5a892013-07-23 16:09:44 -07001390
1391 desc->next = 0;
1392 desc->tag = (type << 8) | num;
1393 desc->len = len;
1394 desc->spec = spec;
1395
1396 /* descriptor data */
1397 desc->data[0] = len;
1398 desc->data[1] = type;
1399
1400 return desc;
1401}
1402
1403static void udc_descriptor_register(udc_t *udc, struct udc_descriptor *desc)
1404{
1405 desc->next = udc->desc_list;
1406 udc->desc_list = desc;
1407}
1408
1409
Amol Jadi151f2a52013-10-07 12:39:11 -07001410struct udc_request *usb30_udc_request_alloc(void)
Amol Jadif3d5a892013-07-23 16:09:44 -07001411{
1412 struct udc_request *req;
1413
1414 req = malloc(sizeof(*req));
1415 ASSERT(req);
1416
1417 req->buf = 0;
1418 req->length = 0;
1419 req->complete = NULL;
1420 req->context = 0;
1421
1422 return req;
1423}
1424
Amol Jadi151f2a52013-10-07 12:39:11 -07001425void usb30_udc_request_free(struct udc_request *req)
Amol Jadif3d5a892013-07-23 16:09:44 -07001426{
1427 free(req);
1428}
1429
Amol Jadi151f2a52013-10-07 12:39:11 -07001430void usb30_udc_endpoint_free(struct udc_endpoint *ept)
Amol Jadif3d5a892013-07-23 16:09:44 -07001431{
1432 /* TODO */
1433}
1434
Amol Jadi151f2a52013-10-07 12:39:11 -07001435int usb30_udc_stop(void)
Amol Jadif3d5a892013-07-23 16:09:44 -07001436{
1437 dwc_device_run(udc_dev->dwc, 0);
1438
1439 return 0;
1440}