diff --git a/board/grunt/usb_pd_policy.c b/board/grunt/usb_pd_policy.c index ca2545c436..3f873beee4 100644 --- a/board/grunt/usb_pd_policy.c +++ b/board/grunt/usb_pd_policy.c @@ -173,16 +173,7 @@ void typec_set_source_current_limit(int port, int rp) int pd_snk_is_vbus_provided(int port) { - int vbus_present = 0; - int rv; - - rv = ppc_is_vbus_present(port, &vbus_present); - if (rv) { - CPRINTS("p%d: VBUS present error (%d)", port, rv); - return 0; - } - - return vbus_present; + return ppc_is_vbus_present(port); } int board_vbus_source_enabled(int port) diff --git a/common/usb_charger.c b/common/usb_charger.c index 1c01695d0e..3e7d52f646 100644 --- a/common/usb_charger.c +++ b/common/usb_charger.c @@ -75,7 +75,8 @@ void usb_charger_vbus_change(int port, int vbus_level) task_set_event(USB_CHG_PORT_TO_TASK_ID(port), USB_CHG_EVENT_VBUS, 0); #endif -#ifdef CONFIG_USB_PD_VBUS_DETECT_CHARGER +#if (defined(CONFIG_USB_PD_VBUS_DETECT_CHARGER) \ + || defined(CONFIG_USB_PD_VBUS_DETECT_PPC)) /* USB PD task */ task_wake(PD_PORT_TO_TASK_ID(port)); #endif diff --git a/common/usbc_ppc.c b/common/usbc_ppc.c index 34cfbabf50..4cea6813bc 100644 --- a/common/usbc_ppc.c +++ b/common/usbc_ppc.c @@ -75,12 +75,14 @@ int ppc_vbus_source_enable(int port, int enable) } #ifdef CONFIG_USB_PD_VBUS_DETECT_PPC -int ppc_is_vbus_present(int port, int *vbus_present) +int ppc_is_vbus_present(int port) { - if (port >= ppc_cnt) - return EC_ERROR_INVAL; + if ((port < 0) || (port >= ppc_cnt)) { + CPRINTS("%s(%d) Invalid port!", __func__, port); + return 0; + } - return ppc_chips[port].drv->is_vbus_present(port, vbus_present); + return ppc_chips[port].drv->is_vbus_present(port); } #endif /* defined(CONFIG_USB_PD_VBUS_DETECT_PPC) */ diff --git a/driver/ppc/sn5s330.c b/driver/ppc/sn5s330.c index d21dba0f66..2d5d457abf 100644 --- a/driver/ppc/sn5s330.c +++ b/driver/ppc/sn5s330.c @@ -17,6 +17,7 @@ #include "i2c.h" #include "system.h" #include "timer.h" +#include "usb_charge.h" #include "usb_pd_tcpm.h" #include "usbc_ppc.h" #include "util.h" @@ -326,7 +327,8 @@ static int sn5s330_init(int port) /* * Before turning on the PP2 FET, let's mask off all interrupts except * for the PP1 overcurrent condition and then clear all pending - * interrupts. + * interrupts. If PPC is being used to detect VBUS, then also enable + * interrupts for VBUS presence. * * TODO(aaboagye): Unmask fast-role swap events once fast-role swap is * implemented in the PD stack. @@ -362,15 +364,22 @@ static int sn5s330_init(int port) return status; } +#if defined(CONFIG_USB_PD_VBUS_DETECT_PPC) && defined(CONFIG_USB_CHARGER) + /* If PPC is being used to detect VBUS, enable VBUS interrupts. */ + regval = ~SN5S330_VBUS_GOOD_MASK; +#else + regval = 0xFF; +#endif /* CONFIG_USB_PD_VBUS_DETECT_PPC && CONFIG_USB_CHARGER */ + status = i2c_write8(i2c_port, i2c_addr, SN5S330_INT_MASK_RISE_REG3, - 0xFF); + regval); if (status) { CPRINTS("Failed to write INT_MASK_RISE3!"); return status; } status = i2c_write8(i2c_port, i2c_addr, SN5S330_INT_MASK_FALL_REG3, - 0xFF); + regval); if (status) { CPRINTS("Failed to write INT_MASK_FALL3!"); return status; @@ -416,16 +425,18 @@ static int sn5s330_init(int port) } #ifdef CONFIG_USB_PD_VBUS_DETECT_PPC -static int sn5s330_is_vbus_present(int port, int *vbus_present) +static int sn5s330_is_vbus_present(int port) { int regval; int rv; rv = read_reg(port, SN5S330_INT_STATUS_REG3, ®val); - if (!rv) - *vbus_present = !!(regval & SN5S330_VBUS_GOOD); + if (rv) { + CPRINTS("p%d: VBUS present error (%d)", port, rv); + return 0; + } - return rv; + return !!(regval & SN5S330_VBUS_GOOD); } #endif /* defined(CONFIG_USB_PD_VBUS_DETECT_PPC) */ @@ -436,7 +447,7 @@ static int sn5s330_is_sourcing_vbus(int port) rv = sn5s330_is_pp_fet_enabled(port, SN5S330_PP1, &is_sourcing_vbus); if (rv) { - CPRINTS("C%d: Failed to determine source FET status! (%d)", + CPRINTS("p%d: Failed to determine source FET status! (%d)", port, rv); return 0; } @@ -520,7 +531,7 @@ static void sn5s330_handle_interrupt(int port) /* * The only interrupts that should be enabled are the PP1 overcurrent - * condition. + * condition, and for VBUS_GOOD if PPC is being used to detect VBUS. */ read_reg(port, SN5S330_INT_TRIP_RISE_REG1, &rise); read_reg(port, SN5S330_INT_TRIP_FALL_REG1, &fall); @@ -532,6 +543,20 @@ static void sn5s330_handle_interrupt(int port) /* Clear the interrupt sources. */ write_reg(port, SN5S330_INT_TRIP_RISE_REG1, rise); write_reg(port, SN5S330_INT_TRIP_FALL_REG1, fall); + +#if defined(CONFIG_USB_PD_VBUS_DETECT_PPC) && defined(CONFIG_USB_CHARGER) + read_reg(port, SN5S330_INT_TRIP_RISE_REG3, &rise); + read_reg(port, SN5S330_INT_TRIP_FALL_REG3, &fall); + + /* Inform other modules about VBUS level */ + if (rise & SN5S330_VBUS_GOOD_MASK + || fall & SN5S330_VBUS_GOOD_MASK) + usb_charger_vbus_change(port, sn5s330_is_vbus_present(port)); + + /* Clear the interrupt sources. */ + write_reg(port, SN5S330_INT_TRIP_RISE_REG3, rise); + write_reg(port, SN5S330_INT_TRIP_FALL_REG3, fall); +#endif /* CONFIG_USB_PD_VBUS_DETECT_PPC && CONFIG_USB_CHARGER */ } static void sn5s330_irq_deferred(void) diff --git a/driver/ppc/sn5s330.h b/driver/ppc/sn5s330.h index 18f1929c0f..e8850faf57 100644 --- a/driver/ppc/sn5s330.h +++ b/driver/ppc/sn5s330.h @@ -120,13 +120,23 @@ enum sn5s330_pp_idx { */ #define SN5S330_ILIM_PP1_MASK (1 << 4) +/* + * INT_MASK_RISE/FALL_EDGE_3 + * + * The VBUS_GOOD bit indicates VBUS has increased beyond a 4.0V threshold. + * For rising edge registers, this indicates VBUS has risen above 4.0V. + * For falling edge registers, this indicates VBUS has fallen below 4.0V. + */ +#define SN5S330_VBUS_GOOD_MASK (1 << 0) + extern const struct ppc_drv sn5s330_drv; /** * Interrupt Handler for the SN5S330. * * By default, the only interrupt sources that are unmasked are overcurrent - * conditions for PP1. + * conditions for PP1, and VBUS_GOOD if PPC is being used to detect VBUS + * (CONFIG_USB_PD_VBUS_DETECT_PPC). * * @param port: The Type-C port which triggered the interrupt. */ diff --git a/include/usbc_ppc.h b/include/usbc_ppc.h index 4fbb913a11..eec8362959 100644 --- a/include/usbc_ppc.h +++ b/include/usbc_ppc.h @@ -77,21 +77,13 @@ struct ppc_drv { #endif /* defined(CONFIG_CMD_PPC_DUMP) */ #ifdef CONFIG_USB_PD_VBUS_DETECT_PPC - /* - * TODO(aaboagye): In order for VBUS detection to work properly for our - * system, we need to enable VBUS interrupts and send the appropriate - * notifications. - */ - /** * Determine if VBUS is present or not. * * @param port: The Type-C port number. - * @param vbus_present: 1: VBUS is present. 0: VBUS is not present. - * @return EC_SUCCESS if able to determine VBUS status, otherwise an - * error. + * @return 1 if VBUS is present, 0 if not. */ - int (*is_vbus_present)(int port, int *vbus_present); + int (*is_vbus_present)(int port); #endif /* defined(CONFIG_USB_PD_VBUS_DETECT_PPC) */ }; @@ -116,11 +108,9 @@ int ppc_init(int port); * Determine if VBUS is present or not. * * @param port: The Type-C port number. - * @param vbus_present: 1: VBUS is present. 0: VBUS is not present. - * @return EC_SUCCESS if able to determine VBUS status, otherwise an - * error. + * @return 1 if VBUS is present, 0 if not. */ -int ppc_is_vbus_present(int port, int *vbus_present); +int ppc_is_vbus_present(int port); /** * Is the port sourcing Vbus?