diff options
Diffstat (limited to 'zephyr/program/trogdor/lazor/src')
-rw-r--r-- | zephyr/program/trogdor/lazor/src/hibernate.c | 48 | ||||
-rw-r--r-- | zephyr/program/trogdor/lazor/src/i2c.c | 17 | ||||
-rw-r--r-- | zephyr/program/trogdor/lazor/src/power.c | 59 | ||||
-rw-r--r-- | zephyr/program/trogdor/lazor/src/sku.c | 92 | ||||
-rw-r--r-- | zephyr/program/trogdor/lazor/src/switchcap.c | 128 | ||||
-rw-r--r-- | zephyr/program/trogdor/lazor/src/usb_pd_policy.c | 261 | ||||
-rw-r--r-- | zephyr/program/trogdor/lazor/src/usbc_config.c | 334 |
7 files changed, 0 insertions, 939 deletions
diff --git a/zephyr/program/trogdor/lazor/src/hibernate.c b/zephyr/program/trogdor/lazor/src/hibernate.c deleted file mode 100644 index 388ff1b087..0000000000 --- a/zephyr/program/trogdor/lazor/src/hibernate.c +++ /dev/null @@ -1,48 +0,0 @@ -/* Copyright 2022 The ChromiumOS Authors - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "common.h" -#include "sku.h" -#include "system.h" -#include "usbc_ppc.h" - -void board_hibernate(void) -{ - int i; - - if (!board_is_clamshell()) { - /* - * Sensors are unpowered in hibernate. Apply PD to the - * interrupt lines such that they don't float. - */ - gpio_pin_configure_dt( - GPIO_DT_FROM_NODELABEL(gpio_accel_gyro_int_l), - GPIO_DISCONNECTED); - gpio_pin_configure_dt( - GPIO_DT_FROM_NODELABEL(gpio_lid_accel_int_l), - GPIO_DISCONNECTED); - } - - /* - * Board rev 5+ has the hardware fix. Don't need the following - * workaround. - */ - if (system_get_board_version() >= 5) - return; - - /* - * Enable the PPC power sink path before EC enters hibernate; - * otherwise, ACOK won't go High and can't wake EC up. Check the - * bug b/170324206 for details. - */ - for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) - ppc_vbus_sink_enable(i, 1); -} - -void board_hibernate_late(void) -{ - /* Set the hibernate GPIO to turn off the rails */ - gpio_pin_set_dt(GPIO_DT_FROM_NODELABEL(gpio_hibernate_l), 0); -} diff --git a/zephyr/program/trogdor/lazor/src/i2c.c b/zephyr/program/trogdor/lazor/src/i2c.c deleted file mode 100644 index e572bbdf37..0000000000 --- a/zephyr/program/trogdor/lazor/src/i2c.c +++ /dev/null @@ -1,17 +0,0 @@ -/* Copyright 2021 The ChromiumOS Authors - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "i2c.h" -#include "i2c/i2c.h" - -/* Lazor board specific i2c implementation */ - -#ifdef CONFIG_PLATFORM_EC_I2C_PASSTHRU_RESTRICTED -int board_allow_i2c_passthru(const struct i2c_cmd_desc_t *cmd_desc) -{ - return (i2c_get_device_for_port(cmd_desc->port) == - i2c_get_device_for_port(I2C_PORT_VIRTUAL_BATTERY)); -} -#endif diff --git a/zephyr/program/trogdor/lazor/src/power.c b/zephyr/program/trogdor/lazor/src/power.c deleted file mode 100644 index ee99c77196..0000000000 --- a/zephyr/program/trogdor/lazor/src/power.c +++ /dev/null @@ -1,59 +0,0 @@ -/* Copyright 2022 The ChromiumOS Authors - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "gpio.h" -#include "power.h" -#include "task.h" - -#include <zephyr/drivers/gpio.h> -#include <zephyr/init.h> - -#include <ap_power/ap_power.h> - -static void board_power_change(struct ap_power_ev_callback *cb, - struct ap_power_ev_data data) -{ - switch (data.event) { - default: - return; - - case AP_POWER_PRE_INIT: - /* Turn on the 3.3V rail */ - gpio_pin_set_dt(GPIO_DT_FROM_NODELABEL(gpio_en_pp3300_a), 1); - - /* Turn on the 5V rail. */ -#ifdef CONFIG_POWER_PP5000_CONTROL - power_5v_enable(task_get_current(), 1); -#else /* !defined(CONFIG_POWER_PP5000_CONTROL) */ - gpio_pin_set_dt(GPIO_DT_FROM_NODELABEL(gpio_en_pp5000_a), 1); -#endif /* defined(CONFIG_POWER_PP5000_CONTROL) */ - break; - - case AP_POWER_SHUTDOWN_COMPLETE: - /* Turn off the 5V rail. */ -#ifdef CONFIG_POWER_PP5000_CONTROL - power_5v_enable(task_get_current(), 0); -#else /* !defined(CONFIG_POWER_PP5000_CONTROL) */ - gpio_pin_set_dt(GPIO_DT_FROM_NODELABEL(gpio_en_pp5000_a), 0); -#endif /* defined(CONFIG_POWER_PP5000_CONTROL) */ - - /* Turn off the 3.3V and 5V rails. */ - gpio_pin_set_dt(GPIO_DT_FROM_NODELABEL(gpio_en_pp3300_a), 0); - break; - } -} - -static int board_power_handler_init(const struct device *unused) -{ - static struct ap_power_ev_callback cb; - - /* Setup a suspend/resume callback */ - ap_power_ev_init_callback(&cb, board_power_change, - AP_POWER_PRE_INIT | - AP_POWER_SHUTDOWN_COMPLETE); - ap_power_ev_add_callback(&cb); - return 0; -} -SYS_INIT(board_power_handler_init, APPLICATION, 1); diff --git a/zephyr/program/trogdor/lazor/src/sku.c b/zephyr/program/trogdor/lazor/src/sku.c deleted file mode 100644 index a6187d422f..0000000000 --- a/zephyr/program/trogdor/lazor/src/sku.c +++ /dev/null @@ -1,92 +0,0 @@ -/* Copyright 2022 The ChromiumOS Authors - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "common.h" -#include "config.h" -#include "console.h" -#include "driver/ln9310.h" -#include "hooks.h" -#include "sku.h" -#include "system.h" -#include "tcpm/ps8xxx_public.h" -#include "util.h" - -#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) -#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) - -static uint8_t sku_id; - -enum board_model { - LAZOR, - LIMOZEEN, - UNKNOWN, -}; - -static const char *const model_name[] = { - "LAZOR", - "LIMOZEEN", - "UNKNOWN", -}; - -static enum board_model get_model(void) -{ - if (sku_id == 0 || sku_id == 1 || sku_id == 2 || sku_id == 3) - return LAZOR; - if (sku_id == 4 || sku_id == 5 || sku_id == 6) - return LIMOZEEN; - return UNKNOWN; -} - -/* Read SKU ID from GPIO and initialize variables for board variants */ -static void sku_init(void) -{ - sku_id = system_get_sku_id(); - CPRINTS("SKU: %u (%s)", sku_id, model_name[get_model()]); -} -DECLARE_HOOK(HOOK_INIT, sku_init, HOOK_PRIO_POST_I2C); - -enum battery_cell_type board_get_battery_cell_type(void) -{ - switch (get_model()) { - case LIMOZEEN: - return BATTERY_CELL_TYPE_3S; - default: - return BATTERY_CELL_TYPE_UNKNOWN; - } -} - -int board_is_clamshell(void) -{ - return get_model() == LIMOZEEN; -} - -__override uint16_t board_get_ps8xxx_product_id(int port) -{ - /* - * Lazor (SKU_ID: 0, 1, 2, 3) rev 3+ changes TCPC from PS8751 to - * PS8805. - * - * Limozeen (SKU_ID: 4, 5, 6) all-rev uses PS8805. - */ - if (get_model() == LAZOR && system_get_board_version() < 3) - return PS8751_PRODUCT_ID; - - return PS8805_PRODUCT_ID; -} - -int board_has_da9313(void) -{ - return get_model() == LAZOR; -} - -int board_has_buck_ic(void) -{ - return get_model() == LIMOZEEN && system_get_board_version() >= 8; -} - -int board_has_ln9310(void) -{ - return get_model() == LIMOZEEN && system_get_board_version() < 8; -} diff --git a/zephyr/program/trogdor/lazor/src/switchcap.c b/zephyr/program/trogdor/lazor/src/switchcap.c deleted file mode 100644 index 77413fb336..0000000000 --- a/zephyr/program/trogdor/lazor/src/switchcap.c +++ /dev/null @@ -1,128 +0,0 @@ -/* Copyright 2022 The ChromiumOS Authors - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "common.h" -#include "config.h" -#include "console.h" -#include "driver/ln9310.h" -#include "gpio/gpio_int.h" -#include "hooks.h" -#include "i2c.h" -#include "power/qcom.h" -#include "sku.h" -#include "system.h" - -#include <zephyr/drivers/gpio.h> - -#define CPRINTS(format, args...) cprints(CC_I2C, format, ##args) -#define CPRINTF(format, args...) cprintf(CC_I2C, format, ##args) - -/* LN9310 switchcap */ -const struct ln9310_config_t ln9310_config = { - .i2c_port = I2C_PORT_POWER, - .i2c_addr_flags = LN9310_I2C_ADDR_0_FLAGS, -}; - -static void switchcap_init(void) -{ - if (board_has_da9313()) { - CPRINTS("Use switchcap: DA9313"); - - /* - * When the chip in power down mode, it outputs high-Z. - * Set pull-down to avoid floating. - */ - gpio_pin_configure_dt(GPIO_DT_FROM_NODELABEL(gpio_da9313_gpio0), - GPIO_INPUT | GPIO_PULL_DOWN); - - /* - * Configure DA9313 enable, push-pull output. Don't set the - * level here; otherwise, it will override its value and - * shutdown the switchcap when sysjump to RW. - */ - gpio_pin_configure_dt(GPIO_DT_FROM_NODELABEL(gpio_switchcap_on), - GPIO_OUTPUT); - } else if (board_has_ln9310()) { - CPRINTS("Use switchcap: LN9310"); - - /* Enable interrupt for LN9310 */ - gpio_enable_dt_interrupt( - GPIO_INT_FROM_NODELABEL(int_switchcap_pg)); - - /* - * Configure LN9310 enable, open-drain output. Don't set the - * level here; otherwise, it will override its value and - * shutdown the switchcap when sysjump to RW. - * - * Note that the gpio.inc configures it GPIO_OUT_LOW. When - * sysjump to RW, will output push-pull a short period of - * time. As it outputs LOW, should be fine. - * - * This GPIO changes like: - * (1) EC boots from RO -> high-Z - * (2) GPIO init according to gpio.inc -> push-pull LOW - * (3) This function configures it -> open-drain HIGH - * (4) Power sequence turns on the switchcap -> open-drain LOW - * (5) EC sysjumps to RW - * (6) GPIO init according to gpio.inc -> push-pull LOW - * (7) This function configures it -> open-drain LOW - */ - gpio_pin_configure_dt(GPIO_DT_FROM_NODELABEL(gpio_switchcap_on), - GPIO_OUTPUT | GPIO_OPEN_DRAIN); - - /* Only configure the switchcap if not sysjump */ - if (!system_jumped_late()) { - /* - * Deassert the enable pin, so the - * switchcap won't be enabled after the switchcap is - * configured from standby mode to switching mode. - */ - gpio_pin_set_dt( - GPIO_DT_FROM_NODELABEL(gpio_switchcap_on), 0); - ln9310_init(); - } - } else if (board_has_buck_ic()) { - CPRINTS("Use Buck IC"); - } else { - CPRINTS("ERROR: No switchcap solution"); - } -} -DECLARE_HOOK(HOOK_INIT, switchcap_init, HOOK_PRIO_DEFAULT); - -void board_set_switchcap_power(int enable) -{ - if (board_has_da9313()) { - gpio_pin_set_dt(GPIO_DT_FROM_NODELABEL(gpio_switchcap_on), - enable); - } else if (board_has_ln9310()) { - gpio_pin_set_dt(GPIO_DT_FROM_NODELABEL(gpio_switchcap_on), - enable); - ln9310_software_enable(enable); - } else if (board_has_buck_ic()) { - gpio_pin_set_dt(GPIO_DT_FROM_NODELABEL(gpio_vbob_en), enable); - } -} - -int board_is_switchcap_enabled(void) -{ - if (board_has_da9313() || board_has_ln9310()) - return gpio_pin_get_dt( - GPIO_DT_FROM_NODELABEL(gpio_switchcap_on)); - - /* Board has buck ic*/ - return gpio_pin_get_dt(GPIO_DT_FROM_NODELABEL(gpio_vbob_en)); -} - -int board_is_switchcap_power_good(void) -{ - if (board_has_da9313()) - return gpio_pin_get_dt( - GPIO_DT_FROM_NODELABEL(gpio_da9313_gpio0)); - else if (board_has_ln9310()) - return ln9310_power_good(); - - /* Board has buck ic no way to check POWER GOOD */ - return 1; -} diff --git a/zephyr/program/trogdor/lazor/src/usb_pd_policy.c b/zephyr/program/trogdor/lazor/src/usb_pd_policy.c deleted file mode 100644 index 32e3376ca0..0000000000 --- a/zephyr/program/trogdor/lazor/src/usb_pd_policy.c +++ /dev/null @@ -1,261 +0,0 @@ -/* Copyright 2022 The ChromiumOS Authors - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "charge_manager.h" -#include "chipset.h" -#include "console.h" -#include "system.h" -#include "usb_mux.h" -#include "usbc_ppc.h" -#include "util.h" - -#include <zephyr/drivers/gpio.h> - -#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) -#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) - -int pd_check_vconn_swap(int port) -{ - /* In G3, do not allow vconn swap since PP5000 rail is off */ - return gpio_pin_get_dt(GPIO_DT_FROM_NODELABEL(gpio_en_pp5000_a)); -} - -static uint8_t vbus_en[CONFIG_USB_PD_PORT_MAX_COUNT]; -#if CONFIG_USB_PD_PORT_MAX_COUNT == 1 -static uint8_t vbus_rp[CONFIG_USB_PD_PORT_MAX_COUNT] = { TYPEC_RP_1A5 }; -#else -static uint8_t vbus_rp[CONFIG_USB_PD_PORT_MAX_COUNT] = { TYPEC_RP_1A5, - TYPEC_RP_1A5 }; -#endif - -static void board_vbus_update_source_current(int port) -{ - /* Both port are controlled by PPC SN5S330. */ - ppc_set_vbus_source_current_limit(port, vbus_rp[port]); - ppc_vbus_source_enable(port, vbus_en[port]); -} - -void pd_power_supply_reset(int port) -{ - int prev_en; - - prev_en = vbus_en[port]; - - /* Disable VBUS */ - vbus_en[port] = 0; - board_vbus_update_source_current(port); - - /* Enable discharge if we were previously sourcing 5V */ - if (prev_en) - pd_set_vbus_discharge(port, 1); - - /* notify host of power info change */ - pd_send_host_event(PD_EVENT_POWER_CHANGE); -} - -int pd_set_power_supply_ready(int port) -{ - /* Disable charging */ - board_vbus_sink_enable(port, 0); - - pd_set_vbus_discharge(port, 0); - - /* Provide VBUS */ - vbus_en[port] = 1; - board_vbus_update_source_current(port); - - /* notify host of power info change */ - pd_send_host_event(PD_EVENT_POWER_CHANGE); - - return EC_SUCCESS; /* we are ready */ -} - -int board_vbus_source_enabled(int port) -{ - return vbus_en[port]; -} - -__override void typec_set_source_current_limit(int port, enum tcpc_rp_value rp) -{ - vbus_rp[port] = rp; - board_vbus_update_source_current(port); -} - -int pd_snk_is_vbus_provided(int port) -{ - return tcpm_check_vbus_level(port, VBUS_PRESENT); -} - -/* ----------------- Vendor Defined Messages ------------------ */ -#ifdef CONFIG_USB_PD_ALT_MODE_DFP -__override int svdm_dp_config(int port, uint32_t *payload) -{ - int opos = pd_alt_mode(port, TCPCI_MSG_SOP, USB_SID_DISPLAYPORT); - uint8_t pin_mode = get_dp_pin_mode(port); - - if (!pin_mode) - return 0; - - /* - * Defer setting the usb_mux until HPD goes high, svdm_dp_attention(). - * The AP only supports one DP phy. An external DP mux switches between - * the two ports. Should switch those muxes when it is really used, - * i.e. HPD high; otherwise, the real use case is preempted, like: - * (1) plug a dongle without monitor connected to port-0, - * (2) plug a dongle without monitor connected to port-1, - * (3) plug a monitor to the port-1 dongle. - */ - - payload[0] = - VDO(USB_SID_DISPLAYPORT, 1, CMD_DP_CONFIG | VDO_OPOS(opos)); - payload[1] = VDO_DP_CFG(pin_mode, /* pin mode */ - 1, /* DPv1.3 signaling */ - 2); /* UFP connected */ - return 2; -}; - -__override void svdm_dp_post_config(int port) -{ - dp_flags[port] |= DP_FLAGS_DP_ON; -} - -/** - * Is the port fine to be muxed its DisplayPort lines? - * - * Only one port can be muxed to DisplayPort at a time. - * - * @param port Port number of TCPC. - * @return 1 is fine; 0 is bad as other port is already muxed; - */ -static int is_dp_muxable(int port) -{ - int i; - - for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) - if (i != port) { - if (usb_mux_get(i) & USB_PD_MUX_DP_ENABLED) - return 0; - } - - return 1; -} - -__override int svdm_dp_attention(int port, uint32_t *payload) -{ - const struct gpio_dt_spec *hpd = - GPIO_DT_FROM_NODELABEL(gpio_dp_hot_plug_det); - int lvl = PD_VDO_DPSTS_HPD_LVL(payload[1]); - int irq = PD_VDO_DPSTS_HPD_IRQ(payload[1]); - int cur_lvl = gpio_pin_get_dt(hpd); - mux_state_t mux_state; - - dp_status[port] = payload[1]; - - if (!is_dp_muxable(port)) { - /* TODO(waihong): Info user? */ - CPRINTS("p%d: The other port is already muxed.", port); - return 0; - } - - /* - * Initial implementation to handle HPD. Only the first-plugged port - * works, i.e. sending HPD signal to AP. The second-plugged port - * will be ignored. - * - * TODO(waihong): Continue the above case, if the first-plugged port - * is then unplugged, switch to the second-plugged port and signal AP? - */ - if (lvl) { - /* - * Enable and switch the DP port selection mux to the - * correct port. - * - * TODO(waihong): Better to move switching DP mux to - * the usb_mux abstraction. - */ - gpio_pin_set_dt(GPIO_DT_FROM_NODELABEL(gpio_dp_mux_sel), - port == 1); - gpio_pin_set_dt(GPIO_DT_FROM_NODELABEL(gpio_dp_mux_oe_l), 0); - - /* Connect the SBU lines in PPC chip. */ - if (IS_ENABLED(CONFIG_USBC_PPC_SBU)) - ppc_set_sbu(port, 1); - - /* - * Connect the USB SS/DP lines in TCPC chip. - * - * When mf_pref not true, still use the dock muxing - * because of the board USB-C topology (limited to 2 - * lanes DP). - */ - usb_mux_set(port, USB_PD_MUX_DOCK, USB_SWITCH_CONNECT, - polarity_rm_dts(pd_get_polarity(port))); - } else { - /* Disconnect the DP port selection mux. */ - gpio_pin_set_dt(GPIO_DT_FROM_NODELABEL(gpio_dp_mux_oe_l), 1); - gpio_pin_set_dt(GPIO_DT_FROM_NODELABEL(gpio_dp_mux_sel), 0); - - /* Disconnect the SBU lines in PPC chip. */ - if (IS_ENABLED(CONFIG_USBC_PPC_SBU)) - ppc_set_sbu(port, 0); - - /* Disconnect the DP but keep the USB SS lines in TCPC chip. */ - usb_mux_set(port, USB_PD_MUX_USB_ENABLED, USB_SWITCH_CONNECT, - polarity_rm_dts(pd_get_polarity(port))); - } - - if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND) && (irq || lvl)) - /* - * Wake up the AP. IRQ or level high indicates a DP sink is now - * present. - */ - pd_notify_dp_alt_mode_entry(port); - - /* Configure TCPC for the HPD event, for proper muxing */ - mux_state = (lvl ? USB_PD_MUX_HPD_LVL : USB_PD_MUX_HPD_LVL_DEASSERTED) | - (irq ? USB_PD_MUX_HPD_IRQ : USB_PD_MUX_HPD_IRQ_DEASSERTED); - usb_mux_hpd_update(port, mux_state); - - /* Signal AP for the HPD event, through GPIO to AP */ - if (irq & cur_lvl) { - uint64_t now = get_time().val; - /* Wait for the minimum spacing between IRQ_HPD if needed */ - if (now < svdm_hpd_deadline[port]) - usleep(svdm_hpd_deadline[port] - now); - - /* Generate IRQ_HPD pulse */ - gpio_pin_set_dt(hpd, 0); - usleep(HPD_DSTREAM_DEBOUNCE_IRQ); - gpio_pin_set_dt(hpd, 1); - - /* Set the minimum time delay (2ms) for the next HPD IRQ */ - svdm_hpd_deadline[port] = - get_time().val + HPD_USTREAM_DEBOUNCE_LVL; - } else if (irq & !lvl) { - CPRINTF("ERR:HPD:IRQ&LOW\n"); - return 0; - } - gpio_pin_set_dt(hpd, lvl); - /* Set the minimum time delay (2ms) for the next HPD IRQ */ - svdm_hpd_deadline[port] = get_time().val + HPD_USTREAM_DEBOUNCE_LVL; - - return 1; -} - -__override void svdm_exit_dp_mode(int port) -{ - if (is_dp_muxable(port)) { - /* Disconnect the DP port selection mux. */ - gpio_pin_set_dt(GPIO_DT_FROM_NODELABEL(gpio_dp_mux_oe_l), 1); - gpio_pin_set_dt(GPIO_DT_FROM_NODELABEL(gpio_dp_mux_sel), 0); - - /* Signal AP for the HPD low event */ - usb_mux_hpd_update(port, USB_PD_MUX_HPD_LVL_DEASSERTED | - USB_PD_MUX_HPD_IRQ_DEASSERTED); - gpio_pin_set_dt(GPIO_DT_FROM_NODELABEL(gpio_dp_hot_plug_det), - 0); - } -} -#endif /* CONFIG_USB_PD_ALT_MODE_DFP */ diff --git a/zephyr/program/trogdor/lazor/src/usbc_config.c b/zephyr/program/trogdor/lazor/src/usbc_config.c deleted file mode 100644 index d7d5ca2cc1..0000000000 --- a/zephyr/program/trogdor/lazor/src/usbc_config.c +++ /dev/null @@ -1,334 +0,0 @@ -/* Copyright 2022 The ChromiumOS Authors - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Lazor board-specific USB-C configuration */ - -#include "battery_fuel_gauge.h" -#include "bc12/pi3usb9201_public.h" -#include "charge_manager.h" -#include "charge_state.h" -#include "charger.h" -#include "charger/isl923x_public.h" -#include "common.h" -#include "config.h" -#include "driver/ln9310.h" -#include "gpio/gpio_int.h" -#include "gpio_signal.h" -#include "hooks.h" -#include "ppc/sn5s330_public.h" -#include "system.h" -#include "tcpm/ps8xxx_public.h" -#include "tcpm/tcpci.h" -#include "timer.h" -#include "usb_mux.h" -#include "usb_pd.h" -#include "usbc_ocp.h" -#include "usbc_ppc.h" - -#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ##args) -#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) - -int charger_profile_override(struct charge_state_data *curr) -{ - int usb_mv; - int port; - - if (curr->state != ST_CHARGE) - return 0; - - /* Lower the max requested voltage to 5V when battery is full. */ - if (chipset_in_state(CHIPSET_STATE_ANY_OFF) && - !(curr->batt.flags & BATT_FLAG_BAD_STATUS) && - !(curr->batt.flags & BATT_FLAG_WANT_CHARGE) && - (curr->batt.status & STATUS_FULLY_CHARGED)) - usb_mv = 5000; - else - usb_mv = PD_MAX_VOLTAGE_MV; - - if (pd_get_max_voltage() != usb_mv) { - CPRINTS("VBUS limited to %dmV", usb_mv); - for (port = 0; port < CONFIG_USB_PD_PORT_MAX_COUNT; port++) - pd_set_external_voltage_limit(port, usb_mv); - } - - return 0; -} - -enum ec_status charger_profile_override_get_param(uint32_t param, - uint32_t *value) -{ - return EC_RES_INVALID_PARAM; -} - -enum ec_status charger_profile_override_set_param(uint32_t param, - uint32_t value) -{ - return EC_RES_INVALID_PARAM; -} - -static void usba_oc_deferred(void) -{ - /* Use next number after all USB-C ports to indicate the USB-A port */ - board_overcurrent_event( - CONFIG_USB_PD_PORT_MAX_COUNT, - !gpio_pin_get_dt(GPIO_DT_FROM_NODELABEL(gpio_usb_a0_oc_odl))); -} -DECLARE_DEFERRED(usba_oc_deferred); - -void usba_oc_interrupt(enum gpio_signal signal) -{ - hook_call_deferred(&usba_oc_deferred_data, 0); -} - -void ppc_interrupt(enum gpio_signal signal) -{ - switch (signal) { - case GPIO_SIGNAL(DT_NODELABEL(gpio_usb_c0_swctl_int_odl)): - sn5s330_interrupt(0); - break; - case GPIO_SIGNAL(DT_NODELABEL(gpio_usb_c1_swctl_int_odl)): - sn5s330_interrupt(1); - break; - default: - break; - } -} - -static void board_connect_c0_sbu_deferred(void) -{ - /* - * If CCD_MODE_ODL asserts, it means there's a debug accessory connected - * and we should enable the SBU FETs. - */ - ppc_set_sbu(0, 1); -} -DECLARE_DEFERRED(board_connect_c0_sbu_deferred); - -void board_connect_c0_sbu(enum gpio_signal s) -{ - hook_call_deferred(&board_connect_c0_sbu_deferred_data, 0); -} - -/* GPIO Interrupt Handlers */ -void tcpc_alert_event(enum gpio_signal signal) -{ - int port = -1; - - switch (signal) { - case GPIO_USB_C0_PD_INT_ODL: - port = 0; - break; - case GPIO_USB_C1_PD_INT_ODL: - port = 1; - break; - default: - return; - } - - schedule_deferred_pd_interrupt(port); -} - -/* - * Port-0/1 USB mux driver. - * - * The USB mux is handled by TCPC chip and the HPD update is through a GPIO - * to AP. But the TCPC chip is also needed to know the HPD status; otherwise, - * the mux misbehaves. - */ -const struct usb_mux_chain usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = { - { - .mux = - &(const struct usb_mux){ - .usb_port = 0, - .driver = &tcpci_tcpm_usb_mux_driver, - .hpd_update = &ps8xxx_tcpc_update_hpd_status, - }, - }, - { - .mux = - &(const struct usb_mux){ - .usb_port = 1, - .driver = &tcpci_tcpm_usb_mux_driver, - .hpd_update = &ps8xxx_tcpc_update_hpd_status, - }, - } -}; - -__override int board_get_default_battery_type(void) -{ - /* - * A 2S battery is set as default. If the board is configured to use - * a 3S battery, according to its SKU_ID, return a 3S battery as - * default. It helps to configure the charger to output a correct - * voltage in case the battery is not attached. - */ - if (board_get_battery_cell_type() == BATTERY_CELL_TYPE_3S) - return BATTERY_LGC_AP18C8K; - - return DEFAULT_BATTERY_TYPE; -} - -/* Initialize board USC-C things */ -static void board_init_usbc(void) -{ - /* Enable USB-A overcurrent interrupt */ - gpio_enable_dt_interrupt(GPIO_INT_FROM_NODELABEL(int_usb_a0_oc)); - /* - * The H1 SBU line for CCD are behind PPC chip. The PPC internal FETs - * for SBU may be disconnected after DP alt mode is off. Should enable - * the CCD_MODE_ODL interrupt to make sure the SBU FETs are connected. - */ - gpio_enable_dt_interrupt(GPIO_INT_FROM_NODELABEL(int_ccd_mode)); -} -DECLARE_HOOK(HOOK_INIT, board_init_usbc, HOOK_PRIO_DEFAULT); - -void board_tcpc_init(void) -{ - /* Only reset TCPC if not sysjump */ - if (!system_jumped_late()) { - /* TODO(crosbug.com/p/61098): How long do we need to wait? */ - board_reset_pd_mcu(); - } - - /* Enable PPC interrupts */ - gpio_enable_dt_interrupt(GPIO_INT_FROM_NODELABEL(int_usb_c0_swctl)); - - /* Enable TCPC interrupts */ - gpio_enable_dt_interrupt(GPIO_INT_FROM_NODELABEL(int_usb_c0_tcpc)); - gpio_enable_dt_interrupt(GPIO_INT_FROM_NODELABEL(int_usb_c1_tcpc)); - - /* - * Initialize HPD to low; after sysjump SOC needs to see - * HPD pulse to enable video path - */ - for (int port = 0; port < CONFIG_USB_PD_PORT_MAX_COUNT; ++port) - usb_mux_hpd_update(port, USB_PD_MUX_HPD_LVL_DEASSERTED | - USB_PD_MUX_HPD_IRQ_DEASSERTED); -} -DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_POST_I2C); - -void board_reset_pd_mcu(void) -{ - cprints(CC_USB, "Resetting TCPCs..."); - cflush(); - - gpio_pin_set_dt(GPIO_DT_FROM_NODELABEL(gpio_usb_c0_pd_rst_l), 0); - gpio_pin_set_dt(GPIO_DT_FROM_NODELABEL(gpio_usb_c1_pd_rst_l), 0); - msleep(PS8XXX_RESET_DELAY_MS); - gpio_pin_set_dt(GPIO_DT_FROM_NODELABEL(gpio_usb_c0_pd_rst_l), 1); - gpio_pin_set_dt(GPIO_DT_FROM_NODELABEL(gpio_usb_c1_pd_rst_l), 1); -} - -void board_set_tcpc_power_mode(int port, int mode) -{ - /* Ignore the "mode" to turn the chip on. We can only do a reset. */ - if (mode) - return; - - board_reset_pd_mcu(); -} - -int board_vbus_sink_enable(int port, int enable) -{ - /* Both ports are controlled by PPC SN5S330 */ - return ppc_vbus_sink_enable(port, enable); -} - -int board_is_sourcing_vbus(int port) -{ - /* Both ports are controlled by PPC SN5S330 */ - return ppc_is_sourcing_vbus(port); -} - -void board_overcurrent_event(int port, int is_overcurrented) -{ - /* TODO(b/120231371): Notify AP */ - CPRINTS("p%d: overcurrent!", port); -} - -int board_set_active_charge_port(int port) -{ - int is_real_port = (port >= 0 && port < CONFIG_USB_PD_PORT_MAX_COUNT); - int i; - - if (!is_real_port && port != CHARGE_PORT_NONE) - return EC_ERROR_INVAL; - - if (port == CHARGE_PORT_NONE) { - CPRINTS("Disabling all charging port"); - - /* Disable all ports. */ - for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) { - /* - * Do not return early if one fails otherwise we can - * get into a boot loop assertion failure. - */ - if (board_vbus_sink_enable(i, 0)) - CPRINTS("Disabling p%d sink path failed.", i); - } - - return EC_SUCCESS; - } - - /* Check if the port is sourcing VBUS. */ - if (board_is_sourcing_vbus(port)) { - CPRINTS("Skip enable p%d", port); - return EC_ERROR_INVAL; - } - - CPRINTS("New charge port: p%d", port); - - /* - * Turn off the other ports' sink path FETs, before enabling the - * requested charge port. - */ - for (i = 0; i < CONFIG_USB_PD_PORT_MAX_COUNT; i++) { - if (i == port) - continue; - - if (board_vbus_sink_enable(i, 0)) - CPRINTS("p%d: sink path disable failed.", i); - } - - /* Enable requested charge port. */ - if (board_vbus_sink_enable(port, 1)) { - CPRINTS("p%d: sink path enable failed.", port); - return EC_ERROR_UNKNOWN; - } - - return EC_SUCCESS; -} - -__override void board_set_charge_limit(int port, int supplier, int charge_ma, - int max_ma, int charge_mv) -{ - /* - * Ignore lower charge ceiling on PD transition if our battery is - * critical, as we may brownout. - */ - if (supplier == CHARGE_SUPPLIER_PD && charge_ma < 1500 && - charge_get_percent() < CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON) { - CPRINTS("Using max ilim %d", max_ma); - charge_ma = max_ma; - } - - charge_set_input_current_limit(charge_ma, charge_mv); -} - -uint16_t tcpc_get_alert_status(void) -{ - uint16_t status = 0; - - if (!gpio_pin_get_dt(GPIO_DT_FROM_NODELABEL(gpio_usb_c0_pd_int_odl))) - if (gpio_pin_get_dt( - GPIO_DT_FROM_NODELABEL(gpio_usb_c0_pd_rst_l))) - status |= PD_STATUS_TCPC_ALERT_0; - if (!gpio_pin_get_dt(GPIO_DT_FROM_NODELABEL(gpio_usb_c1_pd_int_odl))) - if (gpio_pin_get_dt( - GPIO_DT_FROM_NODELABEL(gpio_usb_c1_pd_rst_l))) - status |= PD_STATUS_TCPC_ALERT_1; - - return status; -} |