Exemple #1
0
static int anx74xx_init_analog(int port)
{
	int reg, rv = EC_SUCCESS;

	/* Analog settings for chip */
	rv |= tcpc_write(port, ANX74XX_REG_HPD_CONTROL,
			 ANX74XX_REG_HPD_OP_MODE);
	rv |= tcpc_write(port, ANX74XX_REG_HPD_CTRL_0,
			 ANX74XX_REG_HPD_DEFAULT);
	if (rv)
		return rv;
	rv = tcpc_read(port, ANX74XX_REG_GPIO_CTRL_4_5, &reg);
	if (rv)
		return rv;
	reg &= ANX74XX_REG_VBUS_GPIO_MODE;
	reg |= ANX74XX_REG_VBUS_OP_ENABLE;
	rv = tcpc_write(port, ANX74XX_REG_GPIO_CTRL_4_5, reg);
	if (rv)
		return rv;
	rv = tcpc_read(port, ANX74XX_REG_CC_SOFTWARE_CTRL, &reg);
	if (rv)
		return rv;
	reg |= ANX74XX_REG_TX_MODE_ENABLE;
	rv = tcpc_write(port, ANX74XX_REG_CC_SOFTWARE_CTRL, reg);

	return rv;
}
Exemple #2
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;
}
Exemple #3
0
static int fusb302_tcpm_transmit(int port, enum tcpm_transmit_type type,
				 uint16_t header, const uint32_t *data)
{
	/*
	 * this is the buffer that will be burst-written into the fusb302
	 * maximum size necessary =
	 * 1: FIFO register address
	 * 4: SOP* tokens
	 * 1: Token that signifies "next X bytes are not tokens"
	 * 30: 2 for header and up to 7*4 = 28 for rest of message
	 * 1: "Insert CRC" Token
	 * 1: EOP Token
	 * 1: "Turn transmitter off" token
	 * 1: "Star Transmission" Command
	 * -
	 * 40: 40 bytes worst-case
	 */
	uint8_t buf[40];
	int buf_pos = 0;

	int reg;

	/* Flush the TXFIFO */
	fusb302_flush_tx_fifo(port);

	switch (type) {
	case TCPC_TX_SOP:

		/* put register address first for of burst tcpc write */
		buf[buf_pos++] = TCPC_REG_FIFOS;

		/* Write the SOP Ordered Set into TX FIFO */
		buf[buf_pos++] = FUSB302_TKN_SYNC1;
		buf[buf_pos++] = FUSB302_TKN_SYNC1;
		buf[buf_pos++] = FUSB302_TKN_SYNC1;
		buf[buf_pos++] = FUSB302_TKN_SYNC2;

		return fusb302_send_message(port, header, data, buf, buf_pos);
	case TCPC_TX_HARD_RESET:
		state[port].tx_hard_reset_req = 1;

		/* Simply hit the SEND_HARD_RESET bit */
		tcpc_read(port, TCPC_REG_CONTROL3, &reg);
		reg |= TCPC_REG_CONTROL3_SEND_HARDRESET;
		tcpc_write(port, TCPC_REG_CONTROL3, reg);

		break;
	case TCPC_TX_BIST_MODE_2:
		/* Simply hit the BIST_MODE2 bit */
		tcpc_read(port, TCPC_REG_CONTROL1, &reg);
		reg |= TCPC_REG_CONTROL1_BIST_MODE2;
		tcpc_write(port, TCPC_REG_CONTROL1, reg);
		break;
	default:
		return EC_ERROR_UNIMPLEMENTED;
	}

	return 0;
}
Exemple #4
0
static int measure_cc_pin_source(int port, int cc_measure)
{
	int switches0_reg;
	int reg;
	int cc_lvl;

	/* Read status register */
	tcpc_read(port, TCPC_REG_SWITCHES0, &reg);
	/* Save current value */
	switches0_reg = reg;
	/* Clear pull-up register settings and measure bits */
	reg &= ~(TCPC_REG_SWITCHES0_MEAS_CC1 | TCPC_REG_SWITCHES0_MEAS_CC2);
	/* Set desired pullup register bit */
	if (cc_measure == TCPC_REG_SWITCHES0_MEAS_CC1)
		reg |= TCPC_REG_SWITCHES0_CC1_PU_EN;
	else
		reg |= TCPC_REG_SWITCHES0_CC2_PU_EN;
	/* Set CC measure bit */
	reg |= cc_measure;

	/* Set measurement switch */
	tcpc_write(port, TCPC_REG_SWITCHES0, reg);

	/* Set MDAC for Open vs Rd/Ra comparison */
	tcpc_write(port, TCPC_REG_MEASURE, state[port].mdac_vnc);

	/* Wait on measurement */
	usleep(250);

	/* Read status register */
	tcpc_read(port, TCPC_REG_STATUS0, &reg);

	/* Assume open */
	cc_lvl = TYPEC_CC_VOLT_OPEN;

	/* CC level is below the 'no connect' threshold (vOpen) */
	if ((reg & TCPC_REG_STATUS0_COMP) == 0) {
		/* Set MDAC for Rd vs Ra comparison */
		tcpc_write(port, TCPC_REG_MEASURE, state[port].mdac_rd);

		/* Wait on measurement */
		usleep(250);

		/* Read status register */
		tcpc_read(port, TCPC_REG_STATUS0, &reg);

		cc_lvl = (reg & TCPC_REG_STATUS0_COMP) ? TYPEC_CC_VOLT_RD
						       : TYPEC_CC_VOLT_RA;
	}

	/* Restore SWITCHES0 register to its value prior */
	tcpc_write(port, TCPC_REG_SWITCHES0, switches0_reg);

	return cc_lvl;
}
Exemple #5
0
static int fusb302_tcpm_set_polarity(int port, int polarity)
{
	/* Port polarity : 0 => CC1 is CC line, 1 => CC2 is CC line */
	int reg;

	tcpc_read(port, TCPC_REG_SWITCHES0, &reg);

	/* clear VCONN switch bits */
	reg &= ~TCPC_REG_SWITCHES0_VCONN_CC1;
	reg &= ~TCPC_REG_SWITCHES0_VCONN_CC2;

	if (state[port].vconn_enabled) {
		/* set VCONN switch to be non-CC line */
		if (polarity)
			reg |= TCPC_REG_SWITCHES0_VCONN_CC1;
		else
			reg |= TCPC_REG_SWITCHES0_VCONN_CC2;
	}

	/* clear meas_cc bits (RX line select) */
	reg &= ~TCPC_REG_SWITCHES0_MEAS_CC1;
	reg &= ~TCPC_REG_SWITCHES0_MEAS_CC2;

	/* set rx polarity */
	if (polarity)
		reg |= TCPC_REG_SWITCHES0_MEAS_CC2;
	else
		reg |= TCPC_REG_SWITCHES0_MEAS_CC1;

	tcpc_write(port, TCPC_REG_SWITCHES0, reg);

	tcpc_read(port, TCPC_REG_SWITCHES1, &reg);

	/* clear tx_cc bits */
	reg &= ~TCPC_REG_SWITCHES1_TXCC1_EN;
	reg &= ~TCPC_REG_SWITCHES1_TXCC2_EN;

	/* set tx polarity */
	if (polarity)
		reg |= TCPC_REG_SWITCHES1_TXCC2_EN;
	else
		reg |= TCPC_REG_SWITCHES1_TXCC1_EN;

	tcpc_write(port, TCPC_REG_SWITCHES1, reg);

	/* Save the polarity for later */
	state[port].cc_polarity = polarity;

	return 0;
}
Exemple #6
0
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, &reg);
	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);
}
Exemple #7
0
static int fusb302_tcpm_set_vconn(int port, int enable)
{
	/*
	 * FUSB302 does not have dedicated VCONN Enable switch.
	 * We'll get through this by disabling both of the
	 * VCONN - CC* switches to disable, and enabling the
	 * saved polarity when enabling.
	 * Therefore at startup, tcpm_set_polarity should be called first,
	 * or else live with the default put into tcpm_init.
	 */
	int reg;

	/* save enable state for later use */
	state[port].vconn_enabled = enable;

	if (enable) {
		/* set to saved polarity */
		tcpm_set_polarity(port, state[port].cc_polarity);
	} else {

		tcpc_read(port, TCPC_REG_SWITCHES0, &reg);

		/* clear VCONN switch bits */
		reg &= ~TCPC_REG_SWITCHES0_VCONN_CC1;
		reg &= ~TCPC_REG_SWITCHES0_VCONN_CC2;

		tcpc_write(port, TCPC_REG_SWITCHES0, reg);
	}

	return 0;
}
Exemple #8
0
static int anx74xx_tcpm_mux_exit(int port)
{
	int  rv = EC_SUCCESS;

	rv |= tcpc_write(port, ANX74XX_REG_ANALOG_CTRL_2,
			 ANX74XX_REG_MODE_TRANS);
	rv |= tcpc_write(port, ANX74XX_REG_ANALOG_CTRL_1,
			 0x0);
	rv |= tcpc_write(port, ANX74XX_REG_ANALOG_CTRL_5,
			 0x04);
	rv |= tcpc_write(port, ANX74XX_REG_ANALOG_CTRL_2,
			 0x0);
	if (rv)
		return EC_ERROR_UNKNOWN;
	return rv;
}
Exemple #9
0
static int anx7688_mux_set(int i2c_addr, mux_state_t mux_state)
{
	int reg = 0;
	int rv, polarity;
	int port = i2c_addr; /* use port index in port_addr field */

	rv = tcpc_read(port, TCPC_REG_CONFIG_STD_OUTPUT, &reg);
	if (rv != EC_SUCCESS)
		return rv;

	reg &= ~TCPC_REG_CONFIG_STD_OUTPUT_MUX_MASK;
	if (mux_state & MUX_USB_ENABLED)
		reg |= TCPC_REG_CONFIG_STD_OUTPUT_MUX_USB;
	if (mux_state & MUX_DP_ENABLED)
		reg |= TCPC_REG_CONFIG_STD_OUTPUT_MUX_DP;

	/* ANX7688 needs to set bit0 */
	rv = tcpc_read(port, TCPC_REG_TCPC_CTRL, &polarity);
	if (rv != EC_SUCCESS)
		return rv;

	/* copy the polarity from TCPC_CTRL[0], take care clear then set */
	reg &= ~TCPC_REG_TCPC_CTRL_POLARITY(1);
	reg |= TCPC_REG_TCPC_CTRL_POLARITY(polarity);
	return tcpc_write(port, TCPC_REG_CONFIG_STD_OUTPUT, reg);
}
Exemple #10
0
static int anx74xx_read_pd_obj(int port,
				uint8_t *buf,
				int plen)
{
	int rv = EC_SUCCESS, i;
	int reg, addr = ANX74XX_REG_PD_RX_DATA_OBJ;

	/* Read PD data objects from ANX */
	for (i = 0; i < plen ; i++) {
		/* Register sequence changes for last two bytes, if
		 * plen is greater than 26
		 */
		if (i == 26)
			addr = ANX74XX_REG_PD_RX_DATA_OBJ_M;
		rv = tcpc_read(port, addr + i, &reg);
		if (rv)
			break;
		buf[i] = reg;
	}

	/* Clear receive message interrupt bit(bit-0) */
	rv |= tcpc_read(port, ANX74XX_REG_IRQ_SOURCE_RECV_MSG, &reg);
	rv |= tcpc_write(port, ANX74XX_REG_IRQ_SOURCE_RECV_MSG,
			 reg & (~0x01));

	return rv;
}
Exemple #11
0
void anx74xx_tcpc_clear_hpd_status(int port)
{
	int reg;

	tcpc_read(port, ANX74XX_REG_HPD_CTRL_0, &reg);
	reg &= 0xcf;
	tcpc_write(port, ANX74XX_REG_HPD_CTRL_0, reg);
}
Exemple #12
0
static void fusb302_flush_tx_fifo(int port)
{
	int reg;

	tcpc_read(port, TCPC_REG_CONTROL0, &reg);
	reg |= TCPC_REG_CONTROL0_TX_FLUSH;
	tcpc_write(port, TCPC_REG_CONTROL0, reg);
}
Exemple #13
0
static void fusb302_flush_rx_fifo(int port)
{
	/*
	 * other bits in the register _should_ be 0
	 * until the day we support other SOP* types...
	 * then we'll have to keep a shadow of what this register
	 * value should be so we don't clobber it here!
	 */
	tcpc_write(port, TCPC_REG_CONTROL1, TCPC_REG_CONTROL1_RX_FLUSH);
}
Exemple #14
0
static int tcpci_tcpm_set_cc(int port, int pull)
{
	/*
	 * Set manual control of Rp/Rd, and set both CC lines to the same
	 * pull.
	 */
	/* TODO: set desired Rp strength */
	return tcpc_write(port, TCPC_REG_ROLE_CTRL,
			  TCPC_REG_ROLE_CTRL_SET(0, 0, pull, pull));
}
Exemple #15
0
void anx74xx_tcpc_update_hpd_status(int port, int hpd_lvl, int hpd_irq)
{
	int reg;

	tcpc_read(port, ANX74XX_REG_HPD_CTRL_0, &reg);
	if (hpd_lvl)
		reg |= ANX74XX_REG_HPD_OUT_DATA;
	else
		reg &= ~ANX74XX_REG_HPD_OUT_DATA;
	tcpc_write(port, ANX74XX_REG_HPD_CTRL_0, reg);

	if (hpd_irq) {
		tcpc_read(port, ANX74XX_REG_HPD_CTRL_0, &reg);
		reg &= ~ANX74XX_REG_HPD_OUT_DATA;
		tcpc_write(port, ANX74XX_REG_HPD_CTRL_0, reg);
		msleep(1);
		reg |= ANX74XX_REG_HPD_OUT_DATA;
		tcpc_write(port, ANX74XX_REG_HPD_CTRL_0, reg);
	}
}
Exemple #16
0
void anx74xx_tcpc_discharge_vbus(int port, int enable)
{
	int reg;

	tcpc_read(port, ANX74XX_REG_HPD_CTRL_0, &reg);
	if (enable)
		reg |= ANX74XX_REG_DISCHARGE_CTRL;
	else
		reg &= ~ANX74XX_REG_DISCHARGE_CTRL;
	tcpc_write(port, ANX74XX_REG_HPD_CTRL_0, reg);
}
Exemple #17
0
void anx74xx_tcpc_set_vbus(int port, int enable)
{
	int reg;

	tcpc_read(port, ANX74XX_REG_GPIO_CTRL_4_5, &reg);
	if (enable)
		reg |= ANX74XX_REG_SET_VBUS;
	else
		reg &= ~ANX74XX_REG_SET_VBUS;
	tcpc_write(port, ANX74XX_REG_GPIO_CTRL_4_5, reg);
}
Exemple #18
0
static int anx74xx_tcpm_set_msg_header(int port, int power_role, int data_role)
{
	int rv = 0, reg;

	rv |= tcpc_read(port, ANX74XX_REG_TX_MSG_HEADER, &reg);
	reg |= ((!!power_role) << ANX74XX_REG_PWR_ROLE_BIT_POS);
	reg |= ((!!data_role) << ANX74XX_REG_DATA_ROLE_BIT_POS);
	rv |= tcpc_write(port, ANX74XX_REG_TX_MSG_HEADER, reg);

	return rv;
}
Exemple #19
0
int anx74xx_tcpm_init(int port)
{
	int rv = 0, reg;

	memset(anx, 0, CONFIG_USB_PD_PORT_COUNT*sizeof(struct anx_state));
	/* Bring chip in normal mode to work */
	anx74xx_set_power_mode(port, ANX74XX_NORMAL_MODE);

	/* Set Pd dual role mode */
	pd_set_dual_role(PD_DRP_TOGGLE_ON);

	/* Initialize analog section of ANX */
	rv |= anx74xx_init_analog(port);

	/* disable all interrupts */
	rv |= tcpc_write(port, ANX74XX_REG_IRQ_EXT_MASK_1,
			 ANX74XX_REG_CLEAR_SET_BITS);

	/* Initialize interrupt polarity */
	rv |= tcpc_write(port, ANX74XX_REG_IRQ_STATUS,
			ANX74XX_INT_ACTIVE_POLARITY);

	/* unmask interrupts */
	rv |= tcpc_read(port, ANX74XX_REG_IRQ_EXT_MASK_1, &reg);
	reg &= (~ANX74XX_REG_ALERT_TX_MSG_ERROR);
	reg &= (~ANX74XX_REG_ALERT_TX_CABLE_RESETOK);
	reg &= (~ANX74XX_REG_ALERT_TX_HARD_RESETOK);
	rv |= tcpc_write(port, ANX74XX_REG_IRQ_EXT_MASK_1, reg);

	rv |= tcpc_read(port, ANX74XX_REG_IRQ_EXT_MASK_2, &reg);
	reg &= (~ANX74XX_REG_EXT_HARD_RST);
	rv |= tcpc_write(port, ANX74XX_REG_IRQ_EXT_MASK_2, reg);

	/*  HPD pin output enable*/
	rv |= tcpc_write(port, ANX74XX_REG_HPD_CTRL_0, ANX74XX_REG_HPD_DEFAULT);

	if (rv)
		return EC_ERROR_UNKNOWN;

	return EC_SUCCESS;
}
Exemple #20
0
static int anx74xx_alert_status(int port, int *alert)
{
	int reg, rv = EC_SUCCESS;

	/* Clear soft irq bit */
	rv |= tcpc_write(port, ANX74XX_REG_IRQ_EXT_SOURCE_3,
			 ANX74XX_REG_CLEAR_SOFT_IRQ);

	/* Read TCPC Alert register1 */
	rv |= tcpc_read(port, ANX74XX_REG_IRQ_EXT_SOURCE_1, &reg);
	if (rv)
		return EC_ERROR_UNKNOWN;

	/* Clears interrupt bits */
	rv |= tcpc_write(port, ANX74XX_REG_IRQ_EXT_SOURCE_1, reg);

	*alert = reg;
	rv = tcpc_read(port, ANX74XX_REG_IRQ_SOURCE_RECV_MSG, &reg);
	if (rv)
		return EC_ERROR_UNKNOWN;

	if (reg & ANX74XX_REG_IRQ_CC_MSG_INT)
		*alert |= ANX74XX_REG_ALERT_MSG_RECV;
	else
		*alert &= (~ANX74XX_REG_ALERT_MSG_RECV);

	if (reg & ANX74XX_REG_IRQ_CC_STATUS_INT) {
		*alert |= ANX74XX_REG_ALERT_CC_CHANGE;
		rv |= tcpc_write(port, ANX74XX_REG_IRQ_SOURCE_RECV_MSG,
				reg & 0xfd);
	} else {
		*alert &= (~ANX74XX_REG_ALERT_CC_CHANGE);
	}

	if (reg & ANX74XX_REG_IRQ_GOOD_CRC_INT) {
		*alert |= ANX74XX_REG_ALERT_TX_ACK_RECV;
		rv |= tcpc_write(port, ANX74XX_REG_IRQ_SOURCE_RECV_MSG,
				reg & 0xfb);
	} else {
		*alert &= (~ANX74XX_REG_ALERT_TX_ACK_RECV);
	}

	if (reg & ANX74XX_REG_IRQ_TX_FAIL_INT) {
		*alert |= ANX74XX_REG_ALERT_TX_MSG_ERROR;
		rv |= tcpc_write(port, ANX74XX_REG_IRQ_SOURCE_RECV_MSG,
				reg & 0xf7);
	}
	/* Read TCPC Alert register2 */
	rv |= tcpc_read(port, ANX74XX_REG_IRQ_EXT_SOURCE_2, &reg);

	/* Clears interrupt bits */
	rv |= tcpc_write(port, ANX74XX_REG_IRQ_EXT_SOURCE_2, reg);

	if (reg & ANX74XX_REG_EXT_HARD_RST)
		*alert |= ANX74XX_REG_ALERT_HARD_RST_RECV;
	else
		*alert &= (~ANX74XX_REG_ALERT_HARD_RST_RECV);

	return rv;
}
Exemple #21
0
static int anx74xx_tcpm_set_cc(int port, int pull)
{
	int rv = EC_SUCCESS;
	int reg;

	/* Enable CC software Control */
	rv |= tcpc_read(port, ANX74XX_REG_CC_SOFTWARE_CTRL, &reg);
	if (rv)
		return EC_ERROR_UNKNOWN;
	reg |= ANX74XX_REG_CC_SW_CTRL_ENABLE;
	rv |= tcpc_write(port, ANX74XX_REG_CC_SOFTWARE_CTRL, reg);
	if (rv)
		return EC_ERROR_UNKNOWN;

	switch (pull) {
	case TYPEC_CC_RP:
	/* Enable Rp */
		rv |= tcpc_read(port, ANX74XX_REG_ANALOG_STATUS, &reg);
		if (rv)
			return EC_ERROR_UNKNOWN;
		reg |= ANX74XX_REG_CC_PULL_RP;
		rv |= tcpc_write(port, ANX74XX_REG_ANALOG_STATUS, reg);
		anx[port].pull = 1;
		break;
	case TYPEC_CC_RD:
	/* Enable Rd */
		rv |= tcpc_read(port, ANX74XX_REG_ANALOG_STATUS, &reg);
		if (rv)
			return EC_ERROR_UNKNOWN;
		reg &= ANX74XX_REG_CC_PULL_RD;
		rv |= tcpc_write(port, ANX74XX_REG_ANALOG_STATUS, reg);
		anx[port].pull = 0;
		break;
	default:
		rv = EC_ERROR_UNKNOWN;
		break;
	}

	return rv;
}
Exemple #22
0
static void fusb302_auto_goodcrc_enable(int port, int enable)
{
	int reg;

	tcpc_read(port,	TCPC_REG_SWITCHES1, &reg);

	if (enable)
		reg |= TCPC_REG_SWITCHES1_AUTO_GCRC;
	else
		reg &= ~TCPC_REG_SWITCHES1_AUTO_GCRC;

	tcpc_write(port, TCPC_REG_SWITCHES1, reg);
}
Exemple #23
0
static void anx74xx_tcpm_set_auto_good_crc(int port, int enable)
{
	int reg;

	if (enable) {
		/* Set default header for Good CRC auto reply */
		tcpc_read(port, ANX74XX_REG_TX_MSG_HEADER, &reg);
		reg |= (PD_REV20 << ANX74XX_REG_SPEC_REV_BIT_POS);
		reg |= ANX74XX_REG_AUTO_GOODCRC_EN;
		tcpc_write(port, ANX74XX_REG_TX_MSG_HEADER, reg);

		reg = ANX74XX_REG_ENABLE_GOODCRC;
		tcpc_write(port, ANX74XX_REG_TX_AUTO_GOODCRC_2, reg);
		/* Set bit-0 if enable, reset bit-0 if disable */
		tcpc_read(port, ANX74XX_REG_TX_AUTO_GOODCRC_1, &reg);
		reg |= ANX74XX_REG_AUTO_GOODCRC_EN;
	} else {
		reg &= ~ANX74XX_REG_AUTO_GOODCRC_EN;
		tcpc_write(port, ANX74XX_REG_TX_AUTO_GOODCRC_2, 0);
	}
	tcpc_write(port, ANX74XX_REG_TX_AUTO_GOODCRC_1, reg);
}
Exemple #24
0
static int anx74xx_tcpm_mux_set(int i2c_addr, mux_state_t mux_state)
{
	int reg = 0, val = 0;
	int rv;
	int port = i2c_addr;

	rv = tcpc_read(port, ANX74XX_REG_ANALOG_CTRL_5, &reg);
	if (rv)
		return EC_ERROR_UNKNOWN;
	reg &= 0x0f;

	if (mux_state & MUX_USB_ENABLED) {
		/* Set pin assignment D */
		if (mux_state & MUX_POLARITY_INVERTED) {
			val = ANX74XX_REG_MUX_DP_MODE_BDF_CC2;
			reg |= ANX74XX_REG_MUX_SSTX_B;
		} else {
			val = ANX74XX_REG_MUX_DP_MODE_BDF_CC1;
			reg |= ANX74XX_REG_MUX_SSTX_A;
		}
	} else if (mux_state & MUX_DP_ENABLED) {
		/* Set pin assignment C */
		if (mux_state & MUX_POLARITY_INVERTED) {
			val = ANX74XX_REG_MUX_DP_MODE_ACE_CC2;
			reg |= ANX74XX_REG_MUX_ML2_B;
		} else {
			val = ANX74XX_REG_MUX_DP_MODE_ACE_CC1;
			reg |= ANX74XX_REG_MUX_ML2_A;
		}
	} else {
		return  EC_ERROR_UNIMPLEMENTED;
	 }

	rv = tcpc_write(port, ANX74XX_REG_ANALOG_CTRL_1, val);
	rv |= tcpc_write(port, ANX74XX_REG_ANALOG_CTRL_5, reg);
	anx[port].mux_state = mux_state;

	return rv;
}
Exemple #25
0
static int anx74xx_tcpm_set_rx_enable(int port, int enable)
{
	int reg, rv = 0;

	rv |= tcpc_read(port, ANX74XX_REG_IRQ_SOURCE_RECV_MSG_MASK, &reg);
	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);

	return rv;
}
Exemple #26
0
static int init_power_status_mask(int port)
{
	uint8_t mask;
	int rv;

#ifdef CONFIG_USB_PD_VBUS_DETECT_TCPC
	mask = TCPC_REG_POWER_STATUS_VBUS_PRES;
#else
	mask = 0;
#endif
	rv = tcpc_write(port, TCPC_REG_POWER_STATUS_MASK , mask);

	return rv;
}
Exemple #27
0
static int anx74xx_tcpm_get_message(int port, uint32_t *payload, int *head)
{
	int reg = 0, rv = EC_SUCCESS;
	int len = 0;

	/* Fetch the header */
	rv |= tcpc_read16(port, ANX74XX_REG_PD_HEADER, &reg);
	if (rv) {
		*head = 0;
		/* Clear receive message interrupt bit(bit-0) */
		tcpc_read(port, ANX74XX_REG_IRQ_SOURCE_RECV_MSG, &reg);
		tcpc_write(port, ANX74XX_REG_IRQ_SOURCE_RECV_MSG,
			 reg & (~0x01));

		return EC_ERROR_UNKNOWN;
	}
	*head = reg;
	len = PD_HEADER_CNT(*head) * 4;
	if (!len) {
		/* Clear receive message interrupt bit(bit-0) */
		tcpc_read(port, ANX74XX_REG_IRQ_SOURCE_RECV_MSG, &reg);
		tcpc_write(port, ANX74XX_REG_IRQ_SOURCE_RECV_MSG,
			 reg & (~0x01));
		return EC_SUCCESS;
	}

	/* Receive message : assuming payload have enough
	 * memory allocated
	 */
	rv |= anx74xx_read_pd_obj(port, (uint8_t *)payload, len);
	if (rv) {
		*head = 0;
		return EC_ERROR_UNKNOWN;
	}

	return rv;
}
Exemple #28
0
static int anx74xx_tcpm_transmit(int port, enum tcpm_transmit_type type,
		  uint16_t header,
		  const uint32_t *data)
{
	uint8_t len = 0;
	int ret = 0, reg = 0;

	switch (type) {
	/* ANX is aware of type */
	case TCPC_TX_SOP:
	case TCPC_TX_SOP_PRIME:
	case TCPC_TX_SOP_PRIME_PRIME:
		len = PD_HEADER_CNT(header) * 4 + 2;
		ret = anx74xx_send_message(port, header,
						  data, type, len);
		break;
	case TCPC_TX_HARD_RESET:
	/* Request HARD RESET */
		tcpc_read(port, ANX74XX_REG_TX_CTRL_1, &reg);
		reg |= ANX74XX_REG_TX_HARD_RESET_REQ;
		ret = tcpc_write(port, ANX74XX_REG_TX_CTRL_1, reg);
		break;
	case TCPC_TX_CABLE_RESET:
	/* Request CABLE RESET */
		tcpc_read(port, ANX74XX_REG_TX_CTRL_1, &reg);
		reg |= ANX74XX_REG_TX_CABLE_RESET_REQ;
		ret = tcpc_write(port, ANX74XX_REG_TX_CTRL_1, reg);
		break;
	case TCPC_TX_BIST_MODE_2:
	/* Request BIST MODE 2 */
		reg = ANX74XX_REG_TX_BIST_START
				| ANX74XX_REG_TX_BIXT_FOREVER | (0x02 << 4);
		ret = tcpc_write(port, ANX74XX_REG_TX_BIST_CTRL, reg);
		msleep(1);
		ret = tcpc_write(port, ANX74XX_REG_TX_BIST_CTRL,
					reg | ANX74XX_REG_TX_BIST_ENABLE);
		msleep(30);
		tcpc_read(port, ANX74XX_REG_TX_BIST_CTRL, &reg);
		ret = tcpc_write(port, ANX74XX_REG_TX_BIST_CTRL,
					reg | ANX74XX_REG_TX_BIST_STOP);
		ret = tcpc_write(port, ANX74XX_REG_TX_BIST_CTRL,
					reg & (~ANX74XX_REG_TX_BIST_STOP));
		ret = tcpc_write(port, ANX74XX_REG_TX_BIST_CTRL, 0);
		break;
	default:
		return EC_ERROR_UNIMPLEMENTED;
	}

	return ret;
}
Exemple #29
0
static void anx7688_update_hpd_enable(int port)
{
	int status, reg, rv;

	rv = tcpc_read(port, ANX7688_REG_STATUS, &status);
	rv |= tcpc_read(port, ANX7688_REG_HPD, &reg);
	if (rv)
		return;

	if (!(reg & ANX7688_REG_HPD_ENABLE) ||
	    !(status & ANX7688_REG_STATUS_LINK)) {
		reg &= ~ANX7688_REG_HPD_IRQ;
		tcpc_write(port, ANX7688_REG_HPD,
			   (status & ANX7688_REG_STATUS_LINK)
			   ? reg | ANX7688_REG_HPD_ENABLE
			   : reg & ~ANX7688_REG_HPD_ENABLE);
	}
}
Exemple #30
0
static int anx74xx_set_mux(int port, int polarity)
{
	int reg, rv = EC_SUCCESS;

	rv = tcpc_read(port, ANX74XX_REG_ANALOG_CTRL_2, &reg);
	if (rv)
		return EC_ERROR_UNKNOWN;
	if (polarity) {
		reg |= ANX74XX_REG_AUX_SWAP_SET_CC2;
		reg &= ~ANX74XX_REG_AUX_SWAP_SET_CC1;
	} else {
		reg |= ANX74XX_REG_AUX_SWAP_SET_CC1;
		reg &= ~ANX74XX_REG_AUX_SWAP_SET_CC2;
	}
	rv = tcpc_write(port, ANX74XX_REG_ANALOG_CTRL_2, reg);

	return rv;
}