common: Drop linux/delay.h from common header
[oweals/u-boot.git] / drivers / usb / gadget / f_thor.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * f_thor.c -- USB TIZEN THOR Downloader gadget function
4  *
5  * Copyright (C) 2013 Samsung Electronics
6  * Lukasz Majewski <l.majewski@samsung.com>
7  *
8  * Based on code from:
9  * git://review.tizen.org/kernel/u-boot
10  *
11  * Developed by:
12  * Copyright (C) 2009 Samsung Electronics
13  * Minkyu Kang <mk7.kang@samsung.com>
14  * Sanghee Kim <sh0130.kim@samsung.com>
15  */
16
17 #include <command.h>
18 #include <errno.h>
19 #include <common.h>
20 #include <console.h>
21 #include <init.h>
22 #include <log.h>
23 #include <malloc.h>
24 #include <memalign.h>
25 #include <version.h>
26 #include <linux/delay.h>
27 #include <linux/usb/ch9.h>
28 #include <linux/usb/gadget.h>
29 #include <linux/usb/composite.h>
30 #include <linux/usb/cdc.h>
31 #include <g_dnl.h>
32 #include <dfu.h>
33
34 #include "f_thor.h"
35
36 static void thor_tx_data(unsigned char *data, int len);
37 static void thor_set_dma(void *addr, int len);
38 static int thor_rx_data(void);
39
40 static struct f_thor *thor_func;
41 static inline struct f_thor *func_to_thor(struct usb_function *f)
42 {
43         return container_of(f, struct f_thor, usb_function);
44 }
45
46 DEFINE_CACHE_ALIGN_BUFFER(unsigned char, thor_tx_data_buf,
47                           sizeof(struct rsp_box));
48 DEFINE_CACHE_ALIGN_BUFFER(unsigned char, thor_rx_data_buf,
49                           sizeof(struct rqt_box));
50
51 /* ********************************************************** */
52 /*         THOR protocol - transmission handling              */
53 /* ********************************************************** */
54 DEFINE_CACHE_ALIGN_BUFFER(char, f_name, F_NAME_BUF_SIZE + 1);
55 static unsigned long long int thor_file_size;
56 static int alt_setting_num;
57
58 static void send_rsp(const struct rsp_box *rsp)
59 {
60         memcpy(thor_tx_data_buf, rsp, sizeof(struct rsp_box));
61         thor_tx_data(thor_tx_data_buf, sizeof(struct rsp_box));
62
63         debug("-RSP: %d, %d\n", rsp->rsp, rsp->rsp_data);
64 }
65
66 static void send_data_rsp(s32 ack, s32 count)
67 {
68         ALLOC_CACHE_ALIGN_BUFFER(struct data_rsp_box, rsp,
69                                  sizeof(struct data_rsp_box));
70
71         rsp->ack = ack;
72         rsp->count = count;
73
74         memcpy(thor_tx_data_buf, rsp, sizeof(struct data_rsp_box));
75         thor_tx_data(thor_tx_data_buf, sizeof(struct data_rsp_box));
76
77         debug("-DATA RSP: %d, %d\n", ack, count);
78 }
79
80 static int process_rqt_info(const struct rqt_box *rqt)
81 {
82         ALLOC_CACHE_ALIGN_BUFFER(struct rsp_box, rsp, sizeof(struct rsp_box));
83         memset(rsp, 0, sizeof(struct rsp_box));
84
85         rsp->rsp = rqt->rqt;
86         rsp->rsp_data = rqt->rqt_data;
87
88         switch (rqt->rqt_data) {
89         case RQT_INFO_VER_PROTOCOL:
90                 rsp->int_data[0] = VER_PROTOCOL_MAJOR;
91                 rsp->int_data[1] = VER_PROTOCOL_MINOR;
92                 break;
93         case RQT_INIT_VER_HW:
94                 snprintf(rsp->str_data[0], sizeof(rsp->str_data[0]),
95                          "%x", checkboard());
96                 break;
97         case RQT_INIT_VER_BOOT:
98                 sprintf(rsp->str_data[0], "%s", U_BOOT_VERSION);
99                 break;
100         case RQT_INIT_VER_KERNEL:
101                 sprintf(rsp->str_data[0], "%s", "k unknown");
102                 break;
103         case RQT_INIT_VER_PLATFORM:
104                 sprintf(rsp->str_data[0], "%s", "p unknown");
105                 break;
106         case RQT_INIT_VER_CSC:
107                 sprintf(rsp->str_data[0], "%s", "c unknown");
108                 break;
109         default:
110                 return -EINVAL;
111         }
112
113         send_rsp(rsp);
114         return true;
115 }
116
117 static int process_rqt_cmd(const struct rqt_box *rqt)
118 {
119         ALLOC_CACHE_ALIGN_BUFFER(struct rsp_box, rsp, sizeof(struct rsp_box));
120         memset(rsp, 0, sizeof(struct rsp_box));
121
122         rsp->rsp = rqt->rqt;
123         rsp->rsp_data = rqt->rqt_data;
124
125         switch (rqt->rqt_data) {
126         case RQT_CMD_REBOOT:
127                 debug("TARGET RESET\n");
128                 send_rsp(rsp);
129                 g_dnl_unregister();
130                 dfu_free_entities();
131 #ifdef CONFIG_THOR_RESET_OFF
132                 return RESET_DONE;
133 #endif
134                 run_command("reset", 0);
135                 break;
136         case RQT_CMD_POWEROFF:
137         case RQT_CMD_EFSCLEAR:
138                 send_rsp(rsp);
139         default:
140                 printf("Command not supported -> cmd: %d\n", rqt->rqt_data);
141                 return -EINVAL;
142         }
143
144         return true;
145 }
146
147 static long long int download_head(unsigned long long total,
148                                    unsigned int packet_size,
149                                    long long int *left,
150                                    int *cnt)
151 {
152         long long int rcv_cnt = 0, left_to_rcv, ret_rcv;
153         struct dfu_entity *dfu_entity = dfu_get_entity(alt_setting_num);
154         void *transfer_buffer = dfu_get_buf(dfu_entity);
155         void *buf = transfer_buffer;
156         int usb_pkt_cnt = 0, ret;
157
158         /*
159          * Files smaller than THOR_STORE_UNIT_SIZE (now 32 MiB) are stored on
160          * the medium.
161          * The packet response is sent on the purpose after successful data
162          * chunk write. There is a room for improvement when asynchronous write
163          * is performed.
164          */
165         while (total - rcv_cnt >= packet_size) {
166                 thor_set_dma(buf, packet_size);
167                 buf += packet_size;
168                 ret_rcv = thor_rx_data();
169                 if (ret_rcv < 0)
170                         return ret_rcv;
171                 rcv_cnt += ret_rcv;
172                 debug("%d: RCV data count: %llu cnt: %d\n", usb_pkt_cnt,
173                       rcv_cnt, *cnt);
174
175                 if ((rcv_cnt % THOR_STORE_UNIT_SIZE) == 0) {
176                         ret = dfu_write(dfu_get_entity(alt_setting_num),
177                                         transfer_buffer, THOR_STORE_UNIT_SIZE,
178                                         (*cnt)++);
179                         if (ret) {
180                                 pr_err("DFU write failed [%d] cnt: %d\n",
181                                       ret, *cnt);
182                                 return ret;
183                         }
184                         buf = transfer_buffer;
185                 }
186                 send_data_rsp(0, ++usb_pkt_cnt);
187         }
188
189         /* Calculate the amount of data to arrive from PC (in bytes) */
190         left_to_rcv = total - rcv_cnt;
191
192         /*
193          * Calculate number of data already received. but not yet stored
194          * on the medium (they are smaller than THOR_STORE_UNIT_SIZE)
195          */
196         *left = left_to_rcv + buf - transfer_buffer;
197         debug("%s: left: %llu left_to_rcv: %llu buf: 0x%p\n", __func__,
198               *left, left_to_rcv, buf);
199
200         if (left_to_rcv) {
201                 thor_set_dma(buf, packet_size);
202                 ret_rcv = thor_rx_data();
203                 if (ret_rcv < 0)
204                         return ret_rcv;
205                 rcv_cnt += ret_rcv;
206                 send_data_rsp(0, ++usb_pkt_cnt);
207         }
208
209         debug("%s: %llu total: %llu cnt: %d\n", __func__, rcv_cnt, total, *cnt);
210
211         return rcv_cnt;
212 }
213
214 static int download_tail(long long int left, int cnt)
215 {
216         struct dfu_entity *dfu_entity;
217         void *transfer_buffer;
218         int ret;
219
220         debug("%s: left: %llu cnt: %d\n", __func__, left, cnt);
221
222         dfu_entity = dfu_get_entity(alt_setting_num);
223         if (!dfu_entity) {
224                 pr_err("Alt setting: %d entity not found!\n", alt_setting_num);
225                 return -ENOENT;
226         }
227
228         transfer_buffer = dfu_get_buf(dfu_entity);
229         if (!transfer_buffer) {
230                 pr_err("Transfer buffer not allocated!\n");
231                 return -ENXIO;
232         }
233
234         if (left) {
235                 ret = dfu_write(dfu_entity, transfer_buffer, left, cnt++);
236                 if (ret) {
237                         pr_err("DFU write failed[%d]: left: %llu\n", ret, left);
238                         return ret;
239                 }
240         }
241
242         /*
243          * To store last "packet" or write file from buffer to filesystem
244          * DFU storage backend requires dfu_flush
245          *
246          * This also frees memory malloc'ed by dfu_get_buf(), so no explicit
247          * need fo call dfu_free_buf() is needed.
248          */
249         ret = dfu_flush(dfu_entity, transfer_buffer, 0, cnt);
250         if (ret)
251                 pr_err("DFU flush failed!\n");
252
253         return ret;
254 }
255
256 static long long int process_rqt_download(const struct rqt_box *rqt)
257 {
258         ALLOC_CACHE_ALIGN_BUFFER(struct rsp_box, rsp, sizeof(struct rsp_box));
259         static long long int left, ret_head;
260         int file_type, ret = 0;
261         static int cnt;
262
263         memset(rsp, 0, sizeof(struct rsp_box));
264         rsp->rsp = rqt->rqt;
265         rsp->rsp_data = rqt->rqt_data;
266
267         switch (rqt->rqt_data) {
268         case RQT_DL_INIT:
269                 thor_file_size = (unsigned long long int)rqt->int_data[0] +
270                                  (((unsigned long long int)rqt->int_data[1])
271                                   << 32);
272                 debug("INIT: total %llu bytes\n", thor_file_size);
273                 break;
274         case RQT_DL_FILE_INFO:
275                 file_type = rqt->int_data[0];
276                 if (file_type == FILE_TYPE_PIT) {
277                         puts("PIT table file - not supported\n");
278                         rsp->ack = -ENOTSUPP;
279                         ret = rsp->ack;
280                         break;
281                 }
282
283                 thor_file_size = (unsigned long long int)rqt->int_data[1] +
284                                  (((unsigned long long int)rqt->int_data[2])
285                                   << 32);
286                 memcpy(f_name, rqt->str_data[0], F_NAME_BUF_SIZE);
287                 f_name[F_NAME_BUF_SIZE] = '\0';
288
289                 debug("INFO: name(%s, %d), size(%llu), type(%d)\n",
290                       f_name, 0, thor_file_size, file_type);
291
292                 rsp->int_data[0] = THOR_PACKET_SIZE;
293
294                 alt_setting_num = dfu_get_alt(f_name);
295                 if (alt_setting_num < 0) {
296                         pr_err("Alt setting [%d] to write not found!\n",
297                               alt_setting_num);
298                         rsp->ack = -ENODEV;
299                         ret = rsp->ack;
300                 }
301                 break;
302         case RQT_DL_FILE_START:
303                 send_rsp(rsp);
304                 ret_head = download_head(thor_file_size, THOR_PACKET_SIZE,
305                                          &left, &cnt);
306                 if (ret_head < 0) {
307                         left = 0;
308                         cnt = 0;
309                 }
310                 return ret_head;
311         case RQT_DL_FILE_END:
312                 debug("DL FILE_END\n");
313                 rsp->ack = download_tail(left, cnt);
314                 ret = rsp->ack;
315                 left = 0;
316                 cnt = 0;
317                 break;
318         case RQT_DL_EXIT:
319                 debug("DL EXIT\n");
320                 break;
321         default:
322                 pr_err("Operation not supported: %d\n", rqt->rqt_data);
323                 ret = -ENOTSUPP;
324         }
325
326         send_rsp(rsp);
327         return ret;
328 }
329
330 static int process_data(void)
331 {
332         ALLOC_CACHE_ALIGN_BUFFER(struct rqt_box, rqt, sizeof(struct rqt_box));
333         int ret = -EINVAL;
334
335         memcpy(rqt, thor_rx_data_buf, sizeof(struct rqt_box));
336
337         debug("+RQT: %d, %d\n", rqt->rqt, rqt->rqt_data);
338
339         switch (rqt->rqt) {
340         case RQT_INFO:
341                 ret = process_rqt_info(rqt);
342                 break;
343         case RQT_CMD:
344                 ret = process_rqt_cmd(rqt);
345                 break;
346         case RQT_DL:
347                 ret = (int) process_rqt_download(rqt);
348                 break;
349         case RQT_UL:
350                 puts("RQT: UPLOAD not supported!\n");
351                 break;
352         default:
353                 pr_err("unknown request (%d)\n", rqt->rqt);
354         }
355
356         return ret;
357 }
358
359 /* ********************************************************** */
360 /*         THOR USB Function                                  */
361 /* ********************************************************** */
362
363 static inline struct usb_endpoint_descriptor *
364 ep_desc(struct usb_gadget *g, struct usb_endpoint_descriptor *hs,
365         struct usb_endpoint_descriptor *fs)
366 {
367         if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH)
368                 return hs;
369         return fs;
370 }
371
372 static struct usb_interface_descriptor thor_downloader_intf_data = {
373         .bLength =              sizeof(thor_downloader_intf_data),
374         .bDescriptorType =      USB_DT_INTERFACE,
375
376         .bNumEndpoints =        2,
377         .bInterfaceClass =      USB_CLASS_CDC_DATA,
378 };
379
380 static struct usb_endpoint_descriptor fs_in_desc = {
381         .bLength =              USB_DT_ENDPOINT_SIZE,
382         .bDescriptorType =      USB_DT_ENDPOINT,
383
384         .bEndpointAddress =     USB_DIR_IN,
385         .bmAttributes = USB_ENDPOINT_XFER_BULK,
386 };
387
388 static struct usb_endpoint_descriptor fs_out_desc = {
389         .bLength =              USB_DT_ENDPOINT_SIZE,
390         .bDescriptorType =      USB_DT_ENDPOINT,
391
392         .bEndpointAddress =     USB_DIR_OUT,
393         .bmAttributes = USB_ENDPOINT_XFER_BULK,
394 };
395
396 /* CDC configuration */
397 static struct usb_interface_descriptor thor_downloader_intf_int = {
398         .bLength =              sizeof(thor_downloader_intf_int),
399         .bDescriptorType =      USB_DT_INTERFACE,
400
401         .bNumEndpoints =        1,
402         .bInterfaceClass =      USB_CLASS_COMM,
403          /* 0x02 Abstract Line Control Model */
404         .bInterfaceSubClass =   USB_CDC_SUBCLASS_ACM,
405         /* 0x01 Common AT commands */
406         .bInterfaceProtocol =   USB_CDC_ACM_PROTO_AT_V25TER,
407 };
408
409 static struct usb_cdc_header_desc thor_downloader_cdc_header = {
410         .bLength         =    sizeof(thor_downloader_cdc_header),
411         .bDescriptorType =    0x24, /* CS_INTERFACE */
412         .bDescriptorSubType = 0x00,
413         .bcdCDC =             0x0110,
414 };
415
416 static struct usb_cdc_call_mgmt_descriptor thor_downloader_cdc_call = {
417         .bLength         =    sizeof(thor_downloader_cdc_call),
418         .bDescriptorType =    0x24, /* CS_INTERFACE */
419         .bDescriptorSubType = 0x01,
420         .bmCapabilities =     0x00,
421         .bDataInterface =     0x01,
422 };
423
424 static struct usb_cdc_acm_descriptor thor_downloader_cdc_abstract = {
425         .bLength         =    sizeof(thor_downloader_cdc_abstract),
426         .bDescriptorType =    0x24, /* CS_INTERFACE */
427         .bDescriptorSubType = 0x02,
428         .bmCapabilities =     0x00,
429 };
430
431 static struct usb_cdc_union_desc thor_downloader_cdc_union = {
432         .bLength         =     sizeof(thor_downloader_cdc_union),
433         .bDescriptorType =     0x24, /* CS_INTERFACE */
434         .bDescriptorSubType =  USB_CDC_UNION_TYPE,
435 };
436
437 static struct usb_endpoint_descriptor fs_int_desc = {
438         .bLength = USB_DT_ENDPOINT_SIZE,
439         .bDescriptorType = USB_DT_ENDPOINT,
440
441         .bEndpointAddress = 3 | USB_DIR_IN,
442         .bmAttributes = USB_ENDPOINT_XFER_INT,
443         .wMaxPacketSize = __constant_cpu_to_le16(16),
444
445         .bInterval = 0x9,
446 };
447
448 static struct usb_interface_assoc_descriptor
449 thor_iad_descriptor = {
450         .bLength =              sizeof(thor_iad_descriptor),
451         .bDescriptorType =      USB_DT_INTERFACE_ASSOCIATION,
452
453         .bFirstInterface =      0,
454         .bInterfaceCount =      2,      /* control + data */
455         .bFunctionClass =       USB_CLASS_COMM,
456         .bFunctionSubClass =    USB_CDC_SUBCLASS_ACM,
457         .bFunctionProtocol =    USB_CDC_PROTO_NONE,
458 };
459
460 static struct usb_endpoint_descriptor hs_in_desc = {
461         .bLength =              USB_DT_ENDPOINT_SIZE,
462         .bDescriptorType =      USB_DT_ENDPOINT,
463
464         .bmAttributes = USB_ENDPOINT_XFER_BULK,
465         .wMaxPacketSize =       __constant_cpu_to_le16(512),
466 };
467
468 static struct usb_endpoint_descriptor hs_out_desc = {
469         .bLength =              USB_DT_ENDPOINT_SIZE,
470         .bDescriptorType =      USB_DT_ENDPOINT,
471
472         .bmAttributes = USB_ENDPOINT_XFER_BULK,
473         .wMaxPacketSize =       __constant_cpu_to_le16(512),
474 };
475
476 static struct usb_endpoint_descriptor hs_int_desc = {
477         .bLength = USB_DT_ENDPOINT_SIZE,
478         .bDescriptorType = USB_DT_ENDPOINT,
479
480         .bmAttributes = USB_ENDPOINT_XFER_INT,
481         .wMaxPacketSize = __constant_cpu_to_le16(16),
482
483         .bInterval = 0x9,
484 };
485
486 /*
487  * This attribute vendor descriptor is necessary for correct operation with
488  * Windows version of THOR download program
489  *
490  * It prevents windows driver from sending zero lenght packet (ZLP) after
491  * each THOR_PACKET_SIZE. This assures consistent behaviour with libusb
492  */
493 static struct usb_cdc_attribute_vendor_descriptor thor_downloader_cdc_av = {
494         .bLength =              sizeof(thor_downloader_cdc_av),
495         .bDescriptorType =      0x24,
496         .bDescriptorSubType =   0x80,
497         .DAUType =              0x0002,
498         .DAULength =            0x0001,
499         .DAUValue =             0x00,
500 };
501
502 static const struct usb_descriptor_header *hs_thor_downloader_function[] = {
503         (struct usb_descriptor_header *)&thor_iad_descriptor,
504
505         (struct usb_descriptor_header *)&thor_downloader_intf_int,
506         (struct usb_descriptor_header *)&thor_downloader_cdc_header,
507         (struct usb_descriptor_header *)&thor_downloader_cdc_call,
508         (struct usb_descriptor_header *)&thor_downloader_cdc_abstract,
509         (struct usb_descriptor_header *)&thor_downloader_cdc_union,
510         (struct usb_descriptor_header *)&hs_int_desc,
511
512         (struct usb_descriptor_header *)&thor_downloader_intf_data,
513         (struct usb_descriptor_header *)&thor_downloader_cdc_av,
514         (struct usb_descriptor_header *)&hs_in_desc,
515         (struct usb_descriptor_header *)&hs_out_desc,
516         NULL,
517 };
518
519 /*-------------------------------------------------------------------------*/
520 static struct usb_request *alloc_ep_req(struct usb_ep *ep, unsigned length)
521 {
522         struct usb_request *req;
523
524         req = usb_ep_alloc_request(ep, 0);
525         if (!req)
526                 return req;
527
528         req->length = length;
529         req->buf = memalign(CONFIG_SYS_CACHELINE_SIZE, length);
530         if (!req->buf) {
531                 usb_ep_free_request(ep, req);
532                 req = NULL;
533         }
534
535         return req;
536 }
537
538 static int thor_rx_data(void)
539 {
540         struct thor_dev *dev = thor_func->dev;
541         int data_to_rx, tmp, status;
542
543         data_to_rx = dev->out_req->length;
544         tmp = data_to_rx;
545         do {
546                 dev->out_req->length = data_to_rx;
547                 debug("dev->out_req->length:%d dev->rxdata:%d\n",
548                       dev->out_req->length, dev->rxdata);
549
550                 status = usb_ep_queue(dev->out_ep, dev->out_req, 0);
551                 if (status) {
552                         pr_err("kill %s:  resubmit %d bytes --> %d\n",
553                               dev->out_ep->name, dev->out_req->length, status);
554                         usb_ep_set_halt(dev->out_ep);
555                         return -EAGAIN;
556                 }
557
558                 while (!dev->rxdata) {
559                         usb_gadget_handle_interrupts(0);
560                         if (ctrlc())
561                                 return -1;
562                 }
563                 dev->rxdata = 0;
564                 data_to_rx -= dev->out_req->actual;
565         } while (data_to_rx);
566
567         return tmp;
568 }
569
570 static void thor_tx_data(unsigned char *data, int len)
571 {
572         struct thor_dev *dev = thor_func->dev;
573         unsigned char *ptr = dev->in_req->buf;
574         int status;
575
576         memset(ptr, 0, len);
577         memcpy(ptr, data, len);
578
579         dev->in_req->length = len;
580
581         debug("%s: dev->in_req->length:%d to_cpy:%zd\n", __func__,
582               dev->in_req->length, sizeof(data));
583
584         status = usb_ep_queue(dev->in_ep, dev->in_req, 0);
585         if (status) {
586                 pr_err("kill %s:  resubmit %d bytes --> %d\n",
587                       dev->in_ep->name, dev->in_req->length, status);
588                 usb_ep_set_halt(dev->in_ep);
589         }
590
591         /* Wait until tx interrupt received */
592         while (!dev->txdata)
593                 usb_gadget_handle_interrupts(0);
594
595         dev->txdata = 0;
596 }
597
598 static void thor_rx_tx_complete(struct usb_ep *ep, struct usb_request *req)
599 {
600         struct thor_dev *dev = thor_func->dev;
601         int status = req->status;
602
603         debug("%s: ep_ptr:%p, req_ptr:%p\n", __func__, ep, req);
604         switch (status) {
605         case 0:
606                 if (ep == dev->out_ep)
607                         dev->rxdata = 1;
608                 else
609                         dev->txdata = 1;
610
611                 break;
612
613         /* this endpoint is normally active while we're configured */
614         case -ECONNABORTED:             /* hardware forced ep reset */
615         case -ECONNRESET:               /* request dequeued */
616         case -ESHUTDOWN:                /* disconnect from host */
617         case -EREMOTEIO:                /* short read */
618         case -EOVERFLOW:
619                 pr_err("ERROR:%d\n", status);
620                 break;
621         }
622
623         debug("%s complete --> %d, %d/%d\n", ep->name,
624               status, req->actual, req->length);
625 }
626
627 static void thor_setup_complete(struct usb_ep *ep, struct usb_request *req)
628 {
629         if (req->status || req->actual != req->length)
630                 debug("setup complete --> %d, %d/%d\n",
631                       req->status, req->actual, req->length);
632 }
633
634 static int
635 thor_func_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
636 {
637         struct thor_dev *dev = thor_func->dev;
638         struct usb_request *req = dev->req;
639         struct usb_gadget *gadget = dev->gadget;
640         int value = 0;
641
642         u16 len = le16_to_cpu(ctrl->wLength);
643
644         debug("Req_Type: 0x%x Req: 0x%x wValue: 0x%x wIndex: 0x%x wLen: 0x%x\n",
645               ctrl->bRequestType, ctrl->bRequest, ctrl->wValue, ctrl->wIndex,
646               ctrl->wLength);
647
648         switch (ctrl->bRequest) {
649         case USB_CDC_REQ_SET_CONTROL_LINE_STATE:
650                 value = 0;
651                 break;
652         case USB_CDC_REQ_SET_LINE_CODING:
653                 value = len;
654                 /* Line Coding set done = configuration done */
655                 thor_func->dev->configuration_done = 1;
656                 break;
657
658         default:
659                 pr_err("thor_setup: unknown request: %d\n", ctrl->bRequest);
660         }
661
662         if (value >= 0) {
663                 req->length = value;
664                 req->zero = value < len;
665                 value = usb_ep_queue(gadget->ep0, req, 0);
666                 if (value < 0) {
667                         debug("%s: ep_queue: %d\n", __func__, value);
668                         req->status = 0;
669                 }
670         }
671
672         return value;
673 }
674
675 /* Specific to the THOR protocol */
676 static void thor_set_dma(void *addr, int len)
677 {
678         struct thor_dev *dev = thor_func->dev;
679
680         debug("in_req:%p, out_req:%p\n", dev->in_req, dev->out_req);
681         debug("addr:%p, len:%d\n", addr, len);
682
683         dev->out_req->buf = addr;
684         dev->out_req->length = len;
685 }
686
687 int thor_init(void)
688 {
689         struct thor_dev *dev = thor_func->dev;
690
691         /* Wait for a device enumeration and configuration settings */
692         debug("THOR enumeration/configuration setting....\n");
693         while (!dev->configuration_done)
694                 usb_gadget_handle_interrupts(0);
695
696         thor_set_dma(thor_rx_data_buf, strlen("THOR"));
697         /* detect the download request from Host PC */
698         if (thor_rx_data() < 0) {
699                 printf("%s: Data not received!\n", __func__);
700                 return -1;
701         }
702
703         if (!strncmp((char *)thor_rx_data_buf, "THOR", strlen("THOR"))) {
704                 puts("Download request from the Host PC\n");
705                 udelay(30 * 1000); /* 30 ms */
706
707                 strcpy((char *)thor_tx_data_buf, "ROHT");
708                 thor_tx_data(thor_tx_data_buf, strlen("ROHT"));
709         } else {
710                 puts("Wrong reply information\n");
711                 return -1;
712         }
713
714         return 0;
715 }
716
717 int thor_handle(void)
718 {
719         int ret;
720
721         /* receive the data from Host PC */
722         while (1) {
723                 thor_set_dma(thor_rx_data_buf, sizeof(struct rqt_box));
724                 ret = thor_rx_data();
725
726                 if (ret > 0) {
727                         ret = process_data();
728 #ifdef CONFIG_THOR_RESET_OFF
729                         if (ret == RESET_DONE)
730                                 break;
731 #endif
732                         if (ret < 0)
733                                 return ret;
734                 } else {
735                         printf("%s: No data received!\n", __func__);
736                         break;
737                 }
738         }
739
740         return 0;
741 }
742
743 static void free_ep_req(struct usb_ep *ep, struct usb_request *req)
744 {
745         if (req->buf)
746                 free(req->buf);
747         usb_ep_free_request(ep, req);
748 }
749
750 static int thor_func_bind(struct usb_configuration *c, struct usb_function *f)
751 {
752         struct usb_gadget *gadget = c->cdev->gadget;
753         struct f_thor *f_thor = func_to_thor(f);
754         struct thor_dev *dev;
755         struct usb_ep *ep;
756         int status;
757
758         thor_func = f_thor;
759         dev = memalign(CONFIG_SYS_CACHELINE_SIZE, sizeof(*dev));
760         if (!dev)
761                 return -ENOMEM;
762
763         memset(dev, 0, sizeof(*dev));
764         dev->gadget = gadget;
765         f_thor->dev = dev;
766
767         debug("%s: usb_configuration: 0x%p usb_function: 0x%p\n",
768               __func__, c, f);
769         debug("f_thor: 0x%p thor: 0x%p\n", f_thor, dev);
770
771         /* EP0  */
772         /* preallocate control response and buffer */
773         dev->req = usb_ep_alloc_request(gadget->ep0, 0);
774         if (!dev->req) {
775                 status = -ENOMEM;
776                 goto fail;
777         }
778         dev->req->buf = memalign(CONFIG_SYS_CACHELINE_SIZE,
779                                  THOR_PACKET_SIZE);
780         if (!dev->req->buf) {
781                 status = -ENOMEM;
782                 goto fail;
783         }
784
785         dev->req->complete = thor_setup_complete;
786
787         /* DYNAMIC interface numbers assignments */
788         status = usb_interface_id(c, f);
789
790         if (status < 0)
791                 goto fail;
792
793         thor_downloader_intf_int.bInterfaceNumber = status;
794         thor_downloader_cdc_union.bMasterInterface0 = status;
795
796         status = usb_interface_id(c, f);
797
798         if (status < 0)
799                 goto fail;
800
801         thor_downloader_intf_data.bInterfaceNumber = status;
802         thor_downloader_cdc_union.bSlaveInterface0 = status;
803
804         /* allocate instance-specific endpoints */
805         ep = usb_ep_autoconfig(gadget, &fs_in_desc);
806         if (!ep) {
807                 status = -ENODEV;
808                 goto fail;
809         }
810
811         if (gadget_is_dualspeed(gadget)) {
812                 hs_in_desc.bEndpointAddress =
813                                 fs_in_desc.bEndpointAddress;
814         }
815
816         dev->in_ep = ep; /* Store IN EP for enabling @ setup */
817         ep->driver_data = dev;
818
819         ep = usb_ep_autoconfig(gadget, &fs_out_desc);
820         if (!ep) {
821                 status = -ENODEV;
822                 goto fail;
823         }
824
825         if (gadget_is_dualspeed(gadget))
826                 hs_out_desc.bEndpointAddress =
827                                 fs_out_desc.bEndpointAddress;
828
829         dev->out_ep = ep; /* Store OUT EP for enabling @ setup */
830         ep->driver_data = dev;
831
832         ep = usb_ep_autoconfig(gadget, &fs_int_desc);
833         if (!ep) {
834                 status = -ENODEV;
835                 goto fail;
836         }
837
838         dev->int_ep = ep;
839         ep->driver_data = dev;
840
841         if (gadget_is_dualspeed(gadget)) {
842                 hs_int_desc.bEndpointAddress =
843                                 fs_int_desc.bEndpointAddress;
844
845                 f->hs_descriptors = (struct usb_descriptor_header **)
846                         &hs_thor_downloader_function;
847
848                 if (!f->hs_descriptors)
849                         goto fail;
850         }
851
852         debug("%s: out_ep:%p out_req:%p\n", __func__,
853               dev->out_ep, dev->out_req);
854
855         return 0;
856
857  fail:
858         if (dev->req)
859                 free_ep_req(gadget->ep0, dev->req);
860         free(dev);
861         return status;
862 }
863
864 static void thor_unbind(struct usb_configuration *c, struct usb_function *f)
865 {
866         struct f_thor *f_thor = func_to_thor(f);
867         struct thor_dev *dev = f_thor->dev;
868
869         free_ep_req(dev->gadget->ep0, dev->req);
870         free(dev);
871         memset(thor_func, 0, sizeof(*thor_func));
872         thor_func = NULL;
873 }
874
875 static void thor_func_disable(struct usb_function *f)
876 {
877         struct f_thor *f_thor = func_to_thor(f);
878         struct thor_dev *dev = f_thor->dev;
879
880         debug("%s:\n", __func__);
881
882         /* Avoid freeing memory when ep is still claimed */
883         if (dev->in_ep->driver_data) {
884                 usb_ep_disable(dev->in_ep);
885                 free_ep_req(dev->in_ep, dev->in_req);
886                 dev->in_ep->driver_data = NULL;
887         }
888
889         if (dev->out_ep->driver_data) {
890                 usb_ep_disable(dev->out_ep);
891                 usb_ep_free_request(dev->out_ep, dev->out_req);
892                 dev->out_ep->driver_data = NULL;
893         }
894
895         if (dev->int_ep->driver_data) {
896                 usb_ep_disable(dev->int_ep);
897                 dev->int_ep->driver_data = NULL;
898         }
899 }
900
901 static int thor_eps_setup(struct usb_function *f)
902 {
903         struct usb_composite_dev *cdev = f->config->cdev;
904         struct usb_gadget *gadget = cdev->gadget;
905         struct thor_dev *dev = thor_func->dev;
906         struct usb_endpoint_descriptor *d;
907         struct usb_request *req;
908         struct usb_ep *ep;
909         int result;
910
911         ep = dev->in_ep;
912         d = ep_desc(gadget, &hs_in_desc, &fs_in_desc);
913         debug("(d)bEndpointAddress: 0x%x\n", d->bEndpointAddress);
914
915         result = usb_ep_enable(ep, d);
916         if (result)
917                 goto err;
918
919         ep->driver_data = cdev; /* claim */
920         req = alloc_ep_req(ep, THOR_PACKET_SIZE);
921         if (!req) {
922                 result = -EIO;
923                 goto err_disable_in_ep;
924         }
925
926         memset(req->buf, 0, req->length);
927         req->complete = thor_rx_tx_complete;
928         dev->in_req = req;
929         ep = dev->out_ep;
930         d = ep_desc(gadget, &hs_out_desc, &fs_out_desc);
931         debug("(d)bEndpointAddress: 0x%x\n", d->bEndpointAddress);
932
933         result = usb_ep_enable(ep, d);
934         if (result)
935                 goto err_free_in_req;
936
937         ep->driver_data = cdev; /* claim */
938         req = usb_ep_alloc_request(ep, 0);
939         if (!req) {
940                 result = -EIO;
941                 goto err_disable_out_ep;
942         }
943
944         req->complete = thor_rx_tx_complete;
945         dev->out_req = req;
946         /* ACM control EP */
947         ep = dev->int_ep;
948         d = ep_desc(gadget, &hs_int_desc, &fs_int_desc);
949         debug("(d)bEndpointAddress: 0x%x\n", d->bEndpointAddress);
950
951         result = usb_ep_enable(ep, d);
952         if (result)
953                 goto err;
954
955         ep->driver_data = cdev; /* claim */
956
957         return 0;
958
959  err_disable_out_ep:
960         usb_ep_disable(dev->out_ep);
961
962  err_free_in_req:
963         free_ep_req(dev->in_ep, dev->in_req);
964         dev->in_req = NULL;
965
966  err_disable_in_ep:
967         usb_ep_disable(dev->in_ep);
968
969  err:
970         return result;
971 }
972
973 static int thor_func_set_alt(struct usb_function *f,
974                              unsigned intf, unsigned alt)
975 {
976         struct thor_dev *dev = thor_func->dev;
977         int result;
978
979         debug("%s: func: %s intf: %d alt: %d\n",
980               __func__, f->name, intf, alt);
981
982         switch (intf) {
983         case 0:
984                 debug("ACM INTR interface\n");
985                 break;
986         case 1:
987                 debug("Communication Data interface\n");
988                 result = thor_eps_setup(f);
989                 if (result)
990                         pr_err("%s: EPs setup failed!\n", __func__);
991                 dev->configuration_done = 1;
992                 break;
993         }
994
995         return 0;
996 }
997
998 static int thor_func_init(struct usb_configuration *c)
999 {
1000         struct f_thor *f_thor;
1001         int status;
1002
1003         debug("%s: cdev: 0x%p\n", __func__, c->cdev);
1004
1005         f_thor = memalign(CONFIG_SYS_CACHELINE_SIZE, sizeof(*f_thor));
1006         if (!f_thor)
1007                 return -ENOMEM;
1008
1009         memset(f_thor, 0, sizeof(*f_thor));
1010
1011         f_thor->usb_function.name = "f_thor";
1012         f_thor->usb_function.bind = thor_func_bind;
1013         f_thor->usb_function.unbind = thor_unbind;
1014         f_thor->usb_function.setup = thor_func_setup;
1015         f_thor->usb_function.set_alt = thor_func_set_alt;
1016         f_thor->usb_function.disable = thor_func_disable;
1017
1018         status = usb_add_function(c, &f_thor->usb_function);
1019         if (status)
1020                 free(f_thor);
1021
1022         return status;
1023 }
1024
1025 int thor_add(struct usb_configuration *c)
1026 {
1027         debug("%s:\n", __func__);
1028         return thor_func_init(c);
1029 }
1030
1031 DECLARE_GADGET_BIND_CALLBACK(usb_dnl_thor, thor_add);