Commit | Line | Data |
---|---|---|
3c2a0909 S |
1 | /* |
2 | * Copyright (c) 2014 Samsung Electronics Co., Ltd. | |
3 | * http://www.samsung.com | |
4 | * | |
5 | * EXYNOS7420 - ATLAS Core frequency scaling support | |
6 | * | |
7 | * This program is free software; you can redistribute it and/or modify | |
8 | * it under the terms of the GNU General Public License version 2 as | |
9 | * published by the Free Software Foundation. | |
10 | */ | |
11 | ||
12 | #include <linux/kernel.h> | |
13 | #include <linux/err.h> | |
14 | #include <linux/clk.h> | |
15 | #include <linux/io.h> | |
16 | #include <linux/slab.h> | |
17 | #include <linux/cpufreq.h> | |
18 | #include <linux/clk-private.h> | |
19 | ||
20 | #include <mach/map.h> | |
21 | #include <mach/regs-clock.h> | |
22 | #include <mach/regs-clock-exynos7420.h> | |
23 | #include <mach/regs-pmu.h> | |
24 | #include <mach/cpufreq.h> | |
25 | #include <mach/asv-exynos.h> | |
26 | #include <linux/of.h> | |
27 | ||
28 | #define CPUFREQ_LEVEL_END_CA57 (L23 + 1) | |
29 | #undef PRINT_DIV_VAL | |
30 | ||
31 | #define ATLAS_EMA_CON (EXYNOS7420_VA_SYSREG + 0x0138) | |
32 | #define CPU_EMA_REG1 (EXYNOS7420_VA_SYSREG + 0x2908) | |
33 | ||
34 | static int max_support_idx_CA57; | |
35 | static int min_support_idx_CA57 = (CPUFREQ_LEVEL_END_CA57 - 1); | |
36 | ||
37 | static struct clk *mout_atlas; | |
38 | static struct clk *mout_atlas_pll; | |
39 | static struct clk *mout_bus0_pll_atlas; | |
40 | ||
41 | static unsigned int exynos7420_volt_table_CA57[CPUFREQ_LEVEL_END_CA57]; | |
42 | static unsigned int exynos7420_abb_table_CA57[CPUFREQ_LEVEL_END_CA57]; | |
43 | ||
44 | static int en_smpl_warn = 0; | |
45 | static BLOCKING_NOTIFIER_HEAD(exynos_cpufreq_smpl_warn_notifier_list); | |
46 | int exynos_cpufreq_smpl_warn_register_notifier(struct notifier_block *nb) | |
47 | { | |
48 | return blocking_notifier_chain_register(&exynos_cpufreq_smpl_warn_notifier_list, nb); | |
49 | } | |
50 | ||
51 | int exynos_cpufreq_smpl_warn_unregister_notifier(struct notifier_block *nb) | |
52 | { | |
53 | return blocking_notifier_chain_unregister(&exynos_cpufreq_smpl_warn_notifier_list, nb); | |
54 | } | |
55 | ||
56 | int exynos_cpufreq_smpl_warn_notify_call_chain(void) | |
57 | { | |
58 | int ret = blocking_notifier_call_chain(&exynos_cpufreq_smpl_warn_notifier_list, 0, NULL); | |
59 | return notifier_to_errno(ret); | |
60 | } | |
61 | EXPORT_SYMBOL(exynos_cpufreq_smpl_warn_notify_call_chain); | |
62 | ||
63 | ||
64 | static struct cpufreq_frequency_table exynos7420_freq_table_CA57[] = { | |
65 | {L0, 2496 * 1000}, | |
66 | {L1, 2400 * 1000}, | |
67 | {L2, 2304 * 1000}, | |
68 | {L3, 2200 * 1000}, | |
69 | {L4, 2100 * 1000}, | |
70 | {L5, 2000 * 1000}, | |
71 | {L6, 1896 * 1000}, | |
72 | {L7, 1800 * 1000}, | |
73 | {L8, 1704 * 1000}, | |
74 | {L9, 1600 * 1000}, | |
75 | {L10, 1500 * 1000}, | |
76 | {L11, 1400 * 1000}, | |
77 | {L12, 1300 * 1000}, | |
78 | {L13, 1200 * 1000}, | |
79 | {L14, 1100 * 1000}, | |
80 | {L15, 1000 * 1000}, | |
81 | {L16, 900 * 1000}, | |
82 | {L17, 800 * 1000}, | |
83 | {L18, 700 * 1000}, | |
84 | {L19, 600 * 1000}, | |
85 | {L20, 500 * 1000}, | |
86 | {L21, 400 * 1000}, | |
87 | {L22, 300 * 1000}, | |
88 | {L23, 200 * 1000}, | |
89 | {0, CPUFREQ_TABLE_END}, | |
90 | }; | |
91 | ||
92 | static struct apll_freq exynos7420_apll_freq_CA57[] = { | |
93 | /* | |
94 | * values: | |
95 | * freq | |
96 | * clock divider for ATLAS1, ATLAS2, ACLK_ATLAS, PCLK_ATLAS, ATCLK, PCLK_DBG_ATLAS, | |
97 | * clock divider for SCLK_ATLAS_PLL, SCLK_HPM_ATLAS, SCLK_CNTCLK | |
98 | * PLL M, P, S values are NOT used, Instead CCF clk_set_rate is used | |
99 | */ | |
100 | APLL_ATLAS_FREQ(2496, 0, 0, 2, 6, 6, 6, 1, 5, 6, 208, 2, 0), /* ARM L0: 2.5GHz */ | |
101 | APLL_ATLAS_FREQ(2400, 0, 0, 2, 6, 6, 6, 1, 5, 6, 200, 2, 0), /* ARM L1: 2.4GMHz */ | |
102 | APLL_ATLAS_FREQ(2304, 0, 0, 2, 6, 6, 6, 1, 5, 6, 192, 2, 0), /* ARM L2: 2.3GMHz */ | |
103 | APLL_ATLAS_FREQ(2200, 0, 0, 2, 6, 6, 6, 1, 5, 6, 275, 3, 0), /* ARM L3: 2.2GHz */ | |
104 | APLL_ATLAS_FREQ(2100, 0, 0, 2, 6, 6, 6, 1, 5, 6, 175, 2, 0), /* ARM L4: 2.1GHz */ | |
105 | APLL_ATLAS_FREQ(2000, 0, 0, 2, 6, 6, 6, 1, 5, 6, 250, 3, 0), /* ARM L5: 2.0GHz */ | |
106 | APLL_ATLAS_FREQ(1896, 0, 0, 2, 6, 6, 6, 1, 4, 6, 158, 2, 0), /* ARM L6: 1.9GHz */ | |
107 | APLL_ATLAS_FREQ(1800, 0, 0, 2, 6, 6, 6, 1, 4, 6, 150, 2, 0), /* ARM L7: 1.8GHz */ | |
108 | APLL_ATLAS_FREQ(1704, 0, 0, 2, 6, 6, 6, 1, 4, 6, 142, 2, 0), /* ARM L8: 1.7GHz */ | |
109 | APLL_ATLAS_FREQ(1600, 0, 0, 2, 6, 6, 6, 1, 4, 6, 200, 3, 0), /* ARM L9: 1.6GHz */ | |
110 | APLL_ATLAS_FREQ(1500, 0, 0, 2, 6, 6, 6, 1, 4, 6, 250, 2, 1), /* ARM L10: 1.5GHz */ | |
111 | APLL_ATLAS_FREQ(1400, 0, 0, 2, 6, 6, 6, 1, 4, 6, 350, 3, 1), /* ARM L11: 1.4GHz */ | |
112 | APLL_ATLAS_FREQ(1300, 0, 0, 2, 6, 6, 6, 1, 4, 6, 325, 3, 1), /* ARM L12: 1.3GHz */ | |
113 | APLL_ATLAS_FREQ(1200, 0, 0, 1, 6, 6, 6, 1, 3, 6, 200, 2, 1), /* ARM L13: 1.2GHz */ | |
114 | APLL_ATLAS_FREQ(1100, 0, 0, 1, 6, 6, 6, 1, 3, 6, 275, 3, 1), /* ARM L14: 1.1GHz */ | |
115 | APLL_ATLAS_FREQ(1000, 0, 0, 1, 6, 6, 6, 1, 3, 6, 250, 3, 1), /* ARM L15: 1.0GHz */ | |
116 | APLL_ATLAS_FREQ( 900, 0, 0, 1, 6, 6, 6, 1, 3, 6, 150, 2, 1), /* ARM L16: 900MHz */ | |
117 | APLL_ATLAS_FREQ( 800, 0, 0, 1, 5, 5, 5, 1, 3, 5, 200, 3, 1), /* ARM L17: 800MHz */ | |
118 | APLL_ATLAS_FREQ( 700, 0, 0, 1, 5, 5, 5, 1, 3, 5, 350, 3, 2), /* ARM L18: 700MHz */ | |
119 | APLL_ATLAS_FREQ( 600, 0, 0, 1, 4, 4, 4, 1, 3, 4, 200, 2, 2), /* ARM L19: 600MHz */ | |
120 | APLL_ATLAS_FREQ( 500, 0, 0, 1, 3, 3, 3, 1, 2, 3, 250, 3, 2), /* ARM L20: 500MHz */ | |
121 | APLL_ATLAS_FREQ( 400, 0, 0, 1, 3, 3, 3, 1, 2, 3, 200, 3, 2), /* ARM L21: 400MHz */ | |
122 | APLL_ATLAS_FREQ( 300, 0, 0, 1, 3, 3, 3, 1, 2, 3, 200, 2, 3), /* ARM L22: 300MHz */ | |
123 | APLL_ATLAS_FREQ( 200, 0, 0, 1, 3, 3, 3, 1, 1, 3, 200, 3, 3), /* ARM L23: 200MHz */ | |
124 | }; | |
125 | ||
126 | /* | |
127 | * ASV group voltage table | |
128 | */ | |
129 | static const unsigned int asv_voltage_7420_CA57[CPUFREQ_LEVEL_END_CA57] = { | |
130 | 1250000, /* L0 2500 */ | |
131 | 1250000, /* L1 2400 */ | |
132 | 1250000, /* L2 2300 */ | |
133 | 1250000, /* L3 2200 */ | |
134 | 1250000, /* L4 2100 */ | |
135 | 1200000, /* L5 2000 */ | |
136 | 1156250, /* L6 1900 */ | |
137 | 1118750, /* L7 1800 */ | |
138 | 1081250, /* L8 1700 */ | |
139 | 1043750, /* L9 1600 */ | |
140 | 1012500, /* L10 1500 */ | |
141 | 981250, /* L11 1400 */ | |
142 | 950000, /* L12 1300 */ | |
143 | 925000, /* L13 1200 */ | |
144 | 900000, /* L14 1100 */ | |
145 | 875000, /* L15 1000 */ | |
146 | 850000, /* L16 900 */ | |
147 | 825000, /* L17 800 */ | |
148 | 800000, /* L18 700 */ | |
149 | 775000, /* L19 600 */ | |
150 | 750000, /* L20 500 */ | |
151 | 725000, /* L21 400 */ | |
152 | 700000, /* L22 300 */ | |
153 | 675000, /* L23 200 */ | |
154 | }; | |
155 | ||
156 | /* minimum memory throughput in megabytes per second */ | |
157 | static int exynos7420_bus_table_CA57[CPUFREQ_LEVEL_END_CA57] = { | |
158 | 1552000, /* 2.5 GHz */ | |
159 | 1552000, /* 2.4 GHz */ | |
160 | 1552000, /* 2.3 GHz */ | |
161 | 1552000, /* 2.2 GHz */ | |
162 | 1552000, /* 2.1 GHz */ | |
163 | 1456000, /* 2.0 GHz */ | |
164 | 1264000, /* 1.9 GHz */ | |
165 | 1026000, /* 1.8 GHz */ | |
166 | 828000, /* 1.7 MHz */ | |
167 | 828000, /* 1.6 GHz */ | |
168 | 828000, /* 1.5 GHz */ | |
169 | 828000, /* 1.4 GHz */ | |
170 | 828000, /* 1.3 GHz */ | |
171 | 828000, /* 1.2 GHz */ | |
172 | 632000, /* 1.1 GHz */ | |
173 | 543000, /* 1.0 GHz */ | |
174 | 543000, /* 900 MHz */ | |
175 | 416000, /* 800 MHz */ | |
176 | 0, /* 700 MHz */ | |
177 | 0, /* 600 MHz */ | |
178 | 0, /* 500 MHz */ | |
179 | 0, /* 400 MHz */ | |
180 | 0, /* 300 MHz */ | |
181 | 0, /* 200 MHz */ | |
182 | }; | |
183 | ||
184 | static int exynos7420_cpufreq_smpl_warn_notifier_call( | |
185 | struct notifier_block *notifer, | |
186 | unsigned long event, void *v) | |
187 | { | |
188 | unsigned int state; | |
189 | ||
190 | state = __raw_readl(EXYNOS7420_ATLAS_SMPL_CTRL0); | |
191 | state &= ~0x40; | |
192 | __raw_writel(state, EXYNOS7420_ATLAS_SMPL_CTRL0); | |
193 | state |= 0x40; | |
194 | __raw_writel(state, EXYNOS7420_ATLAS_SMPL_CTRL0); | |
195 | ||
196 | pr_info("%s: SMPL_WARN: SMPL_WARN is cleared\n",__func__); | |
197 | ||
198 | return NOTIFY_OK; | |
199 | } | |
200 | ||
201 | static int exynos7420_check_smpl_CA57(void) | |
202 | { | |
203 | int tmp; | |
204 | ||
205 | tmp = __raw_readl(EXYNOS7420_ATLAS_SMPL_CTRL1); | |
206 | ||
207 | if (tmp & 0x80) { | |
208 | pr_info("%s: SMPL_WARN HAPPENED!\n", __func__); | |
209 | return 1; | |
210 | } | |
211 | ||
212 | return 0; | |
213 | }; | |
214 | ||
215 | static struct notifier_block exynos7420_cpufreq_smpl_warn_notifier = { | |
216 | .notifier_call = exynos7420_cpufreq_smpl_warn_notifier_call, | |
217 | }; | |
218 | ||
219 | static void exynos7420_set_clkdiv_CA57(unsigned int div_index) | |
220 | { | |
221 | unsigned int tmp, tmp1; | |
222 | ||
223 | /* Change Divider - ATLAS0 */ | |
224 | tmp = exynos7420_apll_freq_CA57[div_index].clk_div_cpu0; | |
225 | ||
226 | __raw_writel(tmp, EXYNOS7420_DIV_ATLAS0); | |
227 | ||
228 | while (__raw_readl(EXYNOS7420_DIV_STAT_ATLAS0) & 0x4101111) | |
229 | cpu_relax(); | |
230 | ||
231 | /* Change Divider - ATLAS1 */ | |
232 | tmp1 = exynos7420_apll_freq_CA57[div_index].clk_div_cpu1; | |
233 | ||
234 | __raw_writel(tmp1, EXYNOS7420_DIV_ATLAS1); | |
235 | ||
236 | while (__raw_readl(EXYNOS7420_DIV_STAT_ATLAS1) & 0x111) | |
237 | cpu_relax(); | |
238 | ||
239 | #ifdef PRINT_DIV_VAL | |
240 | tmp = __raw_readl(EXYNOS7420_DIV_ATLAS0); | |
241 | tmp1 = __raw_readl(EXYNOS7420_DIV_ATLAS1); | |
242 | ||
243 | pr_info("%s: DIV_ATLAS0[0x%08x], DIV_ATLAS1[0x%08x]\n", | |
244 | __func__, tmp, tmp1); | |
245 | #endif | |
246 | } | |
247 | ||
248 | static bool exynos7420_pms_change_CA57(unsigned int old_index, | |
249 | unsigned int new_index) | |
250 | { | |
251 | unsigned int old_pm = (exynos7420_apll_freq_CA57[old_index].mps >> | |
252 | EXYNOS7420_PLL_PDIV_SHIFT); | |
253 | unsigned int new_pm = (exynos7420_apll_freq_CA57[new_index].mps >> | |
254 | EXYNOS7420_PLL_PDIV_SHIFT); | |
255 | ||
256 | return (old_pm == new_pm) ? 0 : 1; | |
257 | } | |
258 | ||
259 | static void exynos7420_set_atlas_pll_CA57(unsigned int new_index, unsigned int old_index) | |
260 | { | |
261 | unsigned int tmp; | |
262 | ||
263 | if (!exynos7420_pms_change_CA57(old_index, new_index)) { | |
264 | /* Change MOUT_ATLAS_PLL frequency | |
265 | When PM value are matching with previous frequency | |
266 | then only S value should be change in this case | |
267 | don't need to change ATLAS_PLL to BUS0_PLL_ATLASO */ | |
268 | clk_set_rate(mout_atlas_pll, exynos7420_freq_table_CA57[new_index].frequency * 1000); | |
269 | } else { | |
270 | /* 1. before change to BUS0_PLL, set div for BUS0_PLL output */ | |
271 | if ((new_index > L17) && (old_index > L17)) | |
272 | exynos7420_set_clkdiv_CA57(L17); /* pll_safe_idx of CA57 */ | |
273 | ||
274 | /* 2. MUX_SEL_ATLAS = MOUT_BUS0_PLL_ALTAS, ATLASCLK uses BUS0_PLL_ATLAS for lock time */ | |
275 | if (clk_set_parent(mout_atlas, mout_bus0_pll_atlas)) | |
276 | pr_err("Unable to set parent %s of clock %s.\n", | |
277 | mout_bus0_pll_atlas->name, mout_atlas->name); | |
278 | do { | |
279 | cpu_relax(); | |
280 | tmp = __raw_readl(EXYNOS7420_MUX_STAT_ATLAS2); | |
281 | tmp &= EXYNOS7420_MUX_STAT_CORE2_MASK; | |
282 | tmp >>= EXYNOS7420_MUX_STAT_CORE2_SHIFT; | |
283 | } while (tmp != 0x1); | |
284 | ||
285 | /* 3. Change MOUT_ATLAS_PLL Frequency */ | |
286 | clk_set_rate(mout_atlas_pll, exynos7420_freq_table_CA57[new_index].frequency * 1000); | |
287 | ||
288 | /* 4. MUX_SEL_ATLAS = MOUT_ATLAS_PLL */ | |
289 | if (clk_set_parent(mout_atlas, mout_atlas_pll)) | |
290 | pr_err("Unable to set parent %s of clock %s.\n", | |
291 | mout_atlas_pll->name, mout_atlas->name); | |
292 | do { | |
293 | cpu_relax(); | |
294 | tmp = __raw_readl(EXYNOS7420_MUX_STAT_ATLAS2); | |
295 | tmp &= EXYNOS7420_MUX_STAT_CORE2_MASK; | |
296 | tmp >>= EXYNOS7420_MUX_STAT_CORE2_SHIFT; | |
297 | } while (tmp != 0x0); | |
298 | ||
299 | /* 5. restore original div value */ | |
300 | if ((new_index > L17) && (old_index > L17)) | |
301 | exynos7420_set_clkdiv_CA57(new_index); | |
302 | } | |
303 | } | |
304 | ||
305 | static void exynos7420_set_frequency_CA57(unsigned int old_index, | |
306 | unsigned int new_index) | |
307 | { | |
308 | if (old_index > new_index) { | |
309 | /* Clock Configuration Procedure */ | |
310 | /* 1. Change the system clock divider values */ | |
311 | exynos7420_set_clkdiv_CA57(new_index); | |
312 | /* 2. Change the atlas_pll m,p,s value */ | |
313 | exynos7420_set_atlas_pll_CA57(new_index, old_index); | |
314 | } else if (old_index < new_index) { | |
315 | /* Clock Configuration Procedure */ | |
316 | /* 1. Change the atlas_pll m,p,s value */ | |
317 | exynos7420_set_atlas_pll_CA57(new_index, old_index); | |
318 | /* 2. Change the system clock divider values */ | |
319 | exynos7420_set_clkdiv_CA57(new_index); | |
320 | } | |
321 | ||
322 | pr_debug("[%s] Atlas NewFreq: %d OldFreq: %d\n", __func__, exynos7420_freq_table_CA57[new_index].frequency, | |
323 | exynos7420_freq_table_CA57[old_index].frequency); | |
324 | } | |
325 | ||
326 | static void __init set_volt_table_CA57(void) | |
327 | { | |
328 | unsigned int i; | |
329 | unsigned int asv_volt = 0; | |
330 | ||
331 | for (i = 0; i < CPUFREQ_LEVEL_END_CA57; i++) { | |
332 | asv_volt = get_match_volt(ID_CL1, exynos7420_freq_table_CA57[i].frequency); | |
333 | if (!asv_volt) | |
334 | exynos7420_volt_table_CA57[i] = asv_voltage_7420_CA57[i]; | |
335 | else | |
336 | exynos7420_volt_table_CA57[i] = asv_volt; | |
337 | ||
338 | pr_info("CPUFREQ of CA57 L%d : %d uV\n", i, | |
339 | exynos7420_volt_table_CA57[i]); | |
340 | ||
341 | exynos7420_abb_table_CA57[i] = | |
342 | get_match_abb(ID_CL1, exynos7420_freq_table_CA57[i].frequency); | |
343 | ||
344 | pr_info("CPUFREQ of CA57 L%d : ABB %d\n", i, | |
345 | exynos7420_abb_table_CA57[i]); | |
346 | } | |
347 | ||
348 | #if defined(CONFIG_CPU_THERMAL) && defined(CONFIG_EXYNOS5_DYNAMIC_CPU_HOTPLUG) | |
349 | switch (exynos_get_table_ver()) { | |
350 | case 0 : | |
351 | case 1 : | |
352 | case 4 : | |
353 | max_support_idx_CA57 = L7; break; /* 1.8GHz */ | |
354 | case 5 : | |
355 | max_support_idx_CA57 = L10; break; /* 1.5GHz */ | |
356 | default : | |
357 | max_support_idx_CA57 = L4; /* 2.1GHz */ | |
358 | } | |
359 | #else | |
360 | max_support_idx_CA57 = L13; /* 1.2 GHz */ | |
361 | #endif | |
362 | ||
363 | min_support_idx_CA57 = L17; /* 800 MHz */ | |
364 | ||
365 | pr_info("CPUFREQ of CA57 max_freq : L%d %u khz\n", max_support_idx_CA57, | |
366 | exynos7420_freq_table_CA57[max_support_idx_CA57].frequency); | |
367 | pr_info("CPUFREQ of CA57 min_freq : L%d %u khz\n", min_support_idx_CA57, | |
368 | exynos7420_freq_table_CA57[min_support_idx_CA57].frequency); | |
369 | } | |
370 | static bool exynos7420_is_alive_CA57(void) | |
371 | { | |
372 | unsigned int tmp; | |
373 | ||
374 | tmp = __raw_readl(EXYNOS7420_ATLAS_PLL_CON1); | |
375 | tmp &= EXYNOS7420_PLL_BYPASS_MASK; | |
376 | tmp >>= EXYNOS7420_PLL_BYPASS_SHIFT; | |
377 | ||
378 | return !tmp ? true : false; | |
379 | } | |
380 | ||
381 | static void exynos7420_set_ema_CA57(unsigned int volt) | |
382 | { | |
383 | exynos_set_ema(ID_CL1, volt); | |
384 | } | |
385 | ||
386 | int __init exynos_cpufreq_cluster1_init(struct exynos_dvfs_info *info) | |
387 | { | |
388 | unsigned long rate; | |
389 | struct device_node *pmic_node; | |
390 | int ret, tmp; | |
391 | ||
392 | set_volt_table_CA57(); | |
393 | ||
394 | mout_atlas_pll = clk_get(NULL, "mout_atlas_pll"); | |
395 | if (IS_ERR(mout_atlas_pll)) { | |
396 | pr_err("failed get mout_atlas_pll clk\n"); | |
397 | goto err_mout_atlas_pll; | |
398 | } | |
399 | ||
400 | mout_atlas = clk_get(NULL, "mout_atlas"); | |
401 | if (IS_ERR(mout_atlas)) { | |
402 | pr_err("failed get mout_atlas clk\n"); | |
403 | goto err_mout_atlas; | |
404 | } | |
405 | ||
406 | if (clk_set_parent(mout_atlas, mout_atlas_pll)) { | |
407 | pr_err("Unable to set parent %s of clock %s.\n", | |
408 | mout_atlas_pll->name, mout_atlas->name); | |
409 | goto err_clk_set_parent_atlas; | |
410 | } | |
411 | ||
412 | mout_bus0_pll_atlas = clk_get(NULL, "mout_bus0_pll_atlas"); | |
413 | if (IS_ERR(mout_bus0_pll_atlas)) { | |
414 | pr_err("failed get mout_bus0_pll_atlas clk\n"); | |
415 | goto err_mout_bus0_pll_atlas; | |
416 | } | |
417 | ||
418 | if (clk_prepare_enable(mout_atlas_pll) || clk_prepare_enable(mout_atlas)) { | |
419 | pr_err("Unable to enable Atlas clocks \n"); | |
420 | goto err_clk_prepare_enable; | |
421 | } | |
422 | ||
423 | rate = clk_get_rate(mout_bus0_pll_atlas) / 1000; | |
424 | ||
425 | info->mpll_freq_khz = rate; | |
426 | info->pll_safe_idx = L17; | |
427 | info->max_support_idx = max_support_idx_CA57; | |
428 | info->min_support_idx = min_support_idx_CA57; | |
429 | ||
430 | /* booting frequency is 1.7GHz */ | |
431 | info->boot_cpu_min_qos = exynos7420_freq_table_CA57[L8].frequency; | |
432 | info->boot_cpu_max_qos = exynos7420_freq_table_CA57[L8].frequency; | |
433 | info->bus_table = exynos7420_bus_table_CA57; | |
434 | info->cpu_clk = mout_atlas_pll; | |
435 | ||
436 | /* reboot limit frequency is 800MHz */ | |
437 | info->reboot_limit_freq = exynos7420_freq_table_CA57[L17].frequency; | |
438 | ||
439 | info->volt_table = exynos7420_volt_table_CA57; | |
440 | info->abb_table = NULL; //exynos7420_abb_table_CA57; | |
441 | info->freq_table = exynos7420_freq_table_CA57; | |
442 | info->set_freq = exynos7420_set_frequency_CA57; | |
443 | info->need_apll_change = exynos7420_pms_change_CA57; | |
444 | info->is_alive = exynos7420_is_alive_CA57; | |
445 | info->set_ema = exynos7420_set_ema_CA57; | |
446 | ||
447 | pmic_node = of_find_compatible_node(NULL, NULL, "samsung,s2mps15-pmic"); | |
448 | ||
449 | if (!pmic_node) { | |
450 | pr_err("%s: faile to get pmic dt_node\n", __func__); | |
451 | } else { | |
452 | ret = of_property_read_u32(pmic_node, "smpl_warn_en", &en_smpl_warn); | |
453 | if (ret) | |
454 | pr_err("%s: faile to get Property of smpl_warn_en\n", __func__); | |
455 | } | |
456 | ||
457 | if (en_smpl_warn) { | |
458 | info->check_smpl = exynos7420_check_smpl_CA57; | |
459 | ||
460 | /* ATLAS_RATIO_SMPL */ | |
461 | tmp = __raw_readl(EXYNOS7420_ATLAS_SMPL_CTRL0); | |
462 | tmp &= 0x7F; | |
463 | tmp |= 0x44; | |
464 | __raw_writel(tmp, EXYNOS7420_ATLAS_SMPL_CTRL0); | |
465 | pr_info("%s SMPL_WARN ENABLE (DIV:%d) ", __func__, tmp&0x3F); | |
466 | ||
467 | exynos_cpufreq_smpl_warn_register_notifier(&exynos7420_cpufreq_smpl_warn_notifier); | |
468 | } | |
469 | ||
470 | return 0; | |
471 | ||
472 | err_clk_prepare_enable: | |
473 | err_mout_bus0_pll_atlas: | |
474 | err_clk_set_parent_atlas: | |
475 | clk_put(mout_atlas); | |
476 | err_mout_atlas: | |
477 | clk_put(mout_atlas_pll); | |
478 | err_mout_atlas_pll: | |
479 | ||
480 | pr_debug("%s: failed initialization\n", __func__); | |
481 | return -EINVAL; | |
482 | } |