diff options
author | Vincent Palatin <vpalatin@chromium.org> | 2016-08-22 15:34:42 +0200 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2016-08-25 07:32:31 -0700 |
commit | e880402f74c7c76b269222caad6c3c80d3d6549e (patch) | |
tree | 1fe28d4b441b6bdae50b1f12cc9eb01a1db4855e /driver | |
parent | 613be38789b8d54aaf43c452ea348782fe53e9c0 (diff) | |
download | chrome-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.c | 60 | ||||
-rw-r--r-- | driver/tcpm/anx7688.c | 1 | ||||
-rw-r--r-- | driver/tcpm/fusb302.c | 80 | ||||
-rw-r--r-- | driver/tcpm/fusb302.h | 7 | ||||
-rw-r--r-- | driver/tcpm/it83xx.c | 42 | ||||
-rw-r--r-- | driver/tcpm/stub.c | 5 | ||||
-rw-r--r-- | driver/tcpm/tcpci.c | 34 | ||||
-rw-r--r-- | driver/tcpm/tcpci.h | 3 | ||||
-rw-r--r-- | driver/tcpm/tcpm.h | 15 |
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, ®); + 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, ®); + rv = tcpc_read(port, ANX74XX_REG_IRQ_SOURCE_RECV_MSG_MASK, ®); + 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, ®); - 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, ®); @@ -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, ®); + + 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, ®); + 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 &= ~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, ®); + 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, ®); + 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 |