diff options
author | Vic Yang <victoryang@chromium.org> | 2012-12-26 16:47:38 +0800 |
---|---|---|
committer | ChromeBot <chrome-bot@google.com> | 2013-02-07 22:06:05 -0800 |
commit | c93378dafad7229e34719165c09f31e15b6300d8 (patch) | |
tree | 23e534457a91ee7e323d615110ddb876e7f77040 | |
parent | f84a5fa8b1f6d688c73a1e6e9b33df79489cbfef (diff) | |
download | chrome-ec-c93378dafad7229e34719165c09f31e15b6300d8.tar.gz |
spring: Distinguish Apple Chargersstabilize-bluetooth-smart
This uses D+/D- voltage to distinguish different Apple chargers.
BUG=chrome-os-partner:14319
TEST=Manual on Spring
BRANCH=none
Change-Id: I50075d466f6e6b1adf613748cf433d7f43c04bfe
Signed-off-by: Vic Yang <victoryang@chromium.org>
Reviewed-on: https://gerrit.chromium.org/gerrit/42850
Reviewed-by: Vincent Palatin <vpalatin@chromium.org>
-rw-r--r-- | board/spring/usb_charging.c | 39 | ||||
-rw-r--r-- | common/tsu6721.c | 27 | ||||
-rw-r--r-- | include/tsu6721.h | 13 |
3 files changed, 61 insertions, 18 deletions
diff --git a/board/spring/usb_charging.c b/board/spring/usb_charging.c index b919ec851b..e1b9029bcb 100644 --- a/board/spring/usb_charging.c +++ b/board/spring/usb_charging.c @@ -5,11 +5,13 @@ /* USB charging control for spring board */ +#include "adc.h" #include "board.h" #include "console.h" #include "gpio.h" #include "lp5562.h" #include "registers.h" +#include "stm32_adc.h" #include "task.h" #include "timer.h" #include "tsu6721.h" @@ -27,13 +29,19 @@ /* PWM controlled current limit */ #define I_LIMIT_500MA 85 -#define I_LIMIT_1000MA 70 +#define I_LIMIT_1000MA 75 #define I_LIMIT_1500MA 50 #define I_LIMIT_2000MA 35 +#define I_LIMIT_2400MA 25 #define I_LIMIT_3000MA 0 static enum ilim_config current_ilim_config = ILIM_CONFIG_MANUAL_OFF; +static const int apple_charger_type[4] = {I_LIMIT_500MA, + I_LIMIT_1000MA, + I_LIMIT_2000MA, + I_LIMIT_2400MA}; + static void board_ilim_use_gpio(void) { /* Disable counter */ @@ -107,6 +115,31 @@ void board_ilim_config(enum ilim_config config) } } +/* Returns Apple charger current limit */ +static int board_apple_charger_current(void) +{ + int vp, vn; + int type = 0; + int data[ADC_CH_COUNT]; + + /* TODO(victoryang): Handle potential race condition. */ + tsu6721_disable_interrupts(); + tsu6721_mux(TSU6721_MUX_USB); + /* Wait 20ms for signal to stablize */ + msleep(20); + adc_read_all_channels(data); + vp = data[ADC_CH_USB_DP_SNS]; + vn = data[ADC_CH_USB_DN_SNS]; + tsu6721_mux(TSU6721_MUX_AUTO); + tsu6721_enable_interrupts(); + if (vp > 1200) + type |= 0x2; + if (vn > 1200) + type |= 0x1; + + return apple_charger_type[type]; +} + void board_pwm_duty_cycle(int percent) { if (current_ilim_config != ILIM_CONFIG_PWM) @@ -143,8 +176,7 @@ static void usb_device_change(int dev_type) if (dev_type & TSU6721_TYPE_CHG12) current_limit = I_LIMIT_3000MA; else if (dev_type & TSU6721_TYPE_APPLE_CHG) { - /* TODO: Distinguish 1A/2A chargers. */ - current_limit = I_LIMIT_1000MA; + current_limit = board_apple_charger_current(); } else if ((dev_type & TSU6721_TYPE_CDP) || (dev_type & TSU6721_TYPE_DCP)) current_limit = I_LIMIT_1500MA; @@ -154,6 +186,7 @@ static void usb_device_change(int dev_type) /* Turns on battery LED */ lp5562_poweron(); } else { + board_ilim_config(ILIM_CONFIG_MANUAL_ON); lp5562_poweroff(); } diff --git a/common/tsu6721.c b/common/tsu6721.c index ba6d3ad4b0..8ea369c463 100644 --- a/common/tsu6721.c +++ b/common/tsu6721.c @@ -45,20 +45,24 @@ void tsu6721_write(uint8_t reg, uint8_t val) CPRINTF("[%T TSU6721 I2C write failed]\n"); } -void tsu6721_enable_interrupts(int mask) +void tsu6721_enable_interrupts(void) { int ctrl = tsu6721_read(TSU6721_REG_CONTROL); - tsu6721_write(TSU6721_REG_INT_MASK1, (~mask) & 0xff); - tsu6721_write(TSU6721_REG_INT_MASK2, ((~mask) >> 8) & 0xff); tsu6721_write(TSU6721_REG_CONTROL, ctrl & 0x1e); } -void tsu6721_disable_interrupt(void) +void tsu6721_disable_interrupts(void) { int ctrl = tsu6721_read(TSU6721_REG_CONTROL); tsu6721_write(TSU6721_REG_CONTROL, ctrl | 0x1); } +void tsu6721_set_interrupt_mask(uint16_t mask) +{ + tsu6721_write(TSU6721_REG_INT_MASK1, (~mask) & 0xff); + tsu6721_write(TSU6721_REG_INT_MASK2, ((~mask) >> 8) & 0xff); +} + int tsu6721_get_interrupts(void) { return (tsu6721_read(TSU6721_REG_INT1) << 8) | @@ -89,7 +93,7 @@ int tsu6721_mux(enum tsu6721_mux sel) return EC_ERROR_INVAL; } - if (sel == TSU6721_MUX_NONE) { + if (sel == TSU6721_MUX_AUTO) { tsu6721_write(TSU6721_REG_CONTROL, ctrl | TSU6721_CTRL_AUTO); } else { tsu6721_write(TSU6721_REG_MANUAL1, sel); @@ -114,10 +118,11 @@ void tsu6721_init(void) settings = (settings & ~0x38); tsu6721_write(TSU6721_REG_TIMER, settings); - tsu6721_enable_interrupts(TSU6721_INT_ATTACH | - TSU6721_INT_DETACH | - TSU6721_INT_ADC_CHANGE | - TSU6721_INT_VBUS); + tsu6721_set_interrupt_mask(TSU6721_INT_ATTACH | + TSU6721_INT_DETACH | + TSU6721_INT_ADC_CHANGE | + TSU6721_INT_VBUS); + tsu6721_enable_interrupts(); } /* * TODO(vpalatin): using the I2C early in the HOOK_INIT @@ -165,7 +170,7 @@ static int command_usbmux(int argc, char **argv) } else if (!strcasecmp(argv[1], "uart2")) { tsu6721_mux(TSU6721_MUX_AUDIO); } else if (!strcasecmp(argv[1], "auto")) { - tsu6721_mux(TSU6721_MUX_NONE); + tsu6721_mux(TSU6721_MUX_AUTO); } else { /* read one register */ ccprintf("Invalid mux value: %s\n", argv[1]); return EC_ERROR_INVAL; @@ -191,7 +196,7 @@ static int usb_command_mux(struct host_cmd_handler_args *args) return EC_RES_ACCESS_DENIED; /* Safety check */ - if (p->mux != TSU6721_MUX_NONE && + if (p->mux != TSU6721_MUX_AUTO && p->mux != TSU6721_MUX_USB && p->mux != TSU6721_MUX_UART && p->mux != TSU6721_MUX_AUDIO) diff --git a/include/tsu6721.h b/include/tsu6721.h index f1101acf06..66bf5b6a33 100644 --- a/include/tsu6721.h +++ b/include/tsu6721.h @@ -32,7 +32,7 @@ #define TSU6721_CTRL_AUTO (1 << 2) enum tsu6721_mux { - TSU6721_MUX_NONE = 0x00, + TSU6721_MUX_AUTO = 0x00, TSU6721_MUX_USB = 0x24, TSU6721_MUX_AUDIO = 0x48, TSU6721_MUX_UART = 0x6C, @@ -81,13 +81,15 @@ uint8_t tsu6721_read(uint8_t reg); /* Write TSU6721 register. */ void tsu6721_write(uint8_t reg, uint8_t val); -/* Enable interrupt(s). The parameter 'mask' can be one or a combination of - * TSU6721_INT_* */ -void tsu6721_enable_interrupts(int mask); +/* Enable interrupts. */ +void tsu6721_enable_interrupts(void); /* Disable all interrupts. */ void tsu6721_disable_interrupts(void); +/* Set interrupt mask. */ +void tsu6721_set_interrupt_mask(uint16_t mask); + /* Get and clear current interrupt status. Return value is a combination of * TSU6721_INT_* */ int tsu6721_get_interrupts(void); @@ -96,4 +98,7 @@ int tsu6721_get_interrupts(void); * TSU6721_TYPE_* */ int tsu6721_get_device_type(void); +/* Control TSU6721 mux. */ +int tsu6721_mux(enum tsu6721_mux sel); + #endif /* TSU6721_H */ |