1
1
// SPDX-License-Identifier: GPL-2.0
2
2
3
3
#include <linux/device.h>
4
+ #include <linux/hwmon.h>
4
5
#include <linux/hwmon-sysfs.h>
5
6
#include <linux/jiffies.h>
6
7
#include <linux/kernel.h>
7
8
#include <linux/math64.h>
8
9
#include <linux/mutex.h>
10
+ #include <linux/sysfs.h>
9
11
#include <asm/unaligned.h>
10
12
11
13
#include "common.h"
@@ -641,6 +643,324 @@ static ssize_t occ_show_extended(struct device *dev,
641
643
return rc ;
642
644
}
643
645
646
+ /*
647
+ * Some helper macros to make it easier to define an occ_attribute. Since these
648
+ * are dynamically allocated, we shouldn't use the existing kernel macros which
649
+ * stringify the name argument.
650
+ */
651
+ #define ATTR_OCC (_name , _mode , _show , _store ) { \
652
+ .attr = { \
653
+ .name = _name, \
654
+ .mode = VERIFY_OCTAL_PERMISSIONS(_mode), \
655
+ }, \
656
+ .show = _show, \
657
+ .store = _store, \
658
+ }
659
+
660
+ #define SENSOR_ATTR_OCC (_name , _mode , _show , _store , _nr , _index ) { \
661
+ .dev_attr = ATTR_OCC(_name, _mode, _show, _store), \
662
+ .index = _index, \
663
+ .nr = _nr, \
664
+ }
665
+
666
+ #define OCC_INIT_ATTR (_name , _mode , _show , _store , _nr , _index ) \
667
+ ((struct sensor_device_attribute_2) \
668
+ SENSOR_ATTR_OCC(_name, _mode, _show, _store, _nr, _index))
669
+
670
+ /*
671
+ * Allocate and instatiate sensor_device_attribute_2s. It's most efficient to
672
+ * use our own instead of the built-in hwmon attribute types.
673
+ */
674
+ static int occ_setup_sensor_attrs (struct occ * occ )
675
+ {
676
+ unsigned int i , s , num_attrs = 0 ;
677
+ struct device * dev = occ -> bus_dev ;
678
+ struct occ_sensors * sensors = & occ -> sensors ;
679
+ struct occ_attribute * attr ;
680
+ struct temp_sensor_2 * temp ;
681
+ ssize_t (* show_temp )(struct device * , struct device_attribute * ,
682
+ char * ) = occ_show_temp_1 ;
683
+ ssize_t (* show_freq )(struct device * , struct device_attribute * ,
684
+ char * ) = occ_show_freq_1 ;
685
+ ssize_t (* show_power )(struct device * , struct device_attribute * ,
686
+ char * ) = occ_show_power_1 ;
687
+ ssize_t (* show_caps )(struct device * , struct device_attribute * ,
688
+ char * ) = occ_show_caps_1_2 ;
689
+
690
+ switch (sensors -> temp .version ) {
691
+ case 1 :
692
+ num_attrs += (sensors -> temp .num_sensors * 2 );
693
+ break ;
694
+ case 2 :
695
+ num_attrs += (sensors -> temp .num_sensors * 4 );
696
+ show_temp = occ_show_temp_2 ;
697
+ break ;
698
+ default :
699
+ sensors -> temp .num_sensors = 0 ;
700
+ }
701
+
702
+ switch (sensors -> freq .version ) {
703
+ case 2 :
704
+ show_freq = occ_show_freq_2 ;
705
+ /* fall through */
706
+ case 1 :
707
+ num_attrs += (sensors -> freq .num_sensors * 2 );
708
+ break ;
709
+ default :
710
+ sensors -> freq .num_sensors = 0 ;
711
+ }
712
+
713
+ switch (sensors -> power .version ) {
714
+ case 2 :
715
+ show_power = occ_show_power_2 ;
716
+ /* fall through */
717
+ case 1 :
718
+ num_attrs += (sensors -> power .num_sensors * 4 );
719
+ break ;
720
+ case 0xA0 :
721
+ num_attrs += (sensors -> power .num_sensors * 16 );
722
+ show_power = occ_show_power_a0 ;
723
+ break ;
724
+ default :
725
+ sensors -> power .num_sensors = 0 ;
726
+ }
727
+
728
+ switch (sensors -> caps .version ) {
729
+ case 1 :
730
+ num_attrs += (sensors -> caps .num_sensors * 7 );
731
+ break ;
732
+ case 3 :
733
+ show_caps = occ_show_caps_3 ;
734
+ /* fall through */
735
+ case 2 :
736
+ num_attrs += (sensors -> caps .num_sensors * 8 );
737
+ break ;
738
+ default :
739
+ sensors -> caps .num_sensors = 0 ;
740
+ }
741
+
742
+ switch (sensors -> extended .version ) {
743
+ case 1 :
744
+ num_attrs += (sensors -> extended .num_sensors * 3 );
745
+ break ;
746
+ default :
747
+ sensors -> extended .num_sensors = 0 ;
748
+ }
749
+
750
+ occ -> attrs = devm_kzalloc (dev , sizeof (* occ -> attrs ) * num_attrs ,
751
+ GFP_KERNEL );
752
+ if (!occ -> attrs )
753
+ return - ENOMEM ;
754
+
755
+ /* null-terminated list */
756
+ occ -> group .attrs = devm_kzalloc (dev , sizeof (* occ -> group .attrs ) *
757
+ num_attrs + 1 , GFP_KERNEL );
758
+ if (!occ -> group .attrs )
759
+ return - ENOMEM ;
760
+
761
+ attr = occ -> attrs ;
762
+
763
+ for (i = 0 ; i < sensors -> temp .num_sensors ; ++ i ) {
764
+ s = i + 1 ;
765
+ temp = ((struct temp_sensor_2 * )sensors -> temp .data ) + i ;
766
+
767
+ snprintf (attr -> name , sizeof (attr -> name ), "temp%d_label" , s );
768
+ attr -> sensor = OCC_INIT_ATTR (attr -> name , 0444 , show_temp , NULL ,
769
+ 0 , i );
770
+ attr ++ ;
771
+
772
+ if (sensors -> temp .version > 1 &&
773
+ temp -> fru_type == OCC_FRU_TYPE_VRM ) {
774
+ snprintf (attr -> name , sizeof (attr -> name ),
775
+ "temp%d_alarm" , s );
776
+ } else {
777
+ snprintf (attr -> name , sizeof (attr -> name ),
778
+ "temp%d_input" , s );
779
+ }
780
+
781
+ attr -> sensor = OCC_INIT_ATTR (attr -> name , 0444 , show_temp , NULL ,
782
+ 1 , i );
783
+ attr ++ ;
784
+
785
+ if (sensors -> temp .version > 1 ) {
786
+ snprintf (attr -> name , sizeof (attr -> name ),
787
+ "temp%d_fru_type" , s );
788
+ attr -> sensor = OCC_INIT_ATTR (attr -> name , 0444 ,
789
+ show_temp , NULL , 2 , i );
790
+ attr ++ ;
791
+
792
+ snprintf (attr -> name , sizeof (attr -> name ),
793
+ "temp%d_fault" , s );
794
+ attr -> sensor = OCC_INIT_ATTR (attr -> name , 0444 ,
795
+ show_temp , NULL , 3 , i );
796
+ attr ++ ;
797
+ }
798
+ }
799
+
800
+ for (i = 0 ; i < sensors -> freq .num_sensors ; ++ i ) {
801
+ s = i + 1 ;
802
+
803
+ snprintf (attr -> name , sizeof (attr -> name ), "freq%d_label" , s );
804
+ attr -> sensor = OCC_INIT_ATTR (attr -> name , 0444 , show_freq , NULL ,
805
+ 0 , i );
806
+ attr ++ ;
807
+
808
+ snprintf (attr -> name , sizeof (attr -> name ), "freq%d_input" , s );
809
+ attr -> sensor = OCC_INIT_ATTR (attr -> name , 0444 , show_freq , NULL ,
810
+ 1 , i );
811
+ attr ++ ;
812
+ }
813
+
814
+ if (sensors -> power .version == 0xA0 ) {
815
+ /*
816
+ * Special case for many-attribute power sensor. Split it into
817
+ * a sensor number per power type, emulating several sensors.
818
+ */
819
+ for (i = 0 ; i < sensors -> power .num_sensors ; ++ i ) {
820
+ unsigned int j ;
821
+ unsigned int nr = 0 ;
822
+
823
+ s = (i * 4 ) + 1 ;
824
+
825
+ for (j = 0 ; j < 4 ; ++ j ) {
826
+ snprintf (attr -> name , sizeof (attr -> name ),
827
+ "power%d_label" , s );
828
+ attr -> sensor = OCC_INIT_ATTR (attr -> name , 0444 ,
829
+ show_power , NULL ,
830
+ nr ++ , i );
831
+ attr ++ ;
832
+
833
+ snprintf (attr -> name , sizeof (attr -> name ),
834
+ "power%d_average" , s );
835
+ attr -> sensor = OCC_INIT_ATTR (attr -> name , 0444 ,
836
+ show_power , NULL ,
837
+ nr ++ , i );
838
+ attr ++ ;
839
+
840
+ snprintf (attr -> name , sizeof (attr -> name ),
841
+ "power%d_average_interval" , s );
842
+ attr -> sensor = OCC_INIT_ATTR (attr -> name , 0444 ,
843
+ show_power , NULL ,
844
+ nr ++ , i );
845
+ attr ++ ;
846
+
847
+ snprintf (attr -> name , sizeof (attr -> name ),
848
+ "power%d_input" , s );
849
+ attr -> sensor = OCC_INIT_ATTR (attr -> name , 0444 ,
850
+ show_power , NULL ,
851
+ nr ++ , i );
852
+ attr ++ ;
853
+
854
+ s ++ ;
855
+ }
856
+ }
857
+ } else {
858
+ for (i = 0 ; i < sensors -> power .num_sensors ; ++ i ) {
859
+ s = i + 1 ;
860
+
861
+ snprintf (attr -> name , sizeof (attr -> name ),
862
+ "power%d_label" , s );
863
+ attr -> sensor = OCC_INIT_ATTR (attr -> name , 0444 ,
864
+ show_power , NULL , 0 , i );
865
+ attr ++ ;
866
+
867
+ snprintf (attr -> name , sizeof (attr -> name ),
868
+ "power%d_average" , s );
869
+ attr -> sensor = OCC_INIT_ATTR (attr -> name , 0444 ,
870
+ show_power , NULL , 1 , i );
871
+ attr ++ ;
872
+
873
+ snprintf (attr -> name , sizeof (attr -> name ),
874
+ "power%d_average_interval" , s );
875
+ attr -> sensor = OCC_INIT_ATTR (attr -> name , 0444 ,
876
+ show_power , NULL , 2 , i );
877
+ attr ++ ;
878
+
879
+ snprintf (attr -> name , sizeof (attr -> name ),
880
+ "power%d_input" , s );
881
+ attr -> sensor = OCC_INIT_ATTR (attr -> name , 0444 ,
882
+ show_power , NULL , 3 , i );
883
+ attr ++ ;
884
+ }
885
+ }
886
+
887
+ if (sensors -> caps .num_sensors >= 1 ) {
888
+ s = sensors -> power .num_sensors + 1 ;
889
+
890
+ snprintf (attr -> name , sizeof (attr -> name ), "power%d_label" , s );
891
+ attr -> sensor = OCC_INIT_ATTR (attr -> name , 0444 , show_caps , NULL ,
892
+ 0 , 0 );
893
+ attr ++ ;
894
+
895
+ snprintf (attr -> name , sizeof (attr -> name ), "power%d_cap" , s );
896
+ attr -> sensor = OCC_INIT_ATTR (attr -> name , 0444 , show_caps , NULL ,
897
+ 1 , 0 );
898
+ attr ++ ;
899
+
900
+ snprintf (attr -> name , sizeof (attr -> name ), "power%d_input" , s );
901
+ attr -> sensor = OCC_INIT_ATTR (attr -> name , 0444 , show_caps , NULL ,
902
+ 2 , 0 );
903
+ attr ++ ;
904
+
905
+ snprintf (attr -> name , sizeof (attr -> name ),
906
+ "power%d_cap_not_redundant" , s );
907
+ attr -> sensor = OCC_INIT_ATTR (attr -> name , 0444 , show_caps , NULL ,
908
+ 3 , 0 );
909
+ attr ++ ;
910
+
911
+ snprintf (attr -> name , sizeof (attr -> name ), "power%d_cap_max" , s );
912
+ attr -> sensor = OCC_INIT_ATTR (attr -> name , 0444 , show_caps , NULL ,
913
+ 4 , 0 );
914
+ attr ++ ;
915
+
916
+ snprintf (attr -> name , sizeof (attr -> name ), "power%d_cap_min" , s );
917
+ attr -> sensor = OCC_INIT_ATTR (attr -> name , 0444 , show_caps , NULL ,
918
+ 5 , 0 );
919
+ attr ++ ;
920
+
921
+ snprintf (attr -> name , sizeof (attr -> name ), "power%d_cap_user" ,
922
+ s );
923
+ attr -> sensor = OCC_INIT_ATTR (attr -> name , 0644 , show_caps ,
924
+ occ_store_caps_user , 6 , 0 );
925
+ attr ++ ;
926
+
927
+ if (sensors -> caps .version > 1 ) {
928
+ snprintf (attr -> name , sizeof (attr -> name ),
929
+ "power%d_cap_user_source" , s );
930
+ attr -> sensor = OCC_INIT_ATTR (attr -> name , 0444 ,
931
+ show_caps , NULL , 7 , 0 );
932
+ attr ++ ;
933
+ }
934
+ }
935
+
936
+ for (i = 0 ; i < sensors -> extended .num_sensors ; ++ i ) {
937
+ s = i + 1 ;
938
+
939
+ snprintf (attr -> name , sizeof (attr -> name ), "extn%d_label" , s );
940
+ attr -> sensor = OCC_INIT_ATTR (attr -> name , 0444 ,
941
+ occ_show_extended , NULL , 0 , i );
942
+ attr ++ ;
943
+
944
+ snprintf (attr -> name , sizeof (attr -> name ), "extn%d_flags" , s );
945
+ attr -> sensor = OCC_INIT_ATTR (attr -> name , 0444 ,
946
+ occ_show_extended , NULL , 1 , i );
947
+ attr ++ ;
948
+
949
+ snprintf (attr -> name , sizeof (attr -> name ), "extn%d_input" , s );
950
+ attr -> sensor = OCC_INIT_ATTR (attr -> name , 0444 ,
951
+ occ_show_extended , NULL , 2 , i );
952
+ attr ++ ;
953
+ }
954
+
955
+ /* put the sensors in the group */
956
+ for (i = 0 ; i < num_attrs ; ++ i ) {
957
+ sysfs_attr_init (& occ -> attrs [i ].sensor .dev_attr .attr );
958
+ occ -> group .attrs [i ] = & occ -> attrs [i ].sensor .dev_attr .attr ;
959
+ }
960
+
961
+ return 0 ;
962
+ }
963
+
644
964
/* only need to do this once at startup, as OCC won't change sensors on us */
645
965
static void occ_parse_poll_response (struct occ * occ )
646
966
{
@@ -704,6 +1024,7 @@ int occ_setup(struct occ *occ, const char *name)
704
1024
int rc ;
705
1025
706
1026
mutex_init (& occ -> lock );
1027
+ occ -> groups [0 ] = & occ -> group ;
707
1028
708
1029
/* no need to lock */
709
1030
rc = occ_poll (occ );
@@ -718,5 +1039,21 @@ int occ_setup(struct occ *occ, const char *name)
718
1039
719
1040
occ_parse_poll_response (occ );
720
1041
1042
+ rc = occ_setup_sensor_attrs (occ );
1043
+ if (rc ) {
1044
+ dev_err (occ -> bus_dev , "failed to setup sensor attrs: %d\n" ,
1045
+ rc );
1046
+ return rc ;
1047
+ }
1048
+
1049
+ occ -> hwmon = devm_hwmon_device_register_with_groups (occ -> bus_dev , name ,
1050
+ occ , occ -> groups );
1051
+ if (IS_ERR (occ -> hwmon )) {
1052
+ rc = PTR_ERR (occ -> hwmon );
1053
+ dev_err (occ -> bus_dev , "failed to register hwmon device: %d\n" ,
1054
+ rc );
1055
+ return rc ;
1056
+ }
1057
+
721
1058
return 0 ;
722
1059
}
0 commit comments