diff options
author | Rong Chang <rongchang@chromium.org> | 2015-06-08 20:55:47 +0800 |
---|---|---|
committer | ChromeOS Commit Bot <chromeos-commit-bot@chromium.org> | 2015-06-10 15:49:35 +0000 |
commit | 2b129cc3b79d9940be9e80b660d2523e399eb732 (patch) | |
tree | 70cac0df0d61f270b0d97bc132a44d8b5f64eb46 /board | |
parent | ffd83ca8e9b3652527aa0966414f528daf068244 (diff) | |
download | chrome-ec-2b129cc3b79d9940be9e80b660d2523e399eb732.tar.gz |
oak: enable CHARGE_MANAGER to handle charging on both ports
This CL copies CL:275686 that enables charge manager to handle charging
on two ports.
Since oak has the same PD design, so both CHARGE_L controls need to be
enabled to detect VBUS when no charger is plugged in. That means if
you set chgoverride -1, this actually enable charging on both ports.
BRANCH=none
BUG=chrome-os-partner:41167
TEST=manual
plug in zinger and donette onto both ports. verify that we charge from
the first one plugged in.
Change-Id: If5ed360e55f6c6b1a0315a68a5a6d924ae856c6d
Signed-off-by: Rong Chang <rongchang@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/275853
Reviewed-by: Alec Berg <alecaberg@chromium.org>
Diffstat (limited to 'board')
-rw-r--r-- | board/oak/board.c | 83 | ||||
-rw-r--r-- | board/oak/board.h | 19 | ||||
-rw-r--r-- | board/oak/usb_pd_policy.c | 36 |
3 files changed, 119 insertions, 19 deletions
diff --git a/board/oak/board.c b/board/oak/board.c index f8c2408a45..b49155b430 100644 --- a/board/oak/board.c +++ b/board/oak/board.c @@ -7,6 +7,8 @@ #include "adc_chip.h" #include "battery.h" +#include "charge_manager.h" +#include "charge_state.h" #include "charger.h" #include "chipset.h" #include "common.h" @@ -35,6 +37,10 @@ #define GPIO_KB_INPUT (GPIO_INPUT | GPIO_PULL_UP | GPIO_INT_BOTH) #define GPIO_KB_OUTPUT GPIO_ODR_HIGH +/* 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) { /* Warm reset AP */ @@ -102,6 +108,19 @@ 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; /** @@ -149,6 +168,70 @@ static void board_init(void) } DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); +/** + * Set active charge port -- only one port can active at a time. + * + * @param charge_port Charge port to enable. + * + * Return EC_SUCCESS if charge port is accepted and made active. + * EC_ERROR_* otherwise. + */ +int board_set_active_charge_port(int charge_port) +{ + /* charge port is a physical port */ + int is_real_port = (charge_port >= 0 && + charge_port < CONFIG_USB_PD_PORT_COUNT); + /* check if we are source VBUS on the port */ + int source = gpio_get_level(charge_port == 0 ? GPIO_USB_C0_5V_OUT : + GPIO_USB_C1_5V_OUT); + + if (is_real_port && source) { + CPRINTF("Skip enable p%d", charge_port); + return EC_ERROR_INVAL; + } + + CPRINTF("New chg p%d", charge_port); + + if (charge_port == CHARGE_PORT_NONE) { + /* + * TODO: currently we only get VBUS knowledge when charge + * is enabled. so, when not changing, we need to enable + * both ports. but, this is dangerous if you have two + * chargers plugged in and you set charge override to -1 + * then it will enable both sides! + */ + gpio_set_level(GPIO_USB_C0_CHARGE_L, 0); + gpio_set_level(GPIO_USB_C1_CHARGE_L, 0); + } else { + /* Make sure non-charging port is disabled */ + gpio_set_level(charge_port ? GPIO_USB_C0_CHARGE_L : + GPIO_USB_C1_CHARGE_L, 1); + /* Enable charging port */ + gpio_set_level(charge_port ? GPIO_USB_C1_CHARGE_L : + GPIO_USB_C0_CHARGE_L, 0); + } + + return EC_SUCCESS; +} + +/** + * Set the charge limit based upon desired maximum. + * + * @param charge_ma Desired charge limit (mA). + */ +void board_set_charge_limit(int charge_ma) +{ + charge_set_input_current_limit(MAX(charge_ma, + CONFIG_CHARGER_INPUT_CURRENT)); +} + +/* Charge manager callback function, called on delayed override timeout */ +void board_charge_manager_override_timeout(void) +{ + /* TODO: what to do here? */ +} +DECLARE_DEFERRED(board_charge_manager_override_timeout); + #ifndef CONFIG_AP_WARM_RESET_INTERRUPT /* Using this hook if system doesn't have enough external line. */ static void check_ap_reset_second(void) diff --git a/board/oak/board.h b/board/oak/board.h index c810b0d4f3..9a29c9badc 100644 --- a/board/oak/board.h +++ b/board/oak/board.h @@ -18,6 +18,7 @@ /* Add for AC adaptor, charger, battery */ #define CONFIG_BATTERY_CUT_OFF #define CONFIG_BATTERY_SMART +#define CONFIG_CHARGE_MANAGER #define CONFIG_CHARGER #ifdef CONFIG_BOARD_OAK_REV_1 @@ -69,7 +70,7 @@ #undef CONFIG_UART_RX_DMA #undef DEFERRABLE_MAX_COUNT -#define DEFERRABLE_MAX_COUNT 9 +#define DEFERRABLE_MAX_COUNT 10 /* * Allow dangerous commands. @@ -136,6 +137,22 @@ 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 diff --git a/board/oak/usb_pd_policy.c b/board/oak/usb_pd_policy.c index 73bc31bce3..5f403ba45a 100644 --- a/board/oak/usb_pd_policy.c +++ b/board/oak/usb_pd_policy.c @@ -73,31 +73,31 @@ void pd_transition_voltage(int idx) int pd_set_power_supply_ready(int port) { - /* - * TODO: this only works on port 0 for now. need to include - * charge manager to manage CHARGE_L - */ - if (port == 0) { - /* Disable charging */ - gpio_set_level(GPIO_USB_C0_CHARGE_L, 1); - /* Provide VBUS */ - gpio_set_level(GPIO_USB_C0_5V_OUT, 1); - } + /* Disable charging */ + gpio_set_level(port ? GPIO_USB_C1_CHARGE_L : + GPIO_USB_C0_CHARGE_L, 1); + /* Provide VBUS */ + gpio_set_level(port ? GPIO_USB_C1_5V_OUT : + GPIO_USB_C0_5V_OUT, 1); + return EC_SUCCESS; /* we are ready */ } void pd_power_supply_reset(int port) { + /* Disable VBUS */ + gpio_set_level(port ? GPIO_USB_C1_5V_OUT : + GPIO_USB_C0_5V_OUT, 0); + /* - * TODO: this only works on port 0 for now. need to include - * charge manager to manage CHARGE_L + * TODO: Currently we can only detect VBUS when charge_l is + * asserted, so, if there is no active charge port, then enable + * charge_l. If the other port is the active charger, then leave + * this port disabled. */ - if (port == 0) { - /* Disable VBUS */ - gpio_set_level(GPIO_USB_C0_5V_OUT, 0); - /* Enable charging */ - gpio_set_level(GPIO_USB_C0_CHARGE_L, 0); - } + if (charge_manager_get_active_charge_port() != !port) + gpio_set_level(port ? GPIO_USB_C1_CHARGE_L : + GPIO_USB_C0_CHARGE_L, 0); } void pd_set_input_current_limit(int port, uint32_t max_ma, |