Logo Search packages:      
Sourcecode: linux-fsl-imx51 version File versions  Download package

static int mxc_i2c_xfer ( struct i2c_adapter *  adap,
struct i2c_msg  msgs[],
int  num 
) [static]

The function is registered in the adapter structure. It is called when an MXC driver wishes to transfer data to a device connected to the I2C device.

Parameters:
adap adapter structure for the MXC i2c device
msgs[] array of messages to be transferred to the device
num number of messages to be transferred to the device
Returns:
The function returns the number of messages transferred, -EREMOTEIO on I2C failure and a 0 if the num argument is less than 0.

Definition at line 422 of file mxc_i2c.c.

References mxc_i2c_device::adap, flags, mxc_i2c_device::low_power, mxc_i2c_device::membase, mxc_i2c_module_dis(), mxc_i2c_module_en(), mxc_i2c_readbytes(), mxc_i2c_repstart(), mxc_i2c_start(), mxc_i2c_stop(), mxc_i2c_wait_for_tc(), mxc_i2c_writebytes(), mxc_i2c_device::transfer_done, and mxc_i2c_device::tx_success.

{
      mxc_i2c_device *dev = (mxc_i2c_device *) (i2c_get_adapdata(adap));
      int i, ret = 0, addr_comp = 0;
      volatile unsigned int sr;
      int retry = 5;

      if (dev->low_power) {
            dev_err(&dev->adap.dev, "I2C Device in low power mode\n");
            return -EREMOTEIO;
      }

      if (num < 1) {
            return 0;
      }

      mxc_i2c_module_en(dev, msgs[0].flags);
      sr = readw(dev->membase + MXC_I2SR);
      /*
       * Check bus state
       */

      while ((sr & MXC_I2SR_IBB) && retry--) {
            udelay(5);
            sr = readw(dev->membase + MXC_I2SR);
      }

      if ((sr & MXC_I2SR_IBB) && retry < 0) {
            mxc_i2c_module_dis(dev);
            dev_err(&dev->adap.dev, "Bus busy\n");
            return -EREMOTEIO;
      }

      //gpio_i2c_active(dev->adap.id);
      dev->transfer_done = false;
      dev->tx_success = false;
      for (i = 0; i < num && ret >= 0; i++) {
            addr_comp = 0;
            /*
             * Send the slave address and transfer direction in the
             * address cycle
             */
            if (i == 0) {
                  /*
                   * Send a start or repeat start signal
                   */
                  if (mxc_i2c_start(dev, &msgs[0]))
                        return -EREMOTEIO;
                  /* Wait for the address cycle to complete */
                  if (mxc_i2c_wait_for_tc(dev, msgs[0].flags)) {
                        mxc_i2c_stop(dev);
                        //gpio_i2c_inactive(dev->adap.id);
                        mxc_i2c_module_dis(dev);
                        return -EREMOTEIO;
                  }
                  addr_comp = 1;
            } else {
                  /*
                   * Generate repeat start only if required i.e the address
                   * changed or the transfer direction changed
                   */
                  if ((msgs[i].addr != msgs[i - 1].addr) ||
                      ((msgs[i].flags & I2C_M_RD) !=
                       (msgs[i - 1].flags & I2C_M_RD))) {
                        mxc_i2c_repstart(dev, &msgs[i]);
                        /* Wait for the address cycle to complete */
                        if (mxc_i2c_wait_for_tc(dev, msgs[i].flags)) {
                              mxc_i2c_stop(dev);
                              //gpio_i2c_inactive(dev->adap.id);
                              mxc_i2c_module_dis(dev);
                              return -EREMOTEIO;
                        }
                        addr_comp = 1;
                  }
            }

            /* Transfer the data */
            if (msgs[i].flags & I2C_M_RD) {
                  /* Read the data */
                  ret = mxc_i2c_readbytes(dev, &msgs[i], (i + 1 == num),
                                    addr_comp);
                  if (ret < 0) {
                        dev_err(&dev->adap.dev, "mxc_i2c_readbytes:"
                              " fail.\n");
                        break;
                  }
            } else {
                  /* Write the data */
                  ret = mxc_i2c_writebytes(dev, &msgs[i], (i + 1 == num));
                  if (ret < 0) {
                        dev_err(&dev->adap.dev, "mxc_i2c_writebytes:"
                              " fail.\n");
                        break;
                  }
            }
      }

      //gpio_i2c_inactive(dev->adap.id);
      mxc_i2c_module_dis(dev);
      /*
       * Decrease by 1 as we do not want Start message to be included in
       * the count
       */
      return (i < 0 ? ret : i);
}


Generated by  Doxygen 1.6.0   Back to index