static int tcpci_tcpm_transmit(int port, enum tcpm_transmit_type type, uint16_t header, const uint32_t *data) { int reg = TCPC_REG_TX_DATA; int rv, cnt = 4*PD_HEADER_CNT(header); /* TX_BYTE_CNT includes 2 bytes for message header */ rv = tcpc_write(port, TCPC_REG_TX_BYTE_CNT, cnt + 2); rv |= tcpc_write16(port, TCPC_REG_TX_HDR, header); /* If tcpc read fails, return error */ if (rv) return rv; if (cnt > 0) { tcpc_lock(port, 1); rv = tcpc_xfer(port, (uint8_t *)®, 1, NULL, 0, I2C_XFER_START); rv |= tcpc_xfer(port, (uint8_t *)data, cnt, NULL, 0, I2C_XFER_STOP); tcpc_lock(port, 0); } /* If tcpc read fails, return error */ if (rv) return rv; rv = tcpc_write(port, TCPC_REG_TRANSMIT, TCPC_REG_TRANSMIT_SET(type)); return rv; }
static int fusb302_tcpm_get_message(int port, uint32_t *payload, int *head) { /* * this is the buffer that will get the burst-read data * from the fusb302. * * it's re-used in a couple different spots, the worst of which * is the PD packet (not header) and CRC. * maximum size necessary = 28 + 4 = 32 */ uint8_t buf[32]; int rv = 0; int len; /* NOTE: Assuming enough memory has been allocated for payload. */ /* * PART 1 OF BURST READ: Write in register address. * Issue a START, no STOP. */ tcpc_lock(port, 1); buf[0] = TCPC_REG_FIFOS; rv |= tcpc_xfer(port, buf, 1, 0, 0, I2C_XFER_START); /* * PART 2 OF BURST READ: Read up to the header. * Issue a repeated START, no STOP. * only grab three bytes so we can get the header * and determine how many more bytes we need to read. */ rv |= tcpc_xfer(port, 0, 0, buf, 3, I2C_XFER_START); /* Grab the header */ *head = (buf[1] & 0xFF); *head |= ((buf[2] << 8) & 0xFF00); /* figure out packet length, subtract header bytes */ len = get_num_bytes(*head) - 2; /* * PART 3 OF BURST READ: Read everything else. * No START, but do issue a STOP at the end. * add 4 to len to read CRC out */ rv |= tcpc_xfer(port, 0, 0, buf, len+4, I2C_XFER_STOP); tcpc_lock(port, 0); /* return the data */ memcpy(payload, buf, len); return rv; }
static int fusb302_send_message(int port, uint16_t header, const uint32_t *data, uint8_t *buf, int buf_pos) { int rv; int reg; int len; len = get_num_bytes(header); /* * packsym tells the TXFIFO that the next X bytes are payload, * and should not be interpreted as special tokens. * The 5 LSBs represent X, the number of bytes. */ reg = FUSB302_TKN_PACKSYM; reg |= (len & 0x1F); buf[buf_pos++] = reg; /* write in the header */ reg = header; buf[buf_pos++] = reg & 0xFF; reg >>= 8; buf[buf_pos++] = reg & 0xFF; /* header is done, subtract from length to make this for-loop simpler */ len -= 2; /* write data objects, if present */ memcpy(&buf[buf_pos], data, len); buf_pos += len; /* put in the CRC */ buf[buf_pos++] = FUSB302_TKN_JAMCRC; /* put in EOP */ buf[buf_pos++] = FUSB302_TKN_EOP; /* Turn transmitter off after sending message */ buf[buf_pos++] = FUSB302_TKN_TXOFF; /* Start transmission */ reg = FUSB302_TKN_TXON; buf[buf_pos++] = FUSB302_TKN_TXON; /* burst write for speed! */ tcpc_lock(port, 1); rv = tcpc_xfer(port, buf, buf_pos, 0, 0, I2C_XFER_SINGLE); tcpc_lock(port, 0); return rv; }
static int tcpci_tcpm_get_message(int port, uint32_t *payload, int *head) { int rv, cnt, reg = TCPC_REG_RX_DATA; rv = tcpc_read(port, TCPC_REG_RX_BYTE_CNT, &cnt); rv |= tcpc_read16(port, TCPC_REG_RX_HDR, (int *)head); if (rv == EC_SUCCESS && cnt > 0) { tcpc_lock(port, 1); rv = tcpc_xfer(port, (uint8_t *)®, 1, (uint8_t *)payload, cnt, I2C_XFER_SINGLE); tcpc_lock(port, 0); } /* Read complete, clear RX status alert bit */ tcpc_write16(port, TCPC_REG_ALERT, TCPC_REG_ALERT_RX_STATUS); return rv; }