summaryrefslogtreecommitdiffstats
path: root/drivers/devfreq/tegra30-devfreq.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2019-09-17 22:15:14 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2019-09-17 22:15:14 -0400
commit77dcfe2b9edc98286cf18e03c243c9b999f955d9 (patch)
tree0ba3c4002b6c26c715bf03fac81d63de13c01d96 /drivers/devfreq/tegra30-devfreq.c
parent04cbfba6208592999d7bfe6609ec01dc3fde73f5 (diff)
parentfc6763a2d7e0a7f49ccec97a46e92e9fb1f3f9dd (diff)
Merge tag 'pm-5.4-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
Pull power management updates from Rafael Wysocki: "These include a rework of the main suspend-to-idle code flow (related to the handling of spurious wakeups), a switch over of several users of cpufreq notifiers to QoS-based limits, a new devfreq driver for Tegra20, a new cpuidle driver and governor for virtualized guests, an extension of the wakeup sources framework to expose wakeup sources as device objects in sysfs, and more. Specifics: - Rework the main suspend-to-idle control flow to avoid repeating "noirq" device resume and suspend operations in case of spurious wakeups from the ACPI EC and decouple the ACPI EC wakeups support from the LPS0 _DSM support (Rafael Wysocki). - Extend the wakeup sources framework to expose wakeup sources as device objects in sysfs (Tri Vo, Stephen Boyd). - Expose system suspend statistics in sysfs (Kalesh Singh). - Introduce a new haltpoll cpuidle driver and a new matching governor for virtualized guests wanting to do guest-side polling in the idle loop (Marcelo Tosatti, Joao Martins, Wanpeng Li, Stephen Rothwell). - Fix the menu and teo cpuidle governors to allow the scheduler tick to be stopped if PM QoS is used to limit the CPU idle state exit latency in some cases (Rafael Wysocki). - Increase the resolution of the play_idle() argument to microseconds for more fine-grained injection of CPU idle cycles (Daniel Lezcano). - Switch over some users of cpuidle notifiers to the new QoS-based frequency limits and drop the CPUFREQ_ADJUST and CPUFREQ_NOTIFY policy notifier events (Viresh Kumar). - Add new cpufreq driver based on nvmem for sun50i (Yangtao Li). - Add support for MT8183 and MT8516 to the mediatek cpufreq driver (Andrew-sh.Cheng, Fabien Parent). - Add i.MX8MN support to the imx-cpufreq-dt cpufreq driver (Anson Huang). - Add qcs404 to cpufreq-dt-platdev blacklist (Jorge Ramirez-Ortiz). - Update the qcom cpufreq driver (among other things, to make it easier to extend and to use kryo cpufreq for other nvmem-based SoCs) and add qcs404 support to it (Niklas Cassel, Douglas RAILLARD, Sibi Sankar, Sricharan R). - Fix assorted issues and make assorted minor improvements in the cpufreq code (Colin Ian King, Douglas RAILLARD, Florian Fainelli, Gustavo Silva, Hariprasad Kelam). - Add new devfreq driver for NVidia Tegra20 (Dmitry Osipenko, Arnd Bergmann). - Add new Exynos PPMU events to devfreq events and extend that mechanism (Lukasz Luba). - Fix and clean up the exynos-bus devfreq driver (Kamil Konieczny). - Improve devfreq documentation and governor code, fix spelling typos in devfreq (Ezequiel Garcia, Krzysztof Kozlowski, Leonard Crestez, MyungJoo Ham, Gaël PORTAY). - Add regulators enable and disable to the OPP (operating performance points) framework (Kamil Konieczny). - Update the OPP framework to support multiple opp-suspend properties (Anson Huang). - Fix assorted issues and make assorted minor improvements in the OPP code (Niklas Cassel, Viresh Kumar, Yue Hu). - Clean up the generic power domains (genpd) framework (Ulf Hansson). - Clean up assorted pieces of power management code and documentation (Akinobu Mita, Amit Kucheria, Chuhong Yuan). - Update the pm-graph tool to version 5.5 including multiple fixes and improvements (Todd Brandt). - Update the cpupower utility (Benjamin Weis, Geert Uytterhoeven, Sébastien Szymanski)" * tag 'pm-5.4-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: (126 commits) cpuidle-haltpoll: Enable kvm guest polling when dedicated physical CPUs are available cpuidle-haltpoll: do not set an owner to allow modunload cpuidle-haltpoll: return -ENODEV on modinit failure cpuidle-haltpoll: set haltpoll as preferred governor cpuidle: allow governor switch on cpuidle_register_driver() PM: runtime: Documentation: add runtime_status ABI document pm-graph: make setVal unbuffered again for python2 and python3 powercap: idle_inject: Use higher resolution for idle injection cpuidle: play_idle: Increase the resolution to usec cpuidle-haltpoll: vcpu hotplug support cpufreq: Add qcs404 to cpufreq-dt-platdev blacklist cpufreq: qcom: Add support for qcs404 on nvmem driver cpufreq: qcom: Refactor the driver to make it easier to extend cpufreq: qcom: Re-organise kryo cpufreq to use it for other nvmem based qcom socs dt-bindings: opp: Add qcom-opp bindings with properties needed for CPR dt-bindings: opp: qcom-nvmem: Support pstates provided by a power domain Documentation: cpufreq: Update policy notifier documentation cpufreq: Remove CPUFREQ_ADJUST and CPUFREQ_NOTIFY policy notifier events PM / Domains: Verify PM domain type in dev_pm_genpd_set_performance_state() PM / Domains: Simplify genpd_lookup_dev() ...
Diffstat (limited to 'drivers/devfreq/tegra30-devfreq.c')
-rw-r--r--drivers/devfreq/tegra30-devfreq.c748
1 files changed, 748 insertions, 0 deletions
diff --git a/drivers/devfreq/tegra30-devfreq.c b/drivers/devfreq/tegra30-devfreq.c
new file mode 100644
index 000000000000..a6ba75f4106d
--- /dev/null
+++ b/drivers/devfreq/tegra30-devfreq.c
@@ -0,0 +1,748 @@
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * A devfreq driver for NVIDIA Tegra SoCs
4 *
5 * Copyright (c) 2014 NVIDIA CORPORATION. All rights reserved.
6 * Copyright (C) 2014 Google, Inc
7 */
8
9#include <linux/clk.h>
10#include <linux/cpufreq.h>
11#include <linux/devfreq.h>
12#include <linux/interrupt.h>
13#include <linux/io.h>
14#include <linux/module.h>
15#include <linux/mod_devicetable.h>
16#include <linux/platform_device.h>
17#include <linux/pm_opp.h>
18#include <linux/reset.h>
19
20#include "governor.h"
21
22#define ACTMON_GLB_STATUS 0x0
23#define ACTMON_GLB_PERIOD_CTRL 0x4
24
25#define ACTMON_DEV_CTRL 0x0
26#define ACTMON_DEV_CTRL_K_VAL_SHIFT 10
27#define ACTMON_DEV_CTRL_ENB_PERIODIC BIT(18)
28#define ACTMON_DEV_CTRL_AVG_BELOW_WMARK_EN BIT(20)
29#define ACTMON_DEV_CTRL_AVG_ABOVE_WMARK_EN BIT(21)
30#define ACTMON_DEV_CTRL_CONSECUTIVE_BELOW_WMARK_NUM_SHIFT 23
31#define ACTMON_DEV_CTRL_CONSECUTIVE_ABOVE_WMARK_NUM_SHIFT 26
32#define ACTMON_DEV_CTRL_CONSECUTIVE_BELOW_WMARK_EN BIT(29)
33#define ACTMON_DEV_CTRL_CONSECUTIVE_ABOVE_WMARK_EN BIT(30)
34#define ACTMON_DEV_CTRL_ENB BIT(31)
35
36#define ACTMON_DEV_UPPER_WMARK 0x4
37#define ACTMON_DEV_LOWER_WMARK 0x8
38#define ACTMON_DEV_INIT_AVG 0xc
39#define ACTMON_DEV_AVG_UPPER_WMARK 0x10
40#define ACTMON_DEV_AVG_LOWER_WMARK 0x14
41#define ACTMON_DEV_COUNT_WEIGHT 0x18
42#define ACTMON_DEV_AVG_COUNT 0x20
43#define ACTMON_DEV_INTR_STATUS 0x24
44
45#define ACTMON_INTR_STATUS_CLEAR 0xffffffff
46
47#define ACTMON_DEV_INTR_CONSECUTIVE_UPPER BIT(31)
48#define ACTMON_DEV_INTR_CONSECUTIVE_LOWER BIT(30)
49
50#define ACTMON_ABOVE_WMARK_WINDOW 1
51#define ACTMON_BELOW_WMARK_WINDOW 3
52#define ACTMON_BOOST_FREQ_STEP 16000
53
54/*
55 * Activity counter is incremented every 256 memory transactions, and each
56 * transaction takes 4 EMC clocks for Tegra124; So the COUNT_WEIGHT is
57 * 4 * 256 = 1024.
58 */
59#define ACTMON_COUNT_WEIGHT 0x400
60
61/*
62 * ACTMON_AVERAGE_WINDOW_LOG2: default value for @DEV_CTRL_K_VAL, which
63 * translates to 2 ^ (K_VAL + 1). ex: 2 ^ (6 + 1) = 128
64 */
65#define ACTMON_AVERAGE_WINDOW_LOG2 6
66#define ACTMON_SAMPLING_PERIOD 12 /* ms */
67#define ACTMON_DEFAULT_AVG_BAND 6 /* 1/10 of % */
68
69#define KHZ 1000
70
71/* Assume that the bus is saturated if the utilization is 25% */
72#define BUS_SATURATION_RATIO 25
73
74/**
75 * struct tegra_devfreq_device_config - configuration specific to an ACTMON
76 * device
77 *
78 * Coefficients and thresholds are percentages unless otherwise noted
79 */
80struct tegra_devfreq_device_config {
81 u32 offset;
82 u32 irq_mask;
83
84 /* Factors applied to boost_freq every consecutive watermark breach */
85 unsigned int boost_up_coeff;
86 unsigned int boost_down_coeff;
87
88 /* Define the watermark bounds when applied to the current avg */
89 unsigned int boost_up_threshold;
90 unsigned int boost_down_threshold;
91
92 /*
93 * Threshold of activity (cycles) below which the CPU frequency isn't
94 * to be taken into account. This is to avoid increasing the EMC
95 * frequency when the CPU is very busy but not accessing the bus often.
96 */
97 u32 avg_dependency_threshold;
98};
99
100enum tegra_actmon_device {
101 MCALL = 0,
102 MCCPU,
103};
104
105static struct tegra_devfreq_device_config actmon_device_configs[] = {
106 {
107 /* MCALL: All memory accesses (including from the CPUs) */
108 .offset = 0x1c0,
109 .irq_mask = 1 << 26,
110 .boost_up_coeff = 200,
111 .boost_down_coeff = 50,
112 .boost_up_threshold = 60,
113 .boost_down_threshold = 40,
114 },
115 {
116 /* MCCPU: memory accesses from the CPUs */
117 .offset = 0x200,
118 .irq_mask = 1 << 25,
119 .boost_up_coeff = 800,
120 .boost_down_coeff = 90,
121 .boost_up_threshold = 27,
122 .boost_down_threshold = 10,
123 .avg_dependency_threshold = 50000,
124 },
125};
126
127/**
128 * struct tegra_devfreq_device - state specific to an ACTMON device
129 *
130 * Frequencies are in kHz.
131 */
132struct tegra_devfreq_device {
133 const struct tegra_devfreq_device_config *config;
134 void __iomem *regs;
135
136 /* Average event count sampled in the last interrupt */
137 u32 avg_count;
138
139 /*
140 * Extra frequency to increase the target by due to consecutive
141 * watermark breaches.
142 */
143 unsigned long boost_freq;
144
145 /* Optimal frequency calculated from the stats for this device */
146 unsigned long target_freq;
147};
148
149struct tegra_devfreq {
150 struct devfreq *devfreq;
151
152 struct reset_control *reset;
153 struct clk *clock;
154 void __iomem *regs;
155
156 struct clk *emc_clock;
157 unsigned long max_freq;
158 unsigned long cur_freq;
159 struct notifier_block rate_change_nb;
160
161 struct tegra_devfreq_device devices[ARRAY_SIZE(actmon_device_configs)];
162
163 int irq;
164};
165
166struct tegra_actmon_emc_ratio {
167 unsigned long cpu_freq;
168 unsigned long emc_freq;
169};
170
171static struct tegra_actmon_emc_ratio actmon_emc_ratios[] = {
172 { 1400000, ULONG_MAX },
173 { 1200000, 750000 },
174 { 1100000, 600000 },
175 { 1000000, 500000 },
176 { 800000, 375000 },
177 { 500000, 200000 },
178 { 250000, 100000 },
179};
180
181static u32 actmon_readl(struct tegra_devfreq *tegra, u32 offset)
182{
183 return readl_relaxed(tegra->regs + offset);
184}
185
186static void actmon_writel(struct tegra_devfreq *tegra, u32 val, u32 offset)
187{
188 writel_relaxed(val, tegra->regs + offset);
189}
190
191static u32 device_readl(struct tegra_devfreq_device *dev, u32 offset)
192{
193 return readl_relaxed(dev->regs + offset);
194}
195
196static void device_writel(struct tegra_devfreq_device *dev, u32 val,
197 u32 offset)
198{
199 writel_relaxed(val, dev->regs + offset);
200}
201
202static unsigned long do_percent(unsigned long val, unsigned int pct)
203{
204 return val * pct / 100;
205}
206
207static void tegra_devfreq_update_avg_wmark(struct tegra_devfreq *tegra,
208 struct tegra_devfreq_device *dev)
209{
210 u32 avg = dev->avg_count;
211 u32 avg_band_freq = tegra->max_freq * ACTMON_DEFAULT_AVG_BAND / KHZ;
212 u32 band = avg_band_freq * ACTMON_SAMPLING_PERIOD;
213
214 device_writel(dev, avg + band, ACTMON_DEV_AVG_UPPER_WMARK);
215
216 avg = max(dev->avg_count, band);
217 device_writel(dev, avg - band, ACTMON_DEV_AVG_LOWER_WMARK);
218}
219
220static void tegra_devfreq_update_wmark(struct tegra_devfreq *tegra,
221 struct tegra_devfreq_device *dev)
222{
223 u32 val = tegra->cur_freq * ACTMON_SAMPLING_PERIOD;
224
225 device_writel(dev, do_percent(val, dev->config->boost_up_threshold),
226 ACTMON_DEV_UPPER_WMARK);
227
228 device_writel(dev, do_percent(val, dev->config->boost_down_threshold),
229 ACTMON_DEV_LOWER_WMARK);
230}
231
232static void actmon_write_barrier(struct tegra_devfreq *tegra)
233{
234 /* ensure the update has reached the ACTMON */
235 readl(tegra->regs + ACTMON_GLB_STATUS);
236}
237
238static void actmon_isr_device(struct tegra_devfreq *tegra,
239 struct tegra_devfreq_device *dev)
240{
241 u32 intr_status, dev_ctrl;
242
243 dev->avg_count = device_readl(dev, ACTMON_DEV_AVG_COUNT);
244 tegra_devfreq_update_avg_wmark(tegra, dev);
245
246 intr_status = device_readl(dev, ACTMON_DEV_INTR_STATUS);
247 dev_ctrl = device_readl(dev, ACTMON_DEV_CTRL);
248
249 if (intr_status & ACTMON_DEV_INTR_CONSECUTIVE_UPPER) {
250 /*
251 * new_boost = min(old_boost * up_coef + step, max_freq)
252 */
253 dev->boost_freq = do_percent(dev->boost_freq,
254 dev->config->boost_up_coeff);
255 dev->boost_freq += ACTMON_BOOST_FREQ_STEP;
256
257 dev_ctrl |= ACTMON_DEV_CTRL_CONSECUTIVE_BELOW_WMARK_EN;
258
259 if (dev->boost_freq >= tegra->max_freq)
260 dev->boost_freq = tegra->max_freq;
261 else
262 dev_ctrl |= ACTMON_DEV_CTRL_CONSECUTIVE_ABOVE_WMARK_EN;
263 } else if (intr_status & ACTMON_DEV_INTR_CONSECUTIVE_LOWER) {
264 /*
265 * new_boost = old_boost * down_coef
266 * or 0 if (old_boost * down_coef < step / 2)
267 */
268 dev->boost_freq = do_percent(dev->boost_freq,
269 dev->config->boost_down_coeff);
270
271 dev_ctrl |= ACTMON_DEV_CTRL_CONSECUTIVE_ABOVE_WMARK_EN;
272
273 if (dev->boost_freq < (ACTMON_BOOST_FREQ_STEP >> 1))
274 dev->boost_freq = 0;
275 else
276 dev_ctrl |= ACTMON_DEV_CTRL_CONSECUTIVE_BELOW_WMARK_EN;
277 }
278
279 if (dev->config->avg_dependency_threshold) {
280 if (dev->avg_count >= dev->config->avg_dependency_threshold)
281 dev_ctrl |= ACTMON_DEV_CTRL_CONSECUTIVE_BELOW_WMARK_EN;
282 else if (dev->boost_freq == 0)
283 dev_ctrl &= ~ACTMON_DEV_CTRL_CONSECUTIVE_BELOW_WMARK_EN;
284 }
285
286 device_writel(dev, dev_ctrl, ACTMON_DEV_CTRL);
287
288 device_writel(dev, ACTMON_INTR_STATUS_CLEAR, ACTMON_DEV_INTR_STATUS);
289
290 actmon_write_barrier(tegra);
291}
292
293static unsigned long actmon_cpu_to_emc_rate(struct tegra_devfreq *tegra,
294 unsigned long cpu_freq)
295{
296 unsigned int i;
297 struct tegra_actmon_emc_ratio *ratio = actmon_emc_ratios;
298
299 for (i = 0; i < ARRAY_SIZE(actmon_emc_ratios); i++, ratio++) {
300 if (cpu_freq >= ratio->cpu_freq) {
301 if (ratio->emc_freq >= tegra->max_freq)
302 return tegra->max_freq;
303 else
304 return ratio->emc_freq;
305 }
306 }
307
308 return 0;
309}
310
311static void actmon_update_target(struct tegra_devfreq *tegra,
312 struct tegra_devfreq_device *dev)
313{
314 unsigned long cpu_freq = 0;
315 unsigned long static_cpu_emc_freq = 0;
316 unsigned int avg_sustain_coef;
317
318 if (dev->config->avg_dependency_threshold) {
319 cpu_freq = cpufreq_get(0);
320 static_cpu_emc_freq = actmon_cpu_to_emc_rate(tegra, cpu_freq);
321 }
322
323 dev->target_freq = dev->avg_count / ACTMON_SAMPLING_PERIOD;
324 avg_sustain_coef = 100 * 100 / dev->config->boost_up_threshold;
325 dev->target_freq = do_percent(dev->target_freq, avg_sustain_coef);
326 dev->target_freq += dev->boost_freq;
327
328 if (dev->avg_count >= dev->config->avg_dependency_threshold)
329 dev->target_freq = max(dev->target_freq, static_cpu_emc_freq);
330}
331
332static irqreturn_t actmon_thread_isr(int irq, void *data)
333{
334 struct tegra_devfreq *tegra = data;
335 bool handled = false;
336 unsigned int i;
337 u32 val;
338
339 mutex_lock(&tegra->devfreq->lock);
340
341 val = actmon_readl(tegra, ACTMON_GLB_STATUS);
342 for (i = 0; i < ARRAY_SIZE(tegra->devices); i++) {
343 if (val & tegra->devices[i].config->irq_mask) {
344 actmon_isr_device(tegra, tegra->devices + i);
345 handled = true;
346 }
347 }
348
349 if (handled)
350 update_devfreq(tegra->devfreq);
351
352 mutex_unlock(&tegra->devfreq->lock);
353
354 return handled ? IRQ_HANDLED : IRQ_NONE;
355}
356
357static int tegra_actmon_rate_notify_cb(struct notifier_block *nb,
358 unsigned long action, void *ptr)
359{
360 struct clk_notifier_data *data = ptr;
361 struct tegra_devfreq *tegra;
362 struct tegra_devfreq_device *dev;
363 unsigned int i;
364
365 if (action != POST_RATE_CHANGE)
366 return NOTIFY_OK;
367
368 tegra = container_of(nb, struct tegra_devfreq, rate_change_nb);
369
370 tegra->cur_freq = data->new_rate / KHZ;
371
372 for (i = 0; i < ARRAY_SIZE(tegra->devices); i++) {
373 dev = &tegra->devices[i];
374
375 tegra_devfreq_update_wmark(tegra, dev);
376 }
377
378 actmon_write_barrier(tegra);
379
380 return NOTIFY_OK;
381}
382
383static void tegra_actmon_configure_device(struct tegra_devfreq *tegra,
384 struct tegra_devfreq_device *dev)
385{
386 u32 val = 0;
387
388 dev->target_freq = tegra->cur_freq;
389
390 dev->avg_count = tegra->cur_freq * ACTMON_SAMPLING_PERIOD;
391 device_writel(dev, dev->avg_count, ACTMON_DEV_INIT_AVG);
392
393 tegra_devfreq_update_avg_wmark(tegra, dev);
394 tegra_devfreq_update_wmark(tegra, dev);
395
396 device_writel(dev, ACTMON_COUNT_WEIGHT, ACTMON_DEV_COUNT_WEIGHT);
397 device_writel(dev, ACTMON_INTR_STATUS_CLEAR, ACTMON_DEV_INTR_STATUS);
398
399 val |= ACTMON_DEV_CTRL_ENB_PERIODIC;
400 val |= (ACTMON_AVERAGE_WINDOW_LOG2 - 1)
401 << ACTMON_DEV_CTRL_K_VAL_SHIFT;
402 val |= (ACTMON_BELOW_WMARK_WINDOW - 1)
403 << ACTMON_DEV_CTRL_CONSECUTIVE_BELOW_WMARK_NUM_SHIFT;
404 val |= (ACTMON_ABOVE_WMARK_WINDOW - 1)
405 << ACTMON_DEV_CTRL_CONSECUTIVE_ABOVE_WMARK_NUM_SHIFT;
406 val |= ACTMON_DEV_CTRL_AVG_ABOVE_WMARK_EN;
407 val |= ACTMON_DEV_CTRL_AVG_BELOW_WMARK_EN;
408 val |= ACTMON_DEV_CTRL_CONSECUTIVE_BELOW_WMARK_EN;
409 val |= ACTMON_DEV_CTRL_CONSECUTIVE_ABOVE_WMARK_EN;
410 val |= ACTMON_DEV_CTRL_ENB;
411
412 device_writel(dev, val, ACTMON_DEV_CTRL);
413}
414
415static void tegra_actmon_start(struct tegra_devfreq *tegra)
416{
417 unsigned int i;
418
419 disable_irq(tegra->irq);
420
421 actmon_writel(tegra, ACTMON_SAMPLING_PERIOD - 1,
422 ACTMON_GLB_PERIOD_CTRL);
423
424 for (i = 0; i < ARRAY_SIZE(tegra->devices); i++)
425 tegra_actmon_configure_device(tegra, &tegra->devices[i]);
426
427 actmon_write_barrier(tegra);
428
429 enable_irq(tegra->irq);
430}
431
432static void tegra_actmon_stop(struct tegra_devfreq *tegra)
433{
434 unsigned int i;
435
436 disable_irq(tegra->irq);
437
438 for (i = 0; i < ARRAY_SIZE(tegra->devices); i++) {
439 device_writel(&tegra->devices[i], 0x00000000, ACTMON_DEV_CTRL);
440 device_writel(&tegra->devices[i], ACTMON_INTR_STATUS_CLEAR,
441 ACTMON_DEV_INTR_STATUS);
442 }
443
444 actmon_write_barrier(tegra);
445
446 enable_irq(tegra->irq);
447}
448
449static int tegra_devfreq_target(struct device *dev, unsigned long *freq,
450 u32 flags)
451{
452 struct tegra_devfreq *tegra = dev_get_drvdata(dev);
453 struct devfreq *devfreq = tegra->devfreq;
454 struct dev_pm_opp *opp;
455 unsigned long rate;
456 int err;
457
458 opp = devfreq_recommended_opp(dev, freq, flags);
459 if (IS_ERR(opp)) {
460 dev_err(dev, "Failed to find opp for %lu Hz\n", *freq);
461 return PTR_ERR(opp);
462 }
463 rate = dev_pm_opp_get_freq(opp);
464 dev_pm_opp_put(opp);
465
466 err = clk_set_min_rate(tegra->emc_clock, rate);
467 if (err)
468 return err;
469
470 err = clk_set_rate(tegra->emc_clock, 0);
471 if (err)
472 goto restore_min_rate;
473
474 return 0;
475
476restore_min_rate:
477 clk_set_min_rate(tegra->emc_clock, devfreq->previous_freq);
478
479 return err;
480}
481
482static int tegra_devfreq_get_dev_status(struct device *dev,
483 struct devfreq_dev_status *stat)
484{
485 struct tegra_devfreq *tegra = dev_get_drvdata(dev);
486 struct tegra_devfreq_device *actmon_dev;
487 unsigned long cur_freq;
488
489 cur_freq = READ_ONCE(tegra->cur_freq);
490
491 /* To be used by the tegra governor */
492 stat->private_data = tegra;
493
494 /* The below are to be used by the other governors */
495 stat->current_frequency = cur_freq * KHZ;
496
497 actmon_dev = &tegra->devices[MCALL];
498
499 /* Number of cycles spent on memory access */
500 stat->busy_time = device_readl(actmon_dev, ACTMON_DEV_AVG_COUNT);
501
502 /* The bus can be considered to be saturated way before 100% */
503 stat->busy_time *= 100 / BUS_SATURATION_RATIO;
504
505 /* Number of cycles in a sampling period */
506 stat->total_time = ACTMON_SAMPLING_PERIOD * cur_freq;
507
508 stat->busy_time = min(stat->busy_time, stat->total_time);
509
510 return 0;
511}
512
513static struct devfreq_dev_profile tegra_devfreq_profile = {
514 .polling_ms = 0,
515 .target = tegra_devfreq_target,
516 .get_dev_status = tegra_devfreq_get_dev_status,
517};
518
519static int tegra_governor_get_target(struct devfreq *devfreq,
520 unsigned long *freq)
521{
522 struct devfreq_dev_status *stat;
523 struct tegra_devfreq *tegra;
524 struct tegra_devfreq_device *dev;
525 unsigned long target_freq = 0;
526 unsigned int i;
527 int err;
528
529 err = devfreq_update_stats(devfreq);
530 if (err)
531 return err;
532
533 stat = &devfreq->last_status;
534
535 tegra = stat->private_data;
536
537 for (i = 0; i < ARRAY_SIZE(tegra->devices); i++) {
538 dev = &tegra->devices[i];
539
540 actmon_update_target(tegra, dev);
541
542 target_freq = max(target_freq, dev->target_freq);
543 }
544
545 *freq = target_freq * KHZ;
546
547 return 0;
548}
549
550static int tegra_governor_event_handler(struct devfreq *devfreq,
551 unsigned int event, void *data)
552{
553 struct tegra_devfreq *tegra = dev_get_drvdata(devfreq->dev.parent);
554
555 switch (event) {
556 case DEVFREQ_GOV_START:
557 devfreq_monitor_start(devfreq);
558 tegra_actmon_start(tegra);
559 break;
560
561 case DEVFREQ_GOV_STOP:
562 tegra_actmon_stop(tegra);
563 devfreq_monitor_stop(devfreq);
564 break;
565
566 case DEVFREQ_GOV_SUSPEND:
567 tegra_actmon_stop(tegra);
568 devfreq_monitor_suspend(devfreq);
569 break;
570
571 case DEVFREQ_GOV_RESUME:
572 devfreq_monitor_resume(devfreq);
573 tegra_actmon_start(tegra);
574 break;
575 }
576
577 return 0;
578}
579
580static struct devfreq_governor tegra_devfreq_governor = {
581 .name = "tegra_actmon",
582 .get_target_freq = tegra_governor_get_target,
583 .event_handler = tegra_governor_event_handler,
584 .immutable = true,
585};
586
587static int tegra_devfreq_probe(struct platform_device *pdev)
588{
589 struct tegra_devfreq *tegra;
590 struct tegra_devfreq_device *dev;
591 unsigned int i;
592 unsigned long rate;
593 int err;
594
595 tegra = devm_kzalloc(&pdev->dev, sizeof(*tegra), GFP_KERNEL);
596 if (!tegra)
597 return -ENOMEM;
598
599 tegra->regs = devm_platform_ioremap_resource(pdev, 0);
600 if (IS_ERR(tegra->regs))
601 return PTR_ERR(tegra->regs);
602
603 tegra->reset = devm_reset_control_get(&pdev->dev, "actmon");
604 if (IS_ERR(tegra->reset)) {
605 dev_err(&pdev->dev, "Failed to get reset\n");
606 return PTR_ERR(tegra->reset);
607 }
608
609 tegra->clock = devm_clk_get(&pdev->dev, "actmon");
610 if (IS_ERR(tegra->clock)) {
611 dev_err(&pdev->dev, "Failed to get actmon clock\n");
612 return PTR_ERR(tegra->clock);
613 }
614
615 tegra->emc_clock = devm_clk_get(&pdev->dev, "emc");
616 if (IS_ERR(tegra->emc_clock)) {
617 dev_err(&pdev->dev, "Failed to get emc clock\n");
618 return PTR_ERR(tegra->emc_clock);
619 }
620
621 tegra->irq = platform_get_irq(pdev, 0);
622 if (tegra->irq < 0) {
623 err = tegra->irq;
624 dev_err(&pdev->dev, "Failed to get IRQ: %d\n", err);
625 return err;
626 }
627
628 reset_control_assert(tegra->reset);
629
630 err = clk_prepare_enable(tegra->clock);
631 if (err) {
632 dev_err(&pdev->dev,
633 "Failed to prepare and enable ACTMON clock\n");
634 return err;
635 }
636
637 reset_control_deassert(tegra->reset);
638
639 tegra->max_freq = clk_round_rate(tegra->emc_clock, ULONG_MAX) / KHZ;
640 tegra->cur_freq = clk_get_rate(tegra->emc_clock) / KHZ;
641
642 for (i = 0; i < ARRAY_SIZE(actmon_device_configs); i++) {
643 dev = tegra->devices + i;
644 dev->config = actmon_device_configs + i;
645 dev->regs = tegra->regs + dev->config->offset;
646 }
647
648 for (rate = 0; rate <= tegra->max_freq * KHZ; rate++) {
649 rate = clk_round_rate(tegra->emc_clock, rate);
650
651 err = dev_pm_opp_add(&pdev->dev, rate, 0);
652 if (err) {
653 dev_err(&pdev->dev, "Failed to add OPP: %d\n", err);
654 goto remove_opps;
655 }
656 }
657
658 platform_set_drvdata(pdev, tegra);
659
660 tegra->rate_change_nb.notifier_call = tegra_actmon_rate_notify_cb;
661 err = clk_notifier_register(tegra->emc_clock, &tegra->rate_change_nb);
662 if (err) {
663 dev_err(&pdev->dev,
664 "Failed to register rate change notifier\n");
665 goto remove_opps;
666 }
667
668 err = devfreq_add_governor(&tegra_devfreq_governor);
669 if (err) {
670 dev_err(&pdev->dev, "Failed to add governor: %d\n", err);
671 goto unreg_notifier;
672 }
673
674 tegra_devfreq_profile.initial_freq = clk_get_rate(tegra->emc_clock);
675 tegra->devfreq = devfreq_add_device(&pdev->dev,
676 &tegra_devfreq_profile,
677 "tegra_actmon",
678 NULL);
679 if (IS_ERR(tegra->devfreq)) {
680 err = PTR_ERR(tegra->devfreq);
681 goto remove_governor;
682 }
683
684 err = devm_request_threaded_irq(&pdev->dev, tegra->irq, NULL,
685 actmon_thread_isr, IRQF_ONESHOT,
686 "tegra-devfreq", tegra);
687 if (err) {
688 dev_err(&pdev->dev, "Interrupt request failed: %d\n", err);
689 goto remove_devfreq;
690 }
691
692 return 0;
693
694remove_devfreq:
695 devfreq_remove_device(tegra->devfreq);
696
697remove_governor:
698 devfreq_remove_governor(&tegra_devfreq_governor);
699
700unreg_notifier:
701 clk_notifier_unregister(tegra->emc_clock, &tegra->rate_change_nb);
702
703remove_opps:
704 dev_pm_opp_remove_all_dynamic(&pdev->dev);
705
706 reset_control_reset(tegra->reset);
707 clk_disable_unprepare(tegra->clock);
708
709 return err;
710}
711
712static int tegra_devfreq_remove(struct platform_device *pdev)
713{
714 struct tegra_devfreq *tegra = platform_get_drvdata(pdev);
715
716 devfreq_remove_device(tegra->devfreq);
717 devfreq_remove_governor(&tegra_devfreq_governor);
718
719 clk_notifier_unregister(tegra->emc_clock, &tegra->rate_change_nb);
720 dev_pm_opp_remove_all_dynamic(&pdev->dev);
721
722 reset_control_reset(tegra->reset);
723 clk_disable_unprepare(tegra->clock);
724
725 return 0;
726}
727
728static const struct of_device_id tegra_devfreq_of_match[] = {
729 { .compatible = "nvidia,tegra30-actmon" },
730 { .compatible = "nvidia,tegra124-actmon" },
731 { },
732};
733
734MODULE_DEVICE_TABLE(of, tegra_devfreq_of_match);
735
736static struct platform_driver tegra_devfreq_driver = {
737 .probe = tegra_devfreq_probe,
738 .remove = tegra_devfreq_remove,
739 .driver = {
740 .name = "tegra-devfreq",
741 .of_match_table = tegra_devfreq_of_match,
742 },
743};
744module_platform_driver(tegra_devfreq_driver);
745
746MODULE_LICENSE("GPL v2");
747MODULE_DESCRIPTION("Tegra devfreq driver");
748MODULE_AUTHOR("Tomeu Vizoso <tomeu.vizoso@collabora.com>");