blob: 8a9250c97c9c38b2541a4969b4e2aa14108d0c75 [file] [log] [blame]
# Copyright 2016 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.
"""Driver for servo micro specific controls through ec3po.
Provides the following console controlled function subtypes:
usbpd_console
"""
import re
import logging
import time
import ec3po_servo
import pty_driver
import servo
# Controls to set in batch operations.
# [off, samus, glados]
usbpd_uart_config = {
'UART3_RX_JTAG_BUFFER_TO_SERVO_TDO': ('IN', 'ALT', 'ALT'),
'UART3_TX_SERVO_JTAG_TCK': ('IN', 'ALT', 'ALT'),
'SPI1_MUX_SEL': ('1', '0', '1'),
'SPI1_BUF_EN_L': ('1', '0', '1'),
'SPI1_VREF_18': ('0', '1', '0'),
'SPI1_VREF_33': ('0', '0', '0'),
'JTAG_BUFIN_EN_L': ('1', '1', '0'),
'SERVO_JTAG_TDO_BUFFER_EN': ('0', '0', '1'),
'SERVO_JTAG_TDO_SEL': ('0', '0', '1'),
}
# Time in seconds to wait for console readiness after a UART routing switch.
# This value was determined experimentally.
CONSOLE_READINESS_DELAY = 0.5
class ec3poServoMicroError(Exception):
"""Exception class for ec."""
def _GetIteChipidReStr(command):
"""Get a regexp for matching get_ite_chipid Servo console command output.
Args:
command: str - The actual console command that will be run. This should
either be 'get_ite_chipid' itself or another command with identical
output.
Returns:
str - A regexp that will match either the expected output, or the usage
output, because the latter is typically printed after any error message.
Match group 1 will contain the output either way. If it starts with
'Usage:' then an error occurred.
This returns str instead of re.compile() because that is what the
pty_driver.ptyDriver._issue_cmd_get_results() interface accepts.
"""
return (
# Match the beginning of a line.
r'[\r\n\f]('
# Match the expected output.
r'ITE EC info:[^\r\n\f]*'
# Alternatively, match the usage output, because it is typically printed
# after any error message. This avoids waiting for the Servod pexpect
# timeout after typical errors.
r'|Usage: %s(?:[ \t\v]+[^\r\n\f]*)?'
# Match the end of a line.
r')[\r\n\f]' % (re.escape(command),))
class ec3poServoMicro(ec3po_servo.ec3poServo):
"""Object to access drv=ec3po_servo_micro controls.
Note, instances of this object get dispatched via base class,
HwDriver's get/set method. That method ultimately calls:
"_[GS]et_%s" % params['subtype'] below.
For example, a control to read kbd_en would be dispatched to
call _Get_kbd_en.
"""
def __init__(self, interface, params):
"""Constructor.
Args:
interface: ec3po interface object to handle low-level communication to
control
params: dictionary of params needed
Raises:
ec3poServoMicroError: on init failure
"""
ec3po_servo.ec3poServo.__init__(
self, interface, params, board='servo_micro')
self._logger.debug('')
def batch_set(self, batch, index):
"""Set a batch of values on servo micro.
Args:
batch: dict of GPIO names, and on/off value
index: index of batch preset
"""
if index not in [0, 1, 2]:
raise ec3poServoMicroError('Index (%s) must be 0, 1, or 2' % index)
for name, values in batch.items():
cmd = 'gpioset %s %s\r' % (name, values[index])
self._issue_cmd(cmd)
def _Set_usbpd_console(self, value):
"""Set or unset PD console routing
Args:
value: An integer value, 0: none, 1:samus, 2:glados
"""
self.batch_set(usbpd_uart_config, value)
# Add a short delay, so the console will be accessible immediately after the
# control is set.
time.sleep(CONSOLE_READINESS_DELAY)
def _Get_usbpd_console(self):
"""Set or unset PD console routing
Args:
value: An integer value, 0: none, 1:samus, 2:glados
"""
return 0
def _Get_enable_ite_dfu(self):
"""Enable ITE EC direct firmware update over I2C mode.
Enable direct firmware update (DFU) over I2C mode on ITE IT8320 EC chip by
sending special non-I2C waveforms over the I2C bus wires.
"""
results = self._issue_safe_cmd_get_results('enable_ite_dfu', [
_GetIteChipidReStr('enable_ite_dfu')])
if results[0] is None or results[0][1].startswith('Usage:'):
raise ec3poServoMicroError(
'Failed to enable DFU mode. results=%r' % (results,))
return results[0][1].strip()
def _Get_get_ite_chipid(self):
"""Verify that ITE EC chip is in DFU mode by querying for its chip ID.
Verify that ITE IT8320 EC chip direct firmware update (DFU) mode is enabled
by querying the EC over I2C for its CHIPID1 and CHIPID2 registers. It will
only respond over I2C when in DFU mode.
"""
results = self._issue_safe_cmd_get_results('get_ite_chipid', [
_GetIteChipidReStr('get_ite_chipid')])
if results[0] is None or results[0][1].startswith('Usage:'):
raise ec3poServoMicroError(
'Failed to query ITE EC chip ID, or failed to parse the output. Has '
'enable_ite_dfu been called? results=%r' % (results,))
return results[0][1].strip()