blob: 1ae621cbbb495f0dcb3cda352486f8d3e4fc72d0 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
|
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2017-09-06 勤为本 first version
*/
#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;
}
|