typedef signed short s16_t;
typedef unsigned char u8_t;
typedef unsigned short u16_t;
typedef unsigned long u32_t;
typedef struct {
s16_t cpu_mhz;
s16_t mem_mhz;
s16_t lx_mhz;
s16_t spif_mhz;
s16_t snaf_mhz;
s16_t sram_mhz;
} cg_dev_freq_t;
#define CG_QUERY_FREQUENCY(dev_type, dev_freq_sel) ({ \
u32_t freq_ret; \
switch(dev_type){ \
case CG_DEV_OCP: \
freq_ret = dev_freq_sel->cpu_mhz; break;\
case CG_DEV_MEM: \
freq_ret = dev_freq_sel->mem_mhz; break;\
case CG_DEV_LX: \
freq_ret = dev_freq_sel->lx_mhz; break;\
case CG_DEV_SPIF: \
freq_ret = dev_freq_sel->spif_mhz; break;\
default: \
freq_ret = (u32_t)(-1); \
} \
freq_ret; \
})
typedef struct {
cg_dev_freq_t dev_freq;
} cg_info_t;
typedef struct {
cg_dev_freq_t cg_mhz;
u16_t spif_div;
u16_t snaf_div;
u16_t snaf_pl;
} otto_soc_context_t;
typedef struct clk_div_sel_info_s{
u16_t divisor;
u16_t div_to_ctrl;
} clk_div_sel_info_t;
typedef struct {
// for record
u16_t ocp_pll;
u16_t sw_vco;
// reg
u32_t cpu0;
u32_t cpum;
u32_t sram_reg;
u32_t sram_timing;
u32_t mem0;
u32_t mem1;
u32_t mem2;
u32_t mem3;
u8_t lx_pll_div;
u8_t spif_pll_div;
u8_t spif_ctrl_div;
u8_t snaf_ctrl_div;
u8_t snaf_pl;
u8_t oc_spif_slow;
u8_t sram_lx_slow;
u8_t oc_mem_slow;
u8_t lx_mem_slow;
} cg_config_t;
cg_info_t cg_info_query;
extern otto_soc_context_t otto_sc;
#define OTTO_SRAM_DEF_FREQ 250
const cg_info_t cg_info_proj = {
.dev_freq ={
.cpu_mhz = 800,
.mem_mhz = 600,
.lx_mhz = 175,
.spif_mhz = 25,
.sram_mhz = OTTO_SRAM_DEF_FREQ, // do not change this
},
};
#define END_OF_INFO (0xFFFF)
#ifdef SPINOR
clk_div_sel_info_t sclk_divisor[] = {
{
.divisor = 2,
.div_to_ctrl = 0,
},
{
.divisor = 4,
.div_to_ctrl = 1,
},
{
.divisor = 6,
.div_to_ctrl = 2,
},
{
.divisor = 8,
.div_to_ctrl = 3,
},
{
.divisor = 10,
.div_to_ctrl = 4,
},
{
.divisor = 12,
.div_to_ctrl = 5,
},
{
.divisor = 14,
.div_to_ctrl = 6,
},
{
.divisor = 16,
.div_to_ctrl = 7,
},
{ /* The end of structure*/
.divisor = END_OF_INFO,
},
};
u32_t get_spi_ctrl_divisor(void)
{
return RFLD_SFCR(spi_clk_div);
}
u32_t get_default_spi_ctrl_divisor(void)
{
SFCR_T reg = {.v = SFCRdv};
return reg.f.spi_clk_div;
}
void set_spi_ctrl_divisor(u16_t clk_div, u16_t spif_mhz)
{
RMOD_SFCR(spi_clk_div, clk_div);
}
#else // SPINAND
clk_div_sel_info_t sclk_divisor[] = {
{
.divisor = 2,
.div_to_ctrl = 0,
},
{
.divisor = 4,
.div_to_ctrl = 1,
},
{
.divisor = 6,
.div_to_ctrl = 2,
},
{
.divisor = 8,
.div_to_ctrl = 3,
},
{
.divisor = 10,
.div_to_ctrl = 4,
},
{
.divisor = 12,
.div_to_ctrl = 5,
},
{
.divisor = 14,
.div_to_ctrl = 6,
},
{
.divisor = 16,
.div_to_ctrl = 7,
},
{ /* The end of structure */
.divisor = END_OF_INFO,
},
};
u32_t get_spi_ctrl_divisor(void)
{
return RFLD_SNAFCFR(spi_clk_div);
}
u32_t get_default_spi_ctrl_divisor(void)
{
SNAFCFR_T reg = {.v = SNAFCFRdv};
return reg.f.spi_clk_div;
}
void set_spi_ctrl_divisor(u16_t clk_div, u16_t spif_mhz)
{
RMOD_SNAFCFR(spi_clk_div, clk_div);
}
void set_spi_ctrl_latency(u16_t latency)
{
RMOD_SNAFCFR(pipe_lat, latency);
}
#endif
#define VCO_FREQ(pdiv, div4, ncode) ((25 * ((1 == (div4)) ? 4 : 1) * (2 * ((ncode) + 2))) / (1 << (pdiv)))
#define CPU_FREQ(vco, div2, div3) ((vco) / (((div2) + 2) * ((div3) + 1))) // div3: 0 for /1, 1 for /2, 2 reserved, 3 for /4
#define LNS_FREQ(vco, div2) ((vco) / (2 * ((div2) + 2))) // LX, SPI-NOR/NAND, SWITCH
#define DLL_FREQ(vco, div2) ((vco) / (((div2) + 2) * 4))
#define LN_DIV(vco, pll) (((vco) / (2 * (pll))) - 2) // LX, SPI_NOR/NAND DIV
#define MEM_FREQ(pdiv, ncode) (25 * (ncode + 2) / (2 * (1 << pdiv)))
#define MIN_LX_PLL (133)
#define MAX_LX_PLL (204)
#define MIN_CPU_PLL (400)
#define MAX_CPU_PLL (800)
#define MIN_SPIF_PLL (133)
#define MAX_SPIF_PLL (204)
#define MIN_SRAM_PLL (250)
#define MAX_SRAM_PLL (500)
#define MAX_SPIF_FREQ (105)
static u32_t _cg_get_sw_vco(void) {
u32_t vco;
PLL_SW_CTRL0_T sw0 = { .v = PLL_SW_CTRL0rv };
vco = VCO_FREQ(sw0.f.sw_cmu_sel_prediv,
sw0.f.sw_cmu_sel_div4,
sw0.f.sw_cmu_ncode_in);
return vco;
}
static u32_t _cg_get_cpu_freq(u32_t cpu0, u32_t cpum) {
u32_t vco, freq;
PLL_CPU_CTRL0_T c0 = { .v = cpu0 };
PLL_CPU_MISC_CTRL_T cm = { .v = cpum };
vco = VCO_FREQ(c0.f.cpu_cmu_sel_prediv,
c0.f.cpu_cmu_sel_div4,
c0.f.cpu_cmu_ncode_in);
freq = CPU_FREQ(vco, cm.f.reg_cmu_divn2_cpu, c0.f.cmu_divn3_cpu);
return freq;
}
// Assembly functions
extern void fetch_and_lock_dcache_range(u32_t base_addr, u32_t end_addr);
extern void fetch_and_lock_icache_range(u32_t base_addr, u32_t end_addr);
extern void _change_cpu_sram_pll(u32_t cpu0_reg, u32_t cpum_reg, u32_t sram_pll_reg, u32_t sram_timing_reg);
void cg_cpu_sram_pll_init(cg_config_t *cg_config) {
u32_t *addr = (u32_t *)_change_cpu_sram_pll;
// locked 8KB cache
fetch_and_lock_icache_range((u32_t)(CACHE_ALIGN(addr)), (u32_t)((CACHE_ALIGN(addr)) + 0x2000));
//GSFUNC(fetch_and_lock_icache_range)
// move t0, a0
// li t1, CACHELINE_SIZE
// move t2, a1
//i_fl_loop:
// cacheop(CACHE_OP_I_FETCH_LOCK, t0)
// addu t0, t1
// bge t2, t0, i_fl_loop
// j ra
//END(fetch_and_lock_icache_range)
// change cpu/sram pll and slow bit between ocp and SRAM/ROM
_change_cpu_sram_pll(cg_config->cpu0, cg_config->cpum, cg_config->sram_reg, cg_config->sram_timing);
//GSFUNC(_change_cpu_sram_pll)
// .set noreorder
// // disable xxx, keep t7 as original CP0_CONFIG value
// mfc0 t7, CP0_CONFIG, 7
// ori t1, t7, 0xC
// mtc0 t1, CP0_CONFIG, 7
// li t8, 1 // keep t8 as 1
//
// // Write and Read SRAM, clear ongoing sram traffic
// li t0, UNCACHE_SRAM_ADDR
// lw t1, 0(t0)
// lw t2, 4(t0)
// sw t1, 0(t0)
// sw t2, 4(t0)
// lw t1, 0(t0)
// lw t2, 4(t0)
// li t6, PLL_GLB_CTRL0ar
// li t5, SYS_STATUSar
// li t4, PLL_SW_DIV_CTRLar
//
// // change pll to lx
// lw t1, 0(t5)
// ins t1, zero, 0x2, 0x1
// sw t1, 0(t5)
//
// // configure cpu pll,
// sw a0, 8(t6) // a0, cpu pll0
// sw a1, 16(t6) // a1, cpu pllm
//
// // SW_CMU_EN/CPU_CMU_EN trigger
// li t2, MODLE_NAME_INFOar
// lw t3, 0(t2)
// ext t3, t3, 0x4, 0x1 // ignore bit 5
// beqz t3, 2f
// li t1, 0x3
// lw t3, 0(t2)
// ext t3, t3, 0x0, 0x4 // version
// bge t3, t1, 2f
// nop
//
// lw t1, 0(t4)
// ins t1, zero, 17, 0x1
// sw t1, 0(t4)
// ins t1, t8, 17, 0x1
// b 1f
// sw t1, 0(t4)
//
//2: lw t1, 0(t6)
// ins t1, zero, 30, 0x1
// sw t1, 0(t6)
// ins t1, t8, 30, 0x1
// sw t1, 0(t6)
//
// // polling ready
//1: lw t2, 0(t6)
// ext t3, t2, 0xF, 0x1
// beqz t3, 1b
//
// // change pll to configued CPU freq.
// lw t1, 0(t5)
// ins t1, t8, 0x2, 0x1
// sw t1, 0(t5)
// li t5, PLL_SRAM_CTRLar
// li t4, CPU_SRAM_ASY_TIMINGar
//
// // config sram pll and slow bit
// sw a2, 0(t5) // a2, sram pll
// sw a3, 0(t4) // a3, sram_async_timing
// li t0, 10000
//2: bnez t0, 2b
// addiu t0, t0, -1
//
// // restore
// mtc0 t7, CP0_CONFIG, 7
// jr ra
// nop
//END(_change_cpu_sram_pll)
// unlocked cache
icache_inv_all();
//GSFUNC(invalidate_icache_all)
// mtc0 zero, CP0_ITAGLO
// li t0, CKSEG0
// li t2, ICACHE_SIZE
// addu t1, t0, t2
//1:
// cacheop(Index_Invalidate_I, t0)
// addiu t0, t0, CACHELINE_SIZE
// bne t0, t1, 1b
// jr ra
//END(invalidate_icache_all)
}
void cg_lx_pll_init(cg_config_t *cg_config) {
RMOD_PLL_GLB_CTRL0(lxb_clk_sel, 0x1); // set val 0x1, of bit lxb_clk_sel, in PLL_GLB_CTRL0
RMOD_PLL_SW_DIV_CTRL(cmu_divn2_lxb, cg_config->lx_pll_div);
RMOD_PLL_GLB_CTRL0(lxb_clk_sel, 0x0);
u32_t cmu_divn2_lxb __attribute__ ((unused)) = RFLD_PLL_SW_DIV_CTRL(cmu_divn2_lxb);
RMOD_CPU_ASY_TIMING(sram_lx_pulse, cg_config->sram_lx_slow); // CPU SRAM register
// lx to dram will be set later
cg_udelay(50, cg_info_query.dev_freq.cpu_mhz);
}
void cg_spif_pll_init(cg_config_t *cg_config) {
#ifdef OTTO_FLASH_NAND_SPI
// SPI-NAND
set_spi_ctrl_divisor(cg_config->snaf_ctrl_div , 0);
set_spi_ctrl_latency(cg_config->snaf_pl);
#else
// SPI-NOR
RMOD_PLL_GLB_CTRL0(nor_clk_sel, 1);
RMOD_PLL_SW_DIV_CTRL(cmu_divn2_spi_nor, cg_config->spif_pll_div );
otto_sc.spif_div = cg_config->spif_ctrl_div;
set_spi_ctrl_divisor(cg_config->spif_ctrl_div+(cg_info_query.dev_freq.spif_mhz>50)?1:0, 0);
// for NOR+NAND, and will set in u-Boot
otto_sc.snaf_pl = cg_config->snaf_pl;
otto_sc.snaf_div = cg_config->snaf_ctrl_div;
RMOD_CMU_BC_OC0(se_spif, cg_config->oc_spif_slow);
RMOD_PLL_GLB_CTRL0(nor_clk_sel, 0);
#endif //ifdef OTTO_FLASH_NAND_SPI
cg_udelay(50, cg_info_query.dev_freq.cpu_mhz);
}
int _cg_config_cpu(cg_config_t *cg_config) {
if(cg_info_query.dev_freq.cpu_mhz > MAX_CPU_PLL ||
cg_info_query.dev_freq.cpu_mhz < MIN_CPU_PLL)
{ return CPU_PLL_SET_FAIL; }
// parameters are from haitao
// 400, 425, 450, 475, 500, 525, 550, 575, 600,
// 625, 650, 675, 700, 725, 750, 775, 800
static u8_t ncode[] = { 0x2E, 0x31, 0x34, 0x37, 0x3A, 0x32, 0x35, 0x37, 0x2E,
0x30, 0x32, 0x34, 0x36, 0x38, 0x3A, 0x3C, 0x3E};
static u8_t divn2[] = { 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x02,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02};
u32_t idx=(cg_info_query.dev_freq.cpu_mhz - MIN_CPU_PLL) / 25;
cg_config->ocp_pll = (MIN_CPU_PLL + idx * 25) / 2;
PLL_CPU_CTRL0_T cpu0 = {.v = PLL_CPU_CTRL0rv };
PLL_CPU_MISC_CTRL_T cpum = {.v = PLL_CPU_MISC_CTRLrv };
PLL_SRAM_CTRL_T sram_reg = { .v = PLL_SRAM_CTRLrv };
CPU_SRAM_ASY_TIMING_T sram_timing = { .v = CPU_SRAM_ASY_TIMINGrv };
cpu0.f.cpu_cmu_ncode_in = ncode[idx];
cpu0.f.cmu_divn3_cpu = 0;
cpum.f.reg_cmu_divn2_cpu = divn2[idx];
cg_info_query.dev_freq.cpu_mhz = _cg_get_cpu_freq(cpu0.v, cpum.v);
cg_config->ocp_pll = cg_info_query.dev_freq.cpu_mhz / 2;
// sram pll prepare, and slow bit check
if(cg_info_query.dev_freq.sram_mhz == MAX_SRAM_PLL) {
sram_reg.f.sram_pll_sel = 1;
} else {
sram_reg.f.sram_pll_sel = 0;
}
if(cg_info_query.dev_freq.sram_mhz < cg_config->ocp_pll) {
sram_timing.f.sram_oc0_pulse = 0;
} else {
sram_timing.f.sram_oc0_pulse = 1;
}
if(cg_config->ocp_pll < cg_info_query.dev_freq.sram_mhz) {
sram_timing.f.oc0_sram_pulse = 0;
} else if(cg_config->ocp_pll < (cg_info_query.dev_freq.sram_mhz << 1)) {
sram_timing.f.oc0_sram_pulse = 1;
} else {
sram_timing.f.oc0_sram_pulse = 2;
}
cg_config->cpu0 = cpu0.v;
cg_config->cpum = cpum.v;
cg_config->sram_reg = sram_reg.v;
cg_config->sram_timing = sram_timing.v;
return 0;
}
int _cg_config_lx(cg_config_t *cg_config) {
cg_config->sw_vco = _cg_get_sw_vco();
if (cg_info_query.dev_freq.lx_mhz < MIN_LX_PLL ||
cg_info_query.dev_freq.lx_mhz > MAX_LX_PLL)
{ return LX_PLL_SET_FAIL; }
//switch vco is fixed 2.4G, lx freq = vco / (2 * (div + 2))
u32_t div = LN_DIV(cg_config->sw_vco, cg_info_query.dev_freq.lx_mhz);
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
cg_config->lx_pll_div = div;
cg_info_query.dev_freq.lx_mhz = LNS_FREQ(cg_config->sw_vco, div);
// slow bit, lx to sram
u8_t slow = 0;
if((3 * cg_info_query.dev_freq.lx_mhz) <= cg_info_query.dev_freq.sram_mhz) { slow = 1; }
else { slow = 0; }
cg_config->sram_lx_slow = slow;
return 0;
}
int _cg_config_spif(cg_config_t *cg_config) {
if(0 == cg_info_query.dev_freq.snaf_mhz)
cg_info_query.dev_freq.snaf_mhz = cg_info_query.dev_freq.spif_mhz;
if((cg_info_query.dev_freq.spif_mhz > MAX_SPIF_FREQ) ||
(cg_info_query.dev_freq.snaf_mhz > MAX_SPIF_FREQ))
return SPIF_PLL_SET_FAIL;
extern clk_div_sel_info_t sclk_divisor[];
u32_t divc = 0, spif_mhz;
u32_t tmp_divc = 7, tmp_spif_mhz = 0;
while(END_OF_INFO!=sclk_divisor[divc].divisor) {
spif_mhz = cg_info_query.dev_freq.lx_mhz / sclk_divisor[divc].divisor;
if((spif_mhz <= cg_info_query.dev_freq.snaf_mhz) && (spif_mhz > tmp_spif_mhz)) {
tmp_divc = divc;
tmp_spif_mhz = spif_mhz;
}
++divc;
}
cg_config->snaf_ctrl_div = tmp_divc;
cg_info_query.dev_freq.snaf_mhz = tmp_spif_mhz;
if(tmp_spif_mhz > 50) cg_config->snaf_pl = 2;
cg_config->snaf_pl = (tmp_spif_mhz > 50) ? 2 : 1;
#ifndef OTTO_FLASH_NAND_SPI
// SPI-NOR
u32_t min_divp = LN_DIV(cg_config->sw_vco, MAX_SPIF_PLL);
u32_t max_divp = LN_DIV(cg_config->sw_vco, MIN_SPIF_PLL);
u32_t divp, tmp_divp=max_divp;
divc = 0; tmp_divc = 7; tmp_spif_mhz = 0;
while(END_OF_INFO!=sclk_divisor[divc].divisor) {
for (divp=min_divp; divp<=max_divp; divp++) {
spif_mhz = LNS_FREQ(cg_config->sw_vco, divp)/sclk_divisor[divc].divisor;
if ((spif_mhz<=cg_info_query.dev_freq.spif_mhz) && (spif_mhz > tmp_spif_mhz)) {
tmp_divp = divp;
tmp_divc = divc;
tmp_spif_mhz = spif_mhz;
}
}
++divc;
}
cg_config->spif_pll_div = tmp_divp;
cg_config->spif_ctrl_div = sclk_divisor[tmp_divc].div_to_ctrl;
// slow bit check
cg_config->oc_spif_slow = (cg_config->ocp_pll > tmp_spif_mhz) ? 0 : 1;
#endif
// if nand only, spif_mhz = snaf_mhz, else nor: spif_mhz, nand: snaf_mhz
cg_info_query.dev_freq.spif_mhz = tmp_spif_mhz;
return PLL_SET_DONE;
}
u32_t cg_guery_mem_freq(u32_t _mem2, u32_t _mem3) {
/* MEM */
SYS_MEM_PLL_CTRL2_T mem2 = { .v = _mem2};
SYS_MEM_PLL_CTRL3_T mem3 = { .v = _mem3 };
return MEM_FREQ(mem2.f.pdiv, mem3.f.n_code);
}
int _cg_config_mem(cg_config_t *cg_config) {
// ERROR Check?
// return Fail;
if (100 == cg_info_query.dev_freq.mem_mhz) {
cg_config->mem0 = SYS_MEM_PLL_CTRL0dv;
cg_config->mem1 = 0x000001EF;
cg_config->mem2 = 0x26226400;
cg_config->mem3 = 0x0E0F0000;
} else {
// 250, 275, 300, 325, 350,
// 375, 400, 425, 450, 475,
// 500, 525, 550, 575, 600,
static u32_t mem0[] = { 0x0008407F, 0x0008407F, 0x0008407F, 0x0008407F, 0x0008407F,
0x0008407F, 0x0000007F, 0x0008407F, 0x0008407F, 0x000C607F,
0x000C607F, 0x000C607F, 0x000C607F, 0x000C807F, 0x0000007F};
static u32_t mem1[] = { 0x4000018F, 0x4000018F, 0x4000018F, 0x4000018F, 0x4000018F,
0x4000018F, 0x400001EF, 0x4000018F, 0x4000018F, 0x4000018F,
0x4000018F, 0x4000018F, 0x4000018F, 0x4000018F, 0x400001EF};
static u32_t mem2[] = { 0x26222400, 0x26222400, 0x26222520, 0x26222520, 0x26222520,
0x26622520, 0x26622520, 0x26A23720, 0x26A23720, 0x26A23740,
0x26A23740, 0x26A33840, 0x26A33840, 0x26A33860, 0x26A33860};
static u32_t mem3[] = { 0x120F0000, 0x140F0000, 0x160F0000, 0x180F0000, 0x1A0F0000,
0x1C0F0000, 0x1E0F0000, 0x200F0000, 0x220F0000, 0x240F0000,
0x260F0000, 0x280F0000, 0x2A0F0000, 0x2C0F0000, 0x2E0F0000};
u32_t idx = (cg_info_query.dev_freq.mem_mhz - 250) / 25;
if(idx >= (sizeof(mem0) / sizeof(u32_t)))
idx = 0;
cg_config->mem0 = mem0[idx]; //SYS_MEM_PLL_CTRL0dv;
cg_config->mem1 = mem1[idx]; //0x400001EF;
cg_config->mem2 = mem2[idx];
cg_config->mem3 = mem3[idx];
}
cg_info_query.dev_freq.mem_mhz = cg_guery_mem_freq(cg_config->mem2, cg_config->mem3);
cg_config->oc_mem_slow = (cg_config->ocp_pll > cg_info_query.dev_freq.mem_mhz)?0:1;
cg_config->lx_mem_slow = (cg_info_query.dev_freq.lx_mhz > cg_info_query.dev_freq.mem_mhz)?0:1;
return PLL_SET_DONE;
}
void cg_mem_pll_init(cg_config_t *cg_config) {
CG_MEM_PLL_OE_DIS();
cg_udelay(200, cg_info_query.dev_freq.cpu_mhz);
SYS_MEM_PLL_CTRL0rv = cg_config->mem0;
SYS_MEM_PLL_CTRL1rv = cg_config->mem1;
SYS_MEM_PLL_CTRL2rv = cg_config->mem2;
SYS_MEM_PLL_CTRL3rv = cg_config->mem3;
SYS_MEM_PLL_CTRL5rv = SYS_MEM_PLL_CTRL5dv;
SYS_MEM_PLL_CTRL6rv = SYS_MEM_PLL_CTRL6dv;
cg_udelay(5, cg_info_query.dev_freq.cpu_mhz);
CG_MEM_PLL_OE_EN();
cg_udelay(200, cg_info_query.dev_freq.cpu_mhz);
// OC v.s MEM slow bit
RMOD_CMU_BC_OC0(se_dram, cg_config->oc_mem_slow);
// LX v.s MEM slow bit
RMOD_CMU_BC_LX0(se_dram, cg_config->lx_mem_slow);
RMOD_CMU_BC_LX1(se_dram, cg_config->lx_mem_slow);
RMOD_CMU_BC_LX2(se_dram, cg_config->lx_mem_slow);
RMOD_CMU_BC_LXP(se_dram, cg_config->lx_mem_slow);
cg_udelay(50, cg_info_query.dev_freq.cpu_mhz);
}
void cg_mem_pll_config_dqs_pi(u32_t dqs0_pi, u32_t dqs1_pi) {
SYS_MEM_PLL_CTRL0_T pll0 = { .v = SYS_MEM_PLL_CTRL0rv };
CG_MEM_PLL_OE_DIS();
pll0.f.post_pi_sel2 = dqs0_pi; // DQS0
pll0.f.post_pi_sel3 = dqs1_pi; // DQS1
SYS_MEM_PLL_CTRL0rv = pll0.v;
cg_udelay(5, cg_info_query.dev_freq.cpu_mhz);
CG_MEM_PLL_OE_EN();
cg_udelay(200, cg_info_query.dev_freq.cpu_mhz);
}
void cg_mem_pll_config_dq_pi(u32_t dq0_7_pi, u32_t dq8_15_pi) {
SYS_MEM_PLL_CTRL1_T pll1 = { .v = SYS_MEM_PLL_CTRL1rv };
CG_MEM_PLL_OE_DIS();
pll1.f.post_pi_sel4 = dq0_7_pi;
pll1.f.post_pi_sel5 = dq8_15_pi;
SYS_MEM_PLL_CTRL1rv = pll1.v;
cg_udelay(5, cg_info_query.dev_freq.cpu_mhz);
CG_MEM_PLL_OE_EN();
cg_udelay(200, cg_info_query.dev_freq.cpu_mhz);
}
int cg_config_transform(cg_config_t *cg_config) {
u32_t res;
// config CPU
res = _cg_config_cpu(cg_config);
res |= _cg_config_lx(cg_config);
res |= _cg_config_spif(cg_config);
res |= _cg_config_mem(cg_config);
return res;
}
void cg_config_apply(cg_config_t *cg_config) {
cg_cpu_sram_pll_init(cg_config); /* CPU PLL */
cg_lx_pll_init(cg_config); /* LX PLL */
cg_spif_pll_init(cg_config); /* SPI-NOR or SPI-NAND PLL */
cg_mem_pll_init(cg_config); /* MEM PLL */
}
u32_t cg_udelay(u32_t us, u32_t mhz) {
u32_t loop_cnt = us * mhz / 2;
while (loop_cnt--) {
;
}
return loop_cnt;
}
u32_t cg_query_freq(u32_t dev_type) {
return CG_QUERY_FREQUENCY(dev_type,(&cg_info_query.dev_freq));
}
void cg_copy_info_to_sram(void) {
// assume snaf = spif
inline_memcpy(&cg_info_query, &cg_info_proj, sizeof(cg_info_t));
}
void cg_init(void) {
int res = 0;
cg_config_t cg_config;
res = cg_config_transform(&cg_config);
if (res != PLL_SET_DONE) {
printf("WW: CG Init Failed, res=0x%x\n", res);
}
cg_config_apply(&cg_config);
if (0 == (res & LX_PLL_SET_FAIL) && uart_baud_rate != 0) {
// re-init uart, lx_mhz might be changed
uart_init(uart_baud_rate, cg_info_query.dev_freq.lx_mhz);
}
printf("II: CPU %dMHz, MEM %dMHz, LX %dMHz, SPIF %dMHz\n",
cg_info_query.dev_freq.cpu_mhz,
cg_info_query.dev_freq.mem_mhz,
cg_info_query.dev_freq.lx_mhz,
cg_info_query.dev_freq.spif_mhz);
}
REG_INIT_FUNC(cg_copy_info_to_sram, 11);
REG_INIT_FUNC(cg_init, 13);
symb_pdefine(cg_info_dev_freq, SF_SYS_CG_DEV_FREQ, &(cg_info_query.dev_freq));