summaryrefslogtreecommitdiff
path: root/driver/ppc
diff options
context:
space:
mode:
authorAseda Aboagye <aaboagye@google.com>2017-11-28 11:02:22 -0800
committerchrome-bot <chrome-bot@chromium.org>2017-12-12 01:05:25 -0800
commit02e4c2ea9a087a22e49287fbfd71714eab21c7f4 (patch)
tree824180c02d7c1cd20d81bfcbf135ee8830cd2e6f /driver/ppc
parent716fcb123d36a46d8432c1e45d49f6828bba93ff (diff)
downloadchrome-ec-02e4c2ea9a087a22e49287fbfd71714eab21c7f4.tar.gz
ppc: sn5s330: Add interrupt handler.
Right now, the only events that are unmasked by default are overcurrent conditions on PP1. This commit adds a simple interrupt handler and introduces a board specific callback when the overcurrent status changes on a port. This way, a board can take whatever action it desires with the notification. BUG=b:69139844 BRANCH=None TEST=Flash zoombini with SN5S330 stuffed. Verify that board boots okay. TEST=With some extra code to setup the interrupt handler, attempt to exceed the current limit set, verify that interrupt handler is called. Reduce the current pulled to under the current limit, verify that the condition is no longer present. CQ-DEPEND=CL:797937 Change-Id: Id3321c5703f9608da895be0ed5841f2fb76e734e Signed-off-by: Aseda Aboagye <aaboagye@google.com> Reviewed-on: https://chromium-review.googlesource.com/797936 Commit-Ready: Aseda Aboagye <aaboagye@chromium.org> Tested-by: Aseda Aboagye <aaboagye@chromium.org> Reviewed-by: Shawn N <shawnn@chromium.org>
Diffstat (limited to 'driver/ppc')
-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) */