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