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"
47 void _fw_usb_suspend_reboot();
49 extern Action eUsbCxFinishAction;
50 extern CommandType eUsbCxCommand;
51 extern BOOLEAN UsbChirpFinish;
52 extern USB_FIFO_CONFIG usbFifoConf;
55 #define vUsb_ep0end(void) \
57 eUsbCxCommand = CMD_VOID; \
58 USB_BYTE_REG_WRITE(ZM_CX_CONFIG_STATUS_OFFSET, 0x01); \
61 #define vUsb_ep0fail(void) USB_BYTE_REG_WRITE(ZM_CX_CONFIG_STATUS_OFFSET, 0x04)
65 USB_BYTE_REG_WRITE(ZM_INTR_SOURCE_7_OFFSET, \
66 (USB_BYTE_REG_READ(ZM_INTR_SOURCE_7_OFFSET)&~BIT1)); \
67 UsbChirpFinish = FALSE; \
70 #define vUsb_suspend() USB_BYTE_REG_WRITE(ZM_INTR_SOURCE_7_OFFSET, \
71 (USB_BYTE_REG_READ(ZM_INTR_SOURCE_7_OFFSET)&~BIT2))
73 #define vUsb_resm() USB_BYTE_REG_WRITE(ZM_INTR_SOURCE_7_OFFSET, \
74 (USB_BYTE_REG_READ(ZM_INTR_SOURCE_7_OFFSET)&~BIT3))
76 #define CHECK_SOF_LOOP_CNT 50
78 void _fw_usb_suspend_reboot()
80 volatile uint32_t gpio_in = 0;
81 volatile uint32_t pupd = 0;
82 volatile uint32_t t = 0;
83 volatile uint32_t sof_no=0,sof_no_new=0;
84 /* Set GO_TO_SUSPEND bit to USB main control register */
86 A_PRINTF("!USB suspend\n\r");
88 /* keep the record of suspend */
89 #if defined(PROJECT_MAGPIE)
90 *((volatile uint32_t*)WATCH_DOG_MAGIC_PATTERN_ADDR) = SUS_MAGIC_PATTERN;
91 #elif defined(PROJECT_K2)
92 HAL_WORD_REG_WRITE(MAGPIE_REG_RST_STATUS_ADDR, SUS_MAGIC_PATTERN);
93 #endif /* #if defined(PROJECT_MAGPIE) */
101 DEBUG_SYSTEM_STATE = (DEBUG_SYSTEM_STATE&(~0xffff)) | 0x1000;
103 /* reset ep3/ep4 fifo in case there
104 * is data which might affect resuming */
105 // HAL_BYTE_REG_WRITE(0x100ae, (HAL_BYTE_REG_READ(0x100ae)|0x10));
106 // HAL_BYTE_REG_WRITE(0x100ae, (HAL_BYTE_REG_READ(0x100af)|0x10));
109 /* config gpio to input before goto suspend */
111 /* disable JTAG/ICE */
112 //jtag = HAL_WORD_REG_READ(0x10004054);
113 //HAL_WORD_REG_WRITE(0x10004054, (jtag|BIT17));
116 //spi = HAL_WORD_REG_READ(0x50040);
117 //HAL_WORD_REG_WRITE(0x50040, (spi&~(BIT8)));
119 /* set all GPIO to input */
120 gpio_in = HAL_WORD_REG_READ(0x1000404c);
121 HAL_WORD_REG_WRITE(0x1000404c, 0x0);
123 /* set PU/PD for all GPIO except two UART pins */
124 pupd = HAL_WORD_REG_READ(0x10004088);
125 HAL_WORD_REG_WRITE(0x10004088, 0xA982AA6A);
128 sof_no= HAL_WORD_REG_READ(0x10004);
129 for (t = 0; t < CHECK_SOF_LOOP_CNT; t++)
131 A_DELAY_USECS(1000); /* delay 1ms */
132 sof_no_new = HAL_WORD_REG_READ(0x10004);
134 if(sof_no_new == sof_no)
140 * Reset "printf" module patch point(RAM to ROM)
141 * when K2 warm start or suspend,
142 * which fixed the error issue cause by redownload
143 * another different firmware.
145 _indir_tbl.cmnos.printf._printf = save_cmnos_printf;
147 /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
148 * setting the go suspend here, power down right away!!!
150 if (t != CHECK_SOF_LOOP_CNT) /* not time out */
151 HAL_WORD_REG_WRITE(0x10000, HAL_WORD_REG_READ(0x10000)|(0x8));
153 DEBUG_SYSTEM_STATE = (DEBUG_SYSTEM_STATE&(~0xffff)) | 0x1100;
155 #if 0 /* pll unstable, h/w bug? */
156 HAL_WORD_REG_WRITE(0x50040, (0x300|6|(1>>1)<<12));
157 A_UART_HWINIT((40*1000*1000)/1, 19200);
159 /* restore gpio setting */
160 //HAL_WORD_REG_WRITE(0x10004054, jtag);
161 //HAL_WORD_REG_WRITE(0x50040, spi);
162 HAL_WORD_REG_WRITE(0x1000404c, gpio_in);
163 HAL_WORD_REG_WRITE(0x10004088, pupd);
165 DEBUG_SYSTEM_STATE = (DEBUG_SYSTEM_STATE&(~0xffff)) | 0x1200;
167 /* since we still need to touch mac_base address after resuming back,
168 * so that reset mac can't be done in ResetFifo function,
169 * move to here... whole mac control reset.... (bit1)
171 HAL_WORD_REG_WRITE(MAGPIE_REG_RST_PWDN_CTRL_ADDR, (BIT1));
172 HAL_WORD_REG_WRITE(MAGPIE_REG_RST_PWDN_CTRL_ADDR,
173 (HAL_WORD_REG_READ(MAGPIE_REG_RST_PWDN_CTRL_ADDR)|BIT0));
174 HAL_WORD_REG_WRITE(MAGPIE_REG_RST_PWDN_CTRL_ADDR, 0x0);
177 //A_PRINTF("reg(0x10020)=(%x)\n", HAL_WORD_REG_READ(0x10020));
178 /* disable ep3 int enable, so that resume back won't
179 * send wdt magic pattern out!!! */
180 mUSB_STATUS_IN_INT_DISABLE();
182 MAGPIE_REG_USB_RX0_SWAP_DATA = 0x1;
183 MAGPIE_REG_USB_TX0_SWAP_DATA = 0x1;
184 MAGPIE_REG_USB_RX1_SWAP_DATA = 0x1;
185 MAGPIE_REG_USB_RX2_SWAP_DATA = 0x1;
187 if (((DEBUG_SYSTEM_STATE&~(0x0000ffff))>>16 == 0x5342)) {
188 /* UART_SEL and SPI_SEL */
189 HAL_WORD_REG_WRITE(0x50040, (0x300|0|(1>>1)<<12));
192 /* Jump to boot code */
198 * usb zero length interrupt should not clear by s/w, h/w will handle that
199 * complete suspend handle, configure gpio, turn off related function,
200 * slow down the pll for stable issue
202 void _fw_usb_fw_task(void)
204 register uint8_t usb_interrupt_level1;
205 register uint8_t usb_interrupt_level2;
207 usb_interrupt_level1 = USB_BYTE_REG_READ(ZM_INTR_GROUP_OFFSET);
208 #if 0 /* these endpoints are handled by DMA */
209 if (usb_interrupt_level1 & BIT5)
214 if (usb_interrupt_level1 & BIT4) {
215 usb_interrupt_level2 =
216 USB_BYTE_REG_READ(ZM_INTR_SOURCE_4_OFFSET);
218 if(usb_interrupt_level2 & BIT6)
219 A_USB_REG_OUT(); /* vUsb_Reg_Out() */
222 if (usb_interrupt_level1 & BIT6) {
223 /* zfGenWatchDogEvent(); ?? */
224 usb_interrupt_level2 =
225 USB_BYTE_REG_READ(ZM_INTR_SOURCE_6_OFFSET);
226 if(usb_interrupt_level2 & BIT6)
227 A_USB_STATUS_IN(); /* vUsb_Status_In() */
230 if (usb_interrupt_level1 & BIT0) {
231 usb_interrupt_level2 =
232 USB_BYTE_REG_READ(ZM_INTR_SOURCE_0_OFFSET);
234 /* refer to FUSB200, p 48, offset:21H, bit7 description,
235 * should clear the command abort interrupt first!?
237 if (usb_interrupt_level2 & BIT7) {
238 /* Handle command abort */
239 USB_BYTE_REG_WRITE(ZM_INTR_SOURCE_0_OFFSET,
240 (USB_BYTE_REG_READ(ZM_INTR_SOURCE_0_OFFSET)
242 A_PRINTF("![SOURCE_0] bit7 on\n\r");
245 if (usb_interrupt_level2 & BIT1)
246 A_USB_EP0_TX(); /* USB EP0 tx interrupt */
248 if (usb_interrupt_level2 & BIT2)
249 A_USB_EP0_RX(); /* USB EP0 rx interrupt */
251 if (usb_interrupt_level2 & BIT0) {
253 /* vWriteUSBFakeData() */
256 if (usb_interrupt_level2 & BIT3)
259 if (usb_interrupt_level2 & BIT4)
262 if (eUsbCxFinishAction == ACT_STALL) {
263 /* set CX_STL to stall Endpoint0 &
264 * will also clear FIFO0 */
265 USB_BYTE_REG_WRITE(ZM_CX_CONFIG_STATUS_OFFSET, 0x04);
266 } else if (eUsbCxFinishAction == ACT_DONE) {
267 /* set CX_DONE to indicate the transmistion
268 * of control frame */
269 USB_BYTE_REG_WRITE(ZM_CX_CONFIG_STATUS_OFFSET, 0x01);
271 eUsbCxFinishAction = ACT_IDLE;
274 if (usb_interrupt_level1 & BIT7) {
275 usb_interrupt_level2 =
276 USB_BYTE_REG_READ(ZM_INTR_SOURCE_7_OFFSET);
279 if (usb_interrupt_level2 & BIT7)
280 vUsb_Data_Out0Byte();
282 if (usb_interrupt_level2 & BIT6)
286 if (usb_interrupt_level2 & BIT1) {
288 A_PRINTF("!USB reset\n\r");
289 // A_PRINTF("![0x1012c]: %\n\r", USB_WORD_REG_READ(0x12c));
291 if (usb_interrupt_level2 & BIT2) {
292 /* TBD: the suspend resume code should put here,
294 * issue, jump back to rom code and what peripherals
295 * should we reset here? */
296 _fw_usb_suspend_reboot();
298 if (usb_interrupt_level2 & BIT3) {
300 A_PRINTF("!USB resume\n\r");
306 void _fw_usb_reset_fifo(void)
308 volatile uint32_t *reg_data;
310 HAL_BYTE_REG_WRITE(0x100ae, (HAL_BYTE_REG_READ(0x100ae)|0x10));
311 HAL_BYTE_REG_WRITE(0x100af, (HAL_BYTE_REG_READ(0x100af)|0x10));
313 /* disable ep3 int enable, so that resume back won't
314 * send wdt magic pattern out!!!
316 mUSB_STATUS_IN_INT_DISABLE();
318 /* update magic pattern to indicate this is a suspend
319 * k2: MAGPIE_REG_RST_WDT_TIMER_CTRL_ADDR
320 * magpie: MAGPIE_REG_RST_STATUS_ADDR
322 HAL_WORD_REG_WRITE(MAGPIE_REG_RST_STATUS_ADDR, SUS_MAGIC_PATTERN);
325 * Before USB suspend, USB DMA must be reset(refer to Otus)
326 * Otus runs the following statements only
327 * HAL_WORD_REG_WRITE( MAGPIE_REG_RST_PWDN_CTRL_ADDR, BIT0|BIT2 );
328 * HAL_WORD_REG_WRITE( MAGPIE_REG_RST_PWDN_CTRL_ADDR, 0x0 );
329 * K2 must run the following statements additionally
330 * reg_data = (A_UINT32 *)(USB_CTRL_BASE_ADDRESS + 0x118);
331 * *reg_data = 0x00000000;
332 * *reg_data = 0x00000001;
333 * because of Hardware bug in K2
335 USB_WORD_REG_WRITE(ZM_SOC_USB_DMA_RESET_OFFSET, 0x0);
337 /* reset both usb(bit2)/wlan(bit1) dma */
338 HAL_WORD_REG_WRITE(MAGPIE_REG_RST_PWDN_CTRL_ADDR, (BIT2));
339 HAL_WORD_REG_WRITE(MAGPIE_REG_RST_PWDN_CTRL_ADDR,
340 (HAL_WORD_REG_READ(MAGPIE_REG_RST_PWDN_CTRL_ADDR)|BIT0));
341 HAL_WORD_REG_WRITE(MAGPIE_REG_RST_PWDN_CTRL_ADDR, 0x0);
343 USB_WORD_REG_WRITE(ZM_SOC_USB_DMA_RESET_OFFSET, BIT0);
345 /* MAC warem reset */
346 //reg_data = (uint32_t *)(K2_REG_MAC_BASE_ADDR + 0x7000);
347 //*reg_data = 0x00000001;
351 //*reg_data = 0x00000000;
353 //while (*reg_data) ;
355 A_PRINTF("\n change clock to 22 and go to suspend now!");
358 HAL_WORD_REG_WRITE(0x50040, (0x200|0|(1>>1)<<12));
359 A_UART_HWINIT((22*1000*1000), 19200);