diff options
| author | Aaron Tian <atian@nvidia.com> | 2019-09-18 05:13:19 -0400 |
|---|---|---|
| committer | mobile promotions <svcmobile_promotions@nvidia.com> | 2019-10-10 16:41:15 -0400 |
| commit | d6c7740ea2ddd9d5087d938e9ee3b3bc2c9b6d0a (patch) | |
| tree | 0a2e87e2cb0dc8f03acd241bc706c578a11fce25 | |
| parent | 384d68067b7e55ba16f52f586355f3e812aa9c6f (diff) | |
video: tegra: host: update T186 VIC actmon driver
Modify T186/T210 VIC actmon driver and wmark_active governor
to address the following issues:
1. To let VIC actmon reports accurate VIC active
cycle counts, set static WEIGHT_COUNT in both
VIC actmon and VIC IP block. It ensures
VIC actmon can capture all activity signal
toggle event from VIC.
The value of WEIGHT_COUNT are equal to:
4 * (max VIC freq / VIC_actmon freq)
= 4 * (1024 / 19.2)
~= 213
2. Since VIC actmon reports active "VIC clock
cycle" instead of "VIC actmon clock cycle",
"relative loading translation" should consider
current VIC clock freq.
E.g.,
- sample_period = 80 us, VIC freq = 115.2 Mhz
- 9216 cycles represents 100% loading
(115.2 * 80)
3. Update upper/lower wmark settings after VIC
clock scaled completed, to ensure wmark settings
are equil to 0 ~ 100% loading of current freq.
- Register 'get_dev_status' instance in
devfreq_dev_profile, to let wmark active
governor can query current device freq.
- Register devfreq transition notifier in
wmark_active governor. It will query current
device freq. and update corresponding wmark
value after VIC freq. changed.
Bug 200501949
Change-Id: Ic159eb93fddc37d55b0c9649a3afcb50ed82cac2
Signed-off-by: Aaron Tian <atian@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/2200520
GVS: Gerrit_Virtual_Submit
Reviewed-by: Arto Merilainen <amerilainen@nvidia.com>
Reviewed-by: Mikko Perttunen <mperttunen@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
| -rw-r--r-- | drivers/devfreq/governor_wmark_active.c | 45 | ||||
| -rw-r--r-- | drivers/video/tegra/host/host1x/host1x_actmon_t186.c | 56 | ||||
| -rw-r--r-- | drivers/video/tegra/host/host1x/hw_host1x5_actmon.h | 6 | ||||
| -rw-r--r-- | drivers/video/tegra/host/nvhost_acm.c | 25 | ||||
| -rw-r--r-- | drivers/video/tegra/host/nvhost_scale.c | 15 | ||||
| -rw-r--r-- | drivers/video/tegra/host/t186/actmon_regs.c | 22 | ||||
| -rw-r--r-- | drivers/video/tegra/host/t186/t186.c | 5 | ||||
| -rw-r--r-- | include/linux/nvhost.h | 8 |
8 files changed, 166 insertions, 16 deletions
diff --git a/drivers/devfreq/governor_wmark_active.c b/drivers/devfreq/governor_wmark_active.c index 4f6d41c7a..8e98c809d 100644 --- a/drivers/devfreq/governor_wmark_active.c +++ b/drivers/devfreq/governor_wmark_active.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (c) 2014-2017, NVIDIA CORPORATION. All rights reserved. | 2 | * Copyright (c) 2014-2019, NVIDIA CORPORATION. All rights reserved. |
| 3 | * | 3 | * |
| 4 | * This program is free software; you can redistribute it and/or modify it | 4 | * This program is free software; you can redistribute it and/or modify it |
| 5 | * under the terms and conditions of the GNU General Public License, | 5 | * under the terms and conditions of the GNU General Public License, |
| @@ -46,6 +46,9 @@ struct wmark_gov_info { | |||
| 46 | 46 | ||
| 47 | /* variable for keeping the average frequency request */ | 47 | /* variable for keeping the average frequency request */ |
| 48 | unsigned long long average_target_freq; | 48 | unsigned long long average_target_freq; |
| 49 | |||
| 50 | /* devfreq notifier_block */ | ||
| 51 | struct notifier_block nb; | ||
| 49 | }; | 52 | }; |
| 50 | 53 | ||
| 51 | static unsigned long freqlist_up(struct wmark_gov_info *wmarkinfo, | 54 | static unsigned long freqlist_up(struct wmark_gov_info *wmarkinfo, |
| @@ -185,9 +188,6 @@ static int devfreq_watermark_target_freq(struct devfreq *df, | |||
| 185 | (wmarkinfo->p_smooth * wmarkinfo->average_target_freq + | 188 | (wmarkinfo->p_smooth * wmarkinfo->average_target_freq + |
| 186 | ideal_freq) / (wmarkinfo->p_smooth + 1); | 189 | ideal_freq) / (wmarkinfo->p_smooth + 1); |
| 187 | 190 | ||
| 188 | /* update watermarks to match the ideal frequency */ | ||
| 189 | update_watermarks(df, dev_stat.current_frequency, ideal_freq); | ||
| 190 | |||
| 191 | /* do not scale too often */ | 191 | /* do not scale too often */ |
| 192 | if (dt < wmarkinfo->p_block_window) | 192 | if (dt < wmarkinfo->p_block_window) |
| 193 | return 0; | 193 | return 0; |
| @@ -276,11 +276,38 @@ static int devfreq_watermark_start(struct devfreq *df) | |||
| 276 | return 0; | 276 | return 0; |
| 277 | } | 277 | } |
| 278 | 278 | ||
| 279 | static int devfreq_watermark_notifier_call(struct notifier_block *nb, | ||
| 280 | unsigned long event, void *ptr) | ||
| 281 | { | ||
| 282 | struct wmark_gov_info *data | ||
| 283 | = container_of(nb, struct wmark_gov_info, nb); | ||
| 284 | struct devfreq *df = (struct devfreq *)data->df; | ||
| 285 | unsigned long freq = 0; | ||
| 286 | |||
| 287 | switch (event) { | ||
| 288 | case DEVFREQ_PRECHANGE: | ||
| 289 | break; | ||
| 290 | case DEVFREQ_POSTCHANGE: | ||
| 291 | /* get device freq. */ | ||
| 292 | df->profile->get_cur_freq(df->dev.parent, &freq); | ||
| 293 | |||
| 294 | /* update watermarks by current device freq. */ | ||
| 295 | if (freq) | ||
| 296 | update_watermarks(df, freq, freq); | ||
| 297 | break; | ||
| 298 | default: | ||
| 299 | break; | ||
| 300 | } | ||
| 301 | |||
| 302 | return NOTIFY_DONE; | ||
| 303 | } | ||
| 304 | |||
| 279 | static int devfreq_watermark_event_handler(struct devfreq *df, | 305 | static int devfreq_watermark_event_handler(struct devfreq *df, |
| 280 | unsigned int event, void *wmark_type) | 306 | unsigned int event, void *wmark_type) |
| 281 | { | 307 | { |
| 282 | struct wmark_gov_info *wmarkinfo; | 308 | struct wmark_gov_info *wmarkinfo; |
| 283 | int ret = 0; | 309 | int ret = 0; |
| 310 | struct notifier_block *nb; | ||
| 284 | 311 | ||
| 285 | switch (event) { | 312 | switch (event) { |
| 286 | case DEVFREQ_GOV_START: | 313 | case DEVFREQ_GOV_START: |
| @@ -300,10 +327,20 @@ static int devfreq_watermark_event_handler(struct devfreq *df, | |||
| 300 | 327 | ||
| 301 | update_watermarks(df, dev_stat.current_frequency, | 328 | update_watermarks(df, dev_stat.current_frequency, |
| 302 | dev_stat.current_frequency); | 329 | dev_stat.current_frequency); |
| 330 | |||
| 331 | nb = &wmarkinfo->nb; | ||
| 332 | nb->notifier_call = devfreq_watermark_notifier_call; | ||
| 333 | ret = devm_devfreq_register_notifier(df->dev.parent, | ||
| 334 | df, nb, DEVFREQ_TRANSITION_NOTIFIER); | ||
| 303 | break; | 335 | break; |
| 304 | } | 336 | } |
| 305 | case DEVFREQ_GOV_STOP: | 337 | case DEVFREQ_GOV_STOP: |
| 306 | devfreq_watermark_debug_stop(df); | 338 | devfreq_watermark_debug_stop(df); |
| 339 | |||
| 340 | wmarkinfo = df->data; | ||
| 341 | nb = &wmarkinfo->nb; | ||
| 342 | devm_devfreq_unregister_notifier(df->dev.parent, | ||
| 343 | df, nb, DEVFREQ_TRANSITION_NOTIFIER); | ||
| 307 | break; | 344 | break; |
| 308 | case DEVFREQ_GOV_SUSPEND: | 345 | case DEVFREQ_GOV_SUSPEND: |
| 309 | devfreq_monitor_suspend(df); | 346 | devfreq_monitor_suspend(df); |
diff --git a/drivers/video/tegra/host/host1x/host1x_actmon_t186.c b/drivers/video/tegra/host/host1x/host1x_actmon_t186.c index 656e56469..8d2a3a52d 100644 --- a/drivers/video/tegra/host/host1x/host1x_actmon_t186.c +++ b/drivers/video/tegra/host/host1x/host1x_actmon_t186.c | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Tegra Graphics Host Actmon support for T186 | 2 | * Tegra Graphics Host Actmon support for T186 |
| 3 | * | 3 | * |
| 4 | * Copyright (c) 2015-2017, NVIDIA CORPORATION. All rights reserved. | 4 | * Copyright (c) 2015-2019, NVIDIA CORPORATION. All rights reserved. |
| 5 | * | 5 | * |
| 6 | * This program is free software; you can redistribute it and/or modify it | 6 | * This program is free software; you can redistribute it and/or modify it |
| 7 | * under the terms and conditions of the GNU General Public License, | 7 | * under the terms and conditions of the GNU General Public License, |
| @@ -181,6 +181,21 @@ static void __iomem *host1x_actmon_get_regs(struct host1x_actmon *actmon) | |||
| 181 | return NULL; | 181 | return NULL; |
| 182 | } | 182 | } |
| 183 | 183 | ||
| 184 | static unsigned long get_module_freq(struct host1x_actmon *actmon) | ||
| 185 | { | ||
| 186 | unsigned long freq = 0; | ||
| 187 | |||
| 188 | struct platform_device *pdev = actmon->pdev; | ||
| 189 | struct nvhost_device_data *engine_pdata = platform_get_drvdata(pdev); | ||
| 190 | struct devfreq *df = engine_pdata->power_manager; | ||
| 191 | struct nvhost_device_data *pdata = dev_get_drvdata(df->dev.parent); | ||
| 192 | struct nvhost_device_profile *profile = pdata->power_profile; | ||
| 193 | |||
| 194 | freq = clk_get_rate(profile->clk); | ||
| 195 | |||
| 196 | return freq; | ||
| 197 | } | ||
| 198 | |||
| 184 | static int host1x_actmon_init(struct host1x_actmon *actmon) | 199 | static int host1x_actmon_init(struct host1x_actmon *actmon) |
| 185 | { | 200 | { |
| 186 | struct platform_device *host_pdev = actmon->host->dev; | 201 | struct platform_device *host_pdev = actmon->host->dev; |
| @@ -226,6 +241,10 @@ static int host1x_actmon_init(struct host1x_actmon *actmon) | |||
| 226 | val |= actmon_local_ctrl_enb_cumulative_f(1); | 241 | val |= actmon_local_ctrl_enb_cumulative_f(1); |
| 227 | actmon_writel(actmon, val, actmon_local_ctrl_r()); | 242 | actmon_writel(actmon, val, actmon_local_ctrl_r()); |
| 228 | 243 | ||
| 244 | /* Set COUNT_WEIGHT @actmon */ | ||
| 245 | actmon_writel(actmon, engine_pdata->actmon_weight_count, | ||
| 246 | actmon_local_count_weight_r()); | ||
| 247 | |||
| 229 | /* Enable global interrupt */ | 248 | /* Enable global interrupt */ |
| 230 | if (engine_pdata->actmon_irq) | 249 | if (engine_pdata->actmon_irq) |
| 231 | actmon_writel(actmon, 0x1, actmon_glb_intr_en_r()); | 250 | actmon_writel(actmon, 0x1, actmon_glb_intr_en_r()); |
| @@ -297,6 +316,8 @@ static int host1x_actmon_avg_norm(struct host1x_actmon *actmon, u32 *avg) | |||
| 297 | { | 316 | { |
| 298 | long val; | 317 | long val; |
| 299 | int err; | 318 | int err; |
| 319 | unsigned long freq = 0; | ||
| 320 | u32 dev_cycle_per_sample = 0; | ||
| 300 | 321 | ||
| 301 | if (!(actmon->init == ACTMON_READY && actmon->clks_per_sample > 0 && | 322 | if (!(actmon->init == ACTMON_READY && actmon->clks_per_sample > 0 && |
| 302 | actmon->divider)) { | 323 | actmon->divider)) { |
| @@ -313,7 +334,11 @@ static int host1x_actmon_avg_norm(struct host1x_actmon *actmon, u32 *avg) | |||
| 313 | val = actmon_readl(actmon, actmon_local_avg_count_r()); | 334 | val = actmon_readl(actmon, actmon_local_avg_count_r()); |
| 314 | nvhost_module_idle(actmon->host->dev); | 335 | nvhost_module_idle(actmon->host->dev); |
| 315 | 336 | ||
| 316 | *avg = (val * 1000) / (actmon->clks_per_sample * actmon->divider); | 337 | freq = get_module_freq(actmon); |
| 338 | dev_cycle_per_sample = ((freq / 1000) * actmon->usecs_per_sample) | ||
| 339 | / 1000; | ||
| 340 | |||
| 341 | *avg = (val * 1000) / dev_cycle_per_sample; | ||
| 317 | 342 | ||
| 318 | return 0; | 343 | return 0; |
| 319 | } | 344 | } |
| @@ -366,13 +391,20 @@ static int host1x_actmon_count_norm(struct host1x_actmon *actmon, u32 *avg) | |||
| 366 | 391 | ||
| 367 | static int host1x_set_high_wmark(struct host1x_actmon *actmon, u32 val_scaled) | 392 | static int host1x_set_high_wmark(struct host1x_actmon *actmon, u32 val_scaled) |
| 368 | { | 393 | { |
| 369 | u32 val = (val_scaled < 1000) ? | 394 | u32 freq_khz = 0; |
| 370 | ((val_scaled * actmon->clks_per_sample * actmon->divider) / | 395 | u32 dev_cycle_per_sample = 0; |
| 371 | 1000) : actmon->clks_per_sample * actmon->divider; | 396 | u32 val = 0; |
| 372 | 397 | ||
| 373 | if (actmon->init != ACTMON_READY) | 398 | if (actmon->init != ACTMON_READY) |
| 374 | return 0; | 399 | return 0; |
| 375 | 400 | ||
| 401 | freq_khz = get_module_freq(actmon) / 1000; | ||
| 402 | dev_cycle_per_sample = (actmon->usecs_per_sample * freq_khz) / 1000; | ||
| 403 | |||
| 404 | val = (val_scaled < 1000) ? | ||
| 405 | ((val_scaled * dev_cycle_per_sample) / 1000) : | ||
| 406 | dev_cycle_per_sample; | ||
| 407 | |||
| 376 | /* write new watermark */ | 408 | /* write new watermark */ |
| 377 | actmon_writel(actmon, val, actmon_local_avg_upper_wmark_r()); | 409 | actmon_writel(actmon, val, actmon_local_avg_upper_wmark_r()); |
| 378 | 410 | ||
| @@ -391,13 +423,20 @@ static int host1x_set_high_wmark(struct host1x_actmon *actmon, u32 val_scaled) | |||
| 391 | 423 | ||
| 392 | static int host1x_set_low_wmark(struct host1x_actmon *actmon, u32 val_scaled) | 424 | static int host1x_set_low_wmark(struct host1x_actmon *actmon, u32 val_scaled) |
| 393 | { | 425 | { |
| 394 | u32 val = (val_scaled < 1000) ? | 426 | u32 freq_khz = 0; |
| 395 | ((val_scaled * actmon->clks_per_sample * actmon->divider) / | 427 | u32 dev_cycle_per_sample = 0; |
| 396 | 1000) : actmon->clks_per_sample * actmon->divider; | 428 | u32 val = 0; |
| 397 | 429 | ||
| 398 | if (actmon->init != ACTMON_READY) | 430 | if (actmon->init != ACTMON_READY) |
| 399 | return 0; | 431 | return 0; |
| 400 | 432 | ||
| 433 | freq_khz = get_module_freq(actmon) / 1000; | ||
| 434 | dev_cycle_per_sample = (actmon->usecs_per_sample * freq_khz) / 1000; | ||
| 435 | |||
| 436 | val = (val_scaled < 1000) ? | ||
| 437 | ((val_scaled * dev_cycle_per_sample) / 1000) : | ||
| 438 | dev_cycle_per_sample; | ||
| 439 | |||
| 401 | /* write new watermark */ | 440 | /* write new watermark */ |
| 402 | actmon_writel(actmon, val, actmon_local_avg_lower_wmark_r()); | 441 | actmon_writel(actmon, val, actmon_local_avg_lower_wmark_r()); |
| 403 | 442 | ||
| @@ -410,7 +449,6 @@ static int host1x_set_low_wmark(struct host1x_actmon *actmon, u32 val_scaled) | |||
| 410 | actmon_writel(actmon, val, actmon_local_intr_en_r()); | 449 | actmon_writel(actmon, val, actmon_local_intr_en_r()); |
| 411 | 450 | ||
| 412 | host1x_actmon_dump_regs(actmon); | 451 | host1x_actmon_dump_regs(actmon); |
| 413 | |||
| 414 | return 0; | 452 | return 0; |
| 415 | } | 453 | } |
| 416 | 454 | ||
diff --git a/drivers/video/tegra/host/host1x/hw_host1x5_actmon.h b/drivers/video/tegra/host/host1x/hw_host1x5_actmon.h index c53c851b4..8e60ca821 100644 --- a/drivers/video/tegra/host/host1x/hw_host1x5_actmon.h +++ b/drivers/video/tegra/host/host1x/hw_host1x5_actmon.h | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (c) 2015, NVIDIA CORPORATION. All rights reserved. | 2 | * Copyright (c) 2015-2019, NVIDIA CORPORATION. All rights reserved. |
| 3 | * | 3 | * |
| 4 | * This program is free software; you can redistribute it and/or modify it | 4 | * This program is free software; you can redistribute it and/or modify it |
| 5 | * under the terms and conditions of the GNU General Public License, | 5 | * under the terms and conditions of the GNU General Public License, |
| @@ -154,6 +154,10 @@ static inline u32 actmon_local_avg_count_r(void) | |||
| 154 | { | 154 | { |
| 155 | return 0xa4; | 155 | return 0xa4; |
| 156 | } | 156 | } |
| 157 | static inline u32 actmon_local_count_weight_r(void) | ||
| 158 | { | ||
| 159 | return 0xa8; | ||
| 160 | } | ||
| 157 | static inline u32 actmon_local_cumulative_r(void) | 161 | static inline u32 actmon_local_cumulative_r(void) |
| 158 | { | 162 | { |
| 159 | return 0xac; | 163 | return 0xac; |
diff --git a/drivers/video/tegra/host/nvhost_acm.c b/drivers/video/tegra/host/nvhost_acm.c index b78355c56..beed307d6 100644 --- a/drivers/video/tegra/host/nvhost_acm.c +++ b/drivers/video/tegra/host/nvhost_acm.c | |||
| @@ -59,6 +59,7 @@ | |||
| 59 | #define MAX_DEVID_LENGTH 32 | 59 | #define MAX_DEVID_LENGTH 32 |
| 60 | 60 | ||
| 61 | static void nvhost_module_load_regs(struct platform_device *pdev, bool prod); | 61 | static void nvhost_module_load_regs(struct platform_device *pdev, bool prod); |
| 62 | static void nvhost_module_set_actmon_regs(struct platform_device *pdev); | ||
| 62 | 63 | ||
| 63 | #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0) | 64 | #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0) |
| 64 | static int nvhost_module_toggle_slcg(struct notifier_block *nb, | 65 | static int nvhost_module_toggle_slcg(struct notifier_block *nb, |
| @@ -141,6 +142,9 @@ void nvhost_module_reset(struct platform_device *dev, bool reboot) | |||
| 141 | /* Load clockgating registers */ | 142 | /* Load clockgating registers */ |
| 142 | nvhost_module_load_regs(dev, pdata->engine_can_cg); | 143 | nvhost_module_load_regs(dev, pdata->engine_can_cg); |
| 143 | 144 | ||
| 145 | /* Set actmon registers */ | ||
| 146 | nvhost_module_set_actmon_regs(dev); | ||
| 147 | |||
| 144 | /* initialize device vm */ | 148 | /* initialize device vm */ |
| 145 | nvhost_vm_init_device(dev); | 149 | nvhost_vm_init_device(dev); |
| 146 | 150 | ||
| @@ -970,6 +974,23 @@ static void nvhost_module_load_regs(struct platform_device *pdev, bool prod) | |||
| 970 | } | 974 | } |
| 971 | } | 975 | } |
| 972 | 976 | ||
| 977 | static void nvhost_module_set_actmon_regs(struct platform_device *pdev) | ||
| 978 | { | ||
| 979 | struct nvhost_device_data *pdata = platform_get_drvdata(pdev); | ||
| 980 | struct nvhost_actmon_register *regs = pdata->actmon_setting_regs; | ||
| 981 | |||
| 982 | if (!regs) | ||
| 983 | return; | ||
| 984 | |||
| 985 | if (nvhost_dev_is_virtual(pdev)) | ||
| 986 | return; | ||
| 987 | |||
| 988 | while (regs->addr) { | ||
| 989 | host1x_writel(pdev, regs->addr, regs->val); | ||
| 990 | regs++; | ||
| 991 | } | ||
| 992 | } | ||
| 993 | |||
| 973 | static int nvhost_module_runtime_suspend(struct device *dev) | 994 | static int nvhost_module_runtime_suspend(struct device *dev) |
| 974 | { | 995 | { |
| 975 | int err; | 996 | int err; |
| @@ -1192,6 +1213,10 @@ static int nvhost_module_finalize_poweron(struct device *dev) | |||
| 1192 | goto out; | 1213 | goto out; |
| 1193 | } | 1214 | } |
| 1194 | 1215 | ||
| 1216 | |||
| 1217 | /* Set actmon registers */ | ||
| 1218 | nvhost_module_set_actmon_regs(pdev); | ||
| 1219 | |||
| 1195 | /* set default EMC rate to zero */ | 1220 | /* set default EMC rate to zero */ |
| 1196 | if (pdata->bwmgr_handle) { | 1221 | if (pdata->bwmgr_handle) { |
| 1197 | for (i = 0; i < NVHOST_MODULE_MAX_CLOCKS; i++) { | 1222 | for (i = 0; i < NVHOST_MODULE_MAX_CLOCKS; i++) { |
diff --git a/drivers/video/tegra/host/nvhost_scale.c b/drivers/video/tegra/host/nvhost_scale.c index eafb6eef6..abfacf0ca 100644 --- a/drivers/video/tegra/host/nvhost_scale.c +++ b/drivers/video/tegra/host/nvhost_scale.c | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Tegra Graphics Host Unit clock scaling | 2 | * Tegra Graphics Host Unit clock scaling |
| 3 | * | 3 | * |
| 4 | * Copyright (c) 2010-2018, NVIDIA Corporation. All rights reserved. | 4 | * Copyright (c) 2010-2019, NVIDIA Corporation. All rights reserved. |
| 5 | * | 5 | * |
| 6 | * This program is free software; you can redistribute it and/or modify it | 6 | * This program is free software; you can redistribute it and/or modify it |
| 7 | * under the terms and conditions of the GNU General Public License, | 7 | * under the terms and conditions of the GNU General Public License, |
| @@ -288,6 +288,17 @@ static int nvhost_scale_get_dev_status(struct device *dev, | |||
| 288 | return 0; | 288 | return 0; |
| 289 | } | 289 | } |
| 290 | 290 | ||
| 291 | static int nvhost_scale_get_cur_freq(struct device *dev, unsigned long *freq) | ||
| 292 | { | ||
| 293 | struct nvhost_device_data *pdata = dev_get_drvdata(dev); | ||
| 294 | struct nvhost_device_profile *profile = pdata->power_profile; | ||
| 295 | |||
| 296 | if (freq) | ||
| 297 | *freq = clk_get_rate(profile->clk); | ||
| 298 | |||
| 299 | return 0; | ||
| 300 | } | ||
| 301 | |||
| 291 | /* | 302 | /* |
| 292 | * nvhost_scale_set_low_wmark(dev, threshold) | 303 | * nvhost_scale_set_low_wmark(dev, threshold) |
| 293 | * | 304 | * |
| @@ -417,6 +428,8 @@ void nvhost_scale_init(struct platform_device *pdev) | |||
| 417 | profile->devfreq_profile.target = nvhost_scale_target; | 428 | profile->devfreq_profile.target = nvhost_scale_target; |
| 418 | profile->devfreq_profile.get_dev_status = | 429 | profile->devfreq_profile.get_dev_status = |
| 419 | nvhost_scale_get_dev_status; | 430 | nvhost_scale_get_dev_status; |
| 431 | profile->devfreq_profile.get_cur_freq = | ||
| 432 | nvhost_scale_get_cur_freq; | ||
| 420 | profile->devfreq_profile.set_low_wmark = | 433 | profile->devfreq_profile.set_low_wmark = |
| 421 | nvhost_scale_set_low_wmark; | 434 | nvhost_scale_set_low_wmark; |
| 422 | profile->devfreq_profile.set_high_wmark = | 435 | profile->devfreq_profile.set_high_wmark = |
diff --git a/drivers/video/tegra/host/t186/actmon_regs.c b/drivers/video/tegra/host/t186/actmon_regs.c new file mode 100644 index 000000000..abf521d38 --- /dev/null +++ b/drivers/video/tegra/host/t186/actmon_regs.c | |||
| @@ -0,0 +1,22 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2019, NVIDIA Corporation. All rights reserved. | ||
| 3 | * | ||
| 4 | * This program is free software; you can redistribute it and/or modify | ||
| 5 | * it under the terms of the GNU General Public License as published by | ||
| 6 | * the Free Software Foundation; either version 2 of the License. | ||
| 7 | * | ||
| 8 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
| 9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
| 10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
| 11 | * more details. | ||
| 12 | * | ||
| 13 | * You should have received a copy of the GNU General Public License | ||
| 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 15 | */ | ||
| 16 | |||
| 17 | static struct nvhost_actmon_register __attribute__((__unused__)) | ||
| 18 | t18x_vic_actmon_registers[] = { | ||
| 19 | /* NV_PVIC_TFBIF_ACTMON_ACTIVE_WEIGHT */ | ||
| 20 | { .addr = 0x00002054, .val = 0x000000d5 }, | ||
| 21 | {} | ||
| 22 | }; | ||
diff --git a/drivers/video/tegra/host/t186/t186.c b/drivers/video/tegra/host/t186/t186.c index f56f21e2a..e0c79926e 100644 --- a/drivers/video/tegra/host/t186/t186.c +++ b/drivers/video/tegra/host/t186/t186.c | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Tegra Graphics Init for T186 Architecture Chips | 2 | * Tegra Graphics Init for T186 Architecture Chips |
| 3 | * | 3 | * |
| 4 | * Copyright (c) 2014-2018, NVIDIA Corporation. All rights reserved. | 4 | * Copyright (c) 2014-2019, NVIDIA Corporation. All rights reserved. |
| 5 | * | 5 | * |
| 6 | * This program is free software; you can redistribute it and/or modify it | 6 | * This program is free software; you can redistribute it and/or modify it |
| 7 | * under the terms and conditions of the GNU General Public License, | 7 | * under the terms and conditions of the GNU General Public License, |
| @@ -48,6 +48,7 @@ | |||
| 48 | 48 | ||
| 49 | #include "streamid_regs.c" | 49 | #include "streamid_regs.c" |
| 50 | #include "cg_regs.c" | 50 | #include "cg_regs.c" |
| 51 | #include "actmon_regs.c" | ||
| 51 | 52 | ||
| 52 | #define HOST_EMC_FLOOR 204000000 | 53 | #define HOST_EMC_FLOOR 204000000 |
| 53 | #define HOST_NVDEC_EMC_FLOOR 102000000 | 54 | #define HOST_NVDEC_EMC_FLOOR 102000000 |
| @@ -446,6 +447,8 @@ struct nvhost_device_data t18_vic_info = { | |||
| 446 | .actmon_regs = HOST1X_THOST_ACTMON_VIC, | 447 | .actmon_regs = HOST1X_THOST_ACTMON_VIC, |
| 447 | .actmon_enabled = false, | 448 | .actmon_enabled = false, |
| 448 | .actmon_irq = 3, | 449 | .actmon_irq = 3, |
| 450 | .actmon_weight_count = 213, | ||
| 451 | .actmon_setting_regs = t18x_vic_actmon_registers, | ||
| 449 | .devfreq_governor = "wmark_active", | 452 | .devfreq_governor = "wmark_active", |
| 450 | .freqs = {100000000, 200000000, 300000000, | 453 | .freqs = {100000000, 200000000, 300000000, |
| 451 | 400000000, 500000000, 600000000}, | 454 | 400000000, 500000000, 600000000}, |
diff --git a/include/linux/nvhost.h b/include/linux/nvhost.h index d6170f7dc..68b967888 100644 --- a/include/linux/nvhost.h +++ b/include/linux/nvhost.h | |||
| @@ -108,6 +108,11 @@ struct nvhost_gating_register { | |||
| 108 | u32 disable; | 108 | u32 disable; |
| 109 | }; | 109 | }; |
| 110 | 110 | ||
| 111 | struct nvhost_actmon_register { | ||
| 112 | u32 addr; | ||
| 113 | u32 val; | ||
| 114 | }; | ||
| 115 | |||
| 111 | struct nvhost_clock { | 116 | struct nvhost_clock { |
| 112 | char *name; | 117 | char *name; |
| 113 | unsigned long default_rate; | 118 | unsigned long default_rate; |
| @@ -244,6 +249,9 @@ struct nvhost_device_data { | |||
| 244 | bool linear_emc; | 249 | bool linear_emc; |
| 245 | /* Offset to actmon registers */ | 250 | /* Offset to actmon registers */ |
| 246 | u32 actmon_regs; | 251 | u32 actmon_regs; |
| 252 | /* WEIGHT_COUNT of actmon */ | ||
| 253 | u32 actmon_weight_count; | ||
| 254 | struct nvhost_actmon_register *actmon_setting_regs; | ||
| 247 | /* Devfreq governor name */ | 255 | /* Devfreq governor name */ |
| 248 | const char *devfreq_governor; | 256 | const char *devfreq_governor; |
| 249 | unsigned long freqs[NVHOST_MODULE_MAX_FREQS]; | 257 | unsigned long freqs[NVHOST_MODULE_MAX_FREQS]; |
