1 /*
2  * Copyright (c) 2006-2018, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2017-09-06     勤为本       first version
9  */
10 
11 
12 #include "ls1c_regs.h"
13 #include "ls1c_public.h"
14 
15 
16 // 晶振的频率
17 #define AHB_CLK                 (24000000)
18 #define APB_CLK                 (AHB_CLK)
19 
20 
21 // START_FREQ寄存器bits
22 #define M_PLL_SHIFT             (8)
23 #define M_PLL                   (0xff << M_PLL_SHIFT)       // PLL倍频系数的整数部分
24 #define FRAC_N_SHIFT            (16)
25 #define FRAC_N                  (0xff << FRAC_N_SHIFT)      // PLL倍频系数的小数部分
26 #define DIV_SDRAM_SHIFT         (0)
27 #define DIV_SDRAM               (0x3  << DIV_SDRAM_SHIFT)
28 
29 // CLK_DIV_PARAM寄存器bits
30 #define DIV_PIX_EN              (0x1  << 31)
31 #define DIV_PIX                 (0x7f << 24)
32 #define DIV_CAM_EN              (0x1  << 23)
33 #define DIV_CAM                 (0x7f << 16)
34 #define DIV_CPU_EN              (0x1  << 15)
35 #define DIV_CPU                 (0x7f << 8)
36 #define DIV_PIX_VALID           (0x1  << 5)
37 #define DIV_PIX_SEL             (0x1  << 4)
38 #define DIV_CAM_VALID           (0x1  << 3)
39 #define DIV_CAM_SEL             (0x1  << 2)
40 #define DIV_CPU_VALID           (0x1  << 1)
41 #define DIV_CPU_SEL             (0x1  << 0)
42 
43 #define DIV_PIX_SHIFT           (24)
44 #define DIV_CAM_SHIFT           (16)
45 #define DIV_CPU_SHIFT           (8)
46 
47 
48 /*
49  * 获取PLL频率
50  * @ret PLL频率
51  */
clk_get_pll_rate(void)52 unsigned long clk_get_pll_rate(void)
53 {
54     unsigned int ctrl;
55     unsigned long pll_rate = 0;
56 
57     ctrl = reg_read_32((volatile unsigned int *)LS1C_START_FREQ);
58     pll_rate = (((ctrl & M_PLL) >> M_PLL_SHIFT) + ((ctrl & FRAC_N) >> FRAC_N_SHIFT)) * APB_CLK / 4;
59 
60     return pll_rate;
61 }
62 
63 
64 /*
65  * 获取CPU频率
66  * @ret CPU频率
67  */
clk_get_cpu_rate(void)68 unsigned long clk_get_cpu_rate(void)
69 {
70     unsigned long pll_rate, cpu_rate;
71     unsigned int ctrl;
72 
73     pll_rate = clk_get_pll_rate();
74     ctrl = reg_read_32((volatile unsigned int *)LS1C_CLK_DIV_PARAM);
75 
76     // 选择时钟来源
77     if (DIV_CPU_SEL & ctrl)     // pll分频作为时钟信号
78     {
79         if (DIV_CPU_EN & ctrl)
80         {
81             cpu_rate = pll_rate / ((ctrl & DIV_CPU) >> DIV_CPU_SHIFT);
82         }
83         else
84         {
85             cpu_rate = pll_rate / 2;
86         }
87     }
88     else                        // bypass模式,晶振作为时钟输入
89     {
90         cpu_rate = APB_CLK;
91     }
92 
93     return cpu_rate;
94 }
95 
96 
97 /*
98  * 获取DDR频率
99  * @ret DDR频率
100  */
clk_get_ddr_rate(void)101 unsigned long clk_get_ddr_rate(void)
102 {
103     unsigned long cpu_rate = 0;
104     unsigned long ddr_rate = 0;
105     unsigned int ctrl;
106 
107     cpu_rate = clk_get_cpu_rate();
108     ctrl = reg_read_32((volatile unsigned int *)LS1C_START_FREQ);
109     ctrl = (ctrl & DIV_SDRAM) >> DIV_SDRAM_SHIFT;
110 
111     switch (ctrl)
112     {
113         case 0:
114             ddr_rate = cpu_rate / 2;
115             break;
116 
117         case 1:
118             ddr_rate = cpu_rate / 4;
119             break;
120 
121         case 2:
122         case 3:
123             ddr_rate = cpu_rate / 3;
124             break;
125     }
126 
127     return ddr_rate;
128 }
129 
130 
131 /*
132  * 获取APB频率
133  * @ret APB频率
134  */
clk_get_apb_rate(void)135 unsigned long clk_get_apb_rate(void)
136 {
137     return clk_get_ddr_rate();
138 }
139 
140 
141 /*
142  * 获取DC频率
143  * @ret DC频率
144  */
clk_get_dc_rate(void)145 unsigned long clk_get_dc_rate(void)
146 {
147     unsigned long pll_rate, dc_rate;
148     unsigned int ctrl;
149 
150     pll_rate = clk_get_pll_rate();
151     ctrl = reg_read_32((volatile unsigned int *)LS1C_CLK_DIV_PARAM);
152 
153     dc_rate = pll_rate / ((ctrl & DIV_PIX) >> DIV_PIX_SHIFT);
154 
155     return dc_rate;
156 }
157 
158 
159 
160