diff options
Diffstat (limited to 'baseboard/honeybuns')
-rw-r--r-- | baseboard/honeybuns/baseboard.c | 489 | ||||
-rw-r--r-- | baseboard/honeybuns/baseboard.h | 330 | ||||
-rw-r--r-- | baseboard/honeybuns/build.mk | 11 | ||||
-rw-r--r-- | baseboard/honeybuns/usb_pd_policy.c | 638 | ||||
-rw-r--r-- | baseboard/honeybuns/usbc_support.c | 480 |
5 files changed, 0 insertions, 1948 deletions
diff --git a/baseboard/honeybuns/baseboard.c b/baseboard/honeybuns/baseboard.c deleted file mode 100644 index df56697fbf..0000000000 --- a/baseboard/honeybuns/baseboard.c +++ /dev/null @@ -1,489 +0,0 @@ -/* Copyright 2020 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. - */ - -/* Honeybuns family-specific configuration */ -#include "console.h" -#include "cros_board_info.h" -#include "driver/mp4245.h" -#include "gpio.h" -#include "hooks.h" -#include "i2c.h" -#include "usb_pd.h" -#include "system.h" -#include "task.h" -#include "timer.h" -#include "usbc_ppc.h" -#include "driver/tcpm/tcpm.h" -#include "util.h" - -#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ## args) - -#define POWER_BUTTON_SHORT_USEC (300 * MSEC) -#define POWER_BUTTON_LONG_USEC (5000 * MSEC) -#define POWER_BUTTON_DEBOUNCE_USEC (30) - -#define BUTTON_EVT_CHANGE BIT(0) -#define BUTTON_EVT_INFO BIT(1) - -enum power { - POWER_OFF, - POWER_ON -}; - -enum button { - BUTTON_RELEASE, - BUTTON_PRESS, - BUTTON_PRESS_POWER_ON, - BUTTON_PRESS_SHORT, - BUTTON_PRESS_LONG, -}; - -#define LED_ON_OFF_BIT BIT(0) -#define LED_COLOR_BIT BIT(2) -#define LED_FLASH_SEQ_LENGTH 8 - -enum led_color { - GREEN, - YELLOW, - OFF, -}; - -static enum power dock_state; -#ifdef SECTION_IS_RW -static int button_level; -static int button_level_pending; -static int dock_mf; -static int led_count; -#endif - -/******************************************************************************/ - -__maybe_unused static void board_power_sequence(int enable) -{ - int i; - - if (enable) { - for(i = 0; i < board_power_seq_count; i++) { - gpio_set_level(board_power_seq[i].signal, - board_power_seq[i].level); - CPRINTS("power seq: rail = %d", i); - if (board_power_seq[i].delay_ms) - msleep(board_power_seq[i].delay_ms); - } - } else { - for(i = board_power_seq_count - 1; i >= 0; i--) { - gpio_set_level(board_power_seq[i].signal, - !board_power_seq[i].level); - CPRINTS("sequence[%d]: level = %d", i, - !board_power_seq[i].level); - } - } - - dock_state = enable; - CPRINTS("board: Power rails %s", dock_state ? "on" : "off"); -} - -/******************************************************************************/ -/* I2C port map configuration */ -const struct i2c_port_t i2c_ports[] = { - {"i2c1", I2C_PORT_I2C1, 400, GPIO_EC_I2C1_SCL, GPIO_EC_I2C1_SDA}, - {"i2c3", I2C_PORT_I2C3, 400, GPIO_EC_I2C3_SCL, GPIO_EC_I2C3_SDA}, -}; -const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); - -#ifdef SECTION_IS_RW -static void baseboard_set_led(enum led_color color) -{ - /* - * TODO(b/164157329): The power button feature should be connected to a - * 2 color LED which is part of the button. Currently, the power button - * LED is a single color LED which is controlled by on the of the power - * rails. Using the status LED now to demonstrate the LED behavior - * associated with a power button press. - */ - CPRINTS("led: color = %d", color); - - /* Not all boards may have LEDs under EC control */ -#if defined(GPIO_PWR_BUTTON_RED) && defined(GPIO_PWR_BUTTON_GREEN) - if (color == OFF) { - gpio_set_level(GPIO_PWR_BUTTON_RED, 1); - gpio_set_level(GPIO_PWR_BUTTON_GREEN, 1); - } else if (color == GREEN) { - gpio_set_level(GPIO_PWR_BUTTON_RED, 1); - gpio_set_level(GPIO_PWR_BUTTON_GREEN, 0); - } else if (color == YELLOW) { - gpio_set_level(GPIO_PWR_BUTTON_RED, 0); - gpio_set_level(GPIO_PWR_BUTTON_GREEN, 0); - } -#endif -} - -static void baseboard_led_callback(void); -DECLARE_DEFERRED(baseboard_led_callback); - -static void baseboard_led_callback(void) -{ - /* - * Flash LED on transition using a simple 3 bit counter. Bit 0 controls - * LED on/off and bit 2 controls which color to set during the on phase. - */ - int color = led_count & LED_COLOR_BIT ? dock_mf : dock_mf ^ 1; - - /* - * TODO(b/164157329): This function implements a simple flashing - * transition when the MF preference bit is changed via a long power - * button press sequence. This might need to move to the board function - * if not required/desired on all variants. - */ - - if (led_count & LED_ON_OFF_BIT) - baseboard_set_led(color); - else - baseboard_set_led(OFF); - - /* Flash sequence is 8 steps */ - if (++led_count < LED_FLASH_SEQ_LENGTH) - hook_call_deferred(&baseboard_led_callback_data, 150 * MSEC); -} - -static void baseboard_change_mf_led(void) -{ - led_count = 0; - baseboard_led_callback(); -} - -void baseboard_set_mst_lane_control(int mf) -{ - /* - * The parameter mf reflects the desired lane control value. If the - * current value does not match the desired, then the MST hub must first - * be put into reset, so the MST hub will latch in the correct value - * when it's taken out of reset. - */ - if (mf != gpio_get_level(GPIO_MST_HUB_LANE_SWITCH)) { - /* put MST into reset */ - gpio_set_level(GPIO_MST_RST_L, 0); - msleep(1); - gpio_set_level(GPIO_MST_HUB_LANE_SWITCH, mf); - CPRINTS("MST: lane control = %s", mf ? "high" : "low"); - msleep(1); - /* lane control is set, take MST out of reset */ - gpio_set_level(GPIO_MST_RST_L, 1); - } -} - -static void baseboard_enable_mp4245(void) -{ - int mv; - int ma; - - mp4245_set_voltage_out(5000); - mp4245_votlage_out_enable(1); - msleep(MP4245_VOUT_5V_DELAY_MS); - mp3245_get_vbus(&mv, &ma); - CPRINTS("mp4245: vout @ %d mV enabled", mv); -} - -#endif /* SECTION_IS_RW */ - -static void baseboard_init(void) -{ -#ifdef SECTION_IS_RW - uint32_t fw_config; -#endif - - /* Turn on power rails */ - board_power_sequence(1); - CPRINTS("board: Power rails enabled"); - -#ifdef SECTION_IS_RW - /* Force TC state machine to start in TC_ERROR_RECOVERY */ - system_clear_reset_flags(EC_RESET_FLAG_POWER_ON); - /* Make certain SN5S330 PPC does full initialization */ - system_set_reset_flags(EC_RESET_FLAG_EFS); - - /* - * Dock multi function (mf) preference is stored in bit 0 of fw_config - * field of the CBI. If this value is programmed, then make sure the - * MST_LANE_CONTROL gpio matches the mf bit. - */ - if (!cbi_get_fw_config(&fw_config)) { - dock_mf = CBI_FW_MF_PREFERENCE(fw_config); - baseboard_set_mst_lane_control(dock_mf); - } else { - dock_mf = dock_get_mf_preference(); - cbi_set_fw_config(dock_mf); - CPRINTS("cbi: setting default result = %s", - cbi_get_fw_config(&fw_config) ? "pass" : "fail"); - } - -#ifdef GPIO_USBC_UF_ATTACHED_SRC - /* Configure UF usbc ppc and check usbc state */ - baseboard_config_usbc_usb3_ppc(); -#endif /* GPIO_USBC_UF_ATTACHED_SRC */ - - /* Enable power button interrupt */ - gpio_enable_interrupt(GPIO_PWR_BTN); - /* Set dock mf preference LED */ - baseboard_set_led(dock_mf); - /* Setup VBUS to default value */ - baseboard_enable_mp4245(); - -#else - /* Set up host port usbc to present Rd on CC lines */ - if(baseboard_usbc_init(USB_PD_PORT_HOST)) - CPRINTS("usbc: Failed to set up sink path"); - else - CPRINTS("usbc: sink path configure success!"); -#endif /* SECTION_IS_RW */ -} -/* - * Power sequencing must run before any other chip init is attempted, so run - * power sequencing as soon as I2C bus is initialized. - */ -DECLARE_HOOK(HOOK_INIT, baseboard_init, HOOK_PRIO_INIT_I2C + 1); - -#ifdef SECTION_IS_RW -static void baseboard_power_on(void) -{ - int port_max = board_get_usb_pd_port_count(); - int port; - - CPRINTS("pwrbtn: power on: mf = %d", dock_mf); - /* Adjust system flags to full PPC init occurs */ - system_clear_reset_flags(EC_RESET_FLAG_POWER_ON); - system_set_reset_flags(EC_RESET_FLAG_EFS); - /* Enable power rails and release reset signals */ - board_power_sequence(1); - /* Set VBUS to 5V and enable output from mp4245 */ - baseboard_enable_mp4245(); - /* Set dock mf preference LED */ - baseboard_set_led(dock_mf); - /* - * Lane control (realtek MST) must be set prior to releasing MST - * reset. - */ - baseboard_set_mst_lane_control(dock_mf); - /* - * When the power to the PPC is turned off, then back on, the PPC will - * default into dead battery mode. Dead battery resistors are disabled - * as part of the full PPC intializaiton sequence. This is required to - * force a detach event with port parter which can be attached as usbc - * source when honeybuns power rails are off. - */ - for (port = 0; port < port_max; port++) { - ppc_init(port); - msleep(1000); - /* Inform TC state machine that it can resume */ - pd_set_suspend(port, 0); - } - /* Enable usbc interrupts */ - board_enable_usbc_interrupts(); - -#ifdef GPIO_USBC_UF_ATTACHED_SRC - baseboard_config_usbc_usb3_ppc(); -#endif -} - -static void baseboard_power_off(void) -{ - int port_max = board_get_usb_pd_port_count(); - int port; - - CPRINTS("pwrbtn: power off"); - /* Put ports in TC suspend state */ - for (port = 0; port < port_max; port++) - pd_set_suspend(port, 1); - - /* Disable ucpd peripheral (prevents interrupts) */ - tcpm_release(USB_PD_PORT_HOST); - /* Disable PPC/TCPC interrupts */ - board_disable_usbc_interrupts(); - -#ifdef GPIO_USBC_UF_ATTACHED_SRC - /* Disable PPC interrupts for PS8803 managed port */ - baseboard_usbc_usb3_enable_interrupts(0); -#endif - /* Set dock power button/MF preference LED */ - baseboard_set_led(OFF); - /* Go into power off state */ - board_power_sequence(0); -} - -static void baseboard_toggle_mf(void) -{ - uint32_t fw_config; - - if (!cbi_get_fw_config(&fw_config)) { - /* Update the user MF preference stored in CBI */ - fw_config ^= CBI_FW_MF_MASK; - cbi_set_fw_config(fw_config); - /* Update variable used to track user MF preference */ - dock_mf = CBI_FW_MF_PREFERENCE(fw_config); - /* Flash led for visual indication of user MF change */ - baseboard_change_mf_led(); - - /* - * Suspend, then release host port to force new MF setting to - * take effect. - */ - pd_set_suspend(USB_PD_PORT_HOST, 1); - msleep(250); - pd_set_suspend(USB_PD_PORT_HOST, 0); - } -} - -/* - * Main task entry point for UCPD task - */ -void power_button_task(void *u) -{ - int timer_us = POWER_BUTTON_DEBOUNCE_USEC * 4; - enum button state = BUTTON_RELEASE; - uint32_t evt; - - /* - * Capture current button level in case it's being pressed when the dock - * is powered on. Note timer_us is initialized for debounce time to - * double check. - */ - button_level = gpio_get_level(GPIO_PWR_BTN); - - while (1) { - evt = task_wait_event(timer_us); - timer_us = -1; - - if (evt == BUTTON_EVT_INFO) { - /* Only used for console command for debug */ - CPRINTS("pwrbtn: pwr = %d, state = %d, level = %d", - dock_state, state, button_level); - continue; - } - - switch (state) { - case BUTTON_RELEASE: - /* - * Default wait state: Only need to check if the button - * is pressed and start the short press timer. - */ - if (evt & BUTTON_EVT_CHANGE && button_level == - BUTTON_PRESSED_LEVEL) { - state = BUTTON_PRESS; - timer_us = (POWER_BUTTON_SHORT_USEC - - POWER_BUTTON_DEBOUNCE_USEC); - } - break; - case BUTTON_PRESS: - /* - * Validate short press by ensuring that button is still - * pressed after short press timer expires. - */ - if (evt & BUTTON_EVT_CHANGE && - button_level == BUTTON_RELEASED_LEVEL) { - state = BUTTON_RELEASE; - } else { - /* Start long press timer */ - timer_us = POWER_BUTTON_LONG_USEC - - POWER_BUTTON_SHORT_USEC; - /* - * If dock is currently off, then change to the - * power on state. If dock is already on, then - * advance to short press state. - */ - if (dock_state == POWER_OFF) { - baseboard_power_on(); - state = BUTTON_PRESS_POWER_ON; - } else { - state = BUTTON_PRESS_SHORT; - } - } - break; - case BUTTON_PRESS_POWER_ON: - /* - * Short press recognized and dock was just powered - * on. If button is no longer pressed, then just return - * to the default state. Else, button is still pressed - * after long press timer has expired. - */ - if (evt & BUTTON_EVT_CHANGE && - button_level == BUTTON_RELEASED_LEVEL) { - state = BUTTON_RELEASE; - } else { - state = BUTTON_PRESS_LONG; - baseboard_toggle_mf(); - } - break; - case BUTTON_PRESS_SHORT: - /* - * Short press was recognized and dock power state was - * already on. If button is now released, then turn dock - * off. - */ - if (evt & BUTTON_EVT_CHANGE && - button_level == BUTTON_RELEASED_LEVEL) { - state = BUTTON_RELEASE; - baseboard_power_off(); - } else { - state = BUTTON_PRESS_LONG; - baseboard_toggle_mf(); - } - break; - case BUTTON_PRESS_LONG: - if (evt & BUTTON_EVT_CHANGE && - button_level == BUTTON_RELEASED_LEVEL) { - state = BUTTON_RELEASE; - } - break; - } - } -} - -static void baseboard_power_button_debounce(void) -{ - int level = gpio_get_level(GPIO_PWR_BTN); - - /* Sanity check, level should be same after debounce interval */ - if (level != button_level_pending) - return; - - button_level = level; - task_set_event(TASK_ID_POWER_BUTTON, BUTTON_EVT_CHANGE); -} -DECLARE_DEFERRED(baseboard_power_button_debounce); - -void baseboard_power_button_evt(int level) -{ - button_level_pending = level; - - hook_call_deferred(&baseboard_power_button_debounce_data, - POWER_BUTTON_DEBOUNCE_USEC); -} - -static int command_pwr_btn(int argc, char **argv) -{ - - if (argc == 1) { - task_set_event(TASK_ID_POWER_BUTTON, BUTTON_EVT_INFO); - return EC_SUCCESS; - } - - if (!strcasecmp(argv[1], "on")) { - baseboard_power_on(); - } else if (!strcasecmp(argv[1], "off")) { - baseboard_power_off(); - } else if (!strcasecmp(argv[1], "mf")) { - baseboard_toggle_mf(); - } else { - return EC_ERROR_PARAM1; - } - - return EC_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(pwr_btn, command_pwr_btn, - "<on|off|mf>", - "Simulate Power Button Press"); - -#endif diff --git a/baseboard/honeybuns/baseboard.h b/baseboard/honeybuns/baseboard.h deleted file mode 100644 index 1b56b07f8c..0000000000 --- a/baseboard/honeybuns/baseboard.h +++ /dev/null @@ -1,330 +0,0 @@ -/* Copyright 2020 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. - */ - -/* Honeybuns baseboard configuration */ - -#ifndef __CROS_EC_BASEBOARD_H -#define __CROS_EC_BASEBOARD_H - -/* EC Defines */ -#define CONFIG_CRC8 - -/* Flash Lyaout */ -/* - * Flash layout: we redefine the sections offsets and sizes as we will use - * RO/RW regions of different sizes. - */ -#undef _IMAGE_SIZE -#undef CONFIG_ROLLBACK_OFF -#undef CONFIG_ROLLBACK_SIZE -#undef CONFIG_FLASH_PSTATE -#undef CONFIG_FW_PSTATE_SIZE -#undef CONFIG_FW_PSTATE_OFF -#undef CONFIG_SHAREDLIB_SIZE -#undef CONFIG_RO_MEM_OFF -#undef CONFIG_RO_STORAGE_OFF -#undef CONFIG_RO_SIZE -#undef CONFIG_RW_MEM_OFF -#undef CONFIG_RW_STORAGE_OFF -#undef CONFIG_RW_SIZE -#undef CONFIG_EC_PROTECTED_STORAGE_OFF -#undef CONFIG_EC_PROTECTED_STORAGE_SIZE -#undef CONFIG_EC_WRITABLE_STORAGE_OFF -#undef CONFIG_EC_WRITABLE_STORAGE_SIZE -#undef CONFIG_WP_STORAGE_OFF -#undef CONFIG_WP_STORAGE_SIZE - -#define CONFIG_FLASH_PSTATE -/* Do not use a dedicated PSTATE bank */ -#undef CONFIG_FLASH_PSTATE_BANK - -#define CONFIG_SHAREDLIB_SIZE 0 - -#define CONFIG_RO_MEM_OFF 0 -#define CONFIG_RO_STORAGE_OFF 0 -#define CONFIG_RO_SIZE (64*1024) - -#define CONFIG_RW_MEM_OFF (CONFIG_RO_SIZE + CONFIG_RO_MEM_OFF) -#define CONFIG_RW_STORAGE_OFF 0 -#define CONFIG_RW_SIZE (CONFIG_FLASH_SIZE_BYTES - \ - (CONFIG_RW_MEM_OFF - CONFIG_RO_MEM_OFF)) - -#define CONFIG_EC_PROTECTED_STORAGE_OFF CONFIG_RO_MEM_OFF -#define CONFIG_EC_PROTECTED_STORAGE_SIZE CONFIG_RO_SIZE -#define CONFIG_EC_WRITABLE_STORAGE_OFF CONFIG_RW_MEM_OFF -#define CONFIG_EC_WRITABLE_STORAGE_SIZE CONFIG_RW_SIZE - -#define CONFIG_WP_STORAGE_OFF CONFIG_EC_PROTECTED_STORAGE_OFF -#define CONFIG_WP_STORAGE_SIZE CONFIG_EC_PROTECTED_STORAGE_SIZE - -/* 48 MHz SYSCLK clock frequency */ -#define CPU_CLOCK 48000000 -#define CONFIG_STM_HWTIMER32 -#define TIM_CLOCK32 2 -#define TIM_CLOCK_MSB 3 -#define TIM_CLOCK_LSB 15 -#define TIM_WATCHDOG 7 - -/* Honeybuns platform does not have a lid switch */ -#undef CONFIG_LID_SWITCH - -/* USART and EC console configs */ -#undef CONFIG_UART_CONSOLE -#define CONFIG_UART_CONSOLE 3 -#define CONFIG_UART_TX_DMA -#undef CONFIG_UART_TX_BUF_SIZE -#define CONFIG_UART_TX_BUF_SIZE 2048 -#define CONFIG_UART_TX_DMA_CH STM32_DMAC_USART3_TX -#define CONFIG_UART_TX_DMA_PH DMAMUX_REQ_USART3_TX - -/* CBI Configs */ -#define I2C_ADDR_EEPROM_FLAGS 0x50 -#define CONFIG_CBI_EEPROM -#define CONFIG_BOARD_VERSION_CBI -#define CONFIG_CMD_CBI -#define CONFIG_EEPROM_CBI_WP -#define CONFIG_BYPASS_CBI_EEPROM_WP_CHECK -#define GPIO_EC_CBI_WP GPIO_EC_FLASH_WP_ODL -#define CBI_FW_MF_MASK BIT(0) -#define CBI_FW_MF_PREFERENCE(val) (val & (CBI_FW_MF_MASK)) - -/* USB Configuration */ -#define CONFIG_USB -#define CONFIG_STREAM_USB -#define CONFIG_USB_UPDATE -#define CONFIG_USB_SERIALNO -#define DEFAULT_SERIALNO "Uninitialized" -#define CONFIG_MAC_ADDR -#define DEFAULT_MAC_ADDR "Uninitialized" - -/* USB endpoint indexes (use define rather than enum to expand them) */ -#define USB_EP_CONTROL 0 -#define USB_EP_UPDATE 1 -#define USB_EP_COUNT 2 - -#define USB_IFACE_UPDATE 0 -#define USB_IFACE_COUNT 1 - -#ifndef __ASSEMBLER__ -/* USB string indexes */ -enum usb_strings { - USB_STR_DESC = 0, - USB_STR_VENDOR, - USB_STR_PRODUCT, - USB_STR_SERIALNO, - USB_STR_VERSION, - USB_STR_UPDATE_NAME, - USB_STR_COUNT -}; -#endif - -/* RW Specific Config Options */ -#ifdef SECTION_IS_RW -/* No AP on any honeybuns variants */ -#undef CONFIG_USB_PD_HOST_CMD - -/* USB Type C and USB PD defines */ -#define CONFIG_USB_POWER_DELIVERY -#define CONFIG_USB_PD_TCPMV2 -#define CONFIG_USB_DRP_ACC_TRYSRC -#define CONFIG_USB_PD_ALT_MODE -#define CONFIG_USB_PD_ALT_MODE_DFP -#define CONFIG_USB_PD_CUSTOM_PDO -#define CONFIG_USB_PD_ALT_MODE_UFP_DP -#define CONFIG_USB_PD_DUAL_ROLE -#define CONFIG_USB_PD_REV30 -/* - * Source current limit pull options. Honeybuns always wants TYPEC_RP_3A0 - * current limits for the usbc host port (C0). For port C1, some variants are - * designed with a 1.5A current limit. This variation is handled via - * BOARD_C1_1A5_LIMIT which would be set in a variant's board.h file. - * - * CONFIG_USB_PD_3A_PORTS should be left at 0 as this will disable DPM from - * doing any dynamic current limit management. - */ -#undef CONFIG_USB_PD_PULLUP -#define CONFIG_USB_PD_PULLUP TYPEC_RP_3A0 -#define CONFIG_USB_PD_3A_PORTS 0 -#define CONFIG_USB_PD_TCPM_MUX -#define CONFIG_USB_PD_TCPM_PS8805 -#define CONFIG_USB_PD_TCPM_STM32GX -#define CONFIG_USB_PD_TCPM_TCPCI -#define CONFIG_USB_PD_DECODE_SOP -#define CONFIG_USB_PD_VBUS_DETECT_PPC -#define CONFIG_USB_PD_DISCHARGE_PPC -#define CONFIG_USBC_PPC_SN5S330 -#define CONFIG_USBC_PPC_VCONN -#define CONFIG_USBC_PPC_DEDICATED_INT -#define CONFIG_USBC_VCONN -#define CONFIG_USBC_VCONN_SWAP -#define CONFIG_USBC_SS_MUX - -#define CONFIG_HAS_TASK_PD_INT -#define CONFIG_STM32G4_UCPD_DEBUG -#define CONFIG_CMD_PPC_DUMP -#define CONFIG_CMD_TCPC_DUMP - -#define CONFIG_MP4245 -#define USB_HUB_OCP_RESET_MSEC (10 * MSEC) - -#else /* RO Specific Config Options */ - -/* RWSIG Config Options */ -/* Sign and switch to RW partition on boot. */ -#define CONFIG_RWSIG -#define CONFIG_RSA -#define CONFIG_SHA256_UNROLLED -#undef CONFIG_RWSIG_JUMP_TIMEOUT -#define CONFIG_RWSIG_JUMP_TIMEOUT (7000 * MSEC) - -/* Don't build PD console command for RO */ -#undef CONFIG_CMD_PD -#undef CONFIG_USB_PD_CONSOLE_CMD -#undef CONFIG_USB_PD_HOST_CMD -/* Make sure these files aren't built in RO */ -#undef CONFIG_USB_PRL_SM -#undef CONFIG_USB_TYPEC_SM -#undef CONFIG_USB_PE_SM - -#endif /* SECTION_IS_RW */ - -#define CONFIG_RWSIG_TYPE_RWSIG -#define CONFIG_RSA_KEY_SIZE 3072 -#define CONFIG_RSA_EXPONENT_3 -#define CONFIG_SHA256 - -/* Define typical operating power and max power. */ -#define PD_MAX_VOLTAGE_MV 5000 -#define PD_MAX_CURRENT_MA 3000 -#define PD_MAX_POWER_MW 15000 -#define PD_OPERATING_POWER_MW 15000 - -/* TODO(b:147314141): Verify these timings */ -#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */ -#define PD_POWER_SUPPLY_TURN_OFF_DELAY 250000 /* us */ - -/* I2C Bus Configuration */ -#define CONFIG_I2C -#define CONFIG_I2C_CONTROLLER - -/* - * Macros for GPIO signals used in common code that don't match the - * schematic names. Signal names in gpio.inc match the schematic and are - * then redefined here to so it's more clear which signal is being used for - * which purpose. - */ -#define GPIO_ENTERING_RW GPIO_EC_ENTERING_RW -#define GPIO_WP_L GPIO_EC_WP_L - -#ifndef __ASSEMBLER__ - -#include "gpio_signal.h" -#include "stddef.h" - -struct power_seq { - enum gpio_signal signal; /* power/reset gpio_signal to control */ - int level; /* level to set in power sequence */ - unsigned int delay_ms; /* delay (in msec) after setting gpio_signal */ -}; - -enum mf_preference { - MF_OFF = 0, - MF_ON, -}; - -/* - * This is required as adc_channel is included in adc.h which ends up being - * included when TCPMv2 functions are included - */ -enum adc_channel { - ADC_CH_COUNT -}; - -extern const struct power_seq board_power_seq[]; -extern const size_t board_power_seq_count; - -void baseboard_power_button_evt(int level); - -/* - * Configure the host port to present Rd on both CC lines. This function is - * called in RO which does not otherwise have usbc/usb-pd support. - * - * @return true - initialized. false - not. - */ -int baseboard_usbc_init(int port); - -/* - * Get a board's desired multi-function (MF) prefernce. This allows for board - * specific policy. - * - * @return 1 if multi function (DP + USB3) is preferred, 0 otherwise - */ -int dock_get_mf_preference(void); - -/* - * Initialize and configure PPC used for USB3 only port - * - * @return EC success if PPC initialization is successful - */ -int baseboard_config_usbc_usb3_ppc(void); - -/* - * Called from interrupt handler for PS8803 attached.src gpio. This gpio signal - * will be set high by the PS8803 when it's in the attached.src state and low - * otherwise. For boards wich have a PPC on this port, this signal is used to - * enable/disable VBUS in the PPC. - */ -void baseboard_usb3_check_state(void); - - -/* - * Set MST_LANE_CONTROL gpio to match the DP pin configuration selected - * by the host in the DP Configure SVDM message. - * - * @param dock_mf 1 -> 2 lanes DP, 0 -> 4 lanes DP - */ -void baseboard_set_mst_lane_control(int dock_mf); - -/* - * Control enable/disable for interrupts used for usb3 only usbc port. - * - * @param enable -> 1 for enable, 0 for disable - */ -void baseboard_usbc_usb3_enable_interrupts(int enable); - -/* - * Called from interrupt handler for PPC used on usb3 only port. - * - */ -void baseboard_usbc_usb3_irq(void); - -/** - * Determine if VBUS is present or not. - * - * @param port: The Type-C port number. - * @return 1 if VBUS is present, 0 if not. - */ -int c1_ps8805_is_vbus_present(int port); - -/** - * Is the port sourcing Vbus? - * - * @param port: The Type-C port number. - * @return 1 if sourcing Vbus, 0 if not. - */ -int c1_ps8805_is_sourcing_vbus(int port); - -/** - * Turn on/off VBUS for port C1 - * - * @param port: The Type-C port number. - * @param enable: 1: Turn on VBUS, 0: turn off VBUS. - * @return EC_SUCCESS on success, error otherwise. - */ -int c1_ps8805_vbus_source_enable(int port, int enable); - -#endif /* !__ASSEMBLER__ */ - -#endif /* __CROS_EC_BASEBOARD_H */ diff --git a/baseboard/honeybuns/build.mk b/baseboard/honeybuns/build.mk deleted file mode 100644 index 2868911925..0000000000 --- a/baseboard/honeybuns/build.mk +++ /dev/null @@ -1,11 +0,0 @@ -# -*- makefile -*- -# Copyright 2020 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. -# -# Honeybuns baseboard specific files build -# - -baseboard-y=baseboard.o -baseboard-$(CONFIG_USB_POWER_DELIVERY)+=usb_pd_policy.o -baseboard-y+=usbc_support.o diff --git a/baseboard/honeybuns/usb_pd_policy.c b/baseboard/honeybuns/usb_pd_policy.c deleted file mode 100644 index ef2350a03d..0000000000 --- a/baseboard/honeybuns/usb_pd_policy.c +++ /dev/null @@ -1,638 +0,0 @@ -/* Copyright 2020 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. - */ - -#include "common.h" -#include "console.h" -#include "chip/stm32/ucpd-stm32gx.h" -#include "cros_board_info.h" -#include "driver/mp4245.h" -#include "driver/tcpm/tcpci.h" -#include "driver/mp4245.h" -#include "hooks.h" -#include "task.h" -#include "timer.h" -#include "usb_common.h" -#include "usb_mux.h" -#include "usb_pd.h" -#include "usb_pd_dp_ufp.h" -#include "usb_tc_sm.h" -#include "usbc_ppc.h" - -#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) -#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) - -#define MP4245_VOLTAGE_WINDOW BIT(2) -#define MP4245_VOLTAGE_WINDOW_MASK (MP4245_VOLTAGE_WINDOW - 1) - -#define PDO_FIXED_FLAGS (PDO_FIXED_DUAL_ROLE | PDO_FIXED_DATA_SWAP |\ - PDO_FIXED_COMM_CAP | PDO_FIXED_UNCONSTRAINED) - -/* Voltage indexes for the PDOs */ -enum volt_idx { - PDO_IDX_5V = 0, - PDO_IDX_9V = 1, - PDO_IDX_15V = 2, - PDO_IDX_20V = 3, - PDO_IDX_COUNT -}; - -/* PDOs */ -const uint32_t pd_src_host_pdo[] = { - [PDO_IDX_5V] = PDO_FIXED(5000, 3000, PDO_FIXED_FLAGS), - [PDO_IDX_9V] = PDO_FIXED(9000, 3000, 0), - [PDO_IDX_15V] = PDO_FIXED(15000, 3000, 0), - [PDO_IDX_20V] = PDO_FIXED(20000, 3000, 0), -}; -BUILD_ASSERT(ARRAY_SIZE(pd_src_host_pdo) == PDO_IDX_COUNT); - -#ifdef BOARD_C1_1A5_LIMIT -const uint32_t pd_src_display_pdo[] = { - [PDO_IDX_5V] = PDO_FIXED(5000, 1500, PDO_FIXED_FLAGS), -}; -#else -const uint32_t pd_src_display_pdo[] = { - [PDO_IDX_5V] = PDO_FIXED(5000, 3000, PDO_FIXED_FLAGS), -}; -#endif - -const uint32_t pd_snk_pdo[] = { - [PDO_IDX_5V] = PDO_FIXED(5000, 0, PDO_FIXED_FLAGS), -}; -const int pd_snk_pdo_cnt = ARRAY_SIZE(pd_snk_pdo); - -static int src_host_pdo_cnt_override; - -#define PD_DR_SWAP_ATTEMPT_MAX 3 -static int pd_dr_swap_attempt_count[CONFIG_USB_PD_PORT_MAX_COUNT]; - -static int command_hostpdo(int argc, char **argv) -{ - char *e; - int limit; - - if (argc >= 2) { - - limit = strtoi(argv[1], &e, 10); - if ((limit < 0) || (limit > PDO_IDX_COUNT)) - return EC_ERROR_PARAM1; - - src_host_pdo_cnt_override = limit; - } - ccprintf("src host pdo override = %d\n", src_host_pdo_cnt_override); - - return EC_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(hostpdo, command_hostpdo, - "<0|1|2|3|4>", - "Limit number of PDOs for C0"); - -int dpm_get_source_pdo(const uint32_t **src_pdo, const int port) -{ - int pdo_cnt = 0; - - if (port == USB_PD_PORT_HOST) { - *src_pdo = pd_src_host_pdo; - pdo_cnt = ARRAY_SIZE(pd_src_host_pdo); - /* - * This override is only active via a console command. Only used - * for debug to limit the level of VBUS offered to port partner - * if desired. The console command only allows 0 -> - * PDO_IDX_COUNT for this value. - */ - if (src_host_pdo_cnt_override) - pdo_cnt = src_host_pdo_cnt_override; - } else { - *src_pdo = pd_src_display_pdo; - pdo_cnt = ARRAY_SIZE(pd_src_display_pdo); - } - - return pdo_cnt; -} - -/* - * Default Port Discovery DR Swap Policy. - * - * 1) If port == 0 and port data role is DFP, transition to pe_drs_send_swap - * 2) If port == 1 and port data role is UFP, transition to pe_drs_send_swap - */ -__override bool port_discovery_dr_swap_policy(int port, - enum pd_data_role dr, bool dr_swap_flag) -{ - /* - * Port0: test if role is DFP - * Port1: test if role is UFP - */ - enum pd_data_role role_test = - (port == USB_PD_PORT_HOST) ? PD_ROLE_DFP : PD_ROLE_UFP; - - /* - * Request data role swap if not in the port's desired data role and if - * the attempt count is less than the max allowed. This function is - * called for each PE run once in a PD contract. If the port partner - * rejects data role swap requests (eg compliance tester), want to limit - * how many DR swap requests are attempted. - */ - if (dr == role_test && (pd_dr_swap_attempt_count[port]++ < - PD_DR_SWAP_ATTEMPT_MAX)) - return true; - - /* Do not perform a DR swap */ - return false; -} - -/* - * Default Port Discovery VCONN Swap Policy. - * - * 1) No need to Vconn swap. This board does not require any cable information. - */ -__override bool port_discovery_vconn_swap_policy(int port, - bool vconn_swap_flag) -{ - return false; -} - -int pd_check_vconn_swap(int port) -{ - /*TODO: Dock is the Vconn source */ - return 1; -} - -void pd_power_supply_reset(int port) -{ - int prev_en; - - if (port < 0 || port >= CONFIG_USB_PD_PORT_MAX_COUNT) - return; - - if (IS_ENABLED(BOARD_C1_NO_PPC) && port) { - prev_en = c1_ps8805_is_sourcing_vbus(port); - /* Disable VBUS via PPC. */ - c1_ps8805_vbus_source_enable(port, 0); - } else { - prev_en = ppc_is_sourcing_vbus(port); - /* Disable VBUS via PPC. */ - ppc_vbus_source_enable(port, 0); - } - - /* Enable discharge if we were previously sourcing 5V */ - if (prev_en) - pd_set_vbus_discharge(port, 1); - - if (port == USB_PD_PORT_HOST) { - int mv; - int ma; - int unused_mv; - - /* - * Because VBUS on C0 is turned on/off via the PPC, the - * voltage from the mp4245 does not need to be turned off, or - * set to 0V. Instead, reset VBUS voltage to default value - * (fixed 5V SRC_CAP) so VBUS is ready to be applied at the next - * attached.src condition. - */ - pd_extract_pdo_power(pd_src_host_pdo[0], &ma, &mv, - &unused_mv); - mp4245_set_voltage_out(mv); - /* Ensure voltage is back to 5V */ - pd_transition_voltage(1); - } -} - -int pd_set_power_supply_ready(int port) -{ - int rv; - - /* - * Note: For host port, the mp4245 output voltage is set for 5V by - * default and each time VBUS is turned off. VOUT from the mp4245 is - * left enabled as there is a switch (either PPC or discrete) to turn - * VBUS on/off on the wire. - */ - if (IS_ENABLED(BOARD_C1_NO_PPC) && port) - rv = c1_ps8805_vbus_source_enable(port, 1); - else - rv = ppc_vbus_source_enable(port, 1); - - if (rv) - return rv; - - return EC_SUCCESS; -} - -void pd_transition_voltage(int idx) -{ - int port = TASK_ID_TO_PD_PORT(task_get_current()); - int mv; - int target_mv; - int mv_average = 0; - int ma; - int vbus_hi; - int vbus_lo; - int i; - int mv_buffer[MP4245_VOLTAGE_WINDOW]; - - /* Only C0 can provide more than 5V */ - if (port != USB_PD_PORT_HOST) - return; - - /* - * Set the VBUS output voltage and current limit to the values specified - * by the PDO requested by sink. Note that USB PD uses idx = 1 for 1st - * PDO of SRC_CAP which must always be 5V fixed supply. - */ - pd_extract_pdo_power(pd_src_host_pdo[idx - 1], &ma, &target_mv, - &mv); - - /* Initialize sample delay buffer */ - for (i = 0; i < MP4245_VOLTAGE_WINDOW; i++) - mv_buffer[i] = 0; - - /* Set VBUS level to value specified in the requested PDO */ - mp4245_set_voltage_out(target_mv); - /* Wait for vbus to be within ~5% of its target value */ - vbus_hi = target_mv + (target_mv >> 4); - vbus_lo = target_mv - (target_mv >> 4); - - for (i = 0; i < 20; i++) { - /* Read current sample */ - mv = 0; - mp3245_get_vbus(&mv, &ma); - /* Add new sample to cicrcular delay buffer */ - mv_buffer[i & MP4245_VOLTAGE_WINDOW_MASK] = mv; - /* - * Don't compute average until sample delay buffer is - * full. - */ - if (i >= (MP4245_VOLTAGE_WINDOW_MASK)) { - int sum = 0; - int j; - - /* Sum the voltage samples */ - for (j = 0; j < MP4245_VOLTAGE_WINDOW; j++) - sum += mv_buffer[j]; - /* Add rounding */ - sum += MP4245_VOLTAGE_WINDOW / 2; - mv_average = sum / MP4245_VOLTAGE_WINDOW; - /* - * Check if average is within the target - * voltage range. - */ - if ((mv_average >= vbus_lo) && - (mv_average <= vbus_hi)) { - CPRINTS("usbc[%d]: VBUS to %d mV in %d steps", - port, target_mv, i); - return; - } - } - - /* - * The voltage ramp from 5V to 20V requires ~30 - * msec. The max loop count and this sleep time gives plenty - * of time for this change. - */ - msleep(2); - } - - CPRINTS("usbc[%d]: Vbus transition timeout: target = %d, measure = %d", - port, target_mv, mv_average); -} - -int pd_snk_is_vbus_provided(int port) -{ - if (IS_ENABLED(BOARD_C1_NO_PPC) && port) - return c1_ps8805_is_vbus_present(port); - else - return ppc_is_vbus_present(port); -} - -__override bool pd_check_vbus_level(int port, enum vbus_level level) -{ - if (level == VBUS_PRESENT) - return pd_snk_is_vbus_provided(port); - else - return !pd_snk_is_vbus_provided(port); -} - -int board_vbus_source_enabled(int port) -{ - if (IS_ENABLED(BOARD_C1_NO_PPC) && port) - return c1_ps8805_is_sourcing_vbus(port); - else - return ppc_is_sourcing_vbus(port); -} - -void pd_set_input_current_limit(int port, uint32_t max_ma, - uint32_t supply_voltage) -{ - -} - -int pd_check_data_swap(int port, - enum pd_data_role data_role) -{ - int swap = 0; - - if (port == 0) - swap = (data_role == PD_ROLE_DFP); - else if (port == 1) - swap = (data_role == PD_ROLE_UFP); - - return swap; -} - -int pd_check_power_swap(int port) -{ - - if (pd_get_power_role(port) == PD_ROLE_SINK) - return 1; - - return 0; -} - -#ifdef BOARD_C1_1A5_LIMIT -__override int typec_get_default_current_limit_rp(int port) -{ - int rp = TYPEC_RP_USB; - - if (port == USB_PD_PORT_HOST) - rp = TYPEC_RP_3A0; - else if (port == USB_PD_PORT_DP) - rp = TYPEC_RP_1A5; - - return rp; -} -#endif - -static void usb_tc_connect(void) -{ - int port = TASK_ID_TO_PD_PORT(task_get_current()); - - /* - * The EC needs to indicate to the USB hub when the host port is - * attached so that the USB-EP can be properly enumerated. GPIO_BPWR_DET - * is used for this purpose. - */ - if (port == USB_PD_PORT_HOST) { - gpio_set_level(GPIO_BPWR_DET, 1); -#ifdef GPIO_UFP_PLUG_DET - gpio_set_level(GPIO_UFP_PLUG_DET, 0); -#endif - } - - /* Clear data role swap attempt counter at each usbc attach */ - pd_dr_swap_attempt_count[port] = 0; -} -DECLARE_HOOK(HOOK_USB_PD_CONNECT, usb_tc_connect, HOOK_PRIO_DEFAULT); - -static void usb_tc_disconnect(void) -{ - int port = TASK_ID_TO_PD_PORT(task_get_current()); - - /* Only the host port disconnect is relevant */ - if (port == USB_PD_PORT_HOST) { - gpio_set_level(GPIO_BPWR_DET, 0); -#ifdef GPIO_UFP_PLUG_DET - gpio_set_level(GPIO_UFP_PLUG_DET, 1); -#endif - } -} -DECLARE_HOOK(HOOK_USB_PD_DISCONNECT, usb_tc_disconnect, HOOK_PRIO_DEFAULT); - -__override bool pd_can_charge_from_device(int port, const int pdo_cnt, - const uint32_t *pdos) -{ - /* - * This function is called to determine if this port can be charged by - * the port partner. We always want to be a power role source, so always - * return false. - */ - - return false; -} - -static int vdm_is_dp_enabled(int port) -{ - mux_state_t mux_state = usb_mux_get(port); - - return !!(mux_state & USB_PD_MUX_DP_ENABLED); -} - -/* ----------------- Vendor Defined Messages ------------------ */ - -const uint32_t vdo_idh = VDO_IDH(0, /* data caps as USB host */ - 1, /* data caps as USB device */ - IDH_PTYPE_HUB, /* UFP product type usbpd hub */ - 1, /* supports alt modes */ - USB_VID_GOOGLE); - -static const uint32_t vdo_idh_rev30 = VDO_IDH_REV30( - 0, /* Data caps as USB host */ - 1, /* Data caps as USB device */ - IDH_PTYPE_HUB, - 1, /* Supports alt modes */ - IDH_PTYPE_DFP_UNDEFINED, - USB_TYPEC_RECEPTACLE, - USB_VID_GOOGLE); - -const uint32_t vdo_product = VDO_PRODUCT(CONFIG_USB_PID, CONFIG_USB_BCD_DEV); - -static const uint32_t vdo_ufp1 = VDO_UFP1( - (VDO_UFP1_CAPABILITY_USB20 - | VDO_UFP1_CAPABILITY_USB32), - USB_TYPEC_RECEPTACLE, - VDO_UFP1_ALT_MODE_RECONFIGURE, - USB_R30_SS_U32_U40_GEN2); - -static int svdm_response_identity(int port, uint32_t *payload) -{ - int vdo_count; - - /* Verify that SVID is PD SID */ - if (PD_VDO_VID(payload[0]) != USB_SID_PD) { - return 0; - } - - /* Cstat and Product VDOs don't depend on spec revision */ - payload[VDO_INDEX_CSTAT] = VDO_CSTAT(0); - payload[VDO_INDEX_PRODUCT] = vdo_product; - - if (pd_get_rev(port, TCPCI_MSG_SOP) == PD_REV30) { - /* PD Revision 3.0 */ - payload[VDO_INDEX_IDH] = vdo_idh_rev30; - payload[VDO_INDEX_PTYPE_UFP1_VDO] = vdo_ufp1; - vdo_count = VDO_INDEX_PTYPE_UFP1_VDO; - } else { - payload[VDO_INDEX_IDH] = vdo_idh; - vdo_count = VDO_INDEX_PRODUCT; - } - - /* Adjust VDO count for VDM header */ - return vdo_count + 1; -} - -static int svdm_response_svids(int port, uint32_t *payload) -{ - /* Verify that SVID is PD SID */ - if (PD_VDO_VID(payload[0]) != USB_SID_PD) { - return 0; - } - - payload[1] = USB_SID_DISPLAYPORT << 16; - /* number of data objects VDO header + 1 SVID for DP */ - return 2; -} - -#define OPOS_DP 1 - -const uint32_t vdo_dp_modes[1] = { - VDO_MODE_DP(/* Must support C and E. D is required for 2 lanes */ - MODE_DP_PIN_C | MODE_DP_PIN_D | MODE_DP_PIN_E, - 0, /* DFP pin cfg supported */ - 0, /* usb2.0 signalling in AMode may be req */ - CABLE_RECEPTACLE, /* its a receptacle */ - MODE_DP_V13, /* DPv1.3 Support, no Gen2 */ - MODE_DP_SNK) /* Its a sink only */ -}; - -static int svdm_response_modes(int port, uint32_t *payload) -{ - if (PD_VDO_VID(payload[0]) == USB_SID_DISPLAYPORT) { - memcpy(payload + 1, vdo_dp_modes, sizeof(vdo_dp_modes)); - return ARRAY_SIZE(vdo_dp_modes) + 1; - } else { - return 0; /* nak */ - } -} - -static int amode_dp_status(int port, uint32_t *payload) -{ - int opos = PD_VDO_OPOS(payload[0]); - int hpd = gpio_get_level(GPIO_DP_HPD); - int mf = dock_get_mf_preference(); - - if (opos != OPOS_DP) - return 0; /* nak */ - - payload[1] = VDO_DP_STATUS(0, /* IRQ_HPD */ - (hpd == 1), /* HPD_HI|LOW */ - 0, /* request exit DP */ - 0, /* request exit USB */ - mf, /* MF pref */ - vdm_is_dp_enabled(port), - 0, /* power low */ - 0x2); - return 2; -} - -static void svdm_configure_demux(int port, int enable, int mf) -{ - mux_state_t demux = usb_mux_get(port); - - if (enable) { - demux |= USB_PD_MUX_DP_ENABLED; - /* 4 lane mode if MF is not preferred */ - if (!mf) - demux &= ~USB_PD_MUX_USB_ENABLED; - /* - * Make sure the MST_LANE_CONTROL gpio is set to match the DP - * pin configuration selected by the host. Note that the mf - * passed into this function reflects the pin configuration - * selected by the host and not the user mf preference which is - * stored in bit 0 of CBI fw_config. - */ - baseboard_set_mst_lane_control(mf); - CPRINTS("DP[%d]: DFP-D selected pin config %s", - port, mf ? "D" : "C"); - } else { - demux &= ~USB_PD_MUX_DP_ENABLED; - demux |= USB_PD_MUX_USB_ENABLED; - } - - /* Configure demux for 2/4 lane DP and USB3 configuration */ - usb_mux_set(port, demux, USB_SWITCH_CONNECT, pd_get_polarity(port)); -} - -static int amode_dp_config(int port, uint32_t *payload) -{ - uint32_t dp_config = payload[1]; - int mf; - - /* - * Check pin assignment selected by DFP_D to determine if 2 lane or 4 - * lane DP ALT-MODe is required. (note PIN_C is for 4 lane and PIN_D is - * for 2 lane mode). - */ - mf = ((dp_config >> 8) & 0xff) == MODE_DP_PIN_D ? 1 : 0; - /* Configure demux for DP mode */ - svdm_configure_demux(port, 1, mf); - /* Notify hpd->pd conv that a DP_CONFIG message has been received */ - pd_ufp_enable_hpd_send(port); - - return 1; -} - -static int svdm_enter_mode(int port, uint32_t *payload) -{ - int rv = 0; /* will generate a NAK */ - - /* SID & mode request is valid */ - if ((PD_VDO_VID(payload[0]) == USB_SID_DISPLAYPORT) && - (PD_VDO_OPOS(payload[0]) == OPOS_DP)) { - - /* Store valid object position to indicate mode is active */ - pd_ufp_set_dp_opos(port, OPOS_DP); - - /* Entering ALT-DP mode, enable DP connection in demux */ - usb_pd_hpd_converter_enable(1); - - /* ACK response has 1 VDO */ - rv = 1; - } - - CPRINTS("svdm_enter[%d]: svid = %x, ret = %d", port, - PD_VDO_VID(payload[0]), rv); - - return rv; -} - -static int svdm_exit_mode(int port, uint32_t *payload) -{ - int opos = pd_ufp_get_dp_opos(port); - - if ((PD_VDO_VID(payload[0]) == USB_SID_DISPLAYPORT) && - (opos == OPOS_DP)) { - /* Clear mode active object position */ - pd_ufp_set_dp_opos(port, 0); - /* Configure demux to disable DP mode */ - svdm_configure_demux(port, 0, 0); - usb_pd_hpd_converter_enable(0); - - return 1; - } else { - CPRINTF("Unknown exit mode req:0x%08x\n", payload[0]); - return 0; - } -} - -static struct amode_fx dp_fx = { - .status = &amode_dp_status, - .config = &amode_dp_config, -}; - -const struct svdm_response svdm_rsp = { - .identity = &svdm_response_identity, - .svids = &svdm_response_svids, - .modes = &svdm_response_modes, - .enter_mode = &svdm_enter_mode, - .amode = &dp_fx, - .exit_mode = &svdm_exit_mode, -}; - -int pd_custom_vdm(int port, int cnt, uint32_t *payload, - uint32_t **rpayload) -{ - /* We don't support, so ignore this message */ - return 0; -} diff --git a/baseboard/honeybuns/usbc_support.c b/baseboard/honeybuns/usbc_support.c deleted file mode 100644 index 4d7049ad37..0000000000 --- a/baseboard/honeybuns/usbc_support.c +++ /dev/null @@ -1,480 +0,0 @@ -/* Copyright 2021 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. - */ - -/* USBC functions for RO */ - -#include "common.h" -#include "console.h" -#include "driver/tcpm/tcpci.h" -#include "driver/tcpm/ps8xxx.h" -#include "sn5s330.h" -#include "hooks.h" -#include "i2c.h" -#include "system.h" -#include "timer.h" -#include "usb_charge.h" -#include "usb_pd_tcpm.h" -#include "usb_pd.h" -#include "usbc_ppc.h" -#include "util.h" -#include "registers.h" -#include "ucpd-stm32gx.h" - -#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ## args) - -enum usbc_states { - UNATTACHED_SNK, - ATTACH_WAIT_SNK, - ATTACHED_SNK, -}; - -/* Variables used to manage the simple usbc state machine */ -static int usbc_port; -static int usbc_state; -static int usbc_vbus; -static enum tcpc_cc_voltage_status cc1_v; -static enum tcpc_cc_voltage_status cc2_v; - -__maybe_unused static __const_data const char * const usbc_state_names[] = { - [UNATTACHED_SNK] = "Unattached.SNK", - [ATTACH_WAIT_SNK] = "AttachWait.SNK", - [ATTACHED_SNK] = "Attached.SNK", -}; - -static int read_reg(uint8_t port, int reg, int *regval) -{ - return i2c_read8(ppc_chips[port].i2c_port, - ppc_chips[port].i2c_addr_flags, - reg, - regval); -} - -static int write_reg(uint8_t port, int reg, int regval) -{ - return i2c_write8(ppc_chips[port].i2c_port, - ppc_chips[port].i2c_addr_flags, - reg, - regval); -} - -static int baseboard_ppc_enable_sink_path(int port) -{ - int regval; - int status; - int retries; - - /* - * It seems that sometimes setting the FUNC_SET1 register fails - * initially. Therefore, we'll retry a couple of times. - */ - retries = 0; - do { - status = write_reg(port, SN5S330_FUNC_SET1, SN5S330_ILIM_3_06); - if (status) { - retries++; - msleep(1); - } else { - break; - } - } while (retries < 10); - - /* Turn off dead battery resistors, turn on CC FETs */ - status = read_reg(port, SN5S330_FUNC_SET4, ®val); - if (!status) { - regval |= SN5S330_CC_EN; - status = write_reg(port, SN5S330_FUNC_SET4, regval); - } - if (status) { - return status; - } - - /* Enable sink path via PP2 */ - status = read_reg(port, SN5S330_FUNC_SET3, ®val); - if (!status) { - regval &= ~SN5S330_PP1_EN; - regval |= SN5S330_PP2_EN; - status = write_reg(port, SN5S330_FUNC_SET3, regval); - } - if (status) { - return status; - } - - return EC_SUCCESS; -} - -static void baseboard_ucpd_apply_rd(int port) -{ - uint32_t cfgr1_reg; - uint32_t moder_reg; - uint32_t cr; - - /* Ensure that clock to UCPD is enabled */ - STM32_RCC_APB1ENR2 |= STM32_RCC_APB1ENR2_UPCD1EN; - - /* Make sure CC1/CC2 pins PB4/PB6 are set for analog mode */ - moder_reg = STM32_GPIO_MODER(GPIO_B); - moder_reg |= 0x3300; - STM32_GPIO_MODER(GPIO_B) = moder_reg; - /* - * CFGR1 must be written when UCPD peripheral is disabled. Note that - * disabling ucpd causes the peripheral to quit any ongoing activity and - * sets all ucpd registers back their default values. - */ - - cfgr1_reg = STM32_UCPD_CFGR1_PSC_CLK_VAL(UCPD_PSC_DIV - 1) | - STM32_UCPD_CFGR1_TRANSWIN_VAL(UCPD_TRANSWIN_CNT - 1) | - STM32_UCPD_CFGR1_IFRGAP_VAL(UCPD_IFRGAP_CNT - 1) | - STM32_UCPD_CFGR1_HBITCLKD_VAL(UCPD_HBIT_DIV - 1); - STM32_UCPD_CFGR1(port) = cfgr1_reg; - - /* Enable ucpd */ - STM32_UCPD_CFGR1(port) |= STM32_UCPD_CFGR1_UCPDEN; - - /* Apply Rd to both CC lines */ - cr = STM32_UCPD_CR(port); - cr |= STM32_UCPD_CR_ANAMODE | STM32_UCPD_CR_CCENABLE_MASK; - STM32_UCPD_CR(port) = cr; - - /* - * After exiting reset, stm32gx will have dead battery mode enabled by - * default which connects Rd to CC1/CC2. This should be disabled when EC - * is powered up. - */ - STM32_PWR_CR3 |= STM32_PWR_CR3_UCPD1_DBDIS; -} - - -static void baseboard_ucpd_get_cc(int port, enum tcpc_cc_voltage_status *cc1, - enum tcpc_cc_voltage_status *cc2) -{ - int vstate_cc1; - int vstate_cc2; - int anamode; - uint32_t sr; - - /* - * cc_voltage_status is determined from vstate_cc bit field in the - * status register. The meaning of the value vstate_cc depends on - * current value of ANAMODE (src/snk). - * - * vstate_cc maps directly to cc_state from tcpci spec when ANAMODE = 1, - * but needs to be modified slightly for case ANAMODE = 0. - * - * If presenting Rp (source), then need to to a circular shift of - * vstate_ccx value: - * vstate_cc | cc_state - * ------------------ - * 0 -> 1 - * 1 -> 2 - * 2 -> 0 - */ - - /* Get vstate_ccx values and power role */ - sr = STM32_UCPD_SR(port); - /* Get Rp or Rd active */ - anamode = !!(STM32_UCPD_CR(port) & STM32_UCPD_CR_ANAMODE); - vstate_cc1 = (sr & STM32_UCPD_SR_VSTATE_CC1_MASK) >> - STM32_UCPD_SR_VSTATE_CC1_SHIFT; - vstate_cc2 = (sr & STM32_UCPD_SR_VSTATE_CC2_MASK) >> - STM32_UCPD_SR_VSTATE_CC2_SHIFT; - - /* Do circular shift if port == source */ - if (anamode) { - if (vstate_cc1 != STM32_UCPD_SR_VSTATE_RA) - vstate_cc1 += 4; - if (vstate_cc2 != STM32_UCPD_SR_VSTATE_RA) - vstate_cc2 += 4; - } else { - if (vstate_cc1 != STM32_UCPD_SR_VSTATE_OPEN) - vstate_cc1 = (vstate_cc1 + 1) % 3; - if (vstate_cc2 != STM32_UCPD_SR_VSTATE_OPEN) - vstate_cc2 = (vstate_cc2 + 1) % 3; - } - - *cc1 = vstate_cc1; - *cc2 = vstate_cc2; -} - -static int baseboard_rp_is_present(enum tcpc_cc_voltage_status cc1, - enum tcpc_cc_voltage_status cc2) -{ - return (cc1 >= TYPEC_CC_VOLT_RP_DEF || cc2 >= TYPEC_CC_VOLT_RP_DEF); -} - -static void baseboard_usbc_check_connect(void); -DECLARE_DEFERRED(baseboard_usbc_check_connect); - -static void baseboard_usbc_check_connect(void) -{ - enum tcpc_cc_voltage_status cc1; - enum tcpc_cc_voltage_status cc2; - int ppc_reg; - enum usbc_states enter_state = usbc_state; - - /* - * In RO, the only usbc related requirement is to enable the stm32g4 - * USB-EP to be enumerated by the host attached to C0. To prevent D+ - * being pulled high prior to VBUS presence, the EC uses GPIO_BPWR_DET - * to signal the USB hub that VBUS is present. Therefore, we need a - * simple usbc state machine to detect an attach (Rp and VBUS) event so - * this GPIO signal is properly controlled in RO. - * - * Note that RO only runs until the RWSIG timer expires and jumps to RW, - * and in RW, the full usb-pd stack is initialized and run. - */ - - /* Get current CC voltage levels */ - baseboard_ucpd_get_cc(usbc_port, &cc1, &cc2); - /* Update VBUS state */ - if (!read_reg(usbc_port, SN5S330_INT_STATUS_REG3, &ppc_reg)) - usbc_vbus = ppc_reg & SN5S330_VBUS_GOOD; - - switch (usbc_state) { - case UNATTACHED_SNK: - /* - * Require either CC1 or CC2 to have a valid Rp CC voltage level - * to advance to ATTACH_WAIT_SNK. - */ - if (baseboard_rp_is_present(cc1, cc2)) - usbc_state = ATTACH_WAIT_SNK; - break; - case ATTACH_WAIT_SNK: - /* - * This state handles debounce by ensuring the CC voltages are - * the same between two state machine iterations. If this - * condition is met, and VBUS is present, then advance to - * ATTACHED_SNK and set GPIO_BPWR_DET. - * - * If Rp voltage is no longer detected, then return to - * UNATTACHED_SNK. - */ - if (usbc_vbus && cc1 == cc1_v && cc2 == cc2_v) { - usbc_state = ATTACHED_SNK; - gpio_set_level(GPIO_BPWR_DET, 1); - } else if (!baseboard_rp_is_present(cc1, cc2)) { - usbc_state = UNATTACHED_SNK; - } - break; - case ATTACHED_SNK: - /* - * In this state, only checking for VBUS going away to indicate - * a detach event and inform the USB hub via GPIO_BPWR_DET. - */ - if (!usbc_vbus) { - usbc_state = UNATTACHED_SNK; - gpio_set_level(GPIO_BPWR_DET, 0); - } - break; - } - - /* Save CC voltage for debounce check */ - cc1_v = cc1; - cc2_v = cc2; - - if (enter_state != usbc_state) - CPRINTS("%s: cc1 = %d, cc2 = %d vbus = %d", - usbc_state_names[usbc_state], cc1, cc2, usbc_vbus); - - hook_call_deferred(&baseboard_usbc_check_connect_data, - PD_T_TRY_CC_DEBOUNCE); -} - -int baseboard_usbc_init(int port) -{ - int rv; - - /* Initialize ucpd and apply Rd to CC lines */ - baseboard_ucpd_apply_rd(port); - /* Initialize ppc to enable sink path */ - rv = baseboard_ppc_enable_sink_path(port); - if (rv) - CPRINTS("ppc init failed!"); - /* Save host port value */ - usbc_port = port; - /* Start RO usbc attach state machine */ - gpio_set_level(GPIO_BPWR_DET, 0); - /* Start simple usbc state machine */ - baseboard_usbc_check_connect(); - - return rv; -} - -#ifdef SECTION_IS_RW -int c1_ps8805_is_vbus_present(int port) -{ - int vbus; - - vbus = tcpm_check_vbus_level(port, VBUS_PRESENT); - - return vbus; -} - -int c1_ps8805_is_sourcing_vbus(int port) -{ - int rv; - int level; - - rv = ps8805_gpio_get_level(port, PS8805_GPIO_1, &level); - if (rv) - return 0; - - return level; -} - - -int c1_ps8805_vbus_source_enable(int port, int enable) -{ - - return ps8805_gpio_set_level(port, PS8805_GPIO_1, enable); -} - -__override bool usb_ufp_check_usb3_enable(int port) -{ - /* USB3.1 mux should be enabled based on UFP data role */ - return port == USB_PD_PORT_HOST; -} - -#ifdef GPIO_USBC_UF_ATTACHED_SRC -static int ppc_ocp_count; - -static void baseboard_usb3_manage_vbus(void) -{ - int level = gpio_get_level(GPIO_USBC_UF_ATTACHED_SRC); - - /* - * GPIO_USBC_UF_MUX_VBUS_EN is an output from the PS8803 which tracks if - * C2 is attached. When it's attached, this signal will be high. Use - * this level to control PPC VBUS on/off. - */ - ppc_vbus_source_enable(USB_PD_PORT_USB3, level); - CPRINTS("C2: State = %s", level ? "Attached.SRC " : "Unattached.SRC"); - - /* Reset OCP event counter for detach */ - if (!level) { - ppc_ocp_count = 0; - -#ifdef GPIO_USB_HUB_OCP_NOTIFY - /* - * In the case of an OCP event on this port, the usb hub should be - * notified via a GPIO signal. Following, an OCP, the attached.src state - * for the usb3 only port is checked again. If it's attached, then make - * sure the OCP notify signal is reset. - */ - gpio_set_level(GPIO_USB_HUB_OCP_NOTIFY, 1); -#endif - } -} -DECLARE_DEFERRED(baseboard_usb3_manage_vbus); - -void baseboard_usb3_check_state(void) -{ - hook_call_deferred(&baseboard_usb3_manage_vbus_data, 0); -} - -void baseboard_usbc_usb3_enable_interrupts(int enable) -{ - if (enable) { - /* Enable VBUS control interrupt for C2 */ - gpio_enable_interrupt(GPIO_USBC_UF_ATTACHED_SRC); - /* Enable PPC interrupt */ - gpio_enable_interrupt(GPIO_USBC_UF_PPC_INT_ODL); - } else { - /* Disable VBUS control interrupt for C2 */ - gpio_disable_interrupt(GPIO_USBC_UF_ATTACHED_SRC); - /* Disable PPC interrupt */ - gpio_disable_interrupt(GPIO_USBC_UF_PPC_INT_ODL); - } -} - -int baseboard_config_usbc_usb3_ppc(void) -{ - int rv; - - /* - * This port is not usb-pd capable, but there is a ppc which must be - * initialized, and keep the VBUS switch enabled. - */ - rv = ppc_init(USB_PD_PORT_USB3); - if (rv) - return rv; - - /* Need to set current limit to 3A to match advertised value */ - ppc_set_vbus_source_current_limit(USB_PD_PORT_USB3, TYPEC_RP_3A0); - /* Reset OCP event counter */ - ppc_ocp_count = 0; - - /* Check state at init time */ - baseboard_usb3_manage_vbus(); - - /* Enable attached.src and PPC interrupts */ - baseboard_usbc_usb3_enable_interrupts(1); - - return EC_SUCCESS; -} - -static void baseboard_usbc_usb3_handle_interrupt(void) -{ - int port = USB_PD_PORT_USB3; - - /* - * SN5S330's /INT pin is level, so process interrupts until it - * deasserts if the chip has a dedicated interrupt pin. - */ - while (gpio_get_level(GPIO_USBC_UF_PPC_INT_ODL) == 0) { - int rise = 0; - int fall = 0; - - read_reg(port, SN5S330_INT_TRIP_RISE_REG1, &rise); - read_reg(port, SN5S330_INT_TRIP_FALL_REG1, &fall); - - /* Notify the system about the overcurrent event. */ - if (rise & SN5S330_ILIM_PP1_MASK) { - CPRINTS("usb3_ppc: VBUS OC!"); - gpio_set_level(GPIO_USB_HUB_OCP_NOTIFY, 0); - if (++ppc_ocp_count < 5) - hook_call_deferred(&baseboard_usb3_manage_vbus_data, - USB_HUB_OCP_RESET_MSEC); - else - CPRINTS("usb3_ppc: VBUS OC limit reached!"); - } - - /* Clear the interrupt sources. */ - write_reg(port, SN5S330_INT_TRIP_RISE_REG1, rise); - write_reg(port, SN5S330_INT_TRIP_FALL_REG1, fall); - - read_reg(port, SN5S330_INT_TRIP_RISE_REG2, &rise); - read_reg(port, SN5S330_INT_TRIP_FALL_REG2, &fall); - - /* - * VCONN may be latched off due to an overcurrent. Indicate - * when the VCONN overcurrent happens. - */ - if (rise & SN5S330_VCONN_ILIM) - CPRINTS("usb3_ppc: VCONN OC!"); - - /* - * CC overvoltage event. There is not action to take here, but - * log the event. - */ - if (rise & SN5S330_CC1_CON || rise & SN5S330_CC2_CON) - CPRINTS("usb3_ppc: CC OV!"); - - /* Clear the interrupt sources. */ - write_reg(port, SN5S330_INT_TRIP_RISE_REG2, rise); - write_reg(port, SN5S330_INT_TRIP_FALL_REG2, fall); - - } -} -DECLARE_DEFERRED(baseboard_usbc_usb3_handle_interrupt); - -void baseboard_usbc_usb3_irq(void) -{ - hook_call_deferred(&baseboard_usbc_usb3_handle_interrupt_data, 0); -} - -#endif /* defined(GPIO_USBC_UF_ATTACHED_SRC) */ -#endif /* defined(SECTION_IS_RW) */ - |