# Copyright 2019 The Chromium OS Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. import logging import time from autotest_lib.client.common_lib import error from autotest_lib.server.cros.faft.cr50_test import Cr50Test class firmware_Cr50DeferredECReset(Cr50Test): """Verify EC_RST_L stays asserted only if all conditions below are True. (1) System got 'Power-On reset'. (2) RDD cable is connected. (3) The power button is held. After this, EC_RST_L should be deasserted as soon as the power button gets released. """ version = 1 def initialize(self, host, cmdline_args, full_args): """Initialize the test and check if cr50 is exists, DTS is controllable, and power delivery mode and power button is adjustable. """ super(firmware_Cr50DeferredECReset, self).initialize(host, cmdline_args, full_args) if not hasattr(self, 'cr50'): raise error.TestNAError('Test can only be run on devices with ' 'access to the Cr50 console') if not self.cr50.servo_v4_supports_dts_mode(): raise error.TestNAError('Need working servo v4 DTS control') self.fast_open(enable_testlab=True) if not self.cr50.testlab_is_on(): raise error.TestNAError('Cr50 testlab mode needs to be enabled') # Test the external power delivery self.servo.set('servo_v4_role', 'snk') time.sleep(3) rv = self.ec.send_command_get_output('chgstate',['.*>'])[0].strip() logging.info(rv) if not 'ac = 0' in rv: raise error.TestFail('Failed in setting servo_v4_role sink') # Test stopping the external power delivery self.servo.set('servo_v4_role', 'src') time.sleep(3) rv = self.ec.send_command_get_output('chgstate',['.*>'])[0].strip() logging.info(rv) if not 'ac = 1' in rv: raise error.TestFail('Failed in setting servo_v4_role source') # Test if the power button is adjustable. self.servo.set('pwr_button', 'press') self.servo.set('pwr_button', 'release') def check_ecrst_asserted(self, expect_assert): """Ask CR50 whether EC_RST_L is asserted or deasserted. Args: expect_assert: True if it is expected asserted. False otherwise. """ # If the console is responsive, then the EC is awake. rv = self.cr50.send_command_get_output('ecrst', ['EC_RST_L is \w{0,2}asserted.*>'])[0].strip() logging.info(rv) expecting_txt = ' asserted' if expect_assert else ' deasserted' if not expecting_txt in rv: raise error.TestFail(rv) def ping_ec(self, expect_response): """Check if EC is running and responding. Args: expect_response: True if EC should respond False otherwise. """ try: rv = self.ec.send_command_get_output('time', ['time.*>'])[0].strip() except error.TestFail as e: logging.info(e) if 'Timeout waiting for response' in str(e): if not expect_response: return raise e else: if not expect_response: raise error.TestFail(rv) def test_deferred_ec_reset(self, power_button_hold, rdd_enable, expect_ec_response): """Do a power-on reset, and check if EC responds. Args: power_button_hold: True if it should be pressed on a system reset. False otherwise. rdd_enable: True if RDD should be detected on a system reset. False otherwise. expect_ec_response: True if EC should run and response on a system reset. False otherwise. """ logging.info('Test deferred_ec_reset starts.') logging.info('Power button held: %s', power_button_hold) logging.info('RDD connection : %s', rdd_enable) # Stop power delivery to DUT self.servo.set('servo_v4_role', 'snk') time.sleep(3) # Battery Cutoff self.ec.send_command('cutoff') time.sleep(3) # EC should not respond self.ping_ec(False) # press (or release) the power button power_button_setval = 'press' if power_button_hold else 'release' # call set_nocheck, since power button shall be recognized as pressed # at this point. self.servo.set_nocheck('pwr_button', power_button_setval) # enable RDD Connection (or disable) self.servo.set_nocheck('servo_v4_dts_mode', 'on' if rdd_enable else 'off') time.sleep(self.cr50.SHORT_WAIT) # Enable power delivery to DUT self.servo.set('servo_v4_role', 'src') # Wait for a while wait_sec = 30 logging.info('waiting for %d seconds', wait_sec) time.sleep(wait_sec) # Check if EC_RST_L is asserted (or deasserted) and EC is on (or off). self.check_ecrst_asserted(not expect_ec_response) self.ping_ec(expect_ec_response) # Release power button self.servo.set('pwr_button', 'release') # Check if EC_RST_L is deasserted and EC is on. self.check_ecrst_asserted(False) self.ping_ec(True) # Recover CCD if self.servo.get('servo_v4_dts_mode') == 'off': self.cr50.ccd_enable() def run_once(self): """Test deferred EC reset feature. """ # Release power button and disable RDD on power-on reset. # EC should be running. self.test_deferred_ec_reset(power_button_hold=False, rdd_enable=False, expect_ec_response=True) # Release power button but enable RDD on power-on reset. # EC should be running. self.test_deferred_ec_reset(power_button_hold=False, rdd_enable=True, expect_ec_response=True) # Hold power button but disable RDD on power-on reset. # EC should be running. self.test_deferred_ec_reset(power_button_hold=True, rdd_enable=False, expect_ec_response=True) # Hold power button and enable RDD on power-on reset. # EC should not be running. self.test_deferred_ec_reset(power_button_hold=True, rdd_enable=True, expect_ec_response=False)