mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2025-12-28 02:35:28 +00:00
charge_manager: Add module for managing battery charge limits
charge_manager is intended to manage charge limits from various tasks (typically PD charge tasks and USB / BC 1.2 charge tasks). These tasks can update the charge limit of a port by calling charge_manager_update (thread-safe function). If the charge limit has changed, charge_manager_refresh will be queued as a deferred task, which will select the "best" charge port and set the proper charge limit. In order to use charge_manager, a board needs to do the following: 1. Declare PD_PORT_COUNT in usb_pd_config.h 2. Implement board_set_charge_limit 3. Implement board_set_active_charge_port 4. Call charge_manager_update whenever the available charge on a port changes. BUG=chrome-os-partner:31361 TEST=Manual on samus_pd, with subsequent commit. Insert and remove various chargers, check console to verify PD charger always has priority and correct current limit is set based upon 'best' charger. BRANCH=samus Change-Id: Iede120b69e0b46ed329bcf9b7e07c39ba5e9f77b Signed-off-by: Shawn Nematbakhsh <shawnn@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/222723 Reviewed-by: Alec Berg <alecaberg@chromium.org>
This commit is contained in:
committed by
chrome-internal-fetch
parent
bcc5057ad3
commit
b8f73a451d
@@ -21,6 +21,7 @@ common-$(CONFIG_BATTERY_BQ27541)+=battery.o
|
||||
common-$(CONFIG_BATTERY_SMART)+=battery.o
|
||||
common-$(CONFIG_BUTTON_COUNT)+=button.o
|
||||
common-$(CONFIG_CAPSENSE)+=capsense.o
|
||||
common-$(CONFIG_CHARGE_MANAGER)+=charge_manager.o
|
||||
common-$(CONFIG_CHARGER)+=charger.o
|
||||
common-$(CONFIG_CHARGER_V1)+=charge_state_v1.o
|
||||
common-$(CONFIG_CHARGER_V2)+=charge_state_v2.o
|
||||
|
||||
151
common/charge_manager.c
Normal file
151
common/charge_manager.c
Normal file
@@ -0,0 +1,151 @@
|
||||
/* Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "charge_manager.h"
|
||||
#include "console.h"
|
||||
#include "hooks.h"
|
||||
#include "usb_pd_config.h"
|
||||
#include "util.h"
|
||||
|
||||
#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args)
|
||||
|
||||
/* Keep track of available charge for each charge port. */
|
||||
static struct charge_port_info available_charge[CHARGE_SUPPLIER_COUNT]
|
||||
[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;
|
||||
|
||||
/**
|
||||
* Initialize available charge. Run before board init, so board init can
|
||||
* initialize data, if needed.
|
||||
*/
|
||||
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 =
|
||||
CHARGE_CURRENT_UNINITIALIZED;
|
||||
available_charge[i][j].voltage =
|
||||
CHARGE_VOLTAGE_UNINITIALIZED;
|
||||
}
|
||||
}
|
||||
DECLARE_HOOK(HOOK_INIT, charge_manager_init, HOOK_PRIO_DEFAULT-1);
|
||||
|
||||
/**
|
||||
* Returns 1 if all ports + suppliers have reported in with some initial charge,
|
||||
* 0 otherwise.
|
||||
*/
|
||||
static int charge_manager_is_seeded(void)
|
||||
{
|
||||
/* Once we're seeded, we don't need to check again. */
|
||||
static int is_seeded;
|
||||
int i, j;
|
||||
|
||||
if (is_seeded)
|
||||
return 1;
|
||||
|
||||
for (i = 0; i < CHARGE_SUPPLIER_COUNT; ++i)
|
||||
for (j = 0; j < PD_PORT_COUNT; ++j)
|
||||
if (available_charge[i][j].current ==
|
||||
CHARGE_CURRENT_UNINITIALIZED ||
|
||||
available_charge[i][j].voltage ==
|
||||
CHARGE_VOLTAGE_UNINITIALIZED)
|
||||
return 0;
|
||||
|
||||
is_seeded = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Charge manager refresh -- responsible for selecting the active charge port
|
||||
* and charge power. Called as a deferred task.
|
||||
*/
|
||||
static void charge_manager_refresh(void)
|
||||
{
|
||||
enum charge_supplier new_supplier = CHARGE_SUPPLIER_NONE;
|
||||
int new_port = CHARGE_PORT_NONE;
|
||||
int new_charge_current, new_charge_voltage, i, j;
|
||||
|
||||
/*
|
||||
* Charge supplier selection logic:
|
||||
* 1. Prefer higher priority (lower CHARGE_SUPPLIER index) supply.
|
||||
* 2. Prefer higher power over lower.
|
||||
* available_charge can be changed at any time by other tasks,
|
||||
* so make no assumptions about its consistency.
|
||||
*/
|
||||
for (i = 0; i < CHARGE_SUPPLIER_COUNT; ++i)
|
||||
for (j = 0; j < PD_PORT_COUNT; ++j)
|
||||
if (available_charge[i][j].current > 0 &&
|
||||
available_charge[i][j].voltage > 0) {
|
||||
new_supplier = i;
|
||||
new_port = j;
|
||||
goto got_supplier;
|
||||
}
|
||||
|
||||
got_supplier:
|
||||
if (new_supplier != CHARGE_SUPPLIER_NONE)
|
||||
for (i = new_port + 1; i < PD_PORT_COUNT; ++i)
|
||||
if (POWER(available_charge[new_supplier][i]) >
|
||||
POWER(available_charge[new_supplier][new_port]))
|
||||
new_port = i;
|
||||
|
||||
if (new_supplier == CHARGE_SUPPLIER_NONE)
|
||||
new_charge_current = new_charge_voltage = 0;
|
||||
else {
|
||||
new_charge_current =
|
||||
available_charge[new_supplier][new_port].current;
|
||||
new_charge_voltage =
|
||||
available_charge[new_supplier][new_port].voltage;
|
||||
}
|
||||
|
||||
/* Change the charge limit + charge port if changed. */
|
||||
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,
|
||||
new_charge_current, new_charge_voltage);
|
||||
board_set_charge_limit(new_charge_current);
|
||||
board_set_active_charge_port(new_port);
|
||||
|
||||
charge_current = new_charge_current;
|
||||
charge_port = new_port;
|
||||
}
|
||||
}
|
||||
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 charge Charge port current / voltage.
|
||||
*/
|
||||
void charge_manager_update(enum charge_supplier supplier,
|
||||
int charge_port,
|
||||
struct charge_port_info *charge)
|
||||
{
|
||||
/* 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;
|
||||
|
||||
/*
|
||||
* Don't call charge_manager_refresh unless all ports +
|
||||
* suppliers have reported in. We don't want to make changes
|
||||
* to our charge port until we are certain we know what is
|
||||
* attached.
|
||||
*/
|
||||
if (charge_manager_is_seeded())
|
||||
hook_call_deferred(charge_manager_refresh, 0);
|
||||
}
|
||||
}
|
||||
38
include/charge_manager.h
Normal file
38
include/charge_manager.h
Normal file
@@ -0,0 +1,38 @@
|
||||
/* Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef __CHARGE_MANAGER_H
|
||||
#define __CHARGE_MANAGER_H
|
||||
|
||||
/* Charge port that indicates no active port */
|
||||
#define CHARGE_PORT_NONE -1
|
||||
/* Initial charge state */
|
||||
#define CHARGE_CURRENT_UNINITIALIZED -1
|
||||
#define CHARGE_VOLTAGE_UNINITIALIZED -1
|
||||
|
||||
#define POWER(charge_port) ((charge_port.current) * (charge_port.voltage))
|
||||
|
||||
/* Charge suppliers, sorted by priority */
|
||||
enum charge_supplier {
|
||||
CHARGE_SUPPLIER_NONE = -1,
|
||||
/* Highest priority supplier first */
|
||||
CHARGE_SUPPLIER_PD = 0,
|
||||
CHARGE_SUPPLIER_TYPEC = 1,
|
||||
CHARGE_SUPPLIER_BC12 = 2,
|
||||
CHARGE_SUPPLIER_COUNT
|
||||
};
|
||||
|
||||
/* Charge tasks report available current and voltage */
|
||||
struct charge_port_info {
|
||||
int current;
|
||||
int voltage;
|
||||
};
|
||||
|
||||
/* Called by charging tasks to update their available charge */
|
||||
void charge_manager_update(enum charge_supplier supplier,
|
||||
int charge_port,
|
||||
struct charge_port_info *charge);
|
||||
|
||||
#endif /* __CHARGE_MANAGER_H */
|
||||
Reference in New Issue
Block a user