summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorScott Collyer <scollyer@google.com>2018-03-16 09:44:32 -0700
committerchrome-bot <chrome-bot@chromium.org>2018-03-20 19:30:17 -0700
commit261afe62f30f0a259505b14ec1afcfb6fb1d781a (patch)
treeda3aacf1d6785da778d036784273532caa1ac96b
parent699838c0c1b9222d2d01d1575be3519fa8e3b9ba (diff)
downloadchrome-ec-261afe62f30f0a259505b14ec1afcfb6fb1d781a.tar.gz
ppc: Add driver for NX20P3483
The NX20P3483 is a USB PD and Type C high voltage sink/source combo switch. This CL adds support for this PPC variant. Unlike the TI SN5S330, the NX20P3483 does not support VCONN and does not need to be informed of CC polarity by the TCPM. To account for these differences, 2 new PPC config options are added and the driver for the TI SN5S330 was modified to include these new options. The SNK/SRC switch mode for the NX20P3483 is controlled by 2 GPIO signals which may be connected the EC or directly to the TCPC. To handle both cases, the ppc_chips structure was modified with a flags, snk_gpio, and src_gpio elements. BUG=b:74206647 BRANCH=none TEST=make -j buildall and verified there are no build errors. Change-Id: Ic4415ab7571b80e7661ea673434eaf4cf1f1fd2d Signed-off-by: Scott Collyer <scollyer@google.com> Reviewed-on: https://chromium-review.googlesource.com/966926 Commit-Ready: Scott Collyer <scollyer@chromium.org> Tested-by: Scott Collyer <scollyer@chromium.org> Reviewed-by: Aseda Aboagye <aaboagye@chromium.org> Reviewed-by: Furquan Shaikh <furquan@chromium.org>
-rw-r--r--common/usb_pd_protocol.c6
-rw-r--r--common/usbc_ppc.c4
-rw-r--r--driver/build.mk1
-rw-r--r--driver/ppc/nx20p3483.c326
-rw-r--r--driver/ppc/nx20p3483.h106
-rw-r--r--driver/ppc/sn5s330.c8
-rw-r--r--include/config.h15
-rw-r--r--include/usbc_ppc.h13
8 files changed, 475 insertions, 4 deletions
diff --git a/common/usb_pd_protocol.c b/common/usb_pd_protocol.c
index 12b1546217..2f25e06564 100644
--- a/common/usb_pd_protocol.c
+++ b/common/usb_pd_protocol.c
@@ -321,9 +321,9 @@ static inline int pd_is_vbus_present(int port)
static void set_polarity(int port, int polarity)
{
tcpm_set_polarity(port, polarity);
-#ifdef CONFIG_USBC_PPC
+#ifdef CONFIG_USBC_PPC_POLARITY
ppc_set_polarity(port, polarity);
-#endif /* defined(CONFIG_USBC_PPC) */
+#endif /* defined(CONFIG_USBC_PPC_POLARITY) */
}
#ifdef CONFIG_USBC_VCONN
@@ -337,7 +337,7 @@ static void set_vconn(int port, int enable)
* "make before break" electrical requirements when swapping anyway.
*/
tcpm_set_vconn(port, enable);
-#ifdef CONFIG_USBC_PPC
+#ifdef CONFIG_USBC_PPC_VCONN
ppc_set_vconn(port, enable);
#endif
}
diff --git a/common/usbc_ppc.c b/common/usbc_ppc.c
index 6ff79a17bf..7011309cf1 100644
--- a/common/usbc_ppc.c
+++ b/common/usbc_ppc.c
@@ -42,6 +42,7 @@ int ppc_is_sourcing_vbus(int port)
return ppc_chips[port].drv->is_sourcing_vbus(port);
}
+#ifdef CONFIG_USBC_PPC_POLARITY
int ppc_set_polarity(int port, int polarity)
{
if ((port < 0) || (port >= ppc_cnt))
@@ -49,6 +50,7 @@ int ppc_set_polarity(int port, int polarity)
return ppc_chips[port].drv->set_polarity(port, polarity);
}
+#endif
int ppc_set_vbus_source_current_limit(int port, enum tcpc_rp_value rp)
{
@@ -66,6 +68,7 @@ int ppc_discharge_vbus(int port, int enable)
return ppc_chips[port].drv->discharge_vbus(port, enable);
}
+#ifdef CONFIG_USBC_PPC_VCONN
int ppc_set_vconn(int port, int enable)
{
if ((port < 0) || (port >= ppc_cnt))
@@ -73,6 +76,7 @@ int ppc_set_vconn(int port, int enable)
return ppc_chips[port].drv->set_vconn(port, enable);
}
+#endif
int ppc_vbus_sink_enable(int port, int enable)
{
diff --git a/driver/build.mk b/driver/build.mk
index 23eb0a2d65..924a76eecd 100644
--- a/driver/build.mk
+++ b/driver/build.mk
@@ -116,6 +116,7 @@ driver-$(CONFIG_USB_MUX_VIRTUAL)+=usb_mux_virtual.o
# Type-C Power Path Controllers (PPC)
driver-$(CONFIG_USBC_PPC_SN5S330)+=ppc/sn5s330.o
+driver-$(CONFIG_USBC_PPC_NX20P3483)+=ppc/nx20p3483.o
# video converters
driver-$(CONFIG_MCDP28X0)+=mcdp28x0.o
diff --git a/driver/ppc/nx20p3483.c b/driver/ppc/nx20p3483.c
new file mode 100644
index 0000000000..7a3893443e
--- /dev/null
+++ b/driver/ppc/nx20p3483.c
@@ -0,0 +1,326 @@
+/* Copyright 2018 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+/* NX20P3483 USB-C Power Path Controller */
+
+#include "common.h"
+#include "console.h"
+#include "driver/ppc/nx20p3483.h"
+#include "gpio.h"
+#include "hooks.h"
+#include "i2c.h"
+#include "system.h"
+#include "usb_charge.h"
+#include "usb_pd_tcpm.h"
+#include "usbc_ppc.h"
+#include "util.h"
+
+#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args)
+#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args)
+
+#define NX20P3483_DB_EXIT_FAIL_THRESHOLD 10
+
+static uint32_t irq_pending; /* Bitmask of ports signaling an interrupt. */
+static int db_exit_fail_count[CONFIG_USB_PD_PORT_COUNT];
+
+static int read_reg(uint8_t port, int reg, int *regval)
+{
+ return i2c_read8(ppc_chips[port].i2c_port,
+ ppc_chips[port].i2c_addr,
+ reg,
+ regval);
+}
+
+static int write_reg(uint8_t port, int reg, int regval)
+{
+ return i2c_write8(ppc_chips[port].i2c_port,
+ ppc_chips[port].i2c_addr,
+ reg,
+ regval);
+}
+
+static int nx20p3483_is_sourcing_vbus(int port)
+{
+ int mode;
+ int rv;
+
+ rv = read_reg(port, NX20P3483_DEVICE_STATUS_REG, &mode);
+ if (rv) {
+ CPRINTS("p%d: Failed to determine NX20P device status! (%d)",
+ port, rv);
+ return 0;
+ }
+
+ return ((mode & NX20P3483_DEVICE_MODE_MASK) == NX20P3483_MODE_5V_SRC);
+}
+
+static int nx20p3483_set_vbus_source_current_limit(int port,
+ enum tcpc_rp_value rp)
+{
+ int regval;
+ int status;
+
+ status = read_reg(port, NX20P3483_5V_SRC_OCP_THRESHOLD_REG, &regval);
+ if (status)
+ return status;
+
+ regval &= ~NX20P3483_ILIM_MASK;
+ switch (rp) {
+ case TYPEC_RP_3A0:
+ regval |= NX20P3483_ILIM_3_000;
+ break;
+
+ case TYPEC_RP_1A5:
+ regval |= NX20P3483_ILIM_1_600;
+ break;
+
+ case TYPEC_RP_USB:
+ default:
+ regval |= NX20P3483_ILIM_0_600;
+ break;
+ };
+
+
+ return write_reg(port, NX20P3483_5V_SRC_OCP_THRESHOLD_REG, regval);
+}
+
+static int nx20p3483_discharge_vbus(int port, int enable)
+{
+ int regval;
+ int status;
+
+ status = read_reg(port, NX20P3483_DEVICE_CONTROL_REG, &regval);
+ if (status)
+ return status;
+
+ if (enable)
+ regval |= NX20P3483_CTRL_VBUSDIS_EN;
+ else
+ regval &= ~NX20P3483_CTRL_VBUSDIS_EN;
+
+ status = write_reg(port, NX20P3483_DEVICE_CONTROL_REG, regval);
+ if (status) {
+ CPRINTS("Failed to %s vbus discharge",
+ enable ? "enable" : "disable");
+ return status;
+ }
+
+ return EC_SUCCESS;
+}
+
+static int nx20p3483_vbus_sink_enable(int port, int enable)
+{
+ int status;
+ int rv;
+
+ enable = !!enable;
+ /*
+ * IF PPC_CFG_FLAGS_GPIO_CONTROL is set, then the SNK/SRC switch
+ * control is driven by the EC. Otherwise, it's controlled directly by
+ * the TCPC and only need to check the status.
+ */
+ if (ppc_chips[port].flags & PPC_CFG_FLAGS_GPIO_CONTROL) {
+
+ /* If enable, makes sure that SRC mode is disabled */
+ if (enable)
+ gpio_set_level(ppc_chips[port].src_gpio, 0);
+
+ /* Set SNK mode based on enable */
+ gpio_set_level(ppc_chips[port].snk_gpio, enable);
+ }
+
+ /* Verify switch status register */
+ rv = read_reg(port, NX20P3483_SWITCH_STATUS_REG, &status);
+ if (rv)
+ return rv;
+ status = !!(status & NX20P3483_HVSNK_STS);
+ return (status == enable) ? EC_SUCCESS : EC_ERROR_UNKNOWN;
+}
+
+static int nx20p3483_vbus_source_enable(int port, int enable)
+{
+ int status;
+ int rv;
+
+ enable = !!enable;
+ /*
+ * IF PPC_CFG_FLAGS_GPIO_CONTROL is set, then the SNK/SRC switch
+ * control is driven by the EC. Otherwise, it's controlled directly by
+ * the TCPC and only need to check the status.
+ */
+ if (ppc_chips[port].flags & PPC_CFG_FLAGS_GPIO_CONTROL) {
+
+ /* If enable, makes sure that SNK mode is disabled */
+ if (enable)
+ gpio_set_level(ppc_chips[port].snk_gpio, 0);
+
+ /* Set SRC mode based on enable */
+ gpio_set_level(ppc_chips[port].src_gpio, enable);
+ }
+
+ /* Verify switch status register */
+ rv = read_reg(port, NX20P3483_SWITCH_STATUS_REG, &status);
+ if (rv)
+ return rv;
+ status = !!(status & NX20P3483_5VSRC_STS);
+ return (status == enable) ? EC_SUCCESS : EC_ERROR_UNKNOWN;
+}
+
+static int nx20p3483_init(int port)
+{
+ int reg;
+ int mask;
+ 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);
+ if (rv)
+ return rv;
+
+ /* Mask interrupts for interrupt 1 register */
+ mask = ~(NX20P3483_INT1_OC_5VSRC | NX20P3483_INT1_DBEXIT_ERR);
+ rv = write_reg(port, NX20P3483_INTERRUPT1_MASK_REG, mask);
+ if (rv)
+ return rv;
+
+ /* Clear any pending interrupts by reading interrupt registers */
+ read_reg(port, NX20P3483_INTERRUPT1_REG, &reg);
+ read_reg(port, NX20P3483_INTERRUPT2_REG, &reg);
+
+ /* Make sure that dead battery mode is exited */
+ 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;
+
+ return EC_SUCCESS;
+}
+
+static void nx20p3483_handle_interrupt(int port)
+{
+ int reg;
+ int control_reg;
+
+ /*
+ * Read interrupt 1 status register. Note, interrupt register is
+ * automatically cleared by reading.
+ */
+ read_reg(port, NX20P3483_INTERRUPT1_REG, &reg);
+
+ /* Check for DBEXIT error */
+ if (reg & NX20P3483_INT1_DBEXIT_ERR) {
+ int mask_reg;
+
+ /*
+ * This failure is not expected. If for some reason, this
+ * keeps happening, then log an error and mask the interrupt to
+ * prevent interrupt floods.
+ */
+ if (++db_exit_fail_count[port] >=
+ NX20P3483_DB_EXIT_FAIL_THRESHOLD) {
+ CPRINTS("Port %d PPC failed to exit DB mode", port);
+ if (read_reg(port, NX20P3483_INTERRUPT1_MASK_REG,
+ &mask_reg)) {
+ mask_reg |= NX20P3483_INT1_DBEXIT_ERR;
+ write_reg(port, NX20P3483_INTERRUPT1_MASK_REG,
+ mask_reg);
+ }
+ }
+ read_reg(port, NX20P3483_DEVICE_CONTROL_REG, &control_reg);
+ reg |= NX20P3483_CTRL_DB_EXIT;
+ write_reg(port, NX20P3483_DEVICE_CONTROL_REG, control_reg);
+ }
+
+ /* Check for 5V OC interrupt */
+ if (reg & NX20P3483_INT1_OC_5VSRC) {
+ /*
+ * TODO (b/69935262): The overcurrent action hasn't
+ * been completed yet, but is required for TI PPC. When that
+ * work is complete, tie it in here.
+ */
+ }
+
+ /*
+ * Read interrupt 2 status register. Note, interrupt register is
+ * automatically cleared by reading.
+ */
+ /*
+ * TODO (b/75272421): Not sure if any of these interrupts
+ * will be used. Might want to use EN_ERR which tracks when both
+ * SNK_EN and SRC_EN are set. However, since for the Analogix TCPC
+ * these values aren't controlled by the EC directly, not sure what
+ * action if any can be taken.
+ */
+ read_reg(port, NX20P3483_INTERRUPT2_REG, &reg);
+}
+
+static void nx20p3483_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)
+ nx20p3483_handle_interrupt(i);
+}
+DECLARE_DEFERRED(nx20p3483_irq_deferred);
+
+void nx20p3483_interrupt(int port)
+{
+ atomic_or(&irq_pending, (1 << port));
+ hook_call_deferred(&nx20p3483_irq_deferred_data, 0);
+}
+
+#ifdef CONFIG_CMD_PPC_DUMP
+static int nx20p3483_dump(int port)
+{
+ int reg_addr;
+ int reg;
+ int rv;
+
+ ccprintf("Port %d NX20P3483 registers\n", port);
+ for (reg_addr = NX20P3483_DEVICE_ID_REG; reg_addr <=
+ NX20P3483_DEVICE_CONTROL_REG; reg_addr++) {
+ rv = read_reg(port, reg_addr, &reg);
+ if (rv) {
+ ccprintf("nx20p: Failed to read register 0x%x\n",
+ reg_addr);
+ return rv;
+ }
+ ccprintf("[0x%02x]: 0x%02x\n", reg_addr, reg);
+ }
+
+ return EC_SUCCESS;
+}
+#endif /* defined(CONFIG_CMD_PPC_DUMP) */
+
+const struct ppc_drv nx20p3483_drv = {
+ .init = &nx20p3483_init,
+ .is_sourcing_vbus = &nx20p3483_is_sourcing_vbus,
+ .vbus_sink_enable = &nx20p3483_vbus_sink_enable,
+ .vbus_source_enable = &nx20p3483_vbus_source_enable,
+#ifdef CONFIG_CMD_PPC_DUMP
+ .reg_dump = &nx20p3483_dump,
+#endif /* defined(CONFIG_CMD_PPC_DUMP) */
+ .set_vbus_source_current_limit =
+ &nx20p3483_set_vbus_source_current_limit,
+ .discharge_vbus = &nx20p3483_discharge_vbus,
+};
diff --git a/driver/ppc/nx20p3483.h b/driver/ppc/nx20p3483.h
new file mode 100644
index 0000000000..a85a0b72b4
--- /dev/null
+++ b/driver/ppc/nx20p3483.h
@@ -0,0 +1,106 @@
+/* Copyright 2018 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+/* NX20P3483 Type-C Power Path Controller */
+
+#ifndef __CROS_EC_NX20P3483_H
+#define __CROS_EC_NX20P3483_H
+
+#define NX20P3483_ADDR0 0xE0
+#define NX20P3483_ADDR1 0xE2
+#define NX20P3483_ADDR2 0xE4
+#define NX20P3483_ADDR3 0xE6
+
+/* NX20P3483 register addresses */
+#define NX20P3483_DEVICE_ID_REG 0x00
+#define NX20P3483_DEVICE_STATUS_REG 0x01
+#define NX20P3483_SWITCH_CONTROL_REG 0x02
+#define NX20P3483_SWITCH_STATUS_REG 0x03
+#define NX20P3483_INTERRUPT1_REG 0x04
+#define NX20P3483_INTERRUPT2_REG 0x05
+#define NX20P3483_INTERRUPT1_MASK_REG 0x06
+#define NX20P3483_INTERRUPT2_MASK_REG 0x07
+#define NX20P3483_OVLO_THRESHOLD_REG 0x08
+#define NX20P3483_HV_SRC_OCP_THRESHOLD_REG 0x09
+#define NX20P3483_5V_SRC_OCP_THRESHOLD_REG 0x0A
+#define NX20P3483_DEVICE_CONTROL_REG 0x0B
+
+/* Device Control Register */
+#define NX20P3483_CTRL_FRS_AT (1 << 3)
+#define NX20P3483_CTRL_DB_EXIT (1 << 2)
+#define NX20P3483_CTRL_VBUSDIS_EN (1 << 1)
+#define NX20P3483_CTRL_LDO_SD (1 << 0)
+
+/* Device Status Modes */
+#define NX20P3483_DEVICE_MODE_MASK 0x7
+#define NX20P3483_MODE_DEAD_BATTERY 0
+#define NX20P3483_MODE_HV_SNK 1
+#define NX20P3483_MODE_5V_SRC 2
+#define NX20P3483_MODE_HV_SRC 3
+#define NX20P3483_MODE_STANDBY 4
+
+/* Switch Status Register */
+#define NX20P3483_HVSNK_STS (1 << 0)
+#define NX20P3483_HVSRC_STS (1 << 1)
+#define NX20P3483_5VSRC_STS (1 << 2)
+
+/* Internal 5V VBUS Switch Current Limit Settings (min) */
+#define NX20P3483_ILIM_MASK 0xF
+#define NX20P3483_ILIM_0_400 0
+#define NX20P3483_ILIM_0_600 1
+#define NX20P3483_ILIM_0_800 2
+#define NX20P3483_ILIM_1_000 3
+#define NX20P3483_ILIM_1_200 4
+#define NX20P3483_ILIM_1_400 5
+#define NX20P3483_ILIM_1_600 6
+#define NX20P3483_ILIM_1_800 7
+#define NX20P3483_ILIM_2_000 8
+#define NX20P3483_ILIM_2_200 9
+#define NX20P3483_ILIM_2_400 10
+#define NX20P3483_ILIM_2_600 11
+#define NX20P3483_ILIM_2_800 12
+#define NX20P3483_ILIM_3_000 13
+#define NX20P3483_ILIM_3_200 14
+#define NX20P3483_ILIM_3_400 15
+
+/* HV VBUS over voltage threshold settings V_mV*/
+#define NX20P3483_OVLO_THRESHOLD_MASK 0x7
+#define NX20P3483_OVLO_06_0 0
+#define NX20P3483_OVLO_06_8 1
+#define NX20P3483_OVLO_10_0 2
+#define NX20P3483_OVLO_11_5 3
+#define NX20P3483_OVLO_14_0 4
+#define NX20P3483_OVLO_17_0 5
+#define NX20P3483_OVLO_23_0 6
+
+/* Interrupt 1 Register Bits */
+#define NX20P3483_INT1_DBEXIT_ERR (1 << 7)
+#define NX20P3483_INT1_OV_5VSRC (1 << 4)
+#define NX20P3483_INT1_RCP_5VSRC (1 << 3)
+#define NX20P3483_INT1_SC_5VSRC (1 << 2)
+#define NX20P3483_INT1_OC_5VSRC (1 << 1)
+#define NX20P3483_INT1_OTP (1 << 0)
+
+/* Interrupt 2 Register Bits */
+#define NX20P3483_INT2_EN_ERR (1 << 7)
+#define NX20P3483_INT2_RCP_HVSNK (1 << 6)
+#define NX20P3483_INT2_SC_HVSNK (1 << 5)
+#define NX20P3483_INT2_OV_HVSNK (1 << 4)
+#define NX20P3483_INT2_RCP_HVSRC (1 << 3)
+#define NX20P3483_INT2_SC_HVSRC (1 << 2)
+#define NX20P3483_INT2_OC_HVSRC (1 << 1)
+#define NX20P3483_INT2_OV_HVSRC (1 << 0)
+
+struct ppc_drv;
+extern const struct ppc_drv nx20p3483_drv;
+
+/**
+ * Interrupt Handler for the NX20P3483.
+ *
+ * @param port: The Type-C port which triggered the interrupt.
+ */
+void nx20p3483_interrupt(int port);
+
+#endif /* defined(__CROS_EC_NX20P3483_H) */
diff --git a/driver/ppc/sn5s330.c b/driver/ppc/sn5s330.c
index 25fa7ae022..e0abf3aacf 100644
--- a/driver/ppc/sn5s330.c
+++ b/driver/ppc/sn5s330.c
@@ -456,6 +456,7 @@ static int sn5s330_is_sourcing_vbus(int port)
return is_sourcing_vbus;
}
+#ifdef CONFIG_USBC_PPC_POLARITY
static int sn5s330_set_polarity(int port, int polarity)
{
int regval;
@@ -472,6 +473,7 @@ static int sn5s330_set_polarity(int port, int polarity)
return write_reg(port, SN5S330_FUNC_SET4, regval);
}
+#endif
static int sn5s330_set_vbus_source_current_limit(int port,
enum tcpc_rp_value rp)
@@ -533,6 +535,7 @@ static int sn5s330_discharge_vbus(int port, int enable)
return EC_SUCCESS;
}
+#ifdef CONFIG_USBC_PPC_VCONN
static int sn5s330_set_vconn(int port, int enable)
{
int regval;
@@ -549,6 +552,7 @@ static int sn5s330_set_vconn(int port, int enable)
return write_reg(port, SN5S330_FUNC_SET4, regval);
}
+#endif
static int sn5s330_vbus_sink_enable(int port, int enable)
{
@@ -623,8 +627,12 @@ const struct ppc_drv sn5s330_drv = {
#ifdef CONFIG_USB_PD_VBUS_DETECT_PPC
.is_vbus_present = &sn5s330_is_vbus_present,
#endif /* defined(CONFIG_USB_PD_VBUS_DETECT_PPC) */
+#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/include/config.h b/include/config.h
index 985c017cfb..62a8bb75b0 100644
--- a/include/config.h
+++ b/include/config.h
@@ -2894,9 +2894,16 @@
/* USB Product ID. */
#undef CONFIG_USB_PID
+/* PPC needs to be informed of CC polarity */
+#undef CONFIG_USBC_PPC_POLARITY
+
/* USB Type-C Power Path Controllers (PPC) */
+#undef CONFIG_USBC_PPC_NX20P3483
#undef CONFIG_USBC_PPC_SN5S330
+/* PPC is capable of providing VCONN */
+#undef CONFIG_USBC_PPC_VCONN
+
/* Support for USB type-c superspeed mux */
#undef CONFIG_USBC_SS_MUX
@@ -3344,10 +3351,16 @@
/*****************************************************************************/
/* Define CONFIG_USBC_PPC if board has a USB Type-C Power Path Controller. */
-#if defined(CONFIG_USBC_PPC_SN5S330)
+#if defined(CONFIG_USBC_PPC_SN5S330) || defined(CONFIG_USBC_PPC_NX20P3483)
#define CONFIG_USBC_PPC
#endif /* "has a PPC" */
+/* The TI SN5S330 supports VCONN and needs to be informed of CC polarity */
+#if defined(CONFIG_USBC_PPC_SN5S330)
+#define CONFIG_USBC_PPC_POLARITY
+#define CONFIG_USBC_PPC_VCONN
+#endif
+
/*****************************************************************************/
/*
* Define CONFIG_USB_PD_VBUS_MEASURE_CHARGER if the charger on the board
diff --git a/include/usbc_ppc.h b/include/usbc_ppc.h
index 54142b2921..1995654536 100644
--- a/include/usbc_ppc.h
+++ b/include/usbc_ppc.h
@@ -48,6 +48,7 @@ struct ppc_drv {
*/
int (*vbus_source_enable)(int port, int enable);
+#ifdef CONFIG_USBC_PPC_POLARITY
/**
* Inform the PPC of the polarity of the CC pins.
*
@@ -56,6 +57,7 @@ struct ppc_drv {
* @return EC_SUCCESS on success, error otherwise.
*/
int (*set_polarity)(int port, int polarity);
+#endif
/**
* Set the Vbus source path current limit
@@ -75,6 +77,7 @@ struct ppc_drv {
*/
int (*discharge_vbus)(int port, int enable);
+#ifdef CONFIG_USBC_PPC_VCONN
/**
* Turn on/off the VCONN FET.
*
@@ -82,6 +85,7 @@ struct ppc_drv {
* @param enable: 1: enable VCONN FET 0: disable VCONN FET.
*/
int (*set_vconn)(int port, int enable);
+#endif
#ifdef CONFIG_CMD_PPC_DUMP
/**
@@ -104,9 +108,18 @@ struct ppc_drv {
#endif /* defined(CONFIG_USB_PD_VBUS_DETECT_PPC) */
};
+
+/* PPC SNK/SRC switch control driven by EC GPIO */
+#define PPC_CFG_FLAGS_GPIO_CONTROL (1 << 0)
+
struct ppc_config_t {
+ /* Used for PPC_CFG_FLAGS_* defined above */
+ uint32_t flags;
int i2c_port;
int i2c_addr;
+ /* snk|src_gpio only required if PPC_CFG_FLAGS_GPIO_CONTROL is set */
+ enum gpio_signal snk_gpio;
+ enum gpio_signal src_gpio;
const struct ppc_drv *drv;
};