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