charger: Move USB charger / BC1.2 task to common code

Move the task responsible for detection of USB chargers to common code
to reduce code duplication.

BUG=chrome-os-partner:40920
TEST=Manual on samus_pd. Plug USB charger, verify detection is correct
on both charge ports.
BRANCH=None

Change-Id: I362f8b5b51741509e459c66928131f1f6d2a3b1d
Signed-off-by: Shawn Nematbakhsh <shawnn@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/276210
Reviewed-by: Vincent Palatin <vpalatin@chromium.org>
Reviewed-by: Alec Berg <alecaberg@chromium.org>
This commit is contained in:
Shawn Nematbakhsh
2015-06-08 13:58:47 -07:00
committed by ChromeOS Commit Bot
parent 5d7c4f0cd6
commit e05ed041cf
24 changed files with 239 additions and 523 deletions

View File

@@ -36,7 +36,6 @@
/* Default input current limit when VBUS is present */
#define DEFAULT_CURR_LIMIT 500 /* mA */
#define USB_BC12_CHARGE_VOLTAGE 5000 /* mV */
/* Exchange status with PD MCU. */
static void pd_mcu_interrupt(enum gpio_signal signal)
@@ -99,19 +98,6 @@ const struct i2c_port_t i2c_ports[] = {
};
const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports);
/* Charge supplier priority: lower number indicates higher priority. */
const int supplier_priority[] = {
[CHARGE_SUPPLIER_PD] = 0,
[CHARGE_SUPPLIER_TYPEC] = 1,
[CHARGE_SUPPLIER_PROPRIETARY] = 1,
[CHARGE_SUPPLIER_BC12_DCP] = 1,
[CHARGE_SUPPLIER_BC12_CDP] = 2,
[CHARGE_SUPPLIER_BC12_SDP] = 3,
[CHARGE_SUPPLIER_OTHER] = 3,
[CHARGE_SUPPLIER_VBUS] = 4
};
BUILD_ASSERT(ARRAY_SIZE(supplier_priority) == CHARGE_SUPPLIER_COUNT);
/**
* Discharge battery when on AC power for factory test.
*/

View File

@@ -96,22 +96,6 @@ enum power_signal {
POWER_SIGNAL_COUNT
};
/* Charge suppliers */
enum charge_supplier {
CHARGE_SUPPLIER_PD,
CHARGE_SUPPLIER_TYPEC,
CHARGE_SUPPLIER_BC12_DCP,
CHARGE_SUPPLIER_BC12_CDP,
CHARGE_SUPPLIER_BC12_SDP,
CHARGE_SUPPLIER_PROPRIETARY,
CHARGE_SUPPLIER_OTHER,
CHARGE_SUPPLIER_VBUS,
CHARGE_SUPPLIER_COUNT
};
/* supplier_priority table defined in board.c */
extern const int supplier_priority[];
/* start as a sink in case we have no other power supply/battery */
#define PD_DEFAULT_STATE PD_STATE_SNK_DISCONNECTED

View File

