rtl93xx:flat_cg

[enable_line_numbers="true"
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));
  • rtl93xx/flat_cg.txt
  • Last modified: 2023/02/07 14:23
  • by oliver