static void i2c_init_port(unsigned int port)
{
	const int i2c_clock_bit[] = {21, 22};

	if (!(STM32_RCC_APB1ENR & (1 << i2c_clock_bit[port]))) {
		/* Only unwedge the bus if the clock is off */
		if (i2c_claim(port) == EC_SUCCESS) {
			i2c_release(port);
		}

		/* enable I2C2 clock */
		STM32_RCC_APB1ENR |= 1 << i2c_clock_bit[port];
	}

	/* force reset of the i2c peripheral */
	STM32_I2C_CR1(port) = 0x8000;
	STM32_I2C_CR1(port) = 0x0000;

	/* set clock configuration : standard mode (100kHz) */
	STM32_I2C_CCR(port) = I2C_CCR;

	/* set slave address */
	if (port == I2C2)
		STM32_I2C_OAR1(port) = I2C_ADDRESS;

	/* configuration : I2C mode / Periphal enabled, ACK enabled */
	STM32_I2C_CR1(port) = (1 << 10) | (1 << 0);
	/* error and event interrupts enabled / input clock is 16Mhz */
	STM32_I2C_CR2(port) = (1 << 9) | (1 << 8) | 0x10;

	/* clear status */
	STM32_I2C_SR1(port) = 0;

	board_i2c_post_init(port);
}
Example #2
0
static void i2c_init(void)
{
	const struct i2c_port_t *p = i2c_ports;
	int i;

	for (i = 0; i < i2c_ports_used; i++, p++)
		i2c_init_port(p);

#ifdef CONFIG_HOSTCMD_I2C_SLAVE_ADDR
	STM32_I2C_CR1(I2C_PORT_EC) |= STM32_I2C_CR1_RXIE | STM32_I2C_CR1_ERRIE
			| STM32_I2C_CR1_ADDRIE | STM32_I2C_CR1_STOPIE
			| STM32_I2C_CR1_NACKIE;
#if defined(CONFIG_LOW_POWER_IDLE) && (I2C_PORT_EC == STM32_I2C1_PORT)
	/*
	 * If using low power idle and EC port is I2C1, then set I2C1 to wake
	 * from STOP mode on address match. Note, this only works on I2C1 and
	 * only if the clock to I2C1 is HSI 8MHz.
	 */
	STM32_I2C_CR1(I2C_PORT_EC) |= STM32_I2C_CR1_WUPEN;
#endif
	STM32_I2C_OAR1(I2C_PORT_EC) = 0x8000 | CONFIG_HOSTCMD_I2C_SLAVE_ADDR;
#ifdef TCPCI_I2C_SLAVE
	/*
	 * Configure TCPC address with OA2[1] masked so that we respond
	 * to CONFIG_TCPC_I2C_BASE_ADDR and CONFIG_TCPC_I2C_BASE_ADDR + 2.
	 */
	STM32_I2C_OAR2(I2C_PORT_EC) = 0x8100 | CONFIG_TCPC_I2C_BASE_ADDR;
#endif
	task_enable_irq(IRQ_SLAVE);
#endif
}
static int wait_until_stop_sent(int port)
{
	timestamp_t deadline;
	timestamp_t slow_cutoff;
	uint8_t is_slow;

	deadline = slow_cutoff = get_time();
	deadline.val += TIMEOUT_STOP_SENT_US;
	slow_cutoff.val += SLOW_STOP_SENT_US;

	while (STM32_I2C_CR1(port) & (1 << 9)) {
		if (timestamp_expired(deadline, NULL)) {
			ccprintf("Stop event deadline passed:\ttask=%d"
							"\tCR1=%016b\n",
				(int)task_get_current(), STM32_I2C_CR1(port));
			return EC_ERROR_TIMEOUT;
		}

		if (is_slow) {
			/* If we haven't gotten a fast response, sleep */
			usleep(STOP_SENT_RETRY_US);
		} else {
			/* Check to see if this request is taking a while */
			if (timestamp_expired(slow_cutoff, NULL)) {
				ccprintf("Stop event taking a while: task=%d",
					(int)task_get_current());
				is_slow = 1;
			}
		}
	}

	return EC_SUCCESS;
}
Example #4
0
static void i2c_set_freq_port(const struct i2c_port_t *p)
{
	int port = p->port;

	/* Disable port */
	STM32_I2C_CR1(port) = 0;
	STM32_I2C_CR2(port) = 0;
	/* Set clock frequency */
	switch (p->kbps) {
	case 1000:
		STM32_I2C_TIMINGR(port) = 0x50110103;
		break;
	case 400:
		STM32_I2C_TIMINGR(port) = 0x50330309;
		break;
	case 100:
		STM32_I2C_TIMINGR(port) = 0xB0420F13;
		break;
	default: /* unknown speed, defaults to 100kBps */
		CPRINTS("I2C bad speed %d kBps", p->kbps);
		STM32_I2C_TIMINGR(port) = 0xB0420F13;
	}
	/* Enable port */
	STM32_I2C_CR1(port) = STM32_I2C_CR1_PE;
}
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;
			}
		}
	}
}
Example #6
0
static void i2c_set_freq_port(const struct i2c_port_t *p,
			      enum stm32_i2c_clk_src src,
			      enum i2c_freq freq)
{
	int port = p->port;
	const uint32_t *regs = timingr_regs[src];