@@ -39,8 +39,8 @@ enum adc_channel {
ADC_CH_COUNT
};
/* Charge suppliers */
enum charge_supplier {
/* Fake test charge suppliers */
enum {
CHARGE_SUPPLIER_TEST1,
CHARGE_SUPPLIER_TEST2,
CHARGE_SUPPLIER_TEST3,
@@ -49,11 +49,10 @@ enum charge_supplier {
CHARGE_SUPPLIER_TEST6,
CHARGE_SUPPLIER_TEST7,
CHARGE_SUPPLIER_TEST8,
CHARGE_SUPPLIER_TEST9,
CHARGE_SUPPLIER_COUNT
CHARGE_SUPPLIER_TEST_COUNT
};
/* supplier_priority table defined in board.c */
/* Custom charge_manager priority table is defined in test code */
extern const int supplier_priority[];
/* Standard-current Rp */

View File

@@ -40,7 +40,6 @@
/* Default input current limit when VBUS is present */
#define DEFAULT_CURR_LIMIT 500 /* mA */
#define USB_BC12_CHARGE_VOLTAGE 5000 /* mV */
static void ap_reset_deferred(void)
{
@@ -109,19 +108,6 @@ const struct i2c_port_t i2c_ports[] = {
const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports);
/* Charge supplier priority: lower number indicates higher priority. */
const int supplier_priority[] = {
[CHARGE_SUPPLIER_PD] = 0,
[CHARGE_SUPPLIER_TYPEC] = 1,
[CHARGE_SUPPLIER_PROPRIETARY] = 1,
[CHARGE_SUPPLIER_BC12_DCP] = 1,
[CHARGE_SUPPLIER_BC12_CDP] = 2,
[CHARGE_SUPPLIER_BC12_SDP] = 3,
[CHARGE_SUPPLIER_OTHER] = 3,
[CHARGE_SUPPLIER_VBUS] = 4
};
BUILD_ASSERT(ARRAY_SIZE(supplier_priority) == CHARGE_SUPPLIER_COUNT);
static int discharging_on_ac;
/**

View File

@@ -138,22 +138,6 @@ enum adc_channel {
ADC_CH_COUNT
};
/* Charge suppliers */
enum charge_supplier {
CHARGE_SUPPLIER_PD,
CHARGE_SUPPLIER_TYPEC,
CHARGE_SUPPLIER_BC12_DCP,
CHARGE_SUPPLIER_BC12_CDP,
CHARGE_SUPPLIER_BC12_SDP,
CHARGE_SUPPLIER_PROPRIETARY,
CHARGE_SUPPLIER_OTHER,
CHARGE_SUPPLIER_VBUS,
CHARGE_SUPPLIER_COUNT
};
/* supplier_priority table defined in board.c */
extern const int supplier_priority[];
/* start as a sink in case we have no other power supply/battery */
#define PD_DEFAULT_STATE PD_STATE_SNK_DISCONNECTED

View File

@@ -91,113 +91,9 @@ void vbus_evt(enum gpio_signal signal)
task_wake(TASK_ID_PD);
}
/* Wait 200ms after a charger is detected to debounce pin contact order */
#define USB_CHG_DEBOUNCE_DELAY_MS 200
/*
* Wait 100ms after reset, before re-enabling attach interrupt, so that the
* spurious attach interrupt from certain ports is ignored.
*/
#define USB_CHG_RESET_DELAY_MS 100
void usb_charger_task(void)
{
int device_type, charger_status;
struct charge_port_info charge;
int type;
charge.voltage = USB_BC12_CHARGE_VOLTAGE;
while (1) {
/* Read interrupt register to clear */
pi3usb9281_get_interrupts(0);
/* Set device type */
device_type = pi3usb9281_get_device_type(0);
charger_status = pi3usb9281_get_charger_status(0);
/* Debounce pin plug order if we detect a charger */
if (device_type || PI3USB9281_CHG_STATUS_ANY(charger_status)) {
msleep(USB_CHG_DEBOUNCE_DELAY_MS);
/* Trigger chip reset to refresh detection registers */
pi3usb9281_reset(0);
/*
* Restore data switch settings - switches return to
* closed on reset until restored.
*/
if (usb_switch_state)
pi3usb9281_set_switches(0, 1);
/* Clear possible disconnect interrupt */
pi3usb9281_get_interrupts(0);
/* Mask attach interrupt */
pi3usb9281_set_interrupt_mask(0,
0xff &
~PI3USB9281_INT_ATTACH);
/* Re-enable interrupts */
pi3usb9281_enable_interrupts(0);
msleep(USB_CHG_RESET_DELAY_MS);
/* Clear possible attach interrupt */
pi3usb9281_get_interrupts(0);
/* Re-enable attach interrupt */
pi3usb9281_set_interrupt_mask(0, 0xff);
/* Re-read ID registers */
device_type = pi3usb9281_get_device_type(0);
charger_status = pi3usb9281_get_charger_status(0);
}
if (PI3USB9281_CHG_STATUS_ANY(charger_status))
type = CHARGE_SUPPLIER_PROPRIETARY;
else if (device_type & PI3USB9281_TYPE_CDP)
type = CHARGE_SUPPLIER_BC12_CDP;
else if (device_type & PI3USB9281_TYPE_DCP)
type = CHARGE_SUPPLIER_BC12_DCP;
else if (device_type & PI3USB9281_TYPE_SDP)
type = CHARGE_SUPPLIER_BC12_SDP;
else
type = CHARGE_SUPPLIER_OTHER;
/* Attachment: decode + update available charge */
if (device_type || PI3USB9281_CHG_STATUS_ANY(charger_status)) {
charge.current = pi3usb9281_get_ilim(device_type,
charger_status);
charge_manager_update_charge(type, 0, &charge);
} else { /* Detachment: update available charge to 0 */
charge.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);
}
/* notify host of power info change */
pd_send_host_event(PD_EVENT_POWER_CHANGE);
/* Wait for interrupt */
task_wait_event(-1);
}
}
void usb_evt(enum gpio_signal signal)
{
task_wake(TASK_ID_USB_CHG);
task_wake(TASK_ID_USB_CHG_P0);
}
#include "gpio_list.h"
@@ -343,19 +239,6 @@ const struct adc_t adc_channels[] = {
};
BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT);
/* Charge supplier priority: lower number indicates higher priority. */
const int supplier_priority[] = {
[CHARGE_SUPPLIER_PD] = 0,
[CHARGE_SUPPLIER_TYPEC] = 1,
[CHARGE_SUPPLIER_PROPRIETARY] = 1,
[CHARGE_SUPPLIER_BC12_DCP] = 1,
[CHARGE_SUPPLIER_BC12_CDP] = 2,
[CHARGE_SUPPLIER_BC12_SDP] = 3,
[CHARGE_SUPPLIER_OTHER] = 3,
[CHARGE_SUPPLIER_VBUS] = 4
};
BUILD_ASSERT(ARRAY_SIZE(supplier_priority) == CHARGE_SUPPLIER_COUNT);
/* I2C ports */
const struct i2c_port_t i2c_ports[] = {
{"master", I2C_PORT_MASTER, 100,
@@ -428,14 +311,15 @@ struct motion_sensor_t motion_sensors[] = {
};
const unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors);
static void board_set_usb_switches(int port, int open)
void board_set_usb_switches(int port, enum usb_switch setting)
{
/* If switch is not changing, then return */
if (open == usb_switch_state)
if (setting == usb_switch_state)
return;
usb_switch_state = open;
pi3usb9281_set_switches(port, open);
if (setting != USB_SWITCH_RESTORE)
usb_switch_state = setting;
pi3usb9281_set_switches(port, usb_switch_state);
}
void board_set_usb_mux(int port, enum typec_mux mux,

View File

@@ -23,6 +23,7 @@
#define CONFIG_CHARGE_MANAGER
#define CONFIG_FORCE_CONSOLE_RESUME
#define CONFIG_STM_HWTIMER32
#define CONFIG_USB_CHARGER
#define CONFIG_USB_POWER_DELIVERY
#define CONFIG_USB_PD_ALT_MODE
#define CONFIG_USB_PD_ALT_MODE_DFP
@@ -168,22 +169,6 @@ enum adc_channel {
ADC_CH_COUNT
};
/* Charge suppliers */
enum charge_supplier {
CHARGE_SUPPLIER_PD,
CHARGE_SUPPLIER_TYPEC,
CHARGE_SUPPLIER_BC12_DCP,
CHARGE_SUPPLIER_BC12_CDP,
CHARGE_SUPPLIER_BC12_SDP,
CHARGE_SUPPLIER_PROPRIETARY,
CHARGE_SUPPLIER_OTHER,
CHARGE_SUPPLIER_VBUS,
CHARGE_SUPPLIER_COUNT
};
/* supplier_priority table defined in board.c */
extern const int supplier_priority[];
/* USB string indexes */
enum usb_strings {
USB_STR_DESC = 0,
@@ -197,6 +182,9 @@ enum usb_strings {
USB_STR_COUNT
};
/* VBUS enable GPIO */
#define GPIO_USB_C0_5V_EN GPIO_CHGR_OTG
/* 1.5A Rp */
#define PD_SRC_VNC PD_SRC_1_5_VNC_MV
#define PD_SRC_RD_THRESHOLD PD_SRC_1_5_RD_THRESH_MV
@@ -226,9 +214,6 @@ int board_discharge_on_ac(int enable);
/* Set the charge current limit. */
void board_set_charge_limit(int charge_ma);
/* Send host event to AP */
void pd_send_host_event(int mask);
/* PP1800 transition GPIO interrupt handler */
void pp1800_on_off_evt(enum gpio_signal signal);

View File

@@ -18,7 +18,8 @@
*/
#define CONFIG_TASK_LIST \
TASK_ALWAYS(HOOKS, hook_task, NULL, LARGER_TASK_STACK_SIZE) \
TASK_ALWAYS(USB_CHG, usb_charger_task, NULL, SMALLER_TASK_STACK_SIZE) \
TASK_ALWAYS(USB_CHG_P0, usb_charger_task, NULL, \
SMALLER_TASK_STACK_SIZE) \
TASK_NOTEST(LIGHTBAR, lightbar_task, NULL, LARGER_TASK_STACK_SIZE) \
TASK_ALWAYS(CHARGER, charger_task, NULL, TASK_STACK_SIZE) \
TASK_NOTEST(MOTIONSENSE, motion_sense_task, NULL, TASK_STACK_SIZE) \

View File

@@ -89,113 +89,9 @@ void vbus_evt(enum gpio_signal signal)
task_wake(TASK_ID_PD);
}
/* Wait 200ms after a charger is detected to debounce pin contact order */
#define USB_CHG_DEBOUNCE_DELAY_MS 200
/*
* Wait 100ms after reset, before re-enabling attach interrupt, so that the
* spurious attach interrupt from certain ports is ignored.
*/
#define USB_CHG_RESET_DELAY_MS 100
void usb_charger_task(void)
{
int device_type, charger_status;
struct charge_port_info charge;
int type;
charge.voltage = USB_BC12_CHARGE_VOLTAGE;
while (1) {
/* Read interrupt register to clear */
pi3usb9281_get_interrupts(0);
/* Set device type */
device_type = pi3usb9281_get_device_type(0);
charger_status = pi3usb9281_get_charger_status(0);
/* Debounce pin plug order if we detect a charger */
if (device_type || PI3USB9281_CHG_STATUS_ANY(charger_status)) {
msleep(USB_CHG_DEBOUNCE_DELAY_MS);
/* Trigger chip reset to refresh detection registers */
pi3usb9281_reset(0);
/*
* Restore data switch settings - switches return to
* closed on reset until restored.
*/
if (usb_switch_state)
pi3usb9281_set_switches(0, 1);
/* Clear possible disconnect interrupt */
pi3usb9281_get_interrupts(0);
/* Mask attach interrupt */
pi3usb9281_set_interrupt_mask(0,
0xff &
~PI3USB9281_INT_ATTACH);
/* Re-enable interrupts */
pi3usb9281_enable_interrupts(0);
msleep(USB_CHG_RESET_DELAY_MS);
/* Clear possible attach interrupt */
pi3usb9281_get_interrupts(0);
/* Re-enable attach interrupt */
pi3usb9281_set_interrupt_mask(0, 0xff);
/* Re-read ID registers */
device_type = pi3usb9281_get_device_type(0);
charger_status = pi3usb9281_get_charger_status(0);
}
if (PI3USB9281_CHG_STATUS_ANY(charger_status))
type = CHARGE_SUPPLIER_PROPRIETARY;
else if (device_type & PI3USB9281_TYPE_CDP)
type = CHARGE_SUPPLIER_BC12_CDP;
else if (device_type & PI3USB9281_TYPE_DCP)
type = CHARGE_SUPPLIER_BC12_DCP;
else if (device_type & PI3USB9281_TYPE_SDP)
type = CHARGE_SUPPLIER_BC12_SDP;
else
type = CHARGE_SUPPLIER_OTHER;
/* Attachment: decode + update available charge */
if (device_type || PI3USB9281_CHG_STATUS_ANY(charger_status)) {
charge.current = pi3usb9281_get_ilim(device_type,
charger_status);
charge_manager_update_charge(type, 0, &charge);
} else { /* Detachment: update available charge to 0 */
charge.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);
}
/* notify host of power info change */
pd_send_host_event(PD_EVENT_POWER_CHANGE);
/* Wait for interrupt */
task_wait_event(-1);
}
}
void usb_evt(enum gpio_signal signal)
{
task_wake(TASK_ID_USB_CHG);
task_wake(TASK_ID_USB_CHG_P0);
}
#include "gpio_list.h"
@@ -364,19 +260,6 @@ const struct adc_t adc_channels[] = {
};
BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT);
/* Charge supplier priority: lower number indicates higher priority. */
const int supplier_priority[] = {
[CHARGE_SUPPLIER_PD] = 0,
[CHARGE_SUPPLIER_TYPEC] = 1,
[CHARGE_SUPPLIER_PROPRIETARY] = 1,
[CHARGE_SUPPLIER_BC12_DCP] = 1,
[CHARGE_SUPPLIER_BC12_CDP] = 2,
[CHARGE_SUPPLIER_BC12_SDP] = 3,
[CHARGE_SUPPLIER_OTHER] = 3,
[CHARGE_SUPPLIER_VBUS] = 4
};
BUILD_ASSERT(ARRAY_SIZE(supplier_priority) == CHARGE_SUPPLIER_COUNT);
/* I2C ports */
const struct i2c_port_t i2c_ports[] = {
{"master", I2C_PORT_MASTER, 100,
@@ -386,14 +269,15 @@ const struct i2c_port_t i2c_ports[] = {
};
const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports);
static void board_set_usb_switches(int port, int open)
void board_set_usb_switches(int port, enum usb_switch setting)
{
/* If switch is not changing, then return */
if (open == usb_switch_state)
if (setting == usb_switch_state)
return;
usb_switch_state = open;
pi3usb9281_set_switches(port, open);
if (setting != USB_SWITCH_RESTORE)
usb_switch_state = setting;
pi3usb9281_set_switches(port, usb_switch_state);
}
/* TODO(crosbug.com/p/38333) remove me */

View File

@@ -25,6 +25,7 @@
#define CONFIG_CMD_CHGRAMP
#define CONFIG_FORCE_CONSOLE_RESUME
#define CONFIG_STM_HWTIMER32
#define CONFIG_USB_CHARGER
#define CONFIG_USB_POWER_DELIVERY
#define CONFIG_USB_PD_DUAL_ROLE
#define CONFIG_USB_PD_FLASH_ERASE_CHECK
@@ -164,22 +165,6 @@ enum adc_channel {
ADC_CH_COUNT
};
/* Charge suppliers */
enum charge_supplier {
CHARGE_SUPPLIER_PD,
CHARGE_SUPPLIER_TYPEC,
CHARGE_SUPPLIER_BC12_DCP,
CHARGE_SUPPLIER_BC12_CDP,
CHARGE_SUPPLIER_BC12_SDP,
CHARGE_SUPPLIER_PROPRIETARY,
CHARGE_SUPPLIER_OTHER,
CHARGE_SUPPLIER_VBUS,
CHARGE_SUPPLIER_COUNT
};
/* supplier_priority table defined in board.c */
extern const int supplier_priority[];
/* USB string indexes */
enum usb_strings {
USB_STR_DESC = 0,
@@ -193,6 +178,9 @@ enum usb_strings {
USB_STR_COUNT
};
/* VBUS enable GPIO */
#define GPIO_USB_C0_5V_EN GPIO_USBC_5V_EN
/* 1.5A Rp */
#define PD_SRC_VNC PD_SRC_1_5_VNC_MV
#define PD_SRC_RD_THRESHOLD PD_SRC_1_5_RD_THRESH_MV
@@ -222,9 +210,6 @@ int board_discharge_on_ac(int enable);
/* Set the charge current limit. */
void board_set_charge_limit(int charge_ma);
/* Send host event to AP */
void pd_send_host_event(int mask);
/* PP1800 transition GPIO interrupt handler */
void pp1800_on_off_evt(enum gpio_signal signal);

View File

@@ -19,7 +19,8 @@
#define CONFIG_TASK_LIST \
TASK_ALWAYS(HOOKS, hook_task, NULL, LARGER_TASK_STACK_SIZE) \
TASK_ALWAYS(CHG_RAMP, chg_ramp_task, NULL, SMALLER_TASK_STACK_SIZE) \
TASK_ALWAYS(USB_CHG, usb_charger_task, NULL, SMALLER_TASK_STACK_SIZE) \
TASK_ALWAYS(USB_CHG_P0, usb_charger_task, NULL, \
SMALLER_TASK_STACK_SIZE) \
TASK_NOTEST(LIGHTBAR, lightbar_task, NULL, LARGER_TASK_STACK_SIZE) \
TASK_ALWAYS(CHARGER, charger_task, NULL, TASK_STACK_SIZE) \
TASK_NOTEST(CHIPSET, chipset_task, NULL, TASK_STACK_SIZE) \

View File

@@ -77,19 +77,6 @@ const struct pwm_t pwm_channels[] = {
};
BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT);
/* Charge supplier priority: lower number indicates higher priority. */
const int supplier_priority[] = {
[CHARGE_SUPPLIER_PD] = 0,
[CHARGE_SUPPLIER_TYPEC] = 1,
[CHARGE_SUPPLIER_PROPRIETARY] = 1,
[CHARGE_SUPPLIER_BC12_DCP] = 1,
[CHARGE_SUPPLIER_BC12_CDP] = 2,
[CHARGE_SUPPLIER_BC12_SDP] = 3,
[CHARGE_SUPPLIER_OTHER] = 3,
[CHARGE_SUPPLIER_VBUS] = 4
};
BUILD_ASSERT(ARRAY_SIZE(supplier_priority) == CHARGE_SUPPLIER_COUNT);
static void pericom_port0_reenable_interrupts(void)
{
CPRINTS("VBUS p0 %d", gpio_get_level(GPIO_USB_C0_VBUS_WAKE));
@@ -156,124 +143,6 @@ void vbus1_evt(enum gpio_signal signal)
task_wake(TASK_ID_PD_C1);
}
/* Wait after a charger is detected to debounce pin contact order */
#define USB_CHG_DEBOUNCE_DELAY_MS 1000
/*
* Wait after reset, before re-enabling attach interrupt, so that the
* spurious attach interrupt from certain ports is ignored.
*/
#define USB_CHG_RESET_DELAY_MS 100
void usb_charger_task(void)
{
int port = (task_get_current() == TASK_ID_USB_CHG_P0 ? 0 : 1);
int vbus_source = (port == 0 ? GPIO_USB_C0_5V_EN : GPIO_USB_C1_5V_EN);
int device_type, charger_status;
struct charge_port_info charge;
int type;
charge.voltage = USB_BC12_CHARGE_VOLTAGE;
while (1) {
/* Read interrupt register to clear on chip */
pi3usb9281_get_interrupts(port);
if (gpio_get_level(vbus_source)) {
/* If we're sourcing VBUS then we're not charging */
device_type = charger_status = 0;
} else {
/* Set device type */
device_type = pi3usb9281_get_device_type(port);
charger_status = pi3usb9281_get_charger_status(port);
}
/* Debounce pin plug order if we detect a charger */
if (device_type || PI3USB9281_CHG_STATUS_ANY(charger_status)) {
msleep(USB_CHG_DEBOUNCE_DELAY_MS);
/*
* Trigger chip reset to refresh detection registers.
* WARNING: This reset is acceptable for samus_pd,
* but may not be acceptable for devices that have
* an OTG / device mode, as we may be interrupting
* the connection.
*/
pi3usb9281_reset(port);
/*
* Restore data switch settings - switches return to
* closed on reset until restored.
*/
mutex_lock(&usb_switch_lock[port]);
if (usb_switch_state[port])
pi3usb9281_set_switches(port, 1);
mutex_unlock(&usb_switch_lock[port]);
/* Clear possible disconnect interrupt */
pi3usb9281_get_interrupts(port);
/* Mask attach interrupt */
pi3usb9281_set_interrupt_mask(port,
0xff &
~PI3USB9281_INT_ATTACH);
/* Re-enable interrupts */
pi3usb9281_enable_interrupts(port);
msleep(USB_CHG_RESET_DELAY_MS);
/* Clear possible attach interrupt */
pi3usb9281_get_interrupts(port);
/* Re-enable attach interrupt */
pi3usb9281_set_interrupt_mask(port, 0xff);
/* Re-read ID registers */
device_type = pi3usb9281_get_device_type(port);
charger_status = pi3usb9281_get_charger_status(port);
}
/* Attachment: decode + update available charge */
if (device_type || PI3USB9281_CHG_STATUS_ANY(charger_status)) {
if (PI3USB9281_CHG_STATUS_ANY(charger_status))
type = CHARGE_SUPPLIER_PROPRIETARY;
else if (device_type & PI3USB9281_TYPE_CDP)
type = CHARGE_SUPPLIER_BC12_CDP;
else if (device_type & PI3USB9281_TYPE_DCP)
type = CHARGE_SUPPLIER_BC12_DCP;
else if (device_type & PI3USB9281_TYPE_SDP)
type = CHARGE_SUPPLIER_BC12_SDP;
else
type = CHARGE_SUPPLIER_OTHER;
charge.current = pi3usb9281_get_ilim(device_type,
charger_status);
charge_manager_update_charge(type, port, &charge);
} else { /* Detachment: update available charge to 0 */
charge.current = 0;
charge_manager_update_charge(
CHARGE_SUPPLIER_PROPRIETARY,
port,
&charge);
charge_manager_update_charge(
CHARGE_SUPPLIER_BC12_CDP,
port,
&charge);
charge_manager_update_charge(
CHARGE_SUPPLIER_BC12_DCP,
port,
&charge);
charge_manager_update_charge(
CHARGE_SUPPLIER_BC12_SDP,
port,
&charge);
charge_manager_update_charge(
CHARGE_SUPPLIER_OTHER,
port,
&charge);
}
/* notify host of power info change */
pd_send_host_event(PD_EVENT_POWER_CHANGE);
/* Wait for interrupt */
task_wait_event(-1);
}
}
/* Charge manager callback function, called on delayed override timeout */
void board_charge_manager_override_timeout(void)
{
@@ -549,16 +418,16 @@ const struct usb_port_mux usb_muxes[] = {
};
BUILD_ASSERT(ARRAY_SIZE(usb_muxes) == CONFIG_USB_PD_PORT_COUNT);
static void board_set_usb_switches(int port, int open)
void board_set_usb_switches(int port, enum usb_switch setting)
{
/* If switch is not changing, then return */
if (open == usb_switch_state[port])
/* If switch is not changing then return */
if (setting == usb_switch_state[port])
return;
mutex_lock(&usb_switch_lock[port]);
usb_switch_state[port] = open;
pi3usb9281_set_switches(port, open);
if (setting != USB_SWITCH_RESTORE)
usb_switch_state[port] = setting;
pi3usb9281_set_switches(port, usb_switch_state[port]);
mutex_unlock(&usb_switch_lock[port]);
}

View File

@@ -44,6 +44,7 @@
#undef CONFIG_PWM
#define CONFIG_STM_HWTIMER32
#undef CONFIG_TASK_PROFILING
#define CONFIG_USB_CHARGER
#define CONFIG_USB_POWER_DELIVERY
#define CONFIG_USB_PD_ALT_MODE
#define CONFIG_USB_PD_ALT_MODE_DFP
@@ -53,7 +54,6 @@
#define CONFIG_USB_PD_CUSTOM_VDM
#define CONFIG_USB_PD_DUAL_ROLE
#define CONFIG_USB_PD_FLASH_ERASE_CHECK
#define CONFIG_USB_PD_HOST_EVENT_ON_POWER_CHANGE
#define CONFIG_USB_PD_INTERNAL_COMP
#define CONFIG_USB_PD_LOGGING
#define CONFIG_USB_PD_LOG_SIZE 512
@@ -114,22 +114,6 @@ enum pwm_channel {
PWM_CH_COUNT
};
/* Charge suppliers */
enum charge_supplier {
CHARGE_SUPPLIER_PD,
CHARGE_SUPPLIER_TYPEC,
CHARGE_SUPPLIER_BC12_DCP,
CHARGE_SUPPLIER_BC12_CDP,
CHARGE_SUPPLIER_BC12_SDP,
CHARGE_SUPPLIER_PROPRIETARY,
CHARGE_SUPPLIER_OTHER,
CHARGE_SUPPLIER_VBUS,
CHARGE_SUPPLIER_COUNT
};
/* supplier_priority table defined in board.c */
extern const int supplier_priority[];
/* Standard-current Rp */
#define PD_SRC_VNC PD_SRC_DEF_VNC_MV
#define PD_SRC_RD_THRESHOLD PD_SRC_DEF_RD_THRESH_MV
@@ -163,9 +147,6 @@ extern const int supplier_priority[];
/* Get the last received battery level. */
int board_get_battery_soc(void);
/* Send host event to AP */
void pd_send_host_event(int mask);
#endif /* !__ASSEMBLER__ */
#endif /* __BOARD_H */

View File

@@ -76,6 +76,7 @@ common-$(CONFIG_STREAM)+=in_stream.o out_stream.o stream_adaptor.o
common-$(CONFIG_SWITCH)+=switch.o
common-$(CONFIG_SW_CRC)+=crc.o
common-$(CONFIG_TEMP_SENSOR)+=temp_sensor.o thermal.o throttle_ap.o
common-$(CONFIG_USB_CHARGER)+=usb_charger.o
common-$(CONFIG_USB_PORT_POWER_DUMB)+=usb_port_power_dumb.o
common-$(CONFIG_USB_PORT_POWER_SMART)+=usb_port_power_smart.o
common-$(CONFIG_USB_POWER_DELIVERY)+=usb_pd_protocol.o usb_pd_policy.o

View File

@@ -23,6 +23,19 @@
#define POWER_SWAP_TIMEOUT (PD_T_SRC_RECOVER_MAX + PD_T_SRC_TURN_ON + \
PD_T_SAFE_0V + 500 * MSEC)
/* Charge supplier priority: lower number indicates higher priority. */
test_mockable const int supplier_priority[] = {
[CHARGE_SUPPLIER_PD] = 0,
[CHARGE_SUPPLIER_TYPEC] = 1,
[CHARGE_SUPPLIER_PROPRIETARY] = 1,
[CHARGE_SUPPLIER_BC12_DCP] = 1,
[CHARGE_SUPPLIER_BC12_CDP] = 2,
[CHARGE_SUPPLIER_BC12_SDP] = 3,
[CHARGE_SUPPLIER_OTHER] = 3,
[CHARGE_SUPPLIER_VBUS] = 4
};
BUILD_ASSERT(ARRAY_SIZE(supplier_priority) == CHARGE_SUPPLIER_COUNT);
/* Keep track of available charge for each charge port. */
static struct charge_port_info available_charge[CHARGE_SUPPLIER_COUNT]
[CONFIG_USB_PD_PORT_COUNT];

View File

@@ -197,10 +197,8 @@ void chg_ramp_task(void)
/* Detect delay is over, fall through to next state */
ramp_st_new = CHG_RAMP_OVERCURRENT_DETECT;
#ifdef CONFIG_USB_PD_HOST_EVENT_ON_POWER_CHANGE
/* notify host of power info change */
pd_send_host_event(PD_EVENT_POWER_CHANGE);
#endif
case CHG_RAMP_OVERCURRENT_DETECT:
/* Check if we should ramp or go straight to stable */
task_wait_time = SECOND;
@@ -297,10 +295,8 @@ void chg_ramp_task(void)
#ifdef CONFIG_USB_PD_LOGGING
charge_manager_save_log(active_port);
#endif
#ifdef CONFIG_USB_PD_HOST_EVENT_ON_POWER_CHANGE
/* notify host of power info change */
pd_send_host_event(PD_EVENT_POWER_CHANGE);
#endif
}
/* Keep an eye on VBUS and restart ramping if it dips */

