From aab9accfce10e70197729afd07451229ac8a178d Mon Sep 17 00:00:00 2001 From: Vic Yang Date: Tue, 19 Feb 2013 13:33:33 +0800 Subject: spring: Add host command to read power info Getting voltage and current can be handy when verifying hardware design. Let's add host command to do this. BUG=chrome-os-partner:17880 TEST=Manual on Spring BRANCH=none Change-Id: I4d4f6a42a9d0f917292d092e132ccd9ce3367fd6 Signed-off-by: Vic Yang Reviewed-on: https://gerrit.chromium.org/gerrit/43508 Reviewed-by: Vincent Palatin --- board/spring/board.c | 20 +++++++++++++++++++ board/spring/board.h | 6 ++++++ board/spring/usb_charging.c | 21 ++++++++++++++++---- common/pmu_tps65090.c | 47 +++++++++++++++++++++++++++++++++++++++++++++ include/ec_commands.h | 16 +++++++++++++++ include/pmu_tpschrome.h | 22 +++++++++++++++++++++ util/ectool.c | 21 ++++++++++++++++++++ 7 files changed, 149 insertions(+), 4 deletions(-) diff --git a/board/spring/board.c b/board/spring/board.c index b271fc5d43..444dc700b0 100644 --- a/board/spring/board.c +++ b/board/spring/board.c @@ -9,8 +9,10 @@ #include "common.h" #include "console.h" #include "dma.h" +#include "ec_commands.h" #include "gpio.h" #include "hooks.h" +#include "host_command.h" #include "i2c.h" #include "lp5562.h" #include "pmu_tpschrome.h" @@ -333,3 +335,21 @@ int board_battery_led(enum charging_state state) return lp5562_set_color(color); } + +/*****************************************************************************/ +/* Host commands */ + +static int power_command_info(struct host_cmd_handler_args *args) +{ + struct ec_response_power_info *r = args->response; + + r->voltage_ac = adc_read_channel(ADC_CH_USB_VBUS_SNS); + r->voltage_system = pmu_adc_read(ADC_VAC) * 17000 / 1024; + r->current_system = pmu_adc_read(ADC_IAC) * 20 * 33 / 1024; + r->usb_dev_type = board_get_usb_dev_type(); + r->usb_current_limit = board_get_usb_current_limit(); + args->response_size = sizeof(*r); + + return EC_RES_SUCCESS; +} +DECLARE_HOST_COMMAND(EC_CMD_POWER_INFO, power_command_info, EC_VER_MASK(0)); diff --git a/board/spring/board.h b/board/spring/board.h index 0e30a98a6b..5a026d9051 100644 --- a/board/spring/board.h +++ b/board/spring/board.h @@ -168,6 +168,12 @@ void board_usb_charge_update(int force_update); /* Update battery LED color */ int board_battery_led(enum charging_state state); +/* Get USB port device type */ +int board_get_usb_dev_type(void); + +/* Get USB port current limit */ +int board_get_usb_current_limit(void); + #endif /* !__ASSEMBLER__ */ #endif /* __BOARD_H */ diff --git a/board/spring/usb_charging.c b/board/spring/usb_charging.c index e1b9029bcb..b56147e61f 100644 --- a/board/spring/usb_charging.c +++ b/board/spring/usb_charging.c @@ -35,6 +35,9 @@ #define I_LIMIT_2400MA 25 #define I_LIMIT_3000MA 0 +static int current_dev_type = TSU6721_TYPE_NONE; +static int current_pwm_duty; + static enum ilim_config current_ilim_config = ILIM_CONFIG_MANUAL_OFF; static const int apple_charger_type[4] = {I_LIMIT_500MA, @@ -149,6 +152,7 @@ void board_pwm_duty_cycle(int percent) if (percent > 100) percent = 100; STM32_TIM_CCR1(3) = (percent * STM32_TIM_ARR(3)) / 100; + current_pwm_duty = percent; } void usb_charge_interrupt(enum gpio_signal signal) @@ -158,11 +162,9 @@ void usb_charge_interrupt(enum gpio_signal signal) static void usb_device_change(int dev_type) { - static int last_dev_type; - - if (last_dev_type == dev_type) + if (current_dev_type == dev_type) return; - last_dev_type = dev_type; + current_dev_type = dev_type; /* Supply VBUS if needed */ if (dev_type & POWERED_DEVICE_TYPE) @@ -228,6 +230,17 @@ void board_usb_charge_update(int force_update) usb_device_change(tsu6721_get_device_type()); } +int board_get_usb_dev_type(void) +{ + return current_dev_type; +} + +int board_get_usb_current_limit(void) +{ + /* Approximate value by PWM duty cycle */ + return 3012 - 29 * current_pwm_duty; +} + /* * Console command for debugging. * TODO(victoryang): Remove after charging control is done. diff --git a/common/pmu_tps65090.c b/common/pmu_tps65090.c index cfb6ffd582..f5f32b1d1c 100644 --- a/common/pmu_tps65090.c +++ b/common/pmu_tps65090.c @@ -85,6 +85,11 @@ #define FET_CTRL_BASE (FET1_CTRL - 1) +/* AD control register bits */ +#define AD_CTRL_ENADREF (1 << 4) +#define AD_CTRL_ADEOC (1 << 5) +#define AD_CTRL_ADSTART (1 << 6) + void __board_hard_reset(void) { CPRINTF("This board is not capable of a hard reset.\n"); @@ -401,6 +406,48 @@ int pmu_enable_fet(int fet_id, int enable, int *power_good) return EC_SUCCESS; } +int pmu_adc_read(int adc_idx) +{ + int ctrl; + int val1, val2; + int rv; + + rv = pmu_read(AD_CTRL, &ctrl); + if (rv) + return rv; + ctrl |= AD_CTRL_ENADREF; + rv = pmu_write(AD_CTRL, ctrl); + if (rv) + return rv; + msleep(20); + + ctrl = (ctrl & ~0xf) | adc_idx; + rv = pmu_write(AD_CTRL, ctrl); + if (rv) + return rv; + udelay(150); + + ctrl |= AD_CTRL_ADSTART; + rv = pmu_write(AD_CTRL, ctrl); + if (rv) + return rv; + udelay(200); + + do { + rv = pmu_read(AD_CTRL, &ctrl); + if (rv) + return rv; + } while (!(ctrl & AD_CTRL_ADEOC)); + + rv = pmu_read(AD_OUT1, &val1) | pmu_read(AD_OUT2, &val2); + if (rv) + return rv; + + rv = pmu_write(AD_CTRL, ctrl & ~AD_CTRL_ENADREF); + + return (val2 << 8) | val1; +} + void pmu_irq_handler(enum gpio_signal signal) { #ifdef CONFIG_AC_POWER_STATUS diff --git a/include/ec_commands.h b/include/ec_commands.h index 54dcbd314a..cd714cc1db 100644 --- a/include/ec_commands.h +++ b/include/ec_commands.h @@ -1241,6 +1241,22 @@ struct ec_response_ldo_get { uint8_t state; } __packed; +/*****************************************************************************/ +/* Power info. */ + +/* + * Get power info. + */ +#define EC_CMD_POWER_INFO 0x9d + +struct ec_response_power_info { + uint32_t usb_dev_type; + uint16_t voltage_ac; + uint16_t voltage_system; + uint16_t current_system; + uint16_t usb_current_limit; +} __packed; + /*****************************************************************************/ /* Temporary debug commands. TODO: remove this crosbug.com/p/13849 */ diff --git a/include/pmu_tpschrome.h b/include/pmu_tpschrome.h index 3de4c37315..39985eea30 100644 --- a/include/pmu_tpschrome.h +++ b/include/pmu_tpschrome.h @@ -74,6 +74,21 @@ enum FASTCHARGE_TIMEOUT { #define FET_LCD_PANEL 6 #define FET_TS 7 +#define ADC_VAC 0 +#define ADC_VBAT 1 +#define ADC_IAC 2 +#define ADC_IBAT 3 +#define ADC_IDCDC1 4 +#define ADC_IDCDC2 5 +#define ADC_IDCDC3 6 +#define ADC_IFET1 7 +#define ADC_IFET2 8 +#define ADC_IFET3 9 +#define ADC_IFET4 10 +#define ADC_IFET5 11 +#define ADC_IFET6 12 +#define ADC_IFET7 13 + /** * Clear tps65090 IRQ register @@ -169,6 +184,13 @@ int pmu_set_term_voltage(enum TPS_TEMPERATURE_RANGE range, */ int pmu_low_current_charging(int enable); +/** + * Read ADC channel + * + * @param adc_idx Index of ADC channel + */ +int pmu_adc_read(int adc_idx); + /** * Handles interrupts from tpschrome * diff --git a/util/ectool.c b/util/ectool.c index 253dc2ef27..3804170b8d 100644 --- a/util/ectool.c +++ b/util/ectool.c @@ -100,6 +100,8 @@ const char help_str[] = " Various lightbar control commands\n" " port80flood\n" " Rapidly write bytes to port 80\n" + " powerinfo\n" + " Prints power-related information\n" " pstoreinfo\n" " Prints information on the EC host persistent storage\n" " pstoreread \n" @@ -1501,6 +1503,24 @@ int cmd_kbpress(int argc, char *argv[]) } +int cmd_power_info(int argc, char *argv[]) +{ + struct ec_response_power_info r; + int rv; + + rv = ec_command(EC_CMD_POWER_INFO, 0, NULL, 0, &r, sizeof(r)); + if (rv < 0) + return rv; + + printf("AC Voltage: %d mV\n", r.voltage_ac); + printf("System Voltage: %d mV\n", r.voltage_system); + printf("System Current: %d mA\n", r.current_system); + printf("USB Device Type: 0x%x\n", r.usb_dev_type); + printf("USB Current Limit: %d mA\n", r.usb_current_limit); + return 0; +} + + int cmd_pstore_info(int argc, char *argv[]) { struct ec_response_pstore_info r; @@ -2748,6 +2768,7 @@ const struct command commands[] = { {"lightbar", cmd_lightbar}, {"keyconfig", cmd_keyconfig}, {"keyscan", cmd_keyscan}, + {"powerinfo", cmd_power_info}, {"pstoreinfo", cmd_pstore_info}, {"pstoreread", cmd_pstore_read}, {"pstorewrite", cmd_pstore_write}, -- cgit v1.2.1