blob: 9e28b6594b8d38f30c56ce164f28adf111ca67a3 [file] [log] [blame]
Deepak Kumar6996ed32018-03-07 20:06:58 +05301/* Copyright (c) 2010-2018, The Linux Foundation. All rights reserved.
Shrenuj Bansala419c792016-10-20 14:05:11 -07002 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 */
13
14#ifndef __KGSL_PWRSCALE_H
15#define __KGSL_PWRSCALE_H
16
17#include <linux/devfreq.h>
18#include <linux/msm_adreno_devfreq.h>
19#include "kgsl_pwrctrl.h"
20
21/* devfreq governor call window in usec */
22#define KGSL_GOVERNOR_CALL_INTERVAL 10000
23
24/* Power events to be tracked with history */
25#define KGSL_PWREVENT_STATE 0
26#define KGSL_PWREVENT_GPU_FREQ 1
27#define KGSL_PWREVENT_BUS_FREQ 2
28#define KGSL_PWREVENT_POPP 3
29#define KGSL_PWREVENT_MAX 4
30
31/**
32 * Amount of time running at a level to be considered
33 * "stable" in msec
34 */
35#define STABLE_TIME 150
36
37/* Amount of idle time needed to re-set stability in usec */
38#define POPP_RESET_TIME 1000000
39
40/* Number of POPP levels */
41#define POPP_MAX 4
42
43/* POPP state bits */
44#define POPP_ON BIT(0)
45#define POPP_PUSH BIT(1)
46
47struct kgsl_popp {
48 int gpu_x;
49 int ddr_y;
50};
51
52struct kgsl_power_stats {
53 u64 busy_time;
54 u64 ram_time;
55 u64 ram_wait;
56};
57
58struct kgsl_pwr_event {
59 unsigned int data;
60 ktime_t start;
61 s64 duration;
62};
63
64struct kgsl_pwr_history {
65 struct kgsl_pwr_event *events;
66 unsigned int type;
67 unsigned int index;
68 unsigned int size;
69};
70
71/**
72 * struct kgsl_pwrscale - Power scaling settings for a KGSL device
73 * @devfreqptr - Pointer to the devfreq device
74 * @gpu_profile - GPU profile data for the devfreq device
75 * @bus_profile - Bus specific data for the bus devfreq device
76 * @freq_table - GPU frequencies for the DCVS algorithm
77 * @last_governor - Prior devfreq governor
78 * @accum_stats - Accumulated statistics for various frequency calculations
79 * @enabled - Whether or not power scaling is enabled
80 * @time - Last submitted sample timestamp
81 * @on_time - Timestamp when gpu busy begins
82 * @freq_change_time - Timestamp of last freq change or popp update
83 * @nh - Notifier for the partner devfreq bus device
84 * @devfreq_wq - Main devfreq workqueue
85 * @devfreq_suspend_ws - Pass device suspension to devfreq
86 * @devfreq_resume_ws - Pass device resume to devfreq
87 * @devfreq_notify_ws - Notify devfreq to update sampling
88 * @next_governor_call - Timestamp after which the governor may be notified of
89 * a new sample
90 * @history - History of power events with timestamps and durations
91 * @popp_level - Current level of POPP mitigation
92 * @popp_state - Control state for POPP, on/off, recently pushed, etc
Ram Chandrasekarcd728d52017-03-21 11:36:35 -060093 * @cooling_dev - Thermal cooling device handle
Deepak Kumar6996ed32018-03-07 20:06:58 +053094 * @ctxt_aware_enable - Whether or not ctxt aware DCVS feature is enabled
95 * @ctxt_aware_busy_penalty - The time in microseconds required to trigger
96 * ctxt aware power level jump
97 * @ctxt_aware_target_pwrlevel - pwrlevel to jump on in case of ctxt aware
98 * power level jump
Shrenuj Bansala419c792016-10-20 14:05:11 -070099 */
100struct kgsl_pwrscale {
101 struct devfreq *devfreqptr;
102 struct msm_adreno_extended_profile gpu_profile;
103 struct msm_busmon_extended_profile bus_profile;
104 unsigned long freq_table[KGSL_MAX_PWRLEVELS];
105 char last_governor[DEVFREQ_NAME_LEN];
106 struct kgsl_power_stats accum_stats;
107 bool enabled;
108 ktime_t time;
109 s64 on_time;
110 s64 freq_change_time;
111 struct srcu_notifier_head nh;
112 struct workqueue_struct *devfreq_wq;
113 struct work_struct devfreq_suspend_ws;
114 struct work_struct devfreq_resume_ws;
115 struct work_struct devfreq_notify_ws;
116 ktime_t next_governor_call;
117 struct kgsl_pwr_history history[KGSL_PWREVENT_MAX];
118 int popp_level;
119 unsigned long popp_state;
Ram Chandrasekarcd728d52017-03-21 11:36:35 -0600120 struct thermal_cooling_device *cooling_dev;
Deepak Kumar6996ed32018-03-07 20:06:58 +0530121 bool ctxt_aware_enable;
122 unsigned int ctxt_aware_target_pwrlevel;
123 unsigned int ctxt_aware_busy_penalty;
Shrenuj Bansala419c792016-10-20 14:05:11 -0700124};
125
126int kgsl_pwrscale_init(struct device *dev, const char *governor);
127void kgsl_pwrscale_close(struct kgsl_device *device);
128
129void kgsl_pwrscale_update(struct kgsl_device *device);
130void kgsl_pwrscale_update_stats(struct kgsl_device *device);
131void kgsl_pwrscale_busy(struct kgsl_device *device);
132void kgsl_pwrscale_sleep(struct kgsl_device *device);
133void kgsl_pwrscale_wake(struct kgsl_device *device);
134
Prakash Kamliyac9b7da02016-12-20 17:45:41 +0530135void kgsl_pwrscale_midframe_timer_restart(struct kgsl_device *device);
136void kgsl_pwrscale_midframe_timer_cancel(struct kgsl_device *device);
137
Shrenuj Bansala419c792016-10-20 14:05:11 -0700138void kgsl_pwrscale_enable(struct kgsl_device *device);
139void kgsl_pwrscale_disable(struct kgsl_device *device, bool turbo);
140
141int kgsl_devfreq_target(struct device *dev, unsigned long *freq, u32 flags);
142int kgsl_devfreq_get_dev_status(struct device *dev,
143 struct devfreq_dev_status *stat);
144int kgsl_devfreq_get_cur_freq(struct device *dev, unsigned long *freq);
145
146int kgsl_busmon_target(struct device *dev, unsigned long *freq, u32 flags);
147int kgsl_busmon_get_dev_status(struct device *dev,
148 struct devfreq_dev_status *stat);
149int kgsl_busmon_get_cur_freq(struct device *dev, unsigned long *freq);
150
151bool kgsl_popp_check(struct kgsl_device *device);
152
153
154#define KGSL_PWRSCALE_INIT(_priv_data) { \
155 .enabled = true, \
156 .gpu_profile = { \
157 .private_data = _priv_data, \
158 .profile = { \
159 .target = kgsl_devfreq_target, \
160 .get_dev_status = kgsl_devfreq_get_dev_status, \
161 .get_cur_freq = kgsl_devfreq_get_cur_freq, \
162 } }, \
163 .bus_profile = { \
164 .private_data = _priv_data, \
165 .profile = { \
166 .target = kgsl_busmon_target, \
167 .get_dev_status = kgsl_busmon_get_dev_status, \
168 .get_cur_freq = kgsl_busmon_get_cur_freq, \
169 } }, \
170 .history[KGSL_PWREVENT_STATE].size = 20, \
171 .history[KGSL_PWREVENT_GPU_FREQ].size = 3, \
172 .history[KGSL_PWREVENT_BUS_FREQ].size = 5, \
173 .history[KGSL_PWREVENT_POPP].size = 5, \
174 }
175#endif