0001
0002
0003
0004
0005
0006
0007 #include <linux/clk.h>
0008 #include <linux/cpu.h>
0009 #include <linux/cpufreq.h>
0010 #include <linux/cpumask.h>
0011 #include <linux/minmax.h>
0012 #include <linux/module.h>
0013 #include <linux/of.h>
0014 #include <linux/of_platform.h>
0015 #include <linux/platform_device.h>
0016 #include <linux/pm_opp.h>
0017 #include <linux/regulator/consumer.h>
0018
0019 struct mtk_cpufreq_platform_data {
0020 int min_volt_shift;
0021 int max_volt_shift;
0022 int proc_max_volt;
0023 int sram_min_volt;
0024 int sram_max_volt;
0025 bool ccifreq_supported;
0026 };
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039 struct mtk_cpu_dvfs_info {
0040 struct cpumask cpus;
0041 struct device *cpu_dev;
0042 struct device *cci_dev;
0043 struct regulator *proc_reg;
0044 struct regulator *sram_reg;
0045 struct clk *cpu_clk;
0046 struct clk *inter_clk;
0047 struct list_head list_head;
0048 int intermediate_voltage;
0049 bool need_voltage_tracking;
0050 int vproc_on_boot;
0051 int pre_vproc;
0052
0053 struct mutex reg_lock;
0054 struct notifier_block opp_nb;
0055 unsigned int opp_cpu;
0056 unsigned long current_freq;
0057 const struct mtk_cpufreq_platform_data *soc_data;
0058 int vtrack_max;
0059 bool ccifreq_bound;
0060 };
0061
0062 static struct platform_device *cpufreq_pdev;
0063
0064 static LIST_HEAD(dvfs_info_list);
0065
0066 static struct mtk_cpu_dvfs_info *mtk_cpu_dvfs_info_lookup(int cpu)
0067 {
0068 struct mtk_cpu_dvfs_info *info;
0069
0070 list_for_each_entry(info, &dvfs_info_list, list_head) {
0071 if (cpumask_test_cpu(cpu, &info->cpus))
0072 return info;
0073 }
0074
0075 return NULL;
0076 }
0077
0078 static int mtk_cpufreq_voltage_tracking(struct mtk_cpu_dvfs_info *info,
0079 int new_vproc)
0080 {
0081 const struct mtk_cpufreq_platform_data *soc_data = info->soc_data;
0082 struct regulator *proc_reg = info->proc_reg;
0083 struct regulator *sram_reg = info->sram_reg;
0084 int pre_vproc, pre_vsram, new_vsram, vsram, vproc, ret;
0085 int retry = info->vtrack_max;
0086
0087 pre_vproc = regulator_get_voltage(proc_reg);
0088 if (pre_vproc < 0) {
0089 dev_err(info->cpu_dev,
0090 "invalid Vproc value: %d\n", pre_vproc);
0091 return pre_vproc;
0092 }
0093
0094 pre_vsram = regulator_get_voltage(sram_reg);
0095 if (pre_vsram < 0) {
0096 dev_err(info->cpu_dev, "invalid Vsram value: %d\n", pre_vsram);
0097 return pre_vsram;
0098 }
0099
0100 new_vsram = clamp(new_vproc + soc_data->min_volt_shift,
0101 soc_data->sram_min_volt, soc_data->sram_max_volt);
0102
0103 do {
0104 if (pre_vproc <= new_vproc) {
0105 vsram = clamp(pre_vproc + soc_data->max_volt_shift,
0106 soc_data->sram_min_volt, new_vsram);
0107 ret = regulator_set_voltage(sram_reg, vsram,
0108 soc_data->sram_max_volt);
0109
0110 if (ret)
0111 return ret;
0112
0113 if (vsram == soc_data->sram_max_volt ||
0114 new_vsram == soc_data->sram_min_volt)
0115 vproc = new_vproc;
0116 else
0117 vproc = vsram - soc_data->min_volt_shift;
0118
0119 ret = regulator_set_voltage(proc_reg, vproc,
0120 soc_data->proc_max_volt);
0121 if (ret) {
0122 regulator_set_voltage(sram_reg, pre_vsram,
0123 soc_data->sram_max_volt);
0124 return ret;
0125 }
0126 } else if (pre_vproc > new_vproc) {
0127 vproc = max(new_vproc,
0128 pre_vsram - soc_data->max_volt_shift);
0129 ret = regulator_set_voltage(proc_reg, vproc,
0130 soc_data->proc_max_volt);
0131 if (ret)
0132 return ret;
0133
0134 if (vproc == new_vproc)
0135 vsram = new_vsram;
0136 else
0137 vsram = max(new_vsram,
0138 vproc + soc_data->min_volt_shift);
0139
0140 ret = regulator_set_voltage(sram_reg, vsram,
0141 soc_data->sram_max_volt);
0142 if (ret) {
0143 regulator_set_voltage(proc_reg, pre_vproc,
0144 soc_data->proc_max_volt);
0145 return ret;
0146 }
0147 }
0148
0149 pre_vproc = vproc;
0150 pre_vsram = vsram;
0151
0152 if (--retry < 0) {
0153 dev_err(info->cpu_dev,
0154 "over loop count, failed to set voltage\n");
0155 return -EINVAL;
0156 }
0157 } while (vproc != new_vproc || vsram != new_vsram);
0158
0159 return 0;
0160 }
0161
0162 static int mtk_cpufreq_set_voltage(struct mtk_cpu_dvfs_info *info, int vproc)
0163 {
0164 const struct mtk_cpufreq_platform_data *soc_data = info->soc_data;
0165 int ret;
0166
0167 if (info->need_voltage_tracking)
0168 ret = mtk_cpufreq_voltage_tracking(info, vproc);
0169 else
0170 ret = regulator_set_voltage(info->proc_reg, vproc,
0171 soc_data->proc_max_volt);
0172 if (!ret)
0173 info->pre_vproc = vproc;
0174
0175 return ret;
0176 }
0177
0178 static bool is_ccifreq_ready(struct mtk_cpu_dvfs_info *info)
0179 {
0180 struct device_link *sup_link;
0181
0182 if (info->ccifreq_bound)
0183 return true;
0184
0185 sup_link = device_link_add(info->cpu_dev, info->cci_dev,
0186 DL_FLAG_AUTOREMOVE_CONSUMER);
0187 if (!sup_link) {
0188 dev_err(info->cpu_dev, "cpu%d: sup_link is NULL\n", info->opp_cpu);
0189 return false;
0190 }
0191
0192 if (sup_link->supplier->links.status != DL_DEV_DRIVER_BOUND)
0193 return false;
0194
0195 info->ccifreq_bound = true;
0196
0197 return true;
0198 }
0199
0200 static int mtk_cpufreq_set_target(struct cpufreq_policy *policy,
0201 unsigned int index)
0202 {
0203 struct cpufreq_frequency_table *freq_table = policy->freq_table;
0204 struct clk *cpu_clk = policy->clk;
0205 struct clk *armpll = clk_get_parent(cpu_clk);
0206 struct mtk_cpu_dvfs_info *info = policy->driver_data;
0207 struct device *cpu_dev = info->cpu_dev;
0208 struct dev_pm_opp *opp;
0209 long freq_hz, pre_freq_hz;
0210 int vproc, pre_vproc, inter_vproc, target_vproc, ret;
0211
0212 inter_vproc = info->intermediate_voltage;
0213
0214 pre_freq_hz = clk_get_rate(cpu_clk);
0215
0216 mutex_lock(&info->reg_lock);
0217
0218 if (unlikely(info->pre_vproc <= 0))
0219 pre_vproc = regulator_get_voltage(info->proc_reg);
0220 else
0221 pre_vproc = info->pre_vproc;
0222
0223 if (pre_vproc < 0) {
0224 dev_err(cpu_dev, "invalid Vproc value: %d\n", pre_vproc);
0225 ret = pre_vproc;
0226 goto out;
0227 }
0228
0229 freq_hz = freq_table[index].frequency * 1000;
0230
0231 opp = dev_pm_opp_find_freq_ceil(cpu_dev, &freq_hz);
0232 if (IS_ERR(opp)) {
0233 dev_err(cpu_dev, "cpu%d: failed to find OPP for %ld\n",
0234 policy->cpu, freq_hz);
0235 ret = PTR_ERR(opp);
0236 goto out;
0237 }
0238 vproc = dev_pm_opp_get_voltage(opp);
0239 dev_pm_opp_put(opp);
0240
0241
0242
0243
0244
0245
0246 if (info->soc_data->ccifreq_supported && !is_ccifreq_ready(info))
0247 vproc = max(vproc, info->vproc_on_boot);
0248
0249
0250
0251
0252
0253 target_vproc = max(inter_vproc, vproc);
0254 if (pre_vproc <= target_vproc) {
0255 ret = mtk_cpufreq_set_voltage(info, target_vproc);
0256 if (ret) {
0257 dev_err(cpu_dev,
0258 "cpu%d: failed to scale up voltage!\n", policy->cpu);
0259 mtk_cpufreq_set_voltage(info, pre_vproc);
0260 goto out;
0261 }
0262 }
0263
0264
0265 ret = clk_set_parent(cpu_clk, info->inter_clk);
0266 if (ret) {
0267 dev_err(cpu_dev,
0268 "cpu%d: failed to re-parent cpu clock!\n", policy->cpu);
0269 mtk_cpufreq_set_voltage(info, pre_vproc);
0270 goto out;
0271 }
0272
0273
0274 ret = clk_set_rate(armpll, freq_hz);
0275 if (ret) {
0276 dev_err(cpu_dev,
0277 "cpu%d: failed to scale cpu clock rate!\n", policy->cpu);
0278 clk_set_parent(cpu_clk, armpll);
0279 mtk_cpufreq_set_voltage(info, pre_vproc);
0280 goto out;
0281 }
0282
0283
0284 ret = clk_set_parent(cpu_clk, armpll);
0285 if (ret) {
0286 dev_err(cpu_dev,
0287 "cpu%d: failed to re-parent cpu clock!\n", policy->cpu);
0288 mtk_cpufreq_set_voltage(info, inter_vproc);
0289 goto out;
0290 }
0291
0292
0293
0294
0295
0296 if (vproc < inter_vproc || vproc < pre_vproc) {
0297 ret = mtk_cpufreq_set_voltage(info, vproc);
0298 if (ret) {
0299 dev_err(cpu_dev,
0300 "cpu%d: failed to scale down voltage!\n", policy->cpu);
0301 clk_set_parent(cpu_clk, info->inter_clk);
0302 clk_set_rate(armpll, pre_freq_hz);
0303 clk_set_parent(cpu_clk, armpll);
0304 goto out;
0305 }
0306 }
0307
0308 info->current_freq = freq_hz;
0309
0310 out:
0311 mutex_unlock(&info->reg_lock);
0312
0313 return ret;
0314 }
0315
0316 #define DYNAMIC_POWER "dynamic-power-coefficient"
0317
0318 static int mtk_cpufreq_opp_notifier(struct notifier_block *nb,
0319 unsigned long event, void *data)
0320 {
0321 struct dev_pm_opp *opp = data;
0322 struct dev_pm_opp *new_opp;
0323 struct mtk_cpu_dvfs_info *info;
0324 unsigned long freq, volt;
0325 struct cpufreq_policy *policy;
0326 int ret = 0;
0327
0328 info = container_of(nb, struct mtk_cpu_dvfs_info, opp_nb);
0329
0330 if (event == OPP_EVENT_ADJUST_VOLTAGE) {
0331 freq = dev_pm_opp_get_freq(opp);
0332
0333 mutex_lock(&info->reg_lock);
0334 if (info->current_freq == freq) {
0335 volt = dev_pm_opp_get_voltage(opp);
0336 ret = mtk_cpufreq_set_voltage(info, volt);
0337 if (ret)
0338 dev_err(info->cpu_dev,
0339 "failed to scale voltage: %d\n", ret);
0340 }
0341 mutex_unlock(&info->reg_lock);
0342 } else if (event == OPP_EVENT_DISABLE) {
0343 freq = dev_pm_opp_get_freq(opp);
0344
0345
0346 if (info->current_freq == freq) {
0347 freq = 1;
0348 new_opp = dev_pm_opp_find_freq_ceil(info->cpu_dev,
0349 &freq);
0350 if (IS_ERR(new_opp)) {
0351 dev_err(info->cpu_dev,
0352 "all opp items are disabled\n");
0353 ret = PTR_ERR(new_opp);
0354 return notifier_from_errno(ret);
0355 }
0356
0357 dev_pm_opp_put(new_opp);
0358 policy = cpufreq_cpu_get(info->opp_cpu);
0359 if (policy) {
0360 cpufreq_driver_target(policy, freq / 1000,
0361 CPUFREQ_RELATION_L);
0362 cpufreq_cpu_put(policy);
0363 }
0364 }
0365 }
0366
0367 return notifier_from_errno(ret);
0368 }
0369
0370 static struct device *of_get_cci(struct device *cpu_dev)
0371 {
0372 struct device_node *np;
0373 struct platform_device *pdev;
0374
0375 np = of_parse_phandle(cpu_dev->of_node, "mediatek,cci", 0);
0376 if (IS_ERR_OR_NULL(np))
0377 return NULL;
0378
0379 pdev = of_find_device_by_node(np);
0380 of_node_put(np);
0381 if (IS_ERR_OR_NULL(pdev))
0382 return NULL;
0383
0384 return &pdev->dev;
0385 }
0386
0387 static int mtk_cpu_dvfs_info_init(struct mtk_cpu_dvfs_info *info, int cpu)
0388 {
0389 struct device *cpu_dev;
0390 struct dev_pm_opp *opp;
0391 unsigned long rate;
0392 int ret;
0393
0394 cpu_dev = get_cpu_device(cpu);
0395 if (!cpu_dev) {
0396 dev_err(cpu_dev, "failed to get cpu%d device\n", cpu);
0397 return -ENODEV;
0398 }
0399 info->cpu_dev = cpu_dev;
0400
0401 info->ccifreq_bound = false;
0402 if (info->soc_data->ccifreq_supported) {
0403 info->cci_dev = of_get_cci(info->cpu_dev);
0404 if (IS_ERR_OR_NULL(info->cci_dev)) {
0405 ret = PTR_ERR(info->cci_dev);
0406 dev_err(cpu_dev, "cpu%d: failed to get cci device\n", cpu);
0407 return -ENODEV;
0408 }
0409 }
0410
0411 info->cpu_clk = clk_get(cpu_dev, "cpu");
0412 if (IS_ERR(info->cpu_clk)) {
0413 ret = PTR_ERR(info->cpu_clk);
0414 return dev_err_probe(cpu_dev, ret,
0415 "cpu%d: failed to get cpu clk\n", cpu);
0416 }
0417
0418 info->inter_clk = clk_get(cpu_dev, "intermediate");
0419 if (IS_ERR(info->inter_clk)) {
0420 ret = PTR_ERR(info->inter_clk);
0421 dev_err_probe(cpu_dev, ret,
0422 "cpu%d: failed to get intermediate clk\n", cpu);
0423 goto out_free_resources;
0424 }
0425
0426 info->proc_reg = regulator_get_optional(cpu_dev, "proc");
0427 if (IS_ERR(info->proc_reg)) {
0428 ret = PTR_ERR(info->proc_reg);
0429 dev_err_probe(cpu_dev, ret,
0430 "cpu%d: failed to get proc regulator\n", cpu);
0431 goto out_free_resources;
0432 }
0433
0434 ret = regulator_enable(info->proc_reg);
0435 if (ret) {
0436 dev_warn(cpu_dev, "cpu%d: failed to enable vproc\n", cpu);
0437 goto out_free_resources;
0438 }
0439
0440
0441 info->sram_reg = regulator_get_optional(cpu_dev, "sram");
0442 if (IS_ERR(info->sram_reg)) {
0443 ret = PTR_ERR(info->sram_reg);
0444 if (ret == -EPROBE_DEFER)
0445 goto out_free_resources;
0446
0447 info->sram_reg = NULL;
0448 } else {
0449 ret = regulator_enable(info->sram_reg);
0450 if (ret) {
0451 dev_warn(cpu_dev, "cpu%d: failed to enable vsram\n", cpu);
0452 goto out_free_resources;
0453 }
0454 }
0455
0456
0457 ret = dev_pm_opp_of_get_sharing_cpus(cpu_dev, &info->cpus);
0458 if (ret) {
0459 dev_err(cpu_dev,
0460 "cpu%d: failed to get OPP-sharing information\n", cpu);
0461 goto out_free_resources;
0462 }
0463
0464 ret = dev_pm_opp_of_cpumask_add_table(&info->cpus);
0465 if (ret) {
0466 dev_warn(cpu_dev, "cpu%d: no OPP table\n", cpu);
0467 goto out_free_resources;
0468 }
0469
0470 ret = clk_prepare_enable(info->cpu_clk);
0471 if (ret)
0472 goto out_free_opp_table;
0473
0474 ret = clk_prepare_enable(info->inter_clk);
0475 if (ret)
0476 goto out_disable_mux_clock;
0477
0478 if (info->soc_data->ccifreq_supported) {
0479 info->vproc_on_boot = regulator_get_voltage(info->proc_reg);
0480 if (info->vproc_on_boot < 0) {
0481 ret = info->vproc_on_boot;
0482 dev_err(info->cpu_dev,
0483 "invalid Vproc value: %d\n", info->vproc_on_boot);
0484 goto out_disable_inter_clock;
0485 }
0486 }
0487
0488
0489 rate = clk_get_rate(info->inter_clk);
0490 opp = dev_pm_opp_find_freq_ceil(cpu_dev, &rate);
0491 if (IS_ERR(opp)) {
0492 dev_err(cpu_dev, "cpu%d: failed to get intermediate opp\n", cpu);
0493 ret = PTR_ERR(opp);
0494 goto out_disable_inter_clock;
0495 }
0496 info->intermediate_voltage = dev_pm_opp_get_voltage(opp);
0497 dev_pm_opp_put(opp);
0498
0499 mutex_init(&info->reg_lock);
0500 info->current_freq = clk_get_rate(info->cpu_clk);
0501
0502 info->opp_cpu = cpu;
0503 info->opp_nb.notifier_call = mtk_cpufreq_opp_notifier;
0504 ret = dev_pm_opp_register_notifier(cpu_dev, &info->opp_nb);
0505 if (ret) {
0506 dev_err(cpu_dev, "cpu%d: failed to register opp notifier\n", cpu);
0507 goto out_disable_inter_clock;
0508 }
0509
0510
0511
0512
0513
0514 info->need_voltage_tracking = (info->sram_reg != NULL);
0515
0516
0517
0518
0519
0520
0521 info->vtrack_max = 3 * DIV_ROUND_UP(max(info->soc_data->sram_max_volt,
0522 info->soc_data->proc_max_volt),
0523 info->soc_data->min_volt_shift);
0524
0525 return 0;
0526
0527 out_disable_inter_clock:
0528 clk_disable_unprepare(info->inter_clk);
0529
0530 out_disable_mux_clock:
0531 clk_disable_unprepare(info->cpu_clk);
0532
0533 out_free_opp_table:
0534 dev_pm_opp_of_cpumask_remove_table(&info->cpus);
0535
0536 out_free_resources:
0537 if (regulator_is_enabled(info->proc_reg))
0538 regulator_disable(info->proc_reg);
0539 if (info->sram_reg && regulator_is_enabled(info->sram_reg))
0540 regulator_disable(info->sram_reg);
0541
0542 if (!IS_ERR(info->proc_reg))
0543 regulator_put(info->proc_reg);
0544 if (!IS_ERR(info->sram_reg))
0545 regulator_put(info->sram_reg);
0546 if (!IS_ERR(info->cpu_clk))
0547 clk_put(info->cpu_clk);
0548 if (!IS_ERR(info->inter_clk))
0549 clk_put(info->inter_clk);
0550
0551 return ret;
0552 }
0553
0554 static void mtk_cpu_dvfs_info_release(struct mtk_cpu_dvfs_info *info)
0555 {
0556 if (!IS_ERR(info->proc_reg)) {
0557 regulator_disable(info->proc_reg);
0558 regulator_put(info->proc_reg);
0559 }
0560 if (!IS_ERR(info->sram_reg)) {
0561 regulator_disable(info->sram_reg);
0562 regulator_put(info->sram_reg);
0563 }
0564 if (!IS_ERR(info->cpu_clk)) {
0565 clk_disable_unprepare(info->cpu_clk);
0566 clk_put(info->cpu_clk);
0567 }
0568 if (!IS_ERR(info->inter_clk)) {
0569 clk_disable_unprepare(info->inter_clk);
0570 clk_put(info->inter_clk);
0571 }
0572
0573 dev_pm_opp_of_cpumask_remove_table(&info->cpus);
0574 dev_pm_opp_unregister_notifier(info->cpu_dev, &info->opp_nb);
0575 }
0576
0577 static int mtk_cpufreq_init(struct cpufreq_policy *policy)
0578 {
0579 struct mtk_cpu_dvfs_info *info;
0580 struct cpufreq_frequency_table *freq_table;
0581 int ret;
0582
0583 info = mtk_cpu_dvfs_info_lookup(policy->cpu);
0584 if (!info) {
0585 pr_err("dvfs info for cpu%d is not initialized.\n",
0586 policy->cpu);
0587 return -EINVAL;
0588 }
0589
0590 ret = dev_pm_opp_init_cpufreq_table(info->cpu_dev, &freq_table);
0591 if (ret) {
0592 dev_err(info->cpu_dev,
0593 "failed to init cpufreq table for cpu%d: %d\n",
0594 policy->cpu, ret);
0595 return ret;
0596 }
0597
0598 cpumask_copy(policy->cpus, &info->cpus);
0599 policy->freq_table = freq_table;
0600 policy->driver_data = info;
0601 policy->clk = info->cpu_clk;
0602
0603 return 0;
0604 }
0605
0606 static int mtk_cpufreq_exit(struct cpufreq_policy *policy)
0607 {
0608 struct mtk_cpu_dvfs_info *info = policy->driver_data;
0609
0610 dev_pm_opp_free_cpufreq_table(info->cpu_dev, &policy->freq_table);
0611
0612 return 0;
0613 }
0614
0615 static struct cpufreq_driver mtk_cpufreq_driver = {
0616 .flags = CPUFREQ_NEED_INITIAL_FREQ_CHECK |
0617 CPUFREQ_HAVE_GOVERNOR_PER_POLICY |
0618 CPUFREQ_IS_COOLING_DEV,
0619 .verify = cpufreq_generic_frequency_table_verify,
0620 .target_index = mtk_cpufreq_set_target,
0621 .get = cpufreq_generic_get,
0622 .init = mtk_cpufreq_init,
0623 .exit = mtk_cpufreq_exit,
0624 .register_em = cpufreq_register_em_with_opp,
0625 .name = "mtk-cpufreq",
0626 .attr = cpufreq_generic_attr,
0627 };
0628
0629 static int mtk_cpufreq_probe(struct platform_device *pdev)
0630 {
0631 const struct mtk_cpufreq_platform_data *data;
0632 struct mtk_cpu_dvfs_info *info, *tmp;
0633 int cpu, ret;
0634
0635 data = dev_get_platdata(&pdev->dev);
0636 if (!data) {
0637 dev_err(&pdev->dev,
0638 "failed to get mtk cpufreq platform data\n");
0639 return -ENODEV;
0640 }
0641
0642 for_each_possible_cpu(cpu) {
0643 info = mtk_cpu_dvfs_info_lookup(cpu);
0644 if (info)
0645 continue;
0646
0647 info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
0648 if (!info) {
0649 ret = -ENOMEM;
0650 goto release_dvfs_info_list;
0651 }
0652
0653 info->soc_data = data;
0654 ret = mtk_cpu_dvfs_info_init(info, cpu);
0655 if (ret) {
0656 dev_err(&pdev->dev,
0657 "failed to initialize dvfs info for cpu%d\n",
0658 cpu);
0659 goto release_dvfs_info_list;
0660 }
0661
0662 list_add(&info->list_head, &dvfs_info_list);
0663 }
0664
0665 ret = cpufreq_register_driver(&mtk_cpufreq_driver);
0666 if (ret) {
0667 dev_err(&pdev->dev, "failed to register mtk cpufreq driver\n");
0668 goto release_dvfs_info_list;
0669 }
0670
0671 return 0;
0672
0673 release_dvfs_info_list:
0674 list_for_each_entry_safe(info, tmp, &dvfs_info_list, list_head) {
0675 mtk_cpu_dvfs_info_release(info);
0676 list_del(&info->list_head);
0677 }
0678
0679 return ret;
0680 }
0681
0682 static struct platform_driver mtk_cpufreq_platdrv = {
0683 .driver = {
0684 .name = "mtk-cpufreq",
0685 },
0686 .probe = mtk_cpufreq_probe,
0687 };
0688
0689 static const struct mtk_cpufreq_platform_data mt2701_platform_data = {
0690 .min_volt_shift = 100000,
0691 .max_volt_shift = 200000,
0692 .proc_max_volt = 1150000,
0693 .sram_min_volt = 0,
0694 .sram_max_volt = 1150000,
0695 .ccifreq_supported = false,
0696 };
0697
0698 static const struct mtk_cpufreq_platform_data mt8183_platform_data = {
0699 .min_volt_shift = 100000,
0700 .max_volt_shift = 200000,
0701 .proc_max_volt = 1150000,
0702 .sram_min_volt = 0,
0703 .sram_max_volt = 1150000,
0704 .ccifreq_supported = true,
0705 };
0706
0707 static const struct mtk_cpufreq_platform_data mt8186_platform_data = {
0708 .min_volt_shift = 100000,
0709 .max_volt_shift = 250000,
0710 .proc_max_volt = 1118750,
0711 .sram_min_volt = 850000,
0712 .sram_max_volt = 1118750,
0713 .ccifreq_supported = true,
0714 };
0715
0716
0717 static const struct of_device_id mtk_cpufreq_machines[] __initconst = {
0718 { .compatible = "mediatek,mt2701", .data = &mt2701_platform_data },
0719 { .compatible = "mediatek,mt2712", .data = &mt2701_platform_data },
0720 { .compatible = "mediatek,mt7622", .data = &mt2701_platform_data },
0721 { .compatible = "mediatek,mt7623", .data = &mt2701_platform_data },
0722 { .compatible = "mediatek,mt8167", .data = &mt2701_platform_data },
0723 { .compatible = "mediatek,mt817x", .data = &mt2701_platform_data },
0724 { .compatible = "mediatek,mt8173", .data = &mt2701_platform_data },
0725 { .compatible = "mediatek,mt8176", .data = &mt2701_platform_data },
0726 { .compatible = "mediatek,mt8183", .data = &mt8183_platform_data },
0727 { .compatible = "mediatek,mt8186", .data = &mt8186_platform_data },
0728 { .compatible = "mediatek,mt8365", .data = &mt2701_platform_data },
0729 { .compatible = "mediatek,mt8516", .data = &mt2701_platform_data },
0730 { }
0731 };
0732 MODULE_DEVICE_TABLE(of, mtk_cpufreq_machines);
0733
0734 static int __init mtk_cpufreq_driver_init(void)
0735 {
0736 struct device_node *np;
0737 const struct of_device_id *match;
0738 const struct mtk_cpufreq_platform_data *data;
0739 int err;
0740
0741 np = of_find_node_by_path("/");
0742 if (!np)
0743 return -ENODEV;
0744
0745 match = of_match_node(mtk_cpufreq_machines, np);
0746 of_node_put(np);
0747 if (!match) {
0748 pr_debug("Machine is not compatible with mtk-cpufreq\n");
0749 return -ENODEV;
0750 }
0751 data = match->data;
0752
0753 err = platform_driver_register(&mtk_cpufreq_platdrv);
0754 if (err)
0755 return err;
0756
0757
0758
0759
0760
0761
0762
0763 cpufreq_pdev = platform_device_register_data(NULL, "mtk-cpufreq", -1,
0764 data, sizeof(*data));
0765 if (IS_ERR(cpufreq_pdev)) {
0766 pr_err("failed to register mtk-cpufreq platform device\n");
0767 platform_driver_unregister(&mtk_cpufreq_platdrv);
0768 return PTR_ERR(cpufreq_pdev);
0769 }
0770
0771 return 0;
0772 }
0773 module_init(mtk_cpufreq_driver_init)
0774
0775 static void __exit mtk_cpufreq_driver_exit(void)
0776 {
0777 platform_device_unregister(cpufreq_pdev);
0778 platform_driver_unregister(&mtk_cpufreq_platdrv);
0779 }
0780 module_exit(mtk_cpufreq_driver_exit)
0781
0782 MODULE_DESCRIPTION("MediaTek CPUFreq driver");
0783 MODULE_AUTHOR("Pi-Cheng Chen <pi-cheng.chen@linaro.org>");
0784 MODULE_LICENSE("GPL v2");