diff options
author | Scott <scollyer@chromium.org> | 2015-06-04 16:03:28 -0700 |
---|---|---|
committer | ChromeOS Commit Bot <chromeos-commit-bot@chromium.org> | 2015-06-23 19:18:44 +0000 |
commit | 99e964c018eec1cba83022361866dd0b14d47610 (patch) | |
tree | 67cb7b386101bbd2abf2f45fc66ffdfd8d1bceb9 /common/usb_pd_tcpc.c | |
parent | 0e2176304f3af2b78e8e0b12dab8feb82abccd8f (diff) | |
download | chrome-ec-99e964c018eec1cba83022361866dd0b14d47610.tar.gz |
pd: Add support for TCPC Alert and Alert_Mask registers
Changed the alert function to hold the ec_int line until
all of the alert bits are cleared. Added support for the
alert_mask register. In addition, created ec_int_status
variable to distinguish which of 3 ec_int sources is
driving the pd_mcu_int line.
BUG=none
BRANCH=tot
TEST=Tested Zinger to Glados and Zinger to Samus and verified
that it established a power contract in both cases. Did not
test Oak, but put exact same changes in board.c as in glados.
Change-Id: I372e75b8fd5d66a0c01db18b46100b86fd9ac064
Signed-off-by: Scott Collyer <scollyer@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/278256
Reviewed-by: Alec Berg <alecaberg@chromium.org>
Diffstat (limited to 'common/usb_pd_tcpc.c')
-rw-r--r-- | common/usb_pd_tcpc.c | 94 |
1 files changed, 63 insertions, 31 deletions
diff --git a/common/usb_pd_tcpc.c b/common/usb_pd_tcpc.c index c9cbf03896..307f7c7c0e 100644 --- a/common/usb_pd_tcpc.c +++ b/common/usb_pd_tcpc.c @@ -187,7 +187,7 @@ static const uint8_t dec4b5b[] = { #define TYPE_C_SRC_3000_THRESHOLD 1230 /* mV */ /* Convert TCPC Alert register to index into pd.alert[] */ -#define ALERT_REG_TO_INDEX(reg) (reg - TCPC_REG_ALERT1) +#define ALERT_REG_TO_INDEX(reg) (reg - TCPC_REG_ALERT) /* PD transmit errors */ enum pd_tx_errors { @@ -209,7 +209,8 @@ static struct pd_port_controller { /* CC status */ uint8_t cc_status[2]; /* TCPC alert status */ - uint8_t alert[2]; + uint16_t alert; + uint16_t alert_mask; /* RX enabled */ uint8_t rx_enabled; @@ -696,10 +697,16 @@ static int cc_voltage_to_status(int port, int cc_volt) return 0; } -static void alert(int port, int reg, int mask) +static void alert(int port, int mask) { - pd[port].alert[ALERT_REG_TO_INDEX(reg)] |= mask; - tcpc_alert(); + /* Always update the Alert status register */ + pd[port].alert |= mask; + /* + * Only send interrupt to TCPM if corresponding + * bit in the alert_enable register is set. + */ + if (pd[port].alert_mask & mask) + tcpc_alert(port); } void tcpc_init(int port) @@ -726,10 +733,9 @@ int tcpc_run(int port, int evt) handle_request(port, pd[port].rx_head, pd[port].rx_payload); - alert(port, TCPC_REG_ALERT1, TCPC_REG_ALERT1_RX_STATUS); + alert(port, TCPC_REG_ALERT_RX_STATUS); } else if (pd[port].rx_head == PD_RX_ERR_HARD_RESET) { - alert(port, TCPC_REG_ALERT1, - TCPC_REG_ALERT1_RX_HARD_RST); + alert(port, TCPC_REG_ALERT_RX_HARD_RST); } } @@ -754,14 +760,11 @@ int tcpc_run(int port, int evt) /* send appropriate alert for tx completion */ if (res >= 0) - alert(port, TCPC_REG_ALERT1, - TCPC_REG_ALERT1_TX_SUCCESS); + alert(port, TCPC_REG_ALERT_TX_SUCCESS); else if (res == PD_TX_ERR_GOODCRC) - alert(port, TCPC_REG_ALERT1, - TCPC_REG_ALERT1_TX_FAILED); + alert(port, TCPC_REG_ALERT_TX_FAILED); else - alert(port, TCPC_REG_ALERT1, - TCPC_REG_ALERT1_TX_DISCARDED); + alert(port, TCPC_REG_ALERT_TX_DISCARDED); } else { /* If we have nothing to transmit, then sample CC lines */ @@ -778,8 +781,7 @@ int tcpc_run(int port, int evt) cc = cc_voltage_to_status(port, cc); if (pd[port].cc_status[i] != cc) { pd[port].cc_status[i] = cc; - alert(port, TCPC_REG_ALERT1, - TCPC_REG_ALERT1_CC_STATUS); + alert(port, TCPC_REG_ALERT_CC_STATUS); } } } @@ -820,17 +822,33 @@ void pd_rx_event(int port) task_set_event(PD_PORT_TO_TASK_ID(port), PD_EVENT_RX, 0); } -int tcpc_alert_status(int port, int alert_reg, uint8_t *alert) +int tcpc_alert_status(int port, uint16_t *alert) { - int ret = pd[port].alert[ALERT_REG_TO_INDEX(alert_reg)]; - - /* TODO: Need to use alert mask to know which bits to let through */ - /* TODO: Alert register is read-clear for now, but shouldn't be */ - pd[port].alert[ALERT_REG_TO_INDEX(alert_reg)] = 0; + /* return the value of the TCPC Alert register */ + uint16_t ret = pd[port].alert; *alert = ret; return EC_SUCCESS; } +int tcpc_alert_status_clear(int port, uint16_t mask) +{ + /* clear only the bits specified by the TCPM */ + pd[port].alert &= ~mask; +#ifndef CONFIG_USB_POWER_DELIVERY + /* Set Alert# inactive if all alert bits clear */ + if (!pd[port].alert) + tcpc_alert_clear(port); +#endif + return EC_SUCCESS; +} + +int tcpc_alert_mask_update(int port, uint16_t mask) +{ + /* Update the alert mask as specificied by the TCPM */ + pd[port].alert_mask = mask; + return EC_SUCCESS; +} + int tcpc_set_cc(int port, int pull) { /* If CC pull resistor not changing, then nothing to do */ @@ -929,6 +947,7 @@ int tcpc_get_message(int port, uint32_t *payload, int *head) #ifndef CONFIG_USB_POWER_DELIVERY static void tcpc_i2c_write(int port, int reg, int len, uint8_t *payload) { + uint16_t alert; switch (reg) { case TCPC_REG_ROLE_CTRL: tcpc_set_cc(port, TCPC_REG_ROLE_CTRL_CC1(payload[1])); @@ -943,9 +962,16 @@ static void tcpc_i2c_write(int port, int reg, int len, uint8_t *payload) TCPC_REG_MSG_HDR_INFO_PROLE(payload[1]), TCPC_REG_MSG_HDR_INFO_DROLE(payload[1])); break; - case TCPC_REG_ALERT1: - case TCPC_REG_ALERT2: - /* TODO: clear alert status reg when writtent to */ + case TCPC_REG_ALERT: + alert = payload[1]; + alert |= (payload[2] << 8); + /* clear alert bits specified by the TCPM */ + tcpc_alert_status_clear(port, alert); + break; + case TCPC_REG_ALERT_MASK: + alert = payload[1]; + alert |= (payload[2] << 8); + tcpc_alert_mask_update(port, alert); break; case TCPC_REG_RX_DETECT: tcpc_set_rx_enable(port, payload[1] & @@ -967,6 +993,7 @@ static void tcpc_i2c_write(int port, int reg, int len, uint8_t *payload) static int tcpc_i2c_read(int port, int reg, uint8_t *payload) { int cc1, cc2; + uint16_t alert; switch (reg) { case TCPC_REG_VENDOR_ID: @@ -995,14 +1022,19 @@ static int tcpc_i2c_read(int port, int reg, uint8_t *payload) payload[0] = TCPC_REG_MSG_HDR_INFO_SET(pd[port].data_role, pd[port].power_role); return 1; - case TCPC_REG_ALERT1: - case TCPC_REG_ALERT2: - tcpc_alert_status(port, reg, payload); - return 1; case TCPC_REG_RX_DETECT: payload[0] = pd[port].rx_enabled ? TCPC_REG_RX_DETECT_SOP_HRST_MASK : 0; return 1; + case TCPC_REG_ALERT: + tcpc_alert_status(port, &alert); + payload[0] = alert & 0xff; + payload[1] = (alert >> 8) & 0xff; + return 2; + case TCPC_REG_ALERT_MASK: + payload[0] = pd[port].alert_mask & 0xff; + payload[1] = (pd[port].alert_mask >> 8) & 0xff; + return 2; case TCPC_REG_RX_BYTE_CNT: payload[0] = 4*PD_HEADER_CNT(pd[port].rx_head); return 1; @@ -1113,11 +1145,11 @@ static int command_tcpc(int argc, char **argv) return EC_SUCCESS; } else if (!strncasecmp(argv[2], "state", 5)) { ccprintf("Port C%d, %s - CC:%d, CC0:%d, CC1:%d, " - "Alert: 0x%02x 0x%02x\n", port, + "Alert: 0x%02x\n", port, pd[port].rx_enabled ? "Ena" : "Dis", pd[port].cc_pull, pd[port].cc_status[0], pd[port].cc_status[1], - pd[port].alert[0], pd[port].alert[1]); + pd[port].alert); } return EC_SUCCESS; |