	/* Disable port */
	STM32_I2C_CR1(port) = 0;
	STM32_I2C_CR2(port) = 0;
	/* Set clock frequency */
	STM32_I2C_TIMINGR(port) = regs[freq];
	/* Enable port */
	STM32_I2C_CR1(port) = STM32_I2C_CR1_PE;
}
static void i2c_set_freq_port(const struct i2c_port_t *p)
{
	int port = p->port;
	int freq = clock_get_freq();

	/* Force peripheral reset and disable port */
	STM32_I2C_CR1(port) = STM32_I2C_CR1_SWRST;
	STM32_I2C_CR1(port) = 0;

	/* Set clock frequency */
	STM32_I2C_CCR(port) = freq / (2 * MSEC * p->kbps);
	STM32_I2C_CR2(port) = freq / SECOND;
	STM32_I2C_TRISE(port) = freq / SECOND + 1;

	/* Enable port */
	STM32_I2C_CR1(port) |= STM32_I2C_CR1_PE;
}
Example #8
0
static void i2c_send_tcpc_response(int len)
{
	/* host_buffer data range, beyond this length, will return 0xec */
	tx_index = 0;
	tx_end = len;

	/* enable transmit interrupt and use irq to send data back */
	STM32_I2C_CR1(host_i2c_resp_port) |= STM32_I2C_CR1_TXIE;
}
static void dump_i2c_reg(int port, const char *what)
{
	CPRINTS("i2c CR1=%04x CR2=%04x SR1=%04x SR2=%04x %s",
		STM32_I2C_CR1(port),
		STM32_I2C_CR2(port),
		STM32_I2C_SR1(port),
		STM32_I2C_SR2(port),
		what);
}
static int master_start(int port, int slave_addr)
{
	int rv;

	/* Change to master send mode, reset stop bit, send start bit */
	STM32_I2C_CR1(port) = (STM32_I2C_CR1(port) & ~(1 << 9)) | (1 << 8);
	/* Wait for start bit sent event */
	rv = wait_status(port, SR1_SB, WAIT_MASTER_START);
	if (rv)
		return rv;

	/* Send address */
	STM32_I2C_DR(port) = slave_addr;
	/* Wait for addr ready */
	rv = wait_status(port, SR1_ADDR, WAIT_ADDR_READY);
	if (rv)
		return rv;

	read_clear_status(port);

	return EC_SUCCESS;
}
static inline void dump_i2c_reg(int port)
{
#ifdef CONFIG_I2C_DEBUG
	CPRINTF("CR1  : %016b\n", STM32_I2C_CR1(port));
	CPRINTF("CR2  : %016b\n", STM32_I2C_CR2(port));
	CPRINTF("SR2  : %016b\n", STM32_I2C_SR2(port));
	CPRINTF("SR1  : %016b\n", STM32_I2C_SR1(port));
	CPRINTF("OAR1 : %016b\n", STM32_I2C_OAR1(port));
	CPRINTF("OAR2 : %016b\n", STM32_I2C_OAR2(port));
	CPRINTF("DR   : %016b\n", STM32_I2C_DR(port));
	CPRINTF("CCR  : %016b\n", STM32_I2C_CCR(port));
	CPRINTF("TRISE: %016b\n", STM32_I2C_TRISE(port));
#endif /* CONFIG_I2C_DEBUG */
}
/**
 * Send a start condition and slave address on the specified port.
 *
 * @param port		I2C port
 * @param slave_addr	Slave address, with LSB set for receive-mode
 *
 * @return Non-zero if error.
 */
