Skip to content

Commit

Permalink
[driver] fix clk driver issue
Browse files Browse the repository at this point in the history
  • Loading branch information
Samul Kyull authored and Samul Kyull committed Oct 17, 2024
1 parent ca98320 commit ec49f5d
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 125 deletions.
4 changes: 2 additions & 2 deletions board/avaota-cam/cdk/avaota_cam.cdkproj
Original file line number Diff line number Diff line change
Expand Up @@ -407,7 +407,7 @@
<File Name="../../../src/drivers/chips/sun20iw5/sys-clk.c">
<FileOption/>
</File>
<File Name="../../../src/drivers/chips/sun20iw5/sys-dram.c" ExcludeProjConfig="BuildSet">
<File Name="../../../src/drivers/chips/sun20iw5/sys-dram.c" ExcludeProjConfig="">
<FileOption/>
</File>
<File Name="../../../src/drivers/chips/sun20iw5/sys-rproc.c">
Expand Down Expand Up @@ -624,7 +624,7 @@
<Optim>Optimize for debug (-Og)</Optim>
<DebugLevel>Default (-g)</DebugLevel>
<IncludePath>$(ProjectPath);../../../include/;../../../include/arch/riscv/;../../../include/cli/;../../../include/drivers/chips/sun20iw5/;../../../include/drivers/mmc/;../../../include/drivers/pmu/reg/;../../../include/drivers/pmu/;../../../include/drivers/reg/;../../../include/drivers/usb/;../../../include/image/;../../../include/lib/elf/;../../../include/lib/fatfs/;../../../include/lib/fdt/;../../../include/drivers/;../../../include/drivers/chips/</IncludePath>
<OtherFlags>-nostdlib -g -ggdb -O0 -nostdinc -march=rv32imafcxthead -mabi=ilp32f -Wno-int-to-pointer-cast -Wno-int-to-pointer-cast -Wno-shift-count-overflow -Wno-builtin-declaration-mismatch -Wno-pointer-to-int-cast -Wno-implicit-function-declaration -Wno-discarded-qualifiers -Wno-unused-function -Wno-unused-variable</OtherFlags>
<OtherFlags>-nostdlib -g -ggdb -O0 -nostdinc -march=rv32imafcxthead -mabi=ilp32f -Wno-int-to-pointer-cast -Wno-int-to-pointer-cast -Wno-shift-count-overflow -Wno-builtin-declaration-mismatch -Wno-pointer-to-int-cast -Wno-implicit-function-declaration -Wno-discarded-qualifiers -Wno-unused-function -Wno-unused-variable -Wno-unused-but-set-variable</OtherFlags>
<Verbose>no</Verbose>
<Ansi>no</Ansi>
<Syntax>no</Syntax>
Expand Down
4 changes: 0 additions & 4 deletions board/avaota-cam/hello_world/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,6 @@ int main(void) {

sunxi_clk_dump();

printk_info("test Store address misaligned exception\n");

asm volatile(".word 0x23232323");

abort();

return 0;
Expand Down
95 changes: 41 additions & 54 deletions src/drivers/chips/sun20iw5/sys-clk.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,25 +13,6 @@

#include <sys-clk.h>

typedef struct {
uint32_t pll_en;
uint32_t pll_ldo_en;
uint32_t pll_lock_en;
uint32_t pll_output_gate;
uint32_t pll_n;
uint32_t pll_m;
} ccu_pll_peri_cfg_info_t;

typedef struct {
uint32_t pll_en;
uint32_t pll_ldo_en;
uint32_t pll_lock_en;
uint32_t pll_output_gate;
uint32_t pll_n;
uint32_t pll_m;
uint32_t pll_d;
} ccu_pll_general_cfg_info_t;

int wait_until_pll_timeout(uint32_t time_cnt) {
uint32_t ret = 1;
do {
Expand All @@ -44,25 +25,26 @@ int wait_until_pll_timeout(uint32_t time_cnt) {
}

static void set_pll_general(uint32_t pll_addr, uint32_t en, uint32_t output_gate_en, uint32_t pll_d, uint32_t pll_d_off, uint32_t pll_n) {
ccu_pll_general_cfg_info_t pll_general_cfg;
uint32_t pll_en;
uint32_t pll_ldo_en;
uint32_t pll_lock_en;
uint32_t pll_output_gate;
uint32_t pll_m;

if (en == 1) {
pll_general_cfg.pll_en = PLL_Enable;
pll_general_cfg.pll_ldo_en = PLL_LDO_Enable;
pll_general_cfg.pll_lock_en = PLL_LOCK_EN_Enable;
pll_en = PLL_Enable;
pll_ldo_en = PLL_LDO_Enable;
pll_lock_en = PLL_LOCK_EN_Enable;
} else {
pll_general_cfg.pll_en = PLL_Disable;
pll_general_cfg.pll_ldo_en = PLL_LDO_Disable;
pll_general_cfg.pll_lock_en = PLL_LOCK_EN_Disable;
pll_en = PLL_Disable;
pll_ldo_en = PLL_LDO_Disable;
pll_lock_en = PLL_LOCK_EN_Disable;
}

pll_general_cfg.pll_output_gate = PLL_OUTPUT_GATE_Disable;
pll_output_gate = PLL_OUTPUT_GATE_Disable;
clrsetbits_le32(pll_addr, PLL_D_MASK, pll_d << pll_d_off);
// clrsetbits_le32(pll_addr, PLL_M_MASK, pll_m << PLL_M_OFFSET);
clrsetbits_le32(pll_addr, PLL_N_MASK, pll_n << PLL_N_OFFSET);

clrsetbits_le32(pll_addr, PLL_LDO_MASK | PLL_OUTPUT_GATE_MASK | PLL_EN_MASK, pll_general_cfg.pll_en | pll_general_cfg.pll_ldo_en | pll_general_cfg.pll_lock_en);

clrsetbits_le32(pll_addr, PLL_LDO_MASK | PLL_OUTPUT_GATE_MASK | PLL_EN_MASK, pll_en | pll_ldo_en | pll_lock_en);
clrsetbits_le32(pll_addr, PLL_LOCK_EN_MASK, PLL_LOCK_EN_Enable);

while ((!(readl(pll_addr) & PLL_LOCK_MASK)) & wait_until_pll_timeout(0xffff))
Expand All @@ -74,53 +56,52 @@ static void set_pll_general(uint32_t pll_addr, uint32_t en, uint32_t output_gate
}

static void set_pll_e90x(void) {
/* Low freq --> High freq */
/* clock 1024/3 = 512M */
clrsetbits_le32(CCU_E90X_CLK_REG, E907_CLK_REG_E907_CLK_DIV_CLEAR_MASK, CCU_E90X_CLK_CPU_M_1 << E907_CLK_REG_E907_CLK_DIV_OFFSET);
clrsetbits_le32(CCU_E90X_CLK_REG, E907_CLK_REG_E907_CLK_SEL_CLEAR_MASK, E907_CLK_REG_E907_CLK_SEL_PERI_PLL_614M << E907_CLK_REG_E907_CLK_SEL_OFFSET);
return;
}

static void set_pll_a27l2(void) {
/* Low freq --> High freq */
/* clock 768/3 = 256M */
clrsetbits_le32(CCU_A27_CLK_REG, A27L2_CLK_REG_A27L2_CLK_DIV_CLEAR_MASK, CCU_A27_CLK_CPU_M_1 << A27L2_CLK_REG_A27L2_CLK_DIV_OFFSET);
clrsetbits_le32(CCU_A27_CLK_REG, A27L2_CLK_REG_A27L2_CLK_SEL_CLEAR_MASK, A27L2_CLK_REG_A27L2_CLK_SEL_CPU_PLL << A27L2_CLK_REG_A27L2_CLK_SEL_OFFSET);
clrsetbits_le32(CCU_A27_CLK_REG, A27L2_CLK_REG_A27L2_CLK_EN_CLEAR_MASK, A27L2_CLK_REG_A27L2_CLK_EN_CLOCK_IS_ON << A27L2_CLK_REG_A27L2_CLK_EN_OFFSET);
return;
}

static void set_pll_peri_ctrl0(uint32_t en, uint32_t output_gate_en, uint32_t pll_n, uint32_t pll_m) {
ccu_pll_peri_cfg_info_t pll_peri_cfg;
uint32_t pll_en;
uint32_t pll_ldo_en;
uint32_t pll_lock_en;
uint32_t pll_output_gate;

if (en == 1) {
pll_peri_cfg.pll_en = PLL_PERI_CTRL0_REG_PLL_EN_ENABLE << PLL_PERI_CTRL0_REG_PLL_EN_OFFSET;
pll_peri_cfg.pll_ldo_en = PLL_PERI_CTRL0_REG_PLL_LDO_EN_ENABLE << PLL_PERI_CTRL0_REG_PLL_LDO_EN_OFFSET;
pll_peri_cfg.pll_lock_en = PLL_PERI_CTRL0_REG_LOCK_ENABLE_ENABLE << PLL_PERI_CTRL0_REG_LOCK_ENABLE_OFFSET;
pll_en = PLL_PERI_CTRL0_REG_PLL_EN_ENABLE << PLL_PERI_CTRL0_REG_PLL_EN_OFFSET;
pll_ldo_en = PLL_PERI_CTRL0_REG_PLL_LDO_EN_ENABLE << PLL_PERI_CTRL0_REG_PLL_LDO_EN_OFFSET;
pll_lock_en = PLL_PERI_CTRL0_REG_LOCK_ENABLE_ENABLE << PLL_PERI_CTRL0_REG_LOCK_ENABLE_OFFSET;
} else {
pll_peri_cfg.pll_en = PLL_PERI_CTRL0_REG_PLL_EN_DISABLE << PLL_PERI_CTRL0_REG_PLL_EN_OFFSET;
pll_peri_cfg.pll_ldo_en = PLL_PERI_CTRL0_REG_PLL_LDO_EN_DISABLE << PLL_PERI_CTRL0_REG_PLL_LDO_EN_OFFSET;
pll_peri_cfg.pll_lock_en = PLL_PERI_CTRL0_REG_LOCK_ENABLE_DISABLE << PLL_PERI_CTRL0_REG_LOCK_ENABLE_OFFSET;
pll_en = PLL_PERI_CTRL0_REG_PLL_EN_DISABLE << PLL_PERI_CTRL0_REG_PLL_EN_OFFSET;
pll_ldo_en = PLL_PERI_CTRL0_REG_PLL_LDO_EN_DISABLE << PLL_PERI_CTRL0_REG_PLL_LDO_EN_OFFSET;
pll_lock_en = PLL_PERI_CTRL0_REG_LOCK_ENABLE_DISABLE << PLL_PERI_CTRL0_REG_LOCK_ENABLE_OFFSET;
}
pll_peri_cfg.pll_output_gate = PLL_VIDEO_CTRL_REG_PLL_OUTPUT_GATE_DISABLE << PLL_VIDEO_CTRL_REG_PLL_OUTPUT_GATE_OFFSET;
pll_peri_cfg.pll_n = pll_n << PLL_PERI_CTRL0_REG_PLL_N_OFFSET;
pll_peri_cfg.pll_m = pll_m << PLL_PERI_CTRL0_REG_PLL_INPUT_DIV_OFFSET;
pll_output_gate = PLL_VIDEO_CTRL_REG_PLL_OUTPUT_GATE_DISABLE << PLL_VIDEO_CTRL_REG_PLL_OUTPUT_GATE_OFFSET;
pll_n = pll_n << PLL_PERI_CTRL0_REG_PLL_N_OFFSET;
pll_m = pll_m << PLL_PERI_CTRL0_REG_PLL_INPUT_DIV_OFFSET;

clrsetbits_le32(CCU_PLL_PERI_CTRL0_REG, PLL_PERI_CTRL0_REG_PLL_INPUT_DIV_CLEAR_MASK, pll_peri_cfg.pll_m);
clrsetbits_le32(CCU_PLL_PERI_CTRL0_REG, PLL_PERI_CTRL0_REG_PLL_N_CLEAR_MASK, pll_peri_cfg.pll_n);
clrsetbits_le32(CCU_PLL_PERI_CTRL0_REG, PLL_PERI_CTRL0_REG_PLL_INPUT_DIV_CLEAR_MASK, pll_m);
clrsetbits_le32(CCU_PLL_PERI_CTRL0_REG, PLL_PERI_CTRL0_REG_PLL_N_CLEAR_MASK, pll_n);

clrsetbits_le32(CCU_PLL_PERI_CTRL0_REG,
PLL_PERI_CTRL0_REG_PLL_EN_CLEAR_MASK | PLL_PERI_CTRL0_REG_PLL_LDO_EN_CLEAR_MASK | PLL_PERI_CTRL0_REG_PLL_OUTPUT_GATE_CLEAR_MASK,
pll_peri_cfg.pll_en | pll_peri_cfg.pll_ldo_en | pll_peri_cfg.pll_output_gate);
pll_en | pll_ldo_en | pll_output_gate);

clrsetbits_le32(CCU_PLL_PERI_CTRL0_REG, PLL_PERI_CTRL0_REG_LOCK_ENABLE_CLEAR_MASK, pll_peri_cfg.pll_lock_en);
clrsetbits_le32(CCU_PLL_PERI_CTRL0_REG, PLL_PERI_CTRL0_REG_LOCK_ENABLE_CLEAR_MASK, pll_lock_en);

while ((!(readl(CCU_PLL_PERI_CTRL0_REG) & PLL_PERI_CTRL0_REG_LOCK_CLEAR_MASK)) & wait_until_pll_timeout(0xffff))
;

if (output_gate_en == 1) {
pll_peri_cfg.pll_output_gate = PLL_PERI_CTRL0_REG_PLL_OUTPUT_GATE_ENABLE << PLL_PERI_CTRL0_REG_PLL_OUTPUT_GATE_OFFSET;
clrsetbits_le32(CCU_PLL_PERI_CTRL0_REG, PLL_PERI_CTRL0_REG_PLL_OUTPUT_GATE_CLEAR_MASK, pll_peri_cfg.pll_output_gate);
pll_output_gate = PLL_PERI_CTRL0_REG_PLL_OUTPUT_GATE_ENABLE << PLL_PERI_CTRL0_REG_PLL_OUTPUT_GATE_OFFSET;
clrsetbits_le32(CCU_PLL_PERI_CTRL0_REG, PLL_PERI_CTRL0_REG_PLL_OUTPUT_GATE_CLEAR_MASK, pll_output_gate);
}
}

Expand All @@ -134,9 +115,8 @@ static void set_pll_peri_ctrl1(void) {
return;
}

/* pll peri hosc*2N/M = 3072M hardware *2 */
/* pll peri hosc*2N/M = 3072M hardware * 2 */
void set_pll_peri(void) {
// When efuse is burned, brom will initialize the peri clock in advance.
if (!(readl(CCU_PLL_PERI_CTRL0_REG) & PLL_PERI_CTRL0_REG_PLL_EN_CLEAR_MASK)) {
if (sunxi_clk_get_hosc_type() == HOSC_FREQ_40M) {
set_pll_peri_ctrl0(PLL_PERI_CTRL0_REG_PLL_EN_ENABLE, PLL_PERI_CTRL0_REG_PLL_OUTPUT_GATE_ENABLE, CCU_AON_PLL_CPU_N_192, CCU_AON_PLL_CPU_M_5);
Expand Down Expand Up @@ -252,7 +232,6 @@ void sunxi_clk_init(void) {
} else {
writel(readl(CCU_FUNC_CFG_REG) & (~PLL_FUNC_CFG_REG_DCXO_ST_CLEAR_MASK), CCU_FUNC_CFG_REG);
set_pll_general(CCU_PLL_CPUX_CTRL_REG, PLL_CPU_CTRL_REG_PLL_EN_ENABLE, PLL_CPU_CTRL_REG_PLL_OUTPUT_GATE_ENABLE, CCU_AON_PLL_CPU_D_1, 2, CCU_AON_PLL_CPU_N_45);
// When efuse is burned, brom will initialize the vedio clock in advance.
if (!(readl(CCU_PLL_VIDEO_CTRL_REG) & PLL_CPU_CTRL_REG_PLL_EN_CLEAR_MASK)) {
set_pll_general(CCU_PLL_VIDEO_CTRL_REG, PLL_CPU_CTRL_REG_PLL_EN_ENABLE, PLL_CPU_CTRL_REG_PLL_OUTPUT_GATE_ENABLE, CCU_AON_PLL_CPU_D_2, 1, CCU_AON_PLL_CPU_N_99);
}
Expand All @@ -267,6 +246,14 @@ void sunxi_clk_init(void) {
}

void sunxi_clk_dump() {
uint32_t reg_val = 0;
uint32_t n, m;

reg_val = read32(CCU_PLL_PERI_CTRL0_REG);
n = (reg_val & PLL_PERI_CTRL0_REG_PLL_N_CLEAR_MASK) >> PLL_PERI_CTRL0_REG_PLL_N_OFFSET;
m = reg_val & PLL_PERI_CTRL0_REG_PLL_INPUT_DIV_CLEAR_MASK;

printk_debug("CLK: PERI FREQ=%luMHz\r\n", (sunxi_clk_get_hosc_type() * 2 * (n + 1)) / (m + 1));
}

/* we got hosc freq in arch/timer.c */
Expand Down
66 changes: 1 addition & 65 deletions src/drivers/chips/sun20iw5/sys-dram.c
Original file line number Diff line number Diff line change
Expand Up @@ -469,77 +469,13 @@ static void mctl_set_timing_params(dram_para_t *para) {
// the MBUS and sdram.
//
static int ccu_set_pll_ddr_clk(int index, dram_para_t *para) {
unsigned int val, clk, n;

if (para->dram_tpr13 & (1 << 6))
clk = para->dram_tpr9;
else
clk = para->dram_clk;

// set VCO clock divider
n = (clk * 2) / 24;

val = readl((CCU_BASE + CCU_PLL_DDR_CTRL_REG));
val &= 0xfff800fc; // clear dividers
val |= (n - 1) << 8;// set PLL division
val |= 0xc0000000; // enable PLL and LDO
val &= 0xdfffffff;
writel(val | 0x20000000, (CCU_BASE + CCU_PLL_DDR_CTRL_REG));

// wait for PLL to lock
while ((readl((CCU_BASE + CCU_PLL_DDR_CTRL_REG)) & 0x10000000) == 0) {
;
}

udelay(20);

// enable PLL output
val = readl(CCU_BASE);
val |= 0x08000000;
writel(val, CCU_BASE);

// turn clock gate on
val = readl((CCU_BASE + CCU_DRAM_CLK_REG));
val &= 0xfcfffcfc;// select DDR clk source, n=1, m=1
val |= 0x80000000;// turn clock on
writel(val, (CCU_BASE + CCU_DRAM_CLK_REG));

return n * 24;
return 0x0;
}

// Main purpose of sys_init seems to be to initalise the clocks for
// the sdram controller.
//
static void mctl_sys_init(dram_para_t *para) {
// assert MBUS reset
clrbits_le32((CCU_BASE + CCU_MBUS_CLK_REG), (1 << 30));

// turn off sdram clock gate, assert sdram reset
clrbits_le32((CCU_BASE + CCU_DRAM_BGR_REG), 0x10001);
clrsetbits_le32((CCU_BASE + CCU_DRAM_CLK_REG), (1 << 31) | (1 << 30), (1 << 27));
udelay(10);

// set ddr pll clock
para->dram_clk = ccu_set_pll_ddr_clk(0, para) / 2;
udelay(100);
dram_disable_all_master();

// release sdram reset
setbits_le32((CCU_BASE + CCU_DRAM_BGR_REG), (1 << 16));

// release MBUS reset
setbits_le32((CCU_BASE + CCU_MBUS_CLK_REG), (1 << 30));
setbits_le32((CCU_BASE + CCU_DRAM_CLK_REG), (1 << 30));

udelay(5);

// turn on sdram clock gate
setbits_le32((CCU_BASE + CCU_DRAM_BGR_REG), (1 << 0));

// turn dram clock gate on, trigger sdr clock update
setbits_le32((CCU_BASE + CCU_DRAM_CLK_REG), (1 << 31) | (1 << 27));
udelay(5);

// mCTL clock enable
writel(0x8000, (MCTL_PHY_BASE + MCTL_PHY_CLKEN));
udelay(10);
Expand Down

0 comments on commit ec49f5d

Please sign in to comment.