138
common/usb_charger.c Normal file
View File

@@ -0,0 +1,138 @@
/* Copyright 2015 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.
*/
/*
* USB charger / BC1.2 task. This code assumes that CONFIG_CHARGE_MANAGER
* is defined and implemented. PI3USB9281 is the only charger detector
* currently supported.
*/
#include "charge_manager.h"
#include "common.h"
#include "ec_commands.h"
#include "gpio.h"
#include "pi3usb9281.h"
#include "task.h"
#include "timer.h"
#include "usb_pd.h"
/* Wait after a charger is detected to debounce pin contact order */
#define USB_CHG_DEBOUNCE_DELAY_MS 1000
/*
* Wait after reset, before re-enabling attach interrupt, so that the
* spurious attach interrupt from certain ports is ignored.
*/
#define USB_CHG_RESET_DELAY_MS 100
void usb_charger_task(void)
{
int port = (task_get_current() == TASK_ID_USB_CHG_P0 ? 0 : 1);
#if (CONFIG_USB_PD_PORT_COUNT == 1)
int vbus_source = GPIO_USB_C0_5V_EN;
#else
int vbus_source = (port == 0 ? GPIO_USB_C0_5V_EN : GPIO_USB_C1_5V_EN);
#endif
int device_type, charger_status;
struct charge_port_info charge;
int type;
charge.voltage = USB_BC12_CHARGE_VOLTAGE;
while (1) {
/* Read interrupt register to clear on chip */
pi3usb9281_get_interrupts(port);
if (gpio_get_level(vbus_source)) {
/* If we're sourcing VBUS then we're not charging */
device_type = charger_status = 0;
} else {
/* Set device type */
device_type = pi3usb9281_get_device_type(port);
charger_status = pi3usb9281_get_charger_status(port);
}
/* Debounce pin plug order if we detect a charger */
if (device_type || PI3USB9281_CHG_STATUS_ANY(charger_status)) {
msleep(USB_CHG_DEBOUNCE_DELAY_MS);
/*
* Trigger chip reset to refresh detection registers.
* WARNING: This reset is acceptable for samus_pd,
* but may not be acceptable for devices that have
* an OTG / device mode, as we may be interrupting
* the connection.
*/
pi3usb9281_reset(port);
/*
* Restore data switch settings - switches return to
* closed on reset until restored.
*/
board_set_usb_switches(port, USB_SWITCH_RESTORE);
/* Clear possible disconnect interrupt */
pi3usb9281_get_interrupts(port);
/* Mask attach interrupt */
pi3usb9281_set_interrupt_mask(port,
0xff &
~PI3USB9281_INT_ATTACH);
/* Re-enable interrupts */
pi3usb9281_enable_interrupts(port);
msleep(USB_CHG_RESET_DELAY_MS);
/* Clear possible attach interrupt */
pi3usb9281_get_interrupts(port);
/* Re-enable attach interrupt */
pi3usb9281_set_interrupt_mask(port, 0xff);
/* Re-read ID registers */
device_type = pi3usb9281_get_device_type(port);
charger_status = pi3usb9281_get_charger_status(port);
}
/* Attachment: decode + update available charge */
if (device_type || PI3USB9281_CHG_STATUS_ANY(charger_status)) {
if (PI3USB9281_CHG_STATUS_ANY(charger_status))
type = CHARGE_SUPPLIER_PROPRIETARY;
else if (device_type & PI3USB9281_TYPE_CDP)
type = CHARGE_SUPPLIER_BC12_CDP;
else if (device_type & PI3USB9281_TYPE_DCP)
type = CHARGE_SUPPLIER_BC12_DCP;
else if (device_type & PI3USB9281_TYPE_SDP)
type = CHARGE_SUPPLIER_BC12_SDP;
else
type = CHARGE_SUPPLIER_OTHER;
charge.current = pi3usb9281_get_ilim(device_type,
charger_status);
charge_manager_update_charge(type, port, &charge);
} else { /* Detachment: update available charge to 0 */
charge.current = 0;
charge_manager_update_charge(
CHARGE_SUPPLIER_PROPRIETARY,
port,
&charge);
charge_manager_update_charge(
CHARGE_SUPPLIER_BC12_CDP,
port,
&charge);
charge_manager_update_charge(
CHARGE_SUPPLIER_BC12_DCP,
port,
&charge);
charge_manager_update_charge(
CHARGE_SUPPLIER_BC12_SDP,
port,
&charge);
charge_manager_update_charge(
CHARGE_SUPPLIER_OTHER,
port,
&charge);
}
/* notify host of power info change */
pd_send_host_event(PD_EVENT_POWER_CHANGE);
/* Wait for interrupt */
task_wait_event(-1);
}
}

