/************************************************************************* * * 时钟相关函数 * *************************************************************************/ #include "ls1c_regs.h" #include "ls1c_public.h" // 晶振的频率 #define AHB_CLK (24000000) #define APB_CLK (AHB_CLK) // START_FREQ寄存器bits #define M_PLL_SHIFT (8) #define M_PLL (0xff << M_PLL_SHIFT) // PLL倍频系数的整数部分 #define FRAC_N_SHIFT (16) #define FRAC_N (0xff << FRAC_N_SHIFT) // PLL倍频系数的小数部分 #define DIV_SDRAM_SHIFT (0) #define DIV_SDRAM (0x3 << DIV_SDRAM_SHIFT) // CLK_DIV_PARAM寄存器bits #define DIV_PIX_EN (0x1 << 31) #define DIV_PIX (0x7f << 24) #define DIV_CAM_EN (0x1 << 23) #define DIV_CAM (0x7f << 16) #define DIV_CPU_EN (0x1 << 15) #define DIV_CPU (0x7f << 8) #define DIV_PIX_VALID (0x1 << 5) #define DIV_PIX_SEL (0x1 << 4) #define DIV_CAM_VALID (0x1 << 3) #define DIV_CAM_SEL (0x1 << 2) #define DIV_CPU_VALID (0x1 << 1) #define DIV_CPU_SEL (0x1 << 0) #define DIV_PIX_SHIFT (24) #define DIV_CAM_SHIFT (16) #define DIV_CPU_SHIFT (8) /* * 获取PLL频率 * @ret PLL频率 */ unsigned long clk_get_pll_rate(void) { unsigned int ctrl; unsigned long pll_rate = 0; ctrl = reg_read_32((volatile unsigned int *)LS1C_START_FREQ); pll_rate = (((ctrl & M_PLL) >> M_PLL_SHIFT) + ((ctrl & FRAC_N) >> FRAC_N_SHIFT)) * APB_CLK / 4; return pll_rate; } /* * 获取CPU频率 * @ret CPU频率 */ unsigned long clk_get_cpu_rate(void) { unsigned long pll_rate, cpu_rate; unsigned int ctrl; pll_rate = clk_get_pll_rate(); ctrl = reg_read_32((volatile unsigned int *)LS1C_CLK_DIV_PARAM); // 选择时钟来源 if (DIV_CPU_SEL & ctrl) // pll分频作为时钟信号 { if (DIV_CPU_EN & ctrl) { cpu_rate = pll_rate / ((ctrl & DIV_CPU) >> DIV_CPU_SHIFT); } else { cpu_rate = pll_rate / 2; } } else // bypass模式,晶振作为时钟输入 { cpu_rate = APB_CLK; } return cpu_rate; } /* * 获取DDR频率 * @ret DDR频率 */ unsigned long clk_get_ddr_rate(void) { unsigned long cpu_rate = 0; unsigned long ddr_rate = 0; unsigned int ctrl; cpu_rate = clk_get_cpu_rate(); ctrl = reg_read_32((volatile unsigned int *)LS1C_START_FREQ); ctrl = (ctrl & DIV_SDRAM) >> DIV_SDRAM_SHIFT; switch (ctrl) { case 0: ddr_rate = cpu_rate / 2; break; case 1: ddr_rate = cpu_rate / 4; break; case 2: case 3: ddr_rate = cpu_rate / 3; break; } return ddr_rate; } /* * 获取APB频率 * @ret APB频率 */ unsigned long clk_get_apb_rate(void) { return clk_get_ddr_rate(); } /* * 获取DC频率 * @ret DC频率 */ unsigned long clk_get_dc_rate(void) { unsigned long pll_rate, dc_rate; unsigned int ctrl; pll_rate = clk_get_pll_rate(); ctrl = reg_read_32((volatile unsigned int *)LS1C_CLK_DIV_PARAM); dc_rate = pll_rate / ((ctrl & DIV_PIX) >> DIV_PIX_SHIFT); return dc_rate; }