diff options
author | Vincent Palatin <vpalatin@chromium.org> | 2014-05-14 15:10:52 -0700 |
---|---|---|
committer | chrome-internal-fetch <chrome-internal-fetch@google.com> | 2014-05-17 20:17:25 +0000 |
commit | dc37d4a1d5c8a4a8639d38a0f6291c98feeb1ecf (patch) | |
tree | 4dc8f825a7c910f7508a500749d500fb22e72603 | |
parent | 5fd33410770fbc9b29432fe6ca81a763e6b47ec4 (diff) | |
download | chrome-ec-dc37d4a1d5c8a4a8639d38a0f6291c98feeb1ecf.tar.gz |
zinger: fast over-current protection
When the supply output is enabled, ensure that we detect quickly any
over-current situation by setting an analog watchdog in continuous
conversion mode.
Signed-off-by: Vincent Palatin <vpalatin@chromium.org>
BRANCH=none
BUG=chrome-os-partner:28331
TEST=plug an electronic load to Zinger and see the OCP triggered
quickly when we go above the current threshold.
Change-Id: I7da50ef242addbd2f4f48f624494daa321ac22b2
Reviewed-on: https://chromium-review.googlesource.com/199924
Tested-by: Vincent Palatin <vpalatin@chromium.org>
Reviewed-by: Alec Berg <alecaberg@chromium.org>
-rw-r--r-- | board/zinger/hardware.c | 40 | ||||
-rw-r--r-- | board/zinger/usb_pd_policy.c | 29 |
2 files changed, 67 insertions, 2 deletions
diff --git a/board/zinger/hardware.c b/board/zinger/hardware.c index cf71c3ffad..0bafa48839 100644 --- a/board/zinger/hardware.c +++ b/board/zinger/hardware.c @@ -116,6 +116,10 @@ static void adc_init(void) STM32_ADC_CFGR2 = 0; /* Sampling time : 13.5 ADC clock cycles. */ STM32_ADC_SMPR = 2; + /* Disable interrupts */ + STM32_ADC_IER = 0; + /* Analog watchdog IRQ */ + task_enable_irq(STM32_IRQ_ADC_COMP); } static void uart_init(void) @@ -171,7 +175,7 @@ int adc_read_channel(enum adc_channel ch) /* Select channel to convert */ STM32_ADC_CHSELR = 1 << ch; /* Clear flags */ - STM32_ADC_ISR = 0xe; + STM32_ADC_ISR = 0x8e; /* Start conversion */ STM32_ADC_CR |= 1 << 2; /* ADSTART */ /* Wait for end of conversion */ @@ -183,6 +187,40 @@ int adc_read_channel(enum adc_channel ch) return value; } +int adc_enable_watchdog(int ch, int high, int low) +{ + /* Set thresholds */ + STM32_ADC_TR = ((high & 0xfff) << 16) | (low & 0xfff); + /* Select channel to convert */ + STM32_ADC_CHSELR = 1 << ch; + /* Clear flags */ + STM32_ADC_ISR = 0x8e; + /* Set Watchdog enable bit on a single channel / continuous mode */ + STM32_ADC_CFGR1 = (ch << 26) | (1 << 23) | (1 << 22) + | (1 << 13) | (1 << 12); + /* Enable watchdog interrupt */ + STM32_ADC_IER = 1 << 7; + /* Start continuous conversion */ + STM32_ADC_CR |= 1 << 2; /* ADSTART */ + + return EC_SUCCESS; +} + +int adc_disable_watchdog(void) +{ + /* Stop on-going conversion */ + STM32_ADC_CR |= 1 << 4; /* ADSTP */ + /* Wait for conversion to stop */ + while (STM32_ADC_CR & (1 << 4)) + ; + /* CONT=0 -> continuous mode off / Clear Watchdog enable */ + STM32_ADC_CFGR1 = 1 << 12; + /* Disable interrupt */ + STM32_ADC_IER = 0; + + return EC_SUCCESS; +} + /* ---- flash handling ---- */ /* diff --git a/board/zinger/usb_pd_policy.c b/board/zinger/usb_pd_policy.c index c55f33561c..a23328bc3a 100644 --- a/board/zinger/usb_pd_policy.c +++ b/board/zinger/usb_pd_policy.c @@ -9,6 +9,7 @@ #include "console.h" #include "debug.h" #include "hooks.h" +#include "irq_handler.h" #include "registers.h" #include "sha1.h" #include "timer.h" @@ -59,6 +60,7 @@ static inline int output_is_enabled(void) enum faults { FAULT_OK = 0, FAULT_OCP, /* Over-Current Protection */ + FAULT_FAST_OCP, /* Over-Current Protection for interrupt context */ FAULT_OVP, /* Under or Over-Voltage Protection */ }; @@ -161,6 +163,9 @@ int pd_set_power_supply_ready(void) return EC_ERROR_INVAL; output_enable(); + /* Over-current monitoring */ + adc_enable_watchdog(ADC_CH_A_SENSE, MAX_CURRENT, 0); + return EC_SUCCESS; /* we are ready */ } @@ -171,16 +176,28 @@ void pd_power_supply_reset(void) volt_idx = 0; set_output_voltage(VO_5V); /* TODO transition delay */ + + /* Stop OCP monitoring to save power */ + adc_disable_watchdog(); } int pd_board_checks(void) { int vbus_volt, vbus_amp; + int watchdog_enabled = STM32_ADC_CFGR1 & (1 << 23); + + if (watchdog_enabled) + /* if the watchdog is enabled, stop it to do other readings */ + adc_disable_watchdog(); vbus_volt = adc_read_channel(ADC_CH_V_SENSE); vbus_amp = adc_read_channel(ADC_CH_A_SENSE); - if (vbus_amp > MAX_CURRENT) { + if (watchdog_enabled) + /* re-enable fast OCP */ + adc_enable_watchdog(ADC_CH_A_SENSE, MAX_CURRENT, 0); + + if ((fault == FAULT_FAST_OCP) || (vbus_amp > MAX_CURRENT)) { debug_printf("OverCurrent : %d mA\n", vbus_amp * VDDA_MV / CURR_GAIN * 1000 / R_SENSE / ADC_SCALE); fault = FAULT_OCP; @@ -208,6 +225,16 @@ int pd_board_checks(void) } +void IRQ_HANDLER(STM32_IRQ_ADC_COMP)(void) +{ + /* cut the power output */ + pd_power_supply_reset(); + /* Clear flags */ + STM32_ADC_ISR = 0x8e; + /* record a special fault, the normal check will record the timeout */ + fault = FAULT_FAST_OCP; +} + /* ----------------- Vendor Defined Messages ------------------ */ int pd_custom_vdm(void *ctxt, int cnt, uint32_t *payload, uint32_t **rpayload) { |