linux/drivers/cpufreq/mediatek-cpufreq.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Copyright (c) 2015 Linaro Ltd.
   4 * Author: Pi-Cheng Chen <pi-cheng.chen@linaro.org>
   5 */
   6
   7#include <linux/clk.h>
   8#include <linux/cpu.h>
   9#include <linux/cpufreq.h>
  10#include <linux/cpumask.h>
  11#include <linux/module.h>
  12#include <linux/of.h>
  13#include <linux/platform_device.h>
  14#include <linux/pm_opp.h>
  15#include <linux/regulator/consumer.h>
  16#include <linux/slab.h>
  17#include <linux/thermal.h>
  18
  19#define MIN_VOLT_SHIFT          (100000)
  20#define MAX_VOLT_SHIFT          (200000)
  21#define MAX_VOLT_LIMIT          (1150000)
  22#define VOLT_TOL                (10000)
  23
  24/*
  25 * The struct mtk_cpu_dvfs_info holds necessary information for doing CPU DVFS
  26 * on each CPU power/clock domain of Mediatek SoCs. Each CPU cluster in
  27 * Mediatek SoCs has two voltage inputs, Vproc and Vsram. In some cases the two
  28 * voltage inputs need to be controlled under a hardware limitation:
  29 * 100mV < Vsram - Vproc < 200mV
  30 *
  31 * When scaling the clock frequency of a CPU clock domain, the clock source
  32 * needs to be switched to another stable PLL clock temporarily until
  33 * the original PLL becomes stable at target frequency.
  34 */
  35struct mtk_cpu_dvfs_info {
  36        struct cpumask cpus;
  37        struct device *cpu_dev;
  38        struct regulator *proc_reg;
  39        struct regulator *sram_reg;
  40        struct clk *cpu_clk;
  41        struct clk *inter_clk;
  42        struct list_head list_head;
  43        int intermediate_voltage;
  44        bool need_voltage_tracking;
  45};
  46
  47static LIST_HEAD(dvfs_info_list);
  48
  49static struct mtk_cpu_dvfs_info *mtk_cpu_dvfs_info_lookup(int cpu)
  50{
  51        struct mtk_cpu_dvfs_info *info;
  52
  53        list_for_each_entry(info, &dvfs_info_list, list_head) {
  54                if (cpumask_test_cpu(cpu, &info->cpus))
  55                        return info;
  56        }
  57
  58        return NULL;
  59}
  60
  61static int mtk_cpufreq_voltage_tracking(struct mtk_cpu_dvfs_info *info,
  62                                        int new_vproc)
  63{
  64        struct regulator *proc_reg = info->proc_reg;
  65        struct regulator *sram_reg = info->sram_reg;
  66        int old_vproc, old_vsram, new_vsram, vsram, vproc, ret;
  67
  68        old_vproc = regulator_get_voltage(proc_reg);
  69        if (old_vproc < 0) {
  70                pr_err("%s: invalid Vproc value: %d\n", __func__, old_vproc);
  71                return old_vproc;
  72        }
  73        /* Vsram should not exceed the maximum allowed voltage of SoC. */
  74        new_vsram = min(new_vproc + MIN_VOLT_SHIFT, MAX_VOLT_LIMIT);
  75
  76        if (old_vproc < new_vproc) {
  77                /*
  78                 * When scaling up voltages, Vsram and Vproc scale up step
  79                 * by step. At each step, set Vsram to (Vproc + 200mV) first,
  80                 * then set Vproc to (Vsram - 100mV).
  81                 * Keep doing it until Vsram and Vproc hit target voltages.
  82                 */
  83                do {
  84                        old_vsram = regulator_get_voltage(sram_reg);
  85                        if (old_vsram < 0) {
  86                                pr_err("%s: invalid Vsram value: %d\n",
  87                                       __func__, old_vsram);
  88                                return old_vsram;
  89                        }
  90                        old_vproc = regulator_get_voltage(proc_reg);
  91                        if (old_vproc < 0) {
  92                                pr_err("%s: invalid Vproc value: %d\n",
  93                                       __func__, old_vproc);
  94                                return old_vproc;
  95                        }
  96
  97                        vsram = min(new_vsram, old_vproc + MAX_VOLT_SHIFT);
  98
  99                        if (vsram + VOLT_TOL >= MAX_VOLT_LIMIT) {
 100                                vsram = MAX_VOLT_LIMIT;
 101
 102                                /*
 103                                 * If the target Vsram hits the maximum voltage,
 104                                 * try to set the exact voltage value first.
 105                                 */
 106                                ret = regulator_set_voltage(sram_reg, vsram,
 107                                                            vsram);
 108                                if (ret)
 109                                        ret = regulator_set_voltage(sram_reg,
 110                                                        vsram - VOLT_TOL,
 111                                                        vsram);
 112
 113                                vproc = new_vproc;
 114                        } else {
 115                                ret = regulator_set_voltage(sram_reg, vsram,
 116                                                            vsram + VOLT_TOL);
 117
 118                                vproc = vsram - MIN_VOLT_SHIFT;
 119                        }
 120                        if (ret)
 121                                return ret;
 122
 123                        ret = regulator_set_voltage(proc_reg, vproc,
 124                                                    vproc + VOLT_TOL);
 125                        if (ret) {
 126                                regulator_set_voltage(sram_reg, old_vsram,
 127                                                      old_vsram);
 128                                return ret;
 129                        }
 130                } while (vproc < new_vproc || vsram < new_vsram);
 131        } else if (old_vproc > new_vproc) {
 132                /*
 133                 * When scaling down voltages, Vsram and Vproc scale down step
 134                 * by step. At each step, set Vproc to (Vsram - 200mV) first,
 135                 * then set Vproc to (Vproc + 100mV).
 136                 * Keep doing it until Vsram and Vproc hit target voltages.
 137                 */
 138                do {
 139                        old_vproc = regulator_get_voltage(proc_reg);
 140                        if (old_vproc < 0) {
 141                                pr_err("%s: invalid Vproc value: %d\n",
 142                                       __func__, old_vproc);
 143                                return old_vproc;
 144                        }
 145                        old_vsram = regulator_get_voltage(sram_reg);
 146                        if (old_vsram < 0) {
 147                                pr_err("%s: invalid Vsram value: %d\n",
 148                                       __func__, old_vsram);
 149                                return old_vsram;
 150                        }
 151
 152                        vproc = max(new_vproc, old_vsram - MAX_VOLT_SHIFT);
 153                        ret = regulator_set_voltage(proc_reg, vproc,
 154                                                    vproc + VOLT_TOL);
 155                        if (ret)
 156                                return ret;
 157
 158                        if (vproc == new_vproc)
 159                                vsram = new_vsram;
 160                        else
 161                                vsram = max(new_vsram, vproc + MIN_VOLT_SHIFT);
 162
 163                        if (vsram + VOLT_TOL >= MAX_VOLT_LIMIT) {
 164                                vsram = MAX_VOLT_LIMIT;
 165
 166                                /*
 167                                 * If the target Vsram hits the maximum voltage,
 168                                 * try to set the exact voltage value first.
 169                                 */
 170                                ret = regulator_set_voltage(sram_reg, vsram,
 171                                                            vsram);
 172                                if (ret)
 173                                        ret = regulator_set_voltage(sram_reg,
 174                                                        vsram - VOLT_TOL,
 175                                                        vsram);
 176                        } else {
 177                                ret = regulator_set_voltage(sram_reg, vsram,
 178                                                            vsram + VOLT_TOL);
 179                        }
 180
 181                        if (ret) {
 182                                regulator_set_voltage(proc_reg, old_vproc,
 183                                                      old_vproc);
 184                                return ret;
 185                        }
 186                } while (vproc > new_vproc + VOLT_TOL ||
 187                         vsram > new_vsram + VOLT_TOL);
 188        }
 189
 190        return 0;
 191}
 192
 193static int mtk_cpufreq_set_voltage(struct mtk_cpu_dvfs_info *info, int vproc)
 194{
 195        if (info->need_voltage_tracking)
 196                return mtk_cpufreq_voltage_tracking(info, vproc);
 197        else
 198                return regulator_set_voltage(info->proc_reg, vproc,
 199                                             vproc + VOLT_TOL);
 200}
 201
 202static int mtk_cpufreq_set_target(struct cpufreq_policy *policy,
 203                                  unsigned int index)
 204{
 205        struct cpufreq_frequency_table *freq_table = policy->freq_table;
 206        struct clk *cpu_clk = policy->clk;
 207        struct clk *armpll = clk_get_parent(cpu_clk);
 208        struct mtk_cpu_dvfs_info *info = policy->driver_data;
 209        struct device *cpu_dev = info->cpu_dev;
 210        struct dev_pm_opp *opp;
 211        long freq_hz, old_freq_hz;
 212        int vproc, old_vproc, inter_vproc, target_vproc, ret;
 213
 214        inter_vproc = info->intermediate_voltage;
 215
 216        old_freq_hz = clk_get_rate(cpu_clk);
 217        old_vproc = regulator_get_voltage(info->proc_reg);
 218        if (old_vproc < 0) {
 219                pr_err("%s: invalid Vproc value: %d\n", __func__, old_vproc);
 220                return old_vproc;
 221        }
 222
 223        freq_hz = freq_table[index].frequency * 1000;
 224
 225        opp = dev_pm_opp_find_freq_ceil(cpu_dev, &freq_hz);
 226        if (IS_ERR(opp)) {
 227                pr_err("cpu%d: failed to find OPP for %ld\n",
 228                       policy->cpu, freq_hz);
 229                return PTR_ERR(opp);
 230        }
 231        vproc = dev_pm_opp_get_voltage(opp);
 232        dev_pm_opp_put(opp);
 233
 234        /*
 235         * If the new voltage or the intermediate voltage is higher than the
 236         * current voltage, scale up voltage first.
 237         */
 238        target_vproc = (inter_vproc > vproc) ? inter_vproc : vproc;
 239        if (old_vproc < target_vproc) {
 240                ret = mtk_cpufreq_set_voltage(info, target_vproc);
 241                if (ret) {
 242                        pr_err("cpu%d: failed to scale up voltage!\n",
 243                               policy->cpu);
 244                        mtk_cpufreq_set_voltage(info, old_vproc);
 245                        return ret;
 246                }
 247        }
 248
 249        /* Reparent the CPU clock to intermediate clock. */
 250        ret = clk_set_parent(cpu_clk, info->inter_clk);
 251        if (ret) {
 252                pr_err("cpu%d: failed to re-parent cpu clock!\n",
 253                       policy->cpu);
 254                mtk_cpufreq_set_voltage(info, old_vproc);
 255                WARN_ON(1);
 256                return ret;
 257        }
 258
 259        /* Set the original PLL to target rate. */
 260        ret = clk_set_rate(armpll, freq_hz);
 261        if (ret) {
 262                pr_err("cpu%d: failed to scale cpu clock rate!\n",
 263                       policy->cpu);
 264                clk_set_parent(cpu_clk, armpll);
 265                mtk_cpufreq_set_voltage(info, old_vproc);
 266                return ret;
 267        }
 268
 269        /* Set parent of CPU clock back to the original PLL. */
 270        ret = clk_set_parent(cpu_clk, armpll);
 271        if (ret) {
 272                pr_err("cpu%d: failed to re-parent cpu clock!\n",
 273                       policy->cpu);
 274                mtk_cpufreq_set_voltage(info, inter_vproc);
 275                WARN_ON(1);
 276                return ret;
 277        }
 278
 279        /*
 280         * If the new voltage is lower than the intermediate voltage or the
 281         * original voltage, scale down to the new voltage.
 282         */
 283        if (vproc < inter_vproc || vproc < old_vproc) {
 284                ret = mtk_cpufreq_set_voltage(info, vproc);
 285                if (ret) {
 286                        pr_err("cpu%d: failed to scale down voltage!\n",
 287                               policy->cpu);
 288                        clk_set_parent(cpu_clk, info->inter_clk);
 289                        clk_set_rate(armpll, old_freq_hz);
 290                        clk_set_parent(cpu_clk, armpll);
 291                        return ret;
 292                }
 293        }
 294
 295        return 0;
 296}
 297
 298#define DYNAMIC_POWER "dynamic-power-coefficient"
 299
 300static int mtk_cpu_dvfs_info_init(struct mtk_cpu_dvfs_info *info, int cpu)
 301{
 302        struct device *cpu_dev;
 303        struct regulator *proc_reg = ERR_PTR(-ENODEV);
 304        struct regulator *sram_reg = ERR_PTR(-ENODEV);
 305        struct clk *cpu_clk = ERR_PTR(-ENODEV);
 306        struct clk *inter_clk = ERR_PTR(-ENODEV);
 307        struct dev_pm_opp *opp;
 308        unsigned long rate;
 309        int ret;
 310
 311        cpu_dev = get_cpu_device(cpu);
 312        if (!cpu_dev) {
 313                pr_err("failed to get cpu%d device\n", cpu);
 314                return -ENODEV;
 315        }
 316
 317        cpu_clk = clk_get(cpu_dev, "cpu");
 318        if (IS_ERR(cpu_clk)) {
 319                if (PTR_ERR(cpu_clk) == -EPROBE_DEFER)
 320                        pr_warn("cpu clk for cpu%d not ready, retry.\n", cpu);
 321                else
 322                        pr_err("failed to get cpu clk for cpu%d\n", cpu);
 323
 324                ret = PTR_ERR(cpu_clk);
 325                return ret;
 326        }
 327
 328        inter_clk = clk_get(cpu_dev, "intermediate");
 329        if (IS_ERR(inter_clk)) {
 330                if (PTR_ERR(inter_clk) == -EPROBE_DEFER)
 331                        pr_warn("intermediate clk for cpu%d not ready, retry.\n",
 332                                cpu);
 333                else
 334                        pr_err("failed to get intermediate clk for cpu%d\n",
 335                               cpu);
 336
 337                ret = PTR_ERR(inter_clk);
 338                goto out_free_resources;
 339        }
 340
 341        proc_reg = regulator_get_optional(cpu_dev, "proc");
 342        if (IS_ERR(proc_reg)) {
 343                if (PTR_ERR(proc_reg) == -EPROBE_DEFER)
 344                        pr_warn("proc regulator for cpu%d not ready, retry.\n",
 345                                cpu);
 346                else
 347                        pr_err("failed to get proc regulator for cpu%d\n",
 348                               cpu);
 349
 350                ret = PTR_ERR(proc_reg);
 351                goto out_free_resources;
 352        }
 353
 354        /* Both presence and absence of sram regulator are valid cases. */
 355        sram_reg = regulator_get_exclusive(cpu_dev, "sram");
 356
 357        /* Get OPP-sharing information from "operating-points-v2" bindings */
 358        ret = dev_pm_opp_of_get_sharing_cpus(cpu_dev, &info->cpus);
 359        if (ret) {
 360                pr_err("failed to get OPP-sharing information for cpu%d\n",
 361                       cpu);
 362                goto out_free_resources;
 363        }
 364
 365        ret = dev_pm_opp_of_cpumask_add_table(&info->cpus);
 366        if (ret) {
 367                pr_warn("no OPP table for cpu%d\n", cpu);
 368                goto out_free_resources;
 369        }
 370
 371        /* Search a safe voltage for intermediate frequency. */
 372        rate = clk_get_rate(inter_clk);
 373        opp = dev_pm_opp_find_freq_ceil(cpu_dev, &rate);
 374        if (IS_ERR(opp)) {
 375                pr_err("failed to get intermediate opp for cpu%d\n", cpu);
 376                ret = PTR_ERR(opp);
 377                goto out_free_opp_table;
 378        }
 379        info->intermediate_voltage = dev_pm_opp_get_voltage(opp);
 380        dev_pm_opp_put(opp);
 381
 382        info->cpu_dev = cpu_dev;
 383        info->proc_reg = proc_reg;
 384        info->sram_reg = IS_ERR(sram_reg) ? NULL : sram_reg;
 385        info->cpu_clk = cpu_clk;
 386        info->inter_clk = inter_clk;
 387
 388        /*
 389         * If SRAM regulator is present, software "voltage tracking" is needed
 390         * for this CPU power domain.
 391         */
 392        info->need_voltage_tracking = !IS_ERR(sram_reg);
 393
 394        return 0;
 395
 396out_free_opp_table:
 397        dev_pm_opp_of_cpumask_remove_table(&info->cpus);
 398
 399out_free_resources:
 400        if (!IS_ERR(proc_reg))
 401                regulator_put(proc_reg);
 402        if (!IS_ERR(sram_reg))
 403                regulator_put(sram_reg);
 404        if (!IS_ERR(cpu_clk))
 405                clk_put(cpu_clk);
 406        if (!IS_ERR(inter_clk))
 407                clk_put(inter_clk);
 408
 409        return ret;
 410}
 411
 412static void mtk_cpu_dvfs_info_release(struct mtk_cpu_dvfs_info *info)
 413{
 414        if (!IS_ERR(info->proc_reg))
 415                regulator_put(info->proc_reg);
 416        if (!IS_ERR(info->sram_reg))
 417                regulator_put(info->sram_reg);
 418        if (!IS_ERR(info->cpu_clk))
 419                clk_put(info->cpu_clk);
 420        if (!IS_ERR(info->inter_clk))
 421                clk_put(info->inter_clk);
 422
 423        dev_pm_opp_of_cpumask_remove_table(&info->cpus);
 424}
 425
 426static int mtk_cpufreq_init(struct cpufreq_policy *policy)
 427{
 428        struct mtk_cpu_dvfs_info *info;
 429        struct cpufreq_frequency_table *freq_table;
 430        int ret;
 431
 432        info = mtk_cpu_dvfs_info_lookup(policy->cpu);
 433        if (!info) {
 434                pr_err("dvfs info for cpu%d is not initialized.\n",
 435                       policy->cpu);
 436                return -EINVAL;
 437        }
 438
 439        ret = dev_pm_opp_init_cpufreq_table(info->cpu_dev, &freq_table);
 440        if (ret) {
 441                pr_err("failed to init cpufreq table for cpu%d: %d\n",
 442                       policy->cpu, ret);
 443                return ret;
 444        }
 445
 446        cpumask_copy(policy->cpus, &info->cpus);
 447        policy->freq_table = freq_table;
 448        policy->driver_data = info;
 449        policy->clk = info->cpu_clk;
 450
 451        dev_pm_opp_of_register_em(info->cpu_dev, policy->cpus);
 452
 453        return 0;
 454}
 455
 456static int mtk_cpufreq_exit(struct cpufreq_policy *policy)
 457{
 458        struct mtk_cpu_dvfs_info *info = policy->driver_data;
 459
 460        dev_pm_opp_free_cpufreq_table(info->cpu_dev, &policy->freq_table);
 461
 462        return 0;
 463}
 464
 465static struct cpufreq_driver mtk_cpufreq_driver = {
 466        .flags = CPUFREQ_NEED_INITIAL_FREQ_CHECK |
 467                 CPUFREQ_HAVE_GOVERNOR_PER_POLICY |
 468                 CPUFREQ_IS_COOLING_DEV,
 469        .verify = cpufreq_generic_frequency_table_verify,
 470        .target_index = mtk_cpufreq_set_target,
 471        .get = cpufreq_generic_get,
 472        .init = mtk_cpufreq_init,
 473        .exit = mtk_cpufreq_exit,
 474        .name = "mtk-cpufreq",
 475        .attr = cpufreq_generic_attr,
 476};
 477
 478static int mtk_cpufreq_probe(struct platform_device *pdev)
 479{
 480        struct mtk_cpu_dvfs_info *info, *tmp;
 481        int cpu, ret;
 482
 483        for_each_possible_cpu(cpu) {
 484                info = mtk_cpu_dvfs_info_lookup(cpu);
 485                if (info)
 486                        continue;
 487
 488                info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
 489                if (!info) {
 490                        ret = -ENOMEM;
 491                        goto release_dvfs_info_list;
 492                }
 493
 494                ret = mtk_cpu_dvfs_info_init(info, cpu);
 495                if (ret) {
 496                        dev_err(&pdev->dev,
 497                                "failed to initialize dvfs info for cpu%d\n",
 498                                cpu);
 499                        goto release_dvfs_info_list;
 500                }
 501
 502                list_add(&info->list_head, &dvfs_info_list);
 503        }
 504
 505        ret = cpufreq_register_driver(&mtk_cpufreq_driver);
 506        if (ret) {
 507                dev_err(&pdev->dev, "failed to register mtk cpufreq driver\n");
 508                goto release_dvfs_info_list;
 509        }
 510
 511        return 0;
 512
 513release_dvfs_info_list:
 514        list_for_each_entry_safe(info, tmp, &dvfs_info_list, list_head) {
 515                mtk_cpu_dvfs_info_release(info);
 516                list_del(&info->list_head);
 517        }
 518
 519        return ret;
 520}
 521
 522static struct platform_driver mtk_cpufreq_platdrv = {
 523        .driver = {
 524                .name   = "mtk-cpufreq",
 525        },
 526        .probe          = mtk_cpufreq_probe,
 527};
 528
 529/* List of machines supported by this driver */
 530static const struct of_device_id mtk_cpufreq_machines[] __initconst = {
 531        { .compatible = "mediatek,mt2701", },
 532        { .compatible = "mediatek,mt2712", },
 533        { .compatible = "mediatek,mt7622", },
 534        { .compatible = "mediatek,mt7623", },
 535        { .compatible = "mediatek,mt8167", },
 536        { .compatible = "mediatek,mt817x", },
 537        { .compatible = "mediatek,mt8173", },
 538        { .compatible = "mediatek,mt8176", },
 539        { .compatible = "mediatek,mt8183", },
 540        { .compatible = "mediatek,mt8516", },
 541
 542        { }
 543};
 544MODULE_DEVICE_TABLE(of, mtk_cpufreq_machines);
 545
 546static int __init mtk_cpufreq_driver_init(void)
 547{
 548        struct device_node *np;
 549        const struct of_device_id *match;
 550        struct platform_device *pdev;
 551        int err;
 552
 553        np = of_find_node_by_path("/");
 554        if (!np)
 555                return -ENODEV;
 556
 557        match = of_match_node(mtk_cpufreq_machines, np);
 558        of_node_put(np);
 559        if (!match) {
 560                pr_debug("Machine is not compatible with mtk-cpufreq\n");
 561                return -ENODEV;
 562        }
 563
 564        err = platform_driver_register(&mtk_cpufreq_platdrv);
 565        if (err)
 566                return err;
 567
 568        /*
 569         * Since there's no place to hold device registration code and no
 570         * device tree based way to match cpufreq driver yet, both the driver
 571         * and the device registration codes are put here to handle defer
 572         * probing.
 573         */
 574        pdev = platform_device_register_simple("mtk-cpufreq", -1, NULL, 0);
 575        if (IS_ERR(pdev)) {
 576                pr_err("failed to register mtk-cpufreq platform device\n");
 577                platform_driver_unregister(&mtk_cpufreq_platdrv);
 578                return PTR_ERR(pdev);
 579        }
 580
 581        return 0;
 582}
 583device_initcall(mtk_cpufreq_driver_init);
 584
 585MODULE_DESCRIPTION("MediaTek CPUFreq driver");
 586MODULE_AUTHOR("Pi-Cheng Chen <pi-cheng.chen@linaro.org>");
 587MODULE_LICENSE("GPL v2");
 588