View File

@@ -914,3 +914,9 @@ int pd_custom_flash_vdm(int port, int cnt, uint32_t *payload)
}
return rsize;
}
static void stub_pd_send_host_event(int mask)
{
}
void pd_send_host_event(int mask)
__attribute__((weak, alias("stub_pd_send_host_event")));

View File

@@ -17,6 +17,21 @@
#define CHARGE_CURRENT_UNINITIALIZED -1
#define CHARGE_VOLTAGE_UNINITIALIZED -1
#define USB_BC12_CHARGE_VOLTAGE 5000 /* mV */
/* Commonly-used charge suppliers listed in no particular order */
enum charge_supplier {
CHARGE_SUPPLIER_PD,
CHARGE_SUPPLIER_TYPEC,
CHARGE_SUPPLIER_BC12_DCP,
CHARGE_SUPPLIER_BC12_CDP,
CHARGE_SUPPLIER_BC12_SDP,
CHARGE_SUPPLIER_PROPRIETARY,
CHARGE_SUPPLIER_OTHER,
CHARGE_SUPPLIER_VBUS,
CHARGE_SUPPLIER_COUNT
};
/* Charge tasks report available current and voltage */
struct charge_port_info {
int current;

View File

@@ -1291,9 +1291,6 @@
/* Check whether PD is the sole power source before flash erase operation */
#undef CONFIG_USB_PD_FLASH_ERASE_CHECK
/* Send host event when power changes */
#undef CONFIG_USB_PD_HOST_EVENT_ON_POWER_CHANGE
/* HW & SW version for alternate mode discover identity response (4bits each) */
#undef CONFIG_USB_PD_IDENTITY_HW_VERS
#undef CONFIG_USB_PD_IDENTITY_SW_VERS
@@ -1371,6 +1368,9 @@
/* Compile chip support for the USB device controller */
#undef CONFIG_USB
/* Common USB / BC1.2 charger task */
#undef CONFIG_USB_CHARGER
/* USB device buffers and descriptors */
#undef CONFIG_USB_RAM_ACCESS_SIZE
#undef CONFIG_USB_RAM_ACCESS_TYPE

View File

@@ -196,8 +196,6 @@ struct usb_endpoint_descriptor {
#define USB_REQ_SET_INTERFACE 0x0B
#define USB_REQ_SYNCH_FRAME 0x0C
#define USB_BC12_CHARGE_VOLTAGE 5000 /* mV */
/* Setup Packet */
struct usb_setup_packet {
uint8_t bmRequestType;

View File

@@ -1191,8 +1191,17 @@ enum typec_mux {
enum usb_switch {
USB_SWITCH_CONNECT,
USB_SWITCH_DISCONNECT,
USB_SWITCH_RESTORE,
};
/**
* Configure USB data switches on type-C port.
*
* @param port port number.
* @param setting new switch setting to configure.
*/
void board_set_usb_switches(int port, enum usb_switch setting);
/**
* Configure superspeed muxes on type-C port.
*
@@ -1226,6 +1235,13 @@ int board_get_usb_mux(int port, const char **dp_str, const char **usb_str);
*/
void board_flip_usb_mux(int port);
/**
* Request that a host event be sent to notify the AP of a PD power event.
*
* @param mask host event mask.
*/
void pd_send_host_event(int mask);
/**
* Determine if in alternate mode or not.
*

View File

@@ -25,8 +25,8 @@ const int supplier_priority[] = {
[CHARGE_SUPPLIER_TEST6] = 3,
[CHARGE_SUPPLIER_TEST7] = 5,
[CHARGE_SUPPLIER_TEST8] = 6,
[CHARGE_SUPPLIER_TEST9] = 6,
};
BUILD_ASSERT((int)CHARGE_SUPPLIER_COUNT == (int)CHARGE_SUPPLIER_TEST_COUNT);
BUILD_ASSERT(ARRAY_SIZE(supplier_priority) == CHARGE_SUPPLIER_COUNT);
static unsigned int active_charge_limit = CHARGE_SUPPLIER_NONE;

View File

@@ -38,7 +38,7 @@ static int charge_limit_ma;
int board_is_ramp_allowed(int supplier)
{
/* Ramp for TEST4-TEST9 */
/* Ramp for TEST4-TEST8 */
return supplier > CHARGE_SUPPLIER_TEST3;
}
@@ -62,7 +62,7 @@ void board_set_charge_limit(int limit_ma)
int board_get_ramp_current_limit(int supplier, int sup_curr)
{
if (supplier == CHARGE_SUPPLIER_TEST9)
if (supplier == CHARGE_SUPPLIER_TEST7)
return 1600;
else if (supplier == CHARGE_SUPPLIER_TEST8)
return 2400;
@@ -70,6 +70,10 @@ int board_get_ramp_current_limit(int supplier, int sup_curr)
return 3000;
}
void pd_send_host_event(int mask)
{
}
/* Test utilities */
static void plug_charger_with_ts(int supplier_type, int port, int min_current,
@@ -191,7 +195,7 @@ static int test_switch_outlet(void)
system_load_current_ma = 3000;
/* Here's a nice powerful charger */
plug_charger(CHARGE_SUPPLIER_TEST7, 0, 500, 3000, 3000);
plug_charger(CHARGE_SUPPLIER_TEST6, 0, 500, 3000, 3000);
/*
* Now the user decides to move it to a nearby outlet...actually
@@ -201,7 +205,7 @@ static int test_switch_outlet(void)
usleep(SECOND * 20);
unplug_charger();
usleep(SECOND * 1.5);
plug_charger(CHARGE_SUPPLIER_TEST7, 0, 500, 3000, 3000);
plug_charger(CHARGE_SUPPLIER_TEST6, 0, 500, 3000, 3000);
usleep(CHARGE_DETECT_DELAY_TEST);
/* Ramp restarts at 500 mA */
TEST_ASSERT(is_in_range(charge_limit_ma, 500, 700));
@@ -399,7 +403,7 @@ static int test_vbus_shift(void)
* At first, the charger is able to supply up to 1900 mA before
* the VBUS voltage starts to drop.
*/
plug_charger(CHARGE_SUPPLIER_TEST7, 0, 500, 1900, 2000);
plug_charger(CHARGE_SUPPLIER_TEST6, 0, 500, 1900, 2000);
TEST_ASSERT(wait_stable_no_overcurrent());
TEST_ASSERT(is_in_range(charge_limit_ma, 1700, 1900));
@@ -456,7 +460,7 @@ static int test_ramp_limit(void)
system_load_current_ma = 3000;
/* Plug in supplier that is limited to 1.6A */
plug_charger(CHARGE_SUPPLIER_TEST9, 0, 500, 3000, 3000);
plug_charger(CHARGE_SUPPLIER_TEST7, 0, 500, 3000, 3000);
usleep(SECOND);
TEST_ASSERT(is_in_range(charge_limit_ma, 500, 700));
TEST_ASSERT(wait_stable_no_overcurrent());
@@ -470,7 +474,7 @@ static int test_ramp_limit(void)
TEST_ASSERT(charge_limit_ma == 2400);
/* Go back to 1.6A limited, but VBUS goes low before that point */
plug_charger(CHARGE_SUPPLIER_TEST9, 0, 500, 1200, 1300);
plug_charger(CHARGE_SUPPLIER_TEST7, 0, 500, 1200, 1300);
usleep(SECOND);
TEST_ASSERT(is_in_range(charge_limit_ma, 500, 700));
TEST_ASSERT(wait_stable_no_overcurrent());