Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (c) 2015 Linaro Ltd.
0004  * Author: Pi-Cheng Chen <pi-cheng.chen@linaro.org>
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  * The struct mtk_cpu_dvfs_info holds necessary information for doing CPU DVFS
0030  * on each CPU power/clock domain of Mediatek SoCs. Each CPU cluster in
0031  * Mediatek SoCs has two voltage inputs, Vproc and Vsram. In some cases the two
0032  * voltage inputs need to be controlled under a hardware limitation:
0033  * 100mV < Vsram - Vproc < 200mV
0034  *
0035  * When scaling the clock frequency of a CPU clock domain, the clock source
0036  * needs to be switched to another stable PLL clock temporarily until
0037  * the original PLL becomes stable at target frequency.
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     /* Avoid race condition for regulators between notify and policy */
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      * If MediaTek cci is supported but is not ready, we will use the value
0243      * of max(target cpu voltage, booting voltage) to prevent high freqeuncy
0244      * low voltage crash.
0245      */
0246     if (info->soc_data->ccifreq_supported && !is_ccifreq_ready(info))
0247         vproc = max(vproc, info->vproc_on_boot);
0248 
0249     /*
0250      * If the new voltage or the intermediate voltage is higher than the
0251      * current voltage, scale up voltage first.
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     /* Reparent the CPU clock to intermediate clock. */
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     /* Set the original PLL to target rate. */
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     /* Set parent of CPU clock back to the original PLL. */
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      * If the new voltage is lower than the intermediate voltage or the
0294      * original voltage, scale down to the new voltage.
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         /* case of current opp item is disabled */
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     /* Both presence and absence of sram regulator are valid cases. */
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     /* Get OPP-sharing information from "operating-points-v2" bindings */
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     /* Search a safe voltage for intermediate frequency. */
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      * If SRAM regulator is present, software "voltage tracking" is needed
0512      * for this CPU power domain.
0513      */
0514     info->need_voltage_tracking = (info->sram_reg != NULL);
0515 
0516     /*
0517      * We assume min voltage is 0 and tracking target voltage using
0518      * min_volt_shift for each iteration.
0519      * The vtrack_max is 3 times of expeted iteration count.
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 /* List of machines supported by this driver */
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      * Since there's no place to hold device registration code and no
0759      * device tree based way to match cpufreq driver yet, both the driver
0760      * and the device registration codes are put here to handle defer
0761      * probing.
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");