| # Copyright 2021 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.firmware_test import FirmwareTest |
| from autotest_lib.server.cros.power import servo_charger |
| from autotest_lib.server.cros.servo import servo |
| |
| |
| class firmware_ECWakeFromULP(FirmwareTest): |
| """ |
| Servo based EC wake from ULP test. |
| """ |
| version = 1 |
| |
| # Retries allowed for reaching designed states. |
| POWER_STATE_RETRY_COUNT = 10 |
| |
| def initialize(self, host, cmdline_args): |
| super(firmware_ECWakeFromULP, self).initialize(host, cmdline_args) |
| self.setup_pdtester(min_batt_level=10) |
| # Only run in normal mode |
| self.switcher.setup_mode('normal') |
| self.charge_manager = servo_charger.ServoV4ChargeManager( |
| host, host.servo) |
| # stop charging to test hibernate |
| self.charge_manager.stop_charging() |
| |
| def cleanup(self): |
| # The DUT might be still hibernated. Force the reboot. |
| if not self.is_ec_console_responsive(): |
| logging.info('System is still hibernated; reboot.') |
| self.switcher.simple_reboot('cold', sync_before_boot=False) |
| |
| if not self.wait_power_state(self.POWER_STATE_S0, |
| self.POWER_STATE_RETRY_COUNT): |
| logging.info('System is S5/G3; press pwrbtn to boot to S0.') |
| self.servo.power_short_press() |
| |
| # Restore the lid_open switch in case the test failed in the middle. |
| if self.check_ec_capability(['lid']): |
| self.servo.set('lid_open', 'yes') |
| |
| self.charge_manager.start_charging() |
| |
| super(firmware_ECWakeFromULP, self).cleanup() |
| |
| def hibernate_and_wake(self, host, wake_func, wake_state): |
| """Shutdown to G3/S5, hibernate EC, and then wake by power button.""" |
| self.run_shutdown_cmd() |
| if not self.wait_power_state(self.POWER_STATE_G3, |
| self.POWER_STATE_RETRY_COUNT): |
| raise error.TestFail('Platform failed to reach G3 state.') |
| |
| self.ec.send_command('hibernate') |
| time.sleep(self.WAKE_DELAY) |
| |
| if self.is_ec_console_responsive(): |
| raise error.TestFail('The DUT is not in hibernate mode.') |
| else: |
| logging.info('Hibernated. EC console in not responsive. ') |
| |
| # wake system |
| wake_func() |
| if not self.wait_power_state(wake_state, self.POWER_STATE_RETRY_COUNT): |
| raise error.TestFail('Platform failed to reach %s state.' % |
| wake_state) |
| if wake_state == self.POWER_STATE_S0: |
| self.switcher.wait_for_client() |
| |
| def is_ec_console_responsive(self): |
| """Test if EC console is responsive.""" |
| try: |
| self.ec.send_command_get_output('help', ['.*>']) |
| return True |
| except servo.UnresponsiveConsoleError: |
| return False |
| |
| def wake_by_lid_switch(self): |
| """Wake up the device by lid switch.""" |
| self.servo.set('lid_open', 'no') |
| time.sleep(self.LID_DELAY) |
| self.servo.set('lid_open', 'yes') |
| |
| def run_once(self, host): |
| """Runs a single iteration of the test.""" |
| if not self.check_ec_capability(): |
| raise error.TestNAError( |
| "Nothing needs to be tested on this device") |
| |
| if self.servo.main_device_is_ccd(): |
| raise error.TestNAError( |
| 'With CCD, we can\'t wake up the DUT from ' |
| 'hibernate by power button. Skip hibernate ' |
| 'test.') |
| elif not self.faft_config.hibernate: |
| raise error.TestNAError('The device does not support hibernate. ' |
| 'Skip hibernate test.') |
| elif not self._client.has_battery(): |
| raise error.TestNAError( |
| 'The device claims to have hibernate support, but does not ' |
| 'have a battery. It probably does not actually have ' |
| 'hibernate support, edit the device.json file in ' |
| 'fw-testing-configs. Skip hibernate test.') |
| |
| # Test hibernate and wake by power button |
| wake_src = 'power button' |
| logging.info('EC hibernate and wake by power button.') |
| self.hibernate_and_wake(host, self.servo.power_short_press, |
| self.POWER_STATE_S0) |
| |
| # Test hibernate and wake by lid switch |
| wake_src = 'lid switch' |
| if not self.check_ec_capability(['lid']): |
| logging.info( |
| 'The device has no lid. ' |
| 'Skip testing hibernate/wake by %s.', wake_src) |
| elif 'c2d2' in self.servo.get_servo_type(): |
| logging.info('The servo is c2d2. We can\'t wake up the DUT from ' |
| 'hibernate by lid open. Skip hibernate test') |
| else: |
| logging.info('Hibernate and wake by %s.', wake_src) |
| self.hibernate_and_wake(host, self.wake_by_lid_switch, |
| self.POWER_STATE_S0) |
| |
| # Test hibernate and wake by AC on |
| wake_src = 'AC on' |
| self.charge_manager.stop_charging() |
| logging.info('Hibernate and wake by %s.', wake_src) |
| if self.faft_config.ac_on_can_wake_ap_from_ulp: |
| logging.info('AC on event can wake AP from ULP.') |
| wake_state = self.POWER_STATE_S0 |
| else: |
| logging.info('AC on event cannot wake AP from ULP.') |
| wake_state = self.POWER_STATE_G3 |
| self.hibernate_and_wake(host, self.charge_manager.start_charging, |
| wake_state) |
| |
| if not self.faft_config.ac_on_can_wake_ap_from_ulp: |
| # Put AP back to S0 |
| self.servo.power_short_press() |