xref: /aosp_15_r20/external/autotest/server/site_tests/firmware_Cr50ECReset/firmware_Cr50ECReset.py (revision 9c5db1993ded3edbeafc8092d69fe5de2ee02df7)
1# Copyright 2018 The Chromium OS Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5from __future__ import print_function
6
7import logging
8import time
9
10from autotest_lib.client.common_lib import error
11from autotest_lib.server.cros.faft.cr50_test import Cr50Test
12from autotest_lib.server.cros.servo import servo
13
14
15class firmware_Cr50ECReset(Cr50Test):
16    """Make sure 'cr50 ecrst' works as intended
17
18    EC_RST_L needs to be able to wake the EC from hibernate and hold the EC in
19    reset. This test verifies the hardware works as intended
20    """
21    version = 1
22
23    # Delays used by the test. Time is given in seconds
24    # Used to wait long enough for the EC to enter/resume from hibernate
25    EC_SETTLE_TIME = 10
26    RELEASE_RESET_DELAY = 3
27    SHORT_PULSE = 1
28
29
30    def initialize(self, host, cmdline_args, full_args):
31        super(firmware_Cr50ECReset, self).initialize(host, cmdline_args,
32                                                     full_args)
33        if not self.faft_config.gsc_can_wake_ec_with_reset:
34            raise error.TestNAError("This DUT has a hardware limitation that "
35                                    "prevents cr50 from waking the EC with "
36                                    "EC_RST_L.")
37
38        # TODO(b/186535695): EC hibernate puts cr50 into reset, so the test
39        # can't verify cr50 behavior while the EC is hibernate.
40        if 'c2d2' in self.servo.get_servo_type():
41            raise error.TestNAError('Cannot run test with c2d2')
42
43        # Don't bother if there is no Chrome EC or if EC hibernate doesn't work.
44        if not self.check_ec_capability():
45            raise error.TestNAError("Nothing needs to be tested on this device")
46
47        # Verify the EC can wake from hibernate with a power button press. If it
48        # can't, it's a device or servo issue.
49        try:
50            self.check_ec_hibernate()
51        except error.TestError as e:
52            raise error.TestNAError('Unsupported setup: %s' % str(e))
53
54
55    def cleanup(self):
56        """Make sure the EC is on, if there is a Chrome EC."""
57        try:
58            if self.check_ec_capability():
59                self.guarantee_ec_is_up()
60        except Exception as e:
61            logging.info('Issue recovering EC: %r', e)
62            logging.info('Trying power state reset')
63            self.host.servo.get_power_state_controller().reset()
64        finally:
65            super(firmware_Cr50ECReset, self).cleanup()
66
67
68    def ec_is_up(self):
69        """If the console is responsive, then the EC is awake"""
70        time.sleep(self.EC_SETTLE_TIME)
71        try:
72            self.ec.send_command_get_output('time', ['.*>'])
73        except servo.UnresponsiveConsoleError as e:
74            logging.info(str(e))
75            return False
76        else:
77            return True
78
79
80    def cold_reset(self, state):
81        """Set cold reset"""
82        self.servo.set('cold_reset', state)
83
84
85    def power_button(self, state):
86        """Press or release the power button"""
87        self.servo.set('pwr_button', 'press' if state == 'on' else 'release')
88
89
90    def cr50_ecrst(self, state):
91        """Set ecrst on cr50"""
92        self.cr50.send_command('ecrst ' + state)
93
94
95    def wake_ec(self, wake_method):
96        """Pulse the wake method to wake the EC
97
98        Args:
99            wake_method: a function that takes in 'on' or 'off' to control the
100                         wake source.
101        """
102        wake_method('on')
103        time.sleep(self.SHORT_PULSE)
104        wake_method('off')
105
106
107    def ec_hibernate(self):
108        """Put the EC in hibernate"""
109        self.ec.send_command('hibernate')
110        if self.ec_is_up():
111            raise error.TestError('Could not put the EC into hibernate')
112
113
114    def guarantee_ec_is_up(self):
115        """Make sure ec isn't held in reset. Use the power button to wake it
116
117        The power button wakes the EC on all systems. Use that to wake the EC
118        and make sure all versions of ecrst are released.
119        """
120        self.cold_reset('off')
121        self.cr50_ecrst('off')
122        time.sleep(self.RELEASE_RESET_DELAY)
123        self.wake_ec(self.power_button)
124        if not self.ec_is_up():
125            raise error.TestError('Could not recover EC with power button')
126
127
128    def can_wake_ec(self, wake_method):
129        """Put the EC in hibernate and verify it can wake up with wake_method
130
131        Args:
132            wake_method: a function that takes in 'on' or 'off' to control the
133                         wake source.
134        Returns:
135            True if wake_method can be used to wake the EC from hibernate
136        """
137        self.ec_hibernate()
138        self.wake_ec(self.cold_reset)
139        wake_successful = self.ec_is_up()
140        self.guarantee_ec_is_up()
141        return wake_successful
142
143
144    def check_basic_ecrst(self):
145        """Verify cr50 can hold the EC in reset"""
146        self.cr50_ecrst('on')
147        if self.ec_is_up():
148            raise error.TestFail('Could not use cr50 ecrst to hold the EC in '
149                                 'reset')
150        # Verify cr50 can release the EC from reset
151        self.cr50_ecrst('off')
152        if not self.ec_is_up():
153            raise error.TestFail('Could not release the EC from reset')
154        self.guarantee_ec_is_up()
155
156    def check_ec_hibernate(self):
157        """Verify EC hibernate"""
158        try:
159            self.ec_hibernate()
160        except error.TestError as e:
161            if 'Could not put the EC into hibernate' in str(e):
162                raise error.TestNAError("EC hibernate doesn't work.")
163        finally:
164            self.guarantee_ec_is_up()
165
166
167    def run_once(self):
168        """Make sure 'cr50 ecrst' works as intended."""
169        failed_wake = []
170
171        # Open cr50 so the test has access to ecrst
172        self.fast_ccd_open(True)
173
174        self.check_basic_ecrst()
175
176        if not self.can_wake_ec(self.cr50_ecrst):
177            failed_wake.append('cr50 ecrst')
178
179        if not self.can_wake_ec(self.cold_reset):
180            failed_wake.append('servo cold_reset')
181
182        if failed_wake:
183            raise error.TestFail('Failed to wake EC with %s' %
184                                 ' and '.join(failed_wake))
185