@@ -717,3 +717,120 @@ u32 cros_ec_get_host_event(struct cros_ec_device *ec_dev)
717
717
return host_event ;
718
718
}
719
719
EXPORT_SYMBOL (cros_ec_get_host_event );
720
+
721
+ /**
722
+ * cros_ec_check_features() - Test for the presence of EC features
723
+ *
724
+ * @ec: EC device, does not have to be connected directly to the AP,
725
+ * can be daisy chained through another device.
726
+ * @feature: One of ec_feature_code bit.
727
+ *
728
+ * Call this function to test whether the ChromeOS EC supports a feature.
729
+ *
730
+ * Return: 1 if supported, 0 if not
731
+ */
732
+ int cros_ec_check_features (struct cros_ec_dev * ec , int feature )
733
+ {
734
+ struct cros_ec_command * msg ;
735
+ int ret ;
736
+
737
+ if (ec -> features [0 ] == -1U && ec -> features [1 ] == -1U ) {
738
+ /* features bitmap not read yet */
739
+ msg = kzalloc (sizeof (* msg ) + sizeof (ec -> features ), GFP_KERNEL );
740
+ if (!msg )
741
+ return - ENOMEM ;
742
+
743
+ msg -> command = EC_CMD_GET_FEATURES + ec -> cmd_offset ;
744
+ msg -> insize = sizeof (ec -> features );
745
+
746
+ ret = cros_ec_cmd_xfer_status (ec -> ec_dev , msg );
747
+ if (ret < 0 ) {
748
+ dev_warn (ec -> dev , "cannot get EC features: %d/%d\n" ,
749
+ ret , msg -> result );
750
+ memset (ec -> features , 0 , sizeof (ec -> features ));
751
+ } else {
752
+ memcpy (ec -> features , msg -> data , sizeof (ec -> features ));
753
+ }
754
+
755
+ dev_dbg (ec -> dev , "EC features %08x %08x\n" ,
756
+ ec -> features [0 ], ec -> features [1 ]);
757
+
758
+ kfree (msg );
759
+ }
760
+
761
+ return ec -> features [feature / 32 ] & EC_FEATURE_MASK_0 (feature );
762
+ }
763
+ EXPORT_SYMBOL_GPL (cros_ec_check_features );
764
+
765
+ /**
766
+ * cros_ec_get_sensor_count() - Return the number of MEMS sensors supported.
767
+ *
768
+ * @ec: EC device, does not have to be connected directly to the AP,
769
+ * can be daisy chained through another device.
770
+ * Return: < 0 in case of error.
771
+ */
772
+ int cros_ec_get_sensor_count (struct cros_ec_dev * ec )
773
+ {
774
+ /*
775
+ * Issue a command to get the number of sensor reported.
776
+ * If not supported, check for legacy mode.
777
+ */
778
+ int ret , sensor_count ;
779
+ struct ec_params_motion_sense * params ;
780
+ struct ec_response_motion_sense * resp ;
781
+ struct cros_ec_command * msg ;
782
+ struct cros_ec_device * ec_dev = ec -> ec_dev ;
783
+ u8 status ;
784
+
785
+ msg = kzalloc (sizeof (* msg ) + max (sizeof (* params ), sizeof (* resp )),
786
+ GFP_KERNEL );
787
+ if (!msg )
788
+ return - ENOMEM ;
789
+
790
+ msg -> version = 1 ;
791
+ msg -> command = EC_CMD_MOTION_SENSE_CMD + ec -> cmd_offset ;
792
+ msg -> outsize = sizeof (* params );
793
+ msg -> insize = sizeof (* resp );
794
+
795
+ params = (struct ec_params_motion_sense * )msg -> data ;
796
+ params -> cmd = MOTIONSENSE_CMD_DUMP ;
797
+
798
+ ret = cros_ec_cmd_xfer (ec -> ec_dev , msg );
799
+ if (ret < 0 ) {
800
+ sensor_count = ret ;
801
+ } else if (msg -> result != EC_RES_SUCCESS ) {
802
+ sensor_count = - EPROTO ;
803
+ } else {
804
+ resp = (struct ec_response_motion_sense * )msg -> data ;
805
+ sensor_count = resp -> dump .sensor_count ;
806
+ }
807
+ kfree (msg );
808
+
809
+ /*
810
+ * Check legacy mode: Let's find out if sensors are accessible
811
+ * via LPC interface.
812
+ */
813
+ if (sensor_count == - EPROTO &&
814
+ ec -> cmd_offset == 0 &&
815
+ ec_dev -> cmd_readmem ) {
816
+ ret = ec_dev -> cmd_readmem (ec_dev , EC_MEMMAP_ACC_STATUS ,
817
+ 1 , & status );
818
+ if (ret >= 0 &&
819
+ (status & EC_MEMMAP_ACC_STATUS_PRESENCE_BIT )) {
820
+ /*
821
+ * We have 2 sensors, one in the lid, one in the base.
822
+ */
823
+ sensor_count = 2 ;
824
+ } else {
825
+ /*
826
+ * EC uses LPC interface and no sensors are presented.
827
+ */
828
+ sensor_count = 0 ;
829
+ }
830
+ } else if (sensor_count == - EPROTO ) {
831
+ /* EC responded, but does not understand DUMP command. */
832
+ sensor_count = 0 ;
833
+ }
834
+ return sensor_count ;
835
+ }
836
+ EXPORT_SYMBOL_GPL (cros_ec_get_sensor_count );
0 commit comments