aboutsummaryrefslogtreecommitdiff
path: root/drivers/devfreq/exynos/exynos5_bus.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/devfreq/exynos/exynos5_bus.c')
-rw-r--r--drivers/devfreq/exynos/exynos5_bus.c189
1 files changed, 59 insertions, 130 deletions
diff --git a/drivers/devfreq/exynos/exynos5_bus.c b/drivers/devfreq/exynos/exynos5_bus.c
index 574b16b59be..6cd0392e279 100644
--- a/drivers/devfreq/exynos/exynos5_bus.c
+++ b/drivers/devfreq/exynos/exynos5_bus.c
@@ -15,10 +15,9 @@
#include <linux/module.h>
#include <linux/devfreq.h>
#include <linux/io.h>
-#include <linux/opp.h>
+#include <linux/pm_opp.h>
#include <linux/slab.h>
#include <linux/suspend.h>
-#include <linux/opp.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
@@ -51,7 +50,7 @@ struct busfreq_data_int {
struct device *dev;
struct devfreq *devfreq;
struct regulator *vdd_int;
- struct exynos_ppmu ppmu[PPMU_END];
+ struct busfreq_ppmu_data ppmu_data;
unsigned long curr_freq;
bool disabled;
@@ -76,49 +75,6 @@ static struct int_bus_opp_table exynos5_int_opp_table[] = {
{0, 0, 0},
};
-static void busfreq_mon_reset(struct busfreq_data_int *data)
-{
- unsigned int i;
-
- for (i = PPMU_RIGHT; i < PPMU_END; i++) {
- void __iomem *ppmu_base = data->ppmu[i].hw_base;
-
- /* Reset the performance and cycle counters */
- exynos_ppmu_reset(ppmu_base);
-
- /* Setup count registers to monitor read/write transactions */
- data->ppmu[i].event[PPMU_PMNCNT3] = RDWR_DATA_COUNT;
- exynos_ppmu_setevent(ppmu_base, PPMU_PMNCNT3,
- data->ppmu[i].event[PPMU_PMNCNT3]);
-
- exynos_ppmu_start(ppmu_base);
- }
-}
-
-static void exynos5_read_ppmu(struct busfreq_data_int *data)
-{
- int i, j;
-
- for (i = PPMU_RIGHT; i < PPMU_END; i++) {
- void __iomem *ppmu_base = data->ppmu[i].hw_base;
-
- exynos_ppmu_stop(ppmu_base);
-
- /* Update local data from PPMU */
- data->ppmu[i].ccnt = __raw_readl(ppmu_base + PPMU_CCNT);
-
- for (j = PPMU_PMNCNT0; j < PPMU_PMNCNT_MAX; j++) {
- if (data->ppmu[i].event[j] == 0)
- data->ppmu[i].count[j] = 0;
- else
- data->ppmu[i].count[j] =
- exynos_ppmu_read(ppmu_base, j);
- }
- }
-
- busfreq_mon_reset(data);
-}
-
static int exynos5_int_setvolt(struct busfreq_data_int *data,
unsigned long volt)
{
@@ -132,7 +88,7 @@ static int exynos5_busfreq_int_target(struct device *dev, unsigned long *_freq,
struct platform_device *pdev = container_of(dev, struct platform_device,
dev);
struct busfreq_data_int *data = platform_get_drvdata(pdev);
- struct opp *opp;
+ struct dev_pm_opp *opp;
unsigned long old_freq, freq;
unsigned long volt;
@@ -144,8 +100,8 @@ static int exynos5_busfreq_int_target(struct device *dev, unsigned long *_freq,
return PTR_ERR(opp);
}
- freq = opp_get_freq(opp);
- volt = opp_get_voltage(opp);
+ freq = dev_pm_opp_get_freq(opp);
+ volt = dev_pm_opp_get_voltage(opp);
rcu_read_unlock();
old_freq = data->curr_freq;
@@ -153,7 +109,7 @@ static int exynos5_busfreq_int_target(struct device *dev, unsigned long *_freq,
if (old_freq == freq)
return 0;
- dev_dbg(dev, "targetting %lukHz %luuV\n", freq, volt);
+ dev_dbg(dev, "targeting %lukHz %luuV\n", freq, volt);
mutex_lock(&data->lock);
@@ -186,59 +142,33 @@ out:
return err;
}
-static int exynos5_get_busier_dmc(struct busfreq_data_int *data)
-{
- int i, j;
- int busy = 0;
- unsigned int temp = 0;
-
- for (i = PPMU_RIGHT; i < PPMU_END; i++) {
- for (j = PPMU_PMNCNT0; j < PPMU_PMNCNT_MAX; j++) {
- if (data->ppmu[i].count[j] > temp) {
- temp = data->ppmu[i].count[j];
- busy = i;
- }
- }
- }
-
- return busy;
-}
-
static int exynos5_int_get_dev_status(struct device *dev,
struct devfreq_dev_status *stat)
{
struct platform_device *pdev = container_of(dev, struct platform_device,
dev);
struct busfreq_data_int *data = platform_get_drvdata(pdev);
+ struct busfreq_ppmu_data *ppmu_data = &data->ppmu_data;
int busier_dmc;
- exynos5_read_ppmu(data);
- busier_dmc = exynos5_get_busier_dmc(data);
+ exynos_read_ppmu(ppmu_data);
+ busier_dmc = exynos_get_busier_ppmu(ppmu_data);
stat->current_frequency = data->curr_freq;
/* Number of cycles spent on memory access */
- stat->busy_time = data->ppmu[busier_dmc].count[PPMU_PMNCNT3];
+ stat->busy_time = ppmu_data->ppmu[busier_dmc].count[PPMU_PMNCNT3];
stat->busy_time *= 100 / INT_BUS_SATURATION_RATIO;
- stat->total_time = data->ppmu[busier_dmc].ccnt;
+ stat->total_time = ppmu_data->ppmu[busier_dmc].ccnt;
return 0;
}
-static void exynos5_int_exit(struct device *dev)
-{
- struct platform_device *pdev = container_of(dev, struct platform_device,
- dev);
- struct busfreq_data_int *data = platform_get_drvdata(pdev);
-
- devfreq_unregister_opp_notifier(dev, data->devfreq);
-}
static struct devfreq_dev_profile exynos5_devfreq_int_profile = {
.initial_freq = 160000,
.polling_ms = 100,
.target = exynos5_busfreq_int_target,
.get_dev_status = exynos5_int_get_dev_status,
- .exit = exynos5_int_exit,
};
static int exynos5250_init_int_tables(struct busfreq_data_int *data)
@@ -246,7 +176,7 @@ static int exynos5250_init_int_tables(struct busfreq_data_int *data)
int i, err = 0;
for (i = LV_0; i < _LV_END; i++) {
- err = opp_add(data->dev, exynos5_int_opp_table[i].clk,
+ err = dev_pm_opp_add(data->dev, exynos5_int_opp_table[i].clk,
exynos5_int_opp_table[i].volt);
if (err) {
dev_err(data->dev, "Cannot add opp entries.\n");
@@ -262,7 +192,7 @@ static int exynos5_busfreq_int_pm_notifier_event(struct notifier_block *this,
{
struct busfreq_data_int *data = container_of(this,
struct busfreq_data_int, pm_notifier);
- struct opp *opp;
+ struct dev_pm_opp *opp;
unsigned long maxfreq = ULONG_MAX;
unsigned long freq;
unsigned long volt;
@@ -276,14 +206,14 @@ static int exynos5_busfreq_int_pm_notifier_event(struct notifier_block *this,
data->disabled = true;
rcu_read_lock();
- opp = opp_find_freq_floor(data->dev, &maxfreq);
+ opp = dev_pm_opp_find_freq_floor(data->dev, &maxfreq);
if (IS_ERR(opp)) {
rcu_read_unlock();
err = PTR_ERR(opp);
goto unlock;
}
- freq = opp_get_freq(opp);
- volt = opp_get_voltage(opp);
+ freq = dev_pm_opp_get_freq(opp);
+ volt = dev_pm_opp_get_voltage(opp);
rcu_read_unlock();
err = exynos5_int_setvolt(data, volt);
@@ -316,7 +246,8 @@ unlock:
static int exynos5_busfreq_int_probe(struct platform_device *pdev)
{
struct busfreq_data_int *data;
- struct opp *opp;
+ struct busfreq_ppmu_data *ppmu_data;
+ struct dev_pm_opp *opp;
struct device *dev = &pdev->dev;
struct device_node *np;
unsigned long initial_freq;
@@ -331,16 +262,26 @@ static int exynos5_busfreq_int_probe(struct platform_device *pdev)
return -ENOMEM;
}
+ ppmu_data = &data->ppmu_data;
+ ppmu_data->ppmu_end = PPMU_END;
+ ppmu_data->ppmu = devm_kzalloc(dev,
+ sizeof(struct exynos_ppmu) * PPMU_END,
+ GFP_KERNEL);
+ if (!ppmu_data->ppmu) {
+ dev_err(dev, "Failed to allocate memory for exynos_ppmu\n");
+ return -ENOMEM;
+ }
+
np = of_find_compatible_node(NULL, NULL, "samsung,exynos5250-ppmu");
if (np == NULL) {
pr_err("Unable to find PPMU node\n");
return -ENOENT;
}
- for (i = PPMU_RIGHT; i < PPMU_END; i++) {
+ for (i = 0; i < ppmu_data->ppmu_end; i++) {
/* map PPMU memory region */
- data->ppmu[i].hw_base = of_iomap(np, i);
- if (data->ppmu[i].hw_base == NULL) {
+ ppmu_data->ppmu[i].hw_base = of_iomap(np, i);
+ if (ppmu_data->ppmu[i].hw_base == NULL) {
dev_err(&pdev->dev, "failed to map memory region\n");
return -ENOMEM;
}
@@ -351,81 +292,69 @@ static int exynos5_busfreq_int_probe(struct platform_device *pdev)
err = exynos5250_init_int_tables(data);
if (err)
- goto err_regulator;
+ return err;
- data->vdd_int = regulator_get(dev, "vdd_int");
+ data->vdd_int = devm_regulator_get(dev, "vdd_int");
if (IS_ERR(data->vdd_int)) {
dev_err(dev, "Cannot get the regulator \"vdd_int\"\n");
- err = PTR_ERR(data->vdd_int);
- goto err_regulator;
+ return PTR_ERR(data->vdd_int);
}
- data->int_clk = clk_get(dev, "int_clk");
+ data->int_clk = devm_clk_get(dev, "int_clk");
if (IS_ERR(data->int_clk)) {
dev_err(dev, "Cannot get clock \"int_clk\"\n");
- err = PTR_ERR(data->int_clk);
- goto err_clock;
+ return PTR_ERR(data->int_clk);
}
rcu_read_lock();
- opp = opp_find_freq_floor(dev,
+ opp = dev_pm_opp_find_freq_floor(dev,
&exynos5_devfreq_int_profile.initial_freq);
if (IS_ERR(opp)) {
rcu_read_unlock();
dev_err(dev, "Invalid initial frequency %lu kHz.\n",
exynos5_devfreq_int_profile.initial_freq);
- err = PTR_ERR(opp);
- goto err_opp_add;
+ return PTR_ERR(opp);
}
- initial_freq = opp_get_freq(opp);
- initial_volt = opp_get_voltage(opp);
+ initial_freq = dev_pm_opp_get_freq(opp);
+ initial_volt = dev_pm_opp_get_voltage(opp);
rcu_read_unlock();
data->curr_freq = initial_freq;
err = clk_set_rate(data->int_clk, initial_freq * 1000);
if (err) {
dev_err(dev, "Failed to set initial frequency\n");
- goto err_opp_add;
+ return err;
}
err = exynos5_int_setvolt(data, initial_volt);
if (err)
- goto err_opp_add;
+ return err;
platform_set_drvdata(pdev, data);
- busfreq_mon_reset(data);
+ busfreq_mon_reset(ppmu_data);
- data->devfreq = devfreq_add_device(dev, &exynos5_devfreq_int_profile,
+ data->devfreq = devm_devfreq_add_device(dev, &exynos5_devfreq_int_profile,
"simple_ondemand", NULL);
+ if (IS_ERR(data->devfreq))
+ return PTR_ERR(data->devfreq);
- if (IS_ERR(data->devfreq)) {
- err = PTR_ERR(data->devfreq);
- goto err_devfreq_add;
+ err = devm_devfreq_register_opp_notifier(dev, data->devfreq);
+ if (err < 0) {
+ dev_err(dev, "Failed to register opp notifier\n");
+ return err;
}
- devfreq_register_opp_notifier(dev, data->devfreq);
-
err = register_pm_notifier(&data->pm_notifier);
if (err) {
dev_err(dev, "Failed to setup pm notifier\n");
- goto err_devfreq_add;
+ return err;
}
/* TODO: Add a new QOS class for int/mif bus */
pm_qos_add_request(&data->int_req, PM_QOS_NETWORK_THROUGHPUT, -1);
return 0;
-
-err_devfreq_add:
- devfreq_remove_device(data->devfreq);
- platform_set_drvdata(pdev, NULL);
-err_opp_add:
- clk_put(data->int_clk);
-err_clock:
- regulator_put(data->vdd_int);
-err_regulator:
- return err;
}
static int exynos5_busfreq_int_remove(struct platform_device *pdev)
@@ -434,27 +363,27 @@ static int exynos5_busfreq_int_remove(struct platform_device *pdev)
pm_qos_remove_request(&data->int_req);
unregister_pm_notifier(&data->pm_notifier);
- devfreq_remove_device(data->devfreq);
- regulator_put(data->vdd_int);
- clk_put(data->int_clk);
- platform_set_drvdata(pdev, NULL);
return 0;
}
+#ifdef CONFIG_PM_SLEEP
static int exynos5_busfreq_int_resume(struct device *dev)
{
struct platform_device *pdev = container_of(dev, struct platform_device,
dev);
struct busfreq_data_int *data = platform_get_drvdata(pdev);
+ struct busfreq_ppmu_data *ppmu_data = &data->ppmu_data;
- busfreq_mon_reset(data);
+ busfreq_mon_reset(ppmu_data);
return 0;
}
-
static const struct dev_pm_ops exynos5_busfreq_int_pm = {
.resume = exynos5_busfreq_int_resume,
};
+#endif
+static SIMPLE_DEV_PM_OPS(exynos5_busfreq_int_pm_ops, NULL,
+ exynos5_busfreq_int_resume);
/* platform device pointer for exynos5 devfreq device. */
static struct platform_device *exynos5_devfreq_pdev;
@@ -465,7 +394,7 @@ static struct platform_driver exynos5_busfreq_int_driver = {
.driver = {
.name = "exynos5-bus-int",
.owner = THIS_MODULE,
- .pm = &exynos5_busfreq_int_pm,
+ .pm = &exynos5_busfreq_int_pm_ops,
},
};
@@ -479,7 +408,7 @@ static int __init exynos5_busfreq_int_init(void)
exynos5_devfreq_pdev =
platform_device_register_simple("exynos5-bus-int", -1, NULL, 0);
- if (IS_ERR_OR_NULL(exynos5_devfreq_pdev)) {
+ if (IS_ERR(exynos5_devfreq_pdev)) {
ret = PTR_ERR(exynos5_devfreq_pdev);
goto out1;
}