699ce73a32bd9349581bf5744e7a441ba0d1e231
[linux-libre-firmware.git] / ath9k_htc / target_firmware / magpie_fw_dev / target / hif / usb_api_magpie_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 #include "adf_os_io.h"
44 #include "sys_cfg.h"
45
46 #define measure_time 0
47 #define measure_time_pll 10000000
48
49 extern Action eUsbCxFinishAction;
50 extern CommandType eUsbCxCommand;
51 extern BOOLEAN UsbChirpFinish;
52 extern USB_FIFO_CONFIG usbFifoConf;
53 extern uint16_t *pu8DescriptorEX;
54 extern uint16_t u16TxRxCounter;
55
56 void zfTurnOffPower_patch(void);
57
58 static void _fw_reset_dma_fifo();
59 static void _fw_restore_dma_fifo();
60 static void _fw_power_on();
61 static void _fw_power_off();
62
63 BOOLEAN bEepromExist = TRUE;
64 BOOLEAN bJumptoFlash = FALSE;
65
66 void _fw_usb_suspend_reboot()
67 {
68         /* reset usb/wlan dma */
69         _fw_reset_dma_fifo();
70
71         /* restore gpio setting and usb/wlan dma state */
72         _fw_restore_dma_fifo();
73
74         /* set clock to bypass mode - 40Mhz from XTAL */
75         iowrite32(MAGPIE_REG_CPU_PLL_BYPASS_ADDR, BIT0 | BIT4);
76
77         A_DELAY_USECS(100); /* wait for stable */
78
79         iowrite32(MAGPIE_REG_CPU_PLL_ADDR, BIT16);
80
81         A_DELAY_USECS(100); /* wait for stable */
82         A_UART_HWINIT((40*1000*1000), 19200);
83
84         A_CLOCK_INIT(40);
85
86         if (!bEepromExist) { /* jump to flash boot (eeprom data in flash) */
87                 bJumptoFlash = TRUE;
88                 A_PRINTF("Jump to Flash BOOT\n");
89                 app_start();
90         } else {
91                 A_PRINTF("receive the suspend command...\n");
92                 /* reboot..... */
93                 A_USB_JUMP_BOOT();
94         }
95
96 }
97
98 #define PCI_RC_RESET_BIT                            BIT6
99 #define PCI_RC_PHY_RESET_BIT                        BIT7
100 #define PCI_RC_PLL_RESET_BIT                        BIT8
101 #define PCI_RC_PHY_SHIFT_RESET_BIT                  BIT10
102
103 /*
104  * -- urn_off_merlin --
105  * . values suggested from Lalit
106  *
107  */
108 static void turn_off_merlin()
109 {
110         volatile uint32_t default_data[9];
111         uint32_t i=0;
112
113         if(1)
114         {
115                 A_PRINTF("turn_off_merlin_ep_start ......\n");
116                 A_DELAY_USECS(measure_time);
117                 default_data[0] = 0x9248fd00;
118                 default_data[1] = 0x24924924;
119                 default_data[2] = 0xa8000019;
120                 default_data[3] = 0x17160820;
121                 default_data[4] = 0x25980560;
122                 default_data[5] = 0xc1c00000;
123                 default_data[6] = 0x1aaabe40;
124                 default_data[7] = 0xbe105554;
125                 default_data[8] = 0x00043007;
126         
127                 for(i=0; i<9; i++)
128                 {
129                         A_DELAY_USECS(10);
130         
131                         iowrite32(0x10ff4040, default_data[i]);
132                 }
133                 A_DELAY_USECS(10);
134                 iowrite32(0x10ff4044, BIT0);
135                 A_PRINTF("turn_off_merlin_ep_end ......\n");
136         }
137 }
138
139 /*
140  * -- turn_off_phy --
141  *
142  * . write shift register to both pcie ep and rc
143  * . 
144  */
145
146 static void turn_off_phy()
147 {
148
149         volatile uint32_t default_data[9];
150         uint32_t i=0;
151
152         default_data[0] = 0x9248fd00;
153         default_data[1] = 0x24924924;
154         default_data[2] = 0xa8000019;
155         default_data[3] = 0x17160820;
156         default_data[4] = 0x25980560;
157         default_data[5] = 0xc1c00000;
158         default_data[6] = 0x1aaabe40;
159         default_data[7] = 0xbe105554;
160         default_data[8] = 0x00043007;
161
162         for(i=0; i<9; i++)
163         {
164                 // check for the done bit to be set 
165
166                 while (1)
167                 {
168                         if (ioread32(0x40028) & BIT31)
169                                 break;
170                 }
171         
172                 A_DELAY_USECS(1);
173     
174                 iowrite32(0x40024, default_data[i]);
175         }
176         iowrite32(0x40028, BIT0);
177 }
178
179 static void turn_off_phy_rc()
180 {
181     
182         volatile uint32_t default_data[9];
183         uint32_t i=0;
184     
185         A_PRINTF("turn_off_phy_rc\n");
186     
187         default_data[0] = 0x9248fd00;
188         default_data[1] = 0x24924924;
189         default_data[2] = 0xa8000019;
190         default_data[3] = 0x13160820;//PwdClk1MHz=0
191         default_data[4] = 0x25980560;
192         default_data[5] = 0xc1c00000;
193         default_data[6] = 0x1aaabe40;
194         default_data[7] = 0xbe105554;
195         default_data[8] = 0x00043007;
196         
197         for(i=0; i<9; i++)
198         {
199                 // check for the done bit to be set 
200      
201                 while (1)
202                 {
203                         if (ioread32(0x40028) & BIT31)
204                                 break;
205                 }
206
207                 A_DELAY_USECS(1);
208
209                 iowrite32(0x40024, default_data[i]);
210         }
211         iowrite32(0x40028, BIT0);
212 }
213
214 volatile uint32_t gpio_func = 0x0;
215 volatile uint32_t gpio = 0x0;
216
217 /*
218  * -- patch zfTurnOffPower --
219  *
220  * . set suspend counter to non-zero value
221  * . 
222  */
223 void zfTurnOffPower_patch(void)
224 {
225         A_PRINTF("+++ goto suspend ......\n");
226
227         /* setting the go suspend here, power down right away */
228         io32_set(0x10000, BIT3);
229
230         A_DELAY_USECS(100);
231
232         // TURN OFF ETH PLL
233         _fw_power_off();
234
235         //32clk wait for External ETH PLL stable
236         A_DELAY_USECS(100);
237     
238         iowrite32(0x52000, 0x70303); /* read back 0x703f7 */
239         iowrite32(0x52008, 0x0e91c); /* read back 0x1e948 */
240     
241         io32_set(MAGPIE_REG_SUSPEND_ENABLE_ADDR, BIT0);
242
243         // wake up, and turn on cpu, eth, pcie and usb pll 
244         _fw_power_on();
245         // restore gpio and other settings
246         _fw_restore_dma_fifo();
247
248         /* clear suspend */
249         io32_clr(MAGPIE_REG_SUSPEND_ENABLE_ADDR, BIT0);
250         io32_clr(0x52028, BIT8 | BIT12 | BIT16);
251 }
252
253 /*
254  * -- patch zfResetUSBFIFO_patch --
255  *
256  * . clear ep3/ep4 fifo
257  * . set suspend magic pattern
258  * . reset pcie ep phy
259  * . reset pcie rc phy
260  * . turn off pcie pll
261  * . reset all pcie/gmac related registers
262  * . reset usb dma
263  */
264 void zfResetUSBFIFO_patch(void)
265 {
266         A_PRINTF("0x9808  0x%x ......\n", ioread32(0x10ff9808));
267         A_PRINTF("0x7890  0x%x ......\n", ioread32(0x10ff7890));
268         A_PRINTF("0x7890  0x%x ......\n", ioread32(0x10ff7890));
269         A_PRINTF("0x4088  0x%x ......\n", ioread32(0x10ff4088));
270         _fw_reset_dma_fifo();
271 }
272
273 static void _fw_reset_dma_fifo()
274 {
275         io8_set(0x100ae, 0x10);
276         io8_set(0x100af, 0x10);
277         A_PRINTF("_fw_reset_dma_fifo\n");
278
279         // disable ep3 int enable, so that resume back won't send wdt magic pattern out!!!
280         mUSB_STATUS_IN_INT_DISABLE();
281
282         /* update magic pattern to indicate this is a suspend */
283         iowrite32(WATCH_DOG_MAGIC_PATTERN_ADDR, SUS_MAGIC_PATTERN);
284
285         A_PRINTF("org 0x4048  0x%x ......\n", ioread32(0x10ff4048));
286         A_PRINTF("org 0x404C  0x%x ......\n", ioread32(0x10ff404C));
287         A_PRINTF("org 0x4088  0x%x ......\n", ioread32(0x10ff4088));
288
289         /* 1010.1010.1010.0110.1010 for UB94 */
290         iowrite32(0x10ff4088, 0xaaa6a);
291         iowrite32(0x10ff404C, 0x0);
292
293         A_DELAY_USECS(1000);
294         A_PRINTF("0x4048  0x%x ......\n", ioread32(0x10ff4048));
295         A_PRINTF("0x404C  0x%x ......\n", ioread32(0x10ff404C));
296         A_PRINTF("0x4088  0x%x ......\n", ioread32(0x10ff4088));
297          
298         // turn off merlin
299         turn_off_merlin();
300         // pcie ep
301         A_PRINTF("turn_off_magpie_ep_start ......\n");
302         A_DELAY_USECS(measure_time);
303         io32_set(0x40040, BIT0 | BIT1);
304         turn_off_phy();
305         io32_clr(0x40040, BIT0 | BIT1);
306         A_PRINTF("turn_off_magpie_ep_end ......\n");
307
308         // pcie rc 
309         A_PRINTF("turn_off_magpie_rc_start ......\n");
310         A_DELAY_USECS(measure_time);
311         io32_clr(0x40040, BIT0);
312         turn_off_phy_rc();
313         A_PRINTF("turn_off_magpie_rc_end ......down\n");
314         A_DELAY_USECS(measure_time);
315
316         A_PRINTF("0x4001C  %p ......\n", ioread32(0x4001c));
317         A_PRINTF("0x40040  %p ......\n", ioread32(0x40040));
318     
319         /* turn off pcie_pll - power down (bit16) */
320         A_PRINTF(" before pwd PCIE PLL CFG:0x5601C: 0x%08x\n",
321                  ioread32(0x5601C));
322         io32_set(0x5601C, BIT18);
323         A_PRINTF(" after pwd PCIE PLL CFG:0x5601C:  0x%08x\n",
324                  ioread32(0x5601C));
325
326         /* set everything to reset state?, requested by Oligo */
327         io32_set(0x50010, BIT13 | BIT12
328                  | BIT11 | BIT9 | BIT7 | BIT6);
329
330         iowrite32(0x5C000, 0);
331
332         A_DELAY_USECS(10);
333
334         /* reset usb DMA controller */
335         iowrite32_usb(ZM_SOC_USB_DMA_RESET_OFFSET, 0x0);
336
337         io32_set(0x50010, BIT4);
338         A_DELAY_USECS(5);
339         io32_clr(0x50010, BIT4);
340
341         iowrite32_usb(ZM_SOC_USB_DMA_RESET_OFFSET, BIT0);
342 }
343
344 static void _fw_power_off()
345 {
346         /*
347          *  1. set CPU bypass
348          *  2. turn off CPU PLL
349          *  3. turn off ETH PLL
350          *  4. disable ETH PLL bypass and update
351          *  4.1 set suspend timeout 
352          *  5. set SUSPEND_ENABLE
353          */
354
355         iowrite32(MAGPIE_REG_CPU_PLL_BYPASS_ADDR, BIT0 | BIT4);
356
357         A_DELAY_USECS(100); // wait for stable
358
359         iowrite32(MAGPIE_REG_CPU_PLL_ADDR, BIT16);
360
361         A_DELAY_USECS(100); // wait for stable
362
363         A_UART_HWINIT((40*1000*1000), 19200);
364         A_CLOCK_INIT(40);
365
366         io32_set(MAGPIE_REG_ETH_PLL_ADDR, BIT16);
367
368         io32_set(MAGPIE_REG_ETH_PLL_BYPASS_ADDR, BIT4 | BIT0);
369
370         io32_set(MAGPIE_REG_SUSPEND_ENABLE_ADDR, 0x10 << 8);
371 }
372
373 static void _fw_power_on()
374
375     /*
376      *  1. turn on CPU PLL
377      *  2. disable CPU bypass
378      *  3. turn on ETH PLL
379      *  4. disable ETH PLL bypass and update
380      *  5. turn on pcie pll
381      */    
382
383         io32_clr(MAGPIE_REG_ETH_PLL_ADDR, BIT16);
384
385         /* deassert eth_pll bypass mode and trigger update bit */
386         io32_clr(MAGPIE_REG_ETH_PLL_BYPASS_ADDR, BIT4 | BIT0);
387 }
388
389 static void _fw_restore_dma_fifo(void)
390 {
391         io32_clr(0x5601C, BIT18);
392     
393         /* reset pcie_rc shift */
394         io32_clr(0x50010, BIT10 | BIT8 | BIT7);
395         A_DELAY_USECS(1);
396         io32_set(0x50010, BIT10 | BIT8 | BIT7);
397
398         /* reset pci_rc phy */
399         io32_set(MAGPIE_REG_RST_RESET_ADDR,
400                  PCI_RC_PHY_SHIFT_RESET_BIT
401                  | PCI_RC_PLL_RESET_BIT | PCI_RC_PHY_RESET_BIT
402                  | PCI_RC_RESET_BIT);
403         A_DELAY_USECS(20);
404
405         // enable dma swap function
406         MAGPIE_REG_USB_RX0_SWAP_DATA = 0x1;
407         MAGPIE_REG_USB_TX0_SWAP_DATA = 0x1;
408         MAGPIE_REG_USB_RX1_SWAP_DATA = 0x1;
409         MAGPIE_REG_USB_RX2_SWAP_DATA = 0x1;
410 }