static int send_start(int port, int slave_addr)
{
	int rv;

	/* Send start bit */
	STM32_I2C_CR1(port) |= STM32_I2C_CR1_START;
	dump_i2c_reg(port, "sent start");
	rv = wait_sr1(port, STM32_I2C_SR1_SB);
	if (rv)
		return I2C_ERROR_FAILED_START;

	/* Write slave address */
	STM32_I2C_DR(port) = slave_addr & 0xff;
	rv = wait_sr1(port, STM32_I2C_SR1_ADDR);
	if (rv)
		return rv;

	/* Read SR2 to clear ADDR bit */
	rv = STM32_I2C_SR2(port);

	dump_i2c_reg(port, "wrote addr");

	return EC_SUCCESS;
}
Example #13
0
static void i2c_send_response_packet(struct host_packet *pkt)
{
	int size = pkt->response_size;
	uint8_t *out = host_buffer;

	/* Ignore host command in-progress */
	if (pkt->driver_result == EC_RES_IN_PROGRESS)
		return;

	/* Write result and size to first two bytes. */
	*out++ = pkt->driver_result;
	*out++ = size;

	/* host_buffer data range */
	tx_index = 0;
	tx_end = size + 2;

	/*
	 * Set the transmitter to be in 'not full' state to keep sending
	 * '0xec' in the event loop. Because of this, the master i2c
	 * doesn't need to snoop the response stream to abort transaction.
	 */
	STM32_I2C_CR1(host_i2c_resp_port) |= STM32_I2C_CR1_TXIE;
}
static void master_stop(int port)
{
	STM32_I2C_CR1(port) |= (1 << 9);
}
Example #15
0
int i2c_xfer(int port, int slave_addr, const uint8_t *out, int out_bytes,
	     uint8_t *in, int in_bytes, int flags)
{
	int rv = EC_SUCCESS;
	int i;

	ASSERT(out || !out_bytes);
	ASSERT(in || !in_bytes);

	/* Clear status */
	STM32_I2C_ICR(port) = 0x3F38;
	STM32_I2C_CR2(port) = 0;

	if (out_bytes || !in_bytes) {
		/* Configure the write transfer */
		STM32_I2C_CR2(port) =  ((out_bytes & 0xFF) << 16)
			| slave_addr
			| (in_bytes == 0 ? STM32_I2C_CR2_AUTOEND : 0);
		/* let's go ... */
		STM32_I2C_CR2(port) |= STM32_I2C_CR2_START;

		for (i = 0; i < out_bytes; i++) {
			rv = wait_isr(port, STM32_I2C_ISR_TXIS);
			if (rv)
				goto xfer_exit;
			/* Write next data byte */
			STM32_I2C_TXDR(port) = out[i];
		}
	}
	if (in_bytes) {
		if (out_bytes) { /* wait for completion of the write */
			rv = wait_isr(port, STM32_I2C_ISR_TC);
			if (rv)
				goto xfer_exit;
		}
		/* Configure the read transfer */
		STM32_I2C_CR2(port) = ((in_bytes & 0xFF) << 16)
				    | STM32_I2C_CR2_RD_WRN | slave_addr
				    | STM32_I2C_CR2_AUTOEND;
		/* START or repeated start */
		STM32_I2C_CR2(port) |= STM32_I2C_CR2_START;

		for (i = 0; i < in_bytes; i++) {
			/* Wait for receive buffer not empty */
			rv = wait_isr(port, STM32_I2C_ISR_RXNE);
			if (rv)
				goto xfer_exit;

			in[i] = STM32_I2C_RXDR(port);
		}
	}
	rv = wait_isr(port, STM32_I2C_ISR_STOP);
	if (rv)
		goto xfer_exit;

xfer_exit:
	/* clear status */
	STM32_I2C_ICR(port) = 0x3F38;
	/* On error, queue a stop condition */
	if (rv) {
		/* queue a STOP condition */
		STM32_I2C_CR2(port) |= STM32_I2C_CR2_STOP;
		/* wait for it to take effect */
		/* Wait up to 100 us for bus idle */
		for (i = 0; i < 10; i++) {
			if (!(STM32_I2C_ISR(port) & STM32_I2C_ISR_BUSY))
				break;
			udelay(10);
		}

		/*
		 * Allow bus to idle for at least one 100KHz clock = 10 us.
		 * This allows slaves on the bus to detect bus-idle before
		 * the next start condition.
		 */
		udelay(10);
		/* re-initialize the controller */
		STM32_I2C_CR2(port) = 0;
		STM32_I2C_CR1(port) &= ~STM32_I2C_CR1_PE;
		udelay(10);
		STM32_I2C_CR1(port) |= STM32_I2C_CR1_PE;
	}

	return rv;
}
int i2c_xfer(int port, int slave_addr, const uint8_t *out, int out_bytes,
	     uint8_t *in, int in_bytes, int flags)
{
	int started = (flags & I2C_XFER_START) ? 0 : 1;
	int rv = EC_SUCCESS;
	int i;

	ASSERT(out || !out_bytes);
	ASSERT(in || !in_bytes);

	dump_i2c_reg(port, "xfer start");

	/*
	 * Clear status
	 *
	 * TODO(crosbug.com/p/29314): should check for any leftover error
	 * status, and reset the port if present.
	 */
	STM32_I2C_SR1(port) = 0;

	/* Clear start, stop, POS, ACK bits to get us in a known state */
	STM32_I2C_CR1(port) &= ~(STM32_I2C_CR1_START |
				 STM32_I2C_CR1_STOP |
				 STM32_I2C_CR1_POS |
				 STM32_I2C_CR1_ACK);

	/* No out bytes and no in bytes means just check for active */
	if (out_bytes || !in_bytes) {
		if (!started) {
			rv = send_start(port, slave_addr);
			if (rv)
				goto xfer_exit;
		}

		/* Write data, if any */
		for (i = 0; i < out_bytes; i++) {
			/* Write next data byte */
			STM32_I2C_DR(port) = out[i];
			dump_i2c_reg(port, "wrote data");

			rv = wait_sr1(port, STM32_I2C_SR1_BTF);
			if (rv)
				goto xfer_exit;
		}

		/* Need repeated start condition before reading */
		started = 0;

		/* If no input bytes, queue stop condition */
		if (!in_bytes && (flags & I2C_XFER_STOP))
			STM32_I2C_CR1(port) |= STM32_I2C_CR1_STOP;
	}

	if (in_bytes) {
		/* Setup ACK/POS before sending start as per user manual */
		if (in_bytes == 2)
			STM32_I2C_CR1(port) |= STM32_I2C_CR1_POS;
		else if (in_bytes != 1)
			STM32_I2C_CR1(port) |= STM32_I2C_CR1_ACK;

		if (!started) {
			rv = send_start(port, slave_addr | 0x01);
			if (rv)
				goto xfer_exit;
		}

		if (in_bytes == 1) {
			/* Set stop immediately after ADDR cleared */
			if (flags & I2C_XFER_STOP)
				STM32_I2C_CR1(port) |= STM32_I2C_CR1_STOP;

			rv = wait_sr1(port, STM32_I2C_SR1_RXNE);
			if (rv)
				goto xfer_exit;

			in[0] = STM32_I2C_DR(port);
		} else if (in_bytes == 2) {
			/* Wait till the shift register is full */
			rv = wait_sr1(port, STM32_I2C_SR1_BTF);
			if (rv)
				goto xfer_exit;

			if (flags & I2C_XFER_STOP)
				STM32_I2C_CR1(port) |= STM32_I2C_CR1_STOP;

			in[0] = STM32_I2C_DR(port);
			in[1] = STM32_I2C_DR(port);
		} else {
			/* Read all but last three */
			for (i = 0; i < in_bytes - 3; i++) {
				/* Wait for receive buffer not empty */
				rv = wait_sr1(port, STM32_I2C_SR1_RXNE);
				if (rv)
					goto xfer_exit;

				dump_i2c_reg(port, "read data");
				in[i] = STM32_I2C_DR(port);
				dump_i2c_reg(port, "post read data");
			}

			/* Wait for BTF (data N-2 in DR, N-1 in shift) */
			rv = wait_sr1(port, STM32_I2C_SR1_BTF);
			if (rv)
				goto xfer_exit;

			/* No more acking */
			STM32_I2C_CR1(port) &= ~STM32_I2C_CR1_ACK;
			in[i++] = STM32_I2C_DR(port);

			/* Wait for BTF (data N-1 in DR, N in shift) */
			rv = wait_sr1(port, STM32_I2C_SR1_BTF);
			if (rv)
				goto xfer_exit;

			/* If this is the last byte, queue stop condition */
			if (flags & I2C_XFER_STOP)
				STM32_I2C_CR1(port) |= STM32_I2C_CR1_STOP;

			/* Read the last two bytes */
			in[i++] = STM32_I2C_DR(port);
			in[i++] = STM32_I2C_DR(port);
		}
	}

 xfer_exit:
	/* On error, queue a stop condition */
	if (rv) {
		flags |= I2C_XFER_STOP;
		STM32_I2C_CR1(port) |= STM32_I2C_CR1_STOP;
		dump_i2c_reg(port, "stop after error");

		/*
		 * If failed at sending start, try resetting the port
		 * to unwedge the bus.
		 */
		if (rv == I2C_ERROR_FAILED_START) {
			const struct i2c_port_t *p = i2c_ports;
			CPRINTS("i2c_xfer start error; "
				"unwedging and resetting i2c %d", port);

			i2c_unwedge(port);

			for (i = 0; i < i2c_ports_used; i++, p++) {
				if (p->port == port) {
					i2c_init_port(p);
					break;
				}
			}
		}
	}

	/* If a stop condition is queued, wait for it to take effect */
	if (flags & I2C_XFER_STOP) {
		/* Wait up to 100 us for bus idle */
		for (i = 0; i < 10; i++) {
			if (!(STM32_I2C_SR2(port) & STM32_I2C_SR2_BUSY))
				break;
			udelay(10);
		}

		/*
		 * Allow bus to idle for at least one 100KHz clock = 10 us.
		 * This allows slaves on the bus to detect bus-idle before
		 * the next start condition.
		 */
		udelay(10);
	}

	return rv;
}
Example #17
0
int chip_i2c_xfer(int port, int slave_addr, const uint8_t *out, int out_bytes,
		  uint8_t *in, int in_bytes, int flags)
{
	int rv = EC_SUCCESS;
	int i;
	int xfer_start = flags & I2C_XFER_START;
	int xfer_stop = flags & I2C_XFER_STOP;

#if defined(CONFIG_I2C_SCL_GATE_ADDR) && defined(CONFIG_I2C_SCL_GATE_PORT)
	if (port == CONFIG_I2C_SCL_GATE_PORT &&
	    slave_addr == CONFIG_I2C_SCL_GATE_ADDR)
		gpio_set_level(CONFIG_I2C_SCL_GATE_GPIO, 1);
#endif

	ASSERT(out || !out_bytes);
	ASSERT(in || !in_bytes);

	/* Clear status */
	if (xfer_start) {
		STM32_I2C_ICR(port) = STM32_I2C_ICR_ALL;
		STM32_I2C_CR2(port) = 0;
	}

	if (out_bytes || !in_bytes) {
		/*
		 * Configure the write transfer: if we are stopping then set
		 * AUTOEND bit to automatically set STOP bit after NBYTES.
		 * if we are not stopping, set RELOAD bit so that we can load
		 * NBYTES again. if we are starting, then set START bit.
		 */
		STM32_I2C_CR2(port) =  ((out_bytes & 0xFF) << 16)
			| slave_addr
			| ((in_bytes == 0 && xfer_stop) ?
				STM32_I2C_CR2_AUTOEND : 0)
			| ((in_bytes == 0 && !xfer_stop) ?
				STM32_I2C_CR2_RELOAD : 0)
			| (xfer_start ? STM32_I2C_CR2_START : 0);

		for (i = 0; i < out_bytes; i++) {
			rv = wait_isr(port, STM32_I2C_ISR_TXIS);
			if (rv)
				goto xfer_exit;
			/* Write next data byte */
			STM32_I2C_TXDR(port) = out[i];
		}
	}
	if (in_bytes) {
		if (out_bytes) { /* wait for completion of the write */
			rv = wait_isr(port, STM32_I2C_ISR_TC);
			if (rv)
				goto xfer_exit;
		}
		/*
		 * Configure the read transfer: if we are stopping then set
		 * AUTOEND bit to automatically set STOP bit after NBYTES.
		 * if we are not stopping, set RELOAD bit so that we can load
		 * NBYTES again. if we were just transmitting, we need to
		 * set START bit to send (re)start and begin read transaction.
		 */
		STM32_I2C_CR2(port) = ((in_bytes & 0xFF) << 16)
			| STM32_I2C_CR2_RD_WRN | slave_addr
			| (xfer_stop ? STM32_I2C_CR2_AUTOEND : 0)
			| (!xfer_stop ? STM32_I2C_CR2_RELOAD : 0)
			| (out_bytes || xfer_start ? STM32_I2C_CR2_START : 0);

		for (i = 0; i < in_bytes; i++) {
			/* Wait for receive buffer not empty */
			rv = wait_isr(port, STM32_I2C_ISR_RXNE);
			if (rv)
				goto xfer_exit;

			in[i] = STM32_I2C_RXDR(port);
		}
	}

	/*
	 * If we are stopping, then we already set AUTOEND and we should
	 * wait for the stop bit to be transmitted. Otherwise, we set
	 * the RELOAD bit and we should wait for transfer complete
	 * reload (TCR).
	 */
	rv = wait_isr(port, xfer_stop ? STM32_I2C_ISR_STOP : STM32_I2C_ISR_TCR);
	if (rv)
		goto xfer_exit;

xfer_exit:
	/* clear status */
	if (xfer_stop)
		STM32_I2C_ICR(port) = STM32_I2C_ICR_ALL;

	/* On error, queue a stop condition */
	if (rv) {
		/* queue a STOP condition */
		STM32_I2C_CR2(port) |= STM32_I2C_CR2_STOP;
		/* wait for it to take effect */
		/* Wait up to 100 us for bus idle */
		for (i = 0; i < 10; i++) {
			if (!(STM32_I2C_ISR(port) & STM32_I2C_ISR_BUSY))
				break;
			udelay(10);
		}

		/*
		 * Allow bus to idle for at least one 100KHz clock = 10 us.
		 * This allows slaves on the bus to detect bus-idle before
		 * the next start condition.
		 */
		udelay(10);
		/* re-initialize the controller */
		STM32_I2C_CR2(port) = 0;
		STM32_I2C_CR1(port) &= ~STM32_I2C_CR1_PE;
		udelay(10);
		STM32_I2C_CR1(port) |= STM32_I2C_CR1_PE;
	}

#ifdef CONFIG_I2C_SCL_GATE_ADDR
	if (port == CONFIG_I2C_SCL_GATE_PORT &&
	    slave_addr == CONFIG_I2C_SCL_GATE_ADDR)
		gpio_set_level(CONFIG_I2C_SCL_GATE_GPIO, 0);
#endif

	return rv;
}
Example #18
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;
			}
		}
	}
}
static inline void enable_ack(int port)
{
	STM32_I2C_CR1(port) |= (1 << 10);
}
static inline void disable_ack(int port)
{
	STM32_I2C_CR1(port) &= ~(1 << 10);
}