Setting up repository
[linux-libre-firmware.git] / ath9k_htc / target_firmware / magpie_fw_dev / target / cmnos / cmnos_clock.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 "sys_cfg.h"
36
37 #if SYSTEM_MODULE_CLOCK
38 #include "athos_api.h"
39
40 LOCAL A_UINT32 cticks = 0;
41
42 #define  A_BAND_DEFAULT 0       // not ust now, avoiding compile error/warning, Ryan
43
44 LOCAL int curr_band = A_BAND_DEFAULT;
45 LOCAL void cmnos_pll_init(void);
46
47 /* We accept frequencies within this deviation from an expected frequency.  */
48 #define A_REFCLK_DEVIATION 800000
49
50 #define A_REFCLK_UNKNOWN  SYS_CFG_REFCLK_UNKNOWN
51 #define A_REFCLK_10_MHZ     SYS_CFG_REFCLK_10_MHZ
52 #define A_REFCLK_20_MHZ     SYS_CFG_REFCLK_20_MHZ
53 #define A_REFCLK_40_MHZ     SYS_CFG_REFCLK_40_MHZ
54
55 LOCAL const struct cmnos_clock_s {
56     A_refclk_speed_t refclk_speed;
57     A_UINT32         ticks_per_sec;
58     // below are useless so far, ryan
59     A_UINT32         pll_ctrl_5ghz;
60     A_UINT32         pll_ctrl_24ghz;
61     A_UINT32         pll_settling_time;      /* 50us */
62 } cmnos_clocking_table[] = {
63     {A_REFCLK_10_MHZ,
64      //10485760, 
65      10000000,
66      0x0,  
67      0x0,
68      0x0},
69
70     {A_REFCLK_20_MHZ,   
71      //20971520, 
72      20000000,
73      0x0,  
74      0x0,
75      0x0},
76
77     {A_REFCLK_40_MHZ,
78      //41943040, 
79      40000000, 
80      0x0,
81      0x0,
82      0x0},
83
84     {A_REFCLK_UNKNOWN,         
85      0, 
86      0x0, 
87      0x0,
88      0x0},
89 };
90
91
92 #define CMNOS_CLOCKING_TABLE_NUM_ENTRIES \
93     (sizeof(cmnos_clocking_table)/sizeof(cmnos_clocking_table[0]))
94
95 LOCAL struct cmnos_clock_s *clock_info;
96
97
98 LOCAL void cmnos_tick(void);
99
100 /*
101  * In case we have PLL initialization problems, software can arrange
102  * (e.g. through BMI) to skip PLL initialization, and other software
103  * can handle it.
104  */
105 int cmnos_skip_pll_init = 0;
106 A_UINT32 pll_ctrl_setting_24ghz = 0;
107 A_UINT32 pll_ctrl_setting_5ghz = 0;
108
109 /*
110  * Use default hardware values for clock-related registers.
111  * The defaults can be overridden through BMI, EJTAG, or patches.
112  *
113  * CPU clock frequencies depend on what mode we're in (2.4GHz or 5GHz):
114  * NB: AR6001 has a "reduced power" mode, but we don't use it.
115  *
116  *     AR6001/AR6002 FPGA CPU clock is always at 40MHz
117  *
118  *     AR6001 Rev 2.x supports 4 CPU speed selections:
119  *       selector:  0   1    2       3
120  *         2.4GHz: 44, 88, 141, refclk
121  *         5  GHz: 40, 80, 128, refclk
122  *
123  *     AR6002 supports 7 CPU/SoC speed selections via CORE_CLK:
124  *           CORE_CLK.DIV setting: 6,7    5     4     3   2     1   0
125  *                        divisor: 16    14    12    10   8     6   4
126  *         2.4GHz (pll at 352MHz): 22  25.1, 29.3, 35.2, 44, 58.7, 88
127  *         5  GHz (pll at 320MHz): 20  22.9, 26.7,   32, 40, 53.3, 80
128  */
129
130 #if defined(DISABLE_SYNC_DURING_PLL_UPDATE_WAR)
131 A_UINT32 cpu_clock_setting;
132 #endif
133
134 //A_COMPILE_TIME_ASSERT(verify_host_interest_small_enough,
135 //                (sizeof(struct host_interest_s) <= HOST_INTEREST_MAX_SIZE))
136
137 //A_COMPILE_TIME_ASSERT(verify_flash_is_present_addr,
138 //                ((A_UINT32)&HOST_INTEREST->hi_flash_is_present) == FLASH_IS_PRESENT_TARGADDR)
139
140
141 LOCAL void
142 cmnos_delay_us(int us)
143 {
144 //    A_UINT32 start_time = A_RTC_REG_READ(LF_TIMER_COUNT0_ADDRESS);
145 //    unsigned int num_LF_ticks = (us+29) / 30 + 1; /* ~30.5us per LF tick */
146     //A_UINT32 ref_clk = (clock_info->ticks_per_sec)/1000/1000;
147     A_UINT32 ref_clk = (clock_info->ticks_per_sec) >> 20;
148     A_UINT32 start_time = NOW();
149     unsigned int num_ticks = us*ref_clk; // system_freq == number of ticks per 1us
150     
151     while ( (NOW() - start_time) < num_ticks) {
152         /* busy spin */;
153     }
154 }
155
156 /*
157  * Return the number of milliseconds since startup.
158  * For this purpose, a "millisecond" is approximated by
159  * 1/32 of a 32KHz clock.
160  */
161 LOCAL A_UINT32
162 cmnos_milliseconds(void)
163 {
164     //unsigned int lowfreq_timer;
165
166     //lowfreq_timer = A_RTC_REG_READ(LF_TIMER_COUNT0_ADDRESS);
167     //lowfreq_timer = NOW();
168
169     /* LF0 timer counts at 32KHz, so adjust to approximate Ms with >> 5.  */
170     //lowfreq_timer = lowfreq_timer;
171
172     /*
173      * NB: We do not account for wrap, which occurs every 36
174      * hours when the 32768Hz low frequency timer wraps the
175      * 32 bit counter.
176      */
177     cmnos_tick();
178
179     return cticks;
180 }
181
182
183 /* Expect 40MHz on AR6001 and 26MHz on AR6002 */
184 //LOCAL A_refclk_speed_t cmnos_refclk_speed;
185
186 LOCAL A_UINT32
187 cmnos_refclk_speed_get(void)
188 {
189     return clock_info->ticks_per_sec;
190 }
191
192 /* The UART is clocked at the reference clock frequency. */
193 LOCAL A_UINT32
194 cmnos_uart_frequency(void)
195 {
196 #if 0
197 #if defined(FPGA)
198     return clock_info->ticks_per_sec;
199 #else
200     return clock_info->ticks_per_sec;
201 #endif
202 #else
203     /* TBD */
204     /* do we need keep a struct to hold the data ?*/
205 #endif
206 }
207
208
209 /*
210  * Adjust any state that needs adjusting when the clock
211  * speed changes.
212  */
213 LOCAL void
214 cmnos_sysclk_change(void)
215 {
216     /* OS may override this function */
217 }
218
219
220 LOCAL void
221 cmnos_clockregs_init(void)
222 {
223     /* TBD */
224     /* we might don't need this init() */
225 }
226
227 /*
228  * Make whatever system-level changes are needed in order to operate
229  * in the specified wireless band.
230  *
231  * For AR6K, we just need to set the PLL appropriately.
232  */
233 LOCAL void
234 cmnos_wlan_band_set(int which_band)
235 {
236     /* TBD */
237     /* we don't have wlan need to config */
238 }
239
240 LOCAL void
241 cmnos_pll_init(void)
242 {
243     /* TBD */
244     /* we don't have pll now, */
245 }
246
247 LOCAL void
248 cmnos_clock_init(A_UINT32 ref_clk)
249 {
250 #if 1
251     unsigned int i;
252
253     /* Look up the nearest supported frequency. */
254     for (i = 0;
255          i < CMNOS_CLOCKING_TABLE_NUM_ENTRIES-1;
256          i++)
257     {
258         A_UINT32 ticks_per_sec;
259
260         ticks_per_sec = cmnos_clocking_table[i].ticks_per_sec;
261         if ((ref_clk > ticks_per_sec - A_REFCLK_DEVIATION) &&
262             (ref_clk < ticks_per_sec + A_REFCLK_DEVIATION))
263         {
264             break;
265         }
266     }
267
268     clock_info = (struct cmnos_clock_s *)&cmnos_clocking_table[i];
269 //    HOST_INTEREST->hi_clock_info = (A_UINT32)clock_info;
270     
271 #endif
272 }
273
274 ////////////////////////////////////////////////////////////////////////
275 // software emulate ticks on millisecond based
276 LOCAL void
277 cmnos_tick(void)
278 {
279 #if 0
280     
281     set_ccompare0(xthal_get_ccompare(XTENSA_TIMER_0)+ONE_MSEC);
282
283     cticks++;
284
285 #else
286   static A_UINT32 last_tick = 0;
287     A_UINT32 current_tick = NOW();
288     A_UINT32 delta_tick;
289
290     // tick is 32 bit register, will overflow soon
291     if( current_tick < last_tick )
292     {
293         delta_tick = (A_UINT32 )((0xffffffff-last_tick)+current_tick+1)/(1000);
294     }
295     else
296     {
297         delta_tick = (A_UINT32 ) (current_tick - last_tick)/(1000);
298     }
299
300         if( delta_tick > 0 )
301             last_tick = current_tick;
302
303         cticks += delta_tick;
304 #endif
305 }
306
307 ////////////////////////////////////////////////////////////////////////
308
309 void
310 cmnos_clock_module_install(struct clock_api *tbl)
311 {
312     tbl->_clock_init         = cmnos_clock_init;
313     tbl->_clockregs_init     = cmnos_clockregs_init;
314     tbl->_delay_us           = cmnos_delay_us;
315     tbl->_wlan_band_set      = cmnos_wlan_band_set;
316     tbl->_refclk_speed_get   = cmnos_refclk_speed_get;
317     tbl->_milliseconds       = cmnos_milliseconds;
318     tbl->_uart_frequency     = cmnos_uart_frequency;
319     tbl->_sysclk_change      = cmnos_sysclk_change;
320
321     tbl->_clock_tick         = cmnos_tick;
322 }
323 #endif /* SYSTEM_MODULE_CLOCK */
324