diff options
author | Aseda Aboagye <aaboagye@google.com> | 2017-11-28 11:02:22 -0800 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2017-12-12 01:05:25 -0800 |
commit | 02e4c2ea9a087a22e49287fbfd71714eab21c7f4 (patch) | |
tree | 824180c02d7c1cd20d81bfcbf135ee8830cd2e6f /driver | |
parent | 716fcb123d36a46d8432c1e45d49f6828bba93ff (diff) | |
download | chrome-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')
-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) */ |