Commit 19b65476 authored by Badhri Jagan Sridharan's avatar Badhri Jagan Sridharan Committed by Greg Kroah-Hartman
Browse files

usb: typec: tcpci: Add support when hidden tx registers are inaccessible



TCPCI spec forbids direct access of TX_BUF_BYTE_x register.
The existing version of tcpci driver assumes that those registers
are directly addressible. Add support for tcpci chips which do
not support direct access to TX_BUF_BYTE_x registers. TX_BUF_BYTE_x
can only be accessed by I2C_WRITE_BYTE_COUNT.

Reviewed-by: default avatarHeikki Krogerus <heikki.krogerus@linux.intel.com>
Signed-off-by: default avatarBadhri Jagan Sridharan <badhri@google.com>
Link: https://lore.kernel.org/r/20200901025927.3596190-3-badhri@google.com


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 492c1dc9
Loading
Loading
Loading
Loading
+35 −11
Original line number Diff line number Diff line
@@ -330,6 +330,31 @@ static int tcpci_pd_transmit(struct tcpc_dev *tcpc,
	int ret;

	cnt = msg ? pd_header_cnt(header) * 4 : 0;
	/**
	 * TCPCI spec forbids direct access of TCPC_TX_DATA.
	 * But, since some of the chipsets offer this capability,
	 * it's fair to support both.
	 */
	if (tcpci->data->TX_BUF_BYTE_x_hidden) {
		u8 buf[TCPC_TRANSMIT_BUFFER_MAX_LEN] = {0,};
		u8 pos = 0;

		/* Payload + header + TCPC_TX_BYTE_CNT */
		buf[pos++] = cnt + 2;

		if (msg)
			memcpy(&buf[pos], &msg->header, sizeof(msg->header));

		pos += sizeof(header);

		if (cnt > 0)
			memcpy(&buf[pos], msg->payload, cnt);

		pos += cnt;
		ret = regmap_raw_write(tcpci->regmap, TCPC_TX_BYTE_CNT, buf, pos);
		if (ret < 0)
			return ret;
	} else {
		ret = regmap_write(tcpci->regmap, TCPC_TX_BYTE_CNT, cnt + 2);
		if (ret < 0)
			return ret;
@@ -339,14 +364,13 @@ static int tcpci_pd_transmit(struct tcpc_dev *tcpc,
			return ret;

		if (cnt > 0) {
		ret = regmap_raw_write(tcpci->regmap, TCPC_TX_DATA,
				       &msg->payload, cnt);
			ret = regmap_raw_write(tcpci->regmap, TCPC_TX_DATA, &msg->payload, cnt);
			if (ret < 0)
				return ret;
		}
	}

	reg = (PD_RETRY_COUNT << TCPC_TRANSMIT_RETRY_SHIFT) |
		(type << TCPC_TRANSMIT_TYPE_SHIFT);
	reg = (PD_RETRY_COUNT << TCPC_TRANSMIT_RETRY_SHIFT) | (type << TCPC_TRANSMIT_TYPE_SHIFT);
	ret = regmap_write(tcpci->regmap, TCPC_TRANSMIT, reg);
	if (ret < 0)
		return ret;
+8 −0
Original line number Diff line number Diff line
@@ -128,9 +128,17 @@
#define TCPC_VBUS_VOLTAGE_ALARM_HI_CFG		0x76
#define TCPC_VBUS_VOLTAGE_ALARM_LO_CFG		0x78

/* I2C_WRITE_BYTE_COUNT + 1 when TX_BUF_BYTE_x is only accessible I2C_WRITE_BYTE_COUNT */
#define TCPC_TRANSMIT_BUFFER_MAX_LEN		31

/*
 * @TX_BUF_BYTE_x_hidden
 *		optional; Set when TX_BUF_BYTE_x can only be accessed through I2C_WRITE_BYTE_COUNT.
 */
struct tcpci;
struct tcpci_data {
	struct regmap *regmap;
	unsigned char TX_BUF_BYTE_x_hidden:1;
	int (*init)(struct tcpci *tcpci, struct tcpci_data *data);
	int (*set_vconn)(struct tcpci *tcpci, struct tcpci_data *data,
			 bool enable);