hif/usb_api: remove dup code - _fw_usbfifo_recv_command
[open-ath9k-htc-firmware.git] / target_firmware / magpie_fw_dev / target / hif / usb_api_main_patch.c
1 /* shared patches for k2 and magpie */
2
3 #include "usb_defs.h"
4 #include "usb_type.h"
5 #include "usb_pre.h"
6 #include "usb_extr.h"
7 #include "usb_std.h"
8 #include "reg_defs.h"
9 #include "athos_api.h"
10 #include "usbfifo_api.h"
11
12 #include "sys_cfg.h"
13
14 #define USB_EP4_MAX_PKT_SIZE bUSB_EP_MAX_PKT_SIZE_64
15 #define USB_EP3_MAX_PKT_SIZE bUSB_EP_MAX_PKT_SIZE_64
16
17 extern USB_FIFO_CONFIG usbFifoConf;
18 extern Action eUsbCxFinishAction;
19 extern void _fw_usb_suspend_reboot();
20
21 typedef void (* USBFIFO_recv_command)(VBUF *cmd);
22 USBFIFO_recv_command m_origUsbfifoRecvCmd = NULL;
23
24 void _fw_usbfifo_recv_command(VBUF *buf)
25 {
26         uint8_t *cmd_data;
27         uint32_t tmp;
28
29         cmd_data = (uint8_t *)(buf->desc_list->buf_addr +
30                                 buf->desc_list->data_offset);
31         tmp = *((uint32_t *)cmd_data);
32         if (tmp == 0xFFFFFFFF)
33                 _fw_usb_suspend_reboot();
34         else
35                 m_origUsbfifoRecvCmd(buf);
36 }
37
38 void _fw_usbfifo_init(USB_FIFO_CONFIG *pConfig)
39 {
40         m_origUsbfifoRecvCmd = pConfig->recv_command;
41
42         usbFifoConf.get_command_buf = pConfig->get_command_buf;
43         usbFifoConf.recv_command    = _fw_usbfifo_recv_command;
44         usbFifoConf.get_event_buf   = pConfig->get_event_buf;
45         usbFifoConf.send_event_done = pConfig->send_event_done;
46 }
47
48 void cold_reboot(void)
49 {
50         A_PRINTF("Cold reboot initiated.");
51 #if defined(PROJECT_MAGPIE)
52         HAL_WORD_REG_WRITE(WATCH_DOG_MAGIC_PATTERN_ADDR, 0);
53 #elif defined(PROJECT_K2)
54         HAL_WORD_REG_WRITE(MAGPIE_REG_RST_STATUS_ADDR, 0);
55 #endif /* #if defined(PROJECT_MAGPIE) */
56         A_USB_JUMP_BOOT();
57 }
58
59 /*
60  * support more than 64 bytes command on ep3
61  */
62 void usb_status_in_patch(void)
63 {
64         uint16_t count;
65         uint16_t remainder;
66         uint16_t reg_buf_len;
67         static uint16_t buf_len;
68         static VBUF *evntbuf = NULL;
69         static volatile uint32_t *regaddr;
70         static BOOLEAN cmd_is_new = TRUE;
71         BOOLEAN cmd_end = FALSE;
72
73         if (cmd_is_new) {
74                 evntbuf = usbFifoConf.get_event_buf();
75                 if (evntbuf != NULL) {
76                         regaddr = (uint32_t *)VBUF_GET_DATA_ADDR(evntbuf);
77                         buf_len = evntbuf->buf_length;
78                 } else {
79                         mUSB_STATUS_IN_INT_DISABLE();
80                         return;
81                 }
82
83                 cmd_is_new = FALSE;
84         }
85
86         if (buf_len > USB_EP3_MAX_PKT_SIZE) {
87                 reg_buf_len = USB_EP3_MAX_PKT_SIZE;
88                 buf_len -= USB_EP3_MAX_PKT_SIZE;
89         }
90         /* TODO: 64 bytes...
91          * controller supposed will take care of zero-length? */
92         else {
93                 reg_buf_len = buf_len;
94                 cmd_end = TRUE;
95         }
96
97         /* INT use EP3 */
98         for (count = 0; count < (reg_buf_len / 4); count++)
99         {
100                 USB_WORD_REG_WRITE(ZM_EP3_DATA_OFFSET, *regaddr);
101                 regaddr++;
102         }
103
104         remainder = reg_buf_len % 4;
105
106         if (remainder) {
107                 switch(remainder) {
108                 case 3:
109                         USB_WORD_REG_WRITE(ZM_CBUS_FIFO_SIZE_OFFSET, 0x7);
110                         break;
111                 case 2:
112                         USB_WORD_REG_WRITE(ZM_CBUS_FIFO_SIZE_OFFSET, 0x3);
113                         break;
114                 case 1:
115                         USB_WORD_REG_WRITE(ZM_CBUS_FIFO_SIZE_OFFSET, 0x1);
116                         break;
117                 }
118
119                 USB_WORD_REG_WRITE(ZM_EP3_DATA_OFFSET, *regaddr);
120
121                 /* Restore CBus FIFO size to word size */
122                 USB_WORD_REG_WRITE(ZM_CBUS_FIFO_SIZE_OFFSET, 0xF);
123         }
124
125         mUSB_EP3_XFER_DONE();
126
127         if (evntbuf != NULL && cmd_end) {
128                 usbFifoConf.send_event_done(evntbuf);
129                 cmd_is_new = TRUE;
130         }
131 }
132
133 /*
134  * support more than 64 bytes command on ep4 
135  */
136 void usb_reg_out_patch(void)
137 {
138         uint16_t usbfifolen;
139         uint16_t ii;
140         uint32_t ep4_data;
141         static volatile uint32_t *regaddr;
142         static uint16_t cmd_len;
143         static VBUF *buf;
144         BOOLEAN cmd_is_last = FALSE;
145         static BOOLEAN cmd_is_new = TRUE;
146
147         /* get the size of this transcation */
148         usbfifolen = USB_BYTE_REG_READ(ZM_EP4_BYTE_COUNT_LOW_OFFSET);
149
150         if (usbfifolen > USB_EP4_MAX_PKT_SIZE) {
151                 A_PRINTF("EP4 FIFO Bug? Buffer is too big: %x\n", usbfifolen);
152                 cold_reboot();
153         }
154
155         /* check is command is new */
156         if(cmd_is_new) {
157
158                 buf = usbFifoConf.get_command_buf();
159                 cmd_len = 0;
160
161                 if(!buf) {
162                         A_PRINTF("%s: Filed to get new buffer.\n", __func__);
163                         goto err;
164                 }
165
166                 /* copy free, assignment buffer of the address */
167                 regaddr = (uint32_t *)buf->desc_list->buf_addr;
168
169                 cmd_is_new = FALSE;
170         }
171
172         /* just in case, suppose should not happen */
173         if(!buf)
174                 goto err;
175
176         /* if size is smaller, this is the last command!
177          * zero-length supposed should be set through 0x27/bit7->0x19/bit4, not here
178          */
179         if(usbfifolen < USB_EP4_MAX_PKT_SIZE)
180                 cmd_is_last = TRUE;
181
182         /* accumulate the size */
183         cmd_len += usbfifolen;
184
185         if (cmd_len > buf->desc_list->buf_size) {
186                 A_PRINTF("%s: Data length on EP4 FIFO is bigger as "
187                          "allocated buffer data! Drop it!\n", __func__);
188                 goto err;
189         }
190
191         /* round it to alignment */
192         if(usbfifolen % 4)
193                 usbfifolen = (usbfifolen >> 2) + 1;
194         else
195                 usbfifolen = usbfifolen >> 2;
196
197         /* retrieve the data from fifo */
198         for(ii = 0; ii < usbfifolen; ii++) {
199                 /* read fifo data out */
200                 ep4_data = USB_WORD_REG_READ(ZM_EP4_DATA_OFFSET);
201                 *regaddr = ep4_data;
202                 regaddr++;
203         }
204
205         /* if this is the last command, callback to HTC */
206         if (cmd_is_last) {
207                 buf->desc_list->next_desc = NULL;
208                 buf->desc_list->data_offset = 0;
209                 buf->desc_list->data_size = cmd_len;
210                 buf->desc_list->control = 0;
211                 buf->next_buf = NULL;
212                 buf->buf_length = cmd_len;
213
214                 usbFifoConf.recv_command(buf);
215
216                 cmd_is_new = TRUE;
217         }
218
219         goto done;
220 err:
221         /* we might get no command buffer here?
222          * but if we return here, the ep4 fifo will be lock out,
223          * so that we still read them out but just drop it? */
224         for(ii = 0; ii < usbfifolen; ii++)
225                 ep4_data = USB_WORD_REG_READ(ZM_EP4_DATA_OFFSET);
226
227 done:
228         /* mUSB_STATUS_IN_INT_ENABLE(); */
229         ;
230 }
231
232 /*
233  * usb1.1 ep6 fix
234  * TODO:
235  * - theoretically ep6 configured same way as ep1
236  * so, if there are some problems we should have it
237  * there too.
238  * - do we really need support usb1.1?
239  */
240 extern uint16_t         u8UsbConfigValue;
241 extern uint16_t         u8UsbInterfaceValue;
242 extern uint16_t         u8UsbInterfaceAlternateSetting;
243 extern SetupPacket      ControlCmd;
244 extern void             vUsbClrEPx(void);
245
246 #undef FS_C1_I0_A0_EP_NUMBER
247 #define FS_C1_I0_A0_EP_NUMBER 6
248
249 #define FS_C1_I0_A0_EP6_BLKSIZE    BLK512BYTE
250 #define FS_C1_I0_A0_EP6_BLKNO      DOUBLE_BLK
251 #define FS_C1_I0_A0_EP6_DIRECTION  DIRECTION_OUT
252 #define FS_C1_I0_A0_EP6_TYPE       TF_TYPE_BULK
253 #define FS_C1_I0_A0_EP6_MAX_PACKET 0x0040
254 #define FS_C1_I0_A0_EP6_bInterval  0
255
256 /* EP6 */
257 #define FS_C1_I0_A0_EP6_FIFO_START      \
258          (FS_C1_I0_A0_EP5_FIFO_START + FS_C1_I0_A0_EP5_FIFO_NO)
259 #define FS_C1_I0_A0_EP6_FIFO_NO         \
260          (FS_C1_I0_A0_EP6_BLKNO * FS_C1_I0_A0_EP6_BLKSIZE)
261 #define FS_C1_I0_A0_EP6_FIFO_CONFIG     \
262          (0x80 | ((FS_C1_I0_A0_EP6_BLKSIZE - 1) << 4) | \
263           ((FS_C1_I0_A0_EP6_BLKNO - 1) << 2) | FS_C1_I0_A0_EP6_TYPE)
264 #define FS_C1_I0_A0_EP6_FIFO_MAP        \
265          (((1 - FS_C1_I0_A0_EP6_DIRECTION) << 4) | EP6)
266 #define FS_C1_I0_A0_EP6_MAP             \
267          (FS_C1_I0_A0_EP6_FIFO_START | (FS_C1_I0_A0_EP6_FIFO_START << 4) | \
268           (MASK_F0 >> (4*FS_C1_I0_A0_EP6_DIRECTION)))
269
270 void vUSBFIFO_EP6Cfg_FS_patch(void)
271 {
272 #if (FS_C1_I0_A0_EP_NUMBER >= 6)
273         int i;
274
275         /* EP0X06 */
276         mUsbEPMap(EP6, FS_C1_I0_A0_EP6_MAP);
277         mUsbFIFOMap(FS_C1_I0_A0_EP6_FIFO_START, FS_C1_I0_A0_EP6_FIFO_MAP);
278         mUsbFIFOConfig(FS_C1_I0_A0_EP6_FIFO_START, FS_C1_I0_A0_EP6_FIFO_CONFIG);
279
280         for(i = FS_C1_I0_A0_EP6_FIFO_START + 1 ;
281             i < FS_C1_I0_A0_EP6_FIFO_START + FS_C1_I0_A0_EP6_FIFO_NO ; i ++)
282         {
283                 mUsbFIFOConfig(i, (FS_C1_I0_A0_EP6_FIFO_CONFIG & (~BIT7)) );
284         }
285
286         mUsbEPMxPtSzHigh(EP6, FS_C1_I0_A0_EP6_DIRECTION,
287                          (FS_C1_I0_A0_EP6_MAX_PACKET & 0x7ff));
288         mUsbEPMxPtSzLow(EP6, FS_C1_I0_A0_EP6_DIRECTION,
289                         (FS_C1_I0_A0_EP6_MAX_PACKET & 0x7ff));
290         mUsbEPinHighBandSet(EP6, FS_C1_I0_A0_EP6_DIRECTION,
291                             FS_C1_I0_A0_EP6_MAX_PACKET);
292 #endif
293 }
294
295 void vUsbFIFO_EPxCfg_FS_patch(void)
296 {
297         switch (u8UsbConfigValue)
298         {
299 #if (FS_CONFIGURATION_NUMBER >= 1)
300                 /* Configuration 0X01 */
301         case 0X01:
302                 switch (u8UsbInterfaceValue)
303                 {
304 #if (FS_C1_INTERFACE_NUMBER >= 1)
305                         /* Interface 0 */
306                 case 0:
307                         switch (u8UsbInterfaceAlternateSetting)
308                         {
309
310 #if (FS_C1_I0_ALT_NUMBER >= 1)
311                                 /* AlternateSetting 0 */
312                         case 0:
313
314                                 /* snapped.... */
315
316                                 /* patch up this ep6_fs config */
317                                 vUSBFIFO_EP6Cfg_FS_patch();
318
319                                 break;
320
321 #endif
322                         default:
323                                 break;
324                         }
325                         break;
326 #endif
327                 default:
328                         break;
329                 }
330                 break;
331 #endif
332         default:
333                 break;
334         }
335         /* mCHECK_STACK(); */
336 }
337
338 BOOLEAN bSet_configuration_patch(void)
339 {
340         /* do some defaul configuration */
341         bSet_configuration();
342
343         /* overwrite defaul FIFO configuration for FullSpeed USB */
344         if ((mLOW_BYTE(mDEV_REQ_VALUE()) != 0) && !mUsbHighSpeedST())
345                         vUsbFIFO_EPxCfg_FS_patch();
346
347         eUsbCxFinishAction = ACT_DONE;
348         return TRUE;
349 }
350
351 extern BOOLEAN bStandardCommand(void);
352
353 BOOLEAN bStandardCommand_patch(void)
354 {
355         if (mDEV_REQ_REQ() == USB_SET_CONFIGURATION) {
356                 A_USB_SET_CONFIG();
357
358 #if ENABLE_SWAP_DATA_MODE
359                 /* SWAP FUNCTION should be enabled while DMA engine
360                  * is not working, the best place to enable it
361                  * is before we trigger the DMA */
362                 MAGPIE_REG_USB_RX0_SWAP_DATA = 0x1;
363                 MAGPIE_REG_USB_TX0_SWAP_DATA = 0x1;
364
365 #if SYSTEM_MODULE_HP_EP5
366                 MAGPIE_REG_USB_RX1_SWAP_DATA = 0x1;
367 #endif
368
369 #if SYSTEM_MODULE_HP_EP6
370                 MAGPIE_REG_USB_RX2_SWAP_DATA = 0x1;
371 #endif
372
373 #endif /* ENABLE_SWAP_DATA_MODE */
374                 return TRUE;
375         } else
376                 return bStandardCommand();
377 }
378
379 /*
380  * usb descriptor patch
381  */
382
383 extern uint16_t         *u8ConfigDescriptorEX;
384 extern uint16_t         *pu8DescriptorEX;
385 extern uint16_t         u16TxRxCounter;
386 extern SetupPacket      ControlCmd;
387 extern uint16_t         *u8UsbDeviceDescriptor;
388 extern BOOLEAN          bGet_descriptor(void);
389
390 uint16_t ConfigDescriptorPatch[30];
391 uint16_t UsbDeviceDescriptorPatch[9];
392
393 #define BCD_DEVICE_OFFSET               6
394 #define BCD_DEVICE_FW_SIGNATURE         0xffff
395 #define VENDOR_ID_OFFSET                4
396 #define PRODUCT_ID_OFFSET               5
397
398 #define EP3_TRANSFER_TYPE_OFFSET        17
399 #define EP3_INT_INTERVAL                19
400 #define EP4_TRANSFER_TYPE_OFFSET        21
401 #define EP4_INT_INTERVAL                22
402
403 BOOLEAN bGet_descriptor_patch(void)
404 {
405         if (mDEV_REQ_VALUE_HIGH() == 1)
406         {
407                 uint8_t *p = (uint8_t *)u8UsbDeviceDescriptor;
408
409                 /* Copy Usb Device Descriptor */
410                 ath_hal_memcpy(UsbDeviceDescriptorPatch, p,
411                                 sizeof(UsbDeviceDescriptorPatch));
412
413                 /* Change bcdDevice. we need it to detect if FW
414                  * was uploaded. */
415                 UsbDeviceDescriptorPatch[BCD_DEVICE_OFFSET] =
416                         BCD_DEVICE_FW_SIGNATURE;
417
418                 pu8DescriptorEX = UsbDeviceDescriptorPatch;
419                 u16TxRxCounter = mTABLE_LEN(u8UsbDeviceDescriptor[0]);
420
421                 if (u16TxRxCounter > mDEV_REQ_LENGTH())
422                         u16TxRxCounter = mDEV_REQ_LENGTH();
423
424                 A_USB_EP0_TX_DATA();
425
426                 return TRUE;
427         } else if (mDEV_REQ_VALUE_HIGH() == 2) {
428                 uint8_t *p = (uint8_t *)u8ConfigDescriptorEX;
429
430                 /* Copy ConfigDescriptor */
431                 ath_hal_memcpy(ConfigDescriptorPatch, p,
432                                 sizeof(ConfigDescriptorPatch));
433
434                  /* place holder for EPx patches */
435
436                 if (mDEV_REQ_VALUE_LOW() == 0) {
437                         /* configuration no: 0 */
438                         pu8DescriptorEX = ConfigDescriptorPatch;
439                         u16TxRxCounter = ConfigDescriptorPatch[1];
440                 } else
441                         return FALSE;
442
443                 if (u16TxRxCounter > mDEV_REQ_LENGTH())
444                         u16TxRxCounter = mDEV_REQ_LENGTH();
445
446                 A_USB_EP0_TX_DATA();
447                 return TRUE;
448         } else
449                 return bGet_descriptor();
450 }
451