summaryrefslogtreecommitdiff
path: root/driver
diff options
context:
space:
mode:
Diffstat (limited to 'driver')
-rw-r--r--driver/ppc/sn5s330.c40
-rw-r--r--driver/ppc/sn5s330.h10
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) */