2 * Copyright (c) 2012 Samsung Electronics Co., Ltd.
3 * http://www.samsung.com/
5 * EXYNOS5 INT clock frequency scaling support using DEVFREQ framework
6 * Based on work done by Jonghwan Choi <jhbird.choi@samsung.com>
7 * Support for only EXYNOS5250 is present.
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
15 #include <linux/module.h>
16 #include <linux/devfreq.h>
18 #include <linux/pm_opp.h>
19 #include <linux/slab.h>
20 #include <linux/suspend.h>
21 #include <linux/clk.h>
22 #include <linux/delay.h>
23 #include <linux/platform_device.h>
24 #include <linux/pm_qos.h>
25 #include <linux/regulator/consumer.h>
26 #include <linux/of_address.h>
27 #include <linux/of_platform.h>
29 #include "exynos_ppmu.h"
31 #define MAX_SAFEVOLT 1100000 /* 1.10V */
32 /* Assume that the bus is saturated if the utilization is 25% */
33 #define INT_BUS_SATURATION_RATIO 25
44 enum exynos_ppmu_list
{
49 struct busfreq_data_int
{
51 struct devfreq
*devfreq
;
52 struct regulator
*vdd_int
;
53 struct busfreq_ppmu_data ppmu_data
;
54 unsigned long curr_freq
;
57 struct notifier_block pm_notifier
;
59 struct pm_qos_request int_req
;
63 struct int_bus_opp_table
{
69 static struct int_bus_opp_table exynos5_int_opp_table
[] = {
70 {LV_0
, 266000, 1025000},
71 {LV_1
, 200000, 1025000},
72 {LV_2
, 160000, 1025000},
73 {LV_3
, 133000, 1025000},
74 {LV_4
, 100000, 1025000},
78 static int exynos5_int_setvolt(struct busfreq_data_int
*data
,
81 return regulator_set_voltage(data
->vdd_int
, volt
, MAX_SAFEVOLT
);
84 static int exynos5_busfreq_int_target(struct device
*dev
, unsigned long *_freq
,
88 struct platform_device
*pdev
= container_of(dev
, struct platform_device
,
90 struct busfreq_data_int
*data
= platform_get_drvdata(pdev
);
91 struct dev_pm_opp
*opp
;
92 unsigned long old_freq
, freq
;
96 opp
= devfreq_recommended_opp(dev
, _freq
, flags
);
99 dev_err(dev
, "%s: Invalid OPP.\n", __func__
);
103 freq
= dev_pm_opp_get_freq(opp
);
104 volt
= dev_pm_opp_get_voltage(opp
);
107 old_freq
= data
->curr_freq
;
109 if (old_freq
== freq
)
112 dev_dbg(dev
, "targeting %lukHz %luuV\n", freq
, volt
);
114 mutex_lock(&data
->lock
);
119 if (freq
> exynos5_int_opp_table
[0].clk
)
120 pm_qos_update_request(&data
->int_req
, freq
* 16 / 1000);
122 pm_qos_update_request(&data
->int_req
, -1);
125 err
= exynos5_int_setvolt(data
, volt
);
129 err
= clk_set_rate(data
->int_clk
, freq
* 1000);
135 err
= exynos5_int_setvolt(data
, volt
);
139 data
->curr_freq
= freq
;
141 mutex_unlock(&data
->lock
);
145 static int exynos5_int_get_dev_status(struct device
*dev
,
146 struct devfreq_dev_status
*stat
)
148 struct platform_device
*pdev
= container_of(dev
, struct platform_device
,
150 struct busfreq_data_int
*data
= platform_get_drvdata(pdev
);
151 struct busfreq_ppmu_data
*ppmu_data
= &data
->ppmu_data
;
154 exynos_read_ppmu(ppmu_data
);
155 busier_dmc
= exynos_get_busier_ppmu(ppmu_data
);
157 stat
->current_frequency
= data
->curr_freq
;
159 /* Number of cycles spent on memory access */
160 stat
->busy_time
= ppmu_data
->ppmu
[busier_dmc
].count
[PPMU_PMNCNT3
];
161 stat
->busy_time
*= 100 / INT_BUS_SATURATION_RATIO
;
162 stat
->total_time
= ppmu_data
->ppmu
[busier_dmc
].ccnt
;
167 static struct devfreq_dev_profile exynos5_devfreq_int_profile
= {
168 .initial_freq
= 160000,
170 .target
= exynos5_busfreq_int_target
,
171 .get_dev_status
= exynos5_int_get_dev_status
,
174 static int exynos5250_init_int_tables(struct busfreq_data_int
*data
)
178 for (i
= LV_0
; i
< _LV_END
; i
++) {
179 err
= dev_pm_opp_add(data
->dev
, exynos5_int_opp_table
[i
].clk
,
180 exynos5_int_opp_table
[i
].volt
);
182 dev_err(data
->dev
, "Cannot add opp entries.\n");
190 static int exynos5_busfreq_int_pm_notifier_event(struct notifier_block
*this,
191 unsigned long event
, void *ptr
)
193 struct busfreq_data_int
*data
= container_of(this,
194 struct busfreq_data_int
, pm_notifier
);
195 struct dev_pm_opp
*opp
;
196 unsigned long maxfreq
= ULONG_MAX
;
202 case PM_SUSPEND_PREPARE
:
203 /* Set Fastest and Deactivate DVFS */
204 mutex_lock(&data
->lock
);
206 data
->disabled
= true;
209 opp
= dev_pm_opp_find_freq_floor(data
->dev
, &maxfreq
);
215 freq
= dev_pm_opp_get_freq(opp
);
216 volt
= dev_pm_opp_get_voltage(opp
);
219 err
= exynos5_int_setvolt(data
, volt
);
223 err
= clk_set_rate(data
->int_clk
, freq
* 1000);
228 data
->curr_freq
= freq
;
230 mutex_unlock(&data
->lock
);
234 case PM_POST_RESTORE
:
235 case PM_POST_SUSPEND
:
237 mutex_lock(&data
->lock
);
238 data
->disabled
= false;
239 mutex_unlock(&data
->lock
);
246 static int exynos5_busfreq_int_probe(struct platform_device
*pdev
)
248 struct busfreq_data_int
*data
;
249 struct busfreq_ppmu_data
*ppmu_data
;
250 struct dev_pm_opp
*opp
;
251 struct device
*dev
= &pdev
->dev
;
252 struct device_node
*np
;
253 unsigned long initial_freq
;
254 unsigned long initial_volt
;
258 data
= devm_kzalloc(&pdev
->dev
, sizeof(struct busfreq_data_int
),
261 dev_err(dev
, "Cannot allocate memory.\n");
265 ppmu_data
= &data
->ppmu_data
;
266 ppmu_data
->ppmu_end
= PPMU_END
;
267 ppmu_data
->ppmu
= devm_kzalloc(dev
,
268 sizeof(struct exynos_ppmu
) * PPMU_END
,
270 if (!ppmu_data
->ppmu
) {
271 dev_err(dev
, "Failed to allocate memory for exynos_ppmu\n");
275 np
= of_find_compatible_node(NULL
, NULL
, "samsung,exynos5250-ppmu");
277 pr_err("Unable to find PPMU node\n");
281 for (i
= 0; i
< ppmu_data
->ppmu_end
; i
++) {
282 /* map PPMU memory region */
283 ppmu_data
->ppmu
[i
].hw_base
= of_iomap(np
, i
);
284 if (ppmu_data
->ppmu
[i
].hw_base
== NULL
) {
285 dev_err(&pdev
->dev
, "failed to map memory region\n");
289 data
->pm_notifier
.notifier_call
= exynos5_busfreq_int_pm_notifier_event
;
291 mutex_init(&data
->lock
);
293 err
= exynos5250_init_int_tables(data
);
297 data
->vdd_int
= devm_regulator_get(dev
, "vdd_int");
298 if (IS_ERR(data
->vdd_int
)) {
299 dev_err(dev
, "Cannot get the regulator \"vdd_int\"\n");
300 return PTR_ERR(data
->vdd_int
);
303 data
->int_clk
= devm_clk_get(dev
, "int_clk");
304 if (IS_ERR(data
->int_clk
)) {
305 dev_err(dev
, "Cannot get clock \"int_clk\"\n");
306 return PTR_ERR(data
->int_clk
);
310 opp
= dev_pm_opp_find_freq_floor(dev
,
311 &exynos5_devfreq_int_profile
.initial_freq
);
314 dev_err(dev
, "Invalid initial frequency %lu kHz.\n",
315 exynos5_devfreq_int_profile
.initial_freq
);
318 initial_freq
= dev_pm_opp_get_freq(opp
);
319 initial_volt
= dev_pm_opp_get_voltage(opp
);
321 data
->curr_freq
= initial_freq
;
323 err
= clk_set_rate(data
->int_clk
, initial_freq
* 1000);
325 dev_err(dev
, "Failed to set initial frequency\n");
329 err
= exynos5_int_setvolt(data
, initial_volt
);
333 platform_set_drvdata(pdev
, data
);
335 busfreq_mon_reset(ppmu_data
);
337 data
->devfreq
= devm_devfreq_add_device(dev
, &exynos5_devfreq_int_profile
,
338 "simple_ondemand", NULL
);
339 if (IS_ERR(data
->devfreq
))
340 return PTR_ERR(data
->devfreq
);
342 err
= devm_devfreq_register_opp_notifier(dev
, data
->devfreq
);
344 dev_err(dev
, "Failed to register opp notifier\n");
348 err
= register_pm_notifier(&data
->pm_notifier
);
350 dev_err(dev
, "Failed to setup pm notifier\n");
354 /* TODO: Add a new QOS class for int/mif bus */
355 pm_qos_add_request(&data
->int_req
, PM_QOS_NETWORK_THROUGHPUT
, -1);
360 static int exynos5_busfreq_int_remove(struct platform_device
*pdev
)
362 struct busfreq_data_int
*data
= platform_get_drvdata(pdev
);
364 pm_qos_remove_request(&data
->int_req
);
365 unregister_pm_notifier(&data
->pm_notifier
);
370 #ifdef CONFIG_PM_SLEEP
371 static int exynos5_busfreq_int_resume(struct device
*dev
)
373 struct platform_device
*pdev
= container_of(dev
, struct platform_device
,
375 struct busfreq_data_int
*data
= platform_get_drvdata(pdev
);
376 struct busfreq_ppmu_data
*ppmu_data
= &data
->ppmu_data
;
378 busfreq_mon_reset(ppmu_data
);
381 static const struct dev_pm_ops exynos5_busfreq_int_pm
= {
382 .resume
= exynos5_busfreq_int_resume
,
385 static SIMPLE_DEV_PM_OPS(exynos5_busfreq_int_pm_ops
, NULL
,
386 exynos5_busfreq_int_resume
);
388 /* platform device pointer for exynos5 devfreq device. */
389 static struct platform_device
*exynos5_devfreq_pdev
;
391 static struct platform_driver exynos5_busfreq_int_driver
= {
392 .probe
= exynos5_busfreq_int_probe
,
393 .remove
= exynos5_busfreq_int_remove
,
395 .name
= "exynos5-bus-int",
396 .pm
= &exynos5_busfreq_int_pm_ops
,
400 static int __init
exynos5_busfreq_int_init(void)
404 ret
= platform_driver_register(&exynos5_busfreq_int_driver
);
408 exynos5_devfreq_pdev
=
409 platform_device_register_simple("exynos5-bus-int", -1, NULL
, 0);
410 if (IS_ERR(exynos5_devfreq_pdev
)) {
411 ret
= PTR_ERR(exynos5_devfreq_pdev
);
417 platform_driver_unregister(&exynos5_busfreq_int_driver
);
421 late_initcall(exynos5_busfreq_int_init
);
423 static void __exit
exynos5_busfreq_int_exit(void)
425 platform_device_unregister(exynos5_devfreq_pdev
);
426 platform_driver_unregister(&exynos5_busfreq_int_driver
);
428 module_exit(exynos5_busfreq_int_exit
);
430 MODULE_LICENSE("GPL");
431 MODULE_DESCRIPTION("EXYNOS5 busfreq driver with devfreq framework");