2 * Copyright (c) 2014 Samsung Electronics Co., Ltd.
3 * http://www.samsung.com
5 * EXYNOS5433 - ATLAS Core frequency scaling support
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.
12 #include <linux/kernel.h>
13 #include <linux/err.h>
14 #include <linux/clk.h>
16 #include <linux/slab.h>
17 #include <linux/cpufreq.h>
18 #include <linux/clk-private.h>
21 #include <mach/regs-clock.h>
22 #include <mach/regs-clock-exynos5433.h>
23 #include <mach/regs-pmu.h>
24 #include <mach/cpufreq.h>
25 #include <mach/asv-exynos.h>
26 #include <mach/asv-exynos_cal.h>
29 #define CPUFREQ_LEVEL_END_CA57 (L23 + 1)
30 #define L2_LOCAL_PWR_EN 0x7
35 static int max_support_idx_CA57
;
36 static int min_support_idx_CA57
= (CPUFREQ_LEVEL_END_CA57
- 1);
38 static struct clk
*mout_atlas
;
39 static struct clk
*mout_atlas_pll
;
40 static struct clk
*mout_bus_pll_div2
;
41 static struct clk
*mout_bus_pll_user
;
42 static struct clk
*fout_atlas_pll
;
44 static unsigned int exynos5433_volt_table_CA57
[CPUFREQ_LEVEL_END_CA57
];
45 static unsigned int exynos5433_abb_table_CA57
[CPUFREQ_LEVEL_END_CA57
];
47 static int en_smpl_warn
= 0;
48 static BLOCKING_NOTIFIER_HEAD(exynos_cpufreq_smpl_warn_notifier_list
);
49 int exynos_cpufreq_smpl_warn_register_notifier(struct notifier_block
*nb
)
51 return blocking_notifier_chain_register(&exynos_cpufreq_smpl_warn_notifier_list
, nb
);
54 int exynos_cpufreq_smpl_warn_unregister_notifier(struct notifier_block
*nb
)
56 return blocking_notifier_chain_unregister(&exynos_cpufreq_smpl_warn_notifier_list
, nb
);
59 int exynos_cpufreq_smpl_warn_notify_call_chain(void)
61 int ret
= blocking_notifier_call_chain(&exynos_cpufreq_smpl_warn_notifier_list
, 0, NULL
);
62 return notifier_to_errno(ret
);
64 EXPORT_SYMBOL(exynos_cpufreq_smpl_warn_notify_call_chain
);
66 static struct cpufreq_frequency_table exynos5433_freq_table_CA57
[] = {
91 {0, CPUFREQ_TABLE_END
},
94 static struct apll_freq exynos5433_apll_freq_CA57
[] = {
98 * clock divider for ATLAS1, ATLAS2, ACLK_ATLAS, PCLK_ATLAS, ATCLK, PCLK_DBG_ATLAS, SCLK_CNTCLK, RESERVED
99 * clock divider for SCLK_ATLAS_PLL, SCLK_HPM_ATLAS, RESERVED
102 APLL_FREQ(2500, 0, 0, 4, 7, 7, 7, 7, 0, 1, 7, 0, 625, 6, 0), /* ARM L0: 2.5GHz */
103 APLL_FREQ(2400, 0, 0, 4, 7, 7, 7, 7, 0, 1, 7, 0, 500, 5, 0), /* ARM L1: 2.4GMHz */
104 APLL_FREQ(2300, 0, 0, 4, 7, 7, 7, 7, 0, 1, 7, 0, 575, 6, 0), /* ARM L2: 2.3GMHz */
105 APLL_FREQ(2200, 0, 0, 4, 7, 7, 7, 7, 0, 1, 7, 0, 550, 6, 0), /* ARM L3: 2.2GHz */
106 APLL_FREQ(2100, 0, 0, 4, 7, 7, 7, 7, 0, 1, 7, 0, 350, 4, 0), /* ARM L4: 2.1GHz */
107 APLL_FREQ(2000, 0, 0, 4, 7, 7, 7, 7, 0, 1, 7, 0, 500, 6, 0), /* ARM L5: 2.0GHz */
108 APLL_FREQ(1900, 0, 0, 4, 7, 7, 7, 7, 0, 1, 7, 0, 475, 6, 0), /* ARM L6: 1.9GHz */
109 APLL_FREQ(1800, 0, 0, 4, 7, 7, 7, 7, 0, 1, 7, 0, 375, 5, 0), /* ARM L7: 1.8GHz */
110 APLL_FREQ(1700, 0, 0, 4, 7, 7, 7, 7, 0, 1, 7, 0, 425, 6, 0), /* ARM L8: 1.7GHz */
111 APLL_FREQ(1600, 0, 0, 4, 7, 7, 7, 7, 0, 1, 7, 0, 400, 6, 0), /* ARM L9: 1.6GHz */
112 APLL_FREQ(1500, 0, 0, 3, 7, 7, 7, 7, 0, 1, 7, 0, 250, 4, 0), /* ARM L10: 1.5GHz */
113 APLL_FREQ(1400, 0, 0, 3, 7, 7, 7, 7, 0, 1, 7, 0, 350, 6, 0), /* ARM L11: 1.4GHz */
114 APLL_FREQ(1300, 0, 0, 3, 7, 7, 7, 7, 0, 1, 7, 0, 325, 6, 0), /* ARM L12: 1.3GHz */
115 APLL_FREQ(1200, 0, 0, 3, 7, 7, 7, 7, 0, 1, 7, 0, 500, 5, 1), /* ARM L13: 1.2GHz */
116 APLL_FREQ(1100, 0, 0, 3, 7, 7, 7, 7, 0, 1, 7, 0, 550, 6, 1), /* ARM L14: 1.1GHz */
117 APLL_FREQ(1000, 0, 0, 3, 7, 7, 7, 7, 0, 1, 7, 0, 500, 6, 1), /* ARM L15: 1.0GHz */
118 APLL_FREQ( 900, 0, 0, 2, 7, 7, 7, 7, 0, 1, 7, 0, 375, 5, 1), /* ARM L16: 900MHz */
119 APLL_FREQ( 800, 0, 0, 2, 7, 7, 7, 7, 0, 1, 7, 0, 400, 6, 1), /* ARM L17: 800MHz */
120 APLL_FREQ( 700, 0, 0, 2, 7, 7, 7, 7, 0, 1, 7, 0, 350, 6, 1), /* ARM L18: 700MHz */
121 APLL_FREQ( 600, 0, 0, 2, 7, 7, 7, 7, 0, 1, 7, 0, 500, 5, 2), /* ARM L19: 600MHz */
122 APLL_FREQ( 500, 0, 0, 2, 7, 7, 7, 7, 0, 1, 7, 0, 500, 6, 2), /* ARM L20: 500MHz */
123 APLL_FREQ( 400, 0, 0, 2, 7, 7, 7, 7, 0, 1, 7, 0, 400, 6, 2), /* ARM L21: 400MHz */
124 APLL_FREQ( 300, 0, 0, 2, 7, 7, 7, 7, 0, 1, 7, 0, 500, 5, 3), /* ARM L22: 300MHz */
125 APLL_FREQ( 200, 0, 0, 2, 7, 7, 7, 7, 0, 1, 7, 0, 400, 6, 3), /* ARM L23: 200MHz */
129 * ASV group voltage table
131 static const unsigned int asv_voltage_5433_CA57
[CPUFREQ_LEVEL_END_CA57
] = {
132 1350000, /* L0 2500 */
133 1350000, /* L1 2400 */
134 1350000, /* L2 2300 */
135 1350000, /* L3 2200 */
136 1350000, /* L4 2100 */
137 1312500, /* L5 2000 */
138 1262500, /* L6 1900 */
139 1212500, /* L7 1800 */
140 1175000, /* L8 1700 */
141 1137500, /* L9 1600 */
142 1112500, /* L10 1500 */
143 1087500, /* L11 1400 */
144 1062500, /* L12 1300 */
145 1037500, /* L13 1200 */
146 1012500, /* L14 1100 */
147 975000, /* L15 1000 */
148 937500, /* L16 900 */
149 912500, /* L17 800 */
150 912500, /* L18 700 */
151 900000, /* L19 600 */
152 900000, /* L20 500 */
153 900000, /* L21 400 */
154 900000, /* L22 300 */
155 900000, /* L23 200 */
158 /* Minimum memory throughput in megabytes per second */
159 static int exynos5433_bus_table_CA57
[CPUFREQ_LEVEL_END_CA57
] = {
160 825000, /* 2.5 GHz */
161 825000, /* 2.4 GHz */
162 825000, /* 2.3 GHz */
163 825000, /* 2.2 GHz */
164 825000, /* 2.1 GHz */
165 825000, /* 2.0 GHz */
166 825000, /* 1.9 GHz */
167 825000, /* 1.8 GHz */
168 667000, /* 1.7 MHz */
169 667000, /* 1.6 GHz */
170 667000, /* 1.5 GHz */
171 667000, /* 1.4 GHz */
172 543000, /* 1.3 GHz */
173 543000, /* 1.2 GHz */
174 413000, /* 1.1 GHz */
175 413000, /* 1.0 GHz */
186 static void exynos5433_set_ema_CA57(unsigned int target_volt
)
188 cal_set_ema(SYSC_DVFS_BIG
, target_volt
);
191 static int exynos5433_cpufreq_smpl_warn_notifier_call(
192 struct notifier_block
*notifer
,
193 unsigned long event
, void *v
)
197 state
= __raw_readl(EXYNOS5430_DIV_EGL_PLL_FREQ_DET
);
199 __raw_writel(state
, EXYNOS5430_DIV_EGL_PLL_FREQ_DET
);
200 pr_info("%s: SMPL_WARN: EXYNOS5430_DIV_EGL_PLL_FREQ_DET is cleared\n",__func__
);
205 static int exynos5433_check_smpl_CA57(void)
209 tmp
= __raw_readl(EXYNOS5430_DIV_EGL_PLL_FREQ_DET
);
212 pr_info("%s: SMPL HAPPENED!", __func__
);
219 static struct notifier_block exynos5433_cpufreq_smpl_warn_notifier
= {
220 .notifier_call
= exynos5433_cpufreq_smpl_warn_notifier_call
,
223 static void exynos5433_set_clkdiv_CA57(unsigned int div_index
)
225 unsigned int tmp
, tmp1
;
227 /* Change Divider - ATLAS0 */
228 tmp
= exynos5433_apll_freq_CA57
[div_index
].clk_div_cpu0
;
230 __raw_writel(tmp
, EXYNOS5430_DIV_EGL0
);
232 while (__raw_readl(EXYNOS5430_DIV_STAT_EGL0
) & 0x1111111)
235 /* Change Divider - ATLAS1 */
236 tmp1
= exynos5433_apll_freq_CA57
[div_index
].clk_div_cpu1
;
238 __raw_writel(tmp1
, EXYNOS5430_DIV_EGL1
);
240 while (__raw_readl(EXYNOS5430_DIV_STAT_EGL1
) & 0x11)
244 tmp
= __raw_readl(EXYNOS5430_DIV_EGL0
);
245 tmp1
= __raw_readl(EXYNOS5430_DIV_EGL1
);
247 pr_info("%s: DIV_ATLAS0[0x%08x], DIV_ATLAS1[0x%08x]\n",
248 __func__
, tmp
, tmp1
);
252 static void exynos5433_set_atlas_pll_CA57(unsigned int new_index
, unsigned int old_index
)
254 unsigned int tmp
, pdiv
;
256 /* 1. before change to BUS_PLL, set div for BUS_PLL output */
257 if ((new_index
> L17
) && (old_index
> L17
))
258 exynos5433_set_clkdiv_CA57(L17
); /* pll_safe_idx of CA57 */
260 /* 2. CLKMUX_SEL_ATLAS = MOUT_BUS_PLL_USER, ATLASCLK uses BUS_PLL_USER for lock time */
261 if (clk_set_parent(mout_atlas
, mout_bus_pll_user
))
262 pr_err("Unable to set parent %s of clock %s.\n",
263 mout_bus_pll_user
->name
, mout_atlas
->name
);
266 tmp
= __raw_readl(EXYNOS5430_SRC_STAT_EGL2
);
267 tmp
&= EXYNOS5430_SRC_STAT_EGL2_EGL_MASK
;
268 tmp
>>= EXYNOS5430_SRC_STAT_EGL2_EGL_SHIFT
;
269 } while (tmp
!= 0x2);
271 /* 3. Set ATLAS_PLL Lock time */
272 pdiv
= ((exynos5433_apll_freq_CA57
[new_index
].mps
&
273 EXYNOS5430_PLL_PDIV_MASK
) >> EXYNOS5430_PLL_PDIV_SHIFT
);
275 __raw_writel((pdiv
* 150), EXYNOS5430_EGL_PLL_LOCK
);
277 /* 4. Change PLL PMS values */
278 tmp
= __raw_readl(EXYNOS5430_EGL_PLL_CON0
);
279 tmp
&= ~(EXYNOS5430_PLL_MDIV_MASK
|
280 EXYNOS5430_PLL_PDIV_MASK
|
281 EXYNOS5430_PLL_SDIV_MASK
);
282 tmp
|= exynos5433_apll_freq_CA57
[new_index
].mps
;
283 __raw_writel(tmp
, EXYNOS5430_EGL_PLL_CON0
);
285 /* 5. wait_lock_time */
288 tmp
= __raw_readl(EXYNOS5430_EGL_PLL_CON0
);
289 } while (!(tmp
& (0x1 << EXYNOS5430_EGL_PLL_CON0_LOCKED_SHIFT
)));
291 /* 6. CLKMUX_SEL_ATLAS = MOUT_ATLAS_PLL */
292 if (clk_set_parent(mout_atlas
, mout_atlas_pll
))
293 pr_err("Unable to set parent %s of clock %s.\n",
294 mout_atlas_pll
->name
, mout_atlas
->name
);
297 tmp
= __raw_readl(EXYNOS5430_SRC_STAT_EGL2
);
298 tmp
&= EXYNOS5430_SRC_STAT_EGL2_EGL_MASK
;
299 tmp
>>= EXYNOS5430_SRC_STAT_EGL2_EGL_SHIFT
;
300 } while (tmp
!= 0x1);
302 /* 7. restore original div value */
303 if ((new_index
> L17
) && (old_index
> L17
))
304 exynos5433_set_clkdiv_CA57(new_index
);
307 static bool exynos5433_pms_change_CA57(unsigned int old_index
,
308 unsigned int new_index
)
310 unsigned int old_pm
= (exynos5433_apll_freq_CA57
[old_index
].mps
>>
311 EXYNOS5430_PLL_PDIV_SHIFT
);
312 unsigned int new_pm
= (exynos5433_apll_freq_CA57
[new_index
].mps
>>
313 EXYNOS5430_PLL_PDIV_SHIFT
);
315 return (old_pm
== new_pm
) ? 0 : 1;
318 static void exynos5433_set_frequency_CA57(unsigned int old_index
,
319 unsigned int new_index
)
323 if (old_index
> new_index
) {
324 if (!exynos5433_pms_change_CA57(old_index
, new_index
)) {
325 /* 1. Change the system clock divider values */
326 exynos5433_set_clkdiv_CA57(new_index
);
327 /* 2. Change just s value in atlas_pll m,p,s value */
328 tmp
= __raw_readl(EXYNOS5430_EGL_PLL_CON0
);
329 tmp
&= ~EXYNOS5430_PLL_SDIV_MASK
;
330 tmp
|= (exynos5433_apll_freq_CA57
[new_index
].mps
& EXYNOS5430_PLL_SDIV_MASK
);
331 __raw_writel(tmp
, EXYNOS5430_EGL_PLL_CON0
);
333 /* Clock Configuration Procedure */
334 /* 1. Change the system clock divider values */
335 exynos5433_set_clkdiv_CA57(new_index
);
336 /* 2. Change the atlas_pll m,p,s value */
337 exynos5433_set_atlas_pll_CA57(new_index
, old_index
);
339 } else if (old_index
< new_index
) {
340 if (!exynos5433_pms_change_CA57(old_index
, new_index
)) {
341 /* 1. Change just s value in atlas_pll m,p,s value */
342 tmp
= __raw_readl(EXYNOS5430_EGL_PLL_CON0
);
343 tmp
&= ~EXYNOS5430_PLL_SDIV_MASK
;
344 tmp
|= (exynos5433_apll_freq_CA57
[new_index
].mps
& EXYNOS5430_PLL_SDIV_MASK
);
345 __raw_writel(tmp
, EXYNOS5430_EGL_PLL_CON0
);
346 /* 2. Change the system clock divider values */
347 exynos5433_set_clkdiv_CA57(new_index
);
349 /* Clock Configuration Procedure */
350 /* 1. Change the atlas_pll m,p,s value */
351 exynos5433_set_atlas_pll_CA57(new_index
, old_index
);
352 /* 2. Change the system clock divider values */
353 exynos5433_set_clkdiv_CA57(new_index
);
357 clk_set_rate(fout_atlas_pll
, exynos5433_freq_table_CA57
[new_index
].frequency
* 1000);
358 pr_debug("[%s] Atlas NewFreq: %d OldFreq: %d\n", __func__
, exynos5433_freq_table_CA57
[new_index
].frequency
,
359 exynos5433_freq_table_CA57
[old_index
].frequency
);
362 static void __init
set_volt_table_CA57(void)
365 unsigned int asv_volt
= 0;
367 for (i
= 0; i
< CPUFREQ_LEVEL_END_CA57
; i
++) {
368 asv_volt
= get_match_volt(ID_CL1
, exynos5433_freq_table_CA57
[i
].frequency
);
370 exynos5433_volt_table_CA57
[i
] = asv_voltage_5433_CA57
[i
];
372 exynos5433_volt_table_CA57
[i
] = asv_volt
;
374 pr_info("CPUFREQ of CA57 L%d : %d uV\n", i
,
375 exynos5433_volt_table_CA57
[i
]);
377 exynos5433_abb_table_CA57
[i
] =
378 get_match_abb(ID_CL1
, exynos5433_freq_table_CA57
[i
].frequency
);
380 pr_info("CPUFREQ of CA57 L%d : ABB %d\n", i
,
381 exynos5433_abb_table_CA57
[i
]);
384 #if defined(CONFIG_CPU_THERMAL) && defined(CONFIG_EXYNOS5_DYNAMIC_CPU_HOTPLUG)
385 switch (exynos_get_table_ver()) {
387 max_support_idx_CA57
= L13
; /* 1.2 GHz */
391 max_support_idx_CA57
= L8
; /* 1.7 GHz */
394 max_support_idx_CA57
= L7
; /* 1.8 GHz */
397 max_support_idx_CA57
= L6
; /* 1.9 GHz */
400 if (is_max_limit_sample() == 1)
401 max_support_idx_CA57
= L8
; /* 1.7 GHz */
403 max_support_idx_CA57
= L13
; /* 1.2 GHz */
406 min_support_idx_CA57
= L18
; /* 700 MHz */
408 pr_info("CPUFREQ of CA57 max_freq : L%d %u khz\n", max_support_idx_CA57
,
409 exynos5433_freq_table_CA57
[max_support_idx_CA57
].frequency
);
410 pr_info("CPUFREQ of CA57 min_freq : L%d %u khz\n", min_support_idx_CA57
,
411 exynos5433_freq_table_CA57
[min_support_idx_CA57
].frequency
);
414 static bool exynos5433_is_alive_CA57(void)
418 tmp
= __raw_readl(EXYNOS5430_EGL_PLL_CON1
);
419 tmp
&= EXYNOS5430_PLL_BYPASS_MASK
;
420 tmp
>>= EXYNOS5430_PLL_BYPASS_SHIFT
;
422 return !tmp
? true : false;
425 int __init
exynos_cpufreq_cluster1_init(struct exynos_dvfs_info
*info
)
429 struct device_node
*pmic_node
;
431 set_volt_table_CA57();
433 mout_atlas
= clk_get(NULL
, "mout_egl");
434 if (IS_ERR(mout_atlas
)) {
435 pr_err("failed get mout_atlas clk\n");
439 mout_atlas_pll
= clk_get(NULL
, "mout_egl_pll");
440 if (IS_ERR(mout_atlas_pll
)) {
441 pr_err("failed get mout_atlas_pll clk\n");
442 goto err_mout_atlas_pll
;
445 if (clk_set_parent(mout_atlas
, mout_atlas_pll
)) {
446 pr_err("Unable to set parent %s of clock %s.\n",
447 mout_atlas_pll
->name
, mout_atlas
->name
);
448 goto err_clk_set_parent_atlas
;
451 mout_bus_pll_div2
= clk_get(NULL
, "mout_bus_pll_div2");
452 if (IS_ERR(mout_bus_pll_div2
)) {
453 pr_err("failed get mout_bus_pll_div2 clk\n");
454 goto err_sclk_bus_pll
;
457 mout_bus_pll_user
= clk_get(NULL
, "mout_bus_pll_egl_user");
458 if (IS_ERR(mout_bus_pll_user
)) {
459 pr_err("failed get mout_bus_pll_user clk\n");
460 goto err_mout_bus_pll_user
;
463 if (clk_set_parent(mout_bus_pll_user
, mout_bus_pll_div2
)) {
464 pr_err("Unable to set parent %s of clock %s.\n",
465 mout_bus_pll_div2
->name
, mout_bus_pll_user
->name
);
466 goto err_clk_set_parent_bus_pll
;
469 rate
= clk_get_rate(mout_bus_pll_user
) / 1000;
471 fout_atlas_pll
= clk_get(NULL
, "fout_egl_pll");
472 if (IS_ERR(fout_atlas_pll
)) {
473 pr_err("failed get fout_atlas_pll clk\n");
474 goto err_fout_atlas_pll
;
477 clk_put(mout_bus_pll_div2
);
479 info
->mpll_freq_khz
= rate
;
480 info
->pll_safe_idx
= L17
;
481 info
->max_support_idx
= max_support_idx_CA57
;
482 info
->min_support_idx
= min_support_idx_CA57
;
484 /* booting frequency is 1.2GHz */
485 info
->boot_cpu_min_qos
= exynos5433_freq_table_CA57
[L13
].frequency
;
486 info
->boot_cpu_max_qos
= exynos5433_freq_table_CA57
[L13
].frequency
;
487 /* reboot limit frequency is 800MHz */
489 info
->reboot_limit_freq
= exynos5433_freq_table_CA57
[L17
].frequency
;
490 info
->bus_table
= exynos5433_bus_table_CA57
;
491 info
->cpu_clk
= fout_atlas_pll
;
493 info
->volt_table
= exynos5433_volt_table_CA57
;
494 info
->abb_table
= exynos5433_abb_table_CA57
;
495 info
->freq_table
= exynos5433_freq_table_CA57
;
496 info
->set_freq
= exynos5433_set_frequency_CA57
;
497 info
->need_apll_change
= exynos5433_pms_change_CA57
;
498 info
->is_alive
= exynos5433_is_alive_CA57
;
499 info
->set_ema
= exynos5433_set_ema_CA57
;
501 /* get smpl_enable value */
502 pmic_node
= of_find_compatible_node(NULL
, NULL
, "samsung,s2mps13-pmic");
505 pr_err("%s: faile to get pmic dt_node\n", __func__
);
507 ret
= of_property_read_u32(pmic_node
, "smpl_warn_en", &en_smpl_warn
);
509 pr_err("%s: faile to get Property of smpl_warn_en\n", __func__
);
513 info
->check_smpl
= exynos5433_check_smpl_CA57
;
516 tmp
= __raw_readl(EXYNOS5430_DIV_EGL_PLL_FREQ_DET
);
517 pr_info("%s SMPL ENABLE %d ", __func__
, tmp
);
520 pr_info("%s -- SMPL ENABLE %d ", __func__
, tmp
);
521 __raw_writel(tmp
, EXYNOS5430_DIV_EGL_PLL_FREQ_DET
);
523 /* Add smpl_notifer */
524 exynos_cpufreq_smpl_warn_register_notifier(&exynos5433_cpufreq_smpl_warn_notifier
);
528 /* dividing ATLAS_CLK to 1/16 */
529 tmp
= __raw_readl(EXYNOS5430_CLKOUT_CMU_EGL
);
532 __raw_writel(tmp
, EXYNOS5430_CLKOUT_CMU_EGL
);
538 err_clk_set_parent_bus_pll
:
539 clk_put(mout_bus_pll_user
);
540 err_mout_bus_pll_user
:
541 clk_put(mout_bus_pll_div2
);
543 err_clk_set_parent_atlas
:
544 clk_put(mout_atlas_pll
);
548 pr_debug("%s: failed initialization\n", __func__
);