1 typedef signed short s16_t;
  2 typedef unsigned char u8_t;
  3 typedef unsigned short u16_t;
  4 typedef unsigned long u32_t;
  5 
  6 typedef struct {
  7     s16_t cpu_mhz;
  8     s16_t mem_mhz;
  9     s16_t lx_mhz;
 10     s16_t spif_mhz;
 11     s16_t snaf_mhz;
 12     s16_t sram_mhz;
 13 } cg_dev_freq_t;
 14 
 15 #define CG_QUERY_FREQUENCY(dev_type, dev_freq_sel) ({ \
 16     u32_t freq_ret; \
 17     switch(dev_type){ \
 18         case CG_DEV_OCP: \
 19             freq_ret = dev_freq_sel->cpu_mhz; break;\
 20         case CG_DEV_MEM: \
 21             freq_ret = dev_freq_sel->mem_mhz; break;\
 22         case CG_DEV_LX: \
 23             freq_ret = dev_freq_sel->lx_mhz; break;\
 24         case CG_DEV_SPIF: \
 25             freq_ret = dev_freq_sel->spif_mhz; break;\
 26         default: \
 27             freq_ret = (u32_t)(-1); \
 28     } \
 29     freq_ret; \
 30 })
 31 
 32 typedef struct {
 33         cg_dev_freq_t       dev_freq;
 34 } cg_info_t;
 35 
 36 typedef struct {
 37         cg_dev_freq_t cg_mhz;
 38         u16_t         spif_div;
 39         u16_t         snaf_div;
 40         u16_t         snaf_pl;
 41 } otto_soc_context_t;
 42 
 43 typedef struct clk_div_sel_info_s{
 44     u16_t divisor;
 45     u16_t div_to_ctrl;
 46 } clk_div_sel_info_t;
 47 
 48 typedef struct {
 49     // for record
 50     u16_t   ocp_pll;
 51     u16_t   sw_vco;
 52     // reg
 53     u32_t   cpu0;
 54     u32_t   cpum;
 55     u32_t   sram_reg;
 56     u32_t   sram_timing;
 57     u32_t   mem0;
 58     u32_t   mem1;
 59     u32_t   mem2;
 60     u32_t   mem3;
 61 
 62     u8_t    lx_pll_div;
 63     u8_t    spif_pll_div;
 64     u8_t    spif_ctrl_div;
 65     u8_t    snaf_ctrl_div;
 66     u8_t    snaf_pl;
 67     u8_t    oc_spif_slow;
 68     u8_t    sram_lx_slow;
 69     u8_t    oc_mem_slow;
 70     u8_t    lx_mem_slow;
 71 } cg_config_t;
 72 
 73 cg_info_t cg_info_query;
 74 extern otto_soc_context_t otto_sc;
 75 
 76 #define OTTO_SRAM_DEF_FREQ 250
 77 const cg_info_t cg_info_proj = {
 78         .dev_freq ={
 79         .cpu_mhz  = 800,
 80         .mem_mhz  = 600,
 81         .lx_mhz   = 175,
 82         .spif_mhz = 25,
 83         .sram_mhz = OTTO_SRAM_DEF_FREQ, // do not change this
 84         },
 85 };
 86 
 87 #define END_OF_INFO (0xFFFF)
 88 
 89 #ifdef SPINOR
 90 clk_div_sel_info_t sclk_divisor[] = {
 91     {
 92         .divisor     = 2,
 93         .div_to_ctrl = 0,
 94     },
 95     {
 96         .divisor     = 4,
 97         .div_to_ctrl = 1,
 98     },
 99     {
100         .divisor     = 6,
101         .div_to_ctrl = 2,
102     },
103     {
104         .divisor     = 8,
105         .div_to_ctrl = 3,
106     },
107     {
108         .divisor     = 10,
109         .div_to_ctrl = 4,
110     },
111     {
112         .divisor     = 12,
113         .div_to_ctrl = 5,
114     },
115     {
116         .divisor     = 14,
117         .div_to_ctrl = 6,
118     },
119     {
120         .divisor     = 16,
121         .div_to_ctrl = 7,
122     },
123     {   /* The end of structure*/
124         .divisor     = END_OF_INFO,
125     },
126 };
127 
128 u32_t get_spi_ctrl_divisor(void)
129 {
130     return RFLD_SFCR(spi_clk_div);
131 }
132 
133 u32_t get_default_spi_ctrl_divisor(void)
134 {
135     SFCR_T reg = {.v = SFCRdv};
136     return reg.f.spi_clk_div;
137 }
138 
139 void set_spi_ctrl_divisor(u16_t clk_div, u16_t spif_mhz)
140 {
141     RMOD_SFCR(spi_clk_div, clk_div);
142 }
143 #else // SPINAND
144 clk_div_sel_info_t sclk_divisor[] = {
145     {
146         .divisor     = 2,
147         .div_to_ctrl = 0,
148     },
149     {
150         .divisor     = 4,
151         .div_to_ctrl = 1,
152     },
153     {
154         .divisor     = 6,
155         .div_to_ctrl = 2,
156     },
157     {
158         .divisor     = 8,
159         .div_to_ctrl = 3,
160     },
161     {
162         .divisor     = 10,
163         .div_to_ctrl = 4,
164     },
165     {
166         .divisor     = 12,
167         .div_to_ctrl = 5,
168     },
169     {
170         .divisor     = 14,
171         .div_to_ctrl = 6,
172     },
173     {
174         .divisor     = 16,
175         .div_to_ctrl = 7,
176     },
177     {   /* The end of structure */
178         .divisor     = END_OF_INFO,
179     },
180 };
181 
182 u32_t get_spi_ctrl_divisor(void)
183 {
184     return RFLD_SNAFCFR(spi_clk_div);
185 }
186 
187 u32_t get_default_spi_ctrl_divisor(void)
188 {
189     SNAFCFR_T reg = {.v = SNAFCFRdv};
190     return reg.f.spi_clk_div;
191 }
192 
193 void set_spi_ctrl_divisor(u16_t clk_div, u16_t spif_mhz)
194 {
195     RMOD_SNAFCFR(spi_clk_div, clk_div);
196 }
197 
198 void set_spi_ctrl_latency(u16_t latency)
199 {
200     RMOD_SNAFCFR(pipe_lat, latency);
201 }
202 #endif
203 
204 #define VCO_FREQ(pdiv, div4, ncode)         ((25 * ((1 == (div4)) ? 4 : 1) * (2 * ((ncode) + 2))) / (1 << (pdiv)))
205 #define CPU_FREQ(vco, div2, div3)           ((vco) / (((div2) + 2) * ((div3) + 1)))   // div3: 0 for /1, 1 for /2, 2 reserved, 3 for /4
206 #define LNS_FREQ(vco, div2)                 ((vco) / (2 * ((div2) + 2)))  // LX, SPI-NOR/NAND, SWITCH
207 #define DLL_FREQ(vco, div2)                 ((vco) / (((div2) + 2) * 4))
208 #define LN_DIV(vco, pll)                    (((vco) / (2 * (pll))) - 2)   // LX, SPI_NOR/NAND DIV
209 #define MEM_FREQ(pdiv, ncode)               (25 * (ncode + 2) / (2 * (1 << pdiv)))
210 
211 #define MIN_LX_PLL    (133)
212 #define MAX_LX_PLL    (204)
213 #define MIN_CPU_PLL   (400)
214 #define MAX_CPU_PLL   (800)
215 #define MIN_SPIF_PLL  (133)
216 #define MAX_SPIF_PLL  (204)
217 #define MIN_SRAM_PLL  (250)
218 #define MAX_SRAM_PLL  (500)
219 #define MAX_SPIF_FREQ (105)
220 
221 static u32_t _cg_get_sw_vco(void) {
222     u32_t vco;
223     PLL_SW_CTRL0_T sw0 = { .v = PLL_SW_CTRL0rv };
224 
225     vco = VCO_FREQ(sw0.f.sw_cmu_sel_prediv,
226                    sw0.f.sw_cmu_sel_div4,
227                    sw0.f.sw_cmu_ncode_in);
228     return vco;
229 }
230 
231 static u32_t _cg_get_cpu_freq(u32_t cpu0, u32_t cpum) {
232     u32_t vco, freq;
233     PLL_CPU_CTRL0_T c0 = { .v = cpu0 };
234     PLL_CPU_MISC_CTRL_T cm = { .v = cpum };
235     vco = VCO_FREQ(c0.f.cpu_cmu_sel_prediv,
236                    c0.f.cpu_cmu_sel_div4,
237                    c0.f.cpu_cmu_ncode_in);
238 
239     freq = CPU_FREQ(vco, cm.f.reg_cmu_divn2_cpu, c0.f.cmu_divn3_cpu);
240     return freq;
241 }
242 
243 // Assembly functions
244 extern void fetch_and_lock_dcache_range(u32_t base_addr, u32_t end_addr);
245 extern void fetch_and_lock_icache_range(u32_t base_addr, u32_t end_addr);
246 extern void _change_cpu_sram_pll(u32_t cpu0_reg, u32_t cpum_reg, u32_t sram_pll_reg, u32_t sram_timing_reg);
247 
248 void cg_cpu_sram_pll_init(cg_config_t *cg_config) {
249     u32_t *addr = (u32_t *)_change_cpu_sram_pll;
250 
251     // locked 8KB cache
252     fetch_and_lock_icache_range((u32_t)(CACHE_ALIGN(addr)), (u32_t)((CACHE_ALIGN(addr)) + 0x2000));
253 //GSFUNC(fetch_and_lock_icache_range)
254 //        move    t0, a0
255 //        li      t1, CACHELINE_SIZE
256 //        move    t2, a1
257 //i_fl_loop:
258 //        cacheop(CACHE_OP_I_FETCH_LOCK, t0)
259 //        addu    t0, t1
260 //        bge     t2, t0, i_fl_loop
261 //        j ra
262 //END(fetch_and_lock_icache_range)
263 
264     // change cpu/sram pll and slow bit between ocp and SRAM/ROM
265     _change_cpu_sram_pll(cg_config->cpu0, cg_config->cpum, cg_config->sram_reg, cg_config->sram_timing);
266 //GSFUNC(_change_cpu_sram_pll)
267 //        .set    noreorder
268 //        // disable xxx, keep t7 as original CP0_CONFIG value
269 //        mfc0    t7, CP0_CONFIG, 7
270 //        ori     t1, t7, 0xC
271 //        mtc0    t1, CP0_CONFIG, 7
272 //        li      t8, 1       // keep t8 as 1
273 //
274 //        // Write and Read SRAM, clear ongoing sram traffic
275 //        li      t0, UNCACHE_SRAM_ADDR
276 //        lw      t1, 0(t0)
277 //        lw      t2, 4(t0)
278 //        sw      t1, 0(t0)
279 //        sw      t2, 4(t0)
280 //        lw      t1, 0(t0)
281 //        lw      t2, 4(t0)
282 //        li      t6, PLL_GLB_CTRL0ar
283 //        li      t5, SYS_STATUSar
284 //        li      t4, PLL_SW_DIV_CTRLar
285 //
286 //        // change pll to lx
287 //        lw      t1, 0(t5)
288 //        ins     t1, zero, 0x2, 0x1
289 //        sw      t1, 0(t5)
290 //
291 //        // configure cpu pll,
292 //        sw      a0, 8(t6)       // a0, cpu pll0
293 //        sw      a1, 16(t6)      // a1, cpu pllm
294 //
295 //        // SW_CMU_EN/CPU_CMU_EN trigger
296 //        li      t2, MODLE_NAME_INFOar
297 //        lw      t3, 0(t2)
298 //        ext     t3, t3, 0x4, 0x1 // ignore bit 5
299 //        beqz    t3, 2f
300 //        li      t1, 0x3
301 //        lw      t3, 0(t2)
302 //        ext     t3, t3, 0x0, 0x4 // version
303 //        bge     t3, t1, 2f
304 //        nop
305 //
306 //        lw      t1, 0(t4)
307 //        ins     t1, zero, 17, 0x1
308 //        sw      t1, 0(t4)
309 //        ins     t1, t8, 17, 0x1
310 //        b       1f
311 //        sw      t1, 0(t4)
312 //
313 //2:      lw      t1, 0(t6)
314 //        ins     t1, zero, 30, 0x1
315 //        sw      t1, 0(t6)
316 //        ins     t1, t8, 30, 0x1
317 //        sw      t1, 0(t6)
318 //
319 //        // polling ready
320 //1:      lw      t2, 0(t6)
321 //        ext     t3, t2, 0xF, 0x1
322 //        beqz    t3, 1b
323 //
324 //        // change pll to configued CPU freq.
325 //        lw      t1, 0(t5)
326 //        ins     t1, t8, 0x2, 0x1
327 //        sw      t1, 0(t5)
328 //        li      t5, PLL_SRAM_CTRLar
329 //        li      t4, CPU_SRAM_ASY_TIMINGar
330 //
331 //        // config sram pll and slow bit
332 //        sw      a2, 0(t5)       // a2, sram pll
333 //        sw      a3, 0(t4)       // a3, sram_async_timing
334 //        li      t0, 10000
335 //2:      bnez    t0, 2b
336 //        addiu   t0, t0, -1
337 //
338 //        // restore
339 //        mtc0    t7, CP0_CONFIG, 7
340 //        jr  ra
341 //        nop
342 //END(_change_cpu_sram_pll)
343 
344     // unlocked cache
345     icache_inv_all();
346 //GSFUNC(invalidate_icache_all)
347 //      mtc0    zero, CP0_ITAGLO
348 //      li      t0, CKSEG0
349 //      li      t2, ICACHE_SIZE
350 //      addu    t1, t0, t2
351 //1:
352 //      cacheop(Index_Invalidate_I, t0)
353 //      addiu   t0, t0, CACHELINE_SIZE
354 //      bne     t0, t1, 1b
355 //      jr      ra
356 //END(invalidate_icache_all)
357 }
358 
359 void cg_lx_pll_init(cg_config_t *cg_config) {
360     RMOD_PLL_GLB_CTRL0(lxb_clk_sel, 0x1); // set val 0x1, of bit lxb_clk_sel, in PLL_GLB_CTRL0
361     RMOD_PLL_SW_DIV_CTRL(cmu_divn2_lxb, cg_config->lx_pll_div);
362     RMOD_PLL_GLB_CTRL0(lxb_clk_sel, 0x0);
363 
364     u32_t cmu_divn2_lxb __attribute__ ((unused)) = RFLD_PLL_SW_DIV_CTRL(cmu_divn2_lxb);
365     RMOD_CPU_ASY_TIMING(sram_lx_pulse, cg_config->sram_lx_slow); // CPU SRAM register
366     // lx to dram will be set later
367     cg_udelay(50, cg_info_query.dev_freq.cpu_mhz);
368 }
369 
370 void cg_spif_pll_init(cg_config_t *cg_config) {
371 #ifdef OTTO_FLASH_NAND_SPI
372 // SPI-NAND
373     set_spi_ctrl_divisor(cg_config->snaf_ctrl_div , 0);
374     set_spi_ctrl_latency(cg_config->snaf_pl);
375 #else
376 // SPI-NOR
377     RMOD_PLL_GLB_CTRL0(nor_clk_sel, 1);
378     RMOD_PLL_SW_DIV_CTRL(cmu_divn2_spi_nor, cg_config->spif_pll_div );
379     otto_sc.spif_div = cg_config->spif_ctrl_div;
380     set_spi_ctrl_divisor(cg_config->spif_ctrl_div+(cg_info_query.dev_freq.spif_mhz>50)?1:0, 0);
381 
382     // for NOR+NAND, and will set in u-Boot
383     otto_sc.snaf_pl = cg_config->snaf_pl;
384     otto_sc.snaf_div = cg_config->snaf_ctrl_div;
385 
386     RMOD_CMU_BC_OC0(se_spif, cg_config->oc_spif_slow);
387     RMOD_PLL_GLB_CTRL0(nor_clk_sel, 0);
388 #endif  //ifdef OTTO_FLASH_NAND_SPI
389     cg_udelay(50, cg_info_query.dev_freq.cpu_mhz);
390 }
391 
392 int _cg_config_cpu(cg_config_t *cg_config) {
393     if(cg_info_query.dev_freq.cpu_mhz > MAX_CPU_PLL ||
394        cg_info_query.dev_freq.cpu_mhz < MIN_CPU_PLL)
395     {  return CPU_PLL_SET_FAIL; }
396 
397                       // parameters are from haitao
398                       //     400,  425,  450,  475,  500,  525,  550,  575,  600,
399                       //     625,  650,  675,  700,  725,  750,  775,  800
400     static u8_t ncode[] = { 0x2E, 0x31, 0x34, 0x37, 0x3A, 0x32, 0x35, 0x37, 0x2E,
401                             0x30, 0x32, 0x34, 0x36, 0x38, 0x3A, 0x3C, 0x3E};
402     static u8_t divn2[] = { 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x02,
403                             0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02};
404 
405     u32_t idx=(cg_info_query.dev_freq.cpu_mhz - MIN_CPU_PLL) / 25;
406 
407     cg_config->ocp_pll = (MIN_CPU_PLL + idx * 25) / 2;
408     PLL_CPU_CTRL0_T cpu0 = {.v = PLL_CPU_CTRL0rv };
409     PLL_CPU_MISC_CTRL_T cpum = {.v = PLL_CPU_MISC_CTRLrv };
410     PLL_SRAM_CTRL_T sram_reg = { .v = PLL_SRAM_CTRLrv };
411     CPU_SRAM_ASY_TIMING_T sram_timing = { .v = CPU_SRAM_ASY_TIMINGrv };
412 
413     cpu0.f.cpu_cmu_ncode_in = ncode[idx];
414     cpu0.f.cmu_divn3_cpu = 0;
415     cpum.f.reg_cmu_divn2_cpu = divn2[idx];
416 
417     cg_info_query.dev_freq.cpu_mhz = _cg_get_cpu_freq(cpu0.v, cpum.v);
418     cg_config->ocp_pll = cg_info_query.dev_freq.cpu_mhz / 2;
419 
420     // sram pll prepare, and slow bit check
421     if(cg_info_query.dev_freq.sram_mhz == MAX_SRAM_PLL) {
422         sram_reg.f.sram_pll_sel = 1;
423     } else {
424         sram_reg.f.sram_pll_sel = 0;
425     }
426 
427     if(cg_info_query.dev_freq.sram_mhz < cg_config->ocp_pll) {
428         sram_timing.f.sram_oc0_pulse = 0;
429     } else {
430         sram_timing.f.sram_oc0_pulse = 1;
431     }
432 
433     if(cg_config->ocp_pll < cg_info_query.dev_freq.sram_mhz) {
434         sram_timing.f.oc0_sram_pulse = 0;
435     } else if(cg_config->ocp_pll < (cg_info_query.dev_freq.sram_mhz << 1)) {
436         sram_timing.f.oc0_sram_pulse = 1;
437     } else {
438         sram_timing.f.oc0_sram_pulse = 2;
439     }
440 
441     cg_config->cpu0 = cpu0.v;
442     cg_config->cpum = cpum.v;
443     cg_config->sram_reg = sram_reg.v;
444     cg_config->sram_timing = sram_timing.v;
445 
446     return 0;
447 }
448 
449 int _cg_config_lx(cg_config_t *cg_config) {
450     cg_config->sw_vco = _cg_get_sw_vco();
451 
452     if (cg_info_query.dev_freq.lx_mhz < MIN_LX_PLL ||
453         cg_info_query.dev_freq.lx_mhz > MAX_LX_PLL)
454     { return LX_PLL_SET_FAIL; }
455 
456     //switch vco is fixed 2.4G, lx freq = vco / (2 * (div + 2))
457     u32_t div = LN_DIV(cg_config->sw_vco, cg_info_query.dev_freq.lx_mhz);
458     if(div > LN_DIV(cg_config->sw_vco, MIN_LX_PLL)) div = LN_DIV(cg_config->sw_vco, OTTO_LX_DEF_FREQ);  // reset to default 175
459     cg_config->lx_pll_div = div;
460 
461     cg_info_query.dev_freq.lx_mhz = LNS_FREQ(cg_config->sw_vco, div);
462 
463     // slow bit, lx to sram
464     u8_t slow = 0;
465     if((3 * cg_info_query.dev_freq.lx_mhz) <= cg_info_query.dev_freq.sram_mhz) { slow = 1; }
466     else { slow = 0; }
467     cg_config->sram_lx_slow = slow;
468     return 0;
469 }
470 
471 int _cg_config_spif(cg_config_t *cg_config) {
472     if(0 == cg_info_query.dev_freq.snaf_mhz)
473         cg_info_query.dev_freq.snaf_mhz = cg_info_query.dev_freq.spif_mhz;
474     if((cg_info_query.dev_freq.spif_mhz > MAX_SPIF_FREQ) ||
475        (cg_info_query.dev_freq.snaf_mhz > MAX_SPIF_FREQ))
476         return SPIF_PLL_SET_FAIL;
477     extern clk_div_sel_info_t sclk_divisor[];
478 
479     u32_t divc = 0, spif_mhz;
480     u32_t tmp_divc = 7, tmp_spif_mhz = 0;
481     while(END_OF_INFO!=sclk_divisor[divc].divisor) {
482         spif_mhz = cg_info_query.dev_freq.lx_mhz / sclk_divisor[divc].divisor;
483         if((spif_mhz <= cg_info_query.dev_freq.snaf_mhz) && (spif_mhz > tmp_spif_mhz)) {
484             tmp_divc = divc;
485             tmp_spif_mhz = spif_mhz;
486         }
487         ++divc;
488     }
489     cg_config->snaf_ctrl_div = tmp_divc;
490     cg_info_query.dev_freq.snaf_mhz = tmp_spif_mhz;
491     if(tmp_spif_mhz > 50) cg_config->snaf_pl = 2;
492     cg_config->snaf_pl = (tmp_spif_mhz > 50) ? 2 : 1;
493 
494 #ifndef OTTO_FLASH_NAND_SPI
495     // SPI-NOR
496     u32_t min_divp = LN_DIV(cg_config->sw_vco, MAX_SPIF_PLL);
497     u32_t max_divp = LN_DIV(cg_config->sw_vco, MIN_SPIF_PLL);
498     u32_t divp, tmp_divp=max_divp;
499     divc = 0; tmp_divc = 7; tmp_spif_mhz = 0;
500 
501     while(END_OF_INFO!=sclk_divisor[divc].divisor) {
502         for (divp=min_divp; divp<=max_divp; divp++) {
503             spif_mhz = LNS_FREQ(cg_config->sw_vco, divp)/sclk_divisor[divc].divisor;
504             if ((spif_mhz<=cg_info_query.dev_freq.spif_mhz) && (spif_mhz > tmp_spif_mhz)) {
505                 tmp_divp = divp;
506                 tmp_divc = divc;
507                 tmp_spif_mhz = spif_mhz;
508             }
509         }
510         ++divc;
511 }
512     cg_config->spif_pll_div = tmp_divp;
513     cg_config->spif_ctrl_div = sclk_divisor[tmp_divc].div_to_ctrl;
514     // slow bit check
515     cg_config->oc_spif_slow = (cg_config->ocp_pll > tmp_spif_mhz) ? 0 : 1;
516 #endif
517     // if nand only, spif_mhz = snaf_mhz, else nor: spif_mhz, nand: snaf_mhz
518     cg_info_query.dev_freq.spif_mhz = tmp_spif_mhz;
519 
520     return PLL_SET_DONE;
521 }
522 
523 u32_t cg_guery_mem_freq(u32_t _mem2, u32_t _mem3) {
524     /* MEM */
525     SYS_MEM_PLL_CTRL2_T mem2 = { .v = _mem2};
526     SYS_MEM_PLL_CTRL3_T mem3 = { .v = _mem3 };
527     return MEM_FREQ(mem2.f.pdiv, mem3.f.n_code);
528 }
529 
530 int _cg_config_mem(cg_config_t *cg_config) {
531     // ERROR Check?
532     // return Fail;
533     if (100 == cg_info_query.dev_freq.mem_mhz) {
534         cg_config->mem0 = SYS_MEM_PLL_CTRL0dv;
535         cg_config->mem1 = 0x000001EF;
536         cg_config->mem2 = 0x26226400;
537         cg_config->mem3 = 0x0E0F0000;
538     } else {
539                                 //     250,        275,        300,        325,        350,
540                                 //     375,        400,        425,        450,        475,
541                                 //     500,        525,        550,        575,        600,
542         static u32_t mem0[] = { 0x0008407F, 0x0008407F, 0x0008407F, 0x0008407F, 0x0008407F,
543                                 0x0008407F, 0x0000007F, 0x0008407F, 0x0008407F, 0x000C607F,
544                                 0x000C607F, 0x000C607F, 0x000C607F, 0x000C807F, 0x0000007F};
545         static u32_t mem1[] = { 0x4000018F, 0x4000018F, 0x4000018F, 0x4000018F, 0x4000018F,
546                                 0x4000018F, 0x400001EF, 0x4000018F, 0x4000018F, 0x4000018F,
547                                 0x4000018F, 0x4000018F, 0x4000018F, 0x4000018F, 0x400001EF};
548         static u32_t mem2[] = { 0x26222400, 0x26222400, 0x26222520, 0x26222520, 0x26222520,
549                                 0x26622520, 0x26622520, 0x26A23720, 0x26A23720, 0x26A23740,
550                                 0x26A23740, 0x26A33840, 0x26A33840, 0x26A33860, 0x26A33860};
551         static u32_t mem3[] = { 0x120F0000, 0x140F0000, 0x160F0000, 0x180F0000, 0x1A0F0000,
552                                 0x1C0F0000, 0x1E0F0000, 0x200F0000, 0x220F0000, 0x240F0000,
553                                 0x260F0000, 0x280F0000, 0x2A0F0000, 0x2C0F0000, 0x2E0F0000};
554         u32_t idx = (cg_info_query.dev_freq.mem_mhz - 250) / 25;
555         if(idx >= (sizeof(mem0) / sizeof(u32_t)))
556             idx = 0;
557 
558         cg_config->mem0 = mem0[idx];    //SYS_MEM_PLL_CTRL0dv;
559         cg_config->mem1 = mem1[idx];    //0x400001EF;
560         cg_config->mem2 = mem2[idx];
561         cg_config->mem3 = mem3[idx];
562     }
563 
564     cg_info_query.dev_freq.mem_mhz = cg_guery_mem_freq(cg_config->mem2, cg_config->mem3);
565 
566     cg_config->oc_mem_slow = (cg_config->ocp_pll > cg_info_query.dev_freq.mem_mhz)?0:1;
567     cg_config->lx_mem_slow = (cg_info_query.dev_freq.lx_mhz > cg_info_query.dev_freq.mem_mhz)?0:1;
568     return PLL_SET_DONE;
569 }
570 
571 SECTION_CG
572 void cg_mem_pll_init(cg_config_t *cg_config) {
573     CG_MEM_PLL_OE_DIS();
574     cg_udelay(200, cg_info_query.dev_freq.cpu_mhz);
575 
576     SYS_MEM_PLL_CTRL0rv = cg_config->mem0;
577     SYS_MEM_PLL_CTRL1rv = cg_config->mem1;
578     SYS_MEM_PLL_CTRL2rv = cg_config->mem2;
579     SYS_MEM_PLL_CTRL3rv = cg_config->mem3;
580     SYS_MEM_PLL_CTRL5rv = SYS_MEM_PLL_CTRL5dv;
581     SYS_MEM_PLL_CTRL6rv = SYS_MEM_PLL_CTRL6dv;
582     cg_udelay(5, cg_info_query.dev_freq.cpu_mhz);
583     CG_MEM_PLL_OE_EN();
584     cg_udelay(200, cg_info_query.dev_freq.cpu_mhz);
585 
586     // OC v.s MEM slow bit
587     RMOD_CMU_BC_OC0(se_dram, cg_config->oc_mem_slow);
588 
589     // LX v.s MEM slow bit
590     RMOD_CMU_BC_LX0(se_dram, cg_config->lx_mem_slow);
591     RMOD_CMU_BC_LX1(se_dram, cg_config->lx_mem_slow);
592     RMOD_CMU_BC_LX2(se_dram, cg_config->lx_mem_slow);
593     RMOD_CMU_BC_LXP(se_dram, cg_config->lx_mem_slow);
594     cg_udelay(50, cg_info_query.dev_freq.cpu_mhz);
595 }
596 
597 void cg_mem_pll_config_dqs_pi(u32_t dqs0_pi, u32_t dqs1_pi) {
598     SYS_MEM_PLL_CTRL0_T pll0 = { .v = SYS_MEM_PLL_CTRL0rv };
599 
600     CG_MEM_PLL_OE_DIS();
601     pll0.f.post_pi_sel2 = dqs0_pi;         // DQS0
602     pll0.f.post_pi_sel3 = dqs1_pi;         // DQS1
603     SYS_MEM_PLL_CTRL0rv = pll0.v;
604     cg_udelay(5, cg_info_query.dev_freq.cpu_mhz);
605     CG_MEM_PLL_OE_EN();
606     cg_udelay(200, cg_info_query.dev_freq.cpu_mhz);
607 }
608 
609 void cg_mem_pll_config_dq_pi(u32_t dq0_7_pi, u32_t dq8_15_pi) {
610     SYS_MEM_PLL_CTRL1_T pll1 = { .v = SYS_MEM_PLL_CTRL1rv };
611 
612     CG_MEM_PLL_OE_DIS();
613     pll1.f.post_pi_sel4 = dq0_7_pi;
614     pll1.f.post_pi_sel5 = dq8_15_pi;
615     SYS_MEM_PLL_CTRL1rv = pll1.v;
616     cg_udelay(5, cg_info_query.dev_freq.cpu_mhz);
617     CG_MEM_PLL_OE_EN();
618     cg_udelay(200, cg_info_query.dev_freq.cpu_mhz);
619 }
620 int cg_config_transform(cg_config_t *cg_config) {
621     u32_t res;
622 
623     // config CPU
624     res  = _cg_config_cpu(cg_config);
625     res |= _cg_config_lx(cg_config);
626     res |= _cg_config_spif(cg_config);
627     res |= _cg_config_mem(cg_config);
628     return res;
629 }
630 
631 void cg_config_apply(cg_config_t *cg_config) {
632     cg_cpu_sram_pll_init(cg_config); /* CPU PLL */
633     cg_lx_pll_init(cg_config);       /* LX PLL */
634     cg_spif_pll_init(cg_config);     /* SPI-NOR or SPI-NAND PLL */
635     cg_mem_pll_init(cg_config);      /* MEM PLL */
636 }
637 
638 u32_t cg_udelay(u32_t us, u32_t mhz) {
639         u32_t loop_cnt = us * mhz / 2;
640         while (loop_cnt--) {
641                 ;
642         }
643         return loop_cnt;
644 }
645 
646 u32_t cg_query_freq(u32_t dev_type) {
647     return CG_QUERY_FREQUENCY(dev_type,(&cg_info_query.dev_freq));
648 }
649 
650 void cg_copy_info_to_sram(void) {
651     // assume snaf = spif
652     inline_memcpy(&cg_info_query, &cg_info_proj, sizeof(cg_info_t));
653 }
654 
655 void cg_init(void) {
656     int res = 0;
657     cg_config_t cg_config;
658 
659     res = cg_config_transform(&cg_config);
660     if (res != PLL_SET_DONE) {
661         printf("WW: CG Init Failed, res=0x%x\n", res);
662     }
663 
664     cg_config_apply(&cg_config);
665     if (0 == (res & LX_PLL_SET_FAIL) && uart_baud_rate != 0) {
666         // re-init uart, lx_mhz might be changed
667         uart_init(uart_baud_rate, cg_info_query.dev_freq.lx_mhz);
668     }
669 
670     printf("II: CPU %dMHz, MEM %dMHz, LX %dMHz, SPIF %dMHz\n",
671         cg_info_query.dev_freq.cpu_mhz,
672         cg_info_query.dev_freq.mem_mhz,
673         cg_info_query.dev_freq.lx_mhz,
674         cg_info_query.dev_freq.spif_mhz);
675 }
676 
677 REG_INIT_FUNC(cg_copy_info_to_sram, 11);
678 REG_INIT_FUNC(cg_init, 13);
679 symb_pdefine(cg_info_dev_freq, SF_SYS_CG_DEV_FREQ, &(cg_info_query.dev_freq));