summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlec Berg <alecaberg@chromium.org>2015-02-16 11:27:58 -0800
committerChromeOS Commit Bot <chromeos-commit-bot@chromium.org>2015-02-18 04:53:12 +0000
commitac5f11bf84d8186a899454e50da3fd634bc9b35e (patch)
tree66417af5efebda9451631de3d7be64e482dc9247
parentf41d33b1d7432f159d3a24c8c31c064852620618 (diff)
downloadchrome-ec-ac5f11bf84d8186a899454e50da3fd634bc9b35e.tar.gz
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>
-rw-r--r--board/ryu/board.c50
-rw-r--r--board/ryu/board.h1
-rw-r--r--board/samus_pd/board.c70
-rw-r--r--board/samus_pd/board.h1
-rw-r--r--common/usb_pd_protocol.c51
5 files changed, 109 insertions, 64 deletions
diff --git a/board/ryu/board.c b/board/ryu/board.c
index 0307f3f91b..0c700b3563 100644
--- a/board/ryu/board.c
+++ b/board/ryu/board.c
@@ -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;
diff --git a/board/ryu/board.h b/board/ryu/board.h
index 7cdfb65dd1..3c9da9ae5e 100644
--- a/board/ryu/board.h
+++ b/board/ryu/board.h
@@ -140,6 +140,7 @@ enum charge_supplier {
CHARGE_SUPPLIER_BC12_SDP,
CHARGE_SUPPLIER_PROPRIETARY,
CHARGE_SUPPLIER_OTHER,
+ CHARGE_SUPPLIER_VBUS,
CHARGE_SUPPLIER_COUNT
};
diff --git a/board/samus_pd/board.c b/board/samus_pd/board.c
index 63b435bc33..d4432e73b6 100644
--- a/board/samus_pd/board.c
+++ b/board/samus_pd/board.c
@@ -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;
}
diff --git a/board/samus_pd/board.h b/board/samus_pd/board.h
index 70a7f7d2fd..a0dff70daf 100644
--- a/board/samus_pd/board.h
+++ b/board/samus_pd/board.h
@@ -107,6 +107,7 @@ enum charge_supplier {
CHARGE_SUPPLIER_BC12_SDP,
CHARGE_SUPPLIER_PROPRIETARY,
CHARGE_SUPPLIER_OTHER,
+ CHARGE_SUPPLIER_VBUS,
CHARGE_SUPPLIER_COUNT
};
diff --git a/common/usb_pd_protocol.c b/common/usb_pd_protocol.c
index 40126aa8fe..d1f92efd08 100644
--- a/common/usb_pd_protocol.c
+++ b/common/usb_pd_protocol.c
@@ -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(