blob: f4a8459f1b6b41c7c67f3a2874418303d581755d [file] [log] [blame]
# Copyright 2017 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 v4 specific controls through ec3po.
Provides the following console controlled function subtypes:
servo_v4_ccd_mode
"""
import logging
import time
import ec3po_servo
import pty_driver
import servo
class ec3poServoV4Error(Exception):
"""Exception class."""
class ec3poServoV4(ec3po_servo.ec3poServo):
"""Object to access drv=ec3po_servo_v4 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.
"""
SWAP_DELAY = 1
DUT_PORT = 1
def __init__(self, interface, params):
"""Constructor.
Args:
interface: ec3po interface object to handle low-level communication to
control
params: dictionary of params needed
Raises:
ec3poServoV4Error: on init failure
"""
ec3po_servo.ec3poServo.__init__(self, interface, params, board='servo_v4')
self._logger.debug('')
def batch_set(self, batch, index):
"""Set a batch of values on console gpio.
Args:
batch: dict of GPIO names, and on/off value
index: index of batch preset
"""
if index not in range(len(batch.values()[0])):
raise ec3poServoV4Error('Index %s out of range' % index)
cmds = []
for name, values in batch.items():
cmds.append('gpioset %s %s\r' % (name, values[index]))
self._issue_cmd(cmds)
def servo_adc(self):
"""Get adc state info from servo V4.
returns:
(chg_cc1, chg_cc2, dut_cc1, dut_cc2, sbu1, sbu2) tuple of float in mv.
> adc
CHG_CC1_PD = 1648
CHG_CC2_PD = 34
DUT_CC1_PD = 1694
DUT_CC2_PD = 991
SBU1_DET = 2731
SBU2_DET = 92
SUB_C_REF = 565
"""
rx = ['(CHG_CC1_PD) = (\d+)',
'(CHG_CC2_PD) = (\d+)',
'(DUT_CC1_PD) = (\d+)',
'(DUT_CC2_PD) = (\d+)',
'(SBU1_DET) = (\d+)',
'(SBU2_DET) = (\d+)']
res = self._issue_safe_cmd_get_results('adc', rx)
if len(res) != 6:
raise ec3poServoV4Error("Can't receive cc info: [%s]" % results)
vals = {entry[1] : entry[2] for entry in res}
return vals
def _Get_adc(self):
"""Get adc value.
Args:
name: adc name.
"""
if 'adc_name' in self._params:
name = self._params['adc_name']
else:
raise ec3poServoV4Error("'adc_name' not in _params")
vals = self.servo_adc()
if name not in vals:
raise ec3poServoV4Error(
"adc_name '%s' not in adc set %s" % (name, vals.keys()))
return vals[name]
def servo_cc_modes(self):
"""Get cc line state info from servo V4.
returns:
(dts, charging, charge_enabled) tuple of on/off.
> cc
dts mode: on
chg mode: off
chg allowed: off
"""
rx = ['dts mode:\s*(off|on)', 'chg mode:\s*(off|on)',
'chg allowed:\s*(off|on)']
res = self._issue_safe_cmd_get_results('cc', rx)
if len(res) != 3:
raise ec3poServoV4Error("Can't receive cc info: [%s]" % results)
dts = res[0][1]
chg = res[1][1]
mode = res[2][1]
return (dts, chg, mode)
def lookup_cc_setting(self, mode, dts):
"""Composite settings into cc commandline arg.
Args:
mode: 'on'/'off' setting for charge enable
dts: 'on'/'off' setting for dts enable
Returns:
string: 'src', 'snk', 'srcdts', 'snkdts' as appropriate.
"""
newdts = 'dts' if (dts == 'on') else ''
newmode = 'src' if (mode == 'on') else 'snk'
newcc = newmode + newdts
return newcc
def _Get_servo_v4_dts_mode(self):
"""Getter of servo_v4_dts_mode.
Returns:
"off": DTS mode is disabled.
"on": DTS mode is enabled.
"""
dts, chg, mode = self.servo_cc_modes()
return dts
def _Set_servo_v4_dts_mode(self, value):
"""Setter of servo_v4_dts_mode.
Args:
value: "off", "on"
"""
if value == 'off' or value == 'on':
dts, chg, mode = self.servo_cc_modes()
newcc = self.lookup_cc_setting(mode, value)
self._issue_cmd('cc %s' % newcc)
else:
raise ValueError("Invalid dts_mode setting: '%s'. Try one of "
"'on' or 'off'." % value)
def _get_pd_info(self, port):
"""Get the current PD state
Args:
port: Type C PD port 0/1
Returns:
"src|snk" for role and state value
"""
pd_cmd = 'pd %s state' % port
# Two FW versions for this command, get full line.
m = self._issue_safe_cmd_get_results(pd_cmd,
['State:\s+([\w]+)_([\w]+)'])[0]
if m is None:
raise ec3poServoV4Error('Cannot retrieve pd state.')
info = {}
info['role'] = m[1].lower()
info['state'] = m[2].lower()
return info
def _Get_servo_v4_power_role(self):
"""Setter of servo_v4_role.
@returns: Current power role
"""
dts, chg, mode = self.servo_cc_modes()
return 'src' if (chg == 'on') else 'snk'
def _Set_servo_v4_power_role(self, role):
"""Setter of servo_v4_power_role.
Args:
role: "src", "snk"
"""
if role == 'src' or role == 'snk':
dts, chg, mode = self.servo_cc_modes()
newrole = 'on' if role == 'src' else 'off'
newcc = self.lookup_cc_setting(newrole, dts)
self._issue_cmd('cc %s' % newcc)
else:
raise ValueError("Invalid power role setting: '%s'. Try one of "
"'src' or 'snk'." % value)