int i2c_dw_resume(struct dw_i2c_dev *dev, bool runtime)
{
	if (!dev->shared_host)
		i2c_dw_init(dev);
	if (!runtime) {
		dev->status |= STATUS_POWERON;
		up(&dev->lock);
	}

	return 0;
}
static ssize_t store_mode(struct device *dev,
			  struct device_attribute *attr,
			  const char *buf, size_t size)
{
	struct dw_i2c_dev *i2c = dev_get_drvdata(dev);
	int ret = 0;
	char mode[MODE_NAME_SIZE];

	if (sscanf(buf, "%9s", mode) != 1) {
		dev_err(dev, "input I2C speed mode: std/fast\n");
		return -EINVAL;
	}

	down(&i2c->lock);
	pm_runtime_get_sync(i2c->dev);

	if (!strncmp("std", mode, MODE_NAME_SIZE)) {
		i2c->master_cfg &= ~DW_IC_SPEED_MASK;
		i2c->master_cfg |= DW_IC_CON_SPEED_STD;
	} else if (!strncmp("fast", mode, MODE_NAME_SIZE)) {
		i2c->fast_plus = 0;
		i2c->master_cfg &= ~DW_IC_SPEED_MASK;
		i2c->master_cfg |= DW_IC_CON_SPEED_FAST;
	} else if (!strncmp("fast+", mode, MODE_NAME_SIZE)) {
		i2c->fast_plus = 1;
		i2c->master_cfg &= ~DW_IC_SPEED_MASK;
		i2c->master_cfg |= DW_IC_CON_SPEED_FAST;
	} else if (!strncmp("high", mode, MODE_NAME_SIZE)) {
		i2c->master_cfg &= ~DW_IC_SPEED_MASK;
		i2c->master_cfg |= DW_IC_CON_SPEED_HIGH;
	} else {
		ret = -EINVAL;
		goto out;
	}

	/* init to configure the i2c master */
	i2c_dw_init(i2c);

	dev_info(dev, "I2C speed mode changed to %s\n", mode);

out:
	pm_runtime_mark_last_busy(i2c->dev);
	pm_runtime_put_autosuspend(i2c->dev);
	up(&i2c->lock);

	return (ret < 0) ? ret : size;
}
示例#3
0
	if (!dev->sda_hold_time && ht) {
		u32 ic_clk = dev->get_clk_rate_khz(dev);

		dev->sda_hold_time = div_u64((u64)ic_clk * ht + 500000,
					     1000000);
	}

	if (!dev->tx_fifo_depth) {
		u32 param1 = i2c_dw_read_comp_param(dev);

		dev->tx_fifo_depth = ((param1 >> 16) & 0xff) + 1;
		dev->rx_fifo_depth = ((param1 >> 8)  & 0xff) + 1;
		dev->adapter.nr = pdev->id;
	}
	r = i2c_dw_init(dev);
	if (r)
		return r;

	i2c_dw_disable_int(dev);
	r = devm_request_irq(&pdev->dev, dev->irq, i2c_dw_isr, IRQF_SHARED,
			pdev->name, dev);
	if (r) {
		dev_err(&pdev->dev, "failure requesting irq %i\n", dev->irq);
		return r;
	}

	adap = &dev->adapter;
	i2c_set_adapdata(adap, dev);
	adap->owner = THIS_MODULE;
	adap->class = I2C_CLASS_DEPRECATED;
/*
 * Prepare controller for a transaction and call i2c_dw_xfer_msg
 */
int
i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
{
	struct dw_i2c_dev *dev = i2c_get_adapdata(adap);
	int ret;

	dev_dbg(dev->dev, "%s: msgs: %d\n", __func__, num);

	mutex_lock(&dev->lock);
	pm_runtime_get_sync(dev->dev);

	INIT_COMPLETION(dev->cmd_complete);
	dev->msgs = msgs;
	dev->msgs_num = num;
	dev->cmd_err = 0;
	dev->msg_write_idx = 0;
	dev->msg_read_idx = 0;
	dev->msg_err = 0;
	dev->status = STATUS_IDLE;
	dev->abort_source = 0;

	ret = i2c_dw_wait_bus_not_busy(dev);
	if (ret < 0)
		goto done;

	/* start the transfers */
	i2c_dw_xfer_init(dev);

	/* wait for tx to complete */
//	ret = wait_for_completion_interruptible_timeout(&dev->cmd_complete, HZ);
	ret = wait_for_completion_timeout(&dev->cmd_complete, HZ);
	if (ret == 0) {
		dev_err(dev->dev, "controller timed out\n");
		i2c_dw_init(dev);
		ret = -ETIMEDOUT;
		goto done;
	} else if (ret < 0)
		goto done;

	if (dev->msg_err) {
		ret = dev->msg_err;
		goto done;
	}

	/* no error */
	if (likely(!dev->cmd_err)) {
		/* Disable the adapter */
		dw_writel(dev, 0, DW_IC_ENABLE);
		ret = num;
		goto done;
	}

	/* We have an error */
	if (dev->cmd_err == DW_IC_ERR_TX_ABRT) {
		ret = i2c_dw_handle_tx_abort(dev);
		goto done;
	}
	ret = -EIO;

done:
	pm_runtime_put(dev->dev);
	mutex_unlock(&dev->lock);

	return ret;
}