patch bcdDevice value for magpie to make easy firmware detection.
[open-ath9k-htc-firmware.git] / target_firmware / magpie_fw_dev / target / rompatch / usb_api_patch.c
1 /*
2  * Copyright (c) 2013 Qualcomm Atheros, Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted (subject to the limitations in the
7  * disclaimer below) provided that the following conditions are met:
8  *
9  *  * Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  *
12  *  * Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the
15  *    distribution.
16  *
17  *  * Neither the name of Qualcomm Atheros nor the names of its
18  *    contributors may be used to endorse or promote products derived
19  *    from this software without specific prior written permission.
20  *
21  * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
22  * GRANTED BY THIS LICENSE.  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
23  * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
24  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
25  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
27  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
30  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
31  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
32  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
33  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34  */
35 #include "usb_defs.h"
36 #include "usb_type.h"
37 #include "usb_pre.h"
38 #include "usb_extr.h"
39 #include "usb_std.h"
40 #include "reg_defs.h"
41 #include "athos_api.h"
42 #include "usbfifo_api.h"
43
44 #include "sys_cfg.h"
45
46 #define measure_time 0
47 #define measure_time_pll 10000000
48
49 typedef void (* USBFIFO_recv_command)(VBUF *cmd);
50
51 extern Action eUsbCxFinishAction;
52 extern CommandType eUsbCxCommand;
53 extern BOOLEAN UsbChirpFinish;
54 extern USB_FIFO_CONFIG usbFifoConf;
55 extern uint16_t *pu8DescriptorEX;
56 extern uint16_t u16TxRxCounter;
57
58 USBFIFO_recv_command m_origUsbfifoRecvCmd = NULL;
59
60 void zfTurnOffPower_patch(void);
61
62 static void _fw_reset_dma_fifo();
63 static void _fw_restore_dma_fifo();
64 static void _fw_power_on();
65 static void _fw_power_off();
66
67 BOOLEAN bEepromExist = TRUE;
68 BOOLEAN bJumptoFlash = FALSE;
69
70 void _fw_usbfifo_recv_command(VBUF *buf)
71 {
72         A_UINT8 *cmd_data;
73         A_UINT32 tmp;
74
75         cmd_data = (A_UINT8 *)(buf->desc_list->buf_addr + buf->desc_list->data_offset);
76         tmp = *((A_UINT32 *)cmd_data);
77         if ( tmp == 0xFFFFFFFF ) {      
78                 // reset usb/wlan dma
79                 _fw_reset_dma_fifo();
80
81                 // restore gpio setting and usb/wlan dma state
82                 _fw_restore_dma_fifo();
83
84                 // set clock to bypass mode - 40Mhz from XTAL 
85                 HAL_WORD_REG_WRITE(MAGPIE_REG_CPU_PLL_BYPASS_ADDR, (BIT0|BIT4));
86
87                 A_DELAY_USECS(100); // wait for stable
88
89                 HAL_WORD_REG_WRITE(MAGPIE_REG_CPU_PLL_ADDR, (BIT16));
90
91                 A_DELAY_USECS(100); // wait for stable
92                 A_UART_HWINIT((40*1000*1000), 19200);
93
94                 A_CLOCK_INIT(40);
95
96                 if (!bEepromExist) { //jump to flash boot (eeprom data in flash)
97                         bJumptoFlash = TRUE;
98                         A_PRINTF("Jump to Flash BOOT\n");
99                         app_start();
100                 }else{
101                         A_PRINTF("receive the suspend command...\n");
102                         // reboot.....
103                         A_USB_JUMP_BOOT();              
104                 }
105
106         } else {
107                 m_origUsbfifoRecvCmd(buf);
108         }
109 }
110
111 void _fw_usbfifo_init(USB_FIFO_CONFIG *pConfig)
112 {
113         m_origUsbfifoRecvCmd = pConfig->recv_command;
114
115         usbFifoConf.get_command_buf = pConfig->get_command_buf;
116         usbFifoConf.recv_command    = _fw_usbfifo_recv_command;
117         usbFifoConf.get_event_buf   = pConfig->get_event_buf;
118         usbFifoConf.send_event_done = pConfig->send_event_done;
119 }
120
121 /*
122  * -- support more than 64 bytes command on ep4 -- 
123  */
124 void vUsb_Reg_Out_patch(void)
125 {   
126         uint16_t usbfifolen;
127         uint16_t ii;
128         uint32_t ep4_data;
129         static volatile uint32_t *regaddr;
130         static uint16_t cmdLen;
131         static VBUF *buf;
132         BOOLEAN cmd_is_last = FALSE;
133         static BOOLEAN cmd_is_new = TRUE;
134
135         // get the size of this transcation
136         usbfifolen = USB_BYTE_REG_READ(ZM_EP4_BYTE_COUNT_LOW_OFFSET);
137
138         // check is command is new
139         if( cmd_is_new ){
140
141                 buf = usbFifoConf.get_command_buf();
142                 cmdLen = 0;
143
144                 if( !buf )
145                         goto ERR;
146
147                 // copy free, assignment buffer of the address
148                 regaddr = (uint32_t *)buf->desc_list->buf_addr;
149
150                 cmd_is_new = FALSE;
151         }
152
153         // just in case, suppose should not happen
154         if( !buf )
155                 goto ERR;
156
157         // if size is smaller, this is the last command!
158         // zero-length supposed should be set through 0x27/bit7->0x19/bit4, not here
159         if( usbfifolen<64 ) {
160                 cmd_is_last = TRUE;
161         }
162
163         // accumulate the size
164         cmdLen += usbfifolen;
165
166         // round it to alignment
167         if(usbfifolen % 4)
168                 usbfifolen = (usbfifolen >> 2) + 1;
169         else
170                 usbfifolen = usbfifolen >> 2;
171
172         // retrieve the data from fifo
173         for(ii = 0; ii < usbfifolen; ii++)
174         {
175                 ep4_data = USB_WORD_REG_READ(ZM_EP4_DATA_OFFSET);   // read fifo data out
176                 *regaddr = ep4_data;
177                 regaddr++;
178         }
179
180         // if this is the last command, callback to HTC
181         if (  cmd_is_last  )
182         {
183                 buf->desc_list->next_desc = NULL;
184                 buf->desc_list->data_offset = 0;
185                 buf->desc_list->data_size = cmdLen;
186                 buf->desc_list->control = 0;
187                 buf->next_buf = NULL;
188                 buf->buf_length = cmdLen;
189
190                 usbFifoConf.recv_command(buf);
191
192                 cmd_is_new = TRUE;
193         }
194
195         goto DONE;
196 ERR:
197         //    we might get no command buffer here?
198         //    but if we return here, the ep4 fifo will be lock out,
199         //    so that we still read them out but just drop it ?
200         for(ii = 0; ii < usbfifolen; ii++)
201         {
202                 ep4_data = USB_WORD_REG_READ(ZM_EP4_DATA_OFFSET);   // read fifo data out
203         }
204
205 DONE:
206         //mUSB_STATUS_IN_INT_ENABLE();
207         ;
208 }
209
210
211 /* 
212  *  -- usb1.1 ep6 fix --
213  */
214 extern uint16_t       u8UsbConfigValue;
215 extern uint16_t       u8UsbInterfaceValue;
216 extern uint16_t       u8UsbInterfaceAlternateSetting;
217 extern SetupPacket    ControlCmd;
218 extern void vUsbClrEPx(void);
219
220 #undef FS_C1_I0_A0_EP_NUMBER
221 #define FS_C1_I0_A0_EP_NUMBER 6
222
223 #define FS_C1_I0_A0_EP6_BLKSIZE    BLK512BYTE
224 #define FS_C1_I0_A0_EP6_BLKNO      DOUBLE_BLK
225 #define FS_C1_I0_A0_EP6_DIRECTION  DIRECTION_OUT
226 #define FS_C1_I0_A0_EP6_TYPE       TF_TYPE_BULK
227 #define FS_C1_I0_A0_EP6_MAX_PACKET 0x0040
228 #define FS_C1_I0_A0_EP6_bInterval  00
229
230 // EP6
231 #define FS_C1_I0_A0_EP6_FIFO_START  (FS_C1_I0_A0_EP5_FIFO_START + FS_C1_I0_A0_EP5_FIFO_NO)
232 #define FS_C1_I0_A0_EP6_FIFO_NO     (FS_C1_I0_A0_EP6_BLKNO * FS_C1_I0_A0_EP6_BLKSIZE)
233 #define FS_C1_I0_A0_EP6_FIFO_CONFIG (0x80 | ((FS_C1_I0_A0_EP6_BLKSIZE - 1) << 4) | ((FS_C1_I0_A0_EP6_BLKNO - 1) << 2) | FS_C1_I0_A0_EP6_TYPE)
234 #define FS_C1_I0_A0_EP6_FIFO_MAP    (((1 - FS_C1_I0_A0_EP6_DIRECTION) << 4) | EP6)
235 #define FS_C1_I0_A0_EP6_MAP         (FS_C1_I0_A0_EP6_FIFO_START |   (FS_C1_I0_A0_EP6_FIFO_START << 4)   | (MASK_F0 >> (4*FS_C1_I0_A0_EP6_DIRECTION)))
236
237
238 #define CMD_PCI_RC_RESET_ON() HAL_WORD_REG_WRITE(MAGPIE_REG_RST_RESET_ADDR, \
239                          (HAL_WORD_REG_READ(MAGPIE_REG_RST_RESET_ADDR)| \
240                           (PCI_RC_PHY_SHIFT_RESET_BIT|PCI_RC_PLL_RESET_BIT|PCI_RC_PHY_RESET_BIT|PCI_RC_RESET_BIT)))
241
242 void vUSBFIFO_EP6Cfg_FS_patch(void)
243 {
244 #if (FS_C1_I0_A0_EP_NUMBER >= 6)
245         int i;
246
247         //EP0X06
248         mUsbEPMap(EP6, FS_C1_I0_A0_EP6_MAP);
249         mUsbFIFOMap(FS_C1_I0_A0_EP6_FIFO_START, FS_C1_I0_A0_EP6_FIFO_MAP);
250         mUsbFIFOConfig(FS_C1_I0_A0_EP6_FIFO_START, FS_C1_I0_A0_EP6_FIFO_CONFIG);
251
252         for(i = FS_C1_I0_A0_EP6_FIFO_START + 1 ;
253             i < FS_C1_I0_A0_EP6_FIFO_START + FS_C1_I0_A0_EP6_FIFO_NO ; i ++)
254         {
255                 mUsbFIFOConfig(i, (FS_C1_I0_A0_EP6_FIFO_CONFIG & (~BIT7)) );
256         }
257
258         mUsbEPMxPtSzHigh(EP6, FS_C1_I0_A0_EP6_DIRECTION, (FS_C1_I0_A0_EP6_MAX_PACKET & 0x7ff));
259         mUsbEPMxPtSzLow(EP6, FS_C1_I0_A0_EP6_DIRECTION, (FS_C1_I0_A0_EP6_MAX_PACKET & 0x7ff));
260         mUsbEPinHighBandSet(EP6 , FS_C1_I0_A0_EP6_DIRECTION, FS_C1_I0_A0_EP6_MAX_PACKET);
261 #endif
262 }
263
264 void vUsbFIFO_EPxCfg_FS_patch(void)
265 {
266         switch (u8UsbConfigValue)
267         {
268 #if (FS_CONFIGURATION_NUMBER >= 1)
269                 // Configuration 0X01
270         case 0X01:
271                 switch (u8UsbInterfaceValue)
272                 {
273 #if (FS_C1_INTERFACE_NUMBER >= 1)
274                         // Interface 0
275                 case 0:
276                         switch (u8UsbInterfaceAlternateSetting)
277                         {
278
279 #if (FS_C1_I0_ALT_NUMBER >= 1)
280                                 // AlternateSetting 0
281                         case 0:
282
283                                 // snapped....
284
285                                 // patch up this ep6_fs config
286                                 vUSBFIFO_EP6Cfg_FS_patch();
287
288                                 break;
289
290 #endif
291                         default:
292                                 break;
293                         }
294                         break;
295 #endif
296                 default:
297                         break;
298                 }
299                 break;
300 #endif
301         default:
302                 break;
303         }
304         //mCHECK_STACK();
305 }
306
307
308 BOOLEAN bSet_configuration_patch(void)
309 {
310         bSet_configuration();
311
312         if (mLOW_BYTE(mDEV_REQ_VALUE()) == 0)
313         {
314                 // snapped....
315                 ;
316         }
317         else
318         {
319                 if (mUsbHighSpeedST())                  // First judge HS or FS??
320                 {
321                         // snapped....
322                         ;
323                 }
324                 else
325                 {
326                         // snapped....
327                         vUsbFIFO_EPxCfg_FS_patch();
328                 }
329
330                 // snapped....
331         }
332
333         eUsbCxFinishAction = ACT_DONE;
334         return TRUE;
335 }
336
337
338 /*
339  * -- support more than 64 bytes command on ep3 -- 
340  */
341 void vUsb_Status_In_patch(void)
342 {
343         uint16_t count;
344         uint16_t remainder;
345         u16_t RegBufLen;
346         BOOLEAN cmdEnd = FALSE;
347
348         static u16_t mBufLen;
349         static VBUF *evntbuf = NULL;
350         static volatile u32_t *regaddr;
351         static BOOLEAN cmd_is_new = TRUE;
352
353         if( cmd_is_new )
354         {
355                 evntbuf = usbFifoConf.get_event_buf();
356                 if ( evntbuf != NULL )
357                 {
358                         regaddr = (u32_t *)VBUF_GET_DATA_ADDR(evntbuf);
359                         mBufLen = evntbuf->buf_length;
360                 }
361                 else
362                 {
363                         mUSB_STATUS_IN_INT_DISABLE();
364                         goto ERR_DONE;
365                 }
366
367                 cmd_is_new = FALSE;
368         }
369
370         if( mBufLen > bUSB_EP_MAX_PKT_SIZE_64 ) {
371                 RegBufLen = bUSB_EP_MAX_PKT_SIZE_64;
372                 mBufLen -= bUSB_EP_MAX_PKT_SIZE_64;
373         }
374         // TODO: 64 byes... controller supposed will take care of zero-length?
375         else {
376                 RegBufLen = mBufLen;
377                 cmdEnd = TRUE;
378         }
379
380         /* INT use EP3 */
381         for(count = 0; count < (RegBufLen / 4); count++)
382         {
383                 USB_WORD_REG_WRITE(ZM_EP3_DATA_OFFSET, *regaddr);
384                 regaddr++;
385         }
386
387         remainder = RegBufLen % 4;
388
389         if (remainder)
390         {
391                 switch(remainder)
392                 {
393                 case 3:
394                         USB_WORD_REG_WRITE(ZM_CBUS_FIFO_SIZE_OFFSET, 0x7);
395                         break;
396                 case 2:
397                         USB_WORD_REG_WRITE(ZM_CBUS_FIFO_SIZE_OFFSET, 0x3);
398                         break;
399                 case 1:
400                         USB_WORD_REG_WRITE(ZM_CBUS_FIFO_SIZE_OFFSET, 0x1);
401                         break;
402                 }
403
404                 USB_WORD_REG_WRITE(ZM_EP3_DATA_OFFSET, *regaddr);
405
406                 // Restore CBus FIFO size to word size            
407                 USB_WORD_REG_WRITE(ZM_CBUS_FIFO_SIZE_OFFSET, 0xF);
408         }
409
410         mUSB_EP3_XFER_DONE();
411
412         if ( evntbuf != NULL && cmdEnd )
413         {
414                 usbFifoConf.send_event_done(evntbuf);
415                 cmd_is_new = TRUE;
416         }
417
418 ERR_DONE:
419         ;
420 }
421
422
423 #define PCI_RC_RESET_BIT                            BIT6
424 #define PCI_RC_PHY_RESET_BIT                        BIT7
425 #define PCI_RC_PLL_RESET_BIT                        BIT8
426 #define PCI_RC_PHY_SHIFT_RESET_BIT                  BIT10
427
428
429 /*
430  * -- urn_off_merlin --
431  * . values suggested from Lalit
432  *
433  */
434 static void turn_off_merlin()
435 {
436         volatile uint32_t default_data[9];
437         uint32_t i=0;
438
439         if(1)
440         {
441                 A_PRINTF("turn_off_merlin_ep_start ......\n");
442                 A_DELAY_USECS(measure_time);
443                 default_data[0] = 0x9248fd00;
444                 default_data[1] = 0x24924924;
445                 default_data[2] = 0xa8000019;
446                 default_data[3] = 0x17160820;
447                 default_data[4] = 0x25980560;
448                 default_data[5] = 0xc1c00000;
449                 default_data[6] = 0x1aaabe40;
450                 default_data[7] = 0xbe105554;
451                 default_data[8] = 0x00043007;
452         
453                 for(i=0; i<9; i++)
454                 {
455                         A_DELAY_USECS(10);
456         
457                         HAL_WORD_REG_WRITE( 0x10ff4040, default_data[i]); 
458                 }
459                 A_DELAY_USECS(10);
460                 HAL_WORD_REG_WRITE(0x10ff4044, BIT0);
461                 A_PRINTF("turn_off_merlin_ep_end ......\n");
462         }
463 }
464
465 /*
466  * -- turn_off_phy --
467  *
468  * . write shift register to both pcie ep and rc
469  * . 
470  */
471
472 static void turn_off_phy()
473 {
474
475         volatile uint32_t default_data[9];
476         volatile uint32_t read_data = 0;
477         uint32_t i=0;
478
479         default_data[0] = 0x9248fd00;
480         default_data[1] = 0x24924924;
481         default_data[2] = 0xa8000019;
482         default_data[3] = 0x17160820;
483         default_data[4] = 0x25980560;
484         default_data[5] = 0xc1c00000;
485         default_data[6] = 0x1aaabe40;
486         default_data[7] = 0xbe105554;
487         default_data[8] = 0x00043007;
488
489         for(i=0; i<9; i++)
490         {
491                 // check for the done bit to be set 
492
493                 while (1)
494                 {
495                         read_data=HAL_WORD_REG_READ(0x40028);
496                         if( read_data & BIT31 )
497                                 break;
498                 }
499         
500                 A_DELAY_USECS(1);
501     
502                 HAL_WORD_REG_WRITE( 0x40024, default_data[i]); 
503         }
504         HAL_WORD_REG_WRITE(0x40028, BIT0);
505 }
506
507 static void turn_off_phy_rc()
508 {
509     
510         volatile uint32_t default_data[9];
511         volatile uint32_t read_data = 0;
512         uint32_t i=0;
513     
514         A_PRINTF("turn_off_phy_rc\n");
515     
516         default_data[0] = 0x9248fd00;
517         default_data[1] = 0x24924924;
518         default_data[2] = 0xa8000019;
519         default_data[3] = 0x13160820;//PwdClk1MHz=0
520         default_data[4] = 0x25980560;
521         default_data[5] = 0xc1c00000;
522         default_data[6] = 0x1aaabe40;
523         default_data[7] = 0xbe105554;
524         default_data[8] = 0x00043007;
525         
526         for(i=0; i<9; i++)
527         {
528                 // check for the done bit to be set 
529      
530                 while (1)
531                 {
532                         read_data=HAL_WORD_REG_READ(0x40028);
533                         if( read_data & BIT31 )
534                                 break;
535                 }
536
537                 A_DELAY_USECS(1);
538
539                 HAL_WORD_REG_WRITE( 0x40024, default_data[i]); 
540         }
541         HAL_WORD_REG_WRITE(0x40028, BIT0);
542 }
543
544 volatile uint32_t gpio_func = 0x0;
545 volatile uint32_t gpio = 0x0;
546
547 /*
548  * -- patch zfTurnOffPower --
549  *
550  * . set suspend counter to non-zero value
551  * . 
552  */
553 void zfTurnOffPower_patch(void)
554 {
555         A_PRINTF("+++ goto suspend ......\n");
556
557         // setting the go suspend here, power down right away...
558         HAL_WORD_REG_WRITE(0x10000, HAL_WORD_REG_READ(0x10000)|(0x8));
559
560         A_DELAY_USECS(100);
561
562         // TURN OFF ETH PLL
563         _fw_power_off();
564
565         //32clk wait for External ETH PLL stable
566         A_DELAY_USECS(100);
567     
568         HAL_WORD_REG_WRITE(0x52000, 0x70303);//read back 0x703f7
569         HAL_WORD_REG_WRITE(0x52008, 0x0e91c);//read back 0x1e948    
570     
571         HAL_WORD_REG_WRITE(MAGPIE_REG_SUSPEND_ENABLE_ADDR,
572                            (HAL_WORD_REG_READ(MAGPIE_REG_SUSPEND_ENABLE_ADDR)|(BIT0))); //0x56030
573         // wake up, and turn on cpu, eth, pcie and usb pll 
574         _fw_power_on();
575         // restore gpio and other settings
576         _fw_restore_dma_fifo();
577
578         // clear suspend..................
579         HAL_WORD_REG_WRITE(MAGPIE_REG_SUSPEND_ENABLE_ADDR,
580                            (HAL_WORD_REG_READ(MAGPIE_REG_SUSPEND_ENABLE_ADDR)&(~BIT0)));
581         HAL_WORD_REG_WRITE(0x52028, HAL_WORD_REG_READ(0x52028)&(~(BIT8|BIT12|BIT16)));
582 }
583
584 /*
585  * -- patch zfResetUSBFIFO_patch --
586  *
587  * . clear ep3/ep4 fifo
588  * . set suspend magic pattern
589  * . reset pcie ep phy
590  * . reset pcie rc phy
591  * . turn off pcie pll
592  * . reset all pcie/gmac related registers
593  * . reset usb dma
594  */
595 void zfResetUSBFIFO_patch(void)
596 {
597         A_PRINTF("0x9808  0x%x ......\n", HAL_WORD_REG_READ(0x10ff9808));
598         A_PRINTF("0x7890  0x%x ......\n", HAL_WORD_REG_READ(0x10ff7890));
599         A_PRINTF("0x7890  0x%x ......\n", HAL_WORD_REG_READ(0x10ff7890));
600         A_PRINTF("0x4088  0x%x ......\n", HAL_WORD_REG_READ(0x10ff4088));
601         _fw_reset_dma_fifo();
602 }
603
604 static void _fw_reset_dma_fifo()
605 {
606         HAL_BYTE_REG_WRITE(0x100ae, (HAL_BYTE_REG_READ(0x100ae)|0x10));
607         HAL_BYTE_REG_WRITE(0x100ae, (HAL_BYTE_REG_READ(0x100af)|0x10));
608         A_PRINTF("_fw_reset_dma_fifo\n");
609
610         // disable ep3 int enable, so that resume back won't send wdt magic pattern out!!!
611         mUSB_STATUS_IN_INT_DISABLE();
612
613         // update magic pattern to indicate this is a suspend
614         HAL_WORD_REG_WRITE(WATCH_DOG_MAGIC_PATTERN_ADDR, SUS_MAGIC_PATTERN);
615
616         A_PRINTF("org 0x4048  0x%x ......\n", HAL_WORD_REG_READ(0x10ff4048));
617         A_PRINTF("org 0x404C  0x%x ......\n", HAL_WORD_REG_READ(0x10ff404C));
618         A_PRINTF("org 0x4088  0x%x ......\n", HAL_WORD_REG_READ(0x10ff4088));
619
620         HAL_WORD_REG_WRITE(0x10ff4088,0xaaa6a);//1010.1010.1010.0110.1010 for UB94
621         HAL_WORD_REG_WRITE(0x10ff404C,0x0);
622
623         A_DELAY_USECS(1000);
624         A_PRINTF("0x4048  0x%x ......\n", HAL_WORD_REG_READ(0x10ff4048));
625         A_PRINTF("0x404C  0x%x ......\n", HAL_WORD_REG_READ(0x10ff404C));
626         A_PRINTF("0x4088  0x%x ......\n", HAL_WORD_REG_READ(0x10ff4088));
627          
628         // turn off merlin
629         turn_off_merlin();
630         // pcie ep
631         A_PRINTF("turn_off_magpie_ep_start ......\n");
632         A_DELAY_USECS(measure_time);
633         HAL_WORD_REG_WRITE( 0x40040, (HAL_WORD_REG_READ(0x40040)|BIT0|(1<<1)));
634         turn_off_phy();
635         HAL_WORD_REG_WRITE( 0x40040, (HAL_WORD_REG_READ(0x40040)&~(BIT0|(1<<1))));
636         A_PRINTF("turn_off_magpie_ep_end ......\n");
637
638         // pcie rc 
639         A_PRINTF("turn_off_magpie_rc_start ......\n");
640         A_DELAY_USECS(measure_time);
641         HAL_WORD_REG_WRITE( 0x40040, (HAL_WORD_REG_READ(0x40040)&(~BIT0)));
642         turn_off_phy_rc();
643         A_PRINTF("turn_off_magpie_rc_end ......down\n");
644         A_DELAY_USECS(measure_time);
645
646         A_PRINTF("0x4001C  %p ......\n", HAL_WORD_REG_READ(0x4001c)); 
647         A_PRINTF("0x40040  %p ......\n", HAL_WORD_REG_READ(0x40040));
648     
649         // turn off pcie_pll - power down (bit16)
650         A_PRINTF(" before pwd PCIE PLL CFG:0x5601C  %p ......\n", HAL_WORD_REG_READ(0x5601C));
651         HAL_WORD_REG_WRITE(0x5601C, (HAL_WORD_REG_READ(0x5601C)|(BIT18)));   
652         A_PRINTF(" after pwd PCIE PLL CFG:0x5601C  %p ......\n", HAL_WORD_REG_READ(0x5601C));
653
654         /* set everything to reset state?, requested by Oligo */
655         HAL_WORD_REG_WRITE(0x50010, HAL_WORD_REG_READ(0x50010)|(BIT13|BIT12|BIT11|BIT9|BIT7|BIT6));
656
657         HAL_WORD_REG_WRITE(0x5C000, 0);
658
659         A_DELAY_USECS(10);
660
661         // reset usb DMA controller
662         HAL_WORD_REG_WRITE((USB_CTRL_BASE_ADDRESS+0x118), 0x0);
663
664         HAL_WORD_REG_WRITE(0x50010, (HAL_WORD_REG_READ(0x50010)|(BIT4)));
665         A_DELAY_USECS(5);
666         HAL_WORD_REG_WRITE(0x50010, (HAL_WORD_REG_READ(0x50010)&(~BIT4)));
667
668
669         HAL_WORD_REG_WRITE((USB_CTRL_BASE_ADDRESS+0x118), 0x1);
670 }
671
672 static void _fw_power_off()
673 {
674         /*
675          *  1. set CPU bypass
676          *  2. turn off CPU PLL
677          *  3. turn off ETH PLL
678          *  4. disable ETH PLL bypass and update
679          *  4.1 set suspend timeout 
680          *  5. set SUSPEND_ENABLE
681          */
682
683         HAL_WORD_REG_WRITE(MAGPIE_REG_CPU_PLL_BYPASS_ADDR, (BIT0|BIT4)); //0x56004
684
685         A_DELAY_USECS(100); // wait for stable
686
687         HAL_WORD_REG_WRITE(MAGPIE_REG_CPU_PLL_ADDR, (BIT16));//0x56000
688
689         A_DELAY_USECS(100); // wait for stable
690
691         A_UART_HWINIT((40*1000*1000), 19200);
692         A_CLOCK_INIT(40);
693
694         HAL_WORD_REG_WRITE(MAGPIE_REG_ETH_PLL_ADDR,
695                            (HAL_WORD_REG_READ(MAGPIE_REG_ETH_PLL_ADDR)|(BIT16)));   //0x5600c
696
697         HAL_WORD_REG_WRITE(MAGPIE_REG_ETH_PLL_BYPASS_ADDR,
698                            (HAL_WORD_REG_READ(MAGPIE_REG_ETH_PLL_BYPASS_ADDR)|(BIT4|BIT0))); //0x56010
699
700         HAL_WORD_REG_WRITE(MAGPIE_REG_SUSPEND_ENABLE_ADDR,
701                            (HAL_WORD_REG_READ(MAGPIE_REG_SUSPEND_ENABLE_ADDR)|(0x10<<8))); //0x56030
702 }
703
704 static void _fw_power_on()
705
706     /*
707      *  1. turn on CPU PLL
708      *  2. disable CPU bypass
709      *  3. turn on ETH PLL
710      *  4. disable ETH PLL bypass and update
711      *  5. turn on pcie pll
712      */    
713
714         HAL_WORD_REG_WRITE(MAGPIE_REG_ETH_PLL_ADDR,
715                            (HAL_WORD_REG_READ(MAGPIE_REG_ETH_PLL_ADDR)&(~BIT16)));
716
717         // deassert eth_pll bypass mode and trigger update bit
718         HAL_WORD_REG_WRITE(MAGPIE_REG_ETH_PLL_BYPASS_ADDR,
719                            (HAL_WORD_REG_READ(MAGPIE_REG_ETH_PLL_BYPASS_ADDR)&(~(BIT4|BIT0))));
720 }
721
722 static void _fw_restore_dma_fifo(void)
723 {
724         HAL_WORD_REG_WRITE(0x5601C, (HAL_WORD_REG_READ(0x5601C)&(~(BIT18))));
725     
726         // reset pcie_rc shift 
727         HAL_WORD_REG_WRITE(0x50010, (HAL_WORD_REG_READ(0x50010)&(~(BIT10|BIT8|BIT7))));
728         A_DELAY_USECS(1);
729         HAL_WORD_REG_WRITE(0x50010, (HAL_WORD_REG_READ(0x50010)|(BIT10|BIT8|BIT7)));
730
731         // reset pci_rc phy
732         CMD_PCI_RC_RESET_ON();
733         A_DELAY_USECS(20);
734
735         // enable dma swap function
736         MAGPIE_REG_USB_RX0_SWAP_DATA = 0x1;
737         MAGPIE_REG_USB_TX0_SWAP_DATA = 0x1;
738         MAGPIE_REG_USB_RX1_SWAP_DATA = 0x1;
739         MAGPIE_REG_USB_RX2_SWAP_DATA = 0x1;
740 }
741
742 extern uint16_t *u8ConfigDescriptorEX;
743 extern uint16_t *pu8DescriptorEX;
744 extern uint16_t u16TxRxCounter;
745
746 extern uint16_t *u8UsbDeviceDescriptor;
747
748 extern BOOLEAN bGet_descriptor(void);
749
750 uint16_t ConfigDescriptorPatch[30];
751
752 uint16_t UsbDeviceDescriptorPatch[9];
753 #define BCD_DEVICE_OFFSET               6
754 #define BCD_DEVICE_FW_SIGNATURE         0xffff
755 #define VENDOR_ID_OFFSET                4
756 #define PRODUCT_ID_OFFSET               5
757
758 #define EP3_TRANSFER_TYPE_OFFSET    17
759 #define EP3_INT_INTERVAL            19
760 #define EP4_TRANSFER_TYPE_OFFSET    21
761 #define EP4_INT_INTERVAL            22
762
763
764
765  #define A_SFLASH_READ_4B(u32Data, start_addr) u32Data = *(uint32_t *)(0xf000000+start_addr);
766  #define FLASH_SIZE 0x800000 //8M
767  #define FLASH_USB_VENDOR_ID_OFFSET     0x86
768  #define FLASH_USB_PRODUCT_ID_OFFSET    0x87
769
770  // flash reserved size for saving eeprom data is 4K.
771  #define EE_DATA_RESERVED_LEN 0x1000 //4K
772
773 #define mLOW_MASK(u16)          ((uint8_t) ((u16) & mMASK(8)))
774 #define mHIGH_MASK(u16)         ((uint8_t) ((u16) & ~mMASK(8)))
775
776 /* (1234) -> 0034 */
777 //#define mLOW_BYTE(u16)          ((U_8)(u16))
778 #define mLOW_BYTE(u16)          mLOW_MASK(u16)
779 /* (1234) -> 0012 */
780 #define mHIGH_BYTE(u16)         ((uint8_t) (((uint16_t) (u16)) >> 8))
781
782 #define mLOW_WORD0(u32)         ((uint16_t) ((u32) & 0xFFFF))
783 #define mHIGH_WORD0(u32)        ((uint16_t) ((u32) >> 16))
784
785 /* (1234) -> 3412 */
786 #define mSWAP_BYTE(u16)         ((mLOW_MASK(u16) << 8) | mHIGH_BYTE(u16))
787  
788 BOOLEAN bGet_descriptor_patch(void)
789 {
790         if (mDEV_REQ_VALUE_HIGH() == 1)
791         {
792                 uint8_t *p = (uint8_t *)u8UsbDeviceDescriptor;
793                 uint32_t u32Tmp=0;
794                 /* Copy Usb Device Descriptor */
795                 ath_hal_memcpy(UsbDeviceDescriptorPatch, p, sizeof(UsbDeviceDescriptorPatch));
796
797                 UsbDeviceDescriptorPatch[BCD_DEVICE_OFFSET] =
798                         BCD_DEVICE_FW_SIGNATURE;
799
800                 /* Patch for custom id from flash */
801                 if (bEepromExist == FALSE) {
802                         A_SFLASH_READ_4B(u32Tmp, FLASH_SIZE -
803                                 EE_DATA_RESERVED_LEN + FLASH_USB_VENDOR_ID_OFFSET*2);
804                         UsbDeviceDescriptorPatch[VENDOR_ID_OFFSET] =
805                                 mSWAP_BYTE(mLOW_WORD0(u32Tmp));
806                         UsbDeviceDescriptorPatch[PRODUCT_ID_OFFSET] =
807                                 mSWAP_BYTE(mHIGH_WORD0(u32Tmp));
808                 }
809       
810                 pu8DescriptorEX = UsbDeviceDescriptorPatch;
811                 u16TxRxCounter = mTABLE_LEN(u8UsbDeviceDescriptor[0]);
812   
813                 if (u16TxRxCounter > mDEV_REQ_LENGTH())  
814                         u16TxRxCounter = mDEV_REQ_LENGTH();
815              
816                 A_USB_EP0_TX_DATA();
817            
818                 //u16TxRxCounter = 18;
819                 return TRUE;
820         }  
821         if (mDEV_REQ_VALUE_HIGH() == 2) {
822                 uint8_t *p = (uint8_t *)u8ConfigDescriptorEX;
823
824                 /* Copy ConfigDescriptor */
825                 ath_hal_memcpy(ConfigDescriptorPatch, p, sizeof(ConfigDescriptorPatch));
826
827                 p = (uint8_t *)ConfigDescriptorPatch;
828
829                 /* Patch the transfer type of EP3 and EP4 */
830                 ConfigDescriptorPatch[EP3_TRANSFER_TYPE_OFFSET] = 0x0283;
831                 ConfigDescriptorPatch[EP3_INT_INTERVAL] = 0x0700;
832                 ConfigDescriptorPatch[EP4_TRANSFER_TYPE_OFFSET] = 0x4002;
833                 ConfigDescriptorPatch[EP4_INT_INTERVAL] = 0x00;
834
835                 switch (mDEV_REQ_VALUE_LOW())
836                 {
837                 case 0x00:      // configuration no: 0
838                         pu8DescriptorEX = ConfigDescriptorPatch;
839                         u16TxRxCounter = ConfigDescriptorPatch[1];
840                         //u16TxRxCounter = 46;
841                         break;
842                 default:
843                         return FALSE;
844                 }
845
846                 if (u16TxRxCounter > mDEV_REQ_LENGTH())
847                         u16TxRxCounter = mDEV_REQ_LENGTH();
848
849                 A_USB_EP0_TX_DATA();
850                 return TRUE;
851         }
852         else {
853                 return bGet_descriptor();
854         }
855 }
856
857 extern BOOLEAN bStandardCommand(void);
858
859 BOOLEAN bStandardCommand_patch(void)
860 {
861         if (mDEV_REQ_REQ() == USB_SET_CONFIGURATION) {
862                 A_USB_SET_CONFIG();
863
864 #if ENABLE_SWAP_DATA_MODE
865                 // SWAP FUNCTION should be enabled while DMA engine is not working,
866                 // the best place to enable it is before we trigger the DMA
867                 MAGPIE_REG_USB_RX0_SWAP_DATA = 0x1;
868                 MAGPIE_REG_USB_TX0_SWAP_DATA = 0x1;
869
870 #if SYSTEM_MODULE_HP_EP5
871                 MAGPIE_REG_USB_RX1_SWAP_DATA = 0x1;
872 #endif
873
874 #if SYSTEM_MODULE_HP_EP6
875                 MAGPIE_REG_USB_RX2_SWAP_DATA = 0x1;
876 #endif
877
878 #endif //ENABLE_SWAP_DATA_MODE
879                 return TRUE;
880         }
881         else {
882                 return bStandardCommand();
883         }
884 }