Пример #1
0
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 *)&reg, 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;
}
Пример #2
0
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;
}
Пример #3
0
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;
}
Пример #4
0
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 *)&reg, 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;
}