pd: Limit input current to 500mA on PD voltage transition

Upon requesting a PD power contract at a new voltage, keep the input
current limit at 500mA until PD_RDY is received.

BUG=b:30744563,chrome-os-partner:59311,chrome-os-partner:44340
BRANCH=ryu, gru, glados
TEST=Manual on kevin, set ilim to 5V through `chglim` console command,
attach zinger. Set ilim to 20V through `chglim`, verify that ilim goes
from 3A to 500mA to 3A.

Signed-off-by: Shawn Nematbakhsh <shawnn@chromium.org>
Change-Id: I452f183cfb958780e336a9f99dc6398356de17a0
Reviewed-on: https://chromium-review.googlesource.com/399918
Commit-Ready: Shawn N <shawnn@chromium.org>
Tested-by: Shawn N <shawnn@chromium.org>
Reviewed-by: Todd Broch <tbroch@chromium.org>
Reviewed-by: Vincent Palatin <vpalatin@chromium.org>
This commit is contained in:
Shawn Nematbakhsh
2016-10-17 14:12:38 -07:00
committed by chrome-bot
parent d447b71f71
commit 64414f92b3
4 changed files with 47 additions and 3 deletions

View File

@@ -817,6 +817,25 @@ void charge_manager_set_ceil(int port, enum ceil_requestor requestor, int ceil)
}
}
void charge_manager_force_ceil(int port, int ceil)
{
ASSERT(port >= 0 && port < CONFIG_USB_PD_PORT_COUNT);
/*
* Force our input current to ceil if we're exceeding it, without
* waiting for our deferred task to run.
*/
if (port == charge_port && ceil < charge_current)
board_set_charge_limit(port, CHARGE_SUPPLIER_PD,
ceil, charge_current_uncapped);
/*
* Now inform charge_manager so it stays in sync with the state of
* the world.
*/
charge_manager_set_ceil(port, CEIL_REQUESTOR_PD, ceil);
}
/**
* Select an 'override port', a port which is always the preferred charge port.
* Returns EC_SUCCESS on success, ec_error_list status on failure.

View File

@@ -659,9 +659,16 @@ static int pd_send_request_msg(int port, int always_send_request)
*/
return -1;
/* Don't re-request the same voltage */
if (!always_send_request && pd[port].prev_request_mv == supply_voltage)
return EC_SUCCESS;
if (!always_send_request) {
/* Don't re-request the same voltage */
if (pd[port].prev_request_mv == supply_voltage)
return EC_SUCCESS;
#ifdef CONFIG_CHARGE_MANAGER
/* Limit current to PD_MIN_MA during transition */
else
charge_manager_force_ceil(port, PD_MIN_MA);
#endif
}
CPRINTF("Req C%d [%d] %dmV %dmA", port, RDO_POS(rdo),
supply_voltage, curr_limit);

View File

@@ -73,6 +73,16 @@ enum ceil_requestor {
/* Update charge ceiling for a given port / requestor */
void charge_manager_set_ceil(int port, enum ceil_requestor requestor, int ceil);
/*
* Update PD charge ceiling for a given port. In the event that our ceiling
* is currently above ceil, change the current limit before returning, without
* waiting for a charge manager refresh. This function should only be used in
* time-critical situations where we absolutely cannot proceed without limiting
* our input current, and it should only be called from the PD tasks.
* If you ever call this function then you are a terrible person.
*/
void charge_manager_force_ceil(int port, int ceil);
/* Select an 'override port', which is always the preferred charge port */
int charge_manager_set_override(int port);
int charge_manager_get_override(void);

View File

@@ -288,6 +288,14 @@ static int test_charge_ceil(void)
TEST_ASSERT(active_charge_port == 1);
TEST_ASSERT(active_charge_limit == 2500);
/* Verify forced ceil takes effect immediately */
charge_manager_force_ceil(1, 500);
TEST_ASSERT(active_charge_port == 1);
TEST_ASSERT(active_charge_limit == 500);
wait_for_charge_manager_refresh();
TEST_ASSERT(active_charge_port == 1);
TEST_ASSERT(active_charge_limit == 500);
return EC_SUCCESS;
}