summaryrefslogtreecommitdiff
path: root/common/charge_manager.c
diff options
context:
space:
mode:
Diffstat (limited to 'common/charge_manager.c')
-rw-r--r--common/charge_manager.c75
1 files changed, 55 insertions, 20 deletions
diff --git a/common/charge_manager.c b/common/charge_manager.c
index c884c05500..3cd3db2280 100644
--- a/common/charge_manager.c
+++ b/common/charge_manager.c
@@ -17,6 +17,12 @@
static struct charge_port_info available_charge[CHARGE_SUPPLIER_COUNT]
[PD_PORT_COUNT];
+/*
+ * Charge ceiling for ports. This can be set to temporarily limit the charge
+ * pulled from a port, without influencing the port selection logic.
+ */
+static int charge_ceil[PD_PORT_COUNT];
+
/* Store current state of port enable / charge current. */
static int charge_port = CHARGE_PORT_NONE;
static int charge_current = CHARGE_CURRENT_UNINITIALIZED;
@@ -30,13 +36,15 @@ static void charge_manager_init(void)
{
int i, j;
- for (i = 0; i < CHARGE_SUPPLIER_COUNT; ++i)
- for (j = 0; j < PD_PORT_COUNT; ++j) {
- available_charge[i][j].current =
+ for (i = 0; i < PD_PORT_COUNT; ++i) {
+ for (j = 0; j < CHARGE_SUPPLIER_COUNT; ++j) {
+ available_charge[j][i].current =
CHARGE_CURRENT_UNINITIALIZED;
- available_charge[i][j].voltage =
+ available_charge[j][i].voltage =
CHARGE_VOLTAGE_UNINITIALIZED;
}
+ charge_ceil[i] = CHARGE_CEIL_NONE;
+ }
}
DECLARE_HOOK(HOOK_INIT, charge_manager_init, HOOK_PRIO_DEFAULT-1);
@@ -73,7 +81,7 @@ static void charge_manager_refresh(void)
{
int new_supplier = CHARGE_SUPPLIER_NONE;
int new_port = CHARGE_PORT_NONE;
- int new_charge_current, new_charge_voltage, i, j;
+ int new_charge_current, new_charge_voltage, i, j, old_port;
/*
* Charge supplier selection logic:
@@ -103,11 +111,16 @@ static void charge_manager_refresh(void)
else {
new_charge_current =
available_charge[new_supplier][new_port].current;
+ /* Enforce port charge ceiling. */
+ if (charge_ceil[new_port] != CHARGE_CEIL_NONE &&
+ charge_ceil[new_port] < new_charge_current)
+ new_charge_current = charge_ceil[new_port];
+
new_charge_voltage =
available_charge[new_supplier][new_port].voltage;
}
- /* Change the charge limit + charge port if changed. */
+ /* Change the charge limit + charge port if modified. */
if (new_port != charge_port || new_charge_current != charge_current) {
CPRINTS("New charge limit: supplier %d port %d current %d "
"voltage %d", new_supplier, new_port,
@@ -117,7 +130,13 @@ static void charge_manager_refresh(void)
charge_current = new_charge_current;
charge_supplier = new_supplier;
+ old_port = charge_port;
charge_port = new_port;
+
+ if (new_port != CHARGE_PORT_NONE)
+ pd_set_new_power_request(new_port);
+ if (old_port != CHARGE_PORT_NONE)
+ pd_set_new_power_request(old_port);
}
}
DECLARE_DEFERRED(charge_manager_refresh);
@@ -126,27 +145,21 @@ DECLARE_DEFERRED(charge_manager_refresh);
* Update available charge for a given port / supplier.
*
* @param supplier Charge supplier to update.
- * @param charge_port Charge port to update.
+ * @param port Charge port to update.
* @param charge Charge port current / voltage.
*/
void charge_manager_update(int supplier,
- int charge_port,
+ int port,
struct charge_port_info *charge)
{
- if (supplier < 0 || supplier >= CHARGE_SUPPLIER_COUNT) {
- CPRINTS("Invalid charge supplier: %d", supplier);
- return;
- }
+ ASSERT(supplier >= 0 && supplier < CHARGE_SUPPLIER_COUNT);
+ ASSERT(port >= 0 && port < PD_PORT_COUNT);
/* Update charge table if needed. */
- if (available_charge[supplier][charge_port].current !=
- charge->current ||
- available_charge[supplier][charge_port].voltage !=
- charge->voltage) {
- available_charge[supplier][charge_port].current =
- charge->current;
- available_charge[supplier][charge_port].voltage =
- charge->voltage;
+ if (available_charge[supplier][port].current != charge->current ||
+ available_charge[supplier][port].voltage != charge->voltage) {
+ available_charge[supplier][port].current = charge->current;
+ available_charge[supplier][port].voltage = charge->voltage;
/*
* Don't call charge_manager_refresh unless all ports +
@@ -159,6 +172,28 @@ void charge_manager_update(int supplier,
}
}
+/**
+ * Update charge ceiling for a given port.
+ *
+ * @param port Charge port to update.
+ * @param ceil Charge ceiling (mA).
+ */
+void charge_manager_set_ceil(int port, int ceil)
+{
+ ASSERT(port >= 0 && port < PD_PORT_COUNT);
+
+ if (charge_ceil[port] != ceil) {
+ charge_ceil[port] = ceil;
+ if (port == charge_port && charge_manager_is_seeded())
+ hook_call_deferred(charge_manager_refresh, 0);
+ }
+}
+
+int charge_manager_get_active_charge_port(void)
+{
+ return charge_port;
+}
+
static int hc_pd_power_info(struct host_cmd_handler_args *args)
{
const struct ec_params_usb_pd_power_info *p = args->params;