summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJett Rink <jettrink@chromium.org>2018-08-07 14:52:04 -0600
committerchrome-bot <chrome-bot@chromium.org>2018-08-23 17:42:49 -0700
commit7487f9eef6159b9b3253b4d30e9dd0b114bd07e1 (patch)
tree21b506771c042375da02ff0f1171b7f6712d699b
parenteab2576658393d15af7fc55e97e827951cafa05e (diff)
downloadchrome-ec-7487f9eef6159b9b3253b4d30e9dd0b114bd07e1.tar.gz
sn5s330: add low power mode
Add a low power mode method for PPCs behind a new config. Implement the low power method for SN5S330 based off of TI AE recommendation. BRANCH=none BUG=b:111520593,b:111006203 TEST=CL stack produce lower power during bip hibernate Change-Id: Icd22f88a8f65c2cd5ab1c95b0750b1eb61e91923 Signed-off-by: Jett Rink <jettrink@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/1166183 Commit-Ready: ChromeOS CL Exonerator Bot <chromiumos-cl-exonerator@appspot.gserviceaccount.com> Reviewed-by: Furquan Shaikh <furquan@chromium.org>
-rw-r--r--common/usbc_ppc.c13
-rw-r--r--driver/ppc/sn5s330.c57
-rw-r--r--driver/ppc/sn5s330.h39
-rw-r--r--include/usbc_ppc.h19
4 files changed, 106 insertions, 22 deletions
diff --git a/common/usbc_ppc.c b/common/usbc_ppc.c
index 7011309cf1..0961ba6e83 100644
--- a/common/usbc_ppc.c
+++ b/common/usbc_ppc.c
@@ -86,6 +86,19 @@ int ppc_vbus_sink_enable(int port, int enable)
return ppc_chips[port].drv->vbus_sink_enable(port, enable);
}
+int ppc_enter_low_power_mode(int port)
+{
+ const struct ppc_config_t *const ppc = &ppc_chips[port];
+
+ if ((port < 0) || (port >= ppc_cnt))
+ return EC_ERROR_INVAL;
+
+ if (ppc->drv->enter_low_power_mode)
+ return ppc->drv->enter_low_power_mode(port);
+ else
+ return EC_ERROR_UNIMPLEMENTED;
+}
+
int ppc_vbus_source_enable(int port, int enable)
{
if ((port < 0) || (port >= ppc_cnt))
diff --git a/driver/ppc/sn5s330.c b/driver/ppc/sn5s330.c
index 9855ab1d89..904a968a03 100644
--- a/driver/ppc/sn5s330.c
+++ b/driver/ppc/sn5s330.c
@@ -514,6 +514,54 @@ static int sn5s330_discharge_vbus(int port, int enable)
return EC_SUCCESS;
}
+static int sn5s330_enter_low_power_mode(int port)
+{
+ int rv;
+
+ /* Turn off both SRC and SNK FETs */
+ rv = clr_flags(port, SN5S330_FUNC_SET3,
+ SN5S330_PP1_EN | SN5S330_PP2_EN);
+
+ if (rv) {
+ CPRINTS("ppc p%d: Could not disable both FETS (%d)", port, rv);
+ return rv;
+ }
+
+ /* Turn off Vconn power */
+ rv = clr_flags(port, SN5S330_FUNC_SET4, SN5S330_VCONN_EN);
+
+ if (rv) {
+ CPRINTS("ppc p%d: Could not disable Vconn (%d)", port, rv);
+ return rv;
+ }
+
+ /* Turn off SBU path */
+ rv = clr_flags(port, SN5S330_FUNC_SET2, SN5S330_SBU_EN);
+
+ if (rv) {
+ CPRINTS("ppc p%d: Could not disable SBU path (%d)", port, rv);
+ return rv;
+ }
+
+ /*
+ * Turn off the Over Voltage Protection circuits. Needs to happen after
+ * FETs are disabled, otherwise OVP can automatically turned back on.
+ * Since FETs are off, any over voltage does not make it to the board
+ * side of the PPC.
+ */
+ rv = clr_flags(port, SN5S330_FUNC_SET9,
+ SN5S330_FORCE_OVP_EN_SBU | SN5S330_FORCE_ON_VBUS_OVP |
+ SN5S330_FORCE_ON_VBUS_UVP);
+
+ if (rv) {
+ CPRINTS("ppc p%d: Could not disable OVP circuit (%d)", port,
+ rv);
+ return rv;
+ }
+
+ return EC_SUCCESS;
+}
+
#ifdef CONFIG_USBC_PPC_VCONN
static int sn5s330_set_vconn(int port, int enable)
{
@@ -600,17 +648,18 @@ const struct ppc_drv sn5s330_drv = {
.is_sourcing_vbus = &sn5s330_is_sourcing_vbus,
.vbus_sink_enable = &sn5s330_vbus_sink_enable,
.vbus_source_enable = &sn5s330_vbus_source_enable,
+ .set_vbus_source_current_limit = &sn5s330_set_vbus_source_current_limit,
+ .discharge_vbus = &sn5s330_discharge_vbus,
+ .enter_low_power_mode = &sn5s330_enter_low_power_mode,
#ifdef CONFIG_CMD_PPC_DUMP
.reg_dump = &sn5s330_dump,
-#endif /* defined(CONFIG_CMD_PPC_DUMP) */
+#endif
#ifdef CONFIG_USB_PD_VBUS_DETECT_PPC
.is_vbus_present = &sn5s330_is_vbus_present,
-#endif /* defined(CONFIG_USB_PD_VBUS_DETECT_PPC) */
+#endif
#ifdef CONFIG_USBC_PPC_POLARITY
.set_polarity = &sn5s330_set_polarity,
#endif
- .set_vbus_source_current_limit = &sn5s330_set_vbus_source_current_limit,
- .discharge_vbus = &sn5s330_discharge_vbus,
#ifdef CONFIG_USBC_PPC_VCONN
.set_vconn = &sn5s330_set_vconn,
#endif
diff --git a/driver/ppc/sn5s330.h b/driver/ppc/sn5s330.h
index 2b17a1d46a..fcb41204ef 100644
--- a/driver/ppc/sn5s330.h
+++ b/driver/ppc/sn5s330.h
@@ -86,34 +86,37 @@ enum sn5s330_pp_idx {
#define SN5S330_ILIM_3_30 12
/* FUNC_SET_2 */
-#define SN5S330_SBU_EN (1 << 4)
+#define SN5S330_SBU_EN (1 << 4)
/* FUNC_SET_3 */
-#define SN5S330_PP1_EN (1 << 0)
-#define SN5S330_PP2_EN (1 << 1)
-#define SN5S330_VBUS_DISCH_EN (1 << 2)
-#define SN5S330_SET_RCP_MODE_PP1 (1 << 5)
-#define SN5S330_SET_RCP_MODE_PP2 (1 << 6)
+#define SN5S330_PP1_EN (1 << 0)
+#define SN5S330_PP2_EN (1 << 1)
+#define SN5S330_VBUS_DISCH_EN (1 << 2)
+#define SN5S330_SET_RCP_MODE_PP1 (1 << 5)
+#define SN5S330_SET_RCP_MODE_PP2 (1 << 6)
/* FUNC_SET_4 */
-#define SN5S330_VCONN_EN (1 << 0)
-#define SN5S330_CC_POLARITY (1 << 1)
-#define SN5S330_CC_EN (1 << 4)
-#define SN5S330_VCONN_ILIM_SEL (1 << 5)
+#define SN5S330_VCONN_EN (1 << 0)
+#define SN5S330_CC_POLARITY (1 << 1)
+#define SN5S330_CC_EN (1 << 4)
+#define SN5S330_VCONN_ILIM_SEL (1 << 5)
/* FUNC_SET_9 */
-#define SN5S330_PP2_CONFIG (1 << 2)
-#define SN5S330_OVP_EN_CC (1 << 4)
-#define SN5S330_CONFIG_UVP (1 << 5)
+#define SN5S330_FORCE_OVP_EN_SBU (1 << 1)
+#define SN5S330_PP2_CONFIG (1 << 2)
+#define SN5S330_OVP_EN_CC (1 << 4)
+#define SN5S330_CONFIG_UVP (1 << 5)
+#define SN5S330_FORCE_ON_VBUS_OVP (1 << 6)
+#define SN5S330_FORCE_ON_VBUS_UVP (1 << 7)
/* INT_STATUS_REG3 */
-#define SN5S330_VBUS_GOOD (1 << 0)
+#define SN5S330_VBUS_GOOD (1 << 0)
/* 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)
+#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/FALL_EDGE_1
diff --git a/include/usbc_ppc.h b/include/usbc_ppc.h
index d65fa79f0e..a93f7e7109 100644
--- a/include/usbc_ppc.h
+++ b/include/usbc_ppc.h
@@ -106,6 +106,15 @@ struct ppc_drv {
*/
int (*is_vbus_present)(int port);
#endif /* defined(CONFIG_USB_PD_VBUS_DETECT_PPC) */
+
+ /**
+ * Optional method to put the PPC into its lowest power state. In this
+ * state it should still fire interrupts if Vbus changes etc.
+ *
+ * @param port: The Type-C port number.
+ * @return EC_SUCCESS on success, error otherwise.
+ */
+ int (*enter_low_power_mode)(int port);
};
struct ppc_config_t {
@@ -203,4 +212,14 @@ int ppc_vbus_source_enable(int port, int enable);
*/
void board_overcurrent_event(int port);
+/**
+ * Put the PPC into its lowest power state. In this state it should still fire
+ * interrupts if Vbus changes etc. This is called by board-specific code when
+ * appropriate.
+ *
+ * @param port: The Type-C port number.
+ * @return EC_SUCCESS on success, error otherwise.
+ */
+int ppc_enter_low_power_mode(int port);
+
#endif /* !defined(__CROS_EC_USBC_PPC_H) */