summaryrefslogtreecommitdiff
path: root/driver
diff options
context:
space:
mode:
authorVincent Palatin <vpalatin@chromium.org>2016-08-22 15:34:42 +0200
committerchrome-bot <chrome-bot@chromium.org>2016-08-25 07:32:31 -0700
commite880402f74c7c76b269222caad6c3c80d3d6549e (patch)
tree1fe28d4b441b6bdae50b1f12cc9eb01a1db4855e /driver
parent613be38789b8d54aaf43c452ea348782fe53e9c0 (diff)
downloadchrome-ec-e880402f74c7c76b269222caad6c3c80d3d6549e.tar.gz
pd: select dynamically Rp value
Add API to switch the Rp pull-up value on CC dynamically at runtime. This is a preparatory work for boards having a more complex maximum source current policy (eg 2 ports sharing a common pool of power). For fusb302, update the voltage thresholds for open/Rd/Ra as they depend on the Rp (was missing from the previous change). Signed-off-by: Vincent Palatin <vpalatin@chromium.org> BRANCH=none BUG=chrome-os-partner:56110 TEST=make buildall Change-Id: Id3c24a31a16217075a398ec21ef58ee07187a882 Reviewed-on: https://chromium-review.googlesource.com/373501 Commit-Ready: Vincent Palatin <vpalatin@chromium.org> Tested-by: Vincent Palatin <vpalatin@chromium.org> Reviewed-by: Vincent Palatin <vpalatin@chromium.org>
Diffstat (limited to 'driver')
-rw-r--r--driver/tcpm/anx74xx.c60
-rw-r--r--driver/tcpm/anx7688.c1
-rw-r--r--driver/tcpm/fusb302.c80
-rw-r--r--driver/tcpm/fusb302.h7
-rw-r--r--driver/tcpm/it83xx.c42
-rw-r--r--driver/tcpm/stub.c5
-rw-r--r--driver/tcpm/tcpci.c34
-rw-r--r--driver/tcpm/tcpci.h3
-rw-r--r--driver/tcpm/tcpm.h15
9 files changed, 163 insertions, 84 deletions
diff --git a/driver/tcpm/anx74xx.c b/driver/tcpm/anx74xx.c
index 0465a5179e..d229f37e12 100644
--- a/driver/tcpm/anx74xx.c
+++ b/driver/tcpm/anx74xx.c
@@ -436,6 +436,36 @@ static int anx74xx_tcpm_get_cc(int port, int *cc1, int *cc2)
return EC_SUCCESS;
}
+static int anx74xx_tcpm_select_rp_value(int port, int rp)
+{
+ int reg;
+ int rv;
+
+ rv = tcpc_read(port, ANX74XX_REG_ANALOG_CTRL_6, &reg);
+ if (rv)
+ return EC_ERROR_UNKNOWN;
+
+ /* clear Bit[0,1] R_RP to default Rp's value */
+ reg &= ~0x03;
+
+ switch (rp) {
+ case TYPEC_RP_1A5:
+ /* Set Rp strength to 12K for presenting 1.5A */
+ reg |= ANX74XX_REG_CC_PULL_RP_12K;
+ break;
+ case TYPEC_RP_3A0:
+ /* Set Rp strength to 4K for presenting 3A */
+ reg |= ANX74XX_REG_CC_PULL_RP_4K;
+ break;
+ case TYPEC_RP_USB:
+ default:
+ /* default: Set Rp strength to 36K */
+ break;
+ }
+
+ return tcpc_write(port, ANX74XX_REG_ANALOG_CTRL_6, reg);
+}
+
static int anx74xx_tcpm_set_cc(int port, int pull)
{
int rv = EC_SUCCESS;
@@ -592,36 +622,17 @@ static int anx74xx_alert_status(int port, int *alert)
static int anx74xx_tcpm_set_rx_enable(int port, int enable)
{
- int reg, rv = 0;
+ int reg, rv;
- rv |= tcpc_read(port, ANX74XX_REG_IRQ_SOURCE_RECV_MSG_MASK, &reg);
+ rv = tcpc_read(port, ANX74XX_REG_IRQ_SOURCE_RECV_MSG_MASK, &reg);
+ if (rv)
+ return rv;
if (enable)
reg &= ~(ANX74XX_REG_IRQ_CC_MSG_INT);
else/* Disable RX message by masking interrupt */
reg |= (ANX74XX_REG_IRQ_CC_MSG_INT);
anx74xx_tcpm_set_auto_good_crc(port, enable);
- rv |= tcpc_write(port, ANX74XX_REG_IRQ_SOURCE_RECV_MSG_MASK, reg);
-
- /* patch for Rp 36K issue */
- rv |= tcpc_read(port, ANX74XX_REG_ANALOG_CTRL_6, &reg);
- if (rv)
- return EC_ERROR_UNKNOWN;
-
- /* clear Bit[0,1] R_RP to default Rp's value */
- reg &= ~0x03;
-
- if (enable) {
-#ifdef CONFIG_USB_PD_PULLUP_1_5A
- /* Set Rp strength to 12K for presenting 1.5A */
- reg |= ANX74XX_REG_CC_PULL_RP_12K;
-#elif defined(CONFIG_USB_PD_PULLUP_3A)
- /* Set Rp strength to 4K for presenting 3A */
- reg |= ANX74XX_REG_CC_PULL_RP_4K;
-#endif
- }
- rv |= tcpc_write(port, ANX74XX_REG_ANALOG_CTRL_6, reg);
-
- return rv;
+ return tcpc_write(port, ANX74XX_REG_IRQ_SOURCE_RECV_MSG_MASK, reg);
}
#ifdef CONFIG_USB_PD_VBUS_DETECT_TCPC
@@ -830,6 +841,7 @@ const struct tcpm_drv anx74xx_tcpm_drv = {
#ifdef CONFIG_USB_PD_VBUS_DETECT_TCPC
.get_vbus_level = &anx74xx_tcpm_get_vbus_level,
#endif
+ .select_rp_value = &anx74xx_tcpm_select_rp_value,
.set_cc = &anx74xx_tcpm_set_cc,
.set_polarity = &anx74xx_tcpm_set_polarity,
.set_vconn = &anx74xx_tcpm_set_vconn,
diff --git a/driver/tcpm/anx7688.c b/driver/tcpm/anx7688.c
index ae1dd32124..7dda345302 100644
--- a/driver/tcpm/anx7688.c
+++ b/driver/tcpm/anx7688.c
@@ -182,6 +182,7 @@ const struct tcpm_drv anx7688_tcpm_drv = {
#ifdef CONFIG_USB_PD_VBUS_DETECT_TCPC
.get_vbus_level = &anx7688_tcpm_get_vbus_level,
#endif
+ .select_rp_value = &tcpci_tcpm_select_rp_value,
.set_cc = &tcpci_tcpm_set_cc,
.set_polarity = &tcpci_tcpm_set_polarity,
.set_vconn = &tcpci_tcpm_set_vconn,
diff --git a/driver/tcpm/fusb302.c b/driver/tcpm/fusb302.c
index a174e5193e..4493adff52 100644
--- a/driver/tcpm/fusb302.c
+++ b/driver/tcpm/fusb302.c
@@ -30,6 +30,8 @@ static struct fusb302_chip_state {
int tx_hard_reset_req;
int device_id;
struct mutex set_cc_lock;
+ uint8_t mdac_vnc;
+ uint8_t mdac_rd;
} state[CONFIG_USB_PD_PORT_COUNT];
/* bring the FUSB302 out of reset after Hard Reset signaling */
@@ -100,7 +102,6 @@ static int measure_cc_pin_source(int port, int cc_measure)
int switches0_reg;
int reg;
int cc_lvl;
- int bc_lvl;
/* Read status register */
tcpc_read(port, TCPC_REG_SWITCHES0, &reg);
@@ -119,8 +120,8 @@ static int measure_cc_pin_source(int port, int cc_measure)
/* Set measurement switch */
tcpc_write(port, TCPC_REG_SWITCHES0, reg);
- /* Set MDAC for Open vs Rd/Ra comparison (~1.6V) */
- tcpc_write(port, TCPC_REG_MEASURE, 0x26);
+ /* Set MDAC for Open vs Rd/Ra comparison */
+ tcpc_write(port, TCPC_REG_MEASURE, state[port].mdac_vnc);
/* Wait on measurement */
usleep(250);
@@ -131,16 +132,19 @@ static int measure_cc_pin_source(int port, int cc_measure)
/* Assume open */
cc_lvl = TYPEC_CC_VOLT_OPEN;
+ /* CC level is below the 'no connect' threshold (vOpen) */
if ((reg & TCPC_REG_STATUS0_COMP) == 0) {
- /*
- * CC line is < 1.6V, now need to determine if Rd or Ra is
- * attached. The Ra threshold is < 200 mV and so can use the
- * bc_lvl field of STATUS0 register.
- */
- bc_lvl = reg & (TCPC_REG_STATUS0_BC_LVL1 |
- TCPC_REG_STATUS0_BC_LVL0);
+ /* Set MDAC for Rd vs Ra comparison */
+ tcpc_write(port, TCPC_REG_MEASURE, state[port].mdac_rd);
+
+ /* Wait on measurement */
+ usleep(250);
- cc_lvl = bc_lvl ? TYPEC_CC_VOLT_RD : TYPEC_CC_VOLT_RA;
+ /* Read status register */
+ tcpc_read(port, TCPC_REG_STATUS0, &reg);
+
+ cc_lvl = (reg & TCPC_REG_STATUS0_COMP) ? TYPEC_CC_VOLT_RD
+ : TYPEC_CC_VOLT_RA;
}
/* Restore SWITCHES0 register to its value prior */
@@ -339,6 +343,40 @@ static int fusb302_send_message(int port, uint16_t header, const uint32_t *data,
return rv;
}
+static int fusb302_tcpm_select_rp_value(int port, int rp)
+{
+ int reg;
+ int rv;
+ uint8_t vnc, rd;
+
+ rv = tcpc_read(port, TCPC_REG_CONTROL0, &reg);
+ if (rv)
+ return rv;
+
+ /* Set the current source for Rp value */
+ reg &= ~TCPC_REG_CONTROL0_HOST_CUR_MASK;
+ switch (rp) {
+ case TYPEC_RP_1A5:
+ reg |= TCPC_REG_CONTROL0_HOST_CUR_1A5;
+ vnc = TCPC_REG_MEASURE_MDAC_MV(PD_SRC_1_5_VNC_MV);
+ rd = TCPC_REG_MEASURE_MDAC_MV(PD_SRC_1_5_RD_THRESH_MV);
+ break;
+ case TYPEC_RP_3A0:
+ reg |= TCPC_REG_CONTROL0_HOST_CUR_3A0;
+ vnc = TCPC_REG_MEASURE_MDAC_MV(PD_SRC_3_0_VNC_MV);
+ rd = TCPC_REG_MEASURE_MDAC_MV(PD_SRC_3_0_RD_THRESH_MV);
+ break;
+ case TYPEC_RP_USB:
+ default:
+ reg |= TCPC_REG_CONTROL0_HOST_CUR_USB;
+ vnc = TCPC_REG_MEASURE_MDAC_MV(PD_SRC_DEF_VNC_MV);
+ rd = TCPC_REG_MEASURE_MDAC_MV(PD_SRC_DEF_RD_THRESH_MV);
+ }
+ state[port].mdac_vnc = vnc;
+ state[port].mdac_rd = rd;
+ return tcpc_write(port, TCPC_REG_CONTROL0, reg);
+}
+
static int fusb302_tcpm_init(int port)
{
int reg;
@@ -347,6 +385,10 @@ static int fusb302_tcpm_init(int port)
state[port].cc_polarity = -1;
state[port].previous_pull = TYPEC_CC_RD;
+ /* set the voltage threshold for no connect detection (vOpen) */
+ state[port].mdac_vnc = TCPC_REG_MEASURE_MDAC_MV(PD_SRC_DEF_VNC_MV);
+ /* set the voltage threshold for Rd vs Ra detection */
+ state[port].mdac_rd = TCPC_REG_MEASURE_MDAC_MV(PD_SRC_DEF_RD_THRESH_MV);
/* all other variables assumed to default to 0 */
@@ -397,15 +439,6 @@ static int fusb302_tcpm_init(int port)
/* Interrupt Enable */
tcpc_read(port, TCPC_REG_CONTROL0, &reg);
reg &= ~TCPC_REG_CONTROL0_INT_MASK;
- /* Set the current source for Rp value */
- reg &= ~TCPC_REG_CONTROL0_HOST_CUR_MASK;
-#ifdef CONFIG_USB_PD_PULLUP_1_5A
- reg |= TCPC_REG_CONTROL0_HOST_CUR_1A5;
-#elif defined(CONFIG_USB_PD_PULLUP_3A)
- reg |= TCPC_REG_CONTROL0_HOST_CUR_3A0;
-#else
- reg |= TCPC_REG_CONTROL0_HOST_CUR_USB;
-#endif
tcpc_write(port, TCPC_REG_CONTROL0, reg);
/* Set VCONN switch defaults */
@@ -468,12 +501,6 @@ static int fusb302_tcpm_set_cc(int port, int pull)
case TYPEC_CC_RP:
/* Only use autodetect feature for revA silicon */
- /*
- * TODO(crosbug.com/p/54452): Add configuration of Rp strength
- * values for presenting desired current to port partner.
- * This value will depend on config flags
- * CONFIG_USB_PD_PULLUP_* in the board file
- */
/* if fusb302 hasn't figured anything out yet */
if ((state[port].device_id == FUSB302_DEVID_302A) &&
!state[port].togdone_pullup_cc1 &&
@@ -1032,6 +1059,7 @@ const struct tcpm_drv fusb302_tcpm_drv = {
#ifdef CONFIG_USB_PD_VBUS_DETECT_TCPC
.get_vbus_level = &fusb302_tcpm_get_vbus_level,
#endif
+ .select_rp_value = &fusb302_tcpm_select_rp_value,
.set_cc = &fusb302_tcpm_set_cc,
.set_polarity = &fusb302_tcpm_set_polarity,
.set_vconn = &fusb302_tcpm_set_vconn,
diff --git a/driver/tcpm/fusb302.h b/driver/tcpm/fusb302.h
index edf8c3fdf8..dc191bee5a 100644
--- a/driver/tcpm/fusb302.h
+++ b/driver/tcpm/fusb302.h
@@ -50,12 +50,7 @@
#define TCPC_REG_MEASURE 0x04
#define TCPC_REG_MEASURE_VBUS (1<<6)
-#define TCPC_REG_MEASURE_MDAC5 (1<<5)
-#define TCPC_REG_MEASURE_MDAC4 (1<<4)
-#define TCPC_REG_MEASURE_MDAC3 (1<<3)
-#define TCPC_REG_MEASURE_MDAC2 (1<<2)
-#define TCPC_REG_MEASURE_MDAC1 (1<<1)
-#define TCPC_REG_MEASURE_MDAC0 (1<<0)
+#define TCPC_REG_MEASURE_MDAC_MV(mv) (((mv)/42) & 0x3f)
#define TCPC_REG_CONTROL0 0x06
#define TCPC_REG_CONTROL0_TX_FLUSH (1<<6)
diff --git a/driver/tcpm/it83xx.c b/driver/tcpm/it83xx.c
index f7bdf5b60b..c3ac8fb49d 100644
--- a/driver/tcpm/it83xx.c
+++ b/driver/tcpm/it83xx.c
@@ -274,23 +274,7 @@ static void it83xx_init(enum usbpd_port port, int role)
/* W/C status */
IT83XX_USBPD_ISR(port) = 0xff;
/* enable cc, select cc1 and Rd. */
- /*
- * bit[3-2]: CC output current (when Rp selected)
- * 00: reserved
- * 01: 330uA outpt (3.0A)
- * 10: 180uA outpt (1.5A)
- * 11: 80uA outpt (USB default)
- */
-#ifdef CONFIG_USB_PD_PULLUP_1_5A
- /* (Rp 1.5A when selected) */
- IT83XX_USBPD_CCGCR(port) = 0x9;
-#elif defined(CONFIG_USB_PD_PULLUP_3A)
- /* (Rp 3.0A when selected) */
- IT83XX_USBPD_CCGCR(port) = 0x5;
-#else
- /* (Rp default when selected) */
IT83XX_USBPD_CCGCR(port) = 0xd;
-#endif
/* change data role as the same power role */
it83xx_set_data_role(port, role);
/* set power role */
@@ -349,6 +333,31 @@ static int it83xx_tcpm_get_cc(int port, int *cc1, int *cc2)
return EC_SUCCESS;
}
+static int it83xx_tcpm_select_rp_value(int port, int rp)
+{
+ uint8_t rp;
+ /*
+ * bit[3-2]: CC output current (when Rp selected)
+ * 00: reserved
+ * 01: 330uA outpt (3.0A)
+ * 10: 180uA outpt (1.5A)
+ * 11: 80uA outpt (USB default)
+ */
+ switch (rp) {
+ case TYPEC_RP_1A5:
+ rp = 2 << 2;
+ break;
+ case TYPEC_RP_3A0:
+ rp = 1 << 2;
+ break;
+ case TYPEC_RP_USB:
+ default:
+ rp = 3 << 2;
+ break;
+ }
+ IT83XX_USBPD_CCGCR(port) = (IT83XX_USBPD_CCGCR(port) & ~(3 << 2)) | Rp;
+}
+
static int it83xx_tcpm_set_cc(int port, int pull)
{
it83xx_set_cc(port, pull);
@@ -459,6 +468,7 @@ const struct tcpm_drv it83xx_tcpm_drv = {
#ifdef CONFIG_USB_PD_VBUS_DETECT_TCPC
.get_vbus_level = NULL,
#endif
+ .select_rp_value = &it83xx_tcpm_select_rp_value,
.set_cc = &it83xx_tcpm_set_cc,
.set_polarity = &it83xx_tcpm_set_polarity,
.set_vconn = &it83xx_tcpm_set_vconn,
diff --git a/driver/tcpm/stub.c b/driver/tcpm/stub.c
index 91ac6638d7..ae3f00f420 100644
--- a/driver/tcpm/stub.c
+++ b/driver/tcpm/stub.c
@@ -66,6 +66,11 @@ int tcpm_get_cc(int port, int *cc1, int *cc2)
return tcpc_get_cc(port, cc1, cc2);
}
+int tcpm_select_rp_value(int port, int rp)
+{
+ return -EC_ERROR_UNIMPLEMENTED;
+}
+
int tcpm_set_cc(int port, int pull)
{
return tcpc_set_cc(port, pull);
diff --git a/driver/tcpm/tcpci.c b/driver/tcpm/tcpci.c
index 14ab07769a..c4600792b0 100644
--- a/driver/tcpm/tcpci.c
+++ b/driver/tcpm/tcpci.c
@@ -85,23 +85,32 @@ static int tcpci_tcpm_get_power_status(int port, int *status)
return tcpc_read(port, TCPC_REG_POWER_STATUS, status);
}
+int tcpci_tcpm_select_rp_value(int port, int rp)
+{
+ int reg;
+ int rv;
+
+ rv = tcpc_read(port, TCPC_REG_ROLE_CTRL, &reg);
+ if (rv)
+ return rv;
+ reg = (reg & ~TCPC_REG_ROLE_CTRL_RP_MASK)
+ | ((rp << 4) & TCPC_REG_ROLE_CTRL_RP_MASK);
+ return tcpc_write(port, TCPC_REG_ROLE_CTRL, reg);
+}
+
int tcpci_tcpm_set_cc(int port, int pull)
{
- uint8_t rp = 0;
+ int reg, rv;
+ uint8_t rp;
+
+ rv = tcpc_read(port, TCPC_REG_ROLE_CTRL, &reg);
+ if (rv)
+ return rv;
+ rp = TCPC_REG_ROLE_CTRL_RP(reg);
/*
* Set manual control of Rp/Rd, and set both CC lines to the same
- * pull. Set desired Rp strength:
- * 00: Rp default
- * 01: Rp 1.5A
- * 10: Rp 3.0A
- * 11: Reserved
+ * pull.
*/
-#ifdef CONFIG_USB_PD_PULLUP_1_5A
- rp = 0x01;
-#elif defined(CONFIG_USB_PD_PULLUP_3A)
- rp = 0x02;
-#endif
-
return tcpc_write(port, TCPC_REG_ROLE_CTRL,
TCPC_REG_ROLE_CTRL_SET(0, rp, pull, pull));
}
@@ -366,6 +375,7 @@ const struct tcpm_drv tcpci_tcpm_drv = {
#ifdef CONFIG_USB_PD_VBUS_DETECT_TCPC
.get_vbus_level = &tcpci_tcpm_get_vbus_level,
#endif
+ .select_rp_value = &tcpci_tcpm_select_rp_value,
.set_cc = &tcpci_tcpm_set_cc,
.set_polarity = &tcpci_tcpm_set_polarity,
.set_vconn = &tcpci_tcpm_set_vconn,
diff --git a/driver/tcpm/tcpci.h b/driver/tcpm/tcpci.h
index 1417640a26..88f7030929 100644
--- a/driver/tcpm/tcpci.h
+++ b/driver/tcpm/tcpci.h
@@ -54,6 +54,8 @@
#define TCPC_REG_ROLE_CTRL 0x1a
#define TCPC_REG_ROLE_CTRL_SET(drp, rp, cc1, cc2) \
((drp) << 6 | (rp) << 4 | (cc2) << 2 | (cc1))
+#define TCPC_REG_ROLE_CTRL_RP_MASK 0x30
+#define TCPC_REG_ROLE_CTRL_RP(reg) (((reg) & TCPC_REG_ROLE_CTRL_RP_MASK) >> 4)
#define TCPC_REG_ROLE_CTRL_CC2(reg) (((reg) & 0xc) >> 2)
#define TCPC_REG_ROLE_CTRL_CC1(reg) ((reg) & 0x3)
@@ -117,6 +119,7 @@ extern const struct usb_mux_driver tcpci_tcpm_usb_mux_driver;
int tcpci_tcpm_get_cc(int port, int *cc1, int *cc2);
int tcpci_tcpm_get_vbus_level(int port);
+int tcpci_tcpm_select_rp_value(int port, int rp);
int tcpci_tcpm_set_cc(int port, int pull);
int tcpci_tcpm_set_polarity(int port, int polarity);
int tcpci_tcpm_set_vconn(int port, int enable);
diff --git a/driver/tcpm/tcpm.h b/driver/tcpm/tcpm.h
index 16cf879f72..b0398f85b1 100644
--- a/driver/tcpm/tcpm.h
+++ b/driver/tcpm/tcpm.h
@@ -78,6 +78,11 @@ static inline int tcpm_get_vbus_level(int port)
return tcpc_config[port].drv->get_vbus_level(port);
}
+static inline int tcpm_select_rp_value(int port, int rp)
+{
+ return tcpc_config[port].drv->select_rp_value(port, rp);
+}
+
static inline int tcpm_set_cc(int port, int pull)
{
return tcpc_config[port].drv->set_cc(port, pull);
@@ -152,6 +157,16 @@ int tcpm_get_cc(int port, int *cc1, int *cc2);
int tcpm_get_vbus_level(int port);
/**
+ * Set the value of the CC pull-up used when we are a source.
+ *
+ * @param port Type-C port number
+ * @param rp One of enum tcpc_rp_value
+ *
+ * @return EC_SUCCESS or error
+ */
+int tcpm_select_rp_value(int port, int rp);
+
+/**
* Set the CC pull resistor. This sets our role as either source or sink.
*
* @param port Type-C port number