diff options
author | Alec Berg <alecaberg@chromium.org> | 2014-11-19 09:08:30 -0800 |
---|---|---|
committer | ChromeOS Commit Bot <chromeos-commit-bot@chromium.org> | 2015-01-09 21:28:07 +0000 |
commit | 1ac80fd3f895f9d5fd383a2146bd11f5100ba443 (patch) | |
tree | caebc4410282438935d45858de57a144bd1262a1 | |
parent | 49d2682b724aa49f53344dcc2768f8ac1af41dda (diff) | |
download | chrome-ec-1ac80fd3f895f9d5fd383a2146bd11f5100ba443.tar.gz |
ryu: add charge manager
Add charge manager to ryu to set how much current to draw from
the port.
BUG=none
BRANCH=samus
TEST=make buildall
Signed-off-by: Alec Berg <alecaberg@chromium.org>
Change-Id: Ia545532e1bf6586566c0b964d966b5d69c0d4b61
Reviewed-on: https://chromium-review.googlesource.com/230760
Tested-by: Vic Yang <victoryang@chromium.org>
Reviewed-by: Shawn N <shawnn@chromium.org>
Commit-Queue: Vic Yang <victoryang@chromium.org>
-rw-r--r-- | board/ryu/board.c | 131 | ||||
-rw-r--r-- | board/ryu/board.h | 23 | ||||
-rw-r--r-- | board/ryu/gpio.inc | 2 | ||||
-rw-r--r-- | board/ryu/usb_pd_config.h | 5 | ||||
-rw-r--r-- | board/ryu/usb_pd_policy.c | 19 | ||||
-rw-r--r-- | board/samus_pd/board.c | 2 | ||||
-rw-r--r-- | board/samus_pd/board.h | 2 | ||||
-rw-r--r-- | common/charge_manager.c | 4 |
8 files changed, 178 insertions, 10 deletions
diff --git a/board/ryu/board.c b/board/ryu/board.c index 7d6bf76042..856b93ecd4 100644 --- a/board/ryu/board.c +++ b/board/ryu/board.c @@ -8,6 +8,8 @@ #include "adc_chip.h" #include "battery.h" #include "case_closed_debug.h" +#include "charge_manager.h" +#include "charge_state.h" #include "charger.h" #include "common.h" #include "console.h" @@ -29,6 +31,8 @@ #include "util.h" #include "pi3usb9281.h" +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args) + void vbus_evt(enum gpio_signal signal) { ccprintf("VBUS %d, %d!\n", signal, gpio_get_level(signal)); @@ -40,6 +44,58 @@ void unhandled_evt(enum gpio_signal signal) ccprintf("Unhandled INT %d,%d!\n", signal, gpio_get_level(signal)); } +/* + * Update available charge. Called from deferred task, queued on Pericom + * interrupt. + */ +static void board_usb_charger_update(void) +{ + int device_type, charger_status; + struct charge_port_info charge; + int type; + charge.voltage = USB_BC12_CHARGE_VOLTAGE; + + /* 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); + 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(type, 0, &charge); + } else { /* Detachment: update available charge to 0 */ + charge.current = 0; + charge_manager_update(CHARGE_SUPPLIER_PROPRIETARY, 0, + &charge); + charge_manager_update(CHARGE_SUPPLIER_BC12_CDP, 0, &charge); + charge_manager_update(CHARGE_SUPPLIER_BC12_DCP, 0, &charge); + charge_manager_update(CHARGE_SUPPLIER_BC12_SDP, 0, &charge); + charge_manager_update(CHARGE_SUPPLIER_OTHER, 0, &charge); + } + + /* notify host of power info change */ + /*pd_send_host_event(PD_EVENT_POWER_CHANGE);*/ +} + +void usb_evt(enum gpio_signal signal) +{ + hook_call_deferred(board_usb_charger_update, 0); +} + #include "gpio_list.h" const void *const usb_strings[] = { @@ -55,6 +111,23 @@ BUILD_ASSERT(ARRAY_SIZE(usb_strings) == USB_STR_COUNT); /* Initialize board. */ static void board_init(void) { + struct charge_port_info charge; + + /* Initialize all pericom charge suppliers to 0 */ + charge.voltage = USB_BC12_CHARGE_VOLTAGE; + charge.current = 0; + charge_manager_update(CHARGE_SUPPLIER_PROPRIETARY, 0, + &charge); + charge_manager_update(CHARGE_SUPPLIER_BC12_CDP, 0, &charge); + charge_manager_update(CHARGE_SUPPLIER_BC12_DCP, 0, &charge); + charge_manager_update(CHARGE_SUPPLIER_BC12_SDP, 0, &charge); + charge_manager_update(CHARGE_SUPPLIER_OTHER, 0, &charge); + + /* Enable pericom BC1.2 interrupts. */ + gpio_enable_interrupt(GPIO_USBC_BC12_INT_L); + pi3usb9281_set_interrupt_mask(0, 0xff); + pi3usb9281_enable_interrupts(0); + /* * Determine recovery mode is requested by the power, volup, and * voldown buttons being pressed. @@ -96,6 +169,18 @@ 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 +}; +BUILD_ASSERT(ARRAY_SIZE(supplier_priority) == CHARGE_SUPPLIER_COUNT); + /* I2C ports */ const struct i2c_port_t i2c_ports[] = { {"master", I2C_PORT_MASTER, 100, @@ -194,3 +279,49 @@ void usb_board_disconnect(void) { gpio_set_level(GPIO_USB_PU_EN_L, 1); } + +/* Charge manager callback function, called on delayed override timeout */ +void board_charge_manager_override_timeout(void) +{ + /* TODO: Implement me! */ +} +DECLARE_DEFERRED(board_charge_manager_override_timeout); + +/** + * Set active charge port -- only one port can be active at a time. + * + * @param charge_port Charge port to enable. + * + * Returns EC_SUCCESS if charge port is accepted and made active, + * EC_ERROR_* otherwise. + */ +int board_set_active_charge_port(int charge_port) +{ + int ret = EC_SUCCESS; + + if (charge_port >= 0 && charge_port < PD_PORT_COUNT && + pd_get_role(charge_port) != PD_ROLE_SINK) { + CPRINTS("Port %d is not a sink, skipping enable", charge_port); + charge_port = CHARGE_PORT_NONE; + ret = EC_ERROR_INVAL; + } + if (charge_port == CHARGE_PORT_NONE) { + /* Disable charging */ + charge_set_input_current_limit(0); + } + + return ret; +} + +/** + * Set the charge limit based upon desired maximum. + * + * @param charge_ma Desired charge limit (mA). + */ +void board_set_charge_limit(int charge_ma) +{ + int rv = charge_set_input_current_limit(MAX(charge_ma, + CONFIG_CHARGER_INPUT_CURRENT)); + if (rv < 0) + CPRINTS("Failed to set input current limit for PD"); +} diff --git a/board/ryu/board.h b/board/ryu/board.h index 1dab8da727..5453965d2d 100644 --- a/board/ryu/board.h +++ b/board/ryu/board.h @@ -20,6 +20,7 @@ /* Optional features */ #undef CONFIG_CMD_HASH +#define CONFIG_CHARGE_MANAGER #define CONFIG_FORCE_CONSOLE_RESUME #define CONFIG_STM_HWTIMER32 #define CONFIG_USB_POWER_DELIVERY @@ -98,6 +99,10 @@ /* Enable Case Closed Debugging */ #define CONFIG_CASE_CLOSED_DEBUG +/* Maximum number of deferrable functions */ +#undef DEFERRABLE_MAX_COUNT +#define DEFERRABLE_MAX_COUNT 9 + #ifndef __ASSEMBLER__ /* Timer selection */ @@ -125,6 +130,21 @@ 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_COUNT +}; + +/* supplier_priority table defined in board.c */ +extern const int supplier_priority[]; + /* USB string indexes */ enum usb_strings { USB_STR_DESC = 0, @@ -139,6 +159,9 @@ enum usb_strings { /* Discharge battery when on AC power for factory test. */ int board_discharge_on_ac(int enable); +/* Set the charge current limit. */ +void board_set_charge_limit(int charge_ma); + #endif /* !__ASSEMBLER__ */ #endif /* __BOARD_H */ diff --git a/board/ryu/gpio.inc b/board/ryu/gpio.inc index 686f629ce8..4b6d5cc717 100644 --- a/board/ryu/gpio.inc +++ b/board/ryu/gpio.inc @@ -9,7 +9,7 @@ GPIO(CHGR_ACOK, D, 4, GPIO_INT_BOTH | GPIO_PULL_UP, vbus_evt) GPIO(BC_TEMP_ALERT_L, C, 5, GPIO_INT_FALLING, unhandled_evt) GPIO(POWER_BUTTON_L, C, 13, GPIO_INT_BOTH, power_button_interrupt) /* active high, the name is for compatibility with existing code */ -GPIO(USBC_BC12_INT_L, D, 11, GPIO_INT_FALLING | GPIO_PULL_UP, unhandled_evt) +GPIO(USBC_BC12_INT_L, D, 11, GPIO_INT_FALLING | GPIO_PULL_UP, usb_evt) GPIO(LID_OPEN, E, 1, GPIO_INT_BOTH | GPIO_PULL_UP, lid_interrupt) GPIO(CHARGE_DONE, E, 6, GPIO_INT_BOTH, inductive_charging_interrupt) GPIO(LB_INT_L, E, 7, GPIO_INT_FALLING | GPIO_PULL_UP, unhandled_evt) diff --git a/board/ryu/usb_pd_config.h b/board/ryu/usb_pd_config.h index 994759163b..453014b2c2 100644 --- a/board/ryu/usb_pd_config.h +++ b/board/ryu/usb_pd_config.h @@ -8,6 +8,9 @@ #ifndef __USB_PD_CONFIG_H #define __USB_PD_CONFIG_H +#include "charge_state.h" +#include "registers.h" + /* Port and task configuration */ #define PD_PORT_COUNT 1 #define PORT_TO_TASK_ID(port) TASK_ID_PD @@ -126,6 +129,7 @@ static inline void pd_set_host_mode(int port, int enable) if (enable) { /* We never charging in power source mode */ gpio_set_level(GPIO_USBC_CHARGE_EN_L, 1); + charge_set_input_current_limit(0); /* High-Z is used for host mode. */ gpio_set_level(GPIO_USBC_CC1_DEVICE_ODL, 1); gpio_set_level(GPIO_USBC_CC2_DEVICE_ODL, 1); @@ -135,7 +139,6 @@ static inline void pd_set_host_mode(int port, int enable) /* Pull low for device mode. */ gpio_set_level(GPIO_USBC_CC1_DEVICE_ODL, 0); gpio_set_level(GPIO_USBC_CC2_DEVICE_ODL, 0); - /* Enable the charging path*/ gpio_set_level(GPIO_USBC_CHARGE_EN_L, 0); } diff --git a/board/ryu/usb_pd_policy.c b/board/ryu/usb_pd_policy.c index b914cabc83..d6bd8c5598 100644 --- a/board/ryu/usb_pd_policy.c +++ b/board/ryu/usb_pd_policy.c @@ -3,7 +3,7 @@ * found in the LICENSE file. */ -#include "charge_state.h" +#include "charge_manager.h" #include "common.h" #include "console.h" #include "gpio.h" @@ -35,10 +35,19 @@ const int pd_snk_pdo_cnt = ARRAY_SIZE(pd_snk_pdo); void pd_set_input_current_limit(int port, uint32_t max_ma, uint32_t supply_voltage) { - int rv = charge_set_input_current_limit(MAX(max_ma, - CONFIG_CHARGER_INPUT_CURRENT)); - if (rv < 0) - CPRINTS("Failed to set input current limit for PD"); + struct charge_port_info charge; + charge.current = max_ma; + charge.voltage = supply_voltage; + charge_manager_update(CHARGE_SUPPLIER_PD, port, &charge); +} + +void typec_set_input_current_limit(int port, uint32_t max_ma, + uint32_t supply_voltage) +{ + struct charge_port_info charge; + charge.current = max_ma; + charge.voltage = supply_voltage; + charge_manager_update(CHARGE_SUPPLIER_TYPEC, port, &charge); } int pd_check_requested_voltage(uint32_t rdo) diff --git a/board/samus_pd/board.c b/board/samus_pd/board.c index 8359d770f2..8266e19ae8 100644 --- a/board/samus_pd/board.c +++ b/board/samus_pd/board.c @@ -418,7 +418,7 @@ const struct adc_t adc_channels[] = { [ADC_C1_CC2_PD] = {"C1_CC2_PD", 3300, 4096, 0, STM32_AIN(5)}, /* Vbus sensing. Converted to mV, full ADC is equivalent to 25.774V. */ - [ADC_BOOSTIN] = {"V_BOOSTIN", 25774, 4096, 0, STM32_AIN(11)}, + [ADC_VBUS] = {"VBUS", 25774, 4096, 0, STM32_AIN(11)}, }; BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); diff --git a/board/samus_pd/board.h b/board/samus_pd/board.h index a607d690ed..8089acb74c 100644 --- a/board/samus_pd/board.h +++ b/board/samus_pd/board.h @@ -85,7 +85,7 @@ enum adc_channel { ADC_C1_CC1_PD, ADC_C0_CC2_PD, ADC_C1_CC2_PD, - ADC_BOOSTIN, + ADC_VBUS, /* Number of ADC channels */ ADC_CH_COUNT }; diff --git a/common/charge_manager.c b/common/charge_manager.c index ffb2912b4f..470c20d08c 100644 --- a/common/charge_manager.c +++ b/common/charge_manager.c @@ -3,8 +3,10 @@ * found in the LICENSE file. */ +#include "adc.h" #include "charge_manager.h" #include "console.h" +#include "gpio.h" #include "hooks.h" #include "host_command.h" #include "timer.h" @@ -515,7 +517,7 @@ static int hc_pd_power_info(struct host_cmd_handler_args *args) r->role == USB_PD_PORT_POWER_SINK_NOT_CHARGING) r->voltage_now = 5000; else - r->voltage_now = adc_read_channel(ADC_BOOSTIN); + r->voltage_now = adc_read_channel(ADC_VBUS); } args->response_size = sizeof(*r); |