Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (C) 2022 MediaTek Inc.
0004  */
0005 
0006 #include <linux/clk.h>
0007 #include <linux/devfreq.h>
0008 #include <linux/minmax.h>
0009 #include <linux/module.h>
0010 #include <linux/of.h>
0011 #include <linux/of_device.h>
0012 #include <linux/platform_device.h>
0013 #include <linux/pm_opp.h>
0014 #include <linux/regulator/consumer.h>
0015 
0016 struct mtk_ccifreq_platform_data {
0017     int min_volt_shift;
0018     int max_volt_shift;
0019     int proc_max_volt;
0020     int sram_min_volt;
0021     int sram_max_volt;
0022 };
0023 
0024 struct mtk_ccifreq_drv {
0025     struct device *dev;
0026     struct devfreq *devfreq;
0027     struct regulator *proc_reg;
0028     struct regulator *sram_reg;
0029     struct clk *cci_clk;
0030     struct clk *inter_clk;
0031     int inter_voltage;
0032     unsigned long pre_freq;
0033     /* Avoid race condition for regulators between notify and policy */
0034     struct mutex reg_lock;
0035     struct notifier_block opp_nb;
0036     const struct mtk_ccifreq_platform_data *soc_data;
0037     int vtrack_max;
0038 };
0039 
0040 static int mtk_ccifreq_set_voltage(struct mtk_ccifreq_drv *drv, int new_voltage)
0041 {
0042     const struct mtk_ccifreq_platform_data *soc_data = drv->soc_data;
0043     struct device *dev = drv->dev;
0044     int pre_voltage, pre_vsram, new_vsram, vsram, voltage, ret;
0045     int retry_max = drv->vtrack_max;
0046 
0047     if (!drv->sram_reg) {
0048         ret = regulator_set_voltage(drv->proc_reg, new_voltage,
0049                         drv->soc_data->proc_max_volt);
0050         return ret;
0051     }
0052 
0053     pre_voltage = regulator_get_voltage(drv->proc_reg);
0054     if (pre_voltage < 0) {
0055         dev_err(dev, "invalid vproc value: %d\n", pre_voltage);
0056         return pre_voltage;
0057     }
0058 
0059     pre_vsram = regulator_get_voltage(drv->sram_reg);
0060     if (pre_vsram < 0) {
0061         dev_err(dev, "invalid vsram value: %d\n", pre_vsram);
0062         return pre_vsram;
0063     }
0064 
0065     new_vsram = clamp(new_voltage + soc_data->min_volt_shift,
0066               soc_data->sram_min_volt, soc_data->sram_max_volt);
0067 
0068     do {
0069         if (pre_voltage <= new_voltage) {
0070             vsram = clamp(pre_voltage + soc_data->max_volt_shift,
0071                       soc_data->sram_min_volt, new_vsram);
0072             ret = regulator_set_voltage(drv->sram_reg, vsram,
0073                             soc_data->sram_max_volt);
0074             if (ret)
0075                 return ret;
0076 
0077             if (vsram == soc_data->sram_max_volt ||
0078                 new_vsram == soc_data->sram_min_volt)
0079                 voltage = new_voltage;
0080             else
0081                 voltage = vsram - soc_data->min_volt_shift;
0082 
0083             ret = regulator_set_voltage(drv->proc_reg, voltage,
0084                             soc_data->proc_max_volt);
0085             if (ret) {
0086                 regulator_set_voltage(drv->sram_reg, pre_vsram,
0087                               soc_data->sram_max_volt);
0088                 return ret;
0089             }
0090         } else if (pre_voltage > new_voltage) {
0091             voltage = max(new_voltage,
0092                       pre_vsram - soc_data->max_volt_shift);
0093             ret = regulator_set_voltage(drv->proc_reg, voltage,
0094                             soc_data->proc_max_volt);
0095             if (ret)
0096                 return ret;
0097 
0098             if (voltage == new_voltage)
0099                 vsram = new_vsram;
0100             else
0101                 vsram = max(new_vsram,
0102                         voltage + soc_data->min_volt_shift);
0103 
0104             ret = regulator_set_voltage(drv->sram_reg, vsram,
0105                             soc_data->sram_max_volt);
0106             if (ret) {
0107                 regulator_set_voltage(drv->proc_reg, pre_voltage,
0108                               soc_data->proc_max_volt);
0109                 return ret;
0110             }
0111         }
0112 
0113         pre_voltage = voltage;
0114         pre_vsram = vsram;
0115 
0116         if (--retry_max < 0) {
0117             dev_err(dev,
0118                 "over loop count, failed to set voltage\n");
0119             return -EINVAL;
0120         }
0121     } while (voltage != new_voltage || vsram != new_vsram);
0122 
0123     return 0;
0124 }
0125 
0126 static int mtk_ccifreq_target(struct device *dev, unsigned long *freq,
0127                   u32 flags)
0128 {
0129     struct mtk_ccifreq_drv *drv = dev_get_drvdata(dev);
0130     struct clk *cci_pll = clk_get_parent(drv->cci_clk);
0131     struct dev_pm_opp *opp;
0132     unsigned long opp_rate;
0133     int voltage, pre_voltage, inter_voltage, target_voltage, ret;
0134 
0135     if (!drv)
0136         return -EINVAL;
0137 
0138     if (drv->pre_freq == *freq)
0139         return 0;
0140 
0141     inter_voltage = drv->inter_voltage;
0142 
0143     opp_rate = *freq;
0144     opp = devfreq_recommended_opp(dev, &opp_rate, 1);
0145     if (IS_ERR(opp)) {
0146         dev_err(dev, "failed to find opp for freq: %ld\n", opp_rate);
0147         return PTR_ERR(opp);
0148     }
0149 
0150     mutex_lock(&drv->reg_lock);
0151 
0152     voltage = dev_pm_opp_get_voltage(opp);
0153     dev_pm_opp_put(opp);
0154 
0155     pre_voltage = regulator_get_voltage(drv->proc_reg);
0156     if (pre_voltage < 0) {
0157         dev_err(dev, "invalid vproc value: %d\n", pre_voltage);
0158         ret = pre_voltage;
0159         goto out_unlock;
0160     }
0161 
0162     /* scale up: set voltage first then freq. */
0163     target_voltage = max(inter_voltage, voltage);
0164     if (pre_voltage <= target_voltage) {
0165         ret = mtk_ccifreq_set_voltage(drv, target_voltage);
0166         if (ret) {
0167             dev_err(dev, "failed to scale up voltage\n");
0168             goto out_restore_voltage;
0169         }
0170     }
0171 
0172     /* switch the cci clock to intermediate clock source. */
0173     ret = clk_set_parent(drv->cci_clk, drv->inter_clk);
0174     if (ret) {
0175         dev_err(dev, "failed to re-parent cci clock\n");
0176         goto out_restore_voltage;
0177     }
0178 
0179     /* set the original clock to target rate. */
0180     ret = clk_set_rate(cci_pll, *freq);
0181     if (ret) {
0182         dev_err(dev, "failed to set cci pll rate: %d\n", ret);
0183         clk_set_parent(drv->cci_clk, cci_pll);
0184         goto out_restore_voltage;
0185     }
0186 
0187     /* switch the cci clock back to the original clock source. */
0188     ret = clk_set_parent(drv->cci_clk, cci_pll);
0189     if (ret) {
0190         dev_err(dev, "failed to re-parent cci clock\n");
0191         mtk_ccifreq_set_voltage(drv, inter_voltage);
0192         goto out_unlock;
0193     }
0194 
0195     /*
0196      * If the new voltage is lower than the intermediate voltage or the
0197      * original voltage, scale down to the new voltage.
0198      */
0199     if (voltage < inter_voltage || voltage < pre_voltage) {
0200         ret = mtk_ccifreq_set_voltage(drv, voltage);
0201         if (ret) {
0202             dev_err(dev, "failed to scale down voltage\n");
0203             goto out_unlock;
0204         }
0205     }
0206 
0207     drv->pre_freq = *freq;
0208     mutex_unlock(&drv->reg_lock);
0209 
0210     return 0;
0211 
0212 out_restore_voltage:
0213     mtk_ccifreq_set_voltage(drv, pre_voltage);
0214 
0215 out_unlock:
0216     mutex_unlock(&drv->reg_lock);
0217     return ret;
0218 }
0219 
0220 static int mtk_ccifreq_opp_notifier(struct notifier_block *nb,
0221                     unsigned long event, void *data)
0222 {
0223     struct dev_pm_opp *opp = data;
0224     struct mtk_ccifreq_drv *drv;
0225     unsigned long freq, volt;
0226 
0227     drv = container_of(nb, struct mtk_ccifreq_drv, opp_nb);
0228 
0229     if (event == OPP_EVENT_ADJUST_VOLTAGE) {
0230         freq = dev_pm_opp_get_freq(opp);
0231 
0232         mutex_lock(&drv->reg_lock);
0233         /* current opp item is changed */
0234         if (freq == drv->pre_freq) {
0235             volt = dev_pm_opp_get_voltage(opp);
0236             mtk_ccifreq_set_voltage(drv, volt);
0237         }
0238         mutex_unlock(&drv->reg_lock);
0239     }
0240 
0241     return 0;
0242 }
0243 
0244 static struct devfreq_dev_profile mtk_ccifreq_profile = {
0245     .target = mtk_ccifreq_target,
0246 };
0247 
0248 static int mtk_ccifreq_probe(struct platform_device *pdev)
0249 {
0250     struct device *dev = &pdev->dev;
0251     struct mtk_ccifreq_drv *drv;
0252     struct devfreq_passive_data *passive_data;
0253     struct dev_pm_opp *opp;
0254     unsigned long rate, opp_volt;
0255     int ret;
0256 
0257     drv = devm_kzalloc(dev, sizeof(*drv), GFP_KERNEL);
0258     if (!drv)
0259         return -ENOMEM;
0260 
0261     drv->dev = dev;
0262     drv->soc_data = (const struct mtk_ccifreq_platform_data *)
0263                 of_device_get_match_data(&pdev->dev);
0264     mutex_init(&drv->reg_lock);
0265     platform_set_drvdata(pdev, drv);
0266 
0267     drv->cci_clk = devm_clk_get(dev, "cci");
0268     if (IS_ERR(drv->cci_clk)) {
0269         ret = PTR_ERR(drv->cci_clk);
0270         return dev_err_probe(dev, ret, "failed to get cci clk\n");
0271     }
0272 
0273     drv->inter_clk = devm_clk_get(dev, "intermediate");
0274     if (IS_ERR(drv->inter_clk)) {
0275         ret = PTR_ERR(drv->inter_clk);
0276         return dev_err_probe(dev, ret,
0277                      "failed to get intermediate clk\n");
0278     }
0279 
0280     drv->proc_reg = devm_regulator_get_optional(dev, "proc");
0281     if (IS_ERR(drv->proc_reg)) {
0282         ret = PTR_ERR(drv->proc_reg);
0283         return dev_err_probe(dev, ret,
0284                      "failed to get proc regulator\n");
0285     }
0286 
0287     ret = regulator_enable(drv->proc_reg);
0288     if (ret) {
0289         dev_err(dev, "failed to enable proc regulator\n");
0290         return ret;
0291     }
0292 
0293     drv->sram_reg = devm_regulator_get_optional(dev, "sram");
0294     if (IS_ERR(drv->sram_reg))
0295         drv->sram_reg = NULL;
0296     else {
0297         ret = regulator_enable(drv->sram_reg);
0298         if (ret) {
0299             dev_err(dev, "failed to enable sram regulator\n");
0300             goto out_free_resources;
0301         }
0302     }
0303 
0304     /*
0305      * We assume min voltage is 0 and tracking target voltage using
0306      * min_volt_shift for each iteration.
0307      * The retry_max is 3 times of expected iteration count.
0308      */
0309     drv->vtrack_max = 3 * DIV_ROUND_UP(max(drv->soc_data->sram_max_volt,
0310                            drv->soc_data->proc_max_volt),
0311                        drv->soc_data->min_volt_shift);
0312 
0313     ret = clk_prepare_enable(drv->cci_clk);
0314     if (ret)
0315         goto out_free_resources;
0316 
0317     ret = dev_pm_opp_of_add_table(dev);
0318     if (ret) {
0319         dev_err(dev, "failed to add opp table: %d\n", ret);
0320         goto out_disable_cci_clk;
0321     }
0322 
0323     rate = clk_get_rate(drv->inter_clk);
0324     opp = dev_pm_opp_find_freq_ceil(dev, &rate);
0325     if (IS_ERR(opp)) {
0326         ret = PTR_ERR(opp);
0327         dev_err(dev, "failed to get intermediate opp: %d\n", ret);
0328         goto out_remove_opp_table;
0329     }
0330     drv->inter_voltage = dev_pm_opp_get_voltage(opp);
0331     dev_pm_opp_put(opp);
0332 
0333     rate = U32_MAX;
0334     opp = dev_pm_opp_find_freq_floor(drv->dev, &rate);
0335     if (IS_ERR(opp)) {
0336         dev_err(dev, "failed to get opp\n");
0337         ret = PTR_ERR(opp);
0338         goto out_remove_opp_table;
0339     }
0340 
0341     opp_volt = dev_pm_opp_get_voltage(opp);
0342     dev_pm_opp_put(opp);
0343     ret = mtk_ccifreq_set_voltage(drv, opp_volt);
0344     if (ret) {
0345         dev_err(dev, "failed to scale to highest voltage %lu in proc_reg\n",
0346             opp_volt);
0347         goto out_remove_opp_table;
0348     }
0349 
0350     passive_data = devm_kzalloc(dev, sizeof(*passive_data), GFP_KERNEL);
0351     if (!passive_data) {
0352         ret = -ENOMEM;
0353         goto out_remove_opp_table;
0354     }
0355 
0356     passive_data->parent_type = CPUFREQ_PARENT_DEV;
0357     drv->devfreq = devm_devfreq_add_device(dev, &mtk_ccifreq_profile,
0358                            DEVFREQ_GOV_PASSIVE,
0359                            passive_data);
0360     if (IS_ERR(drv->devfreq)) {
0361         ret = -EPROBE_DEFER;
0362         dev_err(dev, "failed to add devfreq device: %ld\n",
0363             PTR_ERR(drv->devfreq));
0364         goto out_remove_opp_table;
0365     }
0366 
0367     drv->opp_nb.notifier_call = mtk_ccifreq_opp_notifier;
0368     ret = dev_pm_opp_register_notifier(dev, &drv->opp_nb);
0369     if (ret) {
0370         dev_err(dev, "failed to register opp notifier: %d\n", ret);
0371         goto out_remove_opp_table;
0372     }
0373     return 0;
0374 
0375 out_remove_opp_table:
0376     dev_pm_opp_of_remove_table(dev);
0377 
0378 out_disable_cci_clk:
0379     clk_disable_unprepare(drv->cci_clk);
0380 
0381 out_free_resources:
0382     if (regulator_is_enabled(drv->proc_reg))
0383         regulator_disable(drv->proc_reg);
0384     if (drv->sram_reg && regulator_is_enabled(drv->sram_reg))
0385         regulator_disable(drv->sram_reg);
0386 
0387     return ret;
0388 }
0389 
0390 static int mtk_ccifreq_remove(struct platform_device *pdev)
0391 {
0392     struct device *dev = &pdev->dev;
0393     struct mtk_ccifreq_drv *drv;
0394 
0395     drv = platform_get_drvdata(pdev);
0396 
0397     dev_pm_opp_unregister_notifier(dev, &drv->opp_nb);
0398     dev_pm_opp_of_remove_table(dev);
0399     clk_disable_unprepare(drv->cci_clk);
0400     regulator_disable(drv->proc_reg);
0401     if (drv->sram_reg)
0402         regulator_disable(drv->sram_reg);
0403 
0404     return 0;
0405 }
0406 
0407 static const struct mtk_ccifreq_platform_data mt8183_platform_data = {
0408     .min_volt_shift = 100000,
0409     .max_volt_shift = 200000,
0410     .proc_max_volt = 1150000,
0411 };
0412 
0413 static const struct mtk_ccifreq_platform_data mt8186_platform_data = {
0414     .min_volt_shift = 100000,
0415     .max_volt_shift = 250000,
0416     .proc_max_volt = 1118750,
0417     .sram_min_volt = 850000,
0418     .sram_max_volt = 1118750,
0419 };
0420 
0421 static const struct of_device_id mtk_ccifreq_machines[] = {
0422     { .compatible = "mediatek,mt8183-cci", .data = &mt8183_platform_data },
0423     { .compatible = "mediatek,mt8186-cci", .data = &mt8186_platform_data },
0424     { },
0425 };
0426 MODULE_DEVICE_TABLE(of, mtk_ccifreq_machines);
0427 
0428 static struct platform_driver mtk_ccifreq_platdrv = {
0429     .probe  = mtk_ccifreq_probe,
0430     .remove = mtk_ccifreq_remove,
0431     .driver = {
0432         .name = "mtk-ccifreq",
0433         .of_match_table = mtk_ccifreq_machines,
0434     },
0435 };
0436 module_platform_driver(mtk_ccifreq_platdrv);
0437 
0438 MODULE_DESCRIPTION("MediaTek CCI devfreq driver");
0439 MODULE_AUTHOR("Jia-Wei Chang <jia-wei.chang@mediatek.com>");
0440 MODULE_LICENSE("GPL v2");