diff --git a/board/fizz/board.c b/board/fizz/board.c index ce0ff98920..918d38892d 100644 --- a/board/fizz/board.c +++ b/board/fizz/board.c @@ -71,20 +71,38 @@ static void tcpc_alert_event(enum gpio_signal signal) */ static int adp_in_state = 1; +static void adp_in_deferred(void); +DECLARE_DEFERRED(adp_in_deferred); static void adp_in_deferred(void) { - /* TODO: Switch power source from USB-C to BJ only if we're in S5. */ - struct charge_port_info cpi; + struct charge_port_info pi = { 0 }; int level = gpio_get_level(GPIO_ADP_IN_L); /* Debounce */ if (level == adp_in_state) return; - /* High = unplugged. Low = plugged. TODO: Set appropriate voltage. */ - cpi.voltage = level ? 0 : 19000; - /* Set to 0 to ensure charge manager will ignore it. */ - cpi.current = 0; - charge_manager_update_charge(CHARGE_SUPPLIER_DEDICATED, 1, &cpi); + if (!level) { + /* BJ is inserted but the voltage isn't effective because PU3 + * is still disabled. */ + pi.voltage = 19000; + if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) { + /* If type-c voltage is higher than BJ voltage, PU3 will + * shut down due to reverse current protection. So, we + * need to lower the voltage first. */ + if (charge_manager_get_charger_voltage() > pi.voltage) { + pd_set_external_voltage_limit( + CHARGE_PORT_TYPEC0, pi.voltage); + hook_call_deferred(&adp_in_deferred_data, + ADP_DEBOUNCE_MS * MSEC); + return; + } + if (gpio_get_level(GPIO_POWER_RATE)) + pi.current = 4620; + else + pi.current = 3330; + } + } + charge_manager_update_charge(CHARGE_SUPPLIER_DEDICATED, 1, &pi); /* * Explicitly notifies the host that BJ is plugged or unplugged * (when running on a type-c adapter). @@ -92,7 +110,6 @@ static void adp_in_deferred(void) pd_send_host_event(PD_EVENT_POWER_CHANGE); adp_in_state = level; } -DECLARE_DEFERRED(adp_in_deferred); /* IRQ for BJ plug/unplug. It shouldn't be called if BJ is the power source. */ void adp_in(enum gpio_signal signal) diff --git a/board/fizz/usb_pd_policy.c b/board/fizz/usb_pd_policy.c index 39e47dd895..5dc807cc82 100644 --- a/board/fizz/usb_pd_policy.c +++ b/board/fizz/usb_pd_policy.c @@ -289,6 +289,14 @@ int board_set_active_charge_port(int port) break; case CHARGE_PORT_BARRELJACK : gpio_set_level(GPIO_AC_JACK_CHARGE_L, 0); + /* If this is switching from type-c to BJ, we have to wait until + * PU3 comes up to keep the system continuously powered. + * NX20P5090 datasheet says turn-on time for 20V is 29 msec. */ + if (active_port == CHARGE_PORT_TYPEC0) + msleep(30); + /* We don't check type-c voltage here. If it's higher than + * BJ voltage, we'll brown out due to the reverse current + * protection of PU3. */ gpio_set_level(GPIO_USB_C0_CHARGE_L, 1); gpio_disable_interrupt(GPIO_ADP_IN_L); break; diff --git a/common/charge_manager.c b/common/charge_manager.c index a068897620..4a6808b50f 100644 --- a/common/charge_manager.c +++ b/common/charge_manager.c @@ -995,6 +995,11 @@ int charge_manager_get_charger_current(void) return charge_current; } +int charge_manager_get_charger_voltage(void) +{ + return charge_voltage; +} + int charge_manager_get_power_limit_uw(void) { int current_ma = charge_current; diff --git a/include/charge_manager.h b/include/charge_manager.h index 6d5bacc2df..0f2624129e 100644 --- a/include/charge_manager.h +++ b/include/charge_manager.h @@ -162,6 +162,13 @@ int charge_manager_get_power_limit_uw(void); */ int charge_manager_get_charger_current(void); +/** + * Get the charger voltage (mV) value. + * + * @return Charger voltage (mV) or CHARGE_VOLTAGE_UNINITIALIZED. + */ +int charge_manager_get_charger_voltage(void); + #ifdef CONFIG_USB_PD_LOGGING /* Save power state log entry for the given port */ void charge_manager_save_log(int port);