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"
44 #include "adf_os_io.h"
48 void _fw_usb_suspend_reboot();
50 extern Action eUsbCxFinishAction;
51 extern CommandType eUsbCxCommand;
52 extern BOOLEAN UsbChirpFinish;
53 extern USB_FIFO_CONFIG usbFifoConf;
57 #define CHECK_SOF_LOOP_CNT 50
59 void _fw_usb_suspend_reboot()
61 volatile uint32_t gpio_in = 0;
62 volatile uint32_t pupd = 0;
63 volatile uint32_t t = 0;
64 volatile uint32_t sof_no=0,sof_no_new=0;
65 /* Set GO_TO_SUSPEND bit to USB main control register */
66 io8_clr_usb(ZM_INTR_SOURCE_7_OFFSET, BIT2);
67 A_PRINTF("!USB suspend\n\r");
69 /* keep the record of suspend */
70 #if defined(PROJECT_MAGPIE)
71 iowrite32(WATCH_DOG_MAGIC_PATTERN_ADDR, SUS_MAGIC_PATTERN);
72 #elif defined(PROJECT_K2)
73 iowrite32(MAGPIE_REG_RST_STATUS_ADDR, SUS_MAGIC_PATTERN);
74 #endif /* #if defined(PROJECT_MAGPIE) */
82 DEBUG_SYSTEM_STATE = (DEBUG_SYSTEM_STATE&(~0xffff)) | 0x1000;
85 /* reset ep3/ep4 fifo in case there
86 * is data which might affect resuming */
87 iowrite8(0x100ae, ioread8(0x100ae) | 0x10);
88 iowrite8(0x100ae, ioread8(0x100af) | 0x10);
90 /* config gpio to input before goto suspend */
92 /* disable JTAG/ICE */
93 jtag = ioread32(0x10004054);
94 iowrite32(0x10004054, jtag | BIT17);
97 spi = ioread32(0x50040);
98 iowrite32(0x50040, spi & ~BIT8);
100 /* set all GPIO to input */
101 gpio_in = ioread32(0x1000404c);
102 iowrite32(0x1000404c, 0x0);
104 /* set PU/PD for all GPIO except two UART pins */
105 pupd = ioread32(0x10004088);
106 iowrite32(0x10004088, 0xA982AA6A);
108 sof_no = ioread32(0x10004);
109 for (t = 0; t < CHECK_SOF_LOOP_CNT; t++)
111 A_DELAY_USECS(1000); /* delay 1ms */
112 sof_no_new = ioread32(0x10004);
114 if(sof_no_new == sof_no)
120 * Reset "printf" module patch point(RAM to ROM)
121 * when K2 warm start or suspend,
122 * which fixed the error issue cause by redownload
123 * another different firmware.
125 _indir_tbl.cmnos.printf._printf = save_cmnos_printf;
127 /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
128 * setting the go suspend here, power down right away!!!
130 if (t != CHECK_SOF_LOOP_CNT) /* not time out */
131 io32_set(0x10000, BIT3);
133 DEBUG_SYSTEM_STATE = (DEBUG_SYSTEM_STATE&(~0xffff)) | 0x1100;
135 #if 0 /* pll unstable, h/w bug? */
136 iowrite32(0x50040, 0x300 | 6 | (1>>1) << 12);
137 A_UART_HWINIT((40*1000*1000)/1, 19200);
139 /* restore gpio setting */
140 iowrite32(0x10004054, jtag);
141 iowrite32(0x50040, spi);
143 iowrite32(0x1000404c, gpio_in);
144 iowrite32(0x10004088, pupd);
146 DEBUG_SYSTEM_STATE = (DEBUG_SYSTEM_STATE&(~0xffff)) | 0x1200;
148 /* since we still need to touch mac_base address after resuming back,
149 * so that reset mac can't be done in ResetFifo function,
150 * move to here... whole mac control reset.... (bit1)
152 iowrite32(MAGPIE_REG_RST_PWDN_CTRL_ADDR, BIT1);
153 io32_set(MAGPIE_REG_RST_PWDN_CTRL_ADDR, BIT0);
154 iowrite32(MAGPIE_REG_RST_PWDN_CTRL_ADDR, 0);
157 /* disable ep3 int enable, so that resume back won't
158 * send wdt magic pattern out!!! */
159 mUSB_STATUS_IN_INT_DISABLE();
161 MAGPIE_REG_USB_RX0_SWAP_DATA = 0x1;
162 MAGPIE_REG_USB_TX0_SWAP_DATA = 0x1;
163 MAGPIE_REG_USB_RX1_SWAP_DATA = 0x1;
164 MAGPIE_REG_USB_RX2_SWAP_DATA = 0x1;
166 if (((DEBUG_SYSTEM_STATE&~(0x0000ffff))>>16 == 0x5342)) {
167 /* UART_SEL and SPI_SEL */
168 iowrite32(0x50040, 0x300 | 0 | (1 >> 1) << 12);
171 /* Jump to boot code */
177 * usb zero length interrupt should not clear by s/w, h/w will handle that
178 * complete suspend handle, configure gpio, turn off related function,
179 * slow down the pll for stable issue
181 void _fw_usb_fw_task(void)
183 register uint8_t usb_interrupt_level1;
184 register uint8_t usb_interrupt_level2;
186 usb_interrupt_level1 = ioread8_usb(ZM_INTR_GROUP_OFFSET);
187 #if 0 /* these endpoints are handled by DMA */
188 if (usb_interrupt_level1 & BIT5)
193 if (usb_interrupt_level1 & BIT4) {
194 usb_interrupt_level2 =
195 ioread8_usb(ZM_INTR_SOURCE_4_OFFSET);
197 if(usb_interrupt_level2 & BIT6)
198 A_USB_REG_OUT(); /* vUsb_Reg_Out() */
201 if (usb_interrupt_level1 & BIT6) {
202 /* zfGenWatchDogEvent(); ?? */
203 usb_interrupt_level2 =
204 ioread8_usb(ZM_INTR_SOURCE_6_OFFSET);
205 if(usb_interrupt_level2 & BIT6)
206 A_USB_STATUS_IN(); /* vUsb_Status_In() */
209 if (usb_interrupt_level1 & BIT0) {
210 usb_interrupt_level2 =
211 ioread8_usb(ZM_INTR_SOURCE_0_OFFSET);
213 /* refer to FUSB200, p 48, offset:21H, bit7 description,
214 * should clear the command abort interrupt first!?
216 if (usb_interrupt_level2 & BIT7) {
217 /* Handle command abort */
218 io8_clr_usb(ZM_INTR_SOURCE_0_OFFSET, BIT7);
219 A_PRINTF("![SOURCE_0] bit7 on\n\r");
222 if (usb_interrupt_level2 & BIT1)
223 A_USB_EP0_TX(); /* USB EP0 tx interrupt */
225 if (usb_interrupt_level2 & BIT2)
226 A_USB_EP0_RX(); /* USB EP0 rx interrupt */
228 if (usb_interrupt_level2 & BIT0) {
230 /* vWriteUSBFakeData() */
233 if (usb_interrupt_level2 & BIT3) {
235 eUsbCxCommand = CMD_VOID;
236 iowrite8_usb(ZM_CX_CONFIG_STATUS_OFFSET, 0x01);
240 if (usb_interrupt_level2 & BIT4)
241 iowrite8_usb(ZM_CX_CONFIG_STATUS_OFFSET, 0x04);
243 if (eUsbCxFinishAction == ACT_STALL) {
244 /* set CX_STL to stall Endpoint0 &
245 * will also clear FIFO0 */
246 iowrite8_usb(ZM_CX_CONFIG_STATUS_OFFSET, 0x04);
247 } else if (eUsbCxFinishAction == ACT_DONE) {
248 /* set CX_DONE to indicate the transmistion
249 * of control frame */
250 iowrite8_usb(ZM_CX_CONFIG_STATUS_OFFSET, 0x01);
252 eUsbCxFinishAction = ACT_IDLE;
255 if (usb_interrupt_level1 & BIT7) {
256 usb_interrupt_level2 =
257 ioread8_usb(ZM_INTR_SOURCE_7_OFFSET);
260 if (usb_interrupt_level2 & BIT7)
261 vUsb_Data_Out0Byte();
263 if (usb_interrupt_level2 & BIT6)
267 if (usb_interrupt_level2 & BIT1) {
268 io8_clr_usb(ZM_INTR_SOURCE_7_OFFSET, BIT1);
269 UsbChirpFinish = FALSE;
270 A_PRINTF("!USB reset\n\r");
272 if (usb_interrupt_level2 & BIT2) {
273 /* TBD: the suspend resume code should put here,
275 * issue, jump back to rom code and what peripherals
276 * should we reset here? */
277 _fw_usb_suspend_reboot();
279 if (usb_interrupt_level2 & BIT3) {
280 io8_clr_usb(ZM_INTR_SOURCE_7_OFFSET, BIT3);
281 A_PRINTF("!USB resume\n\r");
287 void _fw_usb_reset_fifo(void)
289 io8_set(0x100ae, 0x10);
290 io8_set(0x100af, 0x10);
292 /* disable ep3 int enable, so that resume back won't
293 * send wdt magic pattern out!!!
295 mUSB_STATUS_IN_INT_DISABLE();
297 /* update magic pattern to indicate this is a suspend
298 * k2: MAGPIE_REG_RST_WDT_TIMER_CTRL_ADDR
299 * magpie: MAGPIE_REG_RST_STATUS_ADDR
301 iowrite32(MAGPIE_REG_RST_STATUS_ADDR, SUS_MAGIC_PATTERN);
304 * Before USB suspend, USB DMA must be reset(refer to Otus)
305 * Otus runs the following statements only
306 * iowrite32( MAGPIE_REG_RST_PWDN_CTRL_ADDR, BIT0|BIT2 );
307 * iowrite32( MAGPIE_REG_RST_PWDN_CTRL_ADDR, 0x0 );
308 * K2 must run the following statements additionally
309 * reg_data = (A_UINT32 *)(USB_CTRL_BASE_ADDRESS + 0x118);
310 * *reg_data = 0x00000000;
311 * *reg_data = 0x00000001;
312 * because of Hardware bug in K2
314 iowrite32_usb(ZM_SOC_USB_DMA_RESET_OFFSET, 0x0);
316 /* reset both usb(bit2)/wlan(bit1) dma */
317 iowrite32(MAGPIE_REG_RST_PWDN_CTRL_ADDR, BIT2);
318 io32_set(MAGPIE_REG_RST_PWDN_CTRL_ADDR, BIT0);
319 iowrite32(MAGPIE_REG_RST_PWDN_CTRL_ADDR, 0x0);
321 iowrite32_usb(ZM_SOC_USB_DMA_RESET_OFFSET, BIT0);
323 /* MAC warem reset */
324 //reg_data = (uint32_t *)(K2_REG_MAC_BASE_ADDR + 0x7000);
325 //*reg_data = 0x00000001;
329 //*reg_data = 0x00000000;
331 //while (*reg_data) ;
333 A_PRINTF("\n change clock to 22 and go to suspend now!");
336 iowrite32(0x50040, 0x200 | 0 | (1 >> 1) << 12);
337 A_UART_HWINIT((22*1000*1000), 19200);