diff options
Diffstat (limited to 'driver')
-rw-r--r-- | driver/ppc/sn5s330.c | 40 | ||||
-rw-r--r-- | driver/ppc/sn5s330.h | 10 |
2 files changed, 50 insertions, 0 deletions
diff --git a/driver/ppc/sn5s330.c b/driver/ppc/sn5s330.c index f261f434ca..1a06c830db 100644 --- a/driver/ppc/sn5s330.c +++ b/driver/ppc/sn5s330.c @@ -24,6 +24,8 @@ #define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) #define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) +static uint32_t irq_pending; /* Bitmask of ports signaling an interrupt. */ + static int read_reg(uint8_t port, int reg, int *regval) { return i2c_read8(ppc_chips[port].i2c_port, @@ -452,6 +454,44 @@ static int sn5s330_vbus_source_enable(int port, int enable) return sn5s330_pp_fet_enable(port, SN5S330_PP1, !!enable); } +static void sn5s330_handle_interrupt(int port) +{ + int rise = 0; + int fall = 0; + + /* + * The only interrupts that should be enabled are the PP1 overcurrent + * condition. + */ + read_reg(port, SN5S330_INT_TRIP_RISE_REG1, &rise); + read_reg(port, SN5S330_INT_TRIP_FALL_REG1, &fall); + + /* Let the board know about the overcurrent event. */ + if (rise & SN5S330_ILIM_PP1_MASK) + board_overcurrent_event(port); + + /* Clear the interrupt sources. */ + write_reg(port, SN5S330_INT_TRIP_RISE_REG1, rise); + write_reg(port, SN5S330_INT_TRIP_FALL_REG1, fall); +} + +static void sn5s330_irq_deferred(void) +{ + int i; + uint32_t pending = atomic_read_clear(&irq_pending); + + for (i = 0; i < CONFIG_USB_PD_PORT_COUNT; i++) + if ((1 << i) & pending) + sn5s330_handle_interrupt(i); +} +DECLARE_DEFERRED(sn5s330_irq_deferred); + +void sn5s330_interrupt(int port) +{ + atomic_or(&irq_pending, (1 << port)); + hook_call_deferred(&sn5s330_irq_deferred_data, 0); +} + const struct ppc_drv sn5s330_drv = { .init = &sn5s330_init, .is_sourcing_vbus = &sn5s330_is_sourcing_vbus, diff --git a/driver/ppc/sn5s330.h b/driver/ppc/sn5s330.h index 683c3f6807..d3d3248a80 100644 --- a/driver/ppc/sn5s330.h +++ b/driver/ppc/sn5s330.h @@ -121,4 +121,14 @@ enum sn5s330_pp_idx { 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. + * + * @param port: The Type-C port which triggered the interrupt. + */ +void sn5s330_interrupt(int port); + #endif /* defined(__CROS_EC_SN5S330_H) */ |