blob: 7fb685b6fe4711f553a1c43e2d9efa367753d88e [file] [log] [blame]
# 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()