3030
3131#define UNCORE_MAJOR_VERSION 0
3232#define UNCORE_MINOR_VERSION 2
33+ #define UNCORE_ELC_SUPPORTED_VERSION 2
3334#define UNCORE_HEADER_INDEX 0
3435#define UNCORE_FABRIC_CLUSTER_OFFSET 8
3536
@@ -46,6 +47,7 @@ struct tpmi_uncore_struct;
4647/* Information for each cluster */
4748struct tpmi_uncore_cluster_info {
4849 bool root_domain ;
50+ bool elc_supported ;
4951 u8 __iomem * cluster_base ;
5052 struct uncore_data uncore_data ;
5153 struct tpmi_uncore_struct * uncore_root ;
@@ -75,6 +77,10 @@ struct tpmi_uncore_struct {
7577/* Bit definitions for CONTROL register */
7678#define UNCORE_MAX_RATIO_MASK GENMASK_ULL(14, 8)
7779#define UNCORE_MIN_RATIO_MASK GENMASK_ULL(21, 15)
80+ #define UNCORE_EFF_LAT_CTRL_RATIO_MASK GENMASK_ULL(28, 22)
81+ #define UNCORE_EFF_LAT_CTRL_LOW_THRESHOLD_MASK GENMASK_ULL(38, 32)
82+ #define UNCORE_EFF_LAT_CTRL_HIGH_THRESHOLD_ENABLE BIT(39)
83+ #define UNCORE_EFF_LAT_CTRL_HIGH_THRESHOLD_MASK GENMASK_ULL(46, 40)
7884
7985/* Helper function to read MMIO offset for max/min control frequency */
8086static void read_control_freq (struct tpmi_uncore_cluster_info * cluster_info ,
@@ -89,6 +95,48 @@ static void read_control_freq(struct tpmi_uncore_cluster_info *cluster_info,
8995 * value = FIELD_GET (UNCORE_MIN_RATIO_MASK , control ) * UNCORE_FREQ_KHZ_MULTIPLIER ;
9096}
9197
98+ /* Helper function to read efficiency latency control values over MMIO */
99+ static int read_eff_lat_ctrl (struct uncore_data * data , unsigned int * val , enum uncore_index index )
100+ {
101+ struct tpmi_uncore_cluster_info * cluster_info ;
102+ u64 ctrl ;
103+
104+ cluster_info = container_of (data , struct tpmi_uncore_cluster_info , uncore_data );
105+ if (cluster_info -> root_domain )
106+ return - ENODATA ;
107+
108+ if (!cluster_info -> elc_supported )
109+ return - EOPNOTSUPP ;
110+
111+ ctrl = readq (cluster_info -> cluster_base + UNCORE_CONTROL_INDEX );
112+
113+ switch (index ) {
114+ case UNCORE_INDEX_EFF_LAT_CTRL_LOW_THRESHOLD :
115+ * val = FIELD_GET (UNCORE_EFF_LAT_CTRL_LOW_THRESHOLD_MASK , ctrl );
116+ * val *= 100 ;
117+ * val = DIV_ROUND_UP (* val , FIELD_MAX (UNCORE_EFF_LAT_CTRL_LOW_THRESHOLD_MASK ));
118+ break ;
119+
120+ case UNCORE_INDEX_EFF_LAT_CTRL_HIGH_THRESHOLD :
121+ * val = FIELD_GET (UNCORE_EFF_LAT_CTRL_HIGH_THRESHOLD_MASK , ctrl );
122+ * val *= 100 ;
123+ * val = DIV_ROUND_UP (* val , FIELD_MAX (UNCORE_EFF_LAT_CTRL_HIGH_THRESHOLD_MASK ));
124+ break ;
125+
126+ case UNCORE_INDEX_EFF_LAT_CTRL_HIGH_THRESHOLD_ENABLE :
127+ * val = FIELD_GET (UNCORE_EFF_LAT_CTRL_HIGH_THRESHOLD_ENABLE , ctrl );
128+ break ;
129+ case UNCORE_INDEX_EFF_LAT_CTRL_FREQ :
130+ * val = FIELD_GET (UNCORE_EFF_LAT_CTRL_RATIO_MASK , ctrl ) * UNCORE_FREQ_KHZ_MULTIPLIER ;
131+ break ;
132+
133+ default :
134+ return - EOPNOTSUPP ;
135+ }
136+
137+ return 0 ;
138+ }
139+
92140#define UNCORE_MAX_RATIO FIELD_MAX(UNCORE_MAX_RATIO_MASK)
93141
94142/* Helper for sysfs read for max/min frequencies. Called under mutex locks */
@@ -137,6 +185,82 @@ static int uncore_read_control_freq(struct uncore_data *data, unsigned int *valu
137185 return 0 ;
138186}
139187
188+ /* Helper function for writing efficiency latency control values over MMIO */
189+ static int write_eff_lat_ctrl (struct uncore_data * data , unsigned int val , enum uncore_index index )
190+ {
191+ struct tpmi_uncore_cluster_info * cluster_info ;
192+ u64 control ;
193+
194+ cluster_info = container_of (data , struct tpmi_uncore_cluster_info , uncore_data );
195+
196+ if (cluster_info -> root_domain )
197+ return - ENODATA ;
198+
199+ if (!cluster_info -> elc_supported )
200+ return - EOPNOTSUPP ;
201+
202+ switch (index ) {
203+ case UNCORE_INDEX_EFF_LAT_CTRL_LOW_THRESHOLD :
204+ if (val > 100 )
205+ return - EINVAL ;
206+ break ;
207+
208+ case UNCORE_INDEX_EFF_LAT_CTRL_HIGH_THRESHOLD :
209+ if (val > 100 )
210+ return - EINVAL ;
211+ break ;
212+
213+ case UNCORE_INDEX_EFF_LAT_CTRL_HIGH_THRESHOLD_ENABLE :
214+ if (val > 1 )
215+ return - EINVAL ;
216+ break ;
217+
218+ case UNCORE_INDEX_EFF_LAT_CTRL_FREQ :
219+ val /= UNCORE_FREQ_KHZ_MULTIPLIER ;
220+ if (val > FIELD_MAX (UNCORE_EFF_LAT_CTRL_RATIO_MASK ))
221+ return - EINVAL ;
222+ break ;
223+
224+ default :
225+ return - EOPNOTSUPP ;
226+ }
227+
228+ control = readq (cluster_info -> cluster_base + UNCORE_CONTROL_INDEX );
229+
230+ switch (index ) {
231+ case UNCORE_INDEX_EFF_LAT_CTRL_LOW_THRESHOLD :
232+ val *= FIELD_MAX (UNCORE_EFF_LAT_CTRL_LOW_THRESHOLD_MASK );
233+ val /= 100 ;
234+ control &= ~UNCORE_EFF_LAT_CTRL_LOW_THRESHOLD_MASK ;
235+ control |= FIELD_PREP (UNCORE_EFF_LAT_CTRL_LOW_THRESHOLD_MASK , val );
236+ break ;
237+
238+ case UNCORE_INDEX_EFF_LAT_CTRL_HIGH_THRESHOLD :
239+ val *= FIELD_MAX (UNCORE_EFF_LAT_CTRL_HIGH_THRESHOLD_MASK );
240+ val /= 100 ;
241+ control &= ~UNCORE_EFF_LAT_CTRL_HIGH_THRESHOLD_MASK ;
242+ control |= FIELD_PREP (UNCORE_EFF_LAT_CTRL_HIGH_THRESHOLD_MASK , val );
243+ break ;
244+
245+ case UNCORE_INDEX_EFF_LAT_CTRL_HIGH_THRESHOLD_ENABLE :
246+ control &= ~UNCORE_EFF_LAT_CTRL_HIGH_THRESHOLD_ENABLE ;
247+ control |= FIELD_PREP (UNCORE_EFF_LAT_CTRL_HIGH_THRESHOLD_ENABLE , val );
248+ break ;
249+
250+ case UNCORE_INDEX_EFF_LAT_CTRL_FREQ :
251+ control &= ~UNCORE_EFF_LAT_CTRL_RATIO_MASK ;
252+ control |= FIELD_PREP (UNCORE_EFF_LAT_CTRL_RATIO_MASK , val );
253+ break ;
254+
255+ default :
256+ break ;
257+ }
258+
259+ writeq (control , cluster_info -> cluster_base + UNCORE_CONTROL_INDEX );
260+
261+ return 0 ;
262+ }
263+
140264/* Helper function to write MMIO offset for max/min control frequency */
141265static void write_control_freq (struct tpmi_uncore_cluster_info * cluster_info , unsigned int input ,
142266 unsigned int index )
@@ -156,7 +280,7 @@ static void write_control_freq(struct tpmi_uncore_cluster_info *cluster_info, un
156280 writeq (control , (cluster_info -> cluster_base + UNCORE_CONTROL_INDEX ));
157281}
158282
159- /* Callback for sysfs write for max/min frequencies. Called under mutex locks */
283+ /* Helper for sysfs write for max/min frequencies. Called under mutex locks */
160284static int uncore_write_control_freq (struct uncore_data * data , unsigned int input ,
161285 enum uncore_index index )
162286{
@@ -234,6 +358,33 @@ static int uncore_read(struct uncore_data *data, unsigned int *value, enum uncor
234358 case UNCORE_INDEX_CURRENT_FREQ :
235359 return uncore_read_freq (data , value );
236360
361+ case UNCORE_INDEX_EFF_LAT_CTRL_LOW_THRESHOLD :
362+ case UNCORE_INDEX_EFF_LAT_CTRL_HIGH_THRESHOLD :
363+ case UNCORE_INDEX_EFF_LAT_CTRL_HIGH_THRESHOLD_ENABLE :
364+ case UNCORE_INDEX_EFF_LAT_CTRL_FREQ :
365+ return read_eff_lat_ctrl (data , value , index );
366+
367+ default :
368+ break ;
369+ }
370+
371+ return - EOPNOTSUPP ;
372+ }
373+
374+ /* Callback for sysfs write for TPMI uncore data. Called under mutex locks. */
375+ static int uncore_write (struct uncore_data * data , unsigned int value , enum uncore_index index )
376+ {
377+ switch (index ) {
378+ case UNCORE_INDEX_EFF_LAT_CTRL_LOW_THRESHOLD :
379+ case UNCORE_INDEX_EFF_LAT_CTRL_HIGH_THRESHOLD :
380+ case UNCORE_INDEX_EFF_LAT_CTRL_HIGH_THRESHOLD_ENABLE :
381+ case UNCORE_INDEX_EFF_LAT_CTRL_FREQ :
382+ return write_eff_lat_ctrl (data , value , index );
383+
384+ case UNCORE_INDEX_MIN_FREQ :
385+ case UNCORE_INDEX_MAX_FREQ :
386+ return uncore_write_control_freq (data , value , index );
387+
237388 default :
238389 break ;
239390 }
@@ -291,7 +442,7 @@ static int uncore_probe(struct auxiliary_device *auxdev, const struct auxiliary_
291442 return - EINVAL ;
292443
293444 /* Register callbacks to uncore core */
294- ret = uncore_freq_common_init (uncore_read , uncore_write_control_freq );
445+ ret = uncore_freq_common_init (uncore_read , uncore_write );
295446 if (ret )
296447 return ret ;
297448
@@ -412,6 +563,9 @@ static int uncore_probe(struct auxiliary_device *auxdev, const struct auxiliary_
412563
413564 cluster_info -> uncore_root = tpmi_uncore ;
414565
566+ if (TPMI_MINOR_VERSION (pd_info -> ufs_header_ver ) >= UNCORE_ELC_SUPPORTED_VERSION )
567+ cluster_info -> elc_supported = true;
568+
415569 ret = uncore_freq_add_entry (& cluster_info -> uncore_data , 0 );
416570 if (ret ) {
417571 cluster_info -> cluster_base = NULL ;
@@ -430,6 +584,9 @@ static int uncore_probe(struct auxiliary_device *auxdev, const struct auxiliary_
430584
431585 auxiliary_set_drvdata (auxdev , tpmi_uncore );
432586
587+ if (topology_max_die_per_package () > 1 )
588+ return 0 ;
589+
433590 tpmi_uncore -> root_cluster .root_domain = true;
434591 tpmi_uncore -> root_cluster .uncore_root = tpmi_uncore ;
435592
@@ -453,7 +610,9 @@ static void uncore_remove(struct auxiliary_device *auxdev)
453610{
454611 struct tpmi_uncore_struct * tpmi_uncore = auxiliary_get_drvdata (auxdev );
455612
456- uncore_freq_remove_die_entry (& tpmi_uncore -> root_cluster .uncore_data );
613+ if (tpmi_uncore -> root_cluster .root_domain )
614+ uncore_freq_remove_die_entry (& tpmi_uncore -> root_cluster .uncore_data );
615+
457616 remove_cluster_entries (tpmi_uncore );
458617
459618 uncore_freq_common_exit ();
0 commit comments