aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/devfreq/tegra-devfreq.c
diff options
context:
space:
mode:
authorTomeu Vizoso <tomeu.vizoso@collabora.com>2015-03-17 05:36:12 -0400
committerMyungJoo Ham <myungjoo.ham@samsung.com>2015-03-31 00:17:03 -0400
commit11573e9132ae40239195fe5162d48caf2b7d85bb (patch)
tree729a8ade4554be982674e84f18827f57f65f0b84 /drivers/devfreq/tegra-devfreq.c
parent4b524f12188c20c64c602ff09ba26a5d39d16b1c (diff)
PM / devfreq: tegra: Update to v5 of the submitted patches
There seemed to be some miscommunication and an old version of the submitted patches was merged. This commit updates the driver to v5, which had this changelog: * Clarify the units of avg_dependency_threshold * Remove unused references to platform_device * Enable and disable interrupts on governor events * Make sure we handle all interrupts for any of the devices we are sampling * Move locking to be per-actmon-device Signed-off-by: Tomeu Vizoso <tomeu.vizoso@collabora.com> CC: Alex Frid <afrid@nvidia.com> CC: Mikko Perttunen <mikko.perttunen@kapsi.fi> [Added const to device ID by MyungJoo] Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
Diffstat (limited to 'drivers/devfreq/tegra-devfreq.c')
-rw-r--r--drivers/devfreq/tegra-devfreq.c457
1 files changed, 253 insertions, 204 deletions
diff --git a/drivers/devfreq/tegra-devfreq.c b/drivers/devfreq/tegra-devfreq.c
index 34790961af5a..d2f4d5ecaefd 100644
--- a/drivers/devfreq/tegra-devfreq.c
+++ b/drivers/devfreq/tegra-devfreq.c
@@ -62,7 +62,8 @@
62#define ACTMON_BELOW_WMARK_WINDOW 3 62#define ACTMON_BELOW_WMARK_WINDOW 3
63#define ACTMON_BOOST_FREQ_STEP 16000 63#define ACTMON_BOOST_FREQ_STEP 16000
64 64
65/* activity counter is incremented every 256 memory transactions, and each 65/*
66 * Activity counter is incremented every 256 memory transactions, and each
66 * transaction takes 4 EMC clocks for Tegra124; So the COUNT_WEIGHT is 67 * transaction takes 4 EMC clocks for Tegra124; So the COUNT_WEIGHT is
67 * 4 * 256 = 1024. 68 * 4 * 256 = 1024.
68 */ 69 */
@@ -85,16 +86,25 @@
85 * struct tegra_devfreq_device_config - configuration specific to an ACTMON 86 * struct tegra_devfreq_device_config - configuration specific to an ACTMON
86 * device 87 * device
87 * 88 *
88 * Coefficients and thresholds are in % 89 * Coefficients and thresholds are percentages unless otherwise noted
89 */ 90 */
90struct tegra_devfreq_device_config { 91struct tegra_devfreq_device_config {
91 u32 offset; 92 u32 offset;
92 u32 irq_mask; 93 u32 irq_mask;
93 94
95 /* Factors applied to boost_freq every consecutive watermark breach */
94 unsigned int boost_up_coeff; 96 unsigned int boost_up_coeff;
95 unsigned int boost_down_coeff; 97 unsigned int boost_down_coeff;
98
99 /* Define the watermark bounds when applied to the current avg */
96 unsigned int boost_up_threshold; 100 unsigned int boost_up_threshold;
97 unsigned int boost_down_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 */
98 u32 avg_dependency_threshold; 108 u32 avg_dependency_threshold;
99}; 109};
100 110
@@ -105,7 +115,7 @@ enum tegra_actmon_device {
105 115
106static struct tegra_devfreq_device_config actmon_device_configs[] = { 116static struct tegra_devfreq_device_config actmon_device_configs[] = {
107 { 117 {
108 /* MCALL */ 118 /* MCALL: All memory accesses (including from the CPUs) */
109 .offset = 0x1c0, 119 .offset = 0x1c0,
110 .irq_mask = 1 << 26, 120 .irq_mask = 1 << 26,
111 .boost_up_coeff = 200, 121 .boost_up_coeff = 200,
@@ -114,7 +124,7 @@ static struct tegra_devfreq_device_config actmon_device_configs[] = {
114 .boost_down_threshold = 40, 124 .boost_down_threshold = 40,
115 }, 125 },
116 { 126 {
117 /* MCCPU */ 127 /* MCCPU: memory accesses from the CPUs */
118 .offset = 0x200, 128 .offset = 0x200,
119 .irq_mask = 1 << 25, 129 .irq_mask = 1 << 25,
120 .boost_up_coeff = 800, 130 .boost_up_coeff = 800,
@@ -132,25 +142,29 @@ static struct tegra_devfreq_device_config actmon_device_configs[] = {
132 */ 142 */
133struct tegra_devfreq_device { 143struct tegra_devfreq_device {
134 const struct tegra_devfreq_device_config *config; 144 const struct tegra_devfreq_device_config *config;
145 void __iomem *regs;
146 spinlock_t lock;
135 147
136 void __iomem *regs; 148 /* Average event count sampled in the last interrupt */
137 u32 avg_band_freq; 149 u32 avg_count;
138 u32 avg_count;
139 150
140 unsigned long target_freq; 151 /*
141 unsigned long boost_freq; 152 * Extra frequency to increase the target by due to consecutive
153 * watermark breaches.
154 */
155 unsigned long boost_freq;
156
157 /* Optimal frequency calculated from the stats for this device */
158 unsigned long target_freq;
142}; 159};
143 160
144struct tegra_devfreq { 161struct tegra_devfreq {
145 struct devfreq *devfreq; 162 struct devfreq *devfreq;
146 163
147 struct platform_device *pdev;
148 struct reset_control *reset; 164 struct reset_control *reset;
149 struct clk *clock; 165 struct clk *clock;
150 void __iomem *regs; 166 void __iomem *regs;
151 167
152 spinlock_t lock;
153
154 struct clk *emc_clock; 168 struct clk *emc_clock;
155 unsigned long max_freq; 169 unsigned long max_freq;
156 unsigned long cur_freq; 170 unsigned long cur_freq;
@@ -174,19 +188,43 @@ static struct tegra_actmon_emc_ratio actmon_emc_ratios[] = {
174 { 250000, 100000 }, 188 { 250000, 100000 },
175}; 189};
176 190
191static u32 actmon_readl(struct tegra_devfreq *tegra, u32 offset)
192{
193 return readl(tegra->regs + offset);
194}
195
196static void actmon_writel(struct tegra_devfreq *tegra, u32 val, u32 offset)
197{
198 writel(val, tegra->regs + offset);
199}
200
201static u32 device_readl(struct tegra_devfreq_device *dev, u32 offset)
202{
203 return readl(dev->regs + offset);
204}
205
206static void device_writel(struct tegra_devfreq_device *dev, u32 val,
207 u32 offset)
208{
209 writel(val, dev->regs + offset);
210}
211
177static unsigned long do_percent(unsigned long val, unsigned int pct) 212static unsigned long do_percent(unsigned long val, unsigned int pct)
178{ 213{
179 return val * pct / 100; 214 return val * pct / 100;
180} 215}
181 216
182static void tegra_devfreq_update_avg_wmark(struct tegra_devfreq_device *dev) 217static void tegra_devfreq_update_avg_wmark(struct tegra_devfreq *tegra,
218 struct tegra_devfreq_device *dev)
183{ 219{
184 u32 avg = dev->avg_count; 220 u32 avg = dev->avg_count;
185 u32 band = dev->avg_band_freq * ACTMON_SAMPLING_PERIOD; 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);
186 225
187 writel(avg + band, dev->regs + ACTMON_DEV_AVG_UPPER_WMARK); 226 avg = max(dev->avg_count, band);
188 avg = max(avg, band); 227 device_writel(dev, avg - band, ACTMON_DEV_AVG_LOWER_WMARK);
189 writel(avg - band, dev->regs + ACTMON_DEV_AVG_LOWER_WMARK);
190} 228}
191 229
192static void tegra_devfreq_update_wmark(struct tegra_devfreq *tegra, 230static void tegra_devfreq_update_wmark(struct tegra_devfreq *tegra,
@@ -194,96 +232,96 @@ static void tegra_devfreq_update_wmark(struct tegra_devfreq *tegra,
194{ 232{
195 u32 val = tegra->cur_freq * ACTMON_SAMPLING_PERIOD; 233 u32 val = tegra->cur_freq * ACTMON_SAMPLING_PERIOD;
196 234
197 writel(do_percent(val, dev->config->boost_up_threshold), 235 device_writel(dev, do_percent(val, dev->config->boost_up_threshold),
198 dev->regs + ACTMON_DEV_UPPER_WMARK); 236 ACTMON_DEV_UPPER_WMARK);
199 237
200 writel(do_percent(val, dev->config->boost_down_threshold), 238 device_writel(dev, do_percent(val, dev->config->boost_down_threshold),
201 dev->regs + ACTMON_DEV_LOWER_WMARK); 239 ACTMON_DEV_LOWER_WMARK);
202} 240}
203 241
204static void actmon_write_barrier(struct tegra_devfreq *tegra) 242static void actmon_write_barrier(struct tegra_devfreq *tegra)
205{ 243{
206 /* ensure the update has reached the ACTMON */ 244 /* ensure the update has reached the ACTMON */
207 wmb(); 245 wmb();
208 readl(tegra->regs + ACTMON_GLB_STATUS); 246 actmon_readl(tegra, ACTMON_GLB_STATUS);
209} 247}
210 248
211static irqreturn_t actmon_isr(int irq, void *data) 249static void actmon_isr_device(struct tegra_devfreq *tegra,
250 struct tegra_devfreq_device *dev)
212{ 251{
213 struct tegra_devfreq *tegra = data;
214 struct tegra_devfreq_device *dev = NULL;
215 unsigned long flags; 252 unsigned long flags;
216 u32 val; 253 u32 intr_status, dev_ctrl;
217 unsigned int i;
218 254
219 val = readl(tegra->regs + ACTMON_GLB_STATUS); 255 spin_lock_irqsave(&dev->lock, flags);
220 256
221 for (i = 0; i < ARRAY_SIZE(tegra->devices); i++) { 257 dev->avg_count = device_readl(dev, ACTMON_DEV_AVG_COUNT);
222 if (val & tegra->devices[i].config->irq_mask) { 258 tegra_devfreq_update_avg_wmark(tegra, dev);
223 dev = tegra->devices + i;
224 break;
225 }
226 }
227
228 if (!dev)
229 return IRQ_NONE;
230
231 spin_lock_irqsave(&tegra->lock, flags);
232
233 dev->avg_count = readl(dev->regs + ACTMON_DEV_AVG_COUNT);
234 tegra_devfreq_update_avg_wmark(dev);
235 259
236 val = readl(dev->regs + ACTMON_DEV_INTR_STATUS); 260 intr_status = device_readl(dev, ACTMON_DEV_INTR_STATUS);
237 if (val & ACTMON_DEV_INTR_CONSECUTIVE_UPPER) { 261 dev_ctrl = device_readl(dev, ACTMON_DEV_CTRL);
238 val = readl(dev->regs + ACTMON_DEV_CTRL) |
239 ACTMON_DEV_CTRL_CONSECUTIVE_ABOVE_WMARK_EN |
240 ACTMON_DEV_CTRL_CONSECUTIVE_BELOW_WMARK_EN;
241 262
263 if (intr_status & ACTMON_DEV_INTR_CONSECUTIVE_UPPER) {
242 /* 264 /*
243 * new_boost = min(old_boost * up_coef + step, max_freq) 265 * new_boost = min(old_boost * up_coef + step, max_freq)
244 */ 266 */
245 dev->boost_freq = do_percent(dev->boost_freq, 267 dev->boost_freq = do_percent(dev->boost_freq,
246 dev->config->boost_up_coeff); 268 dev->config->boost_up_coeff);
247 dev->boost_freq += ACTMON_BOOST_FREQ_STEP; 269 dev->boost_freq += ACTMON_BOOST_FREQ_STEP;
248 if (dev->boost_freq >= tegra->max_freq) {
249 dev->boost_freq = tegra->max_freq;
250 val &= ~ACTMON_DEV_CTRL_CONSECUTIVE_ABOVE_WMARK_EN;
251 }
252 writel(val, dev->regs + ACTMON_DEV_CTRL);
253 } else if (val & ACTMON_DEV_INTR_CONSECUTIVE_LOWER) {
254 val = readl(dev->regs + ACTMON_DEV_CTRL) |
255 ACTMON_DEV_CTRL_CONSECUTIVE_ABOVE_WMARK_EN |
256 ACTMON_DEV_CTRL_CONSECUTIVE_BELOW_WMARK_EN;
257 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) {
258 /* 278 /*
259 * new_boost = old_boost * down_coef 279 * new_boost = old_boost * down_coef
260 * or 0 if (old_boost * down_coef < step / 2) 280 * or 0 if (old_boost * down_coef < step / 2)
261 */ 281 */
262 dev->boost_freq = do_percent(dev->boost_freq, 282 dev->boost_freq = do_percent(dev->boost_freq,
263 dev->config->boost_down_coeff); 283 dev->config->boost_down_coeff);
264 if (dev->boost_freq < (ACTMON_BOOST_FREQ_STEP >> 1)) { 284
285 dev_ctrl |= ACTMON_DEV_CTRL_CONSECUTIVE_ABOVE_WMARK_EN;
286
287 if (dev->boost_freq < (ACTMON_BOOST_FREQ_STEP >> 1))
265 dev->boost_freq = 0; 288 dev->boost_freq = 0;
266 val &= ~ACTMON_DEV_CTRL_CONSECUTIVE_BELOW_WMARK_EN; 289 else
267 } 290 dev_ctrl |= ACTMON_DEV_CTRL_CONSECUTIVE_BELOW_WMARK_EN;
268 writel(val, dev->regs + ACTMON_DEV_CTRL);
269 } 291 }
270 292
271 if (dev->config->avg_dependency_threshold) { 293 if (dev->config->avg_dependency_threshold) {
272 val = readl(dev->regs + ACTMON_DEV_CTRL);
273 if (dev->avg_count >= dev->config->avg_dependency_threshold) 294 if (dev->avg_count >= dev->config->avg_dependency_threshold)
274 val |= ACTMON_DEV_CTRL_CONSECUTIVE_BELOW_WMARK_EN; 295 dev_ctrl |= ACTMON_DEV_CTRL_CONSECUTIVE_BELOW_WMARK_EN;
275 else if (dev->boost_freq == 0) 296 else if (dev->boost_freq == 0)
276 val &= ~ACTMON_DEV_CTRL_CONSECUTIVE_BELOW_WMARK_EN; 297 dev_ctrl &= ~ACTMON_DEV_CTRL_CONSECUTIVE_BELOW_WMARK_EN;
277 writel(val, dev->regs + ACTMON_DEV_CTRL);
278 } 298 }
279 299
280 writel(ACTMON_INTR_STATUS_CLEAR, dev->regs + ACTMON_DEV_INTR_STATUS); 300 device_writel(dev, dev_ctrl, ACTMON_DEV_CTRL);
301
302 device_writel(dev, ACTMON_INTR_STATUS_CLEAR, ACTMON_DEV_INTR_STATUS);
281 303
282 actmon_write_barrier(tegra); 304 actmon_write_barrier(tegra);
283 305
284 spin_unlock_irqrestore(&tegra->lock, flags); 306 spin_unlock_irqrestore(&dev->lock, flags);
307}
285 308
286 return IRQ_WAKE_THREAD; 309static 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;
287} 325}
288 326
289static unsigned long actmon_cpu_to_emc_rate(struct tegra_devfreq *tegra, 327static unsigned long actmon_cpu_to_emc_rate(struct tegra_devfreq *tegra,
@@ -317,7 +355,7 @@ static void actmon_update_target(struct tegra_devfreq *tegra,
317 static_cpu_emc_freq = actmon_cpu_to_emc_rate(tegra, cpu_freq); 355 static_cpu_emc_freq = actmon_cpu_to_emc_rate(tegra, cpu_freq);
318 } 356 }
319 357
320 spin_lock_irqsave(&tegra->lock, flags); 358 spin_lock_irqsave(&dev->lock, flags);
321 359
322 dev->target_freq = dev->avg_count / ACTMON_SAMPLING_PERIOD; 360 dev->target_freq = dev->avg_count / ACTMON_SAMPLING_PERIOD;
323 avg_sustain_coef = 100 * 100 / dev->config->boost_up_threshold; 361 avg_sustain_coef = 100 * 100 / dev->config->boost_up_threshold;
@@ -327,7 +365,7 @@ static void actmon_update_target(struct tegra_devfreq *tegra,
327 if (dev->avg_count >= dev->config->avg_dependency_threshold) 365 if (dev->avg_count >= dev->config->avg_dependency_threshold)
328 dev->target_freq = max(dev->target_freq, static_cpu_emc_freq); 366 dev->target_freq = max(dev->target_freq, static_cpu_emc_freq);
329 367
330 spin_unlock_irqrestore(&tegra->lock, flags); 368 spin_unlock_irqrestore(&dev->lock, flags);
331} 369}
332 370
333static irqreturn_t actmon_thread_isr(int irq, void *data) 371static irqreturn_t actmon_thread_isr(int irq, void *data)
@@ -345,131 +383,110 @@ static int tegra_actmon_rate_notify_cb(struct notifier_block *nb,
345 unsigned long action, void *ptr) 383 unsigned long action, void *ptr)
346{ 384{
347 struct clk_notifier_data *data = ptr; 385 struct clk_notifier_data *data = ptr;
348 struct tegra_devfreq *tegra = container_of(nb, struct tegra_devfreq, 386 struct tegra_devfreq *tegra;
349 rate_change_nb); 387 struct tegra_devfreq_device *dev;
350 unsigned int i; 388 unsigned int i;
351 unsigned long flags; 389 unsigned long flags;
352 390
353 spin_lock_irqsave(&tegra->lock, flags); 391 if (action != POST_RATE_CHANGE)
392 return NOTIFY_OK;
354 393
355 switch (action) { 394 tegra = container_of(nb, struct tegra_devfreq, rate_change_nb);
356 case POST_RATE_CHANGE:
357 tegra->cur_freq = data->new_rate / KHZ;
358 395
359 for (i = 0; i < ARRAY_SIZE(tegra->devices); i++) 396 tegra->cur_freq = data->new_rate / KHZ;
360 tegra_devfreq_update_wmark(tegra, tegra->devices + i);
361 397
362 actmon_write_barrier(tegra); 398 for (i = 0; i < ARRAY_SIZE(tegra->devices); i++) {
363 break; 399 dev = &tegra->devices[i];
364 case PRE_RATE_CHANGE: 400
365 /* fall through */ 401 spin_lock_irqsave(&dev->lock, flags);
366 case ABORT_RATE_CHANGE: 402 tegra_devfreq_update_wmark(tegra, dev);
367 break; 403 spin_unlock_irqrestore(&dev->lock, flags);
368 }; 404 }
369 405
370 spin_unlock_irqrestore(&tegra->lock, flags); 406 actmon_write_barrier(tegra);
371 407
372 return NOTIFY_OK; 408 return NOTIFY_OK;
373} 409}
374 410
375static void tegra_actmon_configure_device(struct tegra_devfreq *tegra, 411static void tegra_actmon_enable_interrupts(struct tegra_devfreq *tegra)
376 struct tegra_devfreq_device *dev)
377{ 412{
413 struct tegra_devfreq_device *dev;
378 u32 val; 414 u32 val;
415 unsigned int i;
379 416
380 dev->avg_band_freq = tegra->max_freq * ACTMON_DEFAULT_AVG_BAND / KHZ; 417 for (i = 0; i < ARRAY_SIZE(tegra->devices); i++) {
381 dev->target_freq = tegra->cur_freq; 418 dev = &tegra->devices[i];
382
383 dev->avg_count = tegra->cur_freq * ACTMON_SAMPLING_PERIOD;
384 writel(dev->avg_count, dev->regs + ACTMON_DEV_INIT_AVG);
385
386 tegra_devfreq_update_avg_wmark(dev);
387 tegra_devfreq_update_wmark(tegra, dev);
388
389 writel(ACTMON_COUNT_WEIGHT, dev->regs + ACTMON_DEV_COUNT_WEIGHT);
390 writel(ACTMON_INTR_STATUS_CLEAR, dev->regs + ACTMON_DEV_INTR_STATUS);
391
392 val = 0;
393 val |= ACTMON_DEV_CTRL_ENB_PERIODIC |
394 ACTMON_DEV_CTRL_AVG_ABOVE_WMARK_EN |
395 ACTMON_DEV_CTRL_AVG_BELOW_WMARK_EN;
396 val |= (ACTMON_AVERAGE_WINDOW_LOG2 - 1)
397 << ACTMON_DEV_CTRL_K_VAL_SHIFT;
398 val |= (ACTMON_BELOW_WMARK_WINDOW - 1)
399 << ACTMON_DEV_CTRL_CONSECUTIVE_BELOW_WMARK_NUM_SHIFT;
400 val |= (ACTMON_ABOVE_WMARK_WINDOW - 1)
401 << ACTMON_DEV_CTRL_CONSECUTIVE_ABOVE_WMARK_NUM_SHIFT;
402 val |= ACTMON_DEV_CTRL_CONSECUTIVE_BELOW_WMARK_EN |
403 ACTMON_DEV_CTRL_CONSECUTIVE_ABOVE_WMARK_EN;
404
405 writel(val, dev->regs + ACTMON_DEV_CTRL);
406 419
407 actmon_write_barrier(tegra); 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;
408 425
409 val = readl(dev->regs + ACTMON_DEV_CTRL); 426 device_writel(dev, val, ACTMON_DEV_CTRL);
410 val |= ACTMON_DEV_CTRL_ENB; 427 }
411 writel(val, dev->regs + ACTMON_DEV_CTRL);
412 428
413 actmon_write_barrier(tegra); 429 actmon_write_barrier(tegra);
414} 430}
415 431
416static int tegra_devfreq_suspend(struct device *dev) 432static void tegra_actmon_disable_interrupts(struct tegra_devfreq *tegra)
417{ 433{
418 struct platform_device *pdev; 434 struct tegra_devfreq_device *dev;
419 struct tegra_devfreq *tegra;
420 struct tegra_devfreq_device *actmon_dev;
421 unsigned int i;
422 u32 val; 435 u32 val;
423 436 unsigned int i;
424 pdev = container_of(dev, struct platform_device, dev);
425 tegra = platform_get_drvdata(pdev);
426 437
427 for (i = 0; i < ARRAY_SIZE(tegra->devices); i++) { 438 for (i = 0; i < ARRAY_SIZE(tegra->devices); i++) {
428 actmon_dev = &tegra->devices[i]; 439 dev = &tegra->devices[i];
429
430 val = readl(actmon_dev->regs + ACTMON_DEV_CTRL);
431 val &= ~ACTMON_DEV_CTRL_ENB;
432 writel(val, actmon_dev->regs + ACTMON_DEV_CTRL);
433 440
434 writel(ACTMON_INTR_STATUS_CLEAR, 441 val = device_readl(dev, ACTMON_DEV_CTRL);
435 actmon_dev->regs + ACTMON_DEV_INTR_STATUS); 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;
436 446
437 actmon_write_barrier(tegra); 447 device_writel(dev, val, ACTMON_DEV_CTRL);
438 } 448 }
439 449
440 return 0; 450 actmon_write_barrier(tegra);
441} 451}
442 452
443static int tegra_devfreq_resume(struct device *dev) 453static void tegra_actmon_configure_device(struct tegra_devfreq *tegra,
454 struct tegra_devfreq_device *dev)
444{ 455{
445 struct platform_device *pdev; 456 u32 val = 0;
446 struct tegra_devfreq *tegra;
447 struct tegra_devfreq_device *actmon_dev;
448 unsigned int i;
449 457
450 pdev = container_of(dev, struct platform_device, dev); 458 dev->target_freq = tegra->cur_freq;
451 tegra = platform_get_drvdata(pdev);
452 459
453 for (i = 0; i < ARRAY_SIZE(tegra->devices); i++) { 460 dev->avg_count = tegra->cur_freq * ACTMON_SAMPLING_PERIOD;
454 actmon_dev = &tegra->devices[i]; 461 device_writel(dev, dev->avg_count, ACTMON_DEV_INIT_AVG);
455 462
456 tegra_actmon_configure_device(tegra, actmon_dev); 463 tegra_devfreq_update_avg_wmark(tegra, dev);
457 } 464 tegra_devfreq_update_wmark(tegra, dev);
458 465
459 return 0; 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);
460} 481}
461 482
462static int tegra_devfreq_target(struct device *dev, unsigned long *freq, 483static int tegra_devfreq_target(struct device *dev, unsigned long *freq,
463 u32 flags) 484 u32 flags)
464{ 485{
465 struct platform_device *pdev; 486 struct tegra_devfreq *tegra = dev_get_drvdata(dev);
466 struct tegra_devfreq *tegra;
467 struct dev_pm_opp *opp; 487 struct dev_pm_opp *opp;
468 unsigned long rate = *freq * KHZ; 488 unsigned long rate = *freq * KHZ;
469 489
470 pdev = container_of(dev, struct platform_device, dev);
471 tegra = platform_get_drvdata(pdev);
472
473 rcu_read_lock(); 490 rcu_read_lock();
474 opp = devfreq_recommended_opp(dev, &rate, flags); 491 opp = devfreq_recommended_opp(dev, &rate, flags);
475 if (IS_ERR(opp)) { 492 if (IS_ERR(opp)) {
@@ -491,13 +508,9 @@ static int tegra_devfreq_target(struct device *dev, unsigned long *freq,
491static int tegra_devfreq_get_dev_status(struct device *dev, 508static int tegra_devfreq_get_dev_status(struct device *dev,
492 struct devfreq_dev_status *stat) 509 struct devfreq_dev_status *stat)
493{ 510{
494 struct platform_device *pdev; 511 struct tegra_devfreq *tegra = dev_get_drvdata(dev);
495 struct tegra_devfreq *tegra;
496 struct tegra_devfreq_device *actmon_dev; 512 struct tegra_devfreq_device *actmon_dev;
497 513
498 pdev = container_of(dev, struct platform_device, dev);
499 tegra = platform_get_drvdata(pdev);
500
501 stat->current_frequency = tegra->cur_freq; 514 stat->current_frequency = tegra->cur_freq;
502 515
503 /* To be used by the tegra governor */ 516 /* To be used by the tegra governor */
@@ -508,7 +521,7 @@ static int tegra_devfreq_get_dev_status(struct device *dev,
508 actmon_dev = &tegra->devices[MCALL]; 521 actmon_dev = &tegra->devices[MCALL];
509 522
510 /* Number of cycles spent on memory access */ 523 /* Number of cycles spent on memory access */
511 stat->busy_time = actmon_dev->avg_count; 524 stat->busy_time = device_readl(actmon_dev, ACTMON_DEV_AVG_COUNT);
512 525
513 /* The bus can be considered to be saturated way before 100% */ 526 /* The bus can be considered to be saturated way before 100% */
514 stat->busy_time *= 100 / BUS_SATURATION_RATIO; 527 stat->busy_time *= 100 / BUS_SATURATION_RATIO;
@@ -516,11 +529,19 @@ static int tegra_devfreq_get_dev_status(struct device *dev,
516 /* Number of cycles in a sampling period */ 529 /* Number of cycles in a sampling period */
517 stat->total_time = ACTMON_SAMPLING_PERIOD * tegra->cur_freq; 530 stat->total_time = ACTMON_SAMPLING_PERIOD * tegra->cur_freq;
518 531
532 stat->busy_time = min(stat->busy_time, stat->total_time);
533
519 return 0; 534 return 0;
520} 535}
521 536
522static int tegra_devfreq_get_target(struct devfreq *devfreq, 537static struct devfreq_dev_profile tegra_devfreq_profile = {
523 unsigned long *freq) 538 .polling_ms = 0,
539 .target = tegra_devfreq_target,
540 .get_dev_status = tegra_devfreq_get_dev_status,
541};
542
543static int tegra_governor_get_target(struct devfreq *devfreq,
544 unsigned long *freq)
524{ 545{
525 struct devfreq_dev_status stat; 546 struct devfreq_dev_status stat;
526 struct tegra_devfreq *tegra; 547 struct tegra_devfreq *tegra;
@@ -548,23 +569,50 @@ static int tegra_devfreq_get_target(struct devfreq *devfreq,
548 return 0; 569 return 0;
549} 570}
550 571
551static int tegra_devfreq_event_handler(struct devfreq *devfreq, 572static int tegra_governor_event_handler(struct devfreq *devfreq,
552 unsigned int event, void *data) 573 unsigned int event, void *data)
553{ 574{
554 return 0; 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 tegra_actmon_enable_interrupts(tegra);
583 devfreq_monitor_start(devfreq);
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 tegra_actmon_enable_interrupts(tegra);
598 devfreq_monitor_resume(devfreq);
599 break;
600 }
601
602 return ret;
555} 603}
556 604
557static struct devfreq_governor tegra_devfreq_governor = { 605static struct devfreq_governor tegra_devfreq_governor = {
558 .name = "tegra", 606 .name = "tegra_actmon",
559 .get_target_freq = tegra_devfreq_get_target, 607 .get_target_freq = tegra_governor_get_target,
560 .event_handler = tegra_devfreq_event_handler, 608 .event_handler = tegra_governor_event_handler,
561}; 609};
562 610
563static struct devfreq_dev_profile tegra_devfreq_profile = { 611static int __init tegra_governor_init(void)
564 .polling_ms = 0, 612{
565 .target = tegra_devfreq_target, 613 return devfreq_add_governor(&tegra_devfreq_governor);
566 .get_dev_status = tegra_devfreq_get_dev_status, 614}
567}; 615subsys_initcall(tegra_governor_init);
568 616
569static int tegra_devfreq_probe(struct platform_device *pdev) 617static int tegra_devfreq_probe(struct platform_device *pdev)
570{ 618{
@@ -580,19 +628,11 @@ static int tegra_devfreq_probe(struct platform_device *pdev)
580 if (!tegra) 628 if (!tegra)
581 return -ENOMEM; 629 return -ENOMEM;
582 630
583 spin_lock_init(&tegra->lock);
584
585 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 631 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
586 if (!res) {
587 dev_err(&pdev->dev, "Failed to get regs resource\n");
588 return -ENODEV;
589 }
590 632
591 tegra->regs = devm_ioremap_resource(&pdev->dev, res); 633 tegra->regs = devm_ioremap_resource(&pdev->dev, res);
592 if (IS_ERR(tegra->regs)) { 634 if (IS_ERR(tegra->regs))
593 dev_err(&pdev->dev, "Failed to get IO memory\n");
594 return PTR_ERR(tegra->regs); 635 return PTR_ERR(tegra->regs);
595 }
596 636
597 tegra->reset = devm_reset_control_get(&pdev->dev, "actmon"); 637 tegra->reset = devm_reset_control_get(&pdev->dev, "actmon");
598 if (IS_ERR(tegra->reset)) { 638 if (IS_ERR(tegra->reset)) {
@@ -630,7 +670,8 @@ static int tegra_devfreq_probe(struct platform_device *pdev)
630 670
631 err = clk_prepare_enable(tegra->clock); 671 err = clk_prepare_enable(tegra->clock);
632 if (err) { 672 if (err) {
633 reset_control_deassert(tegra->reset); 673 dev_err(&pdev->dev,
674 "Failed to prepare and enable ACTMON clock\n");
634 return err; 675 return err;
635 } 676 }
636 677
@@ -643,30 +684,24 @@ static int tegra_devfreq_probe(struct platform_device *pdev)
643 684
644 tegra->cur_freq = clk_get_rate(tegra->emc_clock) / KHZ; 685 tegra->cur_freq = clk_get_rate(tegra->emc_clock) / KHZ;
645 686
646 writel(ACTMON_SAMPLING_PERIOD - 1, 687 actmon_writel(tegra, ACTMON_SAMPLING_PERIOD - 1,
647 tegra->regs + ACTMON_GLB_PERIOD_CTRL); 688 ACTMON_GLB_PERIOD_CTRL);
648 689
649 for (i = 0; i < ARRAY_SIZE(actmon_device_configs); i++) { 690 for (i = 0; i < ARRAY_SIZE(actmon_device_configs); i++) {
650 dev = tegra->devices + i; 691 dev = tegra->devices + i;
651 dev->config = actmon_device_configs + i; 692 dev->config = actmon_device_configs + i;
652 dev->regs = tegra->regs + dev->config->offset; 693 dev->regs = tegra->regs + dev->config->offset;
694 spin_lock_init(&dev->lock);
653 695
654 tegra_actmon_configure_device(tegra, tegra->devices + i); 696 tegra_actmon_configure_device(tegra, dev);
655 } 697 }
656 698
657 err = devfreq_add_governor(&tegra_devfreq_governor); 699 irq = platform_get_irq(pdev, 0);
658 if (err) { 700 if (irq <= 0) {
659 dev_err(&pdev->dev, "Failed to add governor\n"); 701 dev_err(&pdev->dev, "Failed to get IRQ\n");
660 return err; 702 return -ENODEV;
661 } 703 }
662 704
663 tegra_devfreq_profile.initial_freq = clk_get_rate(tegra->emc_clock);
664 tegra->devfreq = devm_devfreq_add_device(&pdev->dev,
665 &tegra_devfreq_profile,
666 "tegra",
667 NULL);
668
669 irq = platform_get_irq(pdev, 0);
670 err = devm_request_threaded_irq(&pdev->dev, irq, actmon_isr, 705 err = devm_request_threaded_irq(&pdev->dev, irq, actmon_isr,
671 actmon_thread_isr, IRQF_SHARED, 706 actmon_thread_isr, IRQF_SHARED,
672 "tegra-devfreq", tegra); 707 "tegra-devfreq", tegra);
@@ -677,12 +712,31 @@ static int tegra_devfreq_probe(struct platform_device *pdev)
677 712
678 platform_set_drvdata(pdev, tegra); 713 platform_set_drvdata(pdev, tegra);
679 714
715 tegra_devfreq_profile.initial_freq = clk_get_rate(tegra->emc_clock);
716 tegra->devfreq = devm_devfreq_add_device(&pdev->dev,
717 &tegra_devfreq_profile,
718 "tegra_actmon",
719 NULL);
720
680 return 0; 721 return 0;
681} 722}
682 723
683static int tegra_devfreq_remove(struct platform_device *pdev) 724static int tegra_devfreq_remove(struct platform_device *pdev)
684{ 725{
685 struct tegra_devfreq *tegra = platform_get_drvdata(pdev); 726 struct tegra_devfreq *tegra = platform_get_drvdata(pdev);
727 int irq = platform_get_irq(pdev, 0);
728 u32 val;
729 unsigned int i;
730
731 for (i = 0; i < ARRAY_SIZE(actmon_device_configs); i++) {
732 val = device_readl(&tegra->devices[i], ACTMON_DEV_CTRL);
733 val &= ~ACTMON_DEV_CTRL_ENB;
734 device_writel(&tegra->devices[i], val, ACTMON_DEV_CTRL);
735 }
736
737 actmon_write_barrier(tegra);
738
739 devm_free_irq(&pdev->dev, irq, tegra);
686 740
687 clk_notifier_unregister(tegra->emc_clock, &tegra->rate_change_nb); 741 clk_notifier_unregister(tegra->emc_clock, &tegra->rate_change_nb);
688 742
@@ -691,28 +745,23 @@ static int tegra_devfreq_remove(struct platform_device *pdev)
691 return 0; 745 return 0;
692} 746}
693 747
694static SIMPLE_DEV_PM_OPS(tegra_devfreq_pm_ops, 748static const struct of_device_id tegra_devfreq_of_match[] = {
695 tegra_devfreq_suspend,
696 tegra_devfreq_resume);
697
698static struct of_device_id tegra_devfreq_of_match[] = {
699 { .compatible = "nvidia,tegra124-actmon" }, 749 { .compatible = "nvidia,tegra124-actmon" },
700 { }, 750 { },
701}; 751};
702 752
753MODULE_DEVICE_TABLE(of, tegra_devfreq_of_match);
754
703static struct platform_driver tegra_devfreq_driver = { 755static struct platform_driver tegra_devfreq_driver = {
704 .probe = tegra_devfreq_probe, 756 .probe = tegra_devfreq_probe,
705 .remove = tegra_devfreq_remove, 757 .remove = tegra_devfreq_remove,
706 .driver = { 758 .driver = {
707 .name = "tegra-devfreq", 759 .name = "tegra-devfreq",
708 .owner = THIS_MODULE,
709 .of_match_table = tegra_devfreq_of_match, 760 .of_match_table = tegra_devfreq_of_match,
710 .pm = &tegra_devfreq_pm_ops,
711 }, 761 },
712}; 762};
713module_platform_driver(tegra_devfreq_driver); 763module_platform_driver(tegra_devfreq_driver);
714 764
715MODULE_LICENSE("GPL"); 765MODULE_LICENSE("GPL v2");
716MODULE_DESCRIPTION("Tegra devfreq driver"); 766MODULE_DESCRIPTION("Tegra devfreq driver");
717MODULE_AUTHOR("Tomeu Vizoso <tomeu.vizoso@collabora.com>"); 767MODULE_AUTHOR("Tomeu Vizoso <tomeu.vizoso@collabora.com>");
718MODULE_DEVICE_TABLE(of, tegra_devfreq_of_match);