diff options
author | Alec Berg <alecaberg@chromium.org> | 2015-02-16 11:27:58 -0800 |
---|---|---|
committer | ChromeOS Commit Bot <chromeos-commit-bot@chromium.org> | 2015-02-18 04:53:12 +0000 |
commit | ac5f11bf84d8186a899454e50da3fd634bc9b35e (patch) | |
tree | 66417af5efebda9451631de3d7be64e482dc9247 | |
parent | f41d33b1d7432f159d3a24c8c31c064852620618 (diff) | |
download | chrome-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.c | 50 | ||||
-rw-r--r-- | board/ryu/board.h | 1 | ||||
-rw-r--r-- | board/samus_pd/board.c | 70 | ||||
-rw-r--r-- | board/samus_pd/board.h | 1 | ||||
-rw-r--r-- | common/usb_pd_protocol.c | 51 |
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( |