summaryrefslogtreecommitdiff
path: root/driver/ppc
diff options
context:
space:
mode:
authorAseda Aboagye <aaboagye@google.com>2017-11-14 12:54:06 -0800
committerchrome-bot <chrome-bot@chromium.org>2017-12-05 18:00:35 -0800
commit864b0b661642836f26e3b7426f701283bc0a069d (patch)
treefeda6279842790f534148998058b6fe85a72f83c /driver/ppc
parent39efbc3ada5545f6784e7d09b7c358684cb124fa (diff)
downloadchrome-ec-864b0b661642836f26e3b7426f701283bc0a069d.tar.gz
sn5s330: Clear interrupts and setup masks at init.
When the SN5S330 is powered initially, there will be certain events set that will assert its interrupt line. As part of the initialization for this part, we should clear all the pending interrupts and setup the masks for the events that we care about. This commit clears all interrupts at init time and masks all interrupts except for overcurrent condition for PP1. BUG=b:69139844 BRANCH=None TEST=Flash zoombini; With nothing plugged in, verify that the interrupt line is deasserted at boot. TEST=Repeat the above test with a charger plugged in. Change-Id: I7acc030184b76d6c38a729cb64658f71e376c819 Signed-off-by: Aseda Aboagye <aaboagye@google.com> Reviewed-on: https://chromium-review.googlesource.com/783510 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.c92
-rw-r--r--driver/ppc/sn5s330.h16
2 files changed, 106 insertions, 2 deletions
diff --git a/driver/ppc/sn5s330.c b/driver/ppc/sn5s330.c
index 81efb290b8..ddd8299678 100644
--- a/driver/ppc/sn5s330.c
+++ b/driver/ppc/sn5s330.c
@@ -146,6 +146,7 @@ static int init_sn5s330(int idx)
int retries;
int i2c_port;
int i2c_addr;
+ int reg;
i2c_port = sn5s330_chips[idx].i2c_port;
i2c_addr = sn5s330_chips[idx].i2c_addr;
@@ -261,11 +262,98 @@ static int init_sn5s330(int idx)
CPRINTS("Failed to turn off PP1 FET!");
}
- /* Don't touch the PP2 FET yet if we're sysjumping. */
+ /*
+ * Don't proceed with the rest of initialization if we're sysjumping.
+ * We would have already done this before.
+ */
if (system_jumped_to_this_image())
return EC_SUCCESS;
- /* For PP2, check to see if we booted in dead battery mode. */
+ /* Clear the digital reset bit. */
+ status = i2c_read8(i2c_port, i2c_addr, SN5S330_INT_STATUS_REG4,
+ &regval);
+ if (status) {
+ CPRINTS("Failed to read INT_STATUS_REG4!");
+ return status;
+ }
+ regval |= SN5S330_DIG_RES;
+ status = i2c_write8(i2c_port, i2c_addr, SN5S330_INT_STATUS_REG4,
+ regval);
+ if (status) {
+ CPRINTS("Failed to write INT_STATUS_REG4!");
+ return status;
+ }
+
+ /*
+ * Before turning on the PP2 FET, let's mask off all interrupts except
+ * for the PP1 overcurrent condition and then clear all pending
+ * interrupts.
+ *
+ * TODO(aaboagye): Unmask fast-role swap events once fast-role swap is
+ * implemented in the PD stack.
+ */
+
+ regval = ~SN5S330_ILIM_PP1_RISE_MASK;
+ status = i2c_write8(i2c_port, i2c_addr, SN5S330_INT_MASK_RISE_REG1,
+ regval);
+ if (status) {
+ CPRINTS("Failed to write INT_MASK_RISE1!");
+ return status;
+ }
+
+ regval = ~SN5S330_ILIM_PP1_FALL_MASK;
+ status = i2c_write8(i2c_port, i2c_addr, SN5S330_INT_MASK_FALL_REG1,
+ regval);
+ if (status) {
+ CPRINTS("Failed to write INT_MASK_FALL1!");
+ return status;
+ }
+
+ /* Now mask all the other interrupts. */
+ status = i2c_write8(i2c_port, i2c_addr, SN5S330_INT_MASK_RISE_REG2,
+ 0xFF);
+ if (status) {
+ CPRINTS("Failed to write INT_MASK_RISE2!");
+ return status;
+ }
+
+ status = i2c_write8(i2c_port, i2c_addr, SN5S330_INT_MASK_FALL_REG2,
+ 0xFF);
+ if (status) {
+ CPRINTS("Failed to write INT_MASK_FALL2!");
+ return status;
+ }
+
+ status = i2c_write8(i2c_port, i2c_addr, SN5S330_INT_MASK_RISE_REG3,
+ 0xFF);
+ if (status) {
+ CPRINTS("Failed to write INT_MASK_RISE3!");
+ return status;
+ }
+
+ status = i2c_write8(i2c_port, i2c_addr, SN5S330_INT_MASK_FALL_REG3,
+ 0xFF);
+ if (status) {
+ CPRINTS("Failed to write INT_MASK_FALL3!");
+ return status;
+ }
+
+ /* Now clear any pending interrupts. */
+ for (reg = SN5S330_INT_TRIP_RISE_REG1;
+ reg <= SN5S330_INT_TRIP_FALL_REG3;
+ reg++) {
+ status = i2c_write8(i2c_port, i2c_addr, reg, 0xFF);
+ if (status) {
+ CPRINTS("Failed to write reg 0x%2x!");
+ return status;
+ }
+ }
+
+
+ /*
+ * For PP2, check to see if we booted in dead battery mode. If we
+ * booted in dead battery mode, the PP2 FET will already be enabled.
+ */
status = i2c_read8(i2c_port, i2c_addr, SN5S330_INT_STATUS_REG4,
&regval);
if (status) {
diff --git a/driver/ppc/sn5s330.h b/driver/ppc/sn5s330.h
index c4aa5fb81b..b3d6c45bee 100644
--- a/driver/ppc/sn5s330.h
+++ b/driver/ppc/sn5s330.h
@@ -101,7 +101,23 @@ enum sn5s330_pp_idx {
#define SN5S330_OVP_EN_CC (1 << 4)
/* INT_STATUS_REG4 */
+#define SN5S330_DIG_RES (1 << 0)
#define SN5S330_DB_BOOT (1 << 1)
+#define SN5S330_VSAFE0V_STAT (1 << 2)
+#define SN5S330_VSAFE0V_MASK (1 << 3)
+
+/*
+ * INT_MASK_RISE_EDGE_1
+ *
+ * The ILIM_PP1 bit indicates an overcurrent condition when sourcing on power
+ * path 1. For rising edge registers, this indicates an overcurrent has
+ * occured; similarly for falling edge, it means the overcurrent condition is no
+ * longer present.
+ */
+#define SN5S330_ILIM_PP1_RISE_MASK (1 << 4)
+
+/* INT_MASK_FALL_EDGE_1 */
+#define SN5S330_ILIM_PP1_FALL_MASK (1 << 4)
/**
* Turn on/off the PP1 or PP2 FET.