Skip to content

Commit 6a32d12

Browse files
mamingrui123opsiff
authored andcommitted
devfreq: Phytium: Tune scaling with ramp-up and hysteresis
Improves NoC-V2 devfreq behavior by fixing low-load oscillation, speeding up ramp-up under rising traffic, and adding hysteresis to reduce frequent back-and-forth transitions between adjacent levels. Signed-off-by: Li Mingzhe <limingzhe1839@phytium.com.cn> Signed-off-by: Wang Yinfeng <wangyinfeng@phytium.com.cn> Signed-off-by: Ma Mingrui <mamingrui1243@phytium.com.cn>
1 parent 2bc5289 commit 6a32d12

1 file changed

Lines changed: 97 additions & 4 deletions

File tree

drivers/devfreq/phytium_noc.c

Lines changed: 97 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,18 @@ struct phytium_nocfreq_info {
4242

4343
/* v2 Register definition */
4444
#define V2_REG_NOC_STATUS 0x0
45+
#define V2_BUSY_CODE_MASK 0x1f
46+
#define V2_BUSY_CODE_MAX 16
47+
48+
/* Fast ramp-up thresholds on each level (busy code out of 16) */
49+
#define V2_UP_225_TO_450_BUSY 4
50+
#define V2_UP_450_TO_900_BUSY 8
51+
#define V2_UP_900_TO_1800_BUSY 12
52+
53+
/* Hysteresis hold/down thresholds */
54+
#define V2_DOWN_450_TO_225_BUSY 2
55+
#define V2_DOWN_900_TO_450_BUSY 6
56+
#define V2_DOWN_1800_TO_900_BUSY 10
4557

4658
struct phytium_nocfreq {
4759
struct device *dev;
@@ -57,6 +69,7 @@ struct phytium_nocfreq {
5769
/* v2 only */
5870
void __iomem *reg_noc_v2;
5971
unsigned int uid;
72+
unsigned int v2_busy_code;
6073

6174
struct mutex lock;
6275

@@ -107,6 +120,49 @@ static u32 phytium_nocfreq_get_peak_bw_v2(struct phytium_nocfreq *priv)
107120
return readl_relaxed(priv->reg_noc_v2 + V2_REG_NOC_STATUS);
108121
}
109122

123+
static unsigned long phytium_nocfreq_min_rate(struct phytium_nocfreq *priv)
124+
{
125+
unsigned long min_rate = priv->freq_table[0];
126+
int i;
127+
128+
for (i = 1; i < priv->freq_count; i++) {
129+
if (priv->freq_table[i] < min_rate)
130+
min_rate = priv->freq_table[i];
131+
}
132+
133+
return min_rate;
134+
}
135+
136+
static unsigned long phytium_nocfreq_max_rate(struct phytium_nocfreq *priv)
137+
{
138+
unsigned long max_rate = priv->freq_table[0];
139+
int i;
140+
141+
for (i = 1; i < priv->freq_count; i++) {
142+
if (priv->freq_table[i] > max_rate)
143+
max_rate = priv->freq_table[i];
144+
}
145+
146+
return max_rate;
147+
}
148+
149+
static unsigned long phytium_nocfreq_next_higher_rate(struct phytium_nocfreq *priv,
150+
unsigned long rate)
151+
{
152+
unsigned long next_rate = ~0UL;
153+
int i;
154+
155+
for (i = 0; i < priv->freq_count; i++) {
156+
if (priv->freq_table[i] > rate && priv->freq_table[i] < next_rate)
157+
next_rate = priv->freq_table[i];
158+
}
159+
160+
if (next_rate == ~0UL)
161+
return rate;
162+
163+
return next_rate;
164+
}
165+
110166
/* v1/v2 General frequency setting */
111167
static int phytium_noc_set_freq(struct device *dev, unsigned long freq)
112168
{
@@ -166,6 +222,36 @@ static int phytium_noc_target(struct device *dev, unsigned long *freq, u32 flags
166222
target_rate = dev_pm_opp_get_freq(opp);
167223
dev_pm_opp_put(opp);
168224

225+
if (priv->info->type == PHYTIUM_NOC_V2) {
226+
unsigned long low = phytium_nocfreq_min_rate(priv);
227+
unsigned long mid1 = phytium_nocfreq_next_higher_rate(priv, low);
228+
unsigned long mid2 = phytium_nocfreq_next_higher_rate(priv, mid1);
229+
unsigned long high = phytium_nocfreq_max_rate(priv);
230+
231+
if (old_freq == low) {
232+
if (priv->v2_busy_code >= V2_UP_225_TO_450_BUSY && mid1 > low &&
233+
target_rate < mid1)
234+
target_rate = mid1;
235+
} else if (old_freq == mid1) {
236+
if (priv->v2_busy_code >= V2_UP_450_TO_900_BUSY && mid2 > mid1 &&
237+
target_rate < mid2)
238+
target_rate = mid2;
239+
else if (priv->v2_busy_code > V2_DOWN_450_TO_225_BUSY &&
240+
priv->v2_busy_code < V2_UP_450_TO_900_BUSY)
241+
target_rate = mid1;
242+
} else if (old_freq == mid2) {
243+
if (priv->v2_busy_code >= V2_UP_900_TO_1800_BUSY && high > mid2 &&
244+
target_rate < high)
245+
target_rate = high;
246+
else if (priv->v2_busy_code > V2_DOWN_900_TO_450_BUSY &&
247+
priv->v2_busy_code < V2_UP_900_TO_1800_BUSY)
248+
target_rate = mid2;
249+
} else if (old_freq == high) {
250+
if (priv->v2_busy_code > V2_DOWN_1800_TO_900_BUSY)
251+
target_rate = high;
252+
}
253+
}
254+
169255
if (target_rate == old_freq)
170256
return 0;
171257

@@ -309,8 +395,15 @@ static int phytium_noc_get_dev_status(struct device *dev, struct devfreq_dev_sta
309395

310396
phytium_nocfreq_restart_handshark_counters_v1(priv);
311397
} else {
312-
stat->busy_time = phytium_nocfreq_get_peak_bw_v2(priv);
313-
stat->total_time = 15 * DIV_ROUND_CLOSEST(priv->rate, priv->freq_table[0]);
398+
u32 raw_busy = phytium_nocfreq_get_peak_bw_v2(priv);
399+
u32 busy_code = raw_busy & V2_BUSY_CODE_MASK;
400+
401+
if (busy_code > V2_BUSY_CODE_MAX)
402+
busy_code = V2_BUSY_CODE_MAX;
403+
404+
priv->v2_busy_code = busy_code;
405+
stat->busy_time = busy_code;
406+
stat->total_time = V2_BUSY_CODE_MAX;
314407
stat->current_frequency = priv->rate;
315408
}
316409
return 0;
@@ -439,8 +532,8 @@ static int phytium_nocfreq_probe(struct platform_device *pdev)
439532
priv->ondemand_data.upthreshold = 80;
440533
priv->ondemand_data.downdifferential = 10;
441534
} else {
442-
priv->ondemand_data.upthreshold = 95;
443-
priv->ondemand_data.downdifferential = 5;
535+
priv->ondemand_data.upthreshold = 80;
536+
priv->ondemand_data.downdifferential = 10;
444537
}
445538

446539
for (i = 0; i < max_state; ++i) {

0 commit comments

Comments
 (0)