예제 #1
0
static int anx7688_init(int port)
{
	int rv = 0;
	int mask = 0;

	/*
	 * 7688 POWER_STATUS[6] is not reliable for tcpci_tcpm_init() to poll
	 * due to it is default 0 in HW, and we cannot write TCPC until it is
	 * ready, or something goes wrong. (Issue 52772)
	 * Instead we poll TCPC 0x50:0xe7 bit6 here to make sure bootdone is
	 * ready(50ms). Then PD main flow can process cc debounce in 50ms ~
	 * 100ms to follow cts.
	 */
	while (1) {
		rv = i2c_read8(I2C_PORT_TCPC, ANX7688_USBC_ADDR,
			       ANX7688_REG_RAMCTRL, &mask);

		if (rv == EC_SUCCESS && (mask & ANX7688_REG_RAMCTRL_BOOT_DONE))
			break;
		msleep(10);
	}

	rv = tcpci_tcpm_drv.init(port);
	if (rv)
		return rv;

	rv = tcpc_read16(port, TCPC_REG_ALERT_MASK, &mask);
	if (rv)
		return rv;

	/* enable vendor specific alert */
	mask |= ANX7688_VENDOR_ALERT;
	rv = tcpc_write16(port, TCPC_REG_ALERT_MASK, mask);
	return rv;
}
예제 #2
0
파일: tcpci.c 프로젝트: fishbaoz/chrome-ec
int tcpci_tcpm_init(int port)
{
	int rv;
	int power_status;

	while (1) {
		rv = tcpc_read(port, TCPC_REG_POWER_STATUS, &power_status);
		/*
		 * If read succeeds and the uninitialized bit is clear, then
		 * initalization is complete, clear all alert bits and write
		 * the initial alert mask.
		 */
		if (rv == EC_SUCCESS &&
		    !(power_status & TCPC_REG_POWER_STATUS_UNINIT)) {
			tcpc_write16(port, TCPC_REG_ALERT, 0xffff);
			/* Initialize power_status_mask */
			init_power_status_mask(port);
			/* Update VBUS status */
			tcpc_vbus[port] = power_status &
				TCPC_REG_POWER_STATUS_VBUS_PRES ? 1 : 0;
			return init_alert_mask(port);
		}
		msleep(10);
	}
}
예제 #3
0
파일: tcpci.c 프로젝트: fishbaoz/chrome-ec
void tcpci_tcpc_alert(int port)
{
	int status;

	/* Read the Alert register from the TCPC */
	tcpm_alert_status(port, &status);

	/*
	 * Clear alert status for everything except RX_STATUS, which shouldn't
	 * be cleared until we have successfully retrieved message.
	 */
	if (status & ~TCPC_REG_ALERT_RX_STATUS)
		tcpc_write16(port, TCPC_REG_ALERT,
			     status & ~TCPC_REG_ALERT_RX_STATUS);

	if (status & TCPC_REG_ALERT_CC_STATUS) {
		/* CC status changed, wake task */
		task_set_event(PD_PORT_TO_TASK_ID(port), PD_EVENT_CC, 0);
	}
	if (status & TCPC_REG_ALERT_POWER_STATUS) {
		int reg = 0;

		tcpc_read(port, TCPC_REG_POWER_STATUS_MASK, &reg);

		if (reg == TCPC_REG_POWER_STATUS_MASK_ALL) {
			/*
			 * If power status mask has been reset, then the TCPC
			 * has reset.
			 */
			task_set_event(PD_PORT_TO_TASK_ID(port),
				       PD_EVENT_TCPC_RESET, 0);
		} else {
			/* Read Power Status register */
			tcpci_tcpm_get_power_status(port, &reg);
			/* Update VBUS status */
			tcpc_vbus[port] = reg &
				TCPC_REG_POWER_STATUS_VBUS_PRES ? 1 : 0;
#if defined(CONFIG_USB_PD_VBUS_DETECT_TCPC) && defined(CONFIG_USB_CHARGER)
			/* Update charge manager with new VBUS state */
			usb_charger_vbus_change(port, tcpc_vbus[port]);
			task_wake(PD_PORT_TO_TASK_ID(port));
#endif /* CONFIG_USB_PD_VBUS_DETECT_TCPC && CONFIG_USB_CHARGER */
		}
	}
	if (status & TCPC_REG_ALERT_RX_STATUS) {
		/* message received */
		task_set_event(PD_PORT_TO_TASK_ID(port), PD_EVENT_RX, 0);
	}
	if (status & TCPC_REG_ALERT_RX_HARD_RST) {
		/* hard reset received */
		pd_execute_hard_reset(port);
		task_wake(PD_PORT_TO_TASK_ID(port));
	}
	if (status & TCPC_REG_ALERT_TX_COMPLETE) {
		/* transmit complete */
		pd_transmit_complete(port, status & TCPC_REG_ALERT_TX_SUCCESS ?
					   TCPC_TX_COMPLETE_SUCCESS :
					   TCPC_TX_COMPLETE_FAILED);
	}
}
예제 #4
0
파일: tcpci.c 프로젝트: fishbaoz/chrome-ec
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;
}
예제 #5
0
파일: tcpci.c 프로젝트: fishbaoz/chrome-ec
static int init_alert_mask(int port)
{
	uint16_t mask;
	int rv;

	/*
	 * Create mask of alert events that will cause the TCPC to
	 * signal the TCPM via the Alert# gpio line.
	 */
	mask = TCPC_REG_ALERT_TX_SUCCESS | TCPC_REG_ALERT_TX_FAILED |
		TCPC_REG_ALERT_TX_DISCARDED | TCPC_REG_ALERT_RX_STATUS |
		TCPC_REG_ALERT_RX_HARD_RST | TCPC_REG_ALERT_CC_STATUS
#ifdef CONFIG_USB_PD_VBUS_DETECT_TCPC
		| TCPC_REG_ALERT_POWER_STATUS
#endif
		;
	/* Set the alert mask in TCPC */
	rv = tcpc_write16(port, TCPC_REG_ALERT_MASK, mask);

	return rv;
}
예제 #6
0
파일: tcpci.c 프로젝트: fishbaoz/chrome-ec
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;
}