diff options
-rw-r--r-- | board/glados/board.c | 125 | ||||
-rw-r--r-- | board/glados/board.h | 20 | ||||
-rw-r--r-- | board/glados/usb_pd_policy.c | 35 |
3 files changed, 162 insertions, 18 deletions
diff --git a/board/glados/board.c b/board/glados/board.c index 2d17d671f7..e72e631b17 100644 --- a/board/glados/board.c +++ b/board/glados/board.c @@ -7,6 +7,8 @@ #include "adc_chip.h" #include "button.h" +#include "charge_manager.h" +#include "charge_state.h" #include "charger.h" #include "console.h" #include "extpower.h" @@ -32,6 +34,10 @@ #define I2C_ADDR_BD99992 0x60 +/* 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) { @@ -95,6 +101,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); + /** * Discharge battery when on AC power for factory test. */ @@ -137,10 +156,116 @@ DECLARE_HOOK(HOOK_CHIPSET_PRE_INIT, pmic_init, HOOK_PRIO_DEFAULT); /* Initialize board. */ static void board_init(void) { + int i; + struct charge_port_info charge_none, charge_vbus; + /* Enable PD MCU interrupt */ gpio_enable_interrupt(GPIO_PD_MCU_INT); /* Enable VBUS interrupt */ gpio_enable_interrupt(GPIO_USB_C0_VBUS_WAKE_L); gpio_enable_interrupt(GPIO_USB_C1_VBUS_WAKE_L); + + /* Initialize all pericom charge suppliers to 0 */ + charge_none.voltage = USB_BC12_CHARGE_VOLTAGE; + charge_none.current = 0; + for (i = 0; i < CONFIG_USB_PD_PORT_COUNT; i++) { + charge_manager_update_charge(CHARGE_SUPPLIER_PROPRIETARY, + i, + &charge_none); + charge_manager_update_charge(CHARGE_SUPPLIER_BC12_CDP, + i, + &charge_none); + charge_manager_update_charge(CHARGE_SUPPLIER_BC12_DCP, + i, + &charge_none); + charge_manager_update_charge(CHARGE_SUPPLIER_BC12_SDP, + i, + &charge_none); + charge_manager_update_charge(CHARGE_SUPPLIER_OTHER, + i, + &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_L)) + 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_L)) + charge_manager_update_charge(CHARGE_SUPPLIER_VBUS, 1, + &charge_vbus); + else + charge_manager_update_charge(CHARGE_SUPPLIER_VBUS, 1, + &charge_none); } DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); + +/** + * 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) +{ + /* charge port is a realy physical port */ + int is_real_port = (charge_port >= 0 && + charge_port < CONFIG_USB_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 && source) { + CPRINTS("Skip enable p%d", charge_port); + return EC_ERROR_INVAL; + } + + CPRINTS("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 charging, 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_EN_L, 0); + gpio_set_level(GPIO_USB_C1_CHARGE_EN_L, 0); + } else { + /* Make sure non-charging port is disabled */ + gpio_set_level(charge_port ? GPIO_USB_C0_CHARGE_EN_L : + GPIO_USB_C1_CHARGE_EN_L, 1); + /* Enable charging port */ + gpio_set_level(charge_port ? GPIO_USB_C1_CHARGE_EN_L : + GPIO_USB_C0_CHARGE_EN_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); + diff --git a/board/glados/board.h b/board/glados/board.h index 4f1eb3dd50..ecf0590a7e 100644 --- a/board/glados/board.h +++ b/board/glados/board.h @@ -12,6 +12,7 @@ #define CONFIG_ADC #define CONFIG_BATTERY_SMART #define CONFIG_BUTTON_COUNT 2 +#define CONFIG_CHARGE_MANAGER #define CONFIG_CHARGER #define CONFIG_CHARGER_V2 @@ -64,6 +65,9 @@ #define I2C_PORT_ACCEL MEC1322_I2C2 #define I2C_PORT_PMIC MEC1322_I2C3 +#undef DEFERRABLE_MAX_COUNT +#define DEFERRABLE_MAX_COUNT 9 + #ifndef __ASSEMBLER__ #include "gpio_signal.h" @@ -92,6 +96,22 @@ 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 diff --git a/board/glados/usb_pd_policy.c b/board/glados/usb_pd_policy.c index 891008f7ce..1799c84724 100644 --- a/board/glados/usb_pd_policy.c +++ b/board/glados/usb_pd_policy.c @@ -73,31 +73,30 @@ 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_EN_L, 1); - /* Provide VBUS */ - gpio_set_level(GPIO_USB_C0_5V_EN, 1); - } + /* Disable charging */ + gpio_set_level(port ? GPIO_USB_C1_CHARGE_EN_L : + GPIO_USB_C0_CHARGE_EN_L, 1); + /* Provide VBUS */ + gpio_set_level(port ? GPIO_USB_C1_5V_EN : + GPIO_USB_C0_5V_EN, 1); + return EC_SUCCESS; /* we are ready */ } void pd_power_supply_reset(int port) { + /* Disable VBUS */ + gpio_set_level(port ? GPIO_USB_C1_5V_EN : + GPIO_USB_C0_5V_EN, 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_en is + * asserted, so, if there is no active charge port, then enable + * charge_en. 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_EN, 0); - /* Enable charging */ - gpio_set_level(GPIO_USB_C0_CHARGE_EN_L, 0); - } + if (charge_manager_get_active_charge_port() != !port) + gpio_set_level(port ? GPIO_USB_C1_CHARGE_EN_L : + GPIO_USB_C0_CHARGE_EN_L, 0); } void pd_set_input_current_limit(int port, uint32_t max_ma, |