1212#include <asm/amd/hsmp.h>
1313
1414#include <linux/acpi.h>
15+ #include <linux/array_size.h>
16+ #include <linux/bits.h>
17+ #include <linux/bitfield.h>
1518#include <linux/device.h>
1619#include <linux/dev_printk.h>
1720#include <linux/ioport.h>
3639
3740static struct hsmp_plat_device * hsmp_pdev ;
3841
42+ struct hsmp_sys_attr {
43+ struct device_attribute dattr ;
44+ u32 msg_id ;
45+ };
46+
3947static int amd_hsmp_acpi_rdwr (struct hsmp_socket * sock , u32 offset ,
4048 u32 * value , bool write )
4149{
@@ -243,6 +251,215 @@ static umode_t hsmp_is_sock_attr_visible(struct kobject *kobj,
243251 return 0 ;
244252}
245253
254+ static umode_t hsmp_is_sock_dev_attr_visible (struct kobject * kobj ,
255+ struct attribute * attr , int id )
256+ {
257+ return attr -> mode ;
258+ }
259+
260+ #define to_hsmp_sys_attr (_attr ) container_of(_attr, struct hsmp_sys_attr, dattr)
261+
262+ static ssize_t hsmp_msg_resp32_show (struct device * dev , struct device_attribute * attr ,
263+ char * buf )
264+ {
265+ struct hsmp_sys_attr * hattr = to_hsmp_sys_attr (attr );
266+ struct hsmp_socket * sock = dev_get_drvdata (dev );
267+ u32 data ;
268+ int ret ;
269+
270+ ret = hsmp_msg_get_nargs (sock -> sock_ind , hattr -> msg_id , & data , 1 );
271+ if (ret )
272+ return ret ;
273+
274+ return sysfs_emit (buf , "%u\n" , data );
275+ }
276+
277+ #define DDR_MAX_BW_MASK GENMASK(31, 20)
278+ #define DDR_UTIL_BW_MASK GENMASK(19, 8)
279+ #define DDR_UTIL_BW_PERC_MASK GENMASK(7, 0)
280+ #define FW_VER_MAJOR_MASK GENMASK(23, 16)
281+ #define FW_VER_MINOR_MASK GENMASK(15, 8)
282+ #define FW_VER_DEBUG_MASK GENMASK(7, 0)
283+ #define FMAX_MASK GENMASK(31, 16)
284+ #define FMIN_MASK GENMASK(15, 0)
285+ #define FREQ_LIMIT_MASK GENMASK(31, 16)
286+ #define FREQ_SRC_IND_MASK GENMASK(15, 0)
287+
288+ static ssize_t hsmp_ddr_max_bw_show (struct device * dev , struct device_attribute * attr ,
289+ char * buf )
290+ {
291+ struct hsmp_sys_attr * hattr = to_hsmp_sys_attr (attr );
292+ struct hsmp_socket * sock = dev_get_drvdata (dev );
293+ u32 data ;
294+ int ret ;
295+
296+ ret = hsmp_msg_get_nargs (sock -> sock_ind , hattr -> msg_id , & data , 1 );
297+ if (ret )
298+ return ret ;
299+
300+ return sysfs_emit (buf , "%lu\n" , FIELD_GET (DDR_MAX_BW_MASK , data ));
301+ }
302+
303+ static ssize_t hsmp_ddr_util_bw_show (struct device * dev , struct device_attribute * attr ,
304+ char * buf )
305+ {
306+ struct hsmp_sys_attr * hattr = to_hsmp_sys_attr (attr );
307+ struct hsmp_socket * sock = dev_get_drvdata (dev );
308+ u32 data ;
309+ int ret ;
310+
311+ ret = hsmp_msg_get_nargs (sock -> sock_ind , hattr -> msg_id , & data , 1 );
312+ if (ret )
313+ return ret ;
314+
315+ return sysfs_emit (buf , "%lu\n" , FIELD_GET (DDR_UTIL_BW_MASK , data ));
316+ }
317+
318+ static ssize_t hsmp_ddr_util_bw_perc_show (struct device * dev , struct device_attribute * attr ,
319+ char * buf )
320+ {
321+ struct hsmp_sys_attr * hattr = to_hsmp_sys_attr (attr );
322+ struct hsmp_socket * sock = dev_get_drvdata (dev );
323+ u32 data ;
324+ int ret ;
325+
326+ ret = hsmp_msg_get_nargs (sock -> sock_ind , hattr -> msg_id , & data , 1 );
327+ if (ret )
328+ return ret ;
329+
330+ return sysfs_emit (buf , "%lu\n" , FIELD_GET (DDR_UTIL_BW_PERC_MASK , data ));
331+ }
332+
333+ static ssize_t hsmp_msg_fw_ver_show (struct device * dev , struct device_attribute * attr ,
334+ char * buf )
335+ {
336+ struct hsmp_sys_attr * hattr = to_hsmp_sys_attr (attr );
337+ struct hsmp_socket * sock = dev_get_drvdata (dev );
338+ u32 data ;
339+ int ret ;
340+
341+ ret = hsmp_msg_get_nargs (sock -> sock_ind , hattr -> msg_id , & data , 1 );
342+ if (ret )
343+ return ret ;
344+
345+ return sysfs_emit (buf , "%lu.%lu.%lu\n" ,
346+ FIELD_GET (FW_VER_MAJOR_MASK , data ),
347+ FIELD_GET (FW_VER_MINOR_MASK , data ),
348+ FIELD_GET (FW_VER_DEBUG_MASK , data ));
349+ }
350+
351+ static ssize_t hsmp_fclk_show (struct device * dev , struct device_attribute * attr ,
352+ char * buf )
353+ {
354+ struct hsmp_sys_attr * hattr = to_hsmp_sys_attr (attr );
355+ struct hsmp_socket * sock = dev_get_drvdata (dev );
356+ u32 data [2 ];
357+ int ret ;
358+
359+ ret = hsmp_msg_get_nargs (sock -> sock_ind , hattr -> msg_id , data , 2 );
360+ if (ret )
361+ return ret ;
362+
363+ return sysfs_emit (buf , "%u\n" , data [0 ]);
364+ }
365+
366+ static ssize_t hsmp_mclk_show (struct device * dev , struct device_attribute * attr ,
367+ char * buf )
368+ {
369+ struct hsmp_sys_attr * hattr = to_hsmp_sys_attr (attr );
370+ struct hsmp_socket * sock = dev_get_drvdata (dev );
371+ u32 data [2 ];
372+ int ret ;
373+
374+ ret = hsmp_msg_get_nargs (sock -> sock_ind , hattr -> msg_id , data , 2 );
375+ if (ret )
376+ return ret ;
377+
378+ return sysfs_emit (buf , "%u\n" , data [1 ]);
379+ }
380+
381+ static ssize_t hsmp_clk_fmax_show (struct device * dev , struct device_attribute * attr ,
382+ char * buf )
383+ {
384+ struct hsmp_sys_attr * hattr = to_hsmp_sys_attr (attr );
385+ struct hsmp_socket * sock = dev_get_drvdata (dev );
386+ u32 data ;
387+ int ret ;
388+
389+ ret = hsmp_msg_get_nargs (sock -> sock_ind , hattr -> msg_id , & data , 1 );
390+ if (ret )
391+ return ret ;
392+
393+ return sysfs_emit (buf , "%lu\n" , FIELD_GET (FMAX_MASK , data ));
394+ }
395+
396+ static ssize_t hsmp_clk_fmin_show (struct device * dev , struct device_attribute * attr ,
397+ char * buf )
398+ {
399+ struct hsmp_sys_attr * hattr = to_hsmp_sys_attr (attr );
400+ struct hsmp_socket * sock = dev_get_drvdata (dev );
401+ u32 data ;
402+ int ret ;
403+
404+ ret = hsmp_msg_get_nargs (sock -> sock_ind , hattr -> msg_id , & data , 1 );
405+ if (ret )
406+ return ret ;
407+
408+ return sysfs_emit (buf , "%lu\n" , FIELD_GET (FMIN_MASK , data ));
409+ }
410+
411+ static ssize_t hsmp_freq_limit_show (struct device * dev , struct device_attribute * attr ,
412+ char * buf )
413+ {
414+ struct hsmp_sys_attr * hattr = to_hsmp_sys_attr (attr );
415+ struct hsmp_socket * sock = dev_get_drvdata (dev );
416+ u32 data ;
417+ int ret ;
418+
419+ ret = hsmp_msg_get_nargs (sock -> sock_ind , hattr -> msg_id , & data , 1 );
420+ if (ret )
421+ return ret ;
422+
423+ return sysfs_emit (buf , "%lu\n" , FIELD_GET (FREQ_LIMIT_MASK , data ));
424+ }
425+
426+ static const char * const freqlimit_srcnames [] = {
427+ "cHTC-Active" ,
428+ "PROCHOT" ,
429+ "TDC limit" ,
430+ "PPT Limit" ,
431+ "OPN Max" ,
432+ "Reliability Limit" ,
433+ "APML Agent" ,
434+ "HSMP Agent" ,
435+ };
436+
437+ static ssize_t hsmp_freq_limit_source_show (struct device * dev , struct device_attribute * attr ,
438+ char * buf )
439+ {
440+ struct hsmp_sys_attr * hattr = to_hsmp_sys_attr (attr );
441+ struct hsmp_socket * sock = dev_get_drvdata (dev );
442+ unsigned int index ;
443+ int len = 0 ;
444+ u16 src_ind ;
445+ u32 data ;
446+ int ret ;
447+
448+ ret = hsmp_msg_get_nargs (sock -> sock_ind , hattr -> msg_id , & data , 1 );
449+ if (ret )
450+ return ret ;
451+
452+ src_ind = FIELD_GET (FREQ_SRC_IND_MASK , data );
453+ for (index = 0 ; index < ARRAY_SIZE (freqlimit_srcnames ); index ++ ) {
454+ if (!src_ind )
455+ break ;
456+ if (src_ind & 1 )
457+ len += sysfs_emit_at (buf , len , "%s\n" , freqlimit_srcnames [index ]);
458+ src_ind >>= 1 ;
459+ }
460+ return len ;
461+ }
462+
246463static int init_acpi (struct device * dev )
247464{
248465 u16 sock_ind ;
@@ -285,6 +502,8 @@ static int init_acpi(struct device *dev)
285502 if (ret )
286503 dev_err (dev , "Failed to register HSMP sensors with hwmon\n" );
287504
505+ dev_set_drvdata (dev , & hsmp_pdev -> sock [sock_ind ]);
506+
288507 return ret ;
289508}
290509
@@ -299,9 +518,52 @@ static struct bin_attribute *hsmp_attr_list[] = {
299518 NULL
300519};
301520
521+ #define HSMP_DEV_ATTR (_name , _msg_id , _show , _mode ) \
522+ static struct hsmp_sys_attr hattr_##_name = { \
523+ .dattr = __ATTR(_name, _mode, _show, NULL), \
524+ .msg_id = _msg_id, \
525+ }
526+
527+ HSMP_DEV_ATTR (c0_residency_input , HSMP_GET_C0_PERCENT , hsmp_msg_resp32_show , 0444 );
528+ HSMP_DEV_ATTR (prochot_status , HSMP_GET_PROC_HOT , hsmp_msg_resp32_show , 0444 );
529+ HSMP_DEV_ATTR (smu_fw_version , HSMP_GET_SMU_VER , hsmp_msg_fw_ver_show , 0444 );
530+ HSMP_DEV_ATTR (protocol_version , HSMP_GET_PROTO_VER , hsmp_msg_resp32_show , 0444 );
531+ HSMP_DEV_ATTR (cclk_freq_limit_input , HSMP_GET_CCLK_THROTTLE_LIMIT , hsmp_msg_resp32_show , 0444 );
532+ HSMP_DEV_ATTR (ddr_max_bw , HSMP_GET_DDR_BANDWIDTH , hsmp_ddr_max_bw_show , 0444 );
533+ HSMP_DEV_ATTR (ddr_utilised_bw_input , HSMP_GET_DDR_BANDWIDTH , hsmp_ddr_util_bw_show , 0444 );
534+ HSMP_DEV_ATTR (ddr_utilised_bw_perc_input , HSMP_GET_DDR_BANDWIDTH , hsmp_ddr_util_bw_perc_show , 0444 );
535+ HSMP_DEV_ATTR (fclk_input , HSMP_GET_FCLK_MCLK , hsmp_fclk_show , 0444 );
536+ HSMP_DEV_ATTR (mclk_input , HSMP_GET_FCLK_MCLK , hsmp_mclk_show , 0444 );
537+ HSMP_DEV_ATTR (clk_fmax , HSMP_GET_SOCKET_FMAX_FMIN , hsmp_clk_fmax_show , 0444 );
538+ HSMP_DEV_ATTR (clk_fmin , HSMP_GET_SOCKET_FMAX_FMIN , hsmp_clk_fmin_show , 0444 );
539+ HSMP_DEV_ATTR (pwr_current_active_freq_limit , HSMP_GET_SOCKET_FREQ_LIMIT ,
540+ hsmp_freq_limit_show , 0444 );
541+ HSMP_DEV_ATTR (pwr_current_active_freq_limit_source , HSMP_GET_SOCKET_FREQ_LIMIT ,
542+ hsmp_freq_limit_source_show , 0444 );
543+
544+ static struct attribute * hsmp_dev_attr_list [] = {
545+ & hattr_c0_residency_input .dattr .attr ,
546+ & hattr_prochot_status .dattr .attr ,
547+ & hattr_smu_fw_version .dattr .attr ,
548+ & hattr_protocol_version .dattr .attr ,
549+ & hattr_cclk_freq_limit_input .dattr .attr ,
550+ & hattr_ddr_max_bw .dattr .attr ,
551+ & hattr_ddr_utilised_bw_input .dattr .attr ,
552+ & hattr_ddr_utilised_bw_perc_input .dattr .attr ,
553+ & hattr_fclk_input .dattr .attr ,
554+ & hattr_mclk_input .dattr .attr ,
555+ & hattr_clk_fmax .dattr .attr ,
556+ & hattr_clk_fmin .dattr .attr ,
557+ & hattr_pwr_current_active_freq_limit .dattr .attr ,
558+ & hattr_pwr_current_active_freq_limit_source .dattr .attr ,
559+ NULL
560+ };
561+
302562static struct attribute_group hsmp_attr_grp = {
303563 .bin_attrs = hsmp_attr_list ,
564+ .attrs = hsmp_dev_attr_list ,
304565 .is_bin_visible = hsmp_is_sock_attr_visible ,
566+ .is_visible = hsmp_is_sock_dev_attr_visible ,
305567};
306568
307569static const struct attribute_group * hsmp_groups [] = {
0 commit comments