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#undef DEBUG
28
29#include <linux/kernel.h>
30#include <linux/errno.h>
31#include <linux/clk.h>
32#include <linux/io.h>
33#include <linux/cpufreq.h>
34#include <linux/slab.h>
35
36#include "soc.h"
37#include "clock.h"
38#include "clock2xxx.h"
39#include "opp2xxx.h"
40#include "cm2xxx.h"
41#include "cm-regbits-24xx.h"
42#include "sdrc.h"
43#include "sram.h"
44
45const struct prcm_config *curr_prcm_set;
46const struct prcm_config *rate_table;
47
48
49
50
51
52
53static unsigned long sys_ck_rate;
54
55
56
57
58
59
60
61unsigned long omap2_table_mpu_recalc(struct clk_hw *clk,
62 unsigned long parent_rate)
63{
64 return curr_prcm_set->mpu_speed;
65}
66
67
68
69
70
71
72
73
74long omap2_round_to_table_rate(struct clk_hw *hw, unsigned long rate,
75 unsigned long *parent_rate)
76{
77 const struct prcm_config *ptr;
78 long highest_rate;
79
80 highest_rate = -EINVAL;
81
82 for (ptr = rate_table; ptr->mpu_speed; ptr++) {
83 if (!(ptr->flags & cpu_mask))
84 continue;
85 if (ptr->xtal_speed != sys_ck_rate)
86 continue;
87
88 highest_rate = ptr->mpu_speed;
89
90
91 if (ptr->mpu_speed <= rate)
92 break;
93 }
94 return highest_rate;
95}
96
97
98int omap2_select_table_rate(struct clk_hw *hw, unsigned long rate,
99 unsigned long parent_rate)
100{
101 u32 cur_rate, done_rate, bypass = 0, tmp;
102 const struct prcm_config *prcm;
103 unsigned long found_speed = 0;
104 unsigned long flags;
105
106 for (prcm = rate_table; prcm->mpu_speed; prcm++) {
107 if (!(prcm->flags & cpu_mask))
108 continue;
109
110 if (prcm->xtal_speed != sys_ck_rate)
111 continue;
112
113 if (prcm->mpu_speed <= rate) {
114 found_speed = prcm->mpu_speed;
115 break;
116 }
117 }
118
119 if (!found_speed) {
120 printk(KERN_INFO "Could not set MPU rate to %luMHz\n",
121 rate / 1000000);
122 return -EINVAL;
123 }
124
125 curr_prcm_set = prcm;
126 cur_rate = omap2xxx_clk_get_core_rate();
127
128 if (prcm->dpll_speed == cur_rate / 2) {
129 omap2xxx_sdrc_reprogram(CORE_CLK_SRC_DPLL, 1);
130 } else if (prcm->dpll_speed == cur_rate * 2) {
131 omap2xxx_sdrc_reprogram(CORE_CLK_SRC_DPLL_X2, 1);
132 } else if (prcm->dpll_speed != cur_rate) {
133 local_irq_save(flags);
134
135 if (prcm->dpll_speed == prcm->xtal_speed)
136 bypass = 1;
137
138 if ((prcm->cm_clksel2_pll & OMAP24XX_CORE_CLK_SRC_MASK) ==
139 CORE_CLK_SRC_DPLL_X2)
140 done_rate = CORE_CLK_SRC_DPLL_X2;
141 else
142 done_rate = CORE_CLK_SRC_DPLL;
143
144
145 omap2_cm_write_mod_reg(prcm->cm_clksel_mpu, MPU_MOD, CM_CLKSEL);
146
147
148 omap2_cm_write_mod_reg(prcm->cm_clksel_dsp,
149 OMAP24XX_DSP_MOD, CM_CLKSEL);
150
151 omap2_cm_write_mod_reg(prcm->cm_clksel_gfx, GFX_MOD, CM_CLKSEL);
152
153
154 tmp = omap2_cm_read_mod_reg(CORE_MOD, CM_CLKSEL1) & OMAP24XX_CLKSEL_DSS2_MASK;
155 omap2_cm_write_mod_reg(prcm->cm_clksel1_core | tmp, CORE_MOD,
156 CM_CLKSEL1);
157
158 if (cpu_is_omap2430())
159 omap2_cm_write_mod_reg(prcm->cm_clksel_mdm,
160 OMAP2430_MDM_MOD, CM_CLKSEL);
161
162
163 omap2xxx_sdrc_reprogram(CORE_CLK_SRC_DPLL_X2, 1);
164
165 omap2_set_prcm(prcm->cm_clksel1_pll, prcm->base_sdrc_rfr,
166 bypass);
167
168 omap2xxx_sdrc_init_params(omap2xxx_sdrc_dll_is_unlocked());
169 omap2xxx_sdrc_reprogram(done_rate, 0);
170
171 local_irq_restore(flags);
172 }
173
174 return 0;
175}
176
177
178
179
180
181
182
183
184
185void omap2xxx_clkt_vps_check_bootloader_rates(void)
186{
187 const struct prcm_config *prcm = NULL;
188 unsigned long rate;
189
190 rate = omap2xxx_clk_get_core_rate();
191 for (prcm = rate_table; prcm->mpu_speed; prcm++) {
192 if (!(prcm->flags & cpu_mask))
193 continue;
194 if (prcm->xtal_speed != sys_ck_rate)
195 continue;
196 if (prcm->dpll_speed <= rate)
197 break;
198 }
199 curr_prcm_set = prcm;
200}
201
202
203
204
205
206
207
208
209
210
211void omap2xxx_clkt_vps_late_init(void)
212{
213 struct clk *c;
214
215 c = clk_get(NULL, "sys_ck");
216 if (IS_ERR(c)) {
217 WARN(1, "could not locate sys_ck\n");
218 } else {
219 sys_ck_rate = clk_get_rate(c);
220 clk_put(c);
221 }
222}
223