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