普通文本  |  118行  |  4.1 KB

# Copyright 2018 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


class firmware_Cr50OpenWhileAPOff(FirmwareTest):
    """Verify the console can be opened while the AP is off.

    Make sure it runs ok when cr50 saw the AP turn off and when it resets while
    the AP is off.

    This test would work the same with any cr50 ccd command that uses vendor
    commands. 'ccd open' is just one.
    """
    version = 1

    SLEEP_DELAY = 20

    def initialize(self, host, cmdline_args):
        """Initialize the test"""
        super(firmware_Cr50OpenWhileAPOff, self).initialize(host, cmdline_args)

        if not hasattr(self, 'cr50'):
            raise error.TestNAError('Test can only be run on devices with '
                                    'access to the Cr50 console')


        # TODO(mruthven): replace with dependency on servo v4 with servo micro
        # and type c cable.
        if 'servo_v4_with_servo_micro' != self.servo.get_servo_version():
            raise error.TestNAError('Run using servo v4 with servo micro')

        # Verify DTS mode while the EC is off. DTS mode needs to work to control
        # deep sleep. Some devices' rdd doesn't work when the EC is off. Make
        # sure it works on this device before running the test.
        self.servo.set('cold_reset', 'on')
        dts_mode_works = self.cr50.servo_v4_supports_dts_mode()
        self.servo.set('cold_reset', 'off')
        if not dts_mode_works:
            raise error.TestNAError('Plug in servo v4 type c cable into ccd '
                    'port')

        if not self.cr50.has_command('ccdstate'):
            raise error.TestNAError('Cannot test on Cr50 with old CCD version')


    def restore_dut(self):
        """Turn on the device and reset cr50

        Do a deep sleep reset to fix the cr50 console. Then turn the device on.

        Raises:
            TestFail if the cr50 console doesn't work
        """
        logging.info('attempt cr50 console recovery')

        # Make sure the device is off
        self.servo.set('cold_reset', 'on')

        # Do a deep sleep reset to restore the cr50 console.
        self.deep_sleep_reset()

        # Deassert EC reset to turn the device back on
        self.servo.set('cold_reset', 'off')

        # Verify the cr50 console responds to commands.
        try:
            logging.info(self.cr50.send_command_get_output('ccdstate', ['.*>']))
        except error.TestFail, e:
            if 'Timeout waiting for response' in e.message:
                raise error.TestFail('Could not restore Cr50 console')
            raise


    def deep_sleep_reset(self):
        """Toggle ccd to get to do a deep sleep reset"""
        # Make sure cr50 has been up long enough to enter deep sleep
        time.sleep(self.SLEEP_DELAY)
        # We cant use cr50 ccd_disable/enable, because those uses the cr50
        # console. Call servo_v4_dts_mode directly.
        self.servo.set_nocheck('servo_v4_dts_mode', 'off')
        time.sleep(self.SLEEP_DELAY)
        self.servo.set_nocheck('servo_v4_dts_mode', 'on')


    def try_ccd_open(self, cr50_reset):
        """Try 'ccd open' and make sure the console doesn't hang"""
        self.cr50.set_ccd_level('lock')

        try:
            # Hold the EC in reset so the AP wont turn on when we press the
            # power button
            self.servo.set('cold_reset', 'on')

            # Do a deep sleep reset before running ccd open
            if cr50_reset:
                self.cr50.clear_deep_sleep_count()
                self.deep_sleep_reset()
                if self.cr50.get_deep_sleep_count() == 0:
                    raise error.TestFail('Did not detect a cr50 reset')

            # Verify ccd open
            self.cr50.set_ccd_level('open')
        finally:
            self.restore_dut()


    def run_once(self):
        """Turn off the AP and try ccd open."""
        self.try_ccd_open(False)
        self.try_ccd_open(True)