mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2026-01-09 09:01:35 +00:00
spring: reset TSU6721 when Toad's ID changes
When Toad's ID changes, VBUS goes low for 10ms. This, however, is not picked up by TSU6721 and thus we need to monitor VBUS and reset TSU6721 when necessary. By resetting TSU6721, we can force it to update device type. BUG=chrome-os-partner:18292 TEST=manual BRANCH=spring Change-Id: Ib96bbb0f101c8c5f5371591603af2dee27f01cc8 Signed-off-by: Vic Yang <victoryang@chromium.org> Reviewed-on: https://gerrit.chromium.org/gerrit/45727
This commit is contained in:
@@ -31,6 +31,9 @@
|
||||
#define POWERED_5000_DEVICE_TYPE (TSU6721_TYPE_OTG)
|
||||
#define POWERED_3300_DEVICE_TYPE (TSU6721_TYPE_JIG_UART_ON)
|
||||
|
||||
/* Toad cable */
|
||||
#define TOAD_DEVICE_TYPE (TSU6721_TYPE_UART | TSU6721_TYPE_AUDIO3)
|
||||
|
||||
/* Voltage threshold of D+ for video */
|
||||
#define VIDEO_ID_THRESHOLD 1335
|
||||
|
||||
@@ -63,11 +66,18 @@ static int current_dev_type = TSU6721_TYPE_NONE;
|
||||
static int nominal_pwm_duty;
|
||||
static int current_pwm_duty;
|
||||
|
||||
static int pending_tsu6721_reset;
|
||||
|
||||
static enum {
|
||||
LIMIT_NORMAL,
|
||||
LIMIT_AGGRESSIVE,
|
||||
} current_limit_mode = LIMIT_AGGRESSIVE;
|
||||
|
||||
static enum {
|
||||
ADC_WATCH_NONE,
|
||||
ADC_WATCH_TOAD,
|
||||
} current_watchdog = ADC_WATCH_NONE;
|
||||
|
||||
/*
|
||||
* Last time we see a power source removed. Also records the power source
|
||||
* type and PWM duty cycle at that moment.
|
||||
@@ -299,6 +309,25 @@ void usb_charge_interrupt(enum gpio_signal signal)
|
||||
task_wake(TASK_ID_PMU_TPS65090_CHARGER);
|
||||
}
|
||||
|
||||
static void board_adc_watch_toad(void)
|
||||
{
|
||||
/* Watch VBUS and interrupt if voltage goes under 3V. */
|
||||
adc_enable_watchdog(STM32_AIN(5), 4095, 1800);
|
||||
task_clear_pending_irq(STM32_IRQ_ADC_1);
|
||||
task_enable_irq(STM32_IRQ_ADC_1);
|
||||
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_PMU_TPS65090_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)
|
||||
@@ -390,6 +419,10 @@ static void usb_device_change(int dev_type)
|
||||
board_ilim_config(ILIM_CONFIG_MANUAL_ON);
|
||||
}
|
||||
|
||||
if ((dev_type & TOAD_DEVICE_TYPE) &&
|
||||
(dev_type & TSU6721_TYPE_VBUS_DEBOUNCED))
|
||||
board_adc_watch_toad();
|
||||
|
||||
/* Log to console */
|
||||
CPRINTF("[%T USB Attached: ");
|
||||
if (dev_type == TSU6721_TYPE_NONE)
|
||||
@@ -412,6 +445,10 @@ static void usb_device_change(int dev_type)
|
||||
CPRINTF("Apple charger]\n");
|
||||
else if (dev_type & TSU6721_TYPE_JIG_UART_ON)
|
||||
CPRINTF("JIG UART ON]\n");
|
||||
else if (dev_type & TSU6721_TYPE_AUDIO3)
|
||||
CPRINTF("Audio 3]\n");
|
||||
else if (dev_type & TSU6721_TYPE_UART)
|
||||
CPRINTF("UART]\n");
|
||||
else if (dev_type & TSU6721_TYPE_VBUS_DEBOUNCED)
|
||||
CPRINTF("Unknown with power]\n");
|
||||
else
|
||||
@@ -443,7 +480,16 @@ DECLARE_HOOK(HOOK_SECOND, board_usb_monitor_detach, HOOK_PRIO_DEFAULT);
|
||||
|
||||
void board_usb_charge_update(int force_update)
|
||||
{
|
||||
int int_val = tsu6721_get_interrupts();
|
||||
int int_val = 0;
|
||||
|
||||
if (pending_tsu6721_reset) {
|
||||
current_watchdog = ADC_WATCH_NONE;
|
||||
adc_disable_watchdog();
|
||||
tsu6721_reset();
|
||||
force_update = 1;
|
||||
pending_tsu6721_reset = 0;
|
||||
} else
|
||||
int_val = tsu6721_get_interrupts();
|
||||
|
||||
if (int_val & TSU6721_INT_DETACH)
|
||||
usb_device_change(TSU6721_TYPE_NONE);
|
||||
|
||||
@@ -97,6 +97,9 @@ static int adc_enable_watchdog_no_lock(void)
|
||||
/* Set channel */
|
||||
STM32_ADC_CR1 = (STM32_ADC_CR1 & ~0x1f) | watchdog_ain_id;
|
||||
|
||||
/* Clear interrupt bit */
|
||||
STM32_ADC_SR &= ~0x1;
|
||||
|
||||
/* AWDSGL=1, SCAN=1, AWDIE=1, AWDEN=1 */
|
||||
STM32_ADC_CR1 |= (1 << 9) | (1 << 8) | (1 << 6) | (1 << 23);
|
||||
|
||||
@@ -138,8 +141,8 @@ static int adc_disable_watchdog_no_lock(void)
|
||||
if (!adc_watchdog_enabled())
|
||||
return EC_ERROR_UNKNOWN;
|
||||
|
||||
/* AWDEN=0 */
|
||||
STM32_ADC_CR1 &= ~(1 << 23);
|
||||
/* AWDEN=0, AWDIE=0 */
|
||||
STM32_ADC_CR1 &= ~(1 << 23) & ~(1 << 6);
|
||||
|
||||
/* CONT=0 */
|
||||
STM32_ADC_CR2 &= ~(1 << 1);
|
||||
|
||||
@@ -24,6 +24,9 @@
|
||||
/* 8-bit I2C address */
|
||||
#define TSU6721_I2C_ADDR (0x25 << 1)
|
||||
|
||||
/* Delay values */
|
||||
#define TSU6721_SW_RESET_DELAY 15
|
||||
|
||||
static int saved_interrupts;
|
||||
|
||||
uint8_t tsu6721_read(uint8_t reg)
|
||||
@@ -86,6 +89,14 @@ int tsu6721_get_device_type(void)
|
||||
(tsu6721_read(TSU6721_REG_DEV_TYPE1));
|
||||
}
|
||||
|
||||
void tsu6721_reset(void)
|
||||
{
|
||||
tsu6721_write(TSU6721_REG_RESET, 0x1);
|
||||
/* TSU6721 reset takes ~10ms. Let's wait for 15ms to be safe. */
|
||||
msleep(TSU6721_SW_RESET_DELAY);
|
||||
tsu6721_init();
|
||||
}
|
||||
|
||||
int tsu6721_mux(enum tsu6721_mux sel)
|
||||
{
|
||||
uint8_t id = tsu6721_read(TSU6721_REG_ADC);
|
||||
|
||||
@@ -105,4 +105,7 @@ int tsu6721_get_device_type(void);
|
||||
/* Control TSU6721 mux. */
|
||||
int tsu6721_mux(enum tsu6721_mux sel);
|
||||
|
||||
/* Reset TSU6721. */
|
||||
void tsu6721_reset(void);
|
||||
|
||||
#endif /* TSU6721_H */
|
||||
|
||||
Reference in New Issue
Block a user