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