From 7e70fc5301b425ce8e0265b6e7ebb3cf9e7109bb Mon Sep 17 00:00:00 2001 From: Eric Yilun Lin Date: Tue, 12 May 2020 11:46:37 +0800 Subject: asurada: enable PPC syv682x on C0/C1 Enable PPC on C0 and C1, where C1 port is optional and dependent to the daughter board connected. BUG=b:152562604 TEST=ensure C0/C1 can sink and source power. BRANCH=master Signed-off-by: Ting Shen Signed-off-by: Eric Yilun Lin Change-Id: I2fabe59562ffbe63e91b60f36b726d63fefdc83b Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2195721 Reviewed-by: Ting Shen Commit-Queue: Ting Shen --- board/asurada/board.c | 124 +++++++++++++++++++++++++++++++++++++++--- board/asurada/board.h | 19 +++++-- board/asurada/gpio.inc | 2 +- board/asurada/usb_pd_policy.c | 57 ++++++++++++++++++- 4 files changed, 188 insertions(+), 14 deletions(-) diff --git a/board/asurada/board.c b/board/asurada/board.c index b6f5b63f8b..2c27fa3079 100644 --- a/board/asurada/board.c +++ b/board/asurada/board.c @@ -7,11 +7,13 @@ #include "adc.h" #include "adc_chip.h" #include "button.h" +#include "charge_manager.h" #include "charger.h" #include "chipset.h" #include "common.h" #include "console.h" #include "driver/charger/isl923x.h" +#include "driver/ppc/syv682x.h" #include "driver/tcpm/it83xx_pd.h" #include "extpower.h" #include "gpio.h" @@ -29,13 +31,12 @@ #include "uart.h" #include "usb_mux.h" #include "usb_pd_tcpm.h" +#include "usbc_ppc.h" #define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args) #define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ## args) -#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ## args) - +static void ppc_interrupt(enum gpio_signal signal); static void x_ec_interrupt(enum gpio_signal signal); #include "gpio_list.h" @@ -86,6 +87,15 @@ static void board_init(void) } DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); +static void board_tcpc_init(void) +{ + gpio_enable_interrupt(GPIO_USB_C0_PPC_INT_ODL); + if (board_get_sub_board() == SUB_BOARD_TYPEC) + gpio_enable_interrupt(GPIO_USB_C1_PPC_INT_ODL); +} +/* Must be done after I2C and subboard */ +DECLARE_HOOK(HOOK_INIT, board_tcpc_init, HOOK_PRIO_INIT_I2C + 1); + /* ADC channels. Must be in the exactly same order as in enum adc_channel. */ const struct adc_t adc_channels[] = { /* Convert to mV (3000mV/1024). */ @@ -139,9 +149,60 @@ const struct i2c_port_t i2c_ports[] = { }; const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); +/* PPC */ +struct ppc_config_t ppc_chips[CONFIG_USB_PD_PORT_MAX_COUNT] = { + { + .i2c_port = I2C_PORT_PPC0, + .i2c_addr_flags = SYV682X_ADDR0_FLAGS, + .drv = &syv682x_drv + }, + { + .i2c_port = I2C_PORT_PPC1, + .i2c_addr_flags = SYV682X_ADDR0_FLAGS, + .drv = &syv682x_drv + }, +}; +unsigned int ppc_cnt = ARRAY_SIZE(ppc_chips); + +static void ppc_interrupt(enum gpio_signal signal) +{ + if (signal == GPIO_USB_C0_PPC_INT_ODL) + /* C0: PPC interrupt */ + syv682x_interrupt(0); +} + +static void hdmi_hpd_interrupt(enum gpio_signal signal) +{ + /* TODO: implement HDMI HPD */ +} + +/* HDMI/TYPE-C function shared subboard interrupt */ static void x_ec_interrupt(enum gpio_signal signal) { - /* TODO: implement this */ + int sub = board_get_sub_board(); + + if (sub == SUB_BOARD_TYPEC) + /* C1: PPC interrupt */ + syv682x_interrupt(1); + else if (sub == SUB_BOARD_HDMI) + hdmi_hpd_interrupt(signal); + else + CPRINTS("Undetected subboard interrupt."); +} + +int ppc_get_alert_status(int port) +{ + if (port == 0) + return gpio_get_level(GPIO_USB_C0_PPC_INT_ODL) == 0; + if (port == 1 && board_get_sub_board() == SUB_BOARD_TYPEC) + return gpio_get_level(GPIO_USB_C1_PPC_INT_ODL) == 0; + + return 0; +} + +void board_overcurrent_event(int port, int is_overcurrented) +{ + /* TODO: check correct operation for Asurada */ } /* TCPC */ @@ -188,11 +249,58 @@ int board_get_version(void) return 0; } -int board_set_active_charge_port(int charge_port) +int board_set_active_charge_port(int port) { - CPRINTS("New chg p%d", charge_port); + int i; + int is_valid_port = port == 0 || (port == 1 && board_get_sub_board() == + SUB_BOARD_TYPEC); + + if (!is_valid_port && port != CHARGE_PORT_NONE) + return EC_ERROR_INVAL; + + if (port == CHARGE_PORT_NONE) { + CPRINTS("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)) + CPRINTS("Disabling C%d as sink failed.", i); + } + + return EC_SUCCESS; + } - return 0; + /* Check if the port is sourcing VBUS. */ + if (ppc_is_sourcing_vbus(port)) { + CPRINTF("Skip enable C%d", port); + return EC_ERROR_INVAL; + } + + CPRINTS("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)) + CPRINTS("C%d: sink path disable failed.", i); + } + + /* Enable requested charge port. */ + if (ppc_vbus_sink_enable(port, 1)) { + CPRINTS("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, @@ -216,6 +324,8 @@ static enum board_sub_board board_get_sub_board(void) /* HDMI board has external pull high. */ if (gpio_get_level(GPIO_EC_X_GPIO3)) { sub = SUB_BOARD_HDMI; + /* Only has 1 PPC with HDMI subboard */ + ppc_cnt = 1; } else { sub = SUB_BOARD_TYPEC; /* EC_X_GPIO1 */ diff --git a/board/asurada/board.h b/board/asurada/board.h index f97bbb2083..41433179e0 100644 --- a/board/asurada/board.h +++ b/board/asurada/board.h @@ -54,8 +54,16 @@ #define CONFIG_I2C_MASTER #define I2C_PORT_CHARGER IT83XX_I2C_CH_A #define I2C_PORT_BATTERY IT83XX_I2C_CH_A - -/* PD / USB-C */ +#define I2C_PORT_PPC0 IT83XX_I2C_CH_C +#define I2C_PORT_PPC1 IT83XX_I2C_CH_E + +/* PD / USB-C / PPC */ +#define CONFIG_CMD_PPC_DUMP +#define CONFIG_USBC_PPC +#define CONFIG_USBC_PPC_DEDICATED_INT +#define CONFIG_USBC_PPC_POLARITY +#define CONFIG_USBC_PPC_SYV682X +#define CONFIG_USBC_PPC_VCONN #define CONFIG_USBC_SS_MUX #define CONFIG_USBC_VCONN #define CONFIG_USBC_VCONN_SWAP @@ -63,15 +71,18 @@ #define CONFIG_USB_PD_ALT_MODE_DFP #define CONFIG_USB_PD_DEBUG_LEVEL 3 #define CONFIG_USB_PD_DECODE_SOP +#define CONFIG_USB_PD_DISCHARGE +#define CONFIG_USB_PD_DISCHARGE_PPC #define CONFIG_USB_PD_DUAL_ROLE #define CONFIG_USB_PD_ITE_ACTIVE_PORT_COUNT 2 -#define CONFIG_USB_PD_LOGGING +#define CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT TYPEC_RP_3A0 #define CONFIG_USB_PD_PORT_MAX_COUNT 2 #define CONFIG_USB_PD_TCPMV1 #define CONFIG_USB_PD_TCPM_ITE_ON_CHIP #define CONFIG_USB_PD_TCPM_TCPCI #define CONFIG_USB_PD_TRY_SRC -#define CONFIG_USB_PD_VBUS_MEASURE_NOT_PRESENT /* TODO: */ +#define CONFIG_USB_PD_VBUS_DETECT_PPC +#define CONFIG_USB_PD_VBUS_MEASURE_CHARGER #define CONFIG_USB_PID 0x5566 /* TODO: update PID */ #define CONFIG_USB_POWER_DELIVERY diff --git a/board/asurada/gpio.inc b/board/asurada/gpio.inc index 1c3ea714f5..1c92ae8daa 100644 --- a/board/asurada/gpio.inc +++ b/board/asurada/gpio.inc @@ -31,6 +31,7 @@ GPIO_INT(PMIC_EC_PWRGD, PIN(F, 3), /* Sensor Interrupts */ /* USB-C interrupts */ +GPIO_INT(USB_C0_PPC_INT_ODL, PIN(D, 1), GPIO_INT_BOTH, ppc_interrupt) /* Volume button interrupts */ @@ -121,7 +122,6 @@ UNIMPLEMENTED_GPIO(AP_SPI_EC_MISO_R, PIN(M, 1)) UNIMPLEMENTED_GPIO(AP_SPI_EC_MOSI, PIN(M, 0)) UNIMPLEMENTED_GPIO(AP_SPI_EC_CLK, PIN(M, 4)) UNIMPLEMENTED_GPIO(SET_VMC_VOLT_AT_1V8, PIN(D, 4)) -UNIMPLEMENTED_GPIO(USB_C0_PPC_INT_ODL, PIN(D, 1)) UNIMPLEMENTED_GPIO(EN_PP3000_VMC_PMU, PIN(D, 2)) UNIMPLEMENTED_GPIO(PWR_LED_ODL, PIN(A, 0)) UNIMPLEMENTED_GPIO(EC_LED_PWM1, PIN(A, 1)) diff --git a/board/asurada/usb_pd_policy.c b/board/asurada/usb_pd_policy.c index 33c659708f..ed10dd11db 100644 --- a/board/asurada/usb_pd_policy.c +++ b/board/asurada/usb_pd_policy.c @@ -2,23 +2,76 @@ * 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 "usb_pd.h" +#include "usbc_ppc.h" + +#ifndef CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT +#error Asurada reference must define CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT +#endif int pd_snk_is_vbus_provided(int port) { - return 0; + return ppc_is_vbus_present(port); } void pd_power_supply_reset(int port) { + int prev_en; + + prev_en = ppc_is_sourcing_vbus(port); + + /* Disable VBUS. */ + ppc_vbus_source_enable(port, 0); + + /* Enable discharge if we were previously sourcing 5V */ + if (prev_en) + pd_set_vbus_discharge(port, 1); + +#ifdef CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT + /* Give back the current quota we are no longer using */ + charge_manager_source_port(port, 0); +#endif /* defined(CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT) */ + + /* Notify host of power info change. */ + pd_send_host_event(PD_EVENT_POWER_CHANGE); } int pd_check_vconn_swap(int port) { + /* TODO: Only allow vconn swap if PP4200_G rail is enabled , s3/s0 on */ return 0; } int pd_set_power_supply_ready(int port) { - return 0; + 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; } + +int board_vbus_source_enabled(int port) +{ + return ppc_is_sourcing_vbus(port); +} + -- cgit v1.2.1