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