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