summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRandall Spangler <rspangler@chromium.org>2013-04-09 10:03:40 -0700
committerChromeBot <chrome-bot@google.com>2013-04-10 14:24:10 -0700
commite5f4032866d703735808f934375d31072ff8603b (patch)
treeb3cfa99414ee2b45520d17fd714aedb448652657
parenta1c99c7228086a4f3d06fc299fa43ba7928c6b48 (diff)
downloadchrome-ec-e5f4032866d703735808f934375d31072ff8603b.tar.gz
Clean up USB external power module
Make internal APIs static, and remove board_ prefix for clarity. Move TSU6721 calls from charger task to extpower_usb functions for better encapsulation. No functional changes, just moving code. Yes, this will make cherry-picking back from spring to TOT less convenient, but now the code is more readable and it will make maintaining the PMU code easier as we add boards. BUG=chrome-os-partner:18343 BRANCH=none TEST=build spring Change-Id: I52b37e57fc8519859996a110b0503277c6f0bbc8 Signed-off-by: Randall Spangler <rspangler@chromium.org> Reviewed-on: https://gerrit.chromium.org/gerrit/47657
-rw-r--r--board/spring/board.c44
-rw-r--r--board/spring/board.h25
-rw-r--r--common/extpower_usb.c349
-rw-r--r--common/pmu_tps65090_charger.c25
-rw-r--r--include/extpower.h5
-rw-r--r--include/extpower_usb.h39
6 files changed, 269 insertions, 218 deletions
diff --git a/board/spring/board.c b/board/spring/board.c
index 4d80769276..4a10237cd3 100644
--- a/board/spring/board.c
+++ b/board/spring/board.c
@@ -28,8 +28,6 @@
#define INT_BOTH_FLOATING (GPIO_INPUT | GPIO_INT_BOTH)
#define INT_BOTH_PULL_UP (GPIO_INPUT | GPIO_PULL_UP | GPIO_INT_BOTH)
-void usb_charge_interrupt(enum gpio_signal signal);
-
/* GPIO signal list. Must match order from enum gpio_signal. */
const struct gpio_info gpio_list[GPIO_COUNT] = {
/* Inputs with interrupt handlers are first for efficiency */
@@ -56,8 +54,7 @@ const struct gpio_info gpio_list[GPIO_COUNT] = {
keyboard_raw_gpio_interrupt},
{"KB_IN07", GPIO_D, (1<<2), GPIO_KB_INPUT,
keyboard_raw_gpio_interrupt},
- {"USB_CHG_INT", GPIO_A, (1<<6), GPIO_INT_FALLING,
- usb_charge_interrupt},
+ {"USB_CHG_INT", GPIO_A, (1<<6), GPIO_INT_FALLING, extpower_interrupt},
/* Other inputs */
{"BCHGR_VACG", GPIO_A, (1<<0), GPIO_INT_BOTH, NULL},
/*
@@ -241,42 +238,3 @@ int pmu_board_init(void)
return failure ? EC_ERROR_UNKNOWN : EC_SUCCESS;
}
#endif /* CONFIG_BOARD_PMU_INIT */
-
-int extpower_is_present(void)
-{
- static int last_vbus;
- int vbus, vbus_good;
-
- if (!gpio_get_level(GPIO_BOOST_EN))
- return 0;
-
- /*
- * UVLO is 4.1V. We consider AC bad when its voltage drops below 4.2V
- * for two consecutive samples. This is to give PWM a chance to bring
- * voltage up.
- */
- vbus = adc_read_channel(ADC_CH_USB_VBUS_SNS);
- vbus_good = (vbus >= 4200 || last_vbus >= 4200);
- last_vbus = vbus;
-
- return vbus_good;
-}
-/*****************************************************************************/
-/* 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, ADC_FLAG_KEEP_ON)
- * 17000 / 1024;
- r->current_system = pmu_adc_read(ADC_IAC, 0)
- * 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 27a1c3cc19..4b416f40ac 100644
--- a/board/spring/board.h
+++ b/board/spring/board.h
@@ -126,31 +126,6 @@ enum gpio_signal {
GPIO_COUNT
};
-/* ILIM pin control */
-enum ilim_config {
- ILIM_CONFIG_MANUAL_OFF,
- ILIM_CONFIG_MANUAL_ON,
- ILIM_CONFIG_PWM,
-};
-
-/* Set ILIM pin control type */
-void board_ilim_config(enum ilim_config config);
-
-/* Set PWM duty cycle */
-void board_pwm_duty_cycle(int percent);
-
-/* Update USB port status */
-void board_usb_charge_update(int force_update);
-
-/* Get USB port device type */
-int board_get_usb_dev_type(void);
-
-/* Get USB port current limit */
-int board_get_usb_current_limit(void);
-
-/* Properly limit input power on EC boot */
-void board_pwm_init_limit(void);
-
#endif /* !__ASSEMBLER__ */
#endif /* __BOARD_H */
diff --git a/common/extpower_usb.c b/common/extpower_usb.c
index 625f93945d..978e54f2b0 100644
--- a/common/extpower_usb.c
+++ b/common/extpower_usb.c
@@ -10,6 +10,7 @@
#include "chipset.h"
#include "clock.h"
#include "console.h"
+#include "extpower.h"
#include "gpio.h"
#include "hooks.h"
#include "host_command.h"
@@ -30,6 +31,13 @@
#define CPUTS(outstr) cputs(CC_USBCHARGE, outstr)
#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ## args)
+/* ILIM pin control */
+enum ilim_config {
+ ILIM_CONFIG_MANUAL_OFF,
+ ILIM_CONFIG_MANUAL_ON,
+ ILIM_CONFIG_PWM,
+};
+
/* Devices that need VBUS power */
#define POWERED_5000_DEVICE_TYPE (TSU6721_TYPE_OTG)
#define POWERED_3300_DEVICE_TYPE (TSU6721_TYPE_JIG_UART_ON)
@@ -141,7 +149,7 @@ static void set_video_power(int enabled)
video_power_enabled = enabled;
}
-static void board_ilim_use_gpio(void)
+static void ilim_use_gpio(void)
{
/* Disable counter */
STM32_TIM_CR1(3) &= ~0x1;
@@ -153,7 +161,7 @@ static void board_ilim_use_gpio(void)
gpio_set_flags(GPIO_ILIM, GPIO_OUTPUT);
}
-static void board_ilim_use_pwm(void)
+static void ilim_use_pwm(void)
{
uint32_t val;
@@ -193,7 +201,10 @@ static void board_ilim_use_pwm(void)
STM32_TIM_CR1(3) |= (1 << 7) | (1 << 0);
}
-void board_ilim_config(enum ilim_config config)
+/**
+ * Set ILIM pin control type.
+ */
+static void ilim_config(enum ilim_config config)
{
if (config == current_ilim_config)
return;
@@ -202,20 +213,22 @@ void board_ilim_config(enum ilim_config config)
switch (config) {
case ILIM_CONFIG_MANUAL_OFF:
case ILIM_CONFIG_MANUAL_ON:
- board_ilim_use_gpio();
+ ilim_use_gpio();
gpio_set_level(GPIO_ILIM,
config == ILIM_CONFIG_MANUAL_ON ? 1 : 0);
break;
case ILIM_CONFIG_PWM:
- board_ilim_use_pwm();
+ ilim_use_pwm();
break;
default:
break;
}
}
-/* Returns Apple charger current limit */
-static int board_apple_charger_current(void)
+/**
+ * Return Apple charger current limit.
+ */
+static int apple_charger_current(void)
{
int vp, vn;
int type = 0;
@@ -239,7 +252,7 @@ static int board_apple_charger_current(void)
return apple_charger_type[type];
}
-static int board_probe_video(int device_type)
+static int probe_video(int device_type)
{
tsu6721_disable_interrupts();
gpio_set_level(GPIO_ID_MUX, 1);
@@ -259,10 +272,13 @@ static int board_probe_video(int device_type)
}
}
-void board_pwm_duty_cycle(int percent)
+/**
+ * Set PWM duty cycle.
+ */
+static void set_pwm_duty_cycle(int percent)
{
if (current_ilim_config != ILIM_CONFIG_PWM)
- board_ilim_config(ILIM_CONFIG_PWM);
+ ilim_config(ILIM_CONFIG_PWM);
if (percent < 0)
percent = 0;
if (percent > 100)
@@ -271,21 +287,7 @@ void board_pwm_duty_cycle(int percent)
current_pwm_duty = percent;
}
-void board_pwm_init_limit(void)
-{
- int dummy;
-
- /*
- * Shut off power input if battery is good. Otherwise, leave
- * 500mA to sustain the system.
- */
- if (battery_current(&dummy))
- board_pwm_duty_cycle(I_LIMIT_500MA);
- else
- board_ilim_config(ILIM_CONFIG_MANUAL_ON);
-}
-
-static int board_pwm_check_lower_bound(void)
+static int pwm_check_lower_bound(void)
{
if (current_limit_mode == LIMIT_AGGRESSIVE)
return (current_pwm_duty > nominal_pwm_duty -
@@ -297,7 +299,7 @@ static int board_pwm_check_lower_bound(void)
current_pwm_duty > 0);
}
-static int board_pwm_check_vbus_low(int vbus, int battery_current)
+static int pwm_check_vbus_low(int vbus, int battery_current)
{
if (battery_current >= 0)
return vbus < PWM_CTRL_VBUS_LOW && current_pwm_duty < 100;
@@ -305,61 +307,20 @@ static int board_pwm_check_vbus_low(int vbus, int battery_current)
return vbus < PWM_CTRL_VBUS_HARD_LOW && current_pwm_duty < 100;
}
-static void board_pwm_tweak(void)
-{
- int vbus, current;
-
- if (current_ilim_config != ILIM_CONFIG_PWM)
- return;
-
- vbus = adc_read_channel(ADC_CH_USB_VBUS_SNS);
- if (battery_current(&current))
- return;
-
- if (user_pwm_duty >= 0) {
- if (current_pwm_duty != user_pwm_duty)
- board_pwm_duty_cycle(user_pwm_duty);
- return;
- }
-
- /*
- * If VBUS voltage is too low:
- * - If battery is discharging, throttling more is going to draw
- * more current from the battery, so do nothing unless VBUS is
- * about to be lower than AC good threshold.
- * - Otherwise, throttle input current to raise VBUS voltage.
- * If VBUS voltage is high enough, allow more current until we hit
- * current limit target.
- */
- if (board_pwm_check_vbus_low(vbus, current)) {
- board_pwm_duty_cycle(current_pwm_duty + PWM_CTRL_STEP_UP);
- CPRINTF("[%T PWM duty up %d%%]\n", current_pwm_duty);
- } else if (vbus > PWM_CTRL_VBUS_HIGH && board_pwm_check_lower_bound()) {
- board_pwm_duty_cycle(current_pwm_duty - PWM_CTRL_STEP_DOWN);
- CPRINTF("[%T PWM duty down %d%%]\n", current_pwm_duty);
- }
-}
-DECLARE_HOOK(HOOK_SECOND, board_pwm_tweak, HOOK_PRIO_DEFAULT);
-
-void board_pwm_nominal_duty_cycle(int percent)
+static void pwm_nominal_duty_cycle(int percent)
{
int dummy;
if (battery_current(&dummy))
- board_pwm_duty_cycle(percent);
+ set_pwm_duty_cycle(percent);
else if (percent + PWM_CTRL_BEGIN_OFFSET > PWM_CTRL_MAX_DUTY)
- board_pwm_duty_cycle(PWM_CTRL_MAX_DUTY);
+ set_pwm_duty_cycle(PWM_CTRL_MAX_DUTY);
else
- board_pwm_duty_cycle(percent + PWM_CTRL_BEGIN_OFFSET);
+ set_pwm_duty_cycle(percent + PWM_CTRL_BEGIN_OFFSET);
nominal_pwm_duty = percent;
}
-void usb_charge_interrupt(enum gpio_signal signal)
-{
- task_wake(TASK_ID_CHARGER);
-}
-
-static void board_adc_watch_toad(void)
+static void adc_watch_toad(void)
{
/* Watch VBUS and interrupt if voltage goes under 3V. */
adc_enable_watchdog(STM32_AIN(5), 4095, 1800);
@@ -368,16 +329,6 @@ static void board_adc_watch_toad(void)
current_watchdog = ADC_WATCH_TOAD;
}
-static void board_adc_watchdog_interrupt(void)
-{
- if (current_watchdog == ADC_WATCH_TOAD) {
- pending_tsu6721_reset = 1;
- task_disable_irq(STM32_IRQ_ADC_1);
- task_wake(TASK_ID_CHARGER);
- }
-}
-DECLARE_IRQ(STM32_IRQ_ADC_1, board_adc_watchdog_interrupt, 2);
-
static int usb_has_power_input(int dev_type)
{
if (dev_type & TSU6721_TYPE_JIG_UART_ON)
@@ -403,16 +354,12 @@ static void usb_boost_power_hook(int power_on)
set_video_power(power_on);
}
-static void usb_boost_pwr_on_hook(void) { usb_boost_power_hook(1); }
-static void usb_boost_pwr_off_hook(void) { usb_boost_power_hook(0); }
-DECLARE_HOOK(HOOK_CHIPSET_PRE_INIT, usb_boost_pwr_on_hook, HOOK_PRIO_DEFAULT);
-DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, usb_boost_pwr_off_hook, HOOK_PRIO_DEFAULT);
-
-/*
- * When a power source is removed, record time, power source type,
- * and PWM duty cycle. Then when we see a power source, compare type
- * and calculate time difference to determine if we have just
- * encountered an over current event.
+/**
+ * Detect over-current events.
+ *
+ * When a power source is removed, record time, power source type, and PWM duty
+ * cycle. Then when we see a power source, compare type and calculate time
+ * difference to determine if we have just encountered an over current event.
*/
static void usb_detect_overcurrent(int dev_type)
{
@@ -446,10 +393,12 @@ static void usb_detect_overcurrent(int dev_type)
}
}
-/*
- * Supply 5V VBUS if needed. If we toggle power output, wait for a
- * moment, and then update device type. To avoid race condition, check
- * if power requirement changes during this time.
+/**
+ * Supply 5V VBUS if needed.
+ *
+ * If we toggle power output, wait for a moment, and then update device
+ * type. To avoid race condition, check if power requirement changes during
+ * this time.
*/
static int usb_manage_boost(int dev_type)
{
@@ -471,7 +420,9 @@ static int usb_manage_boost(int dev_type)
return dev_type;
}
-/* Updates ILIM current limit according to device type. */
+/**
+ * Update ILIM current limit according to device type.
+ */
static void usb_update_ilim(int dev_type)
{
if (usb_has_power_input(dev_type)) {
@@ -480,14 +431,14 @@ static void usb_update_ilim(int dev_type)
if (dev_type & TSU6721_TYPE_CHG12)
current_limit = I_LIMIT_3000MA;
else if (dev_type & TSU6721_TYPE_APPLE_CHG) {
- current_limit = board_apple_charger_current();
+ current_limit = apple_charger_current();
} else if ((dev_type & TSU6721_TYPE_CDP) ||
(dev_type & TSU6721_TYPE_DCP))
current_limit = I_LIMIT_1500MA;
- board_pwm_nominal_duty_cycle(current_limit);
+ pwm_nominal_duty_cycle(current_limit);
} else {
- board_ilim_config(ILIM_CONFIG_MANUAL_ON);
+ ilim_config(ILIM_CONFIG_MANUAL_ON);
}
}
@@ -515,7 +466,7 @@ static void usb_device_change(int dev_type)
* USB host, probe for video output.
*/
if (dev_type & TSU6721_TYPE_USB_HOST)
- dev_type = board_probe_video(dev_type);
+ dev_type = probe_video(dev_type);
usb_detect_overcurrent(dev_type);
@@ -529,7 +480,7 @@ static void usb_device_change(int dev_type)
if ((dev_type & TOAD_DEVICE_TYPE) &&
(dev_type & TSU6721_TYPE_VBUS_DEBOUNCED))
- board_adc_watch_toad();
+ adc_watch_toad();
usb_log_dev_type(dev_type);
@@ -542,35 +493,41 @@ static void usb_device_change(int dev_type)
enable_sleep(SLEEP_MASK_USB_PWR);
}
+/*****************************************************************************/
+/* External API */
+
/*
- * TODO(victoryang): Get rid of polling loop when ADC watchdog is ready.
- * See crosbug.com/p/18171
+ * TODO: Init here until we can do with HOOK_INIT. Just need to set prio so we
+ * init before the charger task does.
*/
-static void board_usb_monitor_detach(void)
+void extpower_charge_init(void)
{
- int vbus;
+ int dummy;
- if (!(current_dev_type & TSU6721_TYPE_JIG_UART_ON))
- return;
+ /*
+ * Shut off power input if battery is good. Otherwise, leave
+ * 500mA to sustain the system.
+ */
+ if (battery_current(&dummy))
+ set_pwm_duty_cycle(I_LIMIT_500MA);
+ else
+ ilim_config(ILIM_CONFIG_MANUAL_ON);
- if (adc_read_channel(ADC_CH_USB_DP_SNS) > VIDEO_ID_THRESHOLD) {
- set_video_power(0);
- gpio_set_level(GPIO_ID_MUX, 0);
- msleep(DELAY_ID_MUX_MS);
- tsu6721_enable_interrupts();
- usb_device_change(TSU6721_TYPE_NONE);
- }
+ /*
+ * Somehow TSU6721 comes up slowly. Let's wait for a moment before
+ * accessing it.
+ * TODO(victoryang): Investigate slow init issue.
+ */
+ msleep(500);
- /* Check if there is external power */
- vbus = adc_read_channel(ADC_CH_USB_VBUS_SNS);
- if (get_video_power() && vbus > 4000)
- set_video_power(0);
- else if (!get_video_power() && vbus <= 4000)
- set_video_power(1);
+ tsu6721_init();
+ gpio_enable_interrupt(GPIO_USB_CHG_INT);
+ msleep(100); /* TSU6721 doesn't work properly right away. */
+
+ extpower_charge_update(1);
}
-DECLARE_HOOK(HOOK_SECOND, board_usb_monitor_detach, HOOK_PRIO_DEFAULT);
-void board_usb_charge_update(int force_update)
+void extpower_charge_update(int force_update)
{
int int_val = 0;
@@ -589,21 +546,131 @@ void board_usb_charge_update(int force_update)
usb_device_change(tsu6721_get_device_type());
}
-int board_get_usb_dev_type(void)
+int extpower_charge_needs_update(void)
{
- return current_dev_type;
+ return tsu6721_peek_interrupts();
}
-int board_get_usb_current_limit(void)
+int extpower_is_present(void)
{
- /* Approximate value by PWM duty cycle */
- return PWM_MAPPING_A + PWM_MAPPING_B * current_pwm_duty;
+ static int last_vbus;
+ int vbus, vbus_good;
+
+ if (!gpio_get_level(GPIO_BOOST_EN))
+ return 0;
+
+ /*
+ * UVLO is 4.1V. We consider AC bad when its voltage drops below 4.2V
+ * for two consecutive samples. This is to give PWM a chance to bring
+ * voltage up.
+ */
+ vbus = adc_read_channel(ADC_CH_USB_VBUS_SNS);
+ vbus_good = (vbus >= 4200 || last_vbus >= 4200);
+ last_vbus = vbus;
+
+ return vbus_good;
+}
+
+void extpower_interrupt(enum gpio_signal signal)
+{
+ task_wake(TASK_ID_CHARGER);
+}
+
+/*****************************************************************************/
+/* Hooks */
+
+static void adc_watchdog_interrupt(void)
+{
+ if (current_watchdog == ADC_WATCH_TOAD) {
+ pending_tsu6721_reset = 1;
+ task_disable_irq(STM32_IRQ_ADC_1);
+ task_wake(TASK_ID_CHARGER);
+ }
+}
+DECLARE_IRQ(STM32_IRQ_ADC_1, adc_watchdog_interrupt, 2);
+
+static void usb_boost_pwr_on_hook(void)
+{
+ usb_boost_power_hook(1);
}
+DECLARE_HOOK(HOOK_CHIPSET_PRE_INIT, usb_boost_pwr_on_hook, HOOK_PRIO_DEFAULT);
+static void usb_boost_pwr_off_hook(void)
+{
+ usb_boost_power_hook(0);
+}
+DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, usb_boost_pwr_off_hook, HOOK_PRIO_DEFAULT);
+
+static void pwm_tweak(void)
+{
+ int vbus, current;
+
+ if (current_ilim_config != ILIM_CONFIG_PWM)
+ return;
+
+ vbus = adc_read_channel(ADC_CH_USB_VBUS_SNS);
+ if (battery_current(&current))
+ return;
+
+ if (user_pwm_duty >= 0) {
+ if (current_pwm_duty != user_pwm_duty)
+ set_pwm_duty_cycle(user_pwm_duty);
+ return;
+ }
+
+ /*
+ * If VBUS voltage is too low:
+ * - If battery is discharging, throttling more is going to draw
+ * more current from the battery, so do nothing unless VBUS is
+ * about to be lower than AC good threshold.
+ * - Otherwise, throttle input current to raise VBUS voltage.
+ * If VBUS voltage is high enough, allow more current until we hit
+ * current limit target.
+ */
+ if (pwm_check_vbus_low(vbus, current)) {
+ set_pwm_duty_cycle(current_pwm_duty + PWM_CTRL_STEP_UP);
+ CPRINTF("[%T PWM duty up %d%%]\n", current_pwm_duty);
+ } else if (vbus > PWM_CTRL_VBUS_HIGH && pwm_check_lower_bound()) {
+ set_pwm_duty_cycle(current_pwm_duty - PWM_CTRL_STEP_DOWN);
+ CPRINTF("[%T PWM duty down %d%%]\n", current_pwm_duty);
+ }
+}
+DECLARE_HOOK(HOOK_SECOND, pwm_tweak, HOOK_PRIO_DEFAULT);
+
+/*
+ * TODO(victoryang): Get rid of polling loop when ADC watchdog is ready.
+ * See crosbug.com/p/18171
+ */
+static void usb_monitor_detach(void)
+{
+ int vbus;
+
+ if (!(current_dev_type & TSU6721_TYPE_JIG_UART_ON))
+ return;
+
+ if (adc_read_channel(ADC_CH_USB_DP_SNS) > VIDEO_ID_THRESHOLD) {
+ set_video_power(0);
+ gpio_set_level(GPIO_ID_MUX, 0);
+ msleep(DELAY_ID_MUX_MS);
+ tsu6721_enable_interrupts();
+ usb_device_change(TSU6721_TYPE_NONE);
+ }
+
+ /* Check if there is external power */
+ vbus = adc_read_channel(ADC_CH_USB_VBUS_SNS);
+ if (get_video_power() && vbus > 4000)
+ set_video_power(0);
+ else if (!get_video_power() && vbus <= 4000)
+ set_video_power(1);
+}
+DECLARE_HOOK(HOOK_SECOND, usb_monitor_detach, HOOK_PRIO_DEFAULT);
+
+/*****************************************************************************/
/*
* Console commands for debugging.
- * TODO(victoryang): Remove after charging control is done.
+ * TODO(victoryang): Gate with CONFIG flag after charging control is done.
*/
+
static int command_ilim(int argc, char **argv)
{
char *e;
@@ -611,13 +678,13 @@ static int command_ilim(int argc, char **argv)
if (argc >= 2) {
if (parse_bool(argv[1], &v)) {
- board_ilim_config(v ? ILIM_CONFIG_MANUAL_ON :
+ ilim_config(v ? ILIM_CONFIG_MANUAL_ON :
ILIM_CONFIG_MANUAL_OFF);
} else {
v = strtoi(argv[1], &e, 0);
if (*e)
return EC_ERROR_PARAM1;
- board_pwm_duty_cycle(v);
+ set_pwm_duty_cycle(v);
}
}
@@ -698,3 +765,23 @@ static int ext_power_command_current_limit(struct host_cmd_handler_args *args)
DECLARE_HOST_COMMAND(EC_CMD_EXT_POWER_CURRENT_LIMIT,
ext_power_command_current_limit,
EC_VER_MASK(0));
+
+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, ADC_FLAG_KEEP_ON)
+ * 17000 / 1024;
+ r->current_system = pmu_adc_read(ADC_IAC, 0)
+ * 20 * 33 / 1024;
+ r->usb_dev_type = current_dev_type;
+
+ /* Approximate value by PWM duty cycle */
+ r->usb_current_limit = PWM_MAPPING_A + PWM_MAPPING_B * current_pwm_duty;
+
+ 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/common/pmu_tps65090_charger.c b/common/pmu_tps65090_charger.c
index c1c7a03e53..b9295c242f 100644
--- a/common/pmu_tps65090_charger.c
+++ b/common/pmu_tps65090_charger.c
@@ -17,7 +17,6 @@
#include "system.h"
#include "task.h"
#include "timer.h"
-#include "tsu6721.h"
#include "util.h"
#define CPUTS(outstr) cputs(CC_CHARGER, outstr)
@@ -405,28 +404,16 @@ void charger_task(void)
enable_charging(0);
disable_sleep(SLEEP_MASK_CHARGING);
-#ifdef CONFIG_TSU6721
- board_pwm_init_limit();
-
- /*
- * Somehow TSU6721 comes up slowly. Let's wait for a moment before
- * accessing it.
- * TODO(victoryang): Investigate slow init issue.
- */
- msleep(500);
-
- tsu6721_init(); /* Init here until we can do with HOOK_INIT */
- gpio_enable_interrupt(GPIO_USB_CHG_INT);
- msleep(100); /* TSU6721 doesn't work properly right away. */
- board_usb_charge_update(1);
+#ifdef CONFIG_EXTPOWER_USB
+ extpower_charge_init();
#endif
while (1) {
last_waken = get_time();
pmu_clear_irq();
-#ifdef CONFIG_TSU6721
- board_usb_charge_update(0);
+#ifdef CONFIG_EXTPOWER_USB
+ extpower_charge_update(0);
#endif
/*
@@ -509,8 +496,8 @@ void charger_task(void)
}
}
-#ifdef CONFIG_TSU6721
- has_pending_event |= tsu6721_peek_interrupts();
+#ifdef CONFIG_EXTPOWER_USB
+ has_pending_event |= extpower_charge_needs_update();
#endif
if (!has_pending_event) {
diff --git a/include/extpower.h b/include/extpower.h
index d3f9a4f6ef..36c5535633 100644
--- a/include/extpower.h
+++ b/include/extpower.h
@@ -10,6 +10,11 @@
#include "common.h"
+#ifdef CONFIG_EXTPOWER_USB
+/* USB-power-specific methods */
+#include "extpower_usb.h"
+#endif
+
/**
* Return non-zero if external power is present.
*/
diff --git a/include/extpower_usb.h b/include/extpower_usb.h
new file mode 100644
index 0000000000..dc5c68c117
--- /dev/null
+++ b/include/extpower_usb.h
@@ -0,0 +1,39 @@
+/* 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.
+ */
+
+/* External power via USB for Chrome EC */
+
+#ifndef __CROS_EC_EXTPOWER_USB_H
+#define __CROS_EC_EXTPOWER_USB_H
+
+#include "common.h"
+
+/*
+ * TODO: this currently piggy-backs on the charger task. Should be able to
+ * move updates to deferred functions and get rid of all the ifdef's in the
+ * charger task. At that point, all these APIs will be internal to the
+ * extpower module and this entire header file can go away.
+ */
+
+/**
+ * Properly limit input power on EC boot.
+ *
+ * Called from charger task.
+ */
+void extpower_charge_init(void);
+
+/**
+ * Update external power state.
+ *
+ * Called from charger task.
+ */
+void extpower_charge_update(int force_update);
+
+/**
+ * Return non-zero if external power needs update from charge task.
+ */
+int extpower_charge_needs_update(void);
+
+#endif /* __CROS_EC_EXTPOWER_USB_H */