| 1 | |
| 2 | * A devfreq driver for NVIDIA Tegra SoCs
|
| 3 | *
|
| 4 | * Copyright (c) 2014 NVIDIA CORPORATION. All rights reserved.
|
| 5 | * Copyright (C) 2014 Google, Inc
|
| 6 | *
|
| 7 | * This program is free software; you can redistribute it and/or modify it
|
| 8 | * under the terms and conditions of the GNU General Public License,
|
| 9 | * version 2, as published by the Free Software Foundation.
|
| 10 | *
|
| 11 | * This program is distributed in the hope it will be useful, but WITHOUT
|
| 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
| 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
| 14 | * more details.
|
| 15 | *
|
| 16 | * You should have received a copy of the GNU General Public License
|
| 17 | * along with this program. If not, see <http://www.gnu.org/licenses/>.
|
| 18 | *
|
| 19 |
|
| 20 |
|
| 21 | #include <linux/clk.h>
|
| 22 | #include <linux/cpufreq.h>
|
| 23 | #include <linux/devfreq.h>
|
| 24 | #include <linux/interrupt.h>
|
| 25 | #include <linux/io.h>
|
| 26 | #include <linux/module.h>
|
| 27 | #include <linux/platform_device.h>
|
| 28 | #include <linux/pm_opp.h>
|
| 29 | #include <linux/reset.h>
|
| 30 |
|
| 31 | #include "governor.h"
|
| 32 |
|
| 33 | #define ACTMON_GLB_STATUS 0x0
|
| 34 | #define ACTMON_GLB_PERIOD_CTRL 0x4
|
| 35 |
|
| 36 | #define ACTMON_DEV_CTRL 0x0
|
| 37 | #define ACTMON_DEV_CTRL_K_VAL_SHIFT 10
|
| 38 | #define ACTMON_DEV_CTRL_ENB_PERIODIC BIT(18)
|
| 39 | #define ACTMON_DEV_CTRL_AVG_BELOW_WMARK_EN BIT(20)
|
| 40 | #define ACTMON_DEV_CTRL_AVG_ABOVE_WMARK_EN BIT(21)
|
| 41 | #define ACTMON_DEV_CTRL_CONSECUTIVE_BELOW_WMARK_NUM_SHIFT 23
|
| 42 | #define ACTMON_DEV_CTRL_CONSECUTIVE_ABOVE_WMARK_NUM_SHIFT 26
|
| 43 | #define ACTMON_DEV_CTRL_CONSECUTIVE_BELOW_WMARK_EN BIT(29)
|
| 44 | #define ACTMON_DEV_CTRL_CONSECUTIVE_ABOVE_WMARK_EN BIT(30)
|
| 45 | #define ACTMON_DEV_CTRL_ENB BIT(31)
|
| 46 |
|
| 47 | #define ACTMON_DEV_UPPER_WMARK 0x4
|
| 48 | #define ACTMON_DEV_LOWER_WMARK 0x8
|
| 49 | #define ACTMON_DEV_INIT_AVG 0xc
|
| 50 | #define ACTMON_DEV_AVG_UPPER_WMARK 0x10
|
| 51 | #define ACTMON_DEV_AVG_LOWER_WMARK 0x14
|
| 52 | #define ACTMON_DEV_COUNT_WEIGHT 0x18
|
| 53 | #define ACTMON_DEV_AVG_COUNT 0x20
|
| 54 | #define ACTMON_DEV_INTR_STATUS 0x24
|
| 55 |
|
| 56 | #define ACTMON_INTR_STATUS_CLEAR 0xffffffff
|
| 57 |
|
| 58 | #define ACTMON_DEV_INTR_CONSECUTIVE_UPPER BIT(31)
|
| 59 | #define ACTMON_DEV_INTR_CONSECUTIVE_LOWER BIT(30)
|
| 60 |
|
| 61 | #define ACTMON_ABOVE_WMARK_WINDOW 1
|
| 62 | #define ACTMON_BELOW_WMARK_WINDOW 3
|
| 63 | #define ACTMON_BOOST_FREQ_STEP 16000
|
| 64 |
|
| 65 | |
| 66 | * Activity counter is incremented every 256 memory transactions, and each
|
| 67 | * transaction takes 4 EMC clocks for Tegra124; So the COUNT_WEIGHT is
|
| 68 | * 4 * 256 = 1024.
|
| 69 |
|
| 70 | #define ACTMON_COUNT_WEIGHT 0x400
|
| 71 |
|
| 72 | |
| 73 | * ACTMON_AVERAGE_WINDOW_LOG2: default value for @DEV_CTRL_K_VAL, which
|
| 74 | * translates to 2 ^ (K_VAL + 1). ex: 2 ^ (6 + 1) = 128
|
| 75 |
|
| 76 | #define ACTMON_AVERAGE_WINDOW_LOG2 6
|
| 77 | #define ACTMON_SAMPLING_PERIOD 12
|
| 78 | #define ACTMON_DEFAULT_AVG_BAND 6
|
| 79 |
|
| 80 | #define KHZ 1000
|
| 81 |
|
| 82 |
|
| 83 | #define BUS_SATURATION_RATIO 25
|
| 84 |
|
| 85 | |
| 86 | * struct tegra_devfreq_device_config - configuration specific to an ACTMON
|
| 87 | * device
|
| 88 | *
|
| 89 | * Coefficients and thresholds are percentages unless otherwise noted
|
| 90 |
|
| 91 | struct tegra_devfreq_device_config {
|
| 92 | u32 offset;
|
| 93 | u32 irq_mask;
|
| 94 |
|
| 95 |
|
| 96 | unsigned int boost_up_coeff;
|
| 97 | unsigned int boost_down_coeff;
|
| 98 |
|
| 99 |
|
| 100 | unsigned int boost_up_threshold;
|
| 101 | unsigned int boost_down_threshold;
|
| 102 |
|
| 103 | |
| 104 | * Threshold of activity (cycles) below which the CPU frequency isn't
|
| 105 | * to be taken into account. This is to avoid increasing the EMC
|
| 106 | * frequency when the CPU is very busy but not accessing the bus often.
|
| 107 |
|
| 108 | u32 avg_dependency_threshold;
|
| 109 | };
|
| 110 |
|
| 111 | enum tegra_actmon_device {
|
| 112 | MCALL = 0,
|
| 113 | MCCPU,
|
| 114 | };
|
| 115 |
|
| 116 | static struct tegra_devfreq_device_config actmon_device_configs[] = {
|
| 117 | {
|
| 118 |
|
| 119 | .offset = 0x1c0,
|
| 120 | .irq_mask = 1 << 26,
|
| 121 | .boost_up_coeff = 200,
|
| 122 | .boost_down_coeff = 50,
|
| 123 | .boost_up_threshold = 60,
|
| 124 | .boost_down_threshold = 40,
|
| 125 | },
|
| 126 | {
|
| 127 |
|
| 128 | .offset = 0x200,
|
| 129 | .irq_mask = 1 << 25,
|
| 130 | .boost_up_coeff = 800,
|
| 131 | .boost_down_coeff = 90,
|
| 132 | .boost_up_threshold = 27,
|
| 133 | .boost_down_threshold = 10,
|
| 134 | .avg_dependency_threshold = 50000,
|
| 135 | },
|
| 136 | };
|
| 137 |
|
| 138 | |
| 139 | * struct tegra_devfreq_device - state specific to an ACTMON device
|
| 140 | *
|
| 141 | * Frequencies are in kHz.
|
| 142 |
|
| 143 | struct tegra_devfreq_device {
|
| 144 | const struct tegra_devfreq_device_config *config;
|
| 145 | void __iomem *regs;
|
| 146 | spinlock_t lock;
|
| 147 |
|
| 148 |
|
| 149 | u32 avg_count;
|
| 150 |
|
| 151 | |
| 152 | * Extra frequency to increase the target by due to consecutive
|
| 153 | * watermark breaches.
|
| 154 |
|
| 155 | unsigned long boost_freq;
|
| 156 |
|
| 157 |
|
| 158 | unsigned long target_freq;
|
| 159 | };
|
| 160 |
|
| 161 | struct tegra_devfreq {
|
| 162 | struct devfreq *devfreq;
|
| 163 |
|
| 164 | struct reset_control *reset;
|
| 165 | struct clk *clock;
|
| 166 | void __iomem *regs;
|
| 167 |
|
| 168 | struct clk *emc_clock;
|
| 169 | unsigned long max_freq;
|
| 170 | unsigned long cur_freq;
|
| 171 | struct notifier_block rate_change_nb;
|
| 172 |
|
| 173 | struct tegra_devfreq_device devices[ARRAY_SIZE(actmon_device_configs)];
|
| 174 | };
|
| 175 |
|
| 176 | struct tegra_actmon_emc_ratio {
|
| 177 | unsigned long cpu_freq;
|
| 178 | unsigned long emc_freq;
|
| 179 | };
|
| 180 |
|
| 181 | static struct tegra_actmon_emc_ratio actmon_emc_ratios[] = {
|
| 182 | { 1400000, ULONG_MAX },
|
| 183 | { 1200000, 750000 },
|
| 184 | { 1100000, 600000 },
|
| 185 | { 1000000, 500000 },
|
| 186 | { 800000, 375000 },
|
| 187 | { 500000, 200000 },
|
| 188 | { 250000, 100000 },
|
| 189 | };
|
| 190 |
|
| 191 | static u32 actmon_readl(struct tegra_devfreq *tegra, u32 offset)
|
| 192 | {
|
| 193 | return readl(tegra->regs + offset);
|
| 194 | }
|
| 195 |
|
| 196 | static void actmon_writel(struct tegra_devfreq *tegra, u32 val, u32 offset)
|
| 197 | {
|
| 198 | writel(val, tegra->regs + offset);
|
| 199 | }
|
| 200 |
|
| 201 | static u32 device_readl(struct tegra_devfreq_device *dev, u32 offset)
|
| 202 | {
|
| 203 | return readl(dev->regs + offset);
|
| 204 | }
|
| 205 |
|
| 206 | static void device_writel(struct tegra_devfreq_device *dev, u32 val,
|
| 207 | u32 offset)
|
| 208 | {
|
| 209 | writel(val, dev->regs + offset);
|
| 210 | }
|
| 211 |
|
| 212 | static unsigned long do_percent(unsigned long val, unsigned int pct)
|
| 213 | {
|
| 214 | return val * pct / 100;
|
| 215 | }
|
| 216 |
|
| 217 | static void tegra_devfreq_update_avg_wmark(struct tegra_devfreq *tegra,
|
| 218 | struct tegra_devfreq_device *dev)
|
| 219 | {
|
| 220 | u32 avg = dev->avg_count;
|
| 221 | u32 avg_band_freq = tegra->max_freq * ACTMON_DEFAULT_AVG_BAND / KHZ;
|
| 222 | u32 band = avg_band_freq * ACTMON_SAMPLING_PERIOD;
|
| 223 |
|
| 224 | device_writel(dev, avg + band, ACTMON_DEV_AVG_UPPER_WMARK);
|
| 225 |
|
| 226 | avg = max(dev->avg_count, band);
|
| 227 | device_writel(dev, avg - band, ACTMON_DEV_AVG_LOWER_WMARK);
|
| 228 | }
|
| 229 |
|
| 230 | static void tegra_devfreq_update_wmark(struct tegra_devfreq *tegra,
|
| 231 | struct tegra_devfreq_device *dev)
|
| 232 | {
|
| 233 | u32 val = tegra->cur_freq * ACTMON_SAMPLING_PERIOD;
|
| 234 |
|
| 235 | device_writel(dev, do_percent(val, dev->config->boost_up_threshold),
|
| 236 | ACTMON_DEV_UPPER_WMARK);
|
| 237 |
|
| 238 | device_writel(dev, do_percent(val, dev->config->boost_down_threshold),
|
| 239 | ACTMON_DEV_LOWER_WMARK);
|
| 240 | }
|
| 241 |
|
| 242 | static void actmon_write_barrier(struct tegra_devfreq *tegra)
|
| 243 | {
|
| 244 |
|
| 245 | wmb();
|
| 246 | actmon_readl(tegra, ACTMON_GLB_STATUS);
|
| 247 | }
|
| 248 |
|
| 249 | static void actmon_isr_device(struct tegra_devfreq *tegra,
|
| 250 | struct tegra_devfreq_device *dev)
|
| 251 | {
|
| 252 | unsigned long flags;
|
| 253 | u32 intr_status, dev_ctrl;
|
| 254 |
|
| 255 | spin_lock_irqsave(&dev->lock, flags);
|
| 256 |
|
| 257 | dev->avg_count = device_readl(dev, ACTMON_DEV_AVG_COUNT);
|
| 258 | tegra_devfreq_update_avg_wmark(tegra, dev);
|
| 259 |
|
| 260 | intr_status = device_readl(dev, ACTMON_DEV_INTR_STATUS);
|
| 261 | dev_ctrl = device_readl(dev, ACTMON_DEV_CTRL);
|
| 262 |
|
| 263 | if (intr_status & ACTMON_DEV_INTR_CONSECUTIVE_UPPER) {
|
| 264 | |
| 265 | * new_boost = min(old_boost * up_coef + step, max_freq)
|
| 266 |
|
| 267 | dev->boost_freq = do_percent(dev->boost_freq,
|
| 268 | dev->config->boost_up_coeff);
|
| 269 | dev->boost_freq += ACTMON_BOOST_FREQ_STEP;
|
| 270 |
|
| 271 | dev_ctrl |= ACTMON_DEV_CTRL_CONSECUTIVE_BELOW_WMARK_EN;
|
| 272 |
|
| 273 | if (dev->boost_freq >= tegra->max_freq)
|
| 274 | dev->boost_freq = tegra->max_freq;
|
| 275 | else
|
| 276 | dev_ctrl |= ACTMON_DEV_CTRL_CONSECUTIVE_ABOVE_WMARK_EN;
|
| 277 | } else if (intr_status & ACTMON_DEV_INTR_CONSECUTIVE_LOWER) {
|
| 278 | |
| 279 | * new_boost = old_boost * down_coef
|
| 280 | * or 0 if (old_boost * down_coef < step / 2)
|
| 281 |
|
| 282 | dev->boost_freq = do_percent(dev->boost_freq,
|
| 283 | dev->config->boost_down_coeff);
|
| 284 |
|
| 285 | dev_ctrl |= ACTMON_DEV_CTRL_CONSECUTIVE_ABOVE_WMARK_EN;
|
| 286 |
|
| 287 | if (dev->boost_freq < (ACTMON_BOOST_FREQ_STEP >> 1))
|
| 288 | dev->boost_freq = 0;
|
| 289 | else
|
| 290 | dev_ctrl |= ACTMON_DEV_CTRL_CONSECUTIVE_BELOW_WMARK_EN;
|
| 291 | }
|
| 292 |
|
| 293 | if (dev->config->avg_dependency_threshold) {
|
| 294 | if (dev->avg_count >= dev->config->avg_dependency_threshold)
|
| 295 | dev_ctrl |= ACTMON_DEV_CTRL_CONSECUTIVE_BELOW_WMARK_EN;
|
| 296 | else if (dev->boost_freq == 0)
|
| 297 | dev_ctrl &= ~ACTMON_DEV_CTRL_CONSECUTIVE_BELOW_WMARK_EN;
|
| 298 | }
|
| 299 |
|
| 300 | device_writel(dev, dev_ctrl, ACTMON_DEV_CTRL);
|
| 301 |
|
| 302 | device_writel(dev, ACTMON_INTR_STATUS_CLEAR, ACTMON_DEV_INTR_STATUS);
|
| 303 |
|
| 304 | actmon_write_barrier(tegra);
|
| 305 |
|
| 306 | spin_unlock_irqrestore(&dev->lock, flags);
|
| 307 | }
|
| 308 |
|
| 309 | static irqreturn_t actmon_isr(int irq, void *data)
|
| 310 | {
|
| 311 | struct tegra_devfreq *tegra = data;
|
| 312 | bool handled = false;
|
| 313 | unsigned int i;
|
| 314 | u32 val;
|
| 315 |
|
| 316 | val = actmon_readl(tegra, ACTMON_GLB_STATUS);
|
| 317 | for (i = 0; i < ARRAY_SIZE(tegra->devices); i++) {
|
| 318 | if (val & tegra->devices[i].config->irq_mask) {
|
| 319 | actmon_isr_device(tegra, tegra->devices + i);
|
| 320 | handled = true;
|
| 321 | }
|
| 322 | }
|
| 323 |
|
| 324 | return handled ? IRQ_WAKE_THREAD : IRQ_NONE;
|
| 325 | }
|
| 326 |
|
| 327 | static unsigned long actmon_cpu_to_emc_rate(struct tegra_devfreq *tegra,
|
| 328 | unsigned long cpu_freq)
|
| 329 | {
|
| 330 | unsigned int i;
|
| 331 | struct tegra_actmon_emc_ratio *ratio = actmon_emc_ratios;
|
| 332 |
|
| 333 | for (i = 0; i < ARRAY_SIZE(actmon_emc_ratios); i++, ratio++) {
|
| 334 | if (cpu_freq >= ratio->cpu_freq) {
|
| 335 | if (ratio->emc_freq >= tegra->max_freq)
|
| 336 | return tegra->max_freq;
|
| 337 | else
|
| 338 | return ratio->emc_freq;
|
| 339 | }
|
| 340 | }
|
| 341 |
|
| 342 | return 0;
|
| 343 | }
|
| 344 |
|
| 345 | static void actmon_update_target(struct tegra_devfreq *tegra,
|
| 346 | struct tegra_devfreq_device *dev)
|
| 347 | {
|
| 348 | unsigned long cpu_freq = 0;
|
| 349 | unsigned long static_cpu_emc_freq = 0;
|
| 350 | unsigned int avg_sustain_coef;
|
| 351 | unsigned long flags;
|
| 352 |
|
| 353 | if (dev->config->avg_dependency_threshold) {
|
| 354 | cpu_freq = cpufreq_get(0);
|
| 355 | static_cpu_emc_freq = actmon_cpu_to_emc_rate(tegra, cpu_freq);
|
| 356 | }
|
| 357 |
|
| 358 | spin_lock_irqsave(&dev->lock, flags);
|
| 359 |
|
| 360 | dev->target_freq = dev->avg_count / ACTMON_SAMPLING_PERIOD;
|
| 361 | avg_sustain_coef = 100 * 100 / dev->config->boost_up_threshold;
|
| 362 | dev->target_freq = do_percent(dev->target_freq, avg_sustain_coef);
|
| 363 | dev->target_freq += dev->boost_freq;
|
| 364 |
|
| 365 | if (dev->avg_count >= dev->config->avg_dependency_threshold)
|
| 366 | dev->target_freq = max(dev->target_freq, static_cpu_emc_freq);
|
| 367 |
|
| 368 | spin_unlock_irqrestore(&dev->lock, flags);
|
| 369 | }
|
| 370 |
|
| 371 | static irqreturn_t actmon_thread_isr(int irq, void *data)
|
| 372 | {
|
| 373 | struct tegra_devfreq *tegra = data;
|
| 374 |
|
| 375 | mutex_lock(&tegra->devfreq->lock);
|
| 376 | update_devfreq(tegra->devfreq);
|
| 377 | mutex_unlock(&tegra->devfreq->lock);
|
| 378 |
|
| 379 | return IRQ_HANDLED;
|
| 380 | }
|
| 381 |
|
| 382 | static int tegra_actmon_rate_notify_cb(struct notifier_block *nb,
|
| 383 | unsigned long action, void *ptr)
|
| 384 | {
|
| 385 | struct clk_notifier_data *data = ptr;
|
| 386 | struct tegra_devfreq *tegra;
|
| 387 | struct tegra_devfreq_device *dev;
|
| 388 | unsigned int i;
|
| 389 | unsigned long flags;
|
| 390 |
|
| 391 | if (action != POST_RATE_CHANGE)
|
| 392 | return NOTIFY_OK;
|
| 393 |
|
| 394 | tegra = container_of(nb, struct tegra_devfreq, rate_change_nb);
|
| 395 |
|
| 396 | tegra->cur_freq = data->new_rate / KHZ;
|
| 397 |
|
| 398 | for (i = 0; i < ARRAY_SIZE(tegra->devices); i++) {
|
| 399 | dev = &tegra->devices[i];
|
| 400 |
|
| 401 | spin_lock_irqsave(&dev->lock, flags);
|
| 402 | tegra_devfreq_update_wmark(tegra, dev);
|
| 403 | spin_unlock_irqrestore(&dev->lock, flags);
|
| 404 | }
|
| 405 |
|
| 406 | actmon_write_barrier(tegra);
|
| 407 |
|
| 408 | return NOTIFY_OK;
|
| 409 | }
|
| 410 |
|
| 411 | static void tegra_actmon_enable_interrupts(struct tegra_devfreq *tegra)
|
| 412 | {
|
| 413 | struct tegra_devfreq_device *dev;
|
| 414 | u32 val;
|
| 415 | unsigned int i;
|
| 416 |
|
| 417 | for (i = 0; i < ARRAY_SIZE(tegra->devices); i++) {
|
| 418 | dev = &tegra->devices[i];
|
| 419 |
|
| 420 | val = device_readl(dev, ACTMON_DEV_CTRL);
|
| 421 | val |= ACTMON_DEV_CTRL_AVG_ABOVE_WMARK_EN;
|
| 422 | val |= ACTMON_DEV_CTRL_AVG_BELOW_WMARK_EN;
|
| 423 | val |= ACTMON_DEV_CTRL_CONSECUTIVE_BELOW_WMARK_EN;
|
| 424 | val |= ACTMON_DEV_CTRL_CONSECUTIVE_ABOVE_WMARK_EN;
|
| 425 |
|
| 426 | device_writel(dev, val, ACTMON_DEV_CTRL);
|
| 427 | }
|
| 428 |
|
| 429 | actmon_write_barrier(tegra);
|
| 430 | }
|
| 431 |
|
| 432 | static void tegra_actmon_disable_interrupts(struct tegra_devfreq *tegra)
|
| 433 | {
|
| 434 | struct tegra_devfreq_device *dev;
|
| 435 | u32 val;
|
| 436 | unsigned int i;
|
| 437 |
|
| 438 | for (i = 0; i < ARRAY_SIZE(tegra->devices); i++) {
|
| 439 | dev = &tegra->devices[i];
|
| 440 |
|
| 441 | val = device_readl(dev, ACTMON_DEV_CTRL);
|
| 442 | val &= ~ACTMON_DEV_CTRL_AVG_ABOVE_WMARK_EN;
|
| 443 | val &= ~ACTMON_DEV_CTRL_AVG_BELOW_WMARK_EN;
|
| 444 | val &= ~ACTMON_DEV_CTRL_CONSECUTIVE_BELOW_WMARK_EN;
|
| 445 | val &= ~ACTMON_DEV_CTRL_CONSECUTIVE_ABOVE_WMARK_EN;
|
| 446 |
|
| 447 | device_writel(dev, val, ACTMON_DEV_CTRL);
|
| 448 | }
|
| 449 |
|
| 450 | actmon_write_barrier(tegra);
|
| 451 | }
|
| 452 |
|
| 453 | static void tegra_actmon_configure_device(struct tegra_devfreq *tegra,
|
| 454 | struct tegra_devfreq_device *dev)
|
| 455 | {
|
| 456 | u32 val = 0;
|
| 457 |
|
| 458 | dev->target_freq = tegra->cur_freq;
|
| 459 |
|
| 460 | dev->avg_count = tegra->cur_freq * ACTMON_SAMPLING_PERIOD;
|
| 461 | device_writel(dev, dev->avg_count, ACTMON_DEV_INIT_AVG);
|
| 462 |
|
| 463 | tegra_devfreq_update_avg_wmark(tegra, dev);
|
| 464 | tegra_devfreq_update_wmark(tegra, dev);
|
| 465 |
|
| 466 | device_writel(dev, ACTMON_COUNT_WEIGHT, ACTMON_DEV_COUNT_WEIGHT);
|
| 467 | device_writel(dev, ACTMON_INTR_STATUS_CLEAR, ACTMON_DEV_INTR_STATUS);
|
| 468 |
|
| 469 | val |= ACTMON_DEV_CTRL_ENB_PERIODIC;
|
| 470 | val |= (ACTMON_AVERAGE_WINDOW_LOG2 - 1)
|
| 471 | << ACTMON_DEV_CTRL_K_VAL_SHIFT;
|
| 472 | val |= (ACTMON_BELOW_WMARK_WINDOW - 1)
|
| 473 | << ACTMON_DEV_CTRL_CONSECUTIVE_BELOW_WMARK_NUM_SHIFT;
|
| 474 | val |= (ACTMON_ABOVE_WMARK_WINDOW - 1)
|
| 475 | << ACTMON_DEV_CTRL_CONSECUTIVE_ABOVE_WMARK_NUM_SHIFT;
|
| 476 | val |= ACTMON_DEV_CTRL_ENB;
|
| 477 |
|
| 478 | device_writel(dev, val, ACTMON_DEV_CTRL);
|
| 479 |
|
| 480 | actmon_write_barrier(tegra);
|
| 481 | }
|
| 482 |
|
| 483 | static int tegra_devfreq_target(struct device *dev, unsigned long *freq,
|
| 484 | u32 flags)
|
| 485 | {
|
| 486 | struct tegra_devfreq *tegra = dev_get_drvdata(dev);
|
| 487 | struct dev_pm_opp *opp;
|
| 488 | unsigned long rate = *freq * KHZ;
|
| 489 |
|
| 490 | opp = devfreq_recommended_opp(dev, &rate, flags);
|
| 491 | if (IS_ERR(opp)) {
|
| 492 | dev_err(dev, "Failed to find opp for %lu KHz\n", *freq);
|
| 493 | return PTR_ERR(opp);
|
| 494 | }
|
| 495 | rate = dev_pm_opp_get_freq(opp);
|
| 496 | dev_pm_opp_put(opp);
|
| 497 |
|
| 498 | clk_set_min_rate(tegra->emc_clock, rate);
|
| 499 | clk_set_rate(tegra->emc_clock, 0);
|
| 500 |
|
| 501 | *freq = rate;
|
| 502 |
|
| 503 | return 0;
|
| 504 | }
|
| 505 |
|
| 506 | static int tegra_devfreq_get_dev_status(struct device *dev,
|
| 507 | struct devfreq_dev_status *stat)
|
| 508 | {
|
| 509 | struct tegra_devfreq *tegra = dev_get_drvdata(dev);
|
| 510 | struct tegra_devfreq_device *actmon_dev;
|
| 511 |
|
| 512 | stat->current_frequency = tegra->cur_freq;
|
| 513 |
|
| 514 |
|
| 515 | stat->private_data = tegra;
|
| 516 |
|
| 517 |
|
| 518 |
|
| 519 | actmon_dev = &tegra->devices[MCALL];
|
| 520 |
|
| 521 |
|
| 522 | stat->busy_time = device_readl(actmon_dev, ACTMON_DEV_AVG_COUNT);
|
| 523 |
|
| 524 |
|
| 525 | stat->busy_time *= 100 / BUS_SATURATION_RATIO;
|
| 526 |
|
| 527 |
|
| 528 | stat->total_time = ACTMON_SAMPLING_PERIOD * tegra->cur_freq;
|
| 529 |
|
| 530 | stat->busy_time = min(stat->busy_time, stat->total_time);
|
| 531 |
|
| 532 | return 0;
|
| 533 | }
|
| 534 |
|
| 535 | static struct devfreq_dev_profile tegra_devfreq_profile = {
|
| 536 | .polling_ms = 0,
|
| 537 | .target = tegra_devfreq_target,
|
| 538 | .get_dev_status = tegra_devfreq_get_dev_status,
|
| 539 | };
|
| 540 |
|
| 541 | static int tegra_governor_get_target(struct devfreq *devfreq,
|
| 542 | unsigned long *freq)
|
| 543 | {
|
| 544 | struct devfreq_dev_status *stat;
|
| 545 | struct tegra_devfreq *tegra;
|
| 546 | struct tegra_devfreq_device *dev;
|
| 547 | unsigned long target_freq = 0;
|
| 548 | unsigned int i;
|
| 549 | int err;
|
| 550 |
|
| 551 | err = devfreq_update_stats(devfreq);
|
| 552 | if (err)
|
| 553 | return err;
|
| 554 |
|
| 555 | stat = &devfreq->last_status;
|
| 556 |
|
| 557 | tegra = stat->private_data;
|
| 558 |
|
| 559 | for (i = 0; i < ARRAY_SIZE(tegra->devices); i++) {
|
| 560 | dev = &tegra->devices[i];
|
| 561 |
|
| 562 | actmon_update_target(tegra, dev);
|
| 563 |
|
| 564 | target_freq = max(target_freq, dev->target_freq);
|
| 565 | }
|
| 566 |
|
| 567 | *freq = target_freq;
|
| 568 |
|
| 569 | return 0;
|
| 570 | }
|
| 571 |
|
| 572 | static int tegra_governor_event_handler(struct devfreq *devfreq,
|
| 573 | unsigned int event, void *data)
|
| 574 | {
|
| 575 | struct tegra_devfreq *tegra;
|
| 576 | int ret = 0;
|
| 577 |
|
| 578 | tegra = dev_get_drvdata(devfreq->dev.parent);
|
| 579 |
|
| 580 | switch (event) {
|
| 581 | case DEVFREQ_GOV_START:
|
| 582 | devfreq_monitor_start(devfreq);
|
| 583 | tegra_actmon_enable_interrupts(tegra);
|
| 584 | break;
|
| 585 |
|
| 586 | case DEVFREQ_GOV_STOP:
|
| 587 | tegra_actmon_disable_interrupts(tegra);
|
| 588 | devfreq_monitor_stop(devfreq);
|
| 589 | break;
|
| 590 |
|
| 591 | case DEVFREQ_GOV_SUSPEND:
|
| 592 | tegra_actmon_disable_interrupts(tegra);
|
| 593 | devfreq_monitor_suspend(devfreq);
|
| 594 | break;
|
| 595 |
|
| 596 | case DEVFREQ_GOV_RESUME:
|
| 597 | devfreq_monitor_resume(devfreq);
|
| 598 | tegra_actmon_enable_interrupts(tegra);
|
| 599 | break;
|
| 600 | }
|
| 601 |
|
| 602 | return ret;
|
| 603 | }
|
| 604 |
|
| 605 | static struct devfreq_governor tegra_devfreq_governor = {
|
| 606 | .name = "tegra_actmon",
|
| 607 | .get_target_freq = tegra_governor_get_target,
|
| 608 | .event_handler = tegra_governor_event_handler,
|
| 609 | };
|
| 610 |
|
| 611 | static int tegra_devfreq_probe(struct platform_device *pdev)
|
| 612 | {
|
| 613 | struct tegra_devfreq *tegra;
|
| 614 | struct tegra_devfreq_device *dev;
|
| 615 | struct resource *res;
|
| 616 | unsigned int i;
|
| 617 | unsigned long rate;
|
| 618 | int irq;
|
| 619 | int err;
|
| 620 |
|
| 621 | tegra = devm_kzalloc(&pdev->dev, sizeof(*tegra), GFP_KERNEL);
|
| 622 | if (!tegra)
|
| 623 | return -ENOMEM;
|
| 624 |
|
| 625 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
| 626 |
|
| 627 | tegra->regs = devm_ioremap_resource(&pdev->dev, res);
|
| 628 | if (IS_ERR(tegra->regs))
|
| 629 | return PTR_ERR(tegra->regs);
|
| 630 |
|
| 631 | tegra->reset = devm_reset_control_get(&pdev->dev, "actmon");
|
| 632 | if (IS_ERR(tegra->reset)) {
|
| 633 | dev_err(&pdev->dev, "Failed to get reset\n");
|
| 634 | return PTR_ERR(tegra->reset);
|
| 635 | }
|
| 636 |
|
| 637 | tegra->clock = devm_clk_get(&pdev->dev, "actmon");
|
| 638 | if (IS_ERR(tegra->clock)) {
|
| 639 | dev_err(&pdev->dev, "Failed to get actmon clock\n");
|
| 640 | return PTR_ERR(tegra->clock);
|
| 641 | }
|
| 642 |
|
| 643 | tegra->emc_clock = devm_clk_get(&pdev->dev, "emc");
|
| 644 | if (IS_ERR(tegra->emc_clock)) {
|
| 645 | dev_err(&pdev->dev, "Failed to get emc clock\n");
|
| 646 | return PTR_ERR(tegra->emc_clock);
|
| 647 | }
|
| 648 |
|
| 649 | clk_set_rate(tegra->emc_clock, ULONG_MAX);
|
| 650 |
|
| 651 | tegra->rate_change_nb.notifier_call = tegra_actmon_rate_notify_cb;
|
| 652 | err = clk_notifier_register(tegra->emc_clock, &tegra->rate_change_nb);
|
| 653 | if (err) {
|
| 654 | dev_err(&pdev->dev,
|
| 655 | "Failed to register rate change notifier\n");
|
| 656 | return err;
|
| 657 | }
|
| 658 |
|
| 659 | reset_control_assert(tegra->reset);
|
| 660 |
|
| 661 | err = clk_prepare_enable(tegra->clock);
|
| 662 | if (err) {
|
| 663 | dev_err(&pdev->dev,
|
| 664 | "Failed to prepare and enable ACTMON clock\n");
|
| 665 | return err;
|
| 666 | }
|
| 667 |
|
| 668 | reset_control_deassert(tegra->reset);
|
| 669 |
|
| 670 | tegra->max_freq = clk_round_rate(tegra->emc_clock, ULONG_MAX) / KHZ;
|
| 671 | tegra->cur_freq = clk_get_rate(tegra->emc_clock) / KHZ;
|
| 672 |
|
| 673 | actmon_writel(tegra, ACTMON_SAMPLING_PERIOD - 1,
|
| 674 | ACTMON_GLB_PERIOD_CTRL);
|
| 675 |
|
| 676 | for (i = 0; i < ARRAY_SIZE(actmon_device_configs); i++) {
|
| 677 | dev = tegra->devices + i;
|
| 678 | dev->config = actmon_device_configs + i;
|
| 679 | dev->regs = tegra->regs + dev->config->offset;
|
| 680 | spin_lock_init(&dev->lock);
|
| 681 |
|
| 682 | tegra_actmon_configure_device(tegra, dev);
|
| 683 | }
|
| 684 |
|
| 685 | for (rate = 0; rate <= tegra->max_freq * KHZ; rate++) {
|
| 686 | rate = clk_round_rate(tegra->emc_clock, rate);
|
| 687 | dev_pm_opp_add(&pdev->dev, rate, 0);
|
| 688 | }
|
| 689 |
|
| 690 | irq = platform_get_irq(pdev, 0);
|
| 691 | if (irq < 0) {
|
| 692 | dev_err(&pdev->dev, "Failed to get IRQ: %d\n", irq);
|
| 693 | return irq;
|
| 694 | }
|
| 695 |
|
| 696 | platform_set_drvdata(pdev, tegra);
|
| 697 |
|
| 698 | err = devm_request_threaded_irq(&pdev->dev, irq, actmon_isr,
|
| 699 | actmon_thread_isr, IRQF_SHARED,
|
| 700 | "tegra-devfreq", tegra);
|
| 701 | if (err) {
|
| 702 | dev_err(&pdev->dev, "Interrupt request failed\n");
|
| 703 | return err;
|
| 704 | }
|
| 705 |
|
| 706 | tegra_devfreq_profile.initial_freq = clk_get_rate(tegra->emc_clock);
|
| 707 | tegra->devfreq = devm_devfreq_add_device(&pdev->dev,
|
| 708 | &tegra_devfreq_profile,
|
| 709 | "tegra_actmon",
|
| 710 | NULL);
|
| 711 |
|
| 712 | return 0;
|
| 713 | }
|
| 714 |
|
| 715 | static int tegra_devfreq_remove(struct platform_device *pdev)
|
| 716 | {
|
| 717 | struct tegra_devfreq *tegra = platform_get_drvdata(pdev);
|
| 718 | int irq = platform_get_irq(pdev, 0);
|
| 719 | u32 val;
|
| 720 | unsigned int i;
|
| 721 |
|
| 722 | for (i = 0; i < ARRAY_SIZE(actmon_device_configs); i++) {
|
| 723 | val = device_readl(&tegra->devices[i], ACTMON_DEV_CTRL);
|
| 724 | val &= ~ACTMON_DEV_CTRL_ENB;
|
| 725 | device_writel(&tegra->devices[i], val, ACTMON_DEV_CTRL);
|
| 726 | }
|
| 727 |
|
| 728 | actmon_write_barrier(tegra);
|
| 729 |
|
| 730 | devm_free_irq(&pdev->dev, irq, tegra);
|
| 731 |
|
| 732 | clk_notifier_unregister(tegra->emc_clock, &tegra->rate_change_nb);
|
| 733 |
|
| 734 | clk_disable_unprepare(tegra->clock);
|
| 735 |
|
| 736 | return 0;
|
| 737 | }
|
| 738 |
|
| 739 | static const struct of_device_id tegra_devfreq_of_match[] = {
|
| 740 | { .compatible = "nvidia,tegra124-actmon" },
|
| 741 | { },
|
| 742 | };
|
| 743 |
|
| 744 | MODULE_DEVICE_TABLE(of, tegra_devfreq_of_match);
|
| 745 |
|
| 746 | static struct platform_driver tegra_devfreq_driver = {
|
| 747 | .probe = tegra_devfreq_probe,
|
| 748 | .remove = tegra_devfreq_remove,
|
| 749 | .driver = {
|
| 750 | .name = "tegra-devfreq",
|
| 751 | .of_match_table = tegra_devfreq_of_match,
|
| 752 | },
|
| 753 | };
|
| 754 |
|
| 755 | static int __init tegra_devfreq_init(void)
|
| 756 | {
|
| 757 | int ret = 0;
|
| 758 |
|
| 759 | ret = devfreq_add_governor(&tegra_devfreq_governor);
|
| 760 | if (ret) {
|
| 761 | pr_err("%s: failed to add governor: %d\n", __func__, ret);
|
| 762 | return ret;
|
| 763 | }
|
| 764 |
|
| 765 | ret = platform_driver_register(&tegra_devfreq_driver);
|
| 766 | if (ret)
|
| 767 | devfreq_remove_governor(&tegra_devfreq_governor);
|
| 768 |
|
| 769 | return ret;
|
| 770 | }
|
| 771 | module_init(tegra_devfreq_init)
|
| 772 |
|
| 773 | static void __exit tegra_devfreq_exit(void)
|
| 774 | {
|
| 775 | int ret = 0;
|
| 776 |
|
| 777 | platform_driver_unregister(&tegra_devfreq_driver);
|
| 778 |
|
| 779 | ret = devfreq_remove_governor(&tegra_devfreq_governor);
|
| 780 | if (ret)
|
| 781 | pr_err("%s: failed to remove governor: %d\n", __func__, ret);
|
| 782 | }
|
| 783 | module_exit(tegra_devfreq_exit)
|
| 784 |
|
| 785 | MODULE_LICENSE("GPL v2");
|
| 786 | MODULE_DESCRIPTION("Tegra devfreq driver");
|
| 787 | MODULE_AUTHOR("Tomeu Vizoso <[email protected]>");
|