@@ -10,15 +10,21 @@
#include <linux/cpumask.h>
#include <linux/module.h>
#include <linux/of.h>
+#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/pm_opp.h>
#include <linux/regulator/consumer.h>
-#define MIN_VOLT_SHIFT (100000)
-#define MAX_VOLT_SHIFT (200000)
-#define MAX_VOLT_LIMIT (1150000)
#define VOLT_TOL (10000)
+struct mtk_cpufreq_platform_data {
+ int min_volt_shift;
+ int max_volt_shift;
+ int proc_max_volt;
+ int sram_min_volt;
+ int sram_max_volt;
+};
+
/*
* The struct mtk_cpu_dvfs_info holds necessary information for doing CPU DVFS
* on each CPU power/clock domain of Mediatek SoCs. Each CPU cluster in
@@ -41,6 +47,7 @@ struct mtk_cpu_dvfs_info {
int intermediate_voltage;
bool need_voltage_tracking;
int pre_vproc;
+ const struct mtk_cpufreq_platform_data *soc_data;
};
static struct platform_device *cpufreq_pdev;
@@ -62,6 +69,7 @@ static struct mtk_cpu_dvfs_info *mtk_cpu_dvfs_info_lookup(int cpu)
static int mtk_cpufreq_voltage_tracking(struct mtk_cpu_dvfs_info *info,
int new_vproc)
{
+ const struct mtk_cpufreq_platform_data *soc_data = info->soc_data;
struct regulator *proc_reg = info->proc_reg;
struct regulator *sram_reg = info->sram_reg;
int pre_vproc, pre_vsram, new_vsram, vsram, vproc, ret;
@@ -73,7 +81,8 @@ static int mtk_cpufreq_voltage_tracking(struct mtk_cpu_dvfs_info *info,
return pre_vproc;
}
/* Vsram should not exceed the maximum allowed voltage of SoC. */
- new_vsram = min(new_vproc + MIN_VOLT_SHIFT, MAX_VOLT_LIMIT);
+ new_vsram = min(new_vproc + soc_data->min_volt_shift,
+ soc_data->sram_max_volt);
if (pre_vproc < new_vproc) {
/*
@@ -96,10 +105,11 @@ static int mtk_cpufreq_voltage_tracking(struct mtk_cpu_dvfs_info *info,
return pre_vproc;
}
- vsram = min(new_vsram, pre_vproc + MAX_VOLT_SHIFT);
+ vsram = min(new_vsram,
+ pre_vproc + soc_data->min_volt_shift);
- if (vsram + VOLT_TOL >= MAX_VOLT_LIMIT) {
- vsram = MAX_VOLT_LIMIT;
+ if (vsram + VOLT_TOL >= soc_data->sram_max_volt) {
+ vsram = soc_data->sram_max_volt;
/*
* If the target Vsram hits the maximum voltage,
@@ -117,7 +127,7 @@ static int mtk_cpufreq_voltage_tracking(struct mtk_cpu_dvfs_info *info,
ret = regulator_set_voltage(sram_reg, vsram,
vsram + VOLT_TOL);
- vproc = vsram - MIN_VOLT_SHIFT;
+ vproc = vsram - soc_data->min_volt_shift;
}
if (ret)
return ret;
@@ -151,7 +161,8 @@ static int mtk_cpufreq_voltage_tracking(struct mtk_cpu_dvfs_info *info,
return pre_vsram;
}
- vproc = max(new_vproc, pre_vsram - MAX_VOLT_SHIFT);
+ vproc = max(new_vproc,
+ pre_vsram - soc_data->max_volt_shift);
ret = regulator_set_voltage(proc_reg, vproc,
vproc + VOLT_TOL);
if (ret)
@@ -160,10 +171,11 @@ static int mtk_cpufreq_voltage_tracking(struct mtk_cpu_dvfs_info *info,
if (vproc == new_vproc)
vsram = new_vsram;
else
- vsram = max(new_vsram, vproc + MIN_VOLT_SHIFT);
+ vsram = max(new_vsram,
+ vproc + soc_data->min_volt_shift);
- if (vsram + VOLT_TOL >= MAX_VOLT_LIMIT) {
- vsram = MAX_VOLT_LIMIT;
+ if (vsram + VOLT_TOL >= soc_data->sram_max_volt) {
+ vsram = soc_data->sram_max_volt;
/*
* If the target Vsram hits the maximum voltage,
@@ -194,13 +206,14 @@ static int mtk_cpufreq_voltage_tracking(struct mtk_cpu_dvfs_info *info,
static int mtk_cpufreq_set_voltage(struct mtk_cpu_dvfs_info *info, int vproc)
{
+ const struct mtk_cpufreq_platform_data *soc_data = info->soc_data;
int ret;
if (info->need_voltage_tracking)
ret = mtk_cpufreq_voltage_tracking(info, vproc);
else
ret = regulator_set_voltage(info->proc_reg, vproc,
- MAX_VOLT_LIMIT);
+ soc_data->proc_max_volt);
if (!ret)
info->pre_vproc = vproc;
@@ -509,9 +522,17 @@ static struct cpufreq_driver mtk_cpufreq_driver = {
static int mtk_cpufreq_probe(struct platform_device *pdev)
{
+ const struct mtk_cpufreq_platform_data *data;
struct mtk_cpu_dvfs_info *info, *tmp;
int cpu, ret;
+ data = dev_get_platdata(&pdev->dev);
+ if (!data) {
+ dev_err(&pdev->dev,
+ "failed to get mtk cpufreq platform data\n");
+ return -ENODEV;
+ }
+
for_each_possible_cpu(cpu) {
info = mtk_cpu_dvfs_info_lookup(cpu);
if (info)
@@ -523,6 +544,7 @@ static int mtk_cpufreq_probe(struct platform_device *pdev)
goto release_dvfs_info_list;
}
+ info->soc_data = data;
ret = mtk_cpu_dvfs_info_init(info, cpu);
if (ret) {
dev_err(&pdev->dev,
@@ -558,20 +580,27 @@ static struct platform_driver mtk_cpufreq_platdrv = {
.probe = mtk_cpufreq_probe,
};
+static const struct mtk_cpufreq_platform_data mt2701_platform_data = {
+ .min_volt_shift = 100000,
+ .max_volt_shift = 200000,
+ .proc_max_volt = 1150000,
+ .sram_min_volt = 0,
+ .sram_max_volt = 1150000,
+};
+
/* List of machines supported by this driver */
static const struct of_device_id mtk_cpufreq_machines[] __initconst = {
- { .compatible = "mediatek,mt2701", },
- { .compatible = "mediatek,mt2712", },
- { .compatible = "mediatek,mt7622", },
- { .compatible = "mediatek,mt7623", },
- { .compatible = "mediatek,mt8167", },
- { .compatible = "mediatek,mt817x", },
- { .compatible = "mediatek,mt8173", },
- { .compatible = "mediatek,mt8176", },
- { .compatible = "mediatek,mt8183", },
- { .compatible = "mediatek,mt8365", },
- { .compatible = "mediatek,mt8516", },
-
+ { .compatible = "mediatek,mt2701", .data = &mt2701_platform_data },
+ { .compatible = "mediatek,mt2712", .data = &mt2701_platform_data },
+ { .compatible = "mediatek,mt7622", .data = &mt2701_platform_data },
+ { .compatible = "mediatek,mt7623", .data = &mt2701_platform_data },
+ { .compatible = "mediatek,mt8167", .data = &mt2701_platform_data },
+ { .compatible = "mediatek,mt817x", .data = &mt2701_platform_data },
+ { .compatible = "mediatek,mt8173", .data = &mt2701_platform_data },
+ { .compatible = "mediatek,mt8176", .data = &mt2701_platform_data },
+ { .compatible = "mediatek,mt8183", .data = &mt2701_platform_data },
+ { .compatible = "mediatek,mt8365", .data = &mt2701_platform_data },
+ { .compatible = "mediatek,mt8516", .data = &mt2701_platform_data },
{ }
};
MODULE_DEVICE_TABLE(of, mtk_cpufreq_machines);
@@ -580,6 +609,7 @@ static int __init mtk_cpufreq_driver_init(void)
{
struct device_node *np;
const struct of_device_id *match;
+ const struct mtk_cpufreq_platform_data *data;
int err;
np = of_find_node_by_path("/");
@@ -592,6 +622,7 @@ static int __init mtk_cpufreq_driver_init(void)
pr_debug("Machine is not compatible with mtk-cpufreq\n");
return -ENODEV;
}
+ data = match->data;
err = platform_driver_register(&mtk_cpufreq_platdrv);
if (err)
@@ -603,7 +634,8 @@ static int __init mtk_cpufreq_driver_init(void)
* and the device registration codes are put here to handle defer
* probing.
*/
- cpufreq_pdev = platform_device_register_simple("mtk-cpufreq", -1, NULL, 0);
+ cpufreq_pdev = platform_device_register_data(NULL, "mtk-cpufreq", -1,
+ data, sizeof(*data));
if (IS_ERR(cpufreq_pdev)) {
pr_err("failed to register mtk-cpufreq platform device\n");
platform_driver_unregister(&mtk_cpufreq_platdrv);