summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorScott Collyer <scollyer@google.com>2018-04-09 19:33:25 -0700
committerchrome-bot <chrome-bot@chromium.org>2018-04-10 19:12:55 -0700
commit9466bef89bc45b30e12e74438469e630fe2c6091 (patch)
treea935e2775d128a69b15eada469fd1cb7d605833b
parentbe6a26363871acb3529a30cdcb4189135a372bd7 (diff)
downloadchrome-ec-9466bef89bc45b30e12e74438469e630fe2c6091.tar.gz
nx20p3483: Fix VBUS OVLO threshold and dead battery mode check
If the board is not powered until VBUS is connected, then that port will trigger dead battery mode in the PPC. This mode must be exited by the host (EC) writing to the control register. Until dead battery mode is exited, VBUS OVLO is fixed at 6.8V. Therefore the regular setting of this value must be done after exiting dead battery mode. This CL also changes the check for dead battery mode to use the mode value in the device status register. The bit in the control register does not reflect the status, but rather, if dead battery mode exit has been written by the host. The current check will result in the dead battery mode section being executed for both ports after every power up. However, only the port that has VBUS active would succeed because the HV_SNK mode can't be enabled unless VBUS is present. Lastly, this CL changes the verification check for the sink/source_enable functions to rely on the mode in the device status register instead of the switch state. The reason for this is that the switch state requires ~15 msec delay before it gets updated following SNK_EN to the nx20p3484 being set high. However, the mode reports the correct state without reqiuring a msleep. BUG=b:77561535 BRANCH=NONE TEST=Tested both port 0 and 1 and verified that Yorp can power up without a battery. In addition verified that nx20p3483_vbus_sink_enable returns EC_SUCCESS for both enable/disable cases. Change-Id: I2c993b592cd30e34a39d1c1b7e3c54be9f505844 Signed-off-by: Scott Collyer <scollyer@google.com> Reviewed-on: https://chromium-review.googlesource.com/1005621 Commit-Ready: Scott Collyer <scollyer@chromium.org> Tested-by: Scott Collyer <scollyer@chromium.org> Reviewed-by: Jett Rink <jettrink@chromium.org>
-rw-r--r--driver/ppc/nx20p3483.c91
1 files changed, 64 insertions, 27 deletions
diff --git a/driver/ppc/nx20p3483.c b/driver/ppc/nx20p3483.c
index 6c89fa76d5..d9f760165a 100644
--- a/driver/ppc/nx20p3483.c
+++ b/driver/ppc/nx20p3483.c
@@ -42,6 +42,26 @@ static int write_reg(uint8_t port, int reg, int regval)
regval);
}
+static int nx20p3483_set_ovp_limit(int port)
+{
+ int rv;
+ int reg;
+
+ /* Set VBUS over voltage threshold (OVLO) */
+ rv = read_reg(port, NX20P3483_OVLO_THRESHOLD_REG, &reg);
+ if (rv)
+ return rv;
+ /* OVLO threshold is 3 bit field */
+ reg &= ~NX20P3483_OVLO_THRESHOLD_MASK;
+ /* Set SNK OVP to 23.0 V */
+ reg |= NX20P3483_OVLO_23_0;
+ rv = write_reg(port, NX20P3483_OVLO_THRESHOLD_REG, reg);
+ if (rv)
+ return rv;
+
+ return EC_SUCCESS;
+}
+
static int nx20p3483_is_sourcing_vbus(int port)
{
int mode;
@@ -115,6 +135,8 @@ static int nx20p3483_vbus_sink_enable(int port, int enable)
{
int status;
int rv;
+ int desired_mode = enable ? NX20P3483_MODE_HV_SNK :
+ NX20P3483_MODE_STANDBY;
enable = !!enable;
/*
@@ -136,18 +158,21 @@ static int nx20p3483_vbus_sink_enable(int port, int enable)
return rv;
}
- /* Verify switch status register */
- rv = read_reg(port, NX20P3483_SWITCH_STATUS_REG, &status);
+ /* Read device status register to get mode */
+ rv = read_reg(port, NX20P3483_DEVICE_STATUS_REG, &status);
if (rv)
return rv;
- status = !!(status & NX20P3483_HVSNK_STS);
- return (status == enable) ? EC_SUCCESS : EC_ERROR_UNKNOWN;
+
+ return ((status & NX20P3483_DEVICE_MODE_MASK) == desired_mode) ?
+ EC_SUCCESS : EC_ERROR_UNKNOWN;
}
static int nx20p3483_vbus_source_enable(int port, int enable)
{
int status;
int rv;
+ int desired_mode = enable ? NX20P3483_MODE_5V_SRC :
+ NX20P3483_MODE_STANDBY;
enable = !!enable;
/*
@@ -169,32 +194,22 @@ static int nx20p3483_vbus_source_enable(int port, int enable)
return rv;
}
- /* Verify switch status register */
- rv = read_reg(port, NX20P3483_SWITCH_STATUS_REG, &status);
+ /* Read device status register to get mode */
+ rv = read_reg(port, NX20P3483_DEVICE_STATUS_REG, &status);
if (rv)
return rv;
- status = !!(status & NX20P3483_5VSRC_STS);
- return (status == enable) ? EC_SUCCESS : EC_ERROR_UNKNOWN;
+
+ return ((status & NX20P3483_DEVICE_MODE_MASK) == desired_mode) ?
+ EC_SUCCESS : EC_ERROR_UNKNOWN;
}
static int nx20p3483_init(int port)
{
int reg;
int mask;
+ int mode;
int rv;
- /* Set VBUS over voltage threshold (OVLO) */
- rv = read_reg(port, NX20P3483_OVLO_THRESHOLD_REG, &reg);
- if (rv)
- return rv;
- /* OVLO threshold is 3 bit field */
- reg &= ~NX20P3483_OVLO_THRESHOLD_MASK;
- /* Set SNK OVP to 23.0 V */
- reg |= NX20P3483_OVLO_23_0;
- rv = write_reg(port, NX20P3483_OVLO_THRESHOLD_REG, reg);
- if (rv)
- return rv;
-
/* Mask interrupts for interrupt 2 register */
mask = ~NX20P3483_INT2_EN_ERR;
rv = write_reg(port, NX20P3483_INTERRUPT2_MASK_REG, mask);
@@ -211,24 +226,40 @@ static int nx20p3483_init(int port)
read_reg(port, NX20P3483_INTERRUPT1_REG, &reg);
read_reg(port, NX20P3483_INTERRUPT2_REG, &reg);
- /* Check for dead battery mode */
- rv = read_reg(port, NX20P3483_DEVICE_CONTROL_REG, &reg);
+ /* Get device mode */
+ rv = read_reg(port, NX20P3483_DEVICE_STATUS_REG, &mode);
if (rv)
return rv;
+ mode &= NX20P3483_DEVICE_MODE_MASK;
- /* If in dead battery mode switch to SNK mode before exiting */
- if (!(reg & NX20P3483_CTRL_DB_EXIT)) {
- rv = nx20p3483_vbus_sink_enable(port, 1);
- if (rv)
- return rv;
+ /* Check if dead battery mode is active. */
+ if (mode == NX20P3483_MODE_DEAD_BATTERY) {
+ /*
+ * If in dead battery mode, must enable HV SNK mode prior to
+ * exiting dead battery mode or VBUS path will get cut off and
+ * system will lose power. Before DB mode is exited, the device
+ * mode will not reflect the correct value and therefore the
+ * return value isn't useful here.
+ */
+ nx20p3483_vbus_sink_enable(port, 1);
/* Exit dead battery mode. */
+ rv = read_reg(port, NX20P3483_DEVICE_CONTROL_REG, &reg);
+ if (rv)
+ return rv;
reg |= NX20P3483_CTRL_DB_EXIT;
rv = write_reg(port, NX20P3483_DEVICE_CONTROL_REG, reg);
if (rv)
return rv;
}
+ /*
+ * Set VBUS over voltage threshold (OVLO). Note that while the PPC is in
+ * dead battery mode, OVLO is forced to 6.8V, so this setting must be
+ * done after dead battery mode is exited.
+ */
+ nx20p3483_set_ovp_limit(port);
+
return EC_SUCCESS;
}
@@ -265,6 +296,12 @@ static void nx20p3483_handle_interrupt(int port)
read_reg(port, NX20P3483_DEVICE_CONTROL_REG, &control_reg);
reg |= NX20P3483_CTRL_DB_EXIT;
write_reg(port, NX20P3483_DEVICE_CONTROL_REG, control_reg);
+ /*
+ * If DB exit mode failed, then the OVP limit setting done in
+ * the init routine will not be successful. Set the OVP limit
+ * again here.
+ */
+ nx20p3483_set_ovp_limit(port);
}
/* Check for 5V OC interrupt */