faft-gsc: use gsc_ecrst_pulse to reset the EC

Use `ecrst pulse` to reset the EC and enter dev mode.

Update faft-gsc tests to use gsc_ecrst_pulse for cold reset. `ecrst
pulse` can reset the EC and keep the EC-EFS2 boot mode in sync with the
system state when ccd is locked.

This changes try to use the ecrst pulse control if it's available. If it
isn't, it falls back to uring the old controls. A follow up CL will
remove the backup methods after the labstation image has ecrst pulse
support in hdctools.

BUG=b:294426380
TEST=run firmware_Cr50DevMode and firmware_Cr50Testlab on hatch

Change-Id: I97d2affe6cd2e39c6fa7bc80683031e12e936b62
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/autotest/+/4755823
Commit-Queue: Mary Ruthven <mruthven@chromium.org>
Reviewed-by: Edward Hill <ecgh@chromium.org>
Tested-by: Mary Ruthven <mruthven@chromium.org>
diff --git a/server/cros/faft/cr50_test.py b/server/cros/faft/cr50_test.py
index 53f5e3d..941ce61 100644
--- a/server/cros/faft/cr50_test.py
+++ b/server/cros/faft/cr50_test.py
@@ -63,9 +63,11 @@
         if 'ccd' in self.servo.get_servo_version():
             self.servo.disable_ccd_watchdog_for_test()
 
-        if ((restore_cr50_image or restore_cr50_board_id) and
-            self.servo.main_device_uses_gsc_drv() and
-            self.gsc.running_mp_image()):
+        if ((restore_cr50_image or restore_cr50_board_id)
+                    and self.servo.main_device_uses_gsc_drv()
+                    and self.gsc.running_mp_image()
+                    and not self.servo.has_control('gsc_ecrst_pulse')
+                    and not self.servo.has_control('cold_reset_select')):
             # Tests that restore the image or the board id have to update
             # to the DBG image. This clears testlab mode. If a board relies
             # on ccd for basic servo functionality, this could make the dut
diff --git a/server/cros/faft/firmware_test.py b/server/cros/faft/firmware_test.py
index d480d48..97f9c89 100644
--- a/server/cros/faft/firmware_test.py
+++ b/server/cros/faft/firmware_test.py
@@ -2453,16 +2453,25 @@
             enable_testlab = False
 
         restore_cold_reset_select = None
-        # If servo uses gsc_ec_reset to hold the EC in reset, it won't be
-        # available when gsc is locked. Use gsc_reset to open ccd since that
-        # works with locked ccd.
-        if self.servo.main_device_uses_gsc_drv():
-            if self.gsc.servo_drv_enabled():
-                logging.info('Using GSC EC reset')
-                self.servo.set('cold_reset_select', 'gsc_ec_reset')
-            else:
-                logging.info('GSC EC reset not enabled. Using GSC reset')
-                self.servo.set('cold_reset_select', 'gsc_reset')
+        if self.servo.has_control('cold_reset_select'):
+            restore_cold_reset_select = self.servo.get('cold_reset_select')
+            # `ecrst pulse` is always available. Use it to reset the EC. It
+            # will reset the EC and keep the EC-EFS2 boot mode in sync with the
+            # system state.
+            if self.servo.has_control('gsc_ecrst_pulse'):
+                self.servo.set('cold_reset_select', 'gsc_ecrst_pulse')
+            elif self.servo.main_device_uses_gsc_drv():
+                # TODO(b/294426380): remove this after servod has support for
+                # using `ecrst pulse` in the lab.
+                # `ecrst pulse` is always available. It will let tests enter
+                # dev mode even when ccd is locked.
+                if self.gsc.servo_drv_enabled():
+                    logging.info('Using GSC EC reset')
+                    self.servo.set('cold_reset_select', 'gsc_ec_reset')
+                else:
+                    logging.info('GSC EC reset not enabled. Using GSC reset')
+                    self.servo.set('cold_reset_select', 'gsc_reset')
+
         # Try to use testlab open first, so we don't have to wait for the
         # physical presence check.
         self.gsc.send_command('ccd testlab open')
