/* 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));