blob: 05386e075458115c1254e8632ca1e3f93bc98bb3 [file] [log] [blame]
# Copyright (c) 2014 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 time
import cros_ec_power
class crosEcSoftrecPower(cros_ec_power.CrosECPower):
"""Driver for power_state that uses the EC to trigger recovery.
A number of boards (generally, the ARM based boards and some x86
based board) require using the EC to trigger recovery mode.
"""
# Recovery types.
_REC_TYPE_REC_ON = 'rec_on'
_REC_TYPE_REC_OFF = 'rec_off'
_REC_TYPE_REC_OFF_CLEARB = 'rec_off_clearb'
_REC_TYPE_FASTBOOT = 'fastboot'
# Corresponding hostevent commands entered on the EC.
_HOSTEVENT_CMD_REC_ON = 'hostevent set 0x4000'
_HOSTEVENT_CMD_REC_OFF = 'hostevent clear 0x4000'
_HOSTEVENT_CMD_REC_OFF_CLEARB = 'hostevent clearb 0x4000'
_HOSTEVENT_CMD_FASTBOOT = 'hostevent set 0x1000000'
_REC_TYPE_HOSTEVENT_CMD_DICT = {
_REC_TYPE_REC_ON : _HOSTEVENT_CMD_REC_ON,
_REC_TYPE_REC_OFF : _HOSTEVENT_CMD_REC_OFF,
_REC_TYPE_REC_OFF_CLEARB : _HOSTEVENT_CMD_REC_OFF_CLEARB,
_REC_TYPE_FASTBOOT : _HOSTEVENT_CMD_FASTBOOT
}
# Time in seconds to allow the EC to pick up the recovery
# host event.
_RECOVERY_DETECTION_DELAY = 1
def __init__(self, interface, params):
"""Constructor
Args:
interface: driver interface object
params: dictionary of params
"""
super(crosEcSoftrecPower, self).__init__(interface, params)
self._boot_to_rec_screen_delay = float(
self._params.get('boot_to_rec_screen_delay', 5.0))
def _power_on_ap(self):
"""Power on the AP after initializing recovery state."""
self._interface.power_short_press()
def _power_on_bytype(self, rec_mode, rec_type=_REC_TYPE_REC_ON):
self._interface.set('ec_uart_cmd', '\r')
if rec_mode == self.REC_ON:
try:
# Before proceeding, we should really check that the EC has reset from
# our command. Pexpect is minimally greedy so we won't be able to match
# the exact reset cause string. But, this should be good enough.
self._interface.set('ec_uart_regexp', '["Reset cause:"]')
self._interface.set('ec_uart_cmd', 'reboot ap-off')
finally:
self._interface.set('ec_uart_regexp', 'None')
time.sleep(self._reset_recovery_time)
else:
# Need to clear the flag in secondary (B) copy of the host events if
# we're in non-recovery mode.
cmd = self._REC_TYPE_HOSTEVENT_CMD_DICT[self._REC_TYPE_REC_OFF_CLEARB]
try:
self._interface.set('ec_uart_regexp', '["Events:"]')
self._interface.set('ec_uart_cmd', cmd)
finally:
self._interface.set('ec_uart_regexp', 'None')
# Tell the EC to tell the CPU we're in recovery mode or non-recovery mode.
cmd = self._REC_TYPE_HOSTEVENT_CMD_DICT[rec_type]
try:
self._interface.set('ec_uart_regexp', '["Events:"]')
self._interface.set('ec_uart_cmd', cmd)
finally:
self._interface.set('ec_uart_regexp', 'None')
time.sleep(self._RECOVERY_DETECTION_DELAY)
self._power_on_ap()
if rec_mode == self.REC_ON:
# Allow time to reach the recovery screen before yielding control.
time.sleep(self._boot_to_rec_screen_delay)
def _power_on(self, rec_mode):
if rec_mode == self.REC_ON:
rec_type = self._REC_TYPE_REC_ON
else:
rec_type = self._REC_TYPE_REC_OFF
self._power_on_bytype(rec_mode, rec_type)
def _power_on_fastboot(self):
self._power_on_bytype(self.REC_ON, rec_type=self._REC_TYPE_FASTBOOT)