예제 #1
0
static int i2c_readbytes(struct i2c_adapter *i2c_adap,
                         const struct i2c_msg *msg, int joined)
{
    struct cx23885_i2c *bus = i2c_adap->algo_data;
    struct cx23885_dev *dev = bus->dev;
    u32 ctrl, cnt;
    int retval;


    if (i2c_debug && !joined)
        dprintk(1, "%s(msg->len=%d)\n", __func__, msg->len);

    /* Deal with i2c probe functions with zero payload */
    if (msg->len == 0) {
        cx_write(bus->reg_addr, msg->addr << 25);
        cx_write(bus->reg_ctrl, bus->i2c_period | (1 << 2) | 1);
        if (!i2c_wait_done(i2c_adap))
            return -EIO;
        if (!i2c_slave_did_ack(i2c_adap))
            return -ENXIO;


        dprintk(1, "%s() returns 0\n", __func__);
        return 0;
    }

    if (i2c_debug) {
        if (joined)
            dprintk(1, " R");
        else
            dprintk(1, " <R %02x", (msg->addr << 1) + 1);
    }

    for (cnt = 0; cnt < msg->len; cnt++) {

        ctrl = bus->i2c_period | (1 << 12) | (1 << 2) | 1;

        if (cnt < msg->len - 1)
            ctrl |= I2C_NOSTOP | I2C_EXTEND;

        cx_write(bus->reg_addr, msg->addr << 25);
        cx_write(bus->reg_ctrl, ctrl);

        if (!i2c_wait_done(i2c_adap))
            goto eio;
        msg->buf[cnt] = cx_read(bus->reg_rdata) & 0xff;
        if (i2c_debug) {
            dprintk(1, " %02x", msg->buf[cnt]);
            if (!(ctrl & I2C_NOSTOP))
                dprintk(1, " >\n");
        }
    }
    return msg->len;

eio:
    retval = -EIO;
    if (i2c_debug)
        pr_err(" ERR: %d\n", retval);
    return retval;
}
예제 #2
0
파일: i2c.c 프로젝트: chch1028/rtems
rtems_status_code stm32f4_i2c_process_message(
  stm32f4_i2c_bus_entry *e,
  stm32f4_i2c_message *msg
)
{
  rtems_status_code sc = RTEMS_SUCCESSFUL;
  rtems_status_code sc_return = RTEMS_SUCCESSFUL;
  volatile stm32f4_i2c *regs = e->regs;
  uint16_t max_7_bit_address = (1 << 7) - 1;
  uint32_t cr1 = regs->cr1;

  if(msg->addr > max_7_bit_address) {
    return RTEMS_NOT_IMPLEMENTED;
  }

  if(msg->len == 0) {
    return RTEMS_INVALID_SIZE;
  }

  sc = rtems_semaphore_obtain(e->mutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
  RTEMS_CHECK_SC(sc, "obtaining mutex");

  e->data = msg->buf;
  e->last = msg->buf + msg->len - 1;
  e->len = msg->len;

  e->addr_with_rw = msg->addr << 1;
  if(msg->read) {
    e->addr_with_rw |= I2C_RW_BIT;
  }
  e->read = msg->read;

  /* Check if no stop is active. */
  if(cr1 & STM32F4_I2C_CR1_STOP) {
    return RTEMS_IO_ERROR;
  }

  /* Start */
  cr1 = regs->cr1;
  if(e->len == 2) {
    cr1 |= STM32F4_I2C_CR1_POS;
  } else {
    cr1 &= ~STM32F4_I2C_CR1_POS;
  }
  cr1 |= STM32F4_I2C_CR1_ACK;
  cr1 |= STM32F4_I2C_CR1_START;
  regs->cr1 = cr1;

  /* Wait for end of message */
  sc = i2c_wait_done(e);

  if(sc != RTEMS_SUCCESSFUL) {
    sc_return = sc;
  }

  sc = rtems_semaphore_release(e->mutex);
  RTEMS_CHECK_SC(sc, "releasing mutex");

  return sc_return;
}
예제 #3
0
/* FIXME: Implement join handling correctly */
static int i2c_readbytes(struct i2c_adapter *i2c_adap,
	const struct i2c_msg *msg, int joined)
{
	struct au0828_dev *dev = i2c_adap->algo_data;
	int i;

	dprintk(4, "%s()\n", __func__);

	au0828_write(dev, AU0828_I2C_MULTIBYTE_MODE_2FF, 0x01);

	/* Set the I2C clock */
	au0828_write(dev, AU0828_I2C_CLK_DIVIDER_202,
		     dev->board.i2c_clk_divider);

	/* Hardware needs 8 bit addresses */
	au0828_write(dev, AU0828_I2C_DEST_ADDR_203, msg->addr << 1);

	dprintk(4, " RECV:\n");

	/* Deal with i2c_scan */
	if (msg->len == 0) {
		au0828_write(dev, AU0828_I2C_TRIGGER_200,
			     AU0828_I2C_TRIGGER_READ);

		if (i2c_wait_read_ack(i2c_adap))
			return -EIO;
		return 0;
	}

	for (i = 0; i < msg->len;) {

		i++;

		if (i < msg->len)
			au0828_write(dev, AU0828_I2C_TRIGGER_200,
				     AU0828_I2C_TRIGGER_READ |
				     AU0828_I2C_TRIGGER_HOLD);
		else
			au0828_write(dev, AU0828_I2C_TRIGGER_200,
				     AU0828_I2C_TRIGGER_READ);

		if (!i2c_wait_read_done(i2c_adap))
			return -EIO;

		msg->buf[i-1] = au0828_read(dev, AU0828_I2C_READ_FIFO_209) &
			0xff;

		dprintk(4, " %02x\n", msg->buf[i-1]);
	}
	if (!i2c_wait_done(i2c_adap))
		return -EIO;

	dprintk(4, "\n");

	return msg->len;
}
예제 #4
0
// Given an i2c_bus and an address, ping the dev at
// the addr and verify that there is a response
int i2c_bus_addr_active(i2c_bus *i2c, short addr)        // i2c_bus_addr_active
{
  // Set new slave address
  BSC_SLAVE_ADDR = addr;
  // Clear current bus status
  BSC_S = CLEAR_STATUS;
  // Only wish to read a single byte
  BSC_DATA_LEN = 1;
  // Initiate read using bus control
  BSC_C = START_READ;
  // Wait for bus to clear
  i2c_wait_done(i2c);
  return !(BSC_S & BSC_S_ERR);
}
예제 #5
0
/* FIXME: Implement join handling correctly */
static int i2c_sendbytes(struct i2c_adapter *i2c_adap,
	const struct i2c_msg *msg, int joined_rlen)
{
	int i, strobe = 0;
	struct au0828_dev *dev = i2c_adap->algo_data;

	dprintk(4, "%s()\n", __func__);

	au0828_write(dev, REG_2FF, 0x01);
	au0828_write(dev, REG_202, 0x07);

	/* Hardware needs 8 bit addresses */
	au0828_write(dev, REG_203, msg->addr << 1);

	dprintk(4, "SEND: %02x\n", msg->addr);

	for (i = 0; i < msg->len;) {

		dprintk(4, " %02x\n", msg->buf[i]);

		au0828_write(dev, REG_205, msg->buf[i]);

		strobe++;
		i++;

		if ((strobe >= 4) || (i >= msg->len)) {

			/* Strobe the byte into the bus */
			if (i < msg->len)
				au0828_write(dev, REG_200, 0x41);
			else
				au0828_write(dev, REG_200, 0x01);

			/* Reset strobe trigger */
			strobe = 0;

			if (!i2c_wait_write_done(i2c_adap))
				return -EIO;

		}

	}
	if (!i2c_wait_done(i2c_adap))
		return -EIO;

	dprintk(4, "\n");

	return msg->len;
}
예제 #6
0
/* FIXME: Implement join handling correctly */
static int i2c_readbytes(struct i2c_adapter *i2c_adap,
	const struct i2c_msg *msg, int joined)
{
	struct au0828_dev *dev = i2c_adap->algo_data;
	int i;

	dprintk(4, "%s()\n", __func__);

	au0828_write(dev, REG_2FF, 0x01);
	au0828_write(dev, REG_202, 0x07);

	/* Hardware needs 8 bit addresses */
	au0828_write(dev, REG_203, msg->addr << 1);

	dprintk(4, " RECV:\n");

	/* Deal with i2c_scan */
	if (msg->len == 0) {
		au0828_write(dev, REG_200, 0x20);
		if (i2c_wait_read_ack(i2c_adap))
			return -EIO;
		return 0;
	}

	for (i = 0; i < msg->len;) {

		i++;

		if (i < msg->len)
			au0828_write(dev, REG_200, 0x60);
		else
			au0828_write(dev, REG_200, 0x20);

		if (!i2c_wait_read_done(i2c_adap))
			return -EIO;

		msg->buf[i-1] = au0828_read(dev, REG_209) & 0xff;

		dprintk(4, " %02x\n", msg->buf[i-1]);
	}
	if (!i2c_wait_done(i2c_adap))
		return -EIO;

	dprintk(4, "\n");

	return msg->len;
}
예제 #7
0
static int i2c_sendbytes(struct i2c_adapter *i2c_adap,
                         const struct i2c_msg *msg, int joined_rlen)
{
    struct cx23885_i2c *bus = i2c_adap->algo_data;
    struct cx23885_dev *dev = bus->dev;
    u32 wdata, addr, ctrl;
    int retval, cnt;

    if (joined_rlen)
        dprintk(1, "%s(msg->wlen=%d, nextmsg->rlen=%d)\n", __func__,
                msg->len, joined_rlen);
    else
        dprintk(1, "%s(msg->len=%d)\n", __func__, msg->len);

    /* Deal with i2c probe functions with zero payload */
    if (msg->len == 0) {
        cx_write(bus->reg_addr, msg->addr << 25);
        cx_write(bus->reg_ctrl, bus->i2c_period | (1 << 2));
        if (!i2c_wait_done(i2c_adap))
            return -EIO;
        if (!i2c_slave_did_ack(i2c_adap))
            return -ENXIO;

        dprintk(1, "%s() returns 0\n", __func__);
        return 0;
    }


    /* dev, reg + first byte */
    addr = (msg->addr << 25) | msg->buf[0];
    wdata = msg->buf[0];
    ctrl = bus->i2c_period | (1 << 12) | (1 << 2);

    if (msg->len > 1)
        ctrl |= I2C_NOSTOP | I2C_EXTEND;
    else if (joined_rlen)
        ctrl |= I2C_NOSTOP;

    cx_write(bus->reg_addr, addr);
    cx_write(bus->reg_wdata, wdata);
    cx_write(bus->reg_ctrl, ctrl);

    if (!i2c_wait_done(i2c_adap))
        goto eio;
    if (i2c_debug) {
        printk(KERN_DEBUG " <W %02x %02x", msg->addr << 1, msg->buf[0]);
        if (!(ctrl & I2C_NOSTOP))
            pr_cont(" >\n");
    }

    for (cnt = 1; cnt < msg->len; cnt++) {
        /* following bytes */
        wdata = msg->buf[cnt];
        ctrl = bus->i2c_period | (1 << 12) | (1 << 2);

        if (cnt < msg->len - 1)
            ctrl |= I2C_NOSTOP | I2C_EXTEND;
        else if (joined_rlen)
            ctrl |= I2C_NOSTOP;

        cx_write(bus->reg_addr, addr);
        cx_write(bus->reg_wdata, wdata);
        cx_write(bus->reg_ctrl, ctrl);

        if (!i2c_wait_done(i2c_adap))
            goto eio;
        if (i2c_debug) {
            pr_cont(" %02x", msg->buf[cnt]);
            if (!(ctrl & I2C_NOSTOP))
                pr_cont(" >\n");
        }
    }
    return msg->len;

eio:
    retval = -EIO;
    if (i2c_debug)
        pr_err(" ERR: %d\n", retval);
    return retval;
}
예제 #8
0
/* FIXME: Implement join handling correctly */
static int i2c_sendbytes(struct i2c_adapter *i2c_adap,
	const struct i2c_msg *msg, int joined_rlen)
{
	int i, strobe = 0;
	struct au0828_dev *dev = i2c_adap->algo_data;

	dprintk(4, "%s()\n", __func__);

	au0828_write(dev, AU0828_I2C_MULTIBYTE_MODE_2FF, 0x01);

	/* Set the I2C clock */
	au0828_write(dev, AU0828_I2C_CLK_DIVIDER_202,
		     dev->board.i2c_clk_divider);

	/* Hardware needs 8 bit addresses */
	au0828_write(dev, AU0828_I2C_DEST_ADDR_203, msg->addr << 1);

	dprintk(4, "SEND: %02x\n", msg->addr);

	/* Deal with i2c_scan */
	if (msg->len == 0) {
		/* The analog tuner detection code makes use of the SMBUS_QUICK
		   message (which involves a zero length i2c write).  To avoid
		   checking the status register when we didn't strobe out any
		   actual bytes to the bus, just do a read check.  This is
		   consistent with how I saw i2c device checking done in the
		   USB trace of the Windows driver */
		au0828_write(dev, AU0828_I2C_TRIGGER_200,
			     AU0828_I2C_TRIGGER_READ);

		if (!i2c_wait_done(i2c_adap))
			return -EIO;

		if (i2c_wait_read_ack(i2c_adap))
			return -EIO;

		return 0;
	}

	for (i = 0; i < msg->len;) {

		dprintk(4, " %02x\n", msg->buf[i]);

		au0828_write(dev, AU0828_I2C_WRITE_FIFO_205, msg->buf[i]);

		strobe++;
		i++;

		if ((strobe >= 4) || (i >= msg->len)) {

			/* Strobe the byte into the bus */
			if (i < msg->len)
				au0828_write(dev, AU0828_I2C_TRIGGER_200,
					     AU0828_I2C_TRIGGER_WRITE |
					     AU0828_I2C_TRIGGER_HOLD);
			else
				au0828_write(dev, AU0828_I2C_TRIGGER_200,
					     AU0828_I2C_TRIGGER_WRITE);

			/* Reset strobe trigger */
			strobe = 0;

			if (!i2c_wait_write_done(i2c_adap))
				return -EIO;

		}

	}
	if (!i2c_wait_done(i2c_adap))
		return -EIO;

	dprintk(4, "\n");

	return msg->len;
}
예제 #9
0
static int i2c_sendbytes(struct i2c_adapter *i2c_adap,
	const struct i2c_msg *msg, int joined_rlen)
{
	int i, strobe = 0;
	struct au0828_dev *dev = i2c_adap->algo_data;

	dprintk(4, "%s()\n", __func__);

	au0828_write(dev, AU0828_I2C_MULTIBYTE_MODE_2FF, 0x01);

	
	au0828_write(dev, AU0828_I2C_CLK_DIVIDER_202,
		     dev->board.i2c_clk_divider);

	
	au0828_write(dev, AU0828_I2C_DEST_ADDR_203, msg->addr << 1);

	dprintk(4, "SEND: %02x\n", msg->addr);

	
	if (msg->len == 0) {
		
		au0828_write(dev, AU0828_I2C_TRIGGER_200,
			     AU0828_I2C_TRIGGER_READ);

		if (!i2c_wait_done(i2c_adap))
			return -EIO;

		if (i2c_wait_read_ack(i2c_adap))
			return -EIO;

		return 0;
	}

	for (i = 0; i < msg->len;) {

		dprintk(4, " %02x\n", msg->buf[i]);

		au0828_write(dev, AU0828_I2C_WRITE_FIFO_205, msg->buf[i]);

		strobe++;
		i++;

		if ((strobe >= 4) || (i >= msg->len)) {

			
			if (i < msg->len)
				au0828_write(dev, AU0828_I2C_TRIGGER_200,
					     AU0828_I2C_TRIGGER_WRITE |
					     AU0828_I2C_TRIGGER_HOLD);
			else
				au0828_write(dev, AU0828_I2C_TRIGGER_200,
					     AU0828_I2C_TRIGGER_WRITE);

			
			strobe = 0;

			if (!i2c_wait_write_done(i2c_adap))
				return -EIO;

		}

	}
	if (!i2c_wait_done(i2c_adap))
		return -EIO;

	dprintk(4, "\n");

	return msg->len;
}