summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVincent Palatin <vpalatin@chromium.org>2014-11-13 20:51:00 -0800
committerAlec Berg <alecaberg@chromium.org>2015-01-10 23:45:31 +0000
commit4cbb3941b188beaf04ffaa2473e65e352aee6254 (patch)
tree1b536186cf7ad32048bf7fdfda73800d6a55b480
parentcf8f65d34af0aff42e66bd395a74adf2874bd200 (diff)
downloadchrome-ec-stabilize-storm-6683.B.tar.gz
zinger: do an intermediate step when discharging from 20V to 5Vstabilize-storm-6683.B
If we discharge directly the output voltage from 20V to 5V under load, an undershot happens and we dip below the 5V UVP threshold. So when doing a down voltage transition from 20V to 5V, split it into 2 steps : a 20V->12V transition then once we are reached 12V, a 12V->5V transition. Signed-off-by: Vincent Palatin <vpalatin@chromium.org> BRANCH=samus BUG=chrome-os-partner:33794 TEST=connect Zinger to a Firefly and an electronic load. Using Firefly, ask for 20V->5V, 12V->5V and 20V->12V transitions, check the VBUS waveforms on the scope. Change-Id: Ie1e091ae6f1fee1fb7d4e3bd72edbe7491acd5ea Reviewed-on: https://chromium-review.googlesource.com/229732 Reviewed-by: Alec Berg <alecaberg@chromium.org> Commit-Queue: Alec Berg <alecaberg@chromium.org> Tested-by: Alec Berg <alecaberg@chromium.org>
-rw-r--r--board/zinger/usb_pd_policy.c73
1 files changed, 54 insertions, 19 deletions
diff --git a/board/zinger/usb_pd_policy.c b/board/zinger/usb_pd_policy.c
index 9559ec92b8..50661a1c57 100644
--- a/board/zinger/usb_pd_policy.c
+++ b/board/zinger/usb_pd_policy.c
@@ -152,13 +152,23 @@ static void discharge_voltage(int target_volt)
#define PDO_FIXED_FLAGS (PDO_FIXED_EXTERNAL | PDO_FIXED_DATA_SWAP)
+/* Voltage indexes for the PDOs */
+enum volt_idx {
+ PDO_IDX_5V = 0,
+ PDO_IDX_12V = 1,
+ PDO_IDX_20V = 2,
+
+ PDO_IDX_COUNT
+};
+
/* Power Delivery Objects */
const uint32_t pd_src_pdo[] = {
- PDO_FIXED(5000, RATED_CURRENT, PDO_FIXED_FLAGS),
- PDO_FIXED(12000, RATED_CURRENT, PDO_FIXED_FLAGS),
- PDO_FIXED(20000, RATED_CURRENT, PDO_FIXED_FLAGS),
+ [PDO_IDX_5V] = PDO_FIXED(5000, RATED_CURRENT, PDO_FIXED_FLAGS),
+ [PDO_IDX_12V] = PDO_FIXED(12000, RATED_CURRENT, PDO_FIXED_FLAGS),
+ [PDO_IDX_20V] = PDO_FIXED(20000, RATED_CURRENT, PDO_FIXED_FLAGS),
};
const int pd_src_pdo_cnt = ARRAY_SIZE(pd_src_pdo);
+BUILD_ASSERT(ARRAY_SIZE(pd_src_pdo) == PDO_IDX_COUNT);
/* PDO voltages (should match the table above) */
static const struct {
@@ -167,14 +177,19 @@ static const struct {
int ovp; /* over-voltage limit in mV */
int ovp_rec;/* over-voltage recovery threshold in mV */
} voltages[ARRAY_SIZE(pd_src_pdo)] = {
- {VO_5V, UVP_MV(5000), OVP_MV(5000), OVP_REC_MV(5000)},
- {VO_12V, UVP_MV(12000), OVP_MV(12000), OVP_REC_MV(12000)},
- {VO_20V, UVP_MV(20000), OVP_MV(20000), OVP_REC_MV(20000)},
+ [PDO_IDX_5V] = {VO_5V, UVP_MV(5000), OVP_MV(5000),
+ OVP_REC_MV(5000)},
+ [PDO_IDX_12V] = {VO_12V, UVP_MV(12000), OVP_MV(12000),
+ OVP_REC_MV(12000)},
+ [PDO_IDX_20V] = {VO_20V, UVP_MV(20000), OVP_MV(20000),
+ OVP_REC_MV(20000)},
};
/* current and previous selected PDO entry */
static int volt_idx;
static int last_volt_idx;
+/* target voltage at the end of discharge */
+static int discharge_volt_idx;
/* output current measurement */
int vbus_amp;
@@ -211,12 +226,18 @@ int pd_check_requested_voltage(uint32_t rdo)
void pd_transition_voltage(int idx)
{
- if (idx - 1 < volt_idx) { /* down voltage transition */
+ last_volt_idx = volt_idx;
+ volt_idx = idx - 1;
+ if (volt_idx < last_volt_idx) { /* down voltage transition */
/* Stop OCP monitoring */
adc_disable_watchdog();
- discharge_voltage(voltages[idx - 1].ovp);
- } else if (idx - 1 > volt_idx) { /* up voltage transition */
+ discharge_volt_idx = volt_idx;
+ /* from 20V : do an intermediate step at 12V */
+ if (volt_idx == PDO_IDX_5V && last_volt_idx == PDO_IDX_20V)
+ volt_idx = PDO_IDX_12V;
+ discharge_voltage(voltages[volt_idx].ovp);
+ } else if (volt_idx > last_volt_idx) { /* up voltage transition */
if (discharge_is_enabled()) {
/* Make sure discharging is disabled */
discharge_disable();
@@ -225,8 +246,6 @@ void pd_transition_voltage(int idx)
MAX_CURRENT_FAST, 0);
}
}
- last_volt_idx = volt_idx;
- volt_idx = idx - 1;
set_output_voltage(voltages[volt_idx].select);
}
@@ -248,16 +267,21 @@ void pd_power_supply_reset(int port)
int need_discharge = (volt_idx > 0) || discharge_is_enabled();
output_disable();
- volt_idx = 0;
- set_output_voltage(VO_5V);
+ last_volt_idx = volt_idx;
+ /* from 20V : do an intermediate step at 12V */
+ volt_idx = volt_idx == PDO_IDX_20V ? PDO_IDX_12V : PDO_IDX_5V;
+ set_output_voltage(voltages[volt_idx].select);
/* TODO transition delay */
/* Stop OCP monitoring to save power */
adc_disable_watchdog();
/* discharge voltage to 5V ? */
- if (need_discharge)
- discharge_voltage(voltages[0].ovp);
+ if (need_discharge) {
+ /* final target : 5V */
+ discharge_volt_idx = PDO_IDX_5V;
+ discharge_voltage(voltages[volt_idx].ovp);
+ }
}
int pd_check_data_swap(int port, int data_role)
@@ -371,6 +395,9 @@ int pd_board_checks(void)
/* the discharge did not work properly */
if (discharge_is_enabled() &&
(get_time().val > discharge_deadline.val)) {
+ /* ensure we always finish a 2-step discharge */
+ volt_idx = discharge_volt_idx;
+ set_output_voltage(voltages[volt_idx].select);
/* stop it */
discharge_disable();
/* enable over-current monitoring */
@@ -402,10 +429,18 @@ void pd_adc_interrupt(void)
/* Clear flags */
STM32_ADC_ISR = 0x8e;
- if (discharge_is_enabled()) { /* discharge completed */
- discharge_disable();
- /* enable over-current monitoring */
- adc_enable_watchdog(ADC_CH_A_SENSE, MAX_CURRENT_FAST, 0);
+ if (discharge_is_enabled()) {
+ if (discharge_volt_idx != volt_idx) {
+ /* first step of the discharge completed: now 12V->5V */
+ volt_idx = PDO_IDX_5V;
+ set_output_voltage(VO_5V);
+ discharge_voltage(voltages[PDO_IDX_5V].ovp);
+ } else { /* discharge complete */
+ discharge_disable();
+ /* enable over-current monitoring */
+ adc_enable_watchdog(ADC_CH_A_SENSE,
+ MAX_CURRENT_FAST, 0);
+ }
} else {/* Over-current detection */
/* cut the power output */
pd_power_supply_reset(0);