FreeBSD/sys/arm/ti/ti_i2c.c
/**
 *	ti_i2c_transfer - called to perform the transfer
 *	@dev: i2c device handle
 *	@msgs: the messages to send/receive
 *	@nmsgs: the number of messages in the msgs array
 *
 *
 *	LOCKING:
 *	Internally locked
 *
 *	RETURNS:
 *	0 on function succeeded
 *	EINVAL if invalid message is passed as an arg
 */
called to perform the transfer
@dev: i2c device handle
@msgs: the messages to send/receive
@nmsgs: the number of messages in the msgs array

Internally locked

0 on function succeeded
EINVAL if invalid message is passed as an arg
called to perform the transfer @dev : i2c device handle @msgs : the messages to send / receive @nmsgs : the number of messages in the msgs array Internally locked 0 on function succeeded EINVAL if invalid message is passed as an arg
static int
ti_i2c_transfer(device_t dev, struct iic_msg *msgs, uint32_t nmsgs)
{
	int err, i, repstart, timeout;
	struct ti_i2c_softc *sc;
	uint16_t reg;
 	sc = device_get_softc(dev);
	TI_I2C_LOCK(sc);
	while (sc->sc_bus_inuse == 1)
		mtx_sleep(sc, &sc->sc_mtx, 0, "i2cbuswait", 0);
	sc->sc_bus_inuse = 1;
	err = 0;
	repstart = 0;
	for (i = 0; i < nmsgs; i++) {
		sc->sc_buffer = &msgs[i];
		sc->sc_buffer_pos = 0;
		sc->sc_error = 0;
		if (sc->sc_buffer == NULL || sc->sc_buffer->buf == NULL ||
		    sc->sc_buffer->len == 0) {
			err = EINVAL;
			break;
		}
		if (repstart == 0) {
			timeout = 0;
			while (ti_i2c_read_2(sc, I2C_REG_STATUS_RAW) & I2C_STAT_BB) {
				if (timeout++ > 100) {
					err = EBUSY;
					goto out;
				}
				DELAY(1000);
			}
			timeout = 0;
		} else
			repstart = 0;
		if (sc->sc_buffer->flags & IIC_M_NOSTOP)
			repstart = 1;
		ti_i2c_write_2(sc, I2C_REG_SA, msgs[i].slave >> 1);
		ti_i2c_write_2(sc, I2C_REG_CNT, sc->sc_buffer->len);
		reg = ti_i2c_read_2(sc, I2C_REG_BUF);
		reg |= I2C_BUF_RXFIFO_CLR | I2C_BUF_TXFIFO_CLR;
		ti_i2c_write_2(sc, I2C_REG_BUF, reg);
		reg = sc->sc_con_reg | I2C_CON_STT;
		if (repstart == 0)
			reg |= I2C_CON_STP;
		if ((sc->sc_buffer->flags & IIC_M_RD) == 0)
			reg |= I2C_CON_TRX;
		ti_i2c_write_2(sc, I2C_REG_CON, reg);
		err = mtx_sleep(sc, &sc->sc_mtx, 0, "i2ciowait", sc->sc_timeout);
		if (err == 0)
			err = sc->sc_error;
		if (err)
			break;
	}
out:
	if (timeout == 0) {
		while (ti_i2c_read_2(sc, I2C_REG_STATUS_RAW) & I2C_STAT_BB) {
			if (timeout++ > 100)
				break;
			DELAY(1000);
		}
	}
	if ((ti_i2c_read_2(sc, I2C_REG_CON) & I2C_CON_MST) == 0)
		ti_i2c_write_2(sc, I2C_REG_CON, sc->sc_con_reg);
	sc->sc_buffer = NULL;
	sc->sc_bus_inuse = 0;
	wakeup(sc);
	TI_I2C_UNLOCK(sc);
	return (err);
}
static int ti_i2c_transfer ( device_t dev , struct iic_msg * msgs , uint32_t nmsgs ) { int err , i , repstart , timeout ; struct ti_i2c_softc * sc ; uint16_t reg ; sc = device_get_softc ( dev ) ; TI_I2C_LOCK ( sc ) ; while ( sc -> sc_bus_inuse == 1 ) mtx_sleep ( sc , & sc -> sc_mtx , 0 , " " , 0 ) ; sc -> sc_bus_inuse = 1 ; err = 0 ; repstart = 0 ; for ( i = 0 ; i < nmsgs ; i ++ ) { sc -> sc_buffer = & msgs [ i ] ; sc -> sc_buffer_pos = 0 ; sc -> sc_error = 0 ; if ( sc -> sc_buffer == NULL || sc -> sc_buffer -> buf == NULL || sc -> sc_buffer -> len == 0 ) { err = EINVAL ; break ; } if ( repstart == 0 ) { timeout = 0 ; while ( ti_i2c_read_2 ( sc , I2C_REG_STATUS_RAW ) & I2C_STAT_BB ) { if ( timeout ++ > 100 ) { err = EBUSY ; goto out ; } DELAY ( 1000 ) ; } timeout = 0 ; } else repstart = 0 ; if ( sc -> sc_buffer -> flags & IIC_M_NOSTOP ) repstart = 1 ; ti_i2c_write_2 ( sc , I2C_REG_SA , msgs [ i ] . slave >> 1 ) ; ti_i2c_write_2 ( sc , I2C_REG_CNT , sc -> sc_buffer -> len ) ; reg = ti_i2c_read_2 ( sc , I2C_REG_BUF ) ; reg |= I2C_BUF_RXFIFO_CLR | I2C_BUF_TXFIFO_CLR ; ti_i2c_write_2 ( sc , I2C_REG_BUF , reg ) ; reg = sc -> sc_con_reg | I2C_CON_STT ; if ( repstart == 0 ) reg |= I2C_CON_STP ; if ( ( sc -> sc_buffer -> flags & IIC_M_RD ) == 0 ) reg |= I2C_CON_TRX ; ti_i2c_write_2 ( sc , I2C_REG_CON , reg ) ; err = mtx_sleep ( sc , & sc -> sc_mtx , 0 , " " , sc -> sc_timeout ) ; if ( err == 0 ) err = sc -> sc_error ; if ( err ) break ; } out : if ( timeout == 0 ) { while ( ti_i2c_read_2 ( sc , I2C_REG_STATUS_RAW ) & I2C_STAT_BB ) { if ( timeout ++ > 100 ) break ; DELAY ( 1000 ) ; } } if ( ( ti_i2c_read_2 ( sc , I2C_REG_CON ) & I2C_CON_MST ) == 0 ) ti_i2c_write_2 ( sc , I2C_REG_CON , sc -> sc_con_reg ) ; sc -> sc_buffer = NULL ; sc -> sc_bus_inuse = 0 ; wakeup ( sc ) ; TI_I2C_UNLOCK ( sc ) ; return ( err ) ; }
ti_i2c_transfer - called to perform the transfer
      @dev: i2c device handle
      @msgs: the messages to send/receive
      @nmsgs: the number of messages in the msgs array
ti_i2c_transfer - called to perform the transfer @dev : i2c device handle @msgs : the messages to send / receive @nmsgs : the number of messages in the msgs array
/* If the controller is busy wait until it is available. */ /* Now we have control over the I2C controller. */ /* Zero byte transfers aren't allowed. */ /* Check if the i2c bus is free. */ /*
			 * On repeated start we send the START condition while
			 * the bus _is_ busy.
			 */ /* Set the slave address. */ /* Write the data length. */ /* Clear the RX and the TX FIFO. */ /* Wait for an event. */ /* Put the controller in master mode again. */ /* Wake up the processes that are waiting for the bus. */