2 * Copyright (c) 2013 Qualcomm Atheros, Inc.
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:
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
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
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.
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.
41 #include "athos_api.h"
42 #include "usbfifo_api.h"
46 #define measure_time 0
47 #define measure_time_pll 10000000
49 typedef void (* USBFIFO_recv_command)(VBUF *cmd);
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;
58 USBFIFO_recv_command m_origUsbfifoRecvCmd = NULL;
60 void zfTurnOffPower_patch(void);
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();
67 BOOLEAN bEepromExist = TRUE;
68 BOOLEAN bJumptoFlash = FALSE;
70 void _fw_usbfifo_recv_command(VBUF *buf)
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 ) {
81 // restore gpio setting and usb/wlan dma state
82 _fw_restore_dma_fifo();
84 // set clock to bypass mode - 40Mhz from XTAL
85 HAL_WORD_REG_WRITE(MAGPIE_REG_CPU_PLL_BYPASS_ADDR, (BIT0|BIT4));
87 A_DELAY_USECS(100); // wait for stable
89 HAL_WORD_REG_WRITE(MAGPIE_REG_CPU_PLL_ADDR, (BIT16));
91 A_DELAY_USECS(100); // wait for stable
92 A_UART_HWINIT((40*1000*1000), 19200);
96 if (!bEepromExist) { //jump to flash boot (eeprom data in flash)
98 A_PRINTF("Jump to Flash BOOT\n");
101 A_PRINTF("receive the suspend command...\n");
107 m_origUsbfifoRecvCmd(buf);
111 void _fw_usbfifo_init(USB_FIFO_CONFIG *pConfig)
113 m_origUsbfifoRecvCmd = pConfig->recv_command;
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;
121 #define PCI_RC_RESET_BIT BIT6
122 #define PCI_RC_PHY_RESET_BIT BIT7
123 #define PCI_RC_PLL_RESET_BIT BIT8
124 #define PCI_RC_PHY_SHIFT_RESET_BIT BIT10
128 * -- urn_off_merlin --
129 * . values suggested from Lalit
132 static void turn_off_merlin()
134 volatile uint32_t default_data[9];
139 A_PRINTF("turn_off_merlin_ep_start ......\n");
140 A_DELAY_USECS(measure_time);
141 default_data[0] = 0x9248fd00;
142 default_data[1] = 0x24924924;
143 default_data[2] = 0xa8000019;
144 default_data[3] = 0x17160820;
145 default_data[4] = 0x25980560;
146 default_data[5] = 0xc1c00000;
147 default_data[6] = 0x1aaabe40;
148 default_data[7] = 0xbe105554;
149 default_data[8] = 0x00043007;
155 HAL_WORD_REG_WRITE( 0x10ff4040, default_data[i]);
158 HAL_WORD_REG_WRITE(0x10ff4044, BIT0);
159 A_PRINTF("turn_off_merlin_ep_end ......\n");
166 * . write shift register to both pcie ep and rc
170 static void turn_off_phy()
173 volatile uint32_t default_data[9];
174 volatile uint32_t read_data = 0;
177 default_data[0] = 0x9248fd00;
178 default_data[1] = 0x24924924;
179 default_data[2] = 0xa8000019;
180 default_data[3] = 0x17160820;
181 default_data[4] = 0x25980560;
182 default_data[5] = 0xc1c00000;
183 default_data[6] = 0x1aaabe40;
184 default_data[7] = 0xbe105554;
185 default_data[8] = 0x00043007;
189 // check for the done bit to be set
193 read_data=HAL_WORD_REG_READ(0x40028);
194 if( read_data & BIT31 )
200 HAL_WORD_REG_WRITE( 0x40024, default_data[i]);
202 HAL_WORD_REG_WRITE(0x40028, BIT0);
205 static void turn_off_phy_rc()
208 volatile uint32_t default_data[9];
209 volatile uint32_t read_data = 0;
212 A_PRINTF("turn_off_phy_rc\n");
214 default_data[0] = 0x9248fd00;
215 default_data[1] = 0x24924924;
216 default_data[2] = 0xa8000019;
217 default_data[3] = 0x13160820;//PwdClk1MHz=0
218 default_data[4] = 0x25980560;
219 default_data[5] = 0xc1c00000;
220 default_data[6] = 0x1aaabe40;
221 default_data[7] = 0xbe105554;
222 default_data[8] = 0x00043007;
226 // check for the done bit to be set
230 read_data=HAL_WORD_REG_READ(0x40028);
231 if( read_data & BIT31 )
237 HAL_WORD_REG_WRITE( 0x40024, default_data[i]);
239 HAL_WORD_REG_WRITE(0x40028, BIT0);
242 volatile uint32_t gpio_func = 0x0;
243 volatile uint32_t gpio = 0x0;
246 * -- patch zfTurnOffPower --
248 * . set suspend counter to non-zero value
251 void zfTurnOffPower_patch(void)
253 A_PRINTF("+++ goto suspend ......\n");
255 // setting the go suspend here, power down right away...
256 HAL_WORD_REG_WRITE(0x10000, HAL_WORD_REG_READ(0x10000)|(0x8));
263 //32clk wait for External ETH PLL stable
266 HAL_WORD_REG_WRITE(0x52000, 0x70303);//read back 0x703f7
267 HAL_WORD_REG_WRITE(0x52008, 0x0e91c);//read back 0x1e948
269 HAL_WORD_REG_WRITE(MAGPIE_REG_SUSPEND_ENABLE_ADDR,
270 (HAL_WORD_REG_READ(MAGPIE_REG_SUSPEND_ENABLE_ADDR)|(BIT0))); //0x56030
271 // wake up, and turn on cpu, eth, pcie and usb pll
273 // restore gpio and other settings
274 _fw_restore_dma_fifo();
276 // clear suspend..................
277 HAL_WORD_REG_WRITE(MAGPIE_REG_SUSPEND_ENABLE_ADDR,
278 (HAL_WORD_REG_READ(MAGPIE_REG_SUSPEND_ENABLE_ADDR)&(~BIT0)));
279 HAL_WORD_REG_WRITE(0x52028, HAL_WORD_REG_READ(0x52028)&(~(BIT8|BIT12|BIT16)));
283 * -- patch zfResetUSBFIFO_patch --
285 * . clear ep3/ep4 fifo
286 * . set suspend magic pattern
287 * . reset pcie ep phy
288 * . reset pcie rc phy
289 * . turn off pcie pll
290 * . reset all pcie/gmac related registers
293 void zfResetUSBFIFO_patch(void)
295 A_PRINTF("0x9808 0x%x ......\n", HAL_WORD_REG_READ(0x10ff9808));
296 A_PRINTF("0x7890 0x%x ......\n", HAL_WORD_REG_READ(0x10ff7890));
297 A_PRINTF("0x7890 0x%x ......\n", HAL_WORD_REG_READ(0x10ff7890));
298 A_PRINTF("0x4088 0x%x ......\n", HAL_WORD_REG_READ(0x10ff4088));
299 _fw_reset_dma_fifo();
302 static void _fw_reset_dma_fifo()
304 HAL_BYTE_REG_WRITE(0x100ae, (HAL_BYTE_REG_READ(0x100ae)|0x10));
305 HAL_BYTE_REG_WRITE(0x100ae, (HAL_BYTE_REG_READ(0x100af)|0x10));
306 A_PRINTF("_fw_reset_dma_fifo\n");
308 // disable ep3 int enable, so that resume back won't send wdt magic pattern out!!!
309 mUSB_STATUS_IN_INT_DISABLE();
311 // update magic pattern to indicate this is a suspend
312 HAL_WORD_REG_WRITE(WATCH_DOG_MAGIC_PATTERN_ADDR, SUS_MAGIC_PATTERN);
314 A_PRINTF("org 0x4048 0x%x ......\n", HAL_WORD_REG_READ(0x10ff4048));
315 A_PRINTF("org 0x404C 0x%x ......\n", HAL_WORD_REG_READ(0x10ff404C));
316 A_PRINTF("org 0x4088 0x%x ......\n", HAL_WORD_REG_READ(0x10ff4088));
318 HAL_WORD_REG_WRITE(0x10ff4088,0xaaa6a);//1010.1010.1010.0110.1010 for UB94
319 HAL_WORD_REG_WRITE(0x10ff404C,0x0);
322 A_PRINTF("0x4048 0x%x ......\n", HAL_WORD_REG_READ(0x10ff4048));
323 A_PRINTF("0x404C 0x%x ......\n", HAL_WORD_REG_READ(0x10ff404C));
324 A_PRINTF("0x4088 0x%x ......\n", HAL_WORD_REG_READ(0x10ff4088));
329 A_PRINTF("turn_off_magpie_ep_start ......\n");
330 A_DELAY_USECS(measure_time);
331 HAL_WORD_REG_WRITE( 0x40040, (HAL_WORD_REG_READ(0x40040)|BIT0|(1<<1)));
333 HAL_WORD_REG_WRITE( 0x40040, (HAL_WORD_REG_READ(0x40040)&~(BIT0|(1<<1))));
334 A_PRINTF("turn_off_magpie_ep_end ......\n");
337 A_PRINTF("turn_off_magpie_rc_start ......\n");
338 A_DELAY_USECS(measure_time);
339 HAL_WORD_REG_WRITE( 0x40040, (HAL_WORD_REG_READ(0x40040)&(~BIT0)));
341 A_PRINTF("turn_off_magpie_rc_end ......down\n");
342 A_DELAY_USECS(measure_time);
344 A_PRINTF("0x4001C %p ......\n", HAL_WORD_REG_READ(0x4001c));
345 A_PRINTF("0x40040 %p ......\n", HAL_WORD_REG_READ(0x40040));
347 // turn off pcie_pll - power down (bit16)
348 A_PRINTF(" before pwd PCIE PLL CFG:0x5601C %p ......\n", HAL_WORD_REG_READ(0x5601C));
349 HAL_WORD_REG_WRITE(0x5601C, (HAL_WORD_REG_READ(0x5601C)|(BIT18)));
350 A_PRINTF(" after pwd PCIE PLL CFG:0x5601C %p ......\n", HAL_WORD_REG_READ(0x5601C));
352 /* set everything to reset state?, requested by Oligo */
353 HAL_WORD_REG_WRITE(0x50010, HAL_WORD_REG_READ(0x50010)|(BIT13|BIT12|BIT11|BIT9|BIT7|BIT6));
355 HAL_WORD_REG_WRITE(0x5C000, 0);
359 // reset usb DMA controller
360 HAL_WORD_REG_WRITE((USB_CTRL_BASE_ADDRESS+0x118), 0x0);
362 HAL_WORD_REG_WRITE(0x50010, (HAL_WORD_REG_READ(0x50010)|(BIT4)));
364 HAL_WORD_REG_WRITE(0x50010, (HAL_WORD_REG_READ(0x50010)&(~BIT4)));
367 HAL_WORD_REG_WRITE((USB_CTRL_BASE_ADDRESS+0x118), 0x1);
370 static void _fw_power_off()
374 * 2. turn off CPU PLL
375 * 3. turn off ETH PLL
376 * 4. disable ETH PLL bypass and update
377 * 4.1 set suspend timeout
378 * 5. set SUSPEND_ENABLE
381 HAL_WORD_REG_WRITE(MAGPIE_REG_CPU_PLL_BYPASS_ADDR, (BIT0|BIT4)); //0x56004
383 A_DELAY_USECS(100); // wait for stable
385 HAL_WORD_REG_WRITE(MAGPIE_REG_CPU_PLL_ADDR, (BIT16));//0x56000
387 A_DELAY_USECS(100); // wait for stable
389 A_UART_HWINIT((40*1000*1000), 19200);
392 HAL_WORD_REG_WRITE(MAGPIE_REG_ETH_PLL_ADDR,
393 (HAL_WORD_REG_READ(MAGPIE_REG_ETH_PLL_ADDR)|(BIT16))); //0x5600c
395 HAL_WORD_REG_WRITE(MAGPIE_REG_ETH_PLL_BYPASS_ADDR,
396 (HAL_WORD_REG_READ(MAGPIE_REG_ETH_PLL_BYPASS_ADDR)|(BIT4|BIT0))); //0x56010
398 HAL_WORD_REG_WRITE(MAGPIE_REG_SUSPEND_ENABLE_ADDR,
399 (HAL_WORD_REG_READ(MAGPIE_REG_SUSPEND_ENABLE_ADDR)|(0x10<<8))); //0x56030
402 static void _fw_power_on()
406 * 2. disable CPU bypass
408 * 4. disable ETH PLL bypass and update
409 * 5. turn on pcie pll
412 HAL_WORD_REG_WRITE(MAGPIE_REG_ETH_PLL_ADDR,
413 (HAL_WORD_REG_READ(MAGPIE_REG_ETH_PLL_ADDR)&(~BIT16)));
415 // deassert eth_pll bypass mode and trigger update bit
416 HAL_WORD_REG_WRITE(MAGPIE_REG_ETH_PLL_BYPASS_ADDR,
417 (HAL_WORD_REG_READ(MAGPIE_REG_ETH_PLL_BYPASS_ADDR)&(~(BIT4|BIT0))));
420 #define CMD_PCI_RC_RESET_ON() HAL_WORD_REG_WRITE(MAGPIE_REG_RST_RESET_ADDR, \
421 (HAL_WORD_REG_READ(MAGPIE_REG_RST_RESET_ADDR)| \
422 (PCI_RC_PHY_SHIFT_RESET_BIT|PCI_RC_PLL_RESET_BIT|PCI_RC_PHY_RESET_BIT|PCI_RC_RESET_BIT)))
424 static void _fw_restore_dma_fifo(void)
426 HAL_WORD_REG_WRITE(0x5601C, (HAL_WORD_REG_READ(0x5601C)&(~(BIT18))));
428 // reset pcie_rc shift
429 HAL_WORD_REG_WRITE(0x50010, (HAL_WORD_REG_READ(0x50010)&(~(BIT10|BIT8|BIT7))));
431 HAL_WORD_REG_WRITE(0x50010, (HAL_WORD_REG_READ(0x50010)|(BIT10|BIT8|BIT7)));
434 CMD_PCI_RC_RESET_ON();
437 // enable dma swap function
438 MAGPIE_REG_USB_RX0_SWAP_DATA = 0x1;
439 MAGPIE_REG_USB_TX0_SWAP_DATA = 0x1;
440 MAGPIE_REG_USB_RX1_SWAP_DATA = 0x1;
441 MAGPIE_REG_USB_RX2_SWAP_DATA = 0x1;
444 extern uint16_t *u8ConfigDescriptorEX;
445 extern uint16_t *pu8DescriptorEX;
446 extern uint16_t u16TxRxCounter;
447 extern SetupPacket ControlCmd;
449 extern uint16_t *u8UsbDeviceDescriptor;
451 extern BOOLEAN bGet_descriptor(void);
453 uint16_t ConfigDescriptorPatch[30];
455 uint16_t UsbDeviceDescriptorPatch[9];
456 #define BCD_DEVICE_OFFSET 6
457 #define BCD_DEVICE_FW_SIGNATURE 0xffff
458 #define VENDOR_ID_OFFSET 4
459 #define PRODUCT_ID_OFFSET 5
461 #define EP3_TRANSFER_TYPE_OFFSET 17
462 #define EP3_INT_INTERVAL 19
463 #define EP4_TRANSFER_TYPE_OFFSET 21
464 #define EP4_INT_INTERVAL 22
468 #define A_SFLASH_READ_4B(u32Data, start_addr) u32Data = *(uint32_t *)(0xf000000+start_addr);
469 #define FLASH_SIZE 0x800000 //8M
470 #define FLASH_USB_VENDOR_ID_OFFSET 0x86
471 #define FLASH_USB_PRODUCT_ID_OFFSET 0x87
473 // flash reserved size for saving eeprom data is 4K.
474 #define EE_DATA_RESERVED_LEN 0x1000 //4K
476 #define mLOW_MASK(u16) ((uint8_t) ((u16) & mMASK(8)))
477 #define mHIGH_MASK(u16) ((uint8_t) ((u16) & ~mMASK(8)))
480 //#define mLOW_BYTE(u16) ((U_8)(u16))
481 #define mLOW_BYTE(u16) mLOW_MASK(u16)
483 #define mHIGH_BYTE(u16) ((uint8_t) (((uint16_t) (u16)) >> 8))
485 #define mLOW_WORD0(u32) ((uint16_t) ((u32) & 0xFFFF))
486 #define mHIGH_WORD0(u32) ((uint16_t) ((u32) >> 16))
489 #define mSWAP_BYTE(u16) ((mLOW_MASK(u16) << 8) | mHIGH_BYTE(u16))
491 BOOLEAN bGet_descriptor_patch(void)
493 if (mDEV_REQ_VALUE_HIGH() == 1)
495 uint8_t *p = (uint8_t *)u8UsbDeviceDescriptor;
497 /* Copy Usb Device Descriptor */
498 ath_hal_memcpy(UsbDeviceDescriptorPatch, p, sizeof(UsbDeviceDescriptorPatch));
500 UsbDeviceDescriptorPatch[BCD_DEVICE_OFFSET] =
501 BCD_DEVICE_FW_SIGNATURE;
503 /* Patch for custom id from flash */
504 if (bEepromExist == FALSE) {
505 A_SFLASH_READ_4B(u32Tmp, FLASH_SIZE -
506 EE_DATA_RESERVED_LEN + FLASH_USB_VENDOR_ID_OFFSET*2);
507 UsbDeviceDescriptorPatch[VENDOR_ID_OFFSET] =
508 mSWAP_BYTE(mLOW_WORD0(u32Tmp));
509 UsbDeviceDescriptorPatch[PRODUCT_ID_OFFSET] =
510 mSWAP_BYTE(mHIGH_WORD0(u32Tmp));
513 pu8DescriptorEX = UsbDeviceDescriptorPatch;
514 u16TxRxCounter = mTABLE_LEN(u8UsbDeviceDescriptor[0]);
516 if (u16TxRxCounter > mDEV_REQ_LENGTH())
517 u16TxRxCounter = mDEV_REQ_LENGTH();
521 //u16TxRxCounter = 18;
524 if (mDEV_REQ_VALUE_HIGH() == 2) {
525 uint8_t *p = (uint8_t *)u8ConfigDescriptorEX;
527 /* Copy ConfigDescriptor */
528 ath_hal_memcpy(ConfigDescriptorPatch, p, sizeof(ConfigDescriptorPatch));
530 /* place holder for EPx patches */
532 switch (mDEV_REQ_VALUE_LOW())
534 case 0x00: // configuration no: 0
535 pu8DescriptorEX = ConfigDescriptorPatch;
536 u16TxRxCounter = ConfigDescriptorPatch[1];
537 //u16TxRxCounter = 46;
543 if (u16TxRxCounter > mDEV_REQ_LENGTH())
544 u16TxRxCounter = mDEV_REQ_LENGTH();
550 return bGet_descriptor();