root/drivers/devfreq/exynos-bus.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. exynos_bus_get_event
  2. exynos_bus_target
  3. exynos_bus_get_dev_status
  4. exynos_bus_exit
  5. exynos_bus_passive_exit
  6. exynos_bus_parent_parse_of
  7. exynos_bus_parse_of
  8. exynos_bus_probe
  9. exynos_bus_shutdown
  10. exynos_bus_resume
  11. exynos_bus_suspend

   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_device.h>
  19 #include <linux/pm_opp.h>
  20 #include <linux/platform_device.h>
  21 #include <linux/regulator/consumer.h>
  22 #include <linux/slab.h>
  23 
  24 #define DEFAULT_SATURATION_RATIO        40
  25 
  26 struct exynos_bus {
  27         struct device *dev;
  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)                                \
  45 static 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 }
  59 exynos_bus_ops_edev(enable_edev);
  60 exynos_bus_ops_edev(disable_edev);
  61 exynos_bus_ops_edev(set_event);
  62 
  63 static 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  */
  93 static 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 
 119 static 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                 stat->total_time = stat->busy_time = 0;
 131                 goto err;
 132         }
 133 
 134         stat->busy_time = (edata.load_count * 100) / bus->ratio;
 135         stat->total_time = edata.total_count;
 136 
 137         dev_dbg(dev, "Usage of devfreq-event : %lu/%lu\n", stat->busy_time,
 138                                                         stat->total_time);
 139 
 140 err:
 141         ret = exynos_bus_set_event(bus);
 142         if (ret < 0) {
 143                 dev_err(dev, "failed to set event to devfreq-event devices\n");
 144                 return ret;
 145         }
 146 
 147         return ret;
 148 }
 149 
 150 static void exynos_bus_exit(struct device *dev)
 151 {
 152         struct exynos_bus *bus = dev_get_drvdata(dev);
 153         int ret;
 154 
 155         ret = exynos_bus_disable_edev(bus);
 156         if (ret < 0)
 157                 dev_warn(dev, "failed to disable the devfreq-event devices\n");
 158 
 159         dev_pm_opp_of_remove_table(dev);
 160         clk_disable_unprepare(bus->clk);
 161         if (bus->opp_table) {
 162                 dev_pm_opp_put_regulators(bus->opp_table);
 163                 bus->opp_table = NULL;
 164         }
 165 }
 166 
 167 static void exynos_bus_passive_exit(struct device *dev)
 168 {
 169         struct exynos_bus *bus = dev_get_drvdata(dev);
 170 
 171         dev_pm_opp_of_remove_table(dev);
 172         clk_disable_unprepare(bus->clk);
 173 }
 174 
 175 static int exynos_bus_parent_parse_of(struct device_node *np,
 176                                         struct exynos_bus *bus)
 177 {
 178         struct device *dev = bus->dev;
 179         struct opp_table *opp_table;
 180         const char *vdd = "vdd";
 181         int i, ret, count, size;
 182 
 183         opp_table = dev_pm_opp_set_regulators(dev, &vdd, 1);
 184         if (IS_ERR(opp_table)) {
 185                 ret = PTR_ERR(opp_table);
 186                 dev_err(dev, "failed to set regulators %d\n", ret);
 187                 return ret;
 188         }
 189 
 190         bus->opp_table = opp_table;
 191 
 192         /*
 193          * Get the devfreq-event devices to get the current utilization of
 194          * buses. This raw data will be used in devfreq ondemand governor.
 195          */
 196         count = devfreq_event_get_edev_count(dev);
 197         if (count < 0) {
 198                 dev_err(dev, "failed to get the count of devfreq-event dev\n");
 199                 ret = count;
 200                 goto err_regulator;
 201         }
 202         bus->edev_count = count;
 203 
 204         size = sizeof(*bus->edev) * count;
 205         bus->edev = devm_kzalloc(dev, size, GFP_KERNEL);
 206         if (!bus->edev) {
 207                 ret = -ENOMEM;
 208                 goto err_regulator;
 209         }
 210 
 211         for (i = 0; i < count; i++) {
 212                 bus->edev[i] = devfreq_event_get_edev_by_phandle(dev, i);
 213                 if (IS_ERR(bus->edev[i])) {
 214                         ret = -EPROBE_DEFER;
 215                         goto err_regulator;
 216                 }
 217         }
 218 
 219         /*
 220          * Optionally, Get the saturation ratio according to Exynos SoC
 221          * When measuring the utilization of each AXI bus with devfreq-event
 222          * devices, the measured real cycle might be much lower than the
 223          * total cycle of bus during sampling rate. In result, the devfreq
 224          * simple-ondemand governor might not decide to change the current
 225          * frequency due to too utilization (= real cycle/total cycle).
 226          * So, this property is used to adjust the utilization when calculating
 227          * the busy_time in exynos_bus_get_dev_status().
 228          */
 229         if (of_property_read_u32(np, "exynos,saturation-ratio", &bus->ratio))
 230                 bus->ratio = DEFAULT_SATURATION_RATIO;
 231 
 232         return 0;
 233 
 234 err_regulator:
 235         dev_pm_opp_put_regulators(bus->opp_table);
 236         bus->opp_table = NULL;
 237 
 238         return ret;
 239 }
 240 
 241 static int exynos_bus_parse_of(struct device_node *np,
 242                               struct exynos_bus *bus)
 243 {
 244         struct device *dev = bus->dev;
 245         struct dev_pm_opp *opp;
 246         unsigned long rate;
 247         int ret;
 248 
 249         /* Get the clock to provide each bus with source clock */
 250         bus->clk = devm_clk_get(dev, "bus");
 251         if (IS_ERR(bus->clk)) {
 252                 dev_err(dev, "failed to get bus clock\n");
 253                 return PTR_ERR(bus->clk);
 254         }
 255 
 256         ret = clk_prepare_enable(bus->clk);
 257         if (ret < 0) {
 258                 dev_err(dev, "failed to get enable clock\n");
 259                 return ret;
 260         }
 261 
 262         /* Get the freq and voltage from OPP table to scale the bus freq */
 263         ret = dev_pm_opp_of_add_table(dev);
 264         if (ret < 0) {
 265                 dev_err(dev, "failed to get OPP table\n");
 266                 goto err_clk;
 267         }
 268 
 269         rate = clk_get_rate(bus->clk);
 270 
 271         opp = devfreq_recommended_opp(dev, &rate, 0);
 272         if (IS_ERR(opp)) {
 273                 dev_err(dev, "failed to find dev_pm_opp\n");
 274                 ret = PTR_ERR(opp);
 275                 goto err_opp;
 276         }
 277         bus->curr_freq = dev_pm_opp_get_freq(opp);
 278         dev_pm_opp_put(opp);
 279 
 280         return 0;
 281 
 282 err_opp:
 283         dev_pm_opp_of_remove_table(dev);
 284 err_clk:
 285         clk_disable_unprepare(bus->clk);
 286 
 287         return ret;
 288 }
 289 
 290 static int exynos_bus_probe(struct platform_device *pdev)
 291 {
 292         struct device *dev = &pdev->dev;
 293         struct device_node *np = dev->of_node, *node;
 294         struct devfreq_dev_profile *profile;
 295         struct devfreq_simple_ondemand_data *ondemand_data;
 296         struct devfreq_passive_data *passive_data;
 297         struct devfreq *parent_devfreq;
 298         struct exynos_bus *bus;
 299         int ret, max_state;
 300         unsigned long min_freq, max_freq;
 301         bool passive = false;
 302 
 303         if (!np) {
 304                 dev_err(dev, "failed to find devicetree node\n");
 305                 return -EINVAL;
 306         }
 307 
 308         bus = devm_kzalloc(&pdev->dev, sizeof(*bus), GFP_KERNEL);
 309         if (!bus)
 310                 return -ENOMEM;
 311         mutex_init(&bus->lock);
 312         bus->dev = &pdev->dev;
 313         platform_set_drvdata(pdev, bus);
 314 
 315         profile = devm_kzalloc(dev, sizeof(*profile), GFP_KERNEL);
 316         if (!profile)
 317                 return -ENOMEM;
 318 
 319         node = of_parse_phandle(dev->of_node, "devfreq", 0);
 320         if (node) {
 321                 of_node_put(node);
 322                 passive = true;
 323         } else {
 324                 ret = exynos_bus_parent_parse_of(np, bus);
 325                 if (ret < 0)
 326                         return ret;
 327         }
 328 
 329         /* Parse the device-tree to get the resource information */
 330         ret = exynos_bus_parse_of(np, bus);
 331         if (ret < 0)
 332                 goto err_reg;
 333 
 334         if (passive)
 335                 goto passive;
 336 
 337         /* Initialize the struct profile and governor data for parent device */
 338         profile->polling_ms = 50;
 339         profile->target = exynos_bus_target;
 340         profile->get_dev_status = exynos_bus_get_dev_status;
 341         profile->exit = exynos_bus_exit;
 342 
 343         ondemand_data = devm_kzalloc(dev, sizeof(*ondemand_data), GFP_KERNEL);
 344         if (!ondemand_data) {
 345                 ret = -ENOMEM;
 346                 goto err;
 347         }
 348         ondemand_data->upthreshold = 40;
 349         ondemand_data->downdifferential = 5;
 350 
 351         /* Add devfreq device to monitor and handle the exynos bus */
 352         bus->devfreq = devm_devfreq_add_device(dev, profile,
 353                                                 DEVFREQ_GOV_SIMPLE_ONDEMAND,
 354                                                 ondemand_data);
 355         if (IS_ERR(bus->devfreq)) {
 356                 dev_err(dev, "failed to add devfreq device\n");
 357                 ret = PTR_ERR(bus->devfreq);
 358                 goto err;
 359         }
 360 
 361         /* Register opp_notifier to catch the change of OPP  */
 362         ret = devm_devfreq_register_opp_notifier(dev, bus->devfreq);
 363         if (ret < 0) {
 364                 dev_err(dev, "failed to register opp notifier\n");
 365                 goto err;
 366         }
 367 
 368         /*
 369          * Enable devfreq-event to get raw data which is used to determine
 370          * current bus load.
 371          */
 372         ret = exynos_bus_enable_edev(bus);
 373         if (ret < 0) {
 374                 dev_err(dev, "failed to enable devfreq-event devices\n");
 375                 goto err;
 376         }
 377 
 378         ret = exynos_bus_set_event(bus);
 379         if (ret < 0) {
 380                 dev_err(dev, "failed to set event to devfreq-event devices\n");
 381                 goto err;
 382         }
 383 
 384         goto out;
 385 passive:
 386         /* Initialize the struct profile and governor data for passive device */
 387         profile->target = exynos_bus_target;
 388         profile->exit = exynos_bus_passive_exit;
 389 
 390         /* Get the instance of parent devfreq device */
 391         parent_devfreq = devfreq_get_devfreq_by_phandle(dev, 0);
 392         if (IS_ERR(parent_devfreq)) {
 393                 ret = -EPROBE_DEFER;
 394                 goto err;
 395         }
 396 
 397         passive_data = devm_kzalloc(dev, sizeof(*passive_data), GFP_KERNEL);
 398         if (!passive_data) {
 399                 ret = -ENOMEM;
 400                 goto err;
 401         }
 402         passive_data->parent = parent_devfreq;
 403 
 404         /* Add devfreq device for exynos bus with passive governor */
 405         bus->devfreq = devm_devfreq_add_device(dev, profile, DEVFREQ_GOV_PASSIVE,
 406                                                 passive_data);
 407         if (IS_ERR(bus->devfreq)) {
 408                 dev_err(dev,
 409                         "failed to add devfreq dev with passive governor\n");
 410                 ret = PTR_ERR(bus->devfreq);
 411                 goto err;
 412         }
 413 
 414 out:
 415         max_state = bus->devfreq->profile->max_state;
 416         min_freq = (bus->devfreq->profile->freq_table[0] / 1000);
 417         max_freq = (bus->devfreq->profile->freq_table[max_state - 1] / 1000);
 418         pr_info("exynos-bus: new bus device registered: %s (%6ld KHz ~ %6ld KHz)\n",
 419                         dev_name(dev), min_freq, max_freq);
 420 
 421         return 0;
 422 
 423 err:
 424         dev_pm_opp_of_remove_table(dev);
 425         clk_disable_unprepare(bus->clk);
 426 err_reg:
 427         if (!passive) {
 428                 dev_pm_opp_put_regulators(bus->opp_table);
 429                 bus->opp_table = NULL;
 430         }
 431 
 432         return ret;
 433 }
 434 
 435 static void exynos_bus_shutdown(struct platform_device *pdev)
 436 {
 437         struct exynos_bus *bus = dev_get_drvdata(&pdev->dev);
 438 
 439         devfreq_suspend_device(bus->devfreq);
 440 }
 441 
 442 #ifdef CONFIG_PM_SLEEP
 443 static int exynos_bus_resume(struct device *dev)
 444 {
 445         struct exynos_bus *bus = dev_get_drvdata(dev);
 446         int ret;
 447 
 448         ret = exynos_bus_enable_edev(bus);
 449         if (ret < 0) {
 450                 dev_err(dev, "failed to enable the devfreq-event devices\n");
 451                 return ret;
 452         }
 453 
 454         return 0;
 455 }
 456 
 457 static int exynos_bus_suspend(struct device *dev)
 458 {
 459         struct exynos_bus *bus = dev_get_drvdata(dev);
 460         int ret;
 461 
 462         ret = exynos_bus_disable_edev(bus);
 463         if (ret < 0) {
 464                 dev_err(dev, "failed to disable the devfreq-event devices\n");
 465                 return ret;
 466         }
 467 
 468         return 0;
 469 }
 470 #endif
 471 
 472 static const struct dev_pm_ops exynos_bus_pm = {
 473         SET_SYSTEM_SLEEP_PM_OPS(exynos_bus_suspend, exynos_bus_resume)
 474 };
 475 
 476 static const struct of_device_id exynos_bus_of_match[] = {
 477         { .compatible = "samsung,exynos-bus", },
 478         { /* sentinel */ },
 479 };
 480 MODULE_DEVICE_TABLE(of, exynos_bus_of_match);
 481 
 482 static struct platform_driver exynos_bus_platdrv = {
 483         .probe          = exynos_bus_probe,
 484         .shutdown       = exynos_bus_shutdown,
 485         .driver = {
 486                 .name   = "exynos-bus",
 487                 .pm     = &exynos_bus_pm,
 488                 .of_match_table = of_match_ptr(exynos_bus_of_match),
 489         },
 490 };
 491 module_platform_driver(exynos_bus_platdrv);
 492 
 493 MODULE_DESCRIPTION("Generic Exynos Bus frequency driver");
 494 MODULE_AUTHOR("Chanwoo Choi <cw00.choi@samsung.com>");
 495 MODULE_LICENSE("GPL v2");

/* [<][>][^][v][top][bottom][index][help] */