blob: 9eb6adca42ad204bae206a69fb6c5699ac4875be [file] [log] [blame]
/* Copyright (c) 2013 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.
*
* TPSChrome powerinfo commands.
*/
#include "battery.h"
#include "console.h"
#include "extpower.h"
#include "host_command.h"
#include "pmu_tpschrome.h"
#include "util.h"
/*
* All these constants are specific to the Pit board. If we reuse this command
* on other boards, we'll need to move the table to board.c.
*/
static const struct {
const char *name;
int voltage_mv;
int current_range_ma;
} pmu_fet[] = {
{"backlight", 11400, 1100},
{"video" , 5000, 220},
{"wwan" , 3300, 3300},
{"sdcard" , 3300, 1100},
{"camera" , 3300, 1100},
{"lcd" , 3300, 1100},
{"video_add", 5000, 1100},
}, pmu_dcdc[] = {
{"p5000", 5050, 5000},
{"p3300", 3333, 5000},
{"p1350", 1350, 5000},
};
/* These constants may be Pit-specific as well. */
static const int pmu_voltage_range_mv = 17000;
static const int pmu_ac_sense_range_mv = 33;
static const int pmu_bat_sense_range_mv = 40;
static const int pmu_adc_resolution = 1024;
static const int pmu_sense_resistor_bat = CONFIG_CHARGER_SENSE_RESISTOR;
static const int pmu_sense_resistor_ac = CONFIG_CHARGER_SENSE_RESISTOR_AC;
static inline int calc_voltage(int adc_value, int range_mv)
{
return adc_value * range_mv / pmu_adc_resolution;
}
static inline int calc_current(int adc_value, int range_ma)
{
return adc_value * range_ma / pmu_adc_resolution;
}
static inline int calc_current_sr(int adc_value, int sense_resistor_mohm,
int range_mv)
{
return adc_value * range_mv * 1000 / sense_resistor_mohm /
pmu_adc_resolution;
}
static int command_powerinfo(int argc, char **argv)
{
int voltage, current;
int index;
ccputs("[pmu powerinfo]\n");
/* DC to DC converter */
for (index = 0; index < ARRAY_SIZE(pmu_dcdc); index++) {
current = calc_current(
pmu_adc_read(ADC_IDCDC1 + index, ADC_FLAG_KEEP_ON),
pmu_dcdc[index].current_range_ma);
voltage = pmu_dcdc[index].voltage_mv;
ccprintf("DCDC%d:%6d mV,%4d mA,%4d mW %s\n",
index + 1, voltage, current, voltage * current / 1000,
pmu_dcdc[index].name);
}
/* FET */
for (index = 0; index < ARRAY_SIZE(pmu_fet); index++) {
current = calc_current(
pmu_adc_read(ADC_IFET1 + index, ADC_FLAG_KEEP_ON),
pmu_fet[index].current_range_ma);
voltage = pmu_fet[index].voltage_mv;
ccprintf("FET%d :%6d mV,%4d mA,%4d mW %s\n",
index + 1, voltage, current, voltage * current / 1000,
pmu_fet[index].name);
}
/* Battery charging */
voltage = calc_voltage(
pmu_adc_read(ADC_VBAT, ADC_FLAG_KEEP_ON),
pmu_voltage_range_mv);
current = calc_current_sr(
pmu_adc_read(ADC_IBAT, ADC_FLAG_KEEP_ON),
pmu_sense_resistor_bat, pmu_bat_sense_range_mv);
ccprintf("Chg :%6d mV,%4d mA,%4d mW\n", voltage, current,
voltage * current / 1000);
/* AC input */
voltage = calc_voltage(
pmu_adc_read(ADC_VAC, ADC_FLAG_KEEP_ON),
pmu_voltage_range_mv);
current = calc_current_sr(
pmu_adc_read(ADC_IAC, 0),
pmu_sense_resistor_ac, pmu_ac_sense_range_mv);
ccprintf("AC :%6d mV,%4d mA,%4d mW\n", voltage, current,
voltage * current / 1000);
return EC_SUCCESS;
}
DECLARE_CONSOLE_COMMAND(powerinfo, command_powerinfo,
NULL,
"Show PMU power info",
NULL);
/**
* Host command to get power info from PMU
*
* This reuses the same EC_CMD_POWER_INFO host command as Spring, but doesn't
* provide the full set of information because Pit doesn't take power over USB.
*/
static int power_command_info(struct host_cmd_handler_args *args)
{
struct ec_response_power_info *r = args->response;
r->voltage_ac = calc_voltage(
pmu_adc_read(ADC_VAC, ADC_FLAG_KEEP_ON),
pmu_voltage_range_mv);
if (extpower_is_present()) {
/* Power source = AC */
r->voltage_system = r->voltage_ac;
r->current_system = calc_current_sr(
pmu_adc_read(ADC_IAC, ADC_FLAG_KEEP_ON),
pmu_sense_resistor_ac, pmu_ac_sense_range_mv);
} else {
/* Power source == battery */
struct batt_params batt;
r->voltage_system = calc_voltage(
pmu_adc_read(ADC_VBAT, ADC_FLAG_KEEP_ON),
pmu_voltage_range_mv);
/*
* PMU reads charging current. When battery is discharging, ADC
* returns 0. Use battery gas gauge output instead.
*/
battery_get_params(&batt);
r->current_system = -batt.current;
}
/* Ignore USB powerinfo fields. */
r->usb_dev_type = 0;
r->usb_current_limit = 0;
args->response_size = sizeof(*r);
return EC_RES_SUCCESS;
}
DECLARE_HOST_COMMAND(EC_CMD_POWER_INFO, power_command_info, EC_VER_MASK(0));