diff --git a/server/cros/servo/servo.py b/server/cros/servo/servo.py
index 0b708d7..47cb8e4 100644
--- a/server/cros/servo/servo.py
+++ b/server/cros/servo/servo.py
@@ -1503,6 +1503,9 @@
         get restricted with ccd capabilities. This returns true if some of
         the servo functionality will be disabled if ccd is restricted.
         """
+        # TODO(b/294426380): remove has_control('cold_reset_select') check
+        # after labstation updates to servod controls that support using
+        # 'ecrst pulse' to reset the EC.
         return (self.get_main_servo_device() in self.GSC_DRV_SERVOS
                 or self.has_control('cold_reset_select'))
 
diff --git a/server/site_tests/firmware_Cr50CCDFirmwareUpdate/firmware_Cr50CCDFirmwareUpdate.py b/server/site_tests/firmware_Cr50CCDFirmwareUpdate/firmware_Cr50CCDFirmwareUpdate.py
index b2a4148..54b4e331 100644
--- a/server/site_tests/firmware_Cr50CCDFirmwareUpdate/firmware_Cr50CCDFirmwareUpdate.py
+++ b/server/site_tests/firmware_Cr50CCDFirmwareUpdate/firmware_Cr50CCDFirmwareUpdate.py
@@ -146,9 +146,13 @@
 
         # Make sure to use the GSC ec_reset command for cold reset snce that's
         # what normal ccd devices will use.
-        if (self.servo.has_control('cold_reset_select')
-                    and self.servo.has_control('gsc_ec_reset')):
-            self.servo.set('cold_reset_select', 'gsc_ec_reset')
+        if self.servo.has_control('cold_reset_select'):
+            if self.servo.has_control('gsc_ecrst_pulse'):
+                self.servo.set('cold_reset_select', 'gsc_ecrst_pulse')
+            elif self.servo.has_control('gsc_ec_reset'):
+                # TODO(b/294426380): remove when the labstation servod image
+                # supports gsc_ecrst_pulse.
+                self.servo.set('cold_reset_select', 'gsc_ec_reset')
         # TODO(b/196824029): remove when servod supports using the power state
         # controller with the ccd device.
         try:
diff --git a/server/site_tests/firmware_Cr50DevMode/firmware_Cr50DevMode.py b/server/site_tests/firmware_Cr50DevMode/firmware_Cr50DevMode.py
index 0e4b685..4cd4aac 100644
--- a/server/site_tests/firmware_Cr50DevMode/firmware_Cr50DevMode.py
+++ b/server/site_tests/firmware_Cr50DevMode/firmware_Cr50DevMode.py
@@ -26,10 +26,14 @@
             if not self.servo.has_control('cold_reset_select'):
                 raise error.TestError('Servo setup issue: board uses EC-EFS2, '
                         'but ec_efs2.xml was not included by servod')
-            self.fast_ccd_open(True)
-            self.gsc.enable_servo_control_caps()
-            self.servo.set_nocheck('cold_reset_select', 'gsc_ec_reset')
-            self.gsc.set_ccd_level('lock')
+            if self.servo.has_control('gsc_ecrst_pulse'):
+                self.servo.set_nocheck('cold_reset_select', 'gsc_ecrst_pulse')
+            else:
+                # TODO(b/294426380): remove when gsc_ecrst_pulse is in the lab.
+                self.fast_ccd_open(True)
+                self.gsc.enable_servo_control_caps()
+                self.servo.set_nocheck('cold_reset_select', 'gsc_ec_reset')
+                self.gsc.set_ccd_level('lock')
 
         self.enter_mode_after_checking_cr50_state('normal')
         self.check_dev_mode(False)
diff --git a/server/site_tests/firmware_Cr50OpenWhileAPOff/firmware_Cr50OpenWhileAPOff.py b/server/site_tests/firmware_Cr50OpenWhileAPOff/firmware_Cr50OpenWhileAPOff.py
index 8c00005..09649d7 100644
--- a/server/site_tests/firmware_Cr50OpenWhileAPOff/firmware_Cr50OpenWhileAPOff.py
+++ b/server/site_tests/firmware_Cr50OpenWhileAPOff/firmware_Cr50OpenWhileAPOff.py
@@ -70,7 +70,12 @@
         if self.servo.has_control('cold_reset_select'):
             # Use the servo micro cold reset signal to hold the EC in reset.
             if self.reset_ec:
-                self.servo.set('cold_reset_select', 'cold_reset_default')
+                if self.servo.has_control('default_cold_reset'):
+                    self.servo.set('cold_reset_select', 'default_cold_reset')
+                else:
+                    # TODO(b/294426380): remove when default_cold_reset is in
+                    # the lab.
+                    self.servo.set('cold_reset_select', 'cold_reset_default')
                 logging.info('Using servo cold_reset signal')
             logging.info('using %s for cold reset',
                          self.servo.get('cold_reset_select'))
diff --git a/server/site_tests/firmware_Cr50Testlab/firmware_Cr50Testlab.py b/server/site_tests/firmware_Cr50Testlab/firmware_Cr50Testlab.py
index 839857d..1fee055 100644
--- a/server/site_tests/firmware_Cr50Testlab/firmware_Cr50Testlab.py
+++ b/server/site_tests/firmware_Cr50Testlab/firmware_Cr50Testlab.py
@@ -30,8 +30,17 @@
             self.BASIC_ERROR = 'Command \'ccd\' failed'
             self.INVALID_PARAM = 'Param2'
 
-        if (host.servo.main_device_uses_gsc_drv()
-                    and self.gsc.running_mp_image()):
+        # 'ecrst pulse' is always available. This test is going to lock ccd.
+        # use 'ecrst pulse' for cold reset, so the test can enter dev mode
+        # when ccd is locked.
+        if (self.servo.has_control('gsc_ecrst_pulse')
+                    and self.servo.has_control('cold_reset_select')):
+            logging.info('Using ecrst pulse for cold reset')
+            self.servo.set('cold_reset_select', 'gsc_ecrst_pulse')
+        elif (self.servo.main_device_uses_gsc_drv()
+              and self.gsc.running_mp_image()):
+            # TODO(b/294426380): remove this after servod has support for
+            # using `ecrst pulse` in the lab.
             raise error.TestNAError('Uses gsc for ecrst. Cannot run until '
                                     'cold_reset issue is resolved')
         # Get the current reset count, so we can check that there haven't been