linux/drivers/devfreq/exynos-bus.c
<<
>>
Prefs
   1/*
   2 * Generic Exynos Bus frequency driver with DEVFREQ Framework
   3 *
   4 * Copyright (c) 2016 Samsung Electronics Co., Ltd.
   5 * Author : Chanwoo Choi <cw00.choi@samsung.com>
   6 *
   7 * This driver support Exynos Bus frequency feature by using
   8 * DEVFREQ framework and is based on drivers/devfreq/exynos/exynos4_bus.c.
   9 *
  10 * This program is free software; you can redistribute it and/or modify
  11 * it under the terms of the GNU General Public License version 2 as
  12 * published by the Free Software Foundation.
  13 */
  14
  15#include <linux/clk.h>
  16#include <linux/devfreq.h>
  17#include <linux/devfreq-event.h>
  18#include <linux/device.h>
  19#include <linux/export.h>
  20#include <linux/module.h>
  21#include <linux/of_device.h>
  22#include <linux/pm_opp.h>
  23#include <linux/platform_device.h>
  24#include <linux/regulator/consumer.h>
  25#include <linux/slab.h>
  26
  27#define DEFAULT_SATURATION_RATIO        40
  28#define DEFAULT_VOLTAGE_TOLERANCE       2
  29
  30struct exynos_bus {
  31        struct device *dev;
  32
  33        struct devfreq *devfreq;
  34        struct devfreq_event_dev **edev;
  35        unsigned int edev_count;
  36        struct mutex lock;
  37
  38        unsigned long curr_freq;
  39
  40        struct regulator *regulator;
  41        struct clk *clk;
  42        unsigned int voltage_tolerance;
  43        unsigned int ratio;
  44};
  45
  46/*
  47 * Control the devfreq-event device to get the current state of bus
  48 */
  49#define exynos_bus_ops_edev(ops)                                \
  50static int exynos_bus_##ops(struct exynos_bus *bus)             \
  51{                                                               \
  52        int i, ret;                                             \
  53                                                                \
  54        for (i = 0; i < bus->edev_count; i++) {                 \
  55                if (!bus->edev[i])                              \
  56                        continue;                               \
  57                ret = devfreq_event_##ops(bus->edev[i]);        \
  58                if (ret < 0)                                    \
  59                        return ret;                             \
  60        }                                                       \
  61                                                                \
  62        return 0;                                               \
  63}
  64exynos_bus_ops_edev(enable_edev);
  65exynos_bus_ops_edev(disable_edev);
  66exynos_bus_ops_edev(set_event);
  67
  68static int exynos_bus_get_event(struct exynos_bus *bus,
  69                                struct devfreq_event_data *edata)
  70{
  71        struct devfreq_event_data event_data;
  72        unsigned long load_count = 0, total_count = 0;
  73        int i, ret = 0;
  74
  75        for (i = 0; i < bus->edev_count; i++) {
  76                if (!bus->edev[i])
  77                        continue;
  78
  79                ret = devfreq_event_get_event(bus->edev[i], &event_data);
  80                if (ret < 0)
  81                        return ret;
  82
  83                if (i == 0 || event_data.load_count > load_count) {
  84                        load_count = event_data.load_count;
  85                        total_count = event_data.total_count;
  86                }
  87        }
  88
  89        edata->load_count = load_count;
  90        edata->total_count = total_count;
  91
  92        return ret;
  93}
  94
  95/*
  96 * Must necessary function for devfreq simple-ondemand governor
  97 */
  98static int exynos_bus_target(struct device *dev, unsigned long *freq, u32 flags)
  99{
 100        struct exynos_bus *bus = dev_get_drvdata(dev);
 101        struct dev_pm_opp *new_opp;
 102        unsigned long old_freq, new_freq, new_volt, tol;
 103        int ret = 0;
 104
 105        /* Get new opp-bus instance according to new bus clock */
 106        new_opp = devfreq_recommended_opp(dev, freq, flags);
 107        if (IS_ERR(new_opp)) {
 108                dev_err(dev, "failed to get recommended opp instance\n");
 109                return PTR_ERR(new_opp);
 110        }
 111
 112        new_freq = dev_pm_opp_get_freq(new_opp);
 113        new_volt = dev_pm_opp_get_voltage(new_opp);
 114        dev_pm_opp_put(new_opp);
 115
 116        old_freq = bus->curr_freq;
 117
 118        if (old_freq == new_freq)
 119                return 0;
 120        tol = new_volt * bus->voltage_tolerance / 100;
 121
 122        /* Change voltage and frequency according to new OPP level */
 123        mutex_lock(&bus->lock);
 124
 125        if (old_freq < new_freq) {
 126                ret = regulator_set_voltage_tol(bus->regulator, new_volt, tol);
 127                if (ret < 0) {
 128                        dev_err(bus->dev, "failed to set voltage\n");
 129                        goto out;
 130                }
 131        }
 132
 133        ret = clk_set_rate(bus->clk, new_freq);
 134        if (ret < 0) {
 135                dev_err(dev, "failed to change clock of bus\n");
 136                clk_set_rate(bus->clk, old_freq);
 137                goto out;
 138        }
 139
 140        if (old_freq > new_freq) {
 141                ret = regulator_set_voltage_tol(bus->regulator, new_volt, tol);
 142                if (ret < 0) {
 143                        dev_err(bus->dev, "failed to set voltage\n");
 144                        goto out;
 145                }
 146        }
 147        bus->curr_freq = new_freq;
 148
 149        dev_dbg(dev, "Set the frequency of bus (%luHz -> %luHz, %luHz)\n",
 150                        old_freq, new_freq, clk_get_rate(bus->clk));
 151out:
 152        mutex_unlock(&bus->lock);
 153
 154        return ret;
 155}
 156
 157static int exynos_bus_get_dev_status(struct device *dev,
 158                                     struct devfreq_dev_status *stat)
 159{
 160        struct exynos_bus *bus = dev_get_drvdata(dev);
 161        struct devfreq_event_data edata;
 162        int ret;
 163
 164        stat->current_frequency = bus->curr_freq;
 165
 166        ret = exynos_bus_get_event(bus, &edata);
 167        if (ret < 0) {
 168                stat->total_time = stat->busy_time = 0;
 169                goto err;
 170        }
 171
 172        stat->busy_time = (edata.load_count * 100) / bus->ratio;
 173        stat->total_time = edata.total_count;
 174
 175        dev_dbg(dev, "Usage of devfreq-event : %lu/%lu\n", stat->busy_time,
 176                                                        stat->total_time);
 177
 178err:
 179        ret = exynos_bus_set_event(bus);
 180        if (ret < 0) {
 181                dev_err(dev, "failed to set event to devfreq-event devices\n");
 182                return ret;
 183        }
 184
 185        return ret;
 186}
 187
 188static void exynos_bus_exit(struct device *dev)
 189{
 190        struct exynos_bus *bus = dev_get_drvdata(dev);
 191        int ret;
 192
 193        ret = exynos_bus_disable_edev(bus);
 194        if (ret < 0)
 195                dev_warn(dev, "failed to disable the devfreq-event devices\n");
 196
 197        if (bus->regulator)
 198                regulator_disable(bus->regulator);
 199
 200        dev_pm_opp_of_remove_table(dev);
 201        clk_disable_unprepare(bus->clk);
 202}
 203
 204/*
 205 * Must necessary function for devfreq passive governor
 206 */
 207static int exynos_bus_passive_target(struct device *dev, unsigned long *freq,
 208                                        u32 flags)
 209{
 210        struct exynos_bus *bus = dev_get_drvdata(dev);
 211        struct dev_pm_opp *new_opp;
 212        unsigned long old_freq, new_freq;
 213        int ret = 0;
 214
 215        /* Get new opp-bus instance according to new bus clock */
 216        new_opp = devfreq_recommended_opp(dev, freq, flags);
 217        if (IS_ERR(new_opp)) {
 218                dev_err(dev, "failed to get recommended opp instance\n");
 219                return PTR_ERR(new_opp);
 220        }
 221
 222        new_freq = dev_pm_opp_get_freq(new_opp);
 223        dev_pm_opp_put(new_opp);
 224
 225        old_freq = bus->curr_freq;
 226
 227        if (old_freq == new_freq)
 228                return 0;
 229
 230        /* Change the frequency according to new OPP level */
 231        mutex_lock(&bus->lock);
 232
 233        ret = clk_set_rate(bus->clk, new_freq);
 234        if (ret < 0) {
 235                dev_err(dev, "failed to set the clock of bus\n");
 236                goto out;
 237        }
 238
 239        *freq = new_freq;
 240        bus->curr_freq = new_freq;
 241
 242        dev_dbg(dev, "Set the frequency of bus (%luHz -> %luHz, %luHz)\n",
 243                        old_freq, new_freq, clk_get_rate(bus->clk));
 244out:
 245        mutex_unlock(&bus->lock);
 246
 247        return ret;
 248}
 249
 250static void exynos_bus_passive_exit(struct device *dev)
 251{
 252        struct exynos_bus *bus = dev_get_drvdata(dev);
 253
 254        dev_pm_opp_of_remove_table(dev);
 255        clk_disable_unprepare(bus->clk);
 256}
 257
 258static int exynos_bus_parent_parse_of(struct device_node *np,
 259                                        struct exynos_bus *bus)
 260{
 261        struct device *dev = bus->dev;
 262        int i, ret, count, size;
 263
 264        /* Get the regulator to provide each bus with the power */
 265        bus->regulator = devm_regulator_get(dev, "vdd");
 266        if (IS_ERR(bus->regulator)) {
 267                dev_err(dev, "failed to get VDD regulator\n");
 268                return PTR_ERR(bus->regulator);
 269        }
 270
 271        ret = regulator_enable(bus->regulator);
 272        if (ret < 0) {
 273                dev_err(dev, "failed to enable VDD regulator\n");
 274                return ret;
 275        }
 276
 277        /*
 278         * Get the devfreq-event devices to get the current utilization of
 279         * buses. This raw data will be used in devfreq ondemand governor.
 280         */
 281        count = devfreq_event_get_edev_count(dev);
 282        if (count < 0) {
 283                dev_err(dev, "failed to get the count of devfreq-event dev\n");
 284                ret = count;
 285                goto err_regulator;
 286        }
 287        bus->edev_count = count;
 288
 289        size = sizeof(*bus->edev) * count;
 290        bus->edev = devm_kzalloc(dev, size, GFP_KERNEL);
 291        if (!bus->edev) {
 292                ret = -ENOMEM;
 293                goto err_regulator;
 294        }
 295
 296        for (i = 0; i < count; i++) {
 297                bus->edev[i] = devfreq_event_get_edev_by_phandle(dev, i);
 298                if (IS_ERR(bus->edev[i])) {
 299                        ret = -EPROBE_DEFER;
 300                        goto err_regulator;
 301                }
 302        }
 303
 304        /*
 305         * Optionally, Get the saturation ratio according to Exynos SoC
 306         * When measuring the utilization of each AXI bus with devfreq-event
 307         * devices, the measured real cycle might be much lower than the
 308         * total cycle of bus during sampling rate. In result, the devfreq
 309         * simple-ondemand governor might not decide to change the current
 310         * frequency due to too utilization (= real cycle/total cycle).
 311         * So, this property is used to adjust the utilization when calculating
 312         * the busy_time in exynos_bus_get_dev_status().
 313         */
 314        if (of_property_read_u32(np, "exynos,saturation-ratio", &bus->ratio))
 315                bus->ratio = DEFAULT_SATURATION_RATIO;
 316
 317        if (of_property_read_u32(np, "exynos,voltage-tolerance",
 318                                        &bus->voltage_tolerance))
 319                bus->voltage_tolerance = DEFAULT_VOLTAGE_TOLERANCE;
 320
 321        return 0;
 322
 323err_regulator:
 324        regulator_disable(bus->regulator);
 325
 326        return ret;
 327}
 328
 329static int exynos_bus_parse_of(struct device_node *np,
 330                              struct exynos_bus *bus)
 331{
 332        struct device *dev = bus->dev;
 333        struct dev_pm_opp *opp;
 334        unsigned long rate;
 335        int ret;
 336
 337        /* Get the clock to provide each bus with source clock */
 338        bus->clk = devm_clk_get(dev, "bus");
 339        if (IS_ERR(bus->clk)) {
 340                dev_err(dev, "failed to get bus clock\n");
 341                return PTR_ERR(bus->clk);
 342        }
 343
 344        ret = clk_prepare_enable(bus->clk);
 345        if (ret < 0) {
 346                dev_err(dev, "failed to get enable clock\n");
 347                return ret;
 348        }
 349
 350        /* Get the freq and voltage from OPP table to scale the bus freq */
 351        ret = dev_pm_opp_of_add_table(dev);
 352        if (ret < 0) {
 353                dev_err(dev, "failed to get OPP table\n");
 354                goto err_clk;
 355        }
 356
 357        rate = clk_get_rate(bus->clk);
 358
 359        opp = devfreq_recommended_opp(dev, &rate, 0);
 360        if (IS_ERR(opp)) {
 361                dev_err(dev, "failed to find dev_pm_opp\n");
 362                ret = PTR_ERR(opp);
 363                goto err_opp;
 364        }
 365        bus->curr_freq = dev_pm_opp_get_freq(opp);
 366        dev_pm_opp_put(opp);
 367
 368        return 0;
 369
 370err_opp:
 371        dev_pm_opp_of_remove_table(dev);
 372err_clk:
 373        clk_disable_unprepare(bus->clk);
 374
 375        return ret;
 376}
 377
 378static int exynos_bus_probe(struct platform_device *pdev)
 379{
 380        struct device *dev = &pdev->dev;
 381        struct device_node *np = dev->of_node, *node;
 382        struct devfreq_dev_profile *profile;
 383        struct devfreq_simple_ondemand_data *ondemand_data;
 384        struct devfreq_passive_data *passive_data;
 385        struct devfreq *parent_devfreq;
 386        struct exynos_bus *bus;
 387        int ret, max_state;
 388        unsigned long min_freq, max_freq;
 389
 390        if (!np) {
 391                dev_err(dev, "failed to find devicetree node\n");
 392                return -EINVAL;
 393        }
 394
 395        bus = devm_kzalloc(&pdev->dev, sizeof(*bus), GFP_KERNEL);
 396        if (!bus)
 397                return -ENOMEM;
 398        mutex_init(&bus->lock);
 399        bus->dev = &pdev->dev;
 400        platform_set_drvdata(pdev, bus);
 401
 402        /* Parse the device-tree to get the resource information */
 403        ret = exynos_bus_parse_of(np, bus);
 404        if (ret < 0)
 405                return ret;
 406
 407        profile = devm_kzalloc(dev, sizeof(*profile), GFP_KERNEL);
 408        if (!profile) {
 409                ret = -ENOMEM;
 410                goto err;
 411        }
 412
 413        node = of_parse_phandle(dev->of_node, "devfreq", 0);
 414        if (node) {
 415                of_node_put(node);
 416                goto passive;
 417        } else {
 418                ret = exynos_bus_parent_parse_of(np, bus);
 419        }
 420
 421        if (ret < 0)
 422                goto err;
 423
 424        /* Initialize the struct profile and governor data for parent device */
 425        profile->polling_ms = 50;
 426        profile->target = exynos_bus_target;
 427        profile->get_dev_status = exynos_bus_get_dev_status;
 428        profile->exit = exynos_bus_exit;
 429
 430        ondemand_data = devm_kzalloc(dev, sizeof(*ondemand_data), GFP_KERNEL);
 431        if (!ondemand_data) {
 432                ret = -ENOMEM;
 433                goto err;
 434        }
 435        ondemand_data->upthreshold = 40;
 436        ondemand_data->downdifferential = 5;
 437
 438        /* Add devfreq device to monitor and handle the exynos bus */
 439        bus->devfreq = devm_devfreq_add_device(dev, profile,
 440                                                DEVFREQ_GOV_SIMPLE_ONDEMAND,
 441                                                ondemand_data);
 442        if (IS_ERR(bus->devfreq)) {
 443                dev_err(dev, "failed to add devfreq device\n");
 444                ret = PTR_ERR(bus->devfreq);
 445                goto err;
 446        }
 447
 448        /* Register opp_notifier to catch the change of OPP  */
 449        ret = devm_devfreq_register_opp_notifier(dev, bus->devfreq);
 450        if (ret < 0) {
 451                dev_err(dev, "failed to register opp notifier\n");
 452                goto err;
 453        }
 454
 455        /*
 456         * Enable devfreq-event to get raw data which is used to determine
 457         * current bus load.
 458         */
 459        ret = exynos_bus_enable_edev(bus);
 460        if (ret < 0) {
 461                dev_err(dev, "failed to enable devfreq-event devices\n");
 462                goto err;
 463        }
 464
 465        ret = exynos_bus_set_event(bus);
 466        if (ret < 0) {
 467                dev_err(dev, "failed to set event to devfreq-event devices\n");
 468                goto err;
 469        }
 470
 471        goto out;
 472passive:
 473        /* Initialize the struct profile and governor data for passive device */
 474        profile->target = exynos_bus_passive_target;
 475        profile->exit = exynos_bus_passive_exit;
 476
 477        /* Get the instance of parent devfreq device */
 478        parent_devfreq = devfreq_get_devfreq_by_phandle(dev, 0);
 479        if (IS_ERR(parent_devfreq)) {
 480                ret = -EPROBE_DEFER;
 481                goto err;
 482        }
 483
 484        passive_data = devm_kzalloc(dev, sizeof(*passive_data), GFP_KERNEL);
 485        if (!passive_data) {
 486                ret = -ENOMEM;
 487                goto err;
 488        }
 489        passive_data->parent = parent_devfreq;
 490
 491        /* Add devfreq device for exynos bus with passive governor */
 492        bus->devfreq = devm_devfreq_add_device(dev, profile, DEVFREQ_GOV_PASSIVE,
 493                                                passive_data);
 494        if (IS_ERR(bus->devfreq)) {
 495                dev_err(dev,
 496                        "failed to add devfreq dev with passive governor\n");
 497                ret = PTR_ERR(bus->devfreq);
 498                goto err;
 499        }
 500
 501out:
 502        max_state = bus->devfreq->profile->max_state;
 503        min_freq = (bus->devfreq->profile->freq_table[0] / 1000);
 504        max_freq = (bus->devfreq->profile->freq_table[max_state - 1] / 1000);
 505        pr_info("exynos-bus: new bus device registered: %s (%6ld KHz ~ %6ld KHz)\n",
 506                        dev_name(dev), min_freq, max_freq);
 507
 508        return 0;
 509
 510err:
 511        dev_pm_opp_of_remove_table(dev);
 512        clk_disable_unprepare(bus->clk);
 513
 514        return ret;
 515}
 516
 517#ifdef CONFIG_PM_SLEEP
 518static int exynos_bus_resume(struct device *dev)
 519{
 520        struct exynos_bus *bus = dev_get_drvdata(dev);
 521        int ret;
 522
 523        ret = exynos_bus_enable_edev(bus);
 524        if (ret < 0) {
 525                dev_err(dev, "failed to enable the devfreq-event devices\n");
 526                return ret;
 527        }
 528
 529        return 0;
 530}
 531
 532static int exynos_bus_suspend(struct device *dev)
 533{
 534        struct exynos_bus *bus = dev_get_drvdata(dev);
 535        int ret;
 536
 537        ret = exynos_bus_disable_edev(bus);
 538        if (ret < 0) {
 539                dev_err(dev, "failed to disable the devfreq-event devices\n");
 540                return ret;
 541        }
 542
 543        return 0;
 544}
 545#endif
 546
 547static const struct dev_pm_ops exynos_bus_pm = {
 548        SET_SYSTEM_SLEEP_PM_OPS(exynos_bus_suspend, exynos_bus_resume)
 549};
 550
 551static const struct of_device_id exynos_bus_of_match[] = {
 552        { .compatible = "samsung,exynos-bus", },
 553        { /* sentinel */ },
 554};
 555MODULE_DEVICE_TABLE(of, exynos_bus_of_match);
 556
 557static struct platform_driver exynos_bus_platdrv = {
 558        .probe          = exynos_bus_probe,
 559        .driver = {
 560                .name   = "exynos-bus",
 561                .pm     = &exynos_bus_pm,
 562                .of_match_table = of_match_ptr(exynos_bus_of_match),
 563        },
 564};
 565module_platform_driver(exynos_bus_platdrv);
 566
 567MODULE_DESCRIPTION("Generic Exynos Bus frequency driver");
 568MODULE_AUTHOR("Chanwoo Choi <cw00.choi@samsung.com>");
 569MODULE_LICENSE("GPL v2");
 570