Пример #1
0
static void i2c_event_handler(int port)
{
	/* save and clear status */
	i2c_sr1[port] = STM32_I2C_SR1(port);
	STM32_I2C_SR1(port) = 0;

	/* Confirm that you are not in master mode */
	if (STM32_I2C_SR2(port) & (1 << 0)) {
		CPRINTS("slave ISR triggered in master mode, ignoring");
		return;
	}

	/* transfer matched our slave address */
	if (i2c_sr1[port] & (1 << 1)) {
		/* If it's a receiver slave */
		if (!(STM32_I2C_SR2(port) & (1 << 2))) {
			dma_start_rx(dma_rx_option + port, sizeof(host_buffer),
				     host_buffer);

			STM32_I2C_CR2(port) |= (1 << 11);
			rx_pending = 1;
		}

		/* cleared by reading SR1 followed by reading SR2 */
		STM32_I2C_SR1(port);
		STM32_I2C_SR2(port);
	} else if (i2c_sr1[port] & (1 << 4)) {
		/* If it's a receiver slave */
		if (!(STM32_I2C_SR2(port) & (1 << 2))) {
			/* Disable, and clear the DMA transfer complete flag */
			dma_disable(DMAC_SLAVE_RX);
			dma_clear_isr(DMAC_SLAVE_RX);

			/* Turn off i2c's DMA flag */
			STM32_I2C_CR2(port) &= ~(1 << 11);
		}
		/* clear STOPF bit by reading SR1 and then writing CR1 */
		STM32_I2C_SR1(port);
		STM32_I2C_CR1(port) = STM32_I2C_CR1(port);
	}

	/* TxE event */
	if (i2c_sr1[port] & (1 << 7)) {
		if (port == I2C2) { /* AP is waiting for EC response */
			if (rx_pending) {
				i2c_process_command();
				/* reset host buffer after end of transfer */
				rx_pending = 0;
			} else {
				/* spurious read : return dummy value */
				STM32_I2C_DR(port) = 0xec;
			}
		}
	}
}
Пример #2
0
static void i2c_event_handler(int port)
{
	int i2c_isr;
	static int rx_pending, buf_idx;
#ifdef TCPCI_I2C_SLAVE
	int addr;
#endif

	i2c_isr = STM32_I2C_ISR(port);

	/*
	 * Check for error conditions. Note, arbitration loss and bus error
	 * are the only two errors we can get as a slave allowing clock
	 * stretching and in non-SMBus mode.
	 */
	if (i2c_isr & (STM32_I2C_ISR_ARLO | STM32_I2C_ISR_BERR)) {
		rx_pending = 0;
		tx_pending = 0;

		/* Make sure TXIS interrupt is disabled */
		STM32_I2C_CR1(port) &= ~STM32_I2C_CR1_TXIE;

		/* Clear error status bits */
		STM32_I2C_ICR(port) |= STM32_I2C_ICR_BERRCF |
				STM32_I2C_ICR_ARLOCF;
	}

	/* Transfer matched our slave address */
	if (i2c_isr & STM32_I2C_ISR_ADDR) {
		if (i2c_isr & STM32_I2C_ISR_DIR) {
			/* Transmitter slave */
			/* Clear transmit buffer */
			STM32_I2C_ISR(port) |= STM32_I2C_ISR_TXE;

			/* Enable txis interrupt to start response */
			STM32_I2C_CR1(port) |= STM32_I2C_CR1_TXIE;
		} else {
			/* Receiver slave */
			buf_idx = 0;
			rx_pending = 1;
		}

		/* Clear ADDR bit by writing to ADDRCF bit */
		STM32_I2C_ICR(port) |= STM32_I2C_ICR_ADDRCF;
		/* Inhibit stop mode when addressed until STOPF flag is set */
		disable_sleep(SLEEP_MASK_I2C_SLAVE);
	}

	/* Stop condition on bus */
	if (i2c_isr & STM32_I2C_ISR_STOP) {
#ifdef TCPCI_I2C_SLAVE
		/*
		 * if tcpc is being addressed, and we received a stop
		 * while rx is pending, then this is a write only to
		 * the tcpc.
		 */
		addr = STM32_I2C_ISR_ADDCODE(STM32_I2C_ISR(port));
		if (rx_pending && ADDR_IS_TCPC(addr))
			i2c_process_tcpc_command(0, addr, buf_idx);
#endif
		rx_pending = 0;
		tx_pending = 0;

		/* Make sure TXIS interrupt is disabled */
		STM32_I2C_CR1(port) &= ~STM32_I2C_CR1_TXIE;

		/* Clear STOPF bit by writing to STOPCF bit */
		STM32_I2C_ICR(port) |= STM32_I2C_ICR_STOPCF;

		/* No longer inhibit deep sleep after stop condition */
		enable_sleep(SLEEP_MASK_I2C_SLAVE);
	}

	/* Receiver full event */
	if (i2c_isr & STM32_I2C_ISR_RXNE)
		host_buffer[buf_idx++] = STM32_I2C_RXDR(port);

	/* Master requested STOP or RESTART */
	if (i2c_isr & STM32_I2C_ISR_NACK) {
		/* Make sure TXIS interrupt is disabled */
		STM32_I2C_CR1(port) &= ~STM32_I2C_CR1_TXIE;
		/* Clear NACK */
		STM32_I2C_ICR(port) |= STM32_I2C_ICR_NACKCF;
		/* Resend last byte on RESTART */
		if (port == I2C_PORT_EC && tx_index)
			tx_index--;
	}

	/* Transmitter empty event */
	if (i2c_isr & STM32_I2C_ISR_TXIS) {
		if (port == I2C_PORT_EC) { /* host is waiting for PD response */
			if (tx_pending) {
				if (tx_index < tx_end) {
					STM32_I2C_TXDR(port) =
						host_buffer[tx_index++];
				} else {
					STM32_I2C_TXDR(port) = 0xec;
					/*
					 * Set tx_index = 0 to prevent NACK
					 * handler resending last buffer byte.
					 */
					tx_index = 0;
					tx_end = 0;
					/* No pending data */
					tx_pending = 0;
				}
			} else if (rx_pending) {
				host_i2c_resp_port = port;
				/*
				 * Disable TXIS interrupt, transmission will
				 * be prepared by host command task.
				 */
				STM32_I2C_CR1(port) &= ~STM32_I2C_CR1_TXIE;

#ifdef TCPCI_I2C_SLAVE
				addr = STM32_I2C_ISR_ADDCODE(
					STM32_I2C_ISR(port));
				if (ADDR_IS_TCPC(addr))
					i2c_process_tcpc_command(1, addr,
								 buf_idx);
				else
#endif
					i2c_process_command();

				/* Reset host buffer after end of transfer */
				rx_pending = 0;
				tx_pending = 1;
			} else {
				STM32_I2C_TXDR(port) = 0xec;
			}
		}
	}
}