mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2026-01-09 17:11:42 +00:00
pd: charge_manager: make new VBUS charge supplier
Make new VBUS charge supplier for Samus and Ryu which allows default 500mA charging when VBUS is present. Before this was accomplished via the type-C supplier, but type-C supplier should only be used for 1.5A and 3A pull-up. VBUS supplier is lowest priority so that any other supplier will take precedence over the default charging rate. This work is done in preparation for charge_ramp module where we don't want to ramp for typeC supplier. BUG=chrome-os-partner:34946 BRANCH=samus TEST=make sure we can boot without battery on samus, and test other chargers including legacy chargers, zinger, and donette. Change-Id: I89f1e9520e4bf9e5debbaf8dd2de1262154eecf8 Signed-off-by: Alec Berg <alecaberg@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/250312 Reviewed-by: Shawn N <shawnn@chromium.org>
This commit is contained in:
committed by
ChromeOS Commit Bot
parent
f41d33b1d7
commit
ac5f11bf84
@@ -33,6 +33,9 @@
|
||||
|
||||
#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args)
|
||||
|
||||
/* Default input current limit when VBUS is present */
|
||||
#define DEFAULT_CURR_LIMIT 500 /* mA */
|
||||
|
||||
static void vbus_log(void)
|
||||
{
|
||||
CPRINTS("VBUS %d", gpio_get_level(GPIO_CHGR_ACOK));
|
||||
@@ -41,6 +44,19 @@ DECLARE_DEFERRED(vbus_log);
|
||||
|
||||
void vbus_evt(enum gpio_signal signal)
|
||||
{
|
||||
struct charge_port_info charge;
|
||||
int vbus_level = gpio_get_level(signal);
|
||||
|
||||
/*
|
||||
* If VBUS is low, or VBUS is high and we are not outputting VBUS
|
||||
* ourselves, then update the VBUS supplier.
|
||||
*/
|
||||
if (!vbus_level || !gpio_get_level(GPIO_USBC_5V_EN)) {
|
||||
charge.voltage = USB_BC12_CHARGE_VOLTAGE;
|
||||
charge.current = vbus_level ? DEFAULT_CURR_LIMIT : 0;
|
||||
charge_manager_update_charge(CHARGE_SUPPLIER_VBUS, 0, &charge);
|
||||
}
|
||||
|
||||
hook_call_deferred(vbus_log, 0);
|
||||
if (task_start_called())
|
||||
task_wake(TASK_ID_PD);
|
||||
@@ -163,18 +179,28 @@ BUILD_ASSERT(ARRAY_SIZE(usb_strings) == USB_STR_COUNT);
|
||||
/* Initialize board. */
|
||||
static void board_init(void)
|
||||
{
|
||||
struct charge_port_info charge;
|
||||
struct charge_port_info charge_none, charge_vbus;
|
||||
|
||||
/* Initialize all pericom charge suppliers to 0 */
|
||||
charge.voltage = USB_BC12_CHARGE_VOLTAGE;
|
||||
charge.current = 0;
|
||||
charge_none.voltage = USB_BC12_CHARGE_VOLTAGE;
|
||||
charge_none.current = 0;
|
||||
charge_manager_update_charge(CHARGE_SUPPLIER_PROPRIETARY,
|
||||
0,
|
||||
&charge);
|
||||
charge_manager_update_charge(CHARGE_SUPPLIER_BC12_CDP, 0, &charge);
|
||||
charge_manager_update_charge(CHARGE_SUPPLIER_BC12_DCP, 0, &charge);
|
||||
charge_manager_update_charge(CHARGE_SUPPLIER_BC12_SDP, 0, &charge);
|
||||
charge_manager_update_charge(CHARGE_SUPPLIER_OTHER, 0, &charge);
|
||||
&charge_none);
|
||||
charge_manager_update_charge(CHARGE_SUPPLIER_BC12_CDP, 0, &charge_none);
|
||||
charge_manager_update_charge(CHARGE_SUPPLIER_BC12_DCP, 0, &charge_none);
|
||||
charge_manager_update_charge(CHARGE_SUPPLIER_BC12_SDP, 0, &charge_none);
|
||||
charge_manager_update_charge(CHARGE_SUPPLIER_OTHER, 0, &charge_none);
|
||||
|
||||
/* Initialize VBUS supplier based on whether or not VBUS is present */
|
||||
charge_vbus.voltage = USB_BC12_CHARGE_VOLTAGE;
|
||||
charge_vbus.current = DEFAULT_CURR_LIMIT;
|
||||
if (gpio_get_level(GPIO_CHGR_ACOK))
|
||||
charge_manager_update_charge(CHARGE_SUPPLIER_VBUS, 0,
|
||||
&charge_vbus);
|
||||
else
|
||||
charge_manager_update_charge(CHARGE_SUPPLIER_VBUS, 0,
|
||||
&charge_none);
|
||||
|
||||
/* Enable pericom BC1.2 interrupts. */
|
||||
gpio_enable_interrupt(GPIO_USBC_BC12_INT_L);
|
||||
@@ -230,7 +256,8 @@ const int supplier_priority[] = {
|
||||
[CHARGE_SUPPLIER_BC12_DCP] = 1,
|
||||
[CHARGE_SUPPLIER_BC12_CDP] = 2,
|
||||
[CHARGE_SUPPLIER_BC12_SDP] = 3,
|
||||
[CHARGE_SUPPLIER_OTHER] = 3
|
||||
[CHARGE_SUPPLIER_OTHER] = 3,
|
||||
[CHARGE_SUPPLIER_VBUS] = 4
|
||||
};
|
||||
BUILD_ASSERT(ARRAY_SIZE(supplier_priority) == CHARGE_SUPPLIER_COUNT);
|
||||
|
||||
@@ -333,9 +360,10 @@ DECLARE_DEFERRED(board_charge_manager_override_timeout);
|
||||
int board_set_active_charge_port(int charge_port)
|
||||
{
|
||||
int ret = EC_SUCCESS;
|
||||
/* check if we are source vbus on that port */
|
||||
int source = gpio_get_level(GPIO_USBC_5V_EN);
|
||||
|
||||
if (charge_port >= 0 && charge_port < PD_PORT_COUNT &&
|
||||
pd_get_role(charge_port) != PD_ROLE_SINK) {
|
||||
if (charge_port >= 0 && charge_port < PD_PORT_COUNT && source) {
|
||||
CPRINTS("Port %d is not a sink, skipping enable", charge_port);
|
||||
charge_port = CHARGE_PORT_NONE;
|
||||
ret = EC_ERROR_INVAL;
|
||||
|
||||
@@ -140,6 +140,7 @@ enum charge_supplier {
|
||||
CHARGE_SUPPLIER_BC12_SDP,
|
||||
CHARGE_SUPPLIER_PROPRIETARY,
|
||||
CHARGE_SUPPLIER_OTHER,
|
||||
CHARGE_SUPPLIER_VBUS,
|
||||
CHARGE_SUPPLIER_COUNT
|
||||
};
|
||||
|
||||
|
||||
@@ -32,6 +32,9 @@
|
||||
/* Amount to offset the input current limit when sending to EC */
|
||||
#define INPUT_CURRENT_LIMIT_OFFSET_MA 192
|
||||
|
||||
/* Default input current limit when VBUS is present */
|
||||
#define DEFAULT_CURR_LIMIT 500 /* mA */
|
||||
|
||||
/* Chipset power state */
|
||||
static enum power_state ps;
|
||||
|
||||
@@ -66,7 +69,8 @@ const int supplier_priority[] = {
|
||||
[CHARGE_SUPPLIER_BC12_DCP] = 1,
|
||||
[CHARGE_SUPPLIER_BC12_CDP] = 2,
|
||||
[CHARGE_SUPPLIER_BC12_SDP] = 3,
|
||||
[CHARGE_SUPPLIER_OTHER] = 3
|
||||
[CHARGE_SUPPLIER_OTHER] = 3,
|
||||
[CHARGE_SUPPLIER_VBUS] = 4
|
||||
};
|
||||
BUILD_ASSERT(ARRAY_SIZE(supplier_priority) == CHARGE_SUPPLIER_COUNT);
|
||||
|
||||
@@ -86,6 +90,19 @@ DECLARE_DEFERRED(pericom_port1_reenable_interrupts);
|
||||
|
||||
void vbus0_evt(enum gpio_signal signal)
|
||||
{
|
||||
struct charge_port_info charge;
|
||||
int vbus_level = gpio_get_level(signal);
|
||||
|
||||
/*
|
||||
* If VBUS is low, or VBUS is high and we are not outputting VBUS
|
||||
* ourselves, then update the VBUS supplier.
|
||||
*/
|
||||
if (!vbus_level || !gpio_get_level(GPIO_USB_C0_5V_EN)) {
|
||||
charge.voltage = USB_BC12_CHARGE_VOLTAGE;
|
||||
charge.current = vbus_level ? DEFAULT_CURR_LIMIT : 0;
|
||||
charge_manager_update_charge(CHARGE_SUPPLIER_VBUS, 0, &charge);
|
||||
}
|
||||
|
||||
/*
|
||||
* Re-enable interrupts on pericom charger detector since the
|
||||
* chip may periodically reset itself, and come back up with
|
||||
@@ -99,6 +116,19 @@ void vbus0_evt(enum gpio_signal signal)
|
||||
|
||||
void vbus1_evt(enum gpio_signal signal)
|
||||
{
|
||||
struct charge_port_info charge;
|
||||
int vbus_level = gpio_get_level(signal);
|
||||
|
||||
/*
|
||||
* If VBUS is low, or VBUS is high and we are not outputting VBUS
|
||||
* ourselves, then update the VBUS supplier.
|
||||
*/
|
||||
if (!vbus_level || !gpio_get_level(GPIO_USB_C1_5V_EN)) {
|
||||
charge.voltage = USB_BC12_CHARGE_VOLTAGE;
|
||||
charge.current = vbus_level ? DEFAULT_CURR_LIMIT : 0;
|
||||
charge_manager_update_charge(CHARGE_SUPPLIER_VBUS, 1, &charge);
|
||||
}
|
||||
|
||||
/*
|
||||
* Re-enable interrupts on pericom charger detector since the
|
||||
* chip may periodically reset itself, and come back up with
|
||||
@@ -359,7 +389,7 @@ static void board_init(void)
|
||||
int pd_enable, i;
|
||||
int slp_s5 = gpio_get_level(GPIO_PCH_SLP_S5_L);
|
||||
int slp_s3 = gpio_get_level(GPIO_PCH_SLP_S3_L);
|
||||
struct charge_port_info charge;
|
||||
struct charge_port_info charge_none, charge_vbus;
|
||||
|
||||
/*
|
||||
* Enable CC lines after all GPIO have been initialized. Note, it is
|
||||
@@ -373,26 +403,43 @@ static void board_init(void)
|
||||
gpio_enable_interrupt(GPIO_USB_C1_VBUS_WAKE);
|
||||
|
||||
/* Initialize all pericom charge suppliers to 0 */
|
||||
charge.voltage = USB_BC12_CHARGE_VOLTAGE;
|
||||
charge.current = 0;
|
||||
charge_none.voltage = USB_BC12_CHARGE_VOLTAGE;
|
||||
charge_none.current = 0;
|
||||
for (i = 0; i < PD_PORT_COUNT; i++) {
|
||||
charge_manager_update_charge(CHARGE_SUPPLIER_PROPRIETARY,
|
||||
i,
|
||||
&charge);
|
||||
&charge_none);
|
||||
charge_manager_update_charge(CHARGE_SUPPLIER_BC12_CDP,
|
||||
i,
|
||||
&charge);
|
||||
&charge_none);
|
||||
charge_manager_update_charge(CHARGE_SUPPLIER_BC12_DCP,
|
||||
i,
|
||||
&charge);
|
||||
&charge_none);
|
||||
charge_manager_update_charge(CHARGE_SUPPLIER_BC12_SDP,
|
||||
i,
|
||||
&charge);
|
||||
&charge_none);
|
||||
charge_manager_update_charge(CHARGE_SUPPLIER_OTHER,
|
||||
i,
|
||||
&charge);
|
||||
&charge_none);
|
||||
}
|
||||
|
||||
/* Initialize VBUS supplier based on whether or not VBUS is present */
|
||||
charge_vbus.voltage = USB_BC12_CHARGE_VOLTAGE;
|
||||
charge_vbus.current = DEFAULT_CURR_LIMIT;
|
||||
if (gpio_get_level(GPIO_USB_C0_VBUS_WAKE))
|
||||
charge_manager_update_charge(CHARGE_SUPPLIER_VBUS, 0,
|
||||
&charge_vbus);
|
||||
else
|
||||
charge_manager_update_charge(CHARGE_SUPPLIER_VBUS, 0,
|
||||
&charge_none);
|
||||
|
||||
if (gpio_get_level(GPIO_USB_C1_VBUS_WAKE))
|
||||
charge_manager_update_charge(CHARGE_SUPPLIER_VBUS, 1,
|
||||
&charge_vbus);
|
||||
else
|
||||
charge_manager_update_charge(CHARGE_SUPPLIER_VBUS, 1,
|
||||
&charge_none);
|
||||
|
||||
/* Enable pericom BC1.2 interrupts. */
|
||||
gpio_enable_interrupt(GPIO_USB_C0_BC12_INT_L);
|
||||
gpio_enable_interrupt(GPIO_USB_C1_BC12_INT_L);
|
||||
@@ -621,8 +668,11 @@ int board_set_active_charge_port(int charge_port)
|
||||
{
|
||||
/* charge port is a realy physical port */
|
||||
int is_real_port = (charge_port >= 0 && charge_port < PD_PORT_COUNT);
|
||||
/* check if we are source vbus on that port */
|
||||
int source = gpio_get_level(charge_port == 0 ? GPIO_USB_C0_5V_EN :
|
||||
GPIO_USB_C1_5V_EN);
|
||||
|
||||
if (is_real_port && pd_get_role(charge_port) != PD_ROLE_SINK) {
|
||||
if (is_real_port && source) {
|
||||
CPRINTS("Skip enable p%d", charge_port);
|
||||
return EC_ERROR_INVAL;
|
||||
}
|
||||
|
||||
@@ -107,6 +107,7 @@ enum charge_supplier {
|
||||
CHARGE_SUPPLIER_BC12_SDP,
|
||||
CHARGE_SUPPLIER_PROPRIETARY,
|
||||
CHARGE_SUPPLIER_OTHER,
|
||||
CHARGE_SUPPLIER_VBUS,
|
||||
CHARGE_SUPPLIER_COUNT
|
||||
};
|
||||
|
||||
|
||||
@@ -228,7 +228,6 @@ static int pd_src_cap_cnt[PD_PORT_COUNT];
|
||||
#define PD_FLAGS_PREVIOUS_PD_CONN (1 << 8) /* previously PD connected */
|
||||
#define PD_FLAGS_CHECK_PR_ROLE (1 << 9) /* check power role in READY */
|
||||
#define PD_FLAGS_CHECK_DR_ROLE (1 << 10)/* check data role in READY */
|
||||
#define PD_FLAGS_VBUS_PRESENT (1 << 11)/* vbus present in sink disconn. */
|
||||
/* Flags to clear on a disconnect */
|
||||
#define PD_FLAGS_RESET_ON_DISCONNECT_MASK (PD_FLAGS_PARTNER_DR_POWER | \
|
||||
PD_FLAGS_PARTNER_DR_DATA | \
|
||||
@@ -238,8 +237,7 @@ static int pd_src_cap_cnt[PD_PORT_COUNT];
|
||||
PD_FLAGS_EXPLICIT_CONTRACT | \
|
||||
PD_FLAGS_PREVIOUS_PD_CONN | \
|
||||
PD_FLAGS_CHECK_PR_ROLE | \
|
||||
PD_FLAGS_CHECK_DR_ROLE | \
|
||||
PD_FLAGS_VBUS_PRESENT)
|
||||
PD_FLAGS_CHECK_DR_ROLE)
|
||||
|
||||
static struct pd_protocol {
|
||||
/* current port power role (SOURCE or SINK) */
|
||||
@@ -387,14 +385,12 @@ static inline void set_state(int port, enum pd_states next_state)
|
||||
#ifdef CONFIG_USB_PD_DUAL_ROLE
|
||||
if (next_state == PD_STATE_SRC_DISCONNECTED ||
|
||||
next_state == PD_STATE_SNK_DISCONNECTED) {
|
||||
if (pd[port].flags & PD_FLAGS_VBUS_PRESENT) {
|
||||
/* Clear the input current limit */
|
||||
pd_set_input_current_limit(port, 0, 0);
|
||||
/* Clear the input current limit */
|
||||
pd_set_input_current_limit(port, 0, 0);
|
||||
#ifdef CONFIG_CHARGE_MANAGER
|
||||
typec_set_input_current_limit(port, 0, 0);
|
||||
charge_manager_set_ceil(port, CHARGE_CEIL_NONE);
|
||||
typec_set_input_current_limit(port, 0, 0);
|
||||
charge_manager_set_ceil(port, CHARGE_CEIL_NONE);
|
||||
#endif
|
||||
}
|
||||
#else /* CONFIG_USB_PD_DUAL_ROLE */
|
||||
if (next_state == PD_STATE_SRC_DISCONNECTED) {
|
||||
#endif
|
||||
@@ -1134,7 +1130,6 @@ static void handle_ctrl_request(int port, uint16_t head,
|
||||
/* reset message ID and swap roles */
|
||||
pd[port].msg_id = 0;
|
||||
pd[port].power_role = PD_ROLE_SINK;
|
||||
pd[port].flags |= PD_FLAGS_VBUS_PRESENT;
|
||||
set_state(port, PD_STATE_SNK_DISCOVERY);
|
||||
} else if (pd[port].task_state == PD_STATE_SNK_DISCOVERY) {
|
||||
/* Don't know what power source is ready. Reset. */
|
||||
@@ -1714,8 +1709,6 @@ static inline int get_typec_current_limit(int cc_voltage)
|
||||
charge = 3000;
|
||||
else if (cc_voltage > TYPE_C_SRC_1500_THRESHOLD)
|
||||
charge = 1500;
|
||||
else if (cc_voltage > PD_SNK_VA)
|
||||
charge = 500;
|
||||
else
|
||||
charge = 0;
|
||||
|
||||
@@ -1798,19 +1791,10 @@ void pd_task(void)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_CHARGE_MANAGER
|
||||
/* Initialize PD supplier current limit to 0 */
|
||||
/* Initialize PD and type-C supplier current limits to 0 */
|
||||
pd_set_input_current_limit(port, 0, 0);
|
||||
typec_set_input_current_limit(port, 0, 0);
|
||||
charge_manager_update_dualrole(port, CAP_UNKNOWN);
|
||||
#ifdef CONFIG_USB_PD_DUAL_ROLE
|
||||
/* If sink, set initial type-C current limit based on vbus */
|
||||
if (pd_snk_is_vbus_provided(port)) {
|
||||
typec_set_input_current_limit(port, 500, TYPE_C_VOLTAGE);
|
||||
pd[port].flags |= PD_FLAGS_VBUS_PRESENT;
|
||||
} else {
|
||||
typec_set_input_current_limit(port, 0, 0);
|
||||
pd[port].flags &= ~PD_FLAGS_VBUS_PRESENT;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
while (1) {
|
||||
@@ -2303,24 +2287,6 @@ void pd_task(void)
|
||||
case PD_STATE_SNK_DISCONNECTED:
|
||||
timeout = 10*MSEC;
|
||||
|
||||
#ifdef CONFIG_CHARGE_MANAGER
|
||||
/*
|
||||
* If VBUS, use default 500mA limit, otherwise
|
||||
* set current limit to 0. This is necessary for
|
||||
* an accessory that provides power with no Rp.
|
||||
*/
|
||||
if (pd_snk_is_vbus_provided(port) &&
|
||||
!(pd[port].flags & PD_FLAGS_VBUS_PRESENT)) {
|
||||
typec_set_input_current_limit(port, 500,
|
||||
TYPE_C_VOLTAGE);
|
||||
pd[port].flags |= PD_FLAGS_VBUS_PRESENT;
|
||||
} else if (!pd_snk_is_vbus_provided(port) &&
|
||||
(pd[port].flags & PD_FLAGS_VBUS_PRESENT)) {
|
||||
typec_set_input_current_limit(port, 0, 0);
|
||||
pd[port].flags &= ~PD_FLAGS_VBUS_PRESENT;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Source connection monitoring */
|
||||
cc1_volt = pd_adc_read(port, 0);
|
||||
cc2_volt = pd_adc_read(port, 1);
|
||||
@@ -2385,8 +2351,7 @@ void pd_task(void)
|
||||
port, typec_curr, TYPE_C_VOLTAGE);
|
||||
#endif
|
||||
pd[port].flags |= PD_FLAGS_CHECK_PR_ROLE |
|
||||
PD_FLAGS_CHECK_DR_ROLE |
|
||||
PD_FLAGS_VBUS_PRESENT;
|
||||
PD_FLAGS_CHECK_DR_ROLE;
|
||||
set_state(port, PD_STATE_SNK_DISCOVERY);
|
||||
timeout = 10*MSEC;
|
||||
hook_call_deferred(
|
||||
|
||||
Reference in New Issue
Block a user