diff options
-rw-r--r-- | baseboard/volteer/baseboard.c | 189 | ||||
-rw-r--r-- | baseboard/volteer/baseboard.h | 64 | ||||
-rw-r--r-- | baseboard/volteer/build.mk | 1 | ||||
-rw-r--r-- | baseboard/volteer/usb_pd_policy.c | 210 | ||||
-rw-r--r-- | board/volteer/board.h | 8 | ||||
-rw-r--r-- | board/volteer/ec.tasklist | 5 | ||||
-rw-r--r-- | board/volteer/gpio.inc | 3 |
7 files changed, 477 insertions, 3 deletions
diff --git a/baseboard/volteer/baseboard.c b/baseboard/volteer/baseboard.c index 2c914b0fa5..cc32ff4b4d 100644 --- a/baseboard/volteer/baseboard.c +++ b/baseboard/volteer/baseboard.c @@ -5,12 +5,27 @@ /* Volteer family-specific configuration */ #include "adc_chip.h" +#include "charge_manager.h" #include "charge_state.h" +#include "driver/ppc/sn5s330.h" +#include "driver/tcpm/tusb422.h" #include "gpio.h" +#include "hooks.h" #include "i2c.h" #include "keyboard_scan.h" #include "pwm.h" #include "pwm_chip.h" +#include "usbc_ppc.h" +#include "usb_mux.h" +#include "usb_pd.h" +#include "usb_pd_tcpm.h" +#include "util.h" + +#define CPRINTS(format, args...) cprints(CC_CHIPSET, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_CHIPSET, format, ## args) + +#define CPRINTSUSB(format, args...) cprints(CC_USBCHARGE, format, ## args) +#define CPRINTFUSB(format, args...) cprintf(CC_USBCHARGE, format, ## args) /******************************************************************************/ /* ADC configuration */ @@ -123,6 +138,8 @@ const struct i2c_port_t i2c_ports[] = { }; const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); +/******************************************************************************/ +/* PWM configuration */ const struct pwm_t pwm_channels[] = { [PWM_CH_LED1_BLUE] = { .channel = 2, @@ -141,3 +158,175 @@ const struct pwm_t pwm_channels[] = { }, }; BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); + + + + + +/******************************************************************************/ +/* USBC TCPC configuration */ +const struct tcpc_config_t tcpc_config[] = { + [USBC_PORT_C0] = { + .bus_type = EC_BUS_TYPE_I2C, + .i2c_info = { + .port = I2C_PORT_USB_C0, + .addr_flags = TUSB422_I2C_ADDR_FLAGS, + }, + .drv = &tusb422_tcpm_drv, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(tcpc_config) == USBC_PORT_COUNT); +BUILD_ASSERT(CONFIG_USB_PD_PORT_MAX_COUNT == USBC_PORT_COUNT); + +/******************************************************************************/ +/* USBC PPC configuration */ +struct ppc_config_t ppc_chips[] = { + [USBC_PORT_C0] = { + .i2c_port = I2C_PORT_USB_C0, + .i2c_addr_flags = SN5S330_ADDR0_FLAGS, + .drv = &sn5s330_drv + }, +}; +BUILD_ASSERT(ARRAY_SIZE(ppc_chips) == USBC_PORT_COUNT); +unsigned int ppc_cnt = ARRAY_SIZE(ppc_chips); + +/******************************************************************************/ +/* USBC mux configuration - Tiger Lake includes internal mux */ +struct usb_mux usb_muxes[] = { + [USBC_PORT_C0] = { + .driver = &virtual_usb_mux_driver, + }, +}; +BUILD_ASSERT(ARRAY_SIZE(usb_muxes) == USBC_PORT_COUNT); + + +static void baseboard_tcpc_init(void) +{ + /* Enable PPC interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_PPC_INT_ODL); + + /* Enable TCPC interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_TCPC_INT_ODL); +} +DECLARE_HOOK(HOOK_INIT, baseboard_tcpc_init, HOOK_PRIO_INIT_I2C + 1); + +/******************************************************************************/ +/* PPC support routines */ +void ppc_interrupt(enum gpio_signal signal) +{ + switch (signal) { + case GPIO_USB_C0_PPC_INT_ODL: + sn5s330_interrupt(USBC_PORT_C0); + break; + + default: + break; + } +} + +/******************************************************************************/ +/* TCPC support routines */ +void board_reset_pd_mcu(void) +{ + /* No reset available for TCPC on port 0 */ +} + +uint16_t tcpc_get_alert_status(void) +{ + uint16_t status = 0; + + /* + * Check which port has the ALERT line set + */ + if (!gpio_get_level(GPIO_USB_C0_TCPC_INT_ODL)) + status |= PD_STATUS_TCPC_ALERT_0; + + return status; +} + +void tcpc_alert_event(enum gpio_signal signal) +{ + /* TODO: b/140572591 - check correct operation for Volteer */ + + int port = -1; + + switch (signal) { + case GPIO_USB_C0_TCPC_INT_ODL: + port = 0; + break; + default: + return; + } + + schedule_deferred_pd_interrupt(port); +} + +int board_set_active_charge_port(int port) +{ + /* TODO: b/140561826 - check correct operation for Volteer */ + + int is_valid_port = (port >= 0 && + port < CONFIG_USB_PD_PORT_MAX_COUNT); + int i; + + if (port == CHARGE_PORT_NONE) { + CPRINTSUSB("Disabling all charger ports"); + + /* Disable all ports. */ + for (i = 0; i < ppc_cnt; i++) { + /* + * Do not return early if one fails otherwise we can + * get into a boot loop assertion failure. + */ + if (ppc_vbus_sink_enable(i, 0)) + CPRINTSUSB("Disabling C%d as sink failed.", i); + } + + return EC_SUCCESS; + } else if (!is_valid_port) { + return EC_ERROR_INVAL; + } + + + /* Check if the port is sourcing VBUS. */ + if (ppc_is_sourcing_vbus(port)) { + CPRINTFUSB("Skip enable C%d", port); + return EC_ERROR_INVAL; + } + + CPRINTSUSB("New charge port: C%d", port); + + /* + * Turn off the other ports' sink path FETs, before enabling the + * requested charge port. + */ + for (i = 0; i < ppc_cnt; i++) { + if (i == port) + continue; + + if (ppc_vbus_sink_enable(i, 0)) + CPRINTSUSB("C%d: sink path disable failed.", i); + } + + /* Enable requested charge port. */ + if (ppc_vbus_sink_enable(port, 1)) { + CPRINTSUSB("C%d: sink path enable failed.", port); + return EC_ERROR_UNKNOWN; + } + + return EC_SUCCESS; +} + +void board_set_charge_limit(int port, int supplier, int charge_ma, + int max_ma, int charge_mv) +{ + charge_set_input_current_limit(MAX(charge_ma, + CONFIG_CHARGER_INPUT_CURRENT), + charge_mv); +} + +void board_overcurrent_event(int port, int is_overcurrented) +{ + /* TODO: b/140561826 - check correct operation for Volteer */ +} + diff --git a/baseboard/volteer/baseboard.h b/baseboard/volteer/baseboard.h index 9c638577c2..585be60309 100644 --- a/baseboard/volteer/baseboard.h +++ b/baseboard/volteer/baseboard.h @@ -8,7 +8,6 @@ #ifndef __CROS_EC_BASEBOARD_H #define __CROS_EC_BASEBOARD_H - /* NPCX7 config */ #define NPCX7_PWM1_SEL 0 /* GPIO C2 is not used as PWM1. */ #define NPCX_UART_MODULE2 1 /* GPIO64/65 are used as UART pins. */ @@ -64,6 +63,7 @@ /* Sensors */ /* Common charger defines */ +#define CONFIG_CHARGE_MANAGER #define CONFIG_CHARGER #define CONFIG_CHARGER_DISCHARGE_ON_AC #define CONFIG_CHARGER_INPUT_CURRENT 512 @@ -78,8 +78,54 @@ /* #define CONFIG_BATTERY_CUT_OFF */ /* USB Type C and USB PD defines */ +/* Enable the new USB-C PD stack */ +#define CONFIG_USB_SM_FRAMEWORK +#define CONFIG_USB_TYPEC_SM +#define CONFIG_USB_PRL_SM +#define CONFIG_USB_PE_SM +#define CONFIG_USB_TYPEC_DRP_ACC_TRYSRC + +#define CONFIG_USB_POWER_DELIVERY +#define CONFIG_USB_PD_DISCHARGE_PPC +#define CONFIG_USB_PD_DUAL_ROLE +#define CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT TYPEC_RP_3A0 +#define CONFIG_USB_PD_PORT_MAX_COUNT 1 +#define CONFIG_USB_PD_TCPC_LOW_POWER +#define CONFIG_USB_PD_TCPM_TCPCI +#define CONFIG_USB_PD_TCPM_TUSB422 /* USBC port C0 */ +#define CONFIG_USB_PD_TRY_SRC +#define CONFIG_USB_PD_VBUS_DETECT_PPC +#define CONFIG_USB_PD_VBUS_MEASURE_NOT_PRESENT + +#define CONFIG_USBC_PPC +#define CONFIG_CMD_PPC_DUMP +/* Note - SN5S330 support automatically adds + * CONFIG_USBC_PPC_POLARITY + * CONFIG_USBC_PPC_SBU + * CONFIG_USBC_PPC_VCONN + */ +#define CONFIG_USBC_PPC_SN5S330 /* USBC port C0 */ + +#define CONFIG_USBC_SS_MUX +#define CONFIG_USB_MUX_VIRTUAL + +#define CONFIG_USBC_VCONN +#define CONFIG_USBC_VCONN_SWAP + +/* TODO: b/144165680 - measure and check these values on Volteer */ +#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ +#define PD_POWER_SUPPLY_TURN_OFF_DELAY 30000 /* us */ +#define PD_VCONN_SWAP_DELAY 5000 /* us */ + +/* + * SN5S30 PPC supports up to 24V VBUS source and sink, however passive USB-C + * cables only support up to 60W. + */ +#define PD_OPERATING_POWER_MW 15000 +#define PD_MAX_POWER_MW 60000 +#define PD_MAX_CURRENT_MA 3000 +#define PD_MAX_VOLTAGE_MV 20000 -/* BC 1.2 */ /* I2C Bus Configuration */ #define CONFIG_I2C @@ -99,6 +145,9 @@ #ifndef __ASSEMBLER__ +#include "gpio_signal.h" + + enum adc_channel { ADC_TEMP_SENSOR_1_CHARGER, ADC_TEMP_SENSOR_2_PP3300_REGULATOR, @@ -114,6 +163,17 @@ enum pwm_channel { PWM_CH_COUNT }; +enum usbc_port { + USBC_PORT_C0 = 0, + USBC_PORT_COUNT +}; + +void board_reset_pd_mcu(void); + +/* Common definition for the USB PD interrupt handlers. */ +void ppc_interrupt(enum gpio_signal signal); +void tcpc_alert_event(enum gpio_signal signal); + #endif /* !__ASSEMBLER__ */ #endif /* __CROS_EC_BASEBOARD_H */ diff --git a/baseboard/volteer/build.mk b/baseboard/volteer/build.mk index 296bc15520..ee12262052 100644 --- a/baseboard/volteer/build.mk +++ b/baseboard/volteer/build.mk @@ -9,3 +9,4 @@ baseboard-y=baseboard.o baseboard-y+=led.o baseboard-y+=battery_presence.o +baseboard-y+=usb_pd_policy.o diff --git a/baseboard/volteer/usb_pd_policy.c b/baseboard/volteer/usb_pd_policy.c new file mode 100644 index 0000000000..ac424984e4 --- /dev/null +++ b/baseboard/volteer/usb_pd_policy.c @@ -0,0 +1,210 @@ +/* Copyright 2019 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ +/* Shared USB-C policy for Volteer boards */ +#include "charge_manager.h" +#include "compile_time_macros.h" +#include "console.h" +#include "gpio.h" +#include "usb_mux.h" +#include "usbc_ppc.h" +#include "usb_pd.h" +#include "system.h" + +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) + +/* + * TODO(b/140578872): Whole file copied from zork. Figure out correct values for + * volteer. + */ +#define PDO_FIXED_FLAGS (PDO_FIXED_DUAL_ROLE | PDO_FIXED_DATA_SWAP |\ + PDO_FIXED_COMM_CAP) +const uint32_t pd_src_pdo[] = { + PDO_FIXED(5000, 1500, PDO_FIXED_FLAGS), +}; +const uint32_t pd_src_pdo_max[] = { + PDO_FIXED(5000, 3000, PDO_FIXED_FLAGS), +}; +const int pd_src_pdo_max_cnt = ARRAY_SIZE(pd_src_pdo_max); + +const int pd_src_pdo_cnt = ARRAY_SIZE(pd_src_pdo); +const uint32_t pd_snk_pdo[] = { + PDO_FIXED(5000, 500, PDO_FIXED_FLAGS), + PDO_BATT(4750, 21000, 15000), + PDO_VAR(4750, 21000, 3000), +}; +const int pd_snk_pdo_cnt = ARRAY_SIZE(pd_snk_pdo); +int pd_check_data_swap(int port, int data_role) +{ + /* Allow data swap if we are a UFP, otherwise don't allow. */ + return (data_role == PD_ROLE_UFP); +} + +int pd_check_power_swap(int port) +{ + /* TODO - check correct operation for Volteer */ + + /* + * Allow power swap if we are acting as a dual role device. If we are + * not acting as dual role (ex. suspended), then only allow power swap + * if we are sourcing when we could be sinking. + */ + if (pd_get_dual_role(port) == PD_DRP_TOGGLE_ON) + return 1; + else if (pd_get_role(port) == PD_ROLE_SOURCE) + return 1; + else + return 0; +} + +int pd_check_vconn_swap(int port) +{ + /* TODO - check correct operation for Volteer */ + return 0; +} + +void pd_power_supply_reset(int port) +{ + /* TODO - check correct operation for Volteer */ +} + +void pd_execute_data_swap(int port, int data_role) +{ + /* TODO - check correct operation for Volteer */ + + /* Do nothing */ +} + +int pd_is_valid_input_voltage(int mv) +{ + /* TODO - check correct operation for Volteer */ + + return 1; +} + +int pd_set_power_supply_ready(int port) +{ + int rv; + + /* Disable charging. */ + rv = ppc_vbus_sink_enable(port, 0); + if (rv) + return rv; + + pd_set_vbus_discharge(port, 0); + + /* Provide Vbus. */ + rv = ppc_vbus_source_enable(port, 1); + if (rv) + return rv; + +#ifdef CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT + /* Ensure we advertise the proper available current quota */ + charge_manager_source_port(port, 1); +#endif /* defined(CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT) */ + + /* Notify host of power info change. */ + pd_send_host_event(PD_EVENT_POWER_CHANGE); + + return EC_SUCCESS; +} + +void pd_transition_voltage(int idx) +{ + /* TODO - check correct operation for Volteer */ + + /* No-operation: we are always 5V */ +} + +int pd_snk_is_vbus_provided(int port) +{ + return ppc_is_vbus_present(port); +} + +void typec_set_source_current_limit(int port, enum tcpc_rp_value rp) +{ + ppc_set_vbus_source_current_limit(port, rp); +} + +int board_vbus_source_enabled(int port) +{ + return ppc_is_sourcing_vbus(port); +} + + +/* ----------------- Vendor Defined Messages ------------------ */ +const struct svdm_response svdm_rsp = { + .identity = NULL, + .svids = NULL, + .modes = NULL, +}; + +int pd_custom_vdm(int port, int cnt, uint32_t *payload, + uint32_t **rpayload) +{ + /* TODO - check correct operation for Volteer */ + + int cmd = PD_VDO_CMD(payload[0]); + uint16_t dev_id = 0; + int is_rw, is_latest; + + /* make sure we have some payload */ + if (cnt == 0) + return 0; + + switch (cmd) { + case VDO_CMD_VERSION: + /* guarantee last byte of payload is null character */ + *(payload + cnt - 1) = 0; + CPRINTF("version: %s\n", (char *)(payload+1)); + break; + case VDO_CMD_READ_INFO: + case VDO_CMD_SEND_INFO: + /* copy hash */ + if (cnt == 7) { + dev_id = VDO_INFO_HW_DEV_ID(payload[6]); + is_rw = VDO_INFO_IS_RW(payload[6]); + + is_latest = pd_dev_store_rw_hash(port, + dev_id, + payload + 1, + is_rw ? + SYSTEM_IMAGE_RW : + SYSTEM_IMAGE_RO); + /* + * Send update host event unless our RW hash is + * already known to be the latest update RW. + */ + if (!is_rw || !is_latest) + pd_send_host_event(PD_EVENT_UPDATE_DEVICE); + + CPRINTF("DevId:%d.%d SW:%d RW:%d\n", + HW_DEV_ID_MAJ(dev_id), + HW_DEV_ID_MIN(dev_id), + VDO_INFO_SW_DBG_VER(payload[6]), + is_rw); + } else if (cnt == 6) { + /* really old devices don't have last byte */ + pd_dev_store_rw_hash(port, dev_id, payload + 1, + SYSTEM_IMAGE_UNKNOWN); + } + break; + case VDO_CMD_CURRENT: + CPRINTF("Current: %dmA\n", payload[1]); + break; + case VDO_CMD_FLIP: + usb_mux_flip(port); + break; +#ifdef CONFIG_USB_PD_LOGGING + case VDO_CMD_GET_LOG: + pd_log_recv_vdm(port, cnt, payload); + break; +#endif /* CONFIG_USB_PD_LOGGING */ + } + + return 0; +} + + diff --git a/board/volteer/board.h b/board/volteer/board.h index 0d645c99c3..06d13e1526 100644 --- a/board/volteer/board.h +++ b/board/volteer/board.h @@ -22,6 +22,14 @@ #define CONFIG_POWER_BUTTON +/* + * USB ID + * TODO(b/140578872): Figure out what volteer's is. + * This is allocated specifically for Zork:Trembyle + * http://google3/hardware/standards/usb/ + */ +#define CONFIG_USB_PID 0x503E + #undef CONFIG_UART_TX_BUF_SIZE #define CONFIG_UART_TX_BUF_SIZE 4096 diff --git a/board/volteer/ec.tasklist b/board/volteer/ec.tasklist index ebb4205d6c..d5f38958eb 100644 --- a/board/volteer/ec.tasklist +++ b/board/volteer/ec.tasklist @@ -12,7 +12,10 @@ TASK_ALWAYS(CHARGER, charger_task, NULL, VENTI_TASK_STACK_SIZE) \ TASK_NOTEST(KEYPROTO, keyboard_protocol_task, NULL, TASK_STACK_SIZE) \ TASK_NOTEST(CHIPSET, chipset_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_NOTEST(PDCMD, pd_command_task, NULL, LARGER_TASK_STACK_SIZE) \ TASK_ALWAYS(HOSTCMD, host_command_task, NULL, LARGER_TASK_STACK_SIZE) \ TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE) \ TASK_ALWAYS(POWERBTN, power_button_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, TASK_STACK_SIZE) + TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_C0, pd_task, NULL, VENTI_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD_INT_C0, pd_interrupt_handler_task, 0, TASK_STACK_SIZE) diff --git a/board/volteer/gpio.inc b/board/volteer/gpio.inc index 5ce78773b6..e9575587c0 100644 --- a/board/volteer/gpio.inc +++ b/board/volteer/gpio.inc @@ -32,6 +32,8 @@ GPIO_INT(PG_EC_ALL_SYS_PWRGD, PIN(F, 4), GPIO_INT_BOTH, power_signal_interrupt /* Sensor Interrupts */ /* USB-C interrupts */ +GPIO_INT(USB_C0_TCPC_INT_ODL, PIN(E, 0), GPIO_INT_BOTH, tcpc_alert_event) +GPIO_INT(USB_C0_PPC_INT_ODL, PIN(6, 2), GPIO_INT_BOTH, ppc_interrupt) /* HDMI interrupts */ @@ -81,6 +83,7 @@ GPIO(SYS_RST_ODL, PIN(C, 5), GPIO_ODR_HIGH) GPIO(EC_PCH_INT_ODL, PIN(D, 6), GPIO_ODR_HIGH) /* TODO - b/140557015 - implement with MKBD sensor events */ /* USB and USBC Signals */ +GPIO(EN_PP3300_AG, PIN(8, 5), GPIO_OUT_LOW) /* Misc Signals */ /* This selects between an LED module on the motherboard and one on the daughter |