Setting up repository
[linux-libre-firmware.git] / carl9170fw / carlfw / usb / usb.c
1 /*
2  * carl9170 firmware - used by the ar9170 wireless device
3  *
4  * USB Controller
5  *
6  * Copyright (c) 2000-2005  ZyDAS Technology Corporation
7  * Copyright (c) 2007-2009 Atheros Communications, Inc.
8  * Copyright    2009    Johannes Berg <johannes@sipsolutions.net>
9  * Copyright 2009-2011  Christian Lamparter <chunkeey@googlemail.com>
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License along
22  * with this program; if not, write to the Free Software Foundation, Inc.,
23  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24  */
25 #include "carl9170.h"
26 #include "usb.h"
27 #include "printf.h"
28 #include "rom.h"
29
30 /*
31  * NB: The firmware has to write into these structures
32  * so don't try to make them "const".
33  */
34
35 static struct ar9170_usb_config usb_config_highspeed = {
36         .cfg = {
37                 .bLength = USB_DT_CONFIG_SIZE,
38                 .bDescriptorType = USB_DT_CONFIG,
39                 .wTotalLength = cpu_to_le16(sizeof(usb_config_highspeed)),
40                 .bNumInterfaces = 1,
41                 .bConfigurationValue = 1,
42                 .iConfiguration = 0,
43                 .bmAttributes = USB_CONFIG_ATT_ONE |
44 #ifdef CONFIG_CARL9170FW_WOL
45                                 USB_CONFIG_ATT_WAKEUP |
46 #endif /* CONFIG_CARL9170FW_WOL */
47                                 0,
48                 .bMaxPower = 0xfa, /* 500 mA */
49         },
50
51         .intf = {
52                 .bLength = USB_DT_INTERFACE_SIZE,
53                 .bDescriptorType = USB_DT_INTERFACE,
54                 .bInterfaceNumber = 0,
55                 .bAlternateSetting = 0,
56                 .bNumEndpoints = AR9170_USB_NUM_EXTRA_EP,
57                 .bInterfaceClass = USB_CLASS_VENDOR_SPEC,
58                 .bInterfaceSubClass = USB_SUBCLASS_VENDOR_SPEC,
59                 .bInterfaceProtocol = 0,
60                 .iInterface = 0,
61         },
62
63         .ep = {
64                 {       /* EP 1 */
65                         .bLength = USB_DT_ENDPOINT_SIZE,
66                         .bDescriptorType = USB_DT_ENDPOINT,
67                         .bEndpointAddress = USB_DIR_OUT | AR9170_USB_EP_TX,
68                         .bmAttributes = USB_ENDPOINT_XFER_BULK,
69                         .wMaxPacketSize = cpu_to_le16(512),
70                         .bInterval = 0,
71                 },
72
73                 {       /* EP 2 */
74                         .bLength = USB_DT_ENDPOINT_SIZE,
75                         .bDescriptorType = USB_DT_ENDPOINT,
76                         .bEndpointAddress = USB_DIR_IN | AR9170_USB_EP_RX,
77                         .bmAttributes = USB_ENDPOINT_XFER_BULK,
78                         .wMaxPacketSize = cpu_to_le16(512),
79                         .bInterval = 0,
80                 },
81
82                 {       /* EP 3 */
83                         .bLength = USB_DT_ENDPOINT_SIZE,
84                         .bDescriptorType = USB_DT_ENDPOINT,
85                         .bEndpointAddress = USB_DIR_IN | AR9170_USB_EP_IRQ,
86                         .bmAttributes = USB_ENDPOINT_XFER_INT,
87                         .wMaxPacketSize = cpu_to_le16(64),
88                         .bInterval = 1,
89                 },
90
91                 {       /* EP 4 */
92                         .bLength = USB_DT_ENDPOINT_SIZE,
93                         .bDescriptorType = USB_DT_ENDPOINT,
94                         .bEndpointAddress = USB_DIR_OUT | AR9170_USB_EP_CMD,
95                         .bmAttributes = USB_ENDPOINT_XFER_INT,
96                         .wMaxPacketSize = cpu_to_le16(64),
97                         .bInterval = 1,
98                 },
99         },
100 };
101
102 static struct ar9170_usb_config usb_config_fullspeed = {
103         .cfg = {
104                 .bLength = USB_DT_CONFIG_SIZE,
105                 .bDescriptorType = USB_DT_CONFIG,
106                 .wTotalLength = cpu_to_le16(sizeof(usb_config_fullspeed)),
107                 .bNumInterfaces = 1,
108                 .bConfigurationValue = 1,
109                 .iConfiguration = 0,
110                 .bmAttributes = USB_CONFIG_ATT_ONE |
111 #ifdef CONFIG_CARL9170FW_WOL
112                                 USB_CONFIG_ATT_WAKEUP |
113 #endif /* CONFIG_CARL9170FW_WOL */
114                                 0,
115                 .bMaxPower = 0xfa, /* 500 mA */
116         },
117
118         .intf = {
119                 .bLength = USB_DT_INTERFACE_SIZE,
120                 .bDescriptorType = USB_DT_INTERFACE,
121                 .bInterfaceNumber = 0,
122                 .bAlternateSetting = 0,
123                 .bNumEndpoints = AR9170_USB_NUM_EXTRA_EP,
124                 .bInterfaceClass = USB_CLASS_VENDOR_SPEC,
125                 .bInterfaceSubClass = USB_SUBCLASS_VENDOR_SPEC,
126                 .bInterfaceProtocol = 0,
127                 .iInterface = 0,
128         },
129
130         .ep = {
131                 {       /* EP 1 */
132                         .bLength = USB_DT_ENDPOINT_SIZE,
133                         .bDescriptorType = USB_DT_ENDPOINT,
134                         .bEndpointAddress = USB_DIR_OUT | AR9170_USB_EP_TX,
135                         .bmAttributes = USB_ENDPOINT_XFER_BULK,
136                         .wMaxPacketSize = cpu_to_le16(64),
137                         .bInterval = 0,
138                 },
139
140                 {       /* EP 2 */
141                         .bLength = USB_DT_ENDPOINT_SIZE,
142                         .bDescriptorType = USB_DT_ENDPOINT,
143                         .bEndpointAddress = USB_DIR_IN | AR9170_USB_EP_RX,
144                         .bmAttributes = USB_ENDPOINT_XFER_BULK,
145                         .wMaxPacketSize = cpu_to_le16(64),
146                         .bInterval = 0,
147                 },
148
149                 {       /* EP 3 */
150                         .bLength = USB_DT_ENDPOINT_SIZE,
151                         .bDescriptorType = USB_DT_ENDPOINT,
152                         .bEndpointAddress = USB_DIR_IN | AR9170_USB_EP_IRQ,
153                         .bmAttributes = USB_ENDPOINT_XFER_INT,
154                         .wMaxPacketSize = cpu_to_le16(64),
155                         .bInterval = 1,
156                 },
157
158                 {       /* EP 4 */
159                         .bLength = USB_DT_ENDPOINT_SIZE,
160                         .bDescriptorType = USB_DT_ENDPOINT,
161                         .bEndpointAddress = USB_DIR_OUT | AR9170_USB_EP_CMD,
162                         .bmAttributes = USB_ENDPOINT_XFER_INT,
163                         .wMaxPacketSize = cpu_to_le16(64),
164                         .bInterval = 1,
165                 },
166         },
167 };
168
169 void usb_reset_eps(void)
170 {
171         unsigned int i;
172
173         /* clear all EPs' toggle bit */
174         for (i = 1; i < __AR9170_USB_NUM_MAX_EP; i++) {
175                 usb_set_input_ep_toggle(i);
176                 usb_clear_input_ep_toggle(i);
177                 usb_clear_input_ep_stall(i);
178         }
179
180         /*
181          * NB: I've no idea why this cannot be integrated into the
182          * previous loop?
183          */
184         for (i = 1; i < __AR9170_USB_NUM_MAX_EP; i++) {
185                 usb_set_output_ep_toggle(i);
186                 usb_clear_output_ep_toggle(i);
187                 usb_clear_output_ep_stall(i);
188         }
189 }
190
191 static void usb_pta_init(void)
192 {
193         unsigned int usb_dma_ctrl = 0;
194         /* Set PTA mode to USB */
195         andl(AR9170_PTA_REG_DMA_MODE_CTRL,
196                 ~AR9170_PTA_DMA_MODE_CTRL_DISABLE_USB);
197
198         /* Do a software reset to PTA component */
199         orl(AR9170_PTA_REG_DMA_MODE_CTRL, AR9170_PTA_DMA_MODE_CTRL_RESET);
200         andl(AR9170_PTA_REG_DMA_MODE_CTRL, ~AR9170_PTA_DMA_MODE_CTRL_RESET);
201
202         if (usb_detect_highspeed()) {
203                 fw.usb.os_cfg_desc = &usb_config_fullspeed;
204                 fw.usb.cfg_desc = &usb_config_highspeed;
205
206                 /* 512 Byte DMA transfers */
207                 usb_dma_ctrl |= AR9170_USB_DMA_CTL_HIGH_SPEED;
208         } else {
209                 fw.usb.cfg_desc = &usb_config_fullspeed;
210                 fw.usb.os_cfg_desc = &usb_config_highspeed;
211         }
212
213 #ifdef CONFIG_CARL9170FW_USB_UP_STREAM
214 # if (CONFIG_CARL9170FW_RX_FRAME_LEN == 4096)
215         usb_dma_ctrl |= AR9170_USB_DMA_CTL_UP_STREAM_4K;
216 # elif (CONFIG_CARL9170FW_RX_FRAME_LEN == 8192)
217         usb_dma_ctrl |= AR9170_USB_DMA_CTL_UP_STREAM_8K;
218 # elif (CONFIG_CARL9170FW_RX_FRAME_LEN == 16384)
219         usb_dma_ctrl |= AR9170_USB_DMA_CTL_UP_STREAM_16K;
220 # elif (CONFIG_CARL9170FW_RX_FRAME_LEN == 32768)
221         usb_dma_ctrl |= AR9170_USB_DMA_CTL_UP_STREAM_32K;
222 # else
223 #       error "Invalid AR9170_RX_FRAME_LEN setting"
224 # endif
225
226 #else /* CONFIG_CARL9170FW_USB_UP_STREAM */
227         usb_dma_ctrl |= AR9170_USB_DMA_CTL_UP_PACKET_MODE;
228 #endif /* CONFIG_CARL9170FW_USB_UP_STREAM */
229
230 #ifdef CONFIG_CARL9170FW_USB_DOWN_STREAM
231         /* Enable down stream mode */
232         usb_dma_ctrl |= AR9170_USB_DMA_CTL_DOWN_STREAM;
233 #endif /* CONFIG_CARL9170FW_USB_DOWN_STREAM */
234
235 #ifdef CONFIG_CARL9170FW_USB_UP_STREAM
236         /* Set the up stream mode maximum aggregate number */
237         set(AR9170_USB_REG_MAX_AGG_UPLOAD, 4);
238
239         /*
240          * Set the up stream mode timeout value.
241          * NB: The vendor driver (otus) set 0x80?
242          */
243         set(AR9170_USB_REG_UPLOAD_TIME_CTL, 0x80);
244 #endif /* CONFIG_CARL9170FW_USB_UP_STREAM */
245
246         /* Enable up stream and down stream */
247         usb_dma_ctrl |= AR9170_USB_DMA_CTL_ENABLE_TO_DEVICE |
248             AR9170_USB_DMA_CTL_ENABLE_FROM_DEVICE;
249
250         set(AR9170_USB_REG_DMA_CTL, usb_dma_ctrl);
251 }
252
253 void usb_init(void)
254 {
255         usb_pta_init();
256
257         fw.usb.config = 1;
258         /*
259          * The fw structure is always initialized with "0"
260          * during boot(); No need to waste precious bytes here.
261          *
262          * fw.usb.interface_setting = 0;
263          * fw.usb.alternate_interface_setting = 0;
264          * fw.usb.device_feature = 0;
265          */
266
267 #ifdef CONFIG_CARL9170FW_WOL
268         fw.usb.device_feature |= USB_DEVICE_REMOTE_WAKEUP;
269         usb_enable_remote_wakeup();
270 #endif /* CONFIG_CARL9170FW_WOL */
271 }
272
273 #define GET_ARRAY(a, o) ((uint32_t *) (((unsigned long) data) + offset))
274
275 static void usb_ep0rx_data(const void *data, const unsigned int len)
276 {
277         unsigned int offset;
278         uint32_t value;
279
280         BUG_ON(len > AR9170_USB_EP_CTRL_MAX);
281         BUILD_BUG_ON(len > AR9170_USB_EP_CTRL_MAX);
282
283         for (offset = 0; offset < ((len + 3) & ~3); offset += 4) {
284                 value = get(AR9170_USB_REG_EP0_DATA);
285                 memcpy(GET_ARRAY(data, offset), &value,
286                        min(len - offset, (unsigned int)4));
287         }
288 }
289
290 static int usb_ep0tx_data(const void *data, const unsigned int len)
291 {
292         unsigned int offset = 0, block, last_block = 0;
293         uint32_t value;
294
295         BUG_ON(len > AR9170_USB_EP_CTRL_MAX);
296         BUILD_BUG_ON(len > AR9170_USB_EP_CTRL_MAX);
297
298         block = min(len, (unsigned int) 4);
299         offset = 0;
300         while (offset < len) {
301
302                 if (last_block != block || block < 4)
303                         setb(AR9170_USB_REG_FIFO_SIZE, (1 << block) - 1);
304
305                 memcpy(&value, GET_ARRAY(data, offset), block);
306
307                 set(AR9170_USB_REG_EP0_DATA, value);
308
309                 offset += block;
310                 last_block = block = min(len - offset, (unsigned int) 4);
311         }
312
313         setb(AR9170_USB_REG_FIFO_SIZE, 0xf);
314
315         /* this will push the data to the host */
316         return 1;
317 }
318 #undef GET_ARRAY
319
320 #ifdef CONFIG_CARL9170FW_USB_STANDARD_CMDS
321 static int usb_get_status(const struct usb_ctrlrequest *ctrl)
322 {
323         __le16 status = cpu_to_le16(fw.usb.device_feature);
324
325         if ((ctrl->bRequestType & USB_DIR_MASK) != USB_DIR_IN)
326                 return -1;
327
328         switch (ctrl->bRequestType & USB_RECIP_MASK) {
329         case USB_RECIP_DEVICE:
330                 status &= cpu_to_le16(~USB_DEVICE_SELF_POWERED);
331                 status &= cpu_to_le16(~USB_DEVICE_REMOTE_WAKEUP);
332                 break;
333
334         case USB_RECIP_INTERFACE:
335                 /* USB spec: This is reserved for future use. */
336                 status = cpu_to_le16(0);
337                 break;
338
339         case USB_RECIP_ENDPOINT: {
340                 unsigned int ep = le16_to_cpu(ctrl->wIndex) & 0xf;
341                 unsigned int dir = le16_to_cpu(ctrl->wIndex) & USB_DIR_MASK;
342
343                 if (ep == 0) {
344                         status = !!(getb(AR9170_USB_REG_CX_CONFIG_STATUS) & BIT(2));
345                 } else {
346                         unsigned int addr;
347
348                         if (dir == USB_DIR_IN)
349                                 addr = AR9170_USB_REG_EP_IN_MAX_SIZE_HIGH;
350                         else
351                                 addr = AR9170_USB_REG_EP_OUT_MAX_SIZE_HIGH;
352
353                         addr += (ep << 1);
354
355                         /*
356                          * AR9170_USB_EP_OUT_STALL == AR9170_USB_EP_IN_STALL
357                          * so it doesn't matter which one we use
358                          */
359                         status = !!(getb(addr) & AR9170_USB_EP_OUT_STALL);
360                 }
361                 break;
362                 }
363         case USB_RECIP_OTHER:
364         default:
365                 break;
366         }
367
368         return usb_ep0tx_data((const void *) &status, sizeof(status));
369 }
370
371 static int usb_get_string_desc(const struct usb_ctrlrequest *ctrl)
372 {
373         const struct usb_string_descriptor *string_desc = NULL;
374
375         switch (le16_to_cpu(ctrl->wValue) & 0xff) {
376         case 0x00:
377                 string_desc = (const struct usb_string_descriptor *)
378                         rom.hw.usb.string0_desc;
379                 break;
380
381         case 0x10:
382                 string_desc = (const struct usb_string_descriptor *)
383                         rom.hw.usb.string1_desc;
384                 break;
385
386         case 0x20:
387                 string_desc = (const struct usb_string_descriptor *)
388                         rom.hw.usb.string2_desc;
389                 break;
390
391         case 0x30:
392                 string_desc = (const struct usb_string_descriptor *)
393                         rom.hw.usb.string3_desc;
394                 break;
395
396         default:
397                 break;
398         }
399
400         if (string_desc)
401                 return usb_ep0tx_data(string_desc, string_desc->bLength);
402
403         return -1;
404 }
405
406 static int usb_get_device_desc(const struct usb_ctrlrequest *ctrl __unused)
407 {
408         return usb_ep0tx_data(&rom.hw.usb.device_desc,
409                               rom.hw.usb.device_desc.bLength);
410 }
411
412 static int usb_get_config_desc(const struct usb_ctrlrequest *ctrl __unused)
413 {
414         fw.usb.cfg_desc->cfg.bDescriptorType = USB_DT_CONFIG;
415
416         return usb_ep0tx_data(fw.usb.cfg_desc,
417                 le16_to_cpu(fw.usb.cfg_desc->cfg.wTotalLength));
418 }
419
420 #ifdef CONFIG_CARL9170FW_USB_MODESWITCH
421 static int usb_get_otherspeed_desc(const struct usb_ctrlrequest *ctrl __unused)
422 {
423
424         fw.usb.os_cfg_desc->cfg.bDescriptorType = USB_DT_OTHER_SPEED_CONFIG;
425
426         return usb_ep0tx_data(fw.usb.os_cfg_desc,
427                 le16_to_cpu(fw.usb.os_cfg_desc->cfg.wTotalLength));
428 }
429 #endif /* CONFIG_CARL9170FW_USB_MODESWITCH */
430
431 static int usb_get_qualifier_desc(const struct usb_ctrlrequest *ctrl __unused)
432 {
433         struct usb_qualifier_descriptor qual;
434
435         /*
436          * The qualifier descriptor shares some structural details
437          * with the main device descriptor.
438          */
439
440         memcpy(&qual, &rom.hw.usb.device_desc, sizeof(qual));
441
442         /* (Re)-Initialize fields */
443         qual.bDescriptorType = USB_DT_DEVICE_QUALIFIER;
444         qual.bLength = sizeof(qual);
445         qual.bNumConfigurations = rom.hw.usb.device_desc.bNumConfigurations;
446         qual.bRESERVED = 0;
447
448         return usb_ep0tx_data(&qual, qual.bLength);
449 }
450
451 #define USB_CHECK_REQTYPE(ctrl, recip, dir)                     \
452         (((ctrl->bRequestType & USB_RECIP_MASK) != recip) ||    \
453          ((ctrl->bRequestType & USB_DIR_MASK) != dir))
454
455 static int usb_get_descriptor(const struct usb_ctrlrequest *ctrl)
456 {
457         int status = -1;
458
459         if (USB_CHECK_REQTYPE(ctrl, USB_RECIP_DEVICE, USB_DIR_IN))
460                 return status;
461
462         switch (le16_to_cpu(ctrl->wValue) >> 8) {
463         case USB_DT_DEVICE:
464                 status = usb_get_device_desc(ctrl);
465                 break;
466
467         case USB_DT_CONFIG:
468                 status = usb_get_config_desc(ctrl);
469                 break;
470
471         case USB_DT_STRING:
472                 status = usb_get_string_desc(ctrl);
473                 break;
474
475         case USB_DT_INTERFACE:
476                 break;
477
478         case USB_DT_ENDPOINT:
479                 break;
480
481         case USB_DT_DEVICE_QUALIFIER:
482                 status = usb_get_qualifier_desc(ctrl);
483                 break;
484
485 #ifdef CONFIG_CARL9170FW_USB_MODESWITCH
486         case USB_DT_OTHER_SPEED_CONFIG:
487                 status = usb_get_otherspeed_desc(ctrl);
488                 break;
489 #endif /* CONFIG_CARL9170FW_USB_MODESWITCH */
490         default:
491                 break;
492
493         }
494
495         return status;
496 }
497
498 static int usb_get_configuration(const struct usb_ctrlrequest *ctrl)
499 {
500         if (USB_CHECK_REQTYPE(ctrl, USB_RECIP_DEVICE, USB_DIR_IN))
501                 return -1;
502
503         return usb_ep0tx_data(&fw.usb.config, fw.usb.config);
504 }
505
506 static int usb_set_configuration(const struct usb_ctrlrequest *ctrl)
507 {
508         unsigned int config;
509
510         if (USB_CHECK_REQTYPE(ctrl, USB_RECIP_DEVICE, USB_DIR_OUT))
511                 return -1;
512
513         config = le16_to_cpu(ctrl->wValue);
514         switch (config) {
515         case 0:
516                 /* Disable Device */
517                 andb(AR9170_USB_REG_DEVICE_ADDRESS,
518                       (uint8_t) ~(AR9170_USB_DEVICE_ADDRESS_CONFIGURE));
519         case 1:
520                 fw.usb.config = config;
521
522 #ifdef CONFIG_CARL9170FW_USB_MODESWITCH
523                 if (usb_detect_highspeed()) {
524                         /* High Speed Configuration */
525                         usb_init_highspeed_fifo_cfg();
526                 } else {
527                         /* Full Speed Configuration */
528                         usb_init_fullspeed_fifo_cfg();
529                 }
530                 /* usb_pta_init() ? */
531                 break;
532 #endif /* CONFIG_CARL9170FW_USB_MODESWITCH */
533
534                 usb_reset_eps();
535                 orb(AR9170_USB_REG_DEVICE_ADDRESS,
536                     (AR9170_USB_DEVICE_ADDRESS_CONFIGURE));
537
538                 usb_enable_global_int();
539                 usb_trigger_out();
540                 return 1;
541
542         default:
543                 return -1;
544         }
545 }
546
547 static int usb_set_address(const struct usb_ctrlrequest *ctrl)
548 {
549         unsigned int address;
550
551         if (USB_CHECK_REQTYPE(ctrl, USB_RECIP_DEVICE, USB_DIR_OUT))
552                 return -1;
553
554         address = le16_to_cpu(ctrl->wValue);
555
556         /*
557          * The original firmware used 0x100 (which is, of course,
558          * too big to fit into uint8_t).
559          * However based on the available information (hw.h), BIT(7)
560          * is used as some sort of flag and should not be
561          * part of the device address.
562          */
563         if (address >= BIT(7))
564                 return -1;
565
566         setb(AR9170_USB_REG_DEVICE_ADDRESS, (uint8_t) address);
567         return 1;
568 }
569
570 static int usb_get_interface(const struct usb_ctrlrequest *ctrl)
571 {
572         if (USB_CHECK_REQTYPE(ctrl, USB_RECIP_INTERFACE, USB_DIR_IN))
573                 return -1;
574
575         if (usb_configured() == false)
576                 return -1;
577
578         switch (fw.usb.config) {
579         case 1:
580                 break;
581
582         default:
583                 return -1;
584         }
585
586         return usb_ep0tx_data(&fw.usb.alternate_interface_setting, 1);
587 }
588
589 static int usb_manipulate_feature(const struct usb_ctrlrequest *ctrl, bool __unused clear)
590 {
591         unsigned int feature;
592
593         if ((ctrl->bRequestType & USB_DIR_MASK) != USB_DIR_OUT)
594                 return -1;
595
596         if (usb_configured() == false)
597                 return -1;
598
599         feature = le16_to_cpu(ctrl->wValue);
600
601         switch (ctrl->bRequestType & USB_RECIP_MASK) {
602         case USB_RECIP_DEVICE: {
603 #ifdef CONFIG_CARL9170FW_WOL
604                 if (feature & USB_DEVICE_REMOTE_WAKEUP) {
605                         if (clear)
606                                 usb_disable_remote_wakeup();
607                         else
608                                 usb_enable_remote_wakeup();
609                 }
610 #endif /* CONFIG_CARL9170FW_WOL */
611
612                 if (clear)
613                         fw.usb.device_feature &= ~feature;
614                 else
615                         fw.usb.device_feature |= feature;
616
617
618                 break;
619                 }
620
621         case USB_RECIP_ENDPOINT: {
622                 unsigned int ep, dir;
623
624                 ep = le16_to_cpu(ctrl->wIndex) & 0xf;
625                 dir = le16_to_cpu(ctrl->wIndex) & USB_DIR_MASK;
626                 if (ep == 0) {
627                         /* According to the spec, EP cannot be stopped this way. */
628                         return -1;
629                 } else {
630                         unsigned int addr;
631
632                         if (dir == USB_DIR_IN)
633                                 addr = AR9170_USB_REG_EP_IN_MAX_SIZE_HIGH;
634                         else
635                                 addr = AR9170_USB_REG_EP_OUT_MAX_SIZE_HIGH;
636
637                         addr += (ep << 1);
638
639                         if (clear)
640                                 andb(addr, ~AR9170_USB_EP_OUT_STALL);
641                         else
642                                 orb(addr, AR9170_USB_EP_OUT_STALL);
643                 }
644                 break;
645                 }
646
647         case USB_RECIP_INTERFACE:
648                 /*
649                  * the current USB Specification Revision 2
650                  * specifies no interface features.
651                  */
652
653         default:
654                 return -1;
655         }
656
657         return 1;
658 }
659
660 #ifdef CONFIG_CARL9170FW_USB_MODESWITCH
661 static int usb_set_interface(const struct usb_ctrlrequest *ctrl)
662 {
663         unsigned int intf, alt_intf;
664         if (USB_CHECK_REQTYPE(ctrl, USB_RECIP_INTERFACE, USB_DIR_OUT))
665                 return -1;
666
667         if (usb_configured() == false)
668                 return -1;
669
670         intf = le16_to_cpu(ctrl->wIndex);
671         alt_intf = le16_to_cpu(ctrl->wValue);
672
673         switch (intf) {
674         case 0:
675                 if (alt_intf != fw.usb.cfg_desc->intf.bAlternateSetting)
676                         return -1;
677
678                 fw.usb.interface_setting = (uint8_t) intf;
679                 fw.usb.alternate_interface_setting = (uint8_t) alt_intf;
680                 if (usb_detect_highspeed())
681                         usb_init_highspeed_fifo_cfg();
682                 else
683                         usb_init_fullspeed_fifo_cfg();
684
685                 usb_reset_eps();
686                 usb_enable_global_int();
687                 usb_trigger_out();
688                 return 1;
689
690         default:
691                 return -1;
692         }
693 }
694 #endif /* CONFIG_CARL9170FW_USB_MODESWITCH */
695 #endif /* CONFIG_CARL9170FW_USB_STANDARD_CMDS */
696
697 static int usb_standard_command(const struct usb_ctrlrequest *ctrl __unused)
698 {
699         int status = -1;
700
701 #ifdef CONFIG_CARL9170FW_USB_STANDARD_CMDS
702         switch (ctrl->bRequest) {
703         case USB_REQ_GET_STATUS:
704                 status = usb_get_status(ctrl);
705                 break;
706
707         case USB_REQ_CLEAR_FEATURE:
708         case USB_REQ_SET_FEATURE:
709                 status = usb_manipulate_feature(ctrl, ctrl->bRequest == USB_REQ_CLEAR_FEATURE);
710                 break;
711
712         case USB_REQ_SET_ADDRESS:
713                 status = usb_set_address(ctrl);
714                 break;
715
716         case USB_REQ_GET_DESCRIPTOR:
717                 status = usb_get_descriptor(ctrl);
718                 break;
719
720         case USB_REQ_SET_DESCRIPTOR:
721                 break;
722
723         case USB_REQ_GET_CONFIGURATION:
724                 status = usb_get_configuration(ctrl);
725                 break;
726
727         case USB_REQ_SET_CONFIGURATION:
728                 status = usb_set_configuration(ctrl);
729                 break;
730
731         case USB_REQ_GET_INTERFACE:
732                 status = usb_get_interface(ctrl);
733                 break;
734
735         case USB_REQ_SET_INTERFACE:
736 #ifdef CONFIG_CARL9170FW_USB_MODESWITCH
737                 status = usb_set_interface(ctrl);
738 #endif /* CONFIG_CARL9170FW_USB_MODESWITCH */
739                 break;
740
741         case USB_REQ_SYNCH_FRAME:
742                 break;
743
744         default:
745                 break;
746
747         }
748 #endif /* CONFIG_CARL9170FW_USB_STANDARD_CMDS */
749
750         return status;
751 }
752
753 static int usb_class_command(const struct usb_ctrlrequest *ctrl __unused)
754 {
755         return -1;
756 }
757
758 static int usb_vendor_command(const struct usb_ctrlrequest *ctrl __unused)
759 {
760         /*
761          * Note: Firmware upload/boot is not implemented.
762          * It's impossible to replace the current image
763          * in place.
764          */
765
766         return -1;
767 }
768
769 #undef USB_CHECK_TYPE
770
771 void usb_ep0setup(void)
772 {
773         struct usb_ctrlrequest ctrl;
774         int status = -1;
775         usb_ep0rx_data(&ctrl, sizeof(ctrl));
776
777         switch (ctrl.bRequestType & USB_TYPE_MASK) {
778         case USB_TYPE_STANDARD:
779                 status = usb_standard_command(&ctrl);
780                 break;
781
782         case USB_TYPE_CLASS:
783                 status = usb_class_command(&ctrl);
784                 break;
785
786         case USB_TYPE_VENDOR:
787                 status = usb_vendor_command(&ctrl);
788                 break;
789
790         default:
791                 break;
792
793         }
794
795         if (status < 0)
796                 fw.usb.ep0_action |= CARL9170_EP0_STALL;
797 #ifdef CONFIG_CARL9170FW_USB_STANDARD_CMDS
798         if (status > 0)
799                 fw.usb.ep0_action |= CARL9170_EP0_TRIGGER;
800 #endif /* CONFIG_CARL9170FW_USB_STANDARD_CMDS */
801 }
802
803 void usb_ep0rx(void)
804 {
805         if (BUG_ON(!fw.usb.ep0_txrx_buffer || !fw.usb.ep0_txrx_len))
806                 return ;
807
808         usb_ep0rx_data(fw.usb.ep0_txrx_buffer, fw.usb.ep0_txrx_len);
809         fw.usb.ep0_txrx_pos = fw.usb.ep0_txrx_len;
810 }
811
812 void usb_ep0tx(void)
813 {
814         if (BUG_ON(!fw.usb.ep0_txrx_buffer || !fw.usb.ep0_txrx_len))
815                 return ;
816
817         usb_ep0tx_data(fw.usb.ep0_txrx_buffer, fw.usb.ep0_txrx_len);
818         fw.usb.ep0_txrx_pos = fw.usb.ep0_txrx_len;
819 }