@@ -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
4658struct 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 */
111167static 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