Beispiel #1
0
/*
 * Prepare controller for a transaction and call omap_i2c_xfer_msg
 * to do the work during IRQ processing.
 */
static int
omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
{
	struct omap_i2c_dev *dev = i2c_get_adapdata(adap);
	int i;
	int r;

	if (dev == NULL)
		return -EINVAL;

	if (dev->shutdown)
		return -EPERM;

	r = omap_i2c_hwspinlock_lock(dev);
	/* To-Do: if we are unable to acquire the lock, we must
	try to recover somehow */
	if (r != 0)
		return r;

	/* We have the bus, enable IRQ */
	omap_i2c_unidle(dev);
	enable_irq(dev->irq);

	r = omap_i2c_wait_for_bb(dev);
	if (r < 0)
		r = omap_i2c_bus_clear(dev);
	if (r < 0)
		goto out;

	/*
	 * When waiting for completion of a i2c transfer, we need to
	 * set a wake up latency constraint for the MPU. This is to
	 * ensure quick enough wakeup from idle, when transfer
	 * completes.
	 */
	if (dev->pm_qos)
		pm_qos_update_request(dev->pm_qos, dev->latency);

	for (i = 0; i < num; i++) {
		r = omap_i2c_xfer_msg(adap, &msgs[i], (i == (num - 1)));
		if (r != 0)
			break;
	}

	if (dev->pm_qos)
		pm_qos_update_request(dev->pm_qos, PM_QOS_DEFAULT_VALUE);

	if (r == 0)
		r = num;

	omap_i2c_wait_for_bb(dev);
out:
	disable_irq(dev->irq);
	omap_i2c_idle(dev);
	omap_i2c_hwspinlock_unlock(dev);

	return r;
}
Beispiel #2
0
/*
 * Prepare controller for a transaction and call omap_i2c_xfer_msg
 * to do the work during IRQ processing.
 */
static int
omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
{
	struct omap_i2c_dev *dev = i2c_get_adapdata(adap);
	int i;
	int r;
#ifdef CONFIG_OMAP4_DPLL_CASCADING
	struct platform_device *pdev;
	struct omap_i2c_bus_platform_data *pdata;
#endif

	if (dev == NULL)
		return -EINVAL;

#ifdef CONFIG_OMAP4_DPLL_CASCADING
	pdev = container_of(dev->dev, struct platform_device, dev);
	pdata = pdev->dev.platform_data;
#endif

	if (dev->shutdown)
		return -EPERM;

	r = omap_i2c_hwspinlock_lock(dev);
	/* To-Do: if we are unable to acquire the lock, we must
	try to recover somehow */
	if (r != 0)
		return r;
        dev->got_lock = true;

	r = omap_i2c_unidle(dev);
	if ((r < 0) && (r != -ETIMEDOUT))
		goto out_unlock;

        /* We have the bus, enable IRQ */
        enable_irq(dev->irq);

	r = omap_i2c_wait_for_bb(dev);
	if (r < 0)
		r = omap_i2c_bus_clear(dev);
	if (r < 0)
		goto out;

	/*
	 * When waiting for completion of a i2c transfer, we need to
	 * set a wake up latency constraint for the MPU. This is to
	 * ensure quick enough wakeup from idle, when transfer
	 * completes.
	 */
	if (dev->pm_qos)
		pm_qos_update_request(dev->pm_qos, dev->latency);

#ifdef CONFIG_OMAP4_DPLL_CASCADING
	spin_lock(&dev->dpll_lock);
	if (dev->dpll_entry == 1) {
		dev->dpll_entry = 0;
		/*
		 * FIXME: Speed > 1000 can not be supported
		 * in DPLL cascading mode.
		 */
		if (dev->speed > 1000) {
			spin_unlock(&dev->dpll_lock);
			return -1;
		}
		omap_i2c_dpll_configure(dev, pdata, OMAP_I2C_DPLL_CLOCK / 1000);

	} else if (dev->dpll_exit == 1) {
		dev->dpll_exit = 0;
		omap_i2c_dpll_configure(dev, pdata, dev->i2c_fclk_rate);
	}
	spin_unlock(&dev->dpll_lock);
#endif
	for (i = 0; i < num; i++) {
		r = omap_i2c_xfer_msg(adap, &msgs[i], (i == (num - 1)));
		if (r != 0)
			break;
	}

	if (dev->pm_qos)
		pm_qos_update_request(dev->pm_qos, PM_QOS_DEFAULT_VALUE);

	if (r == 0)
		r = num;

	omap_i2c_wait_for_bb(dev);
out:
	disable_irq(dev->irq);
	omap_i2c_idle(dev);
out_unlock:
	omap_i2c_hwspinlock_unlock(dev);
	return r;
}
Beispiel #3
0
/*
 * Prepare controller for a transaction and call omap_i2c_xfer_msg
 * to do the work during IRQ processing.
 */
static int
omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
{
	struct omap_i2c_dev *dev = i2c_get_adapdata(adap);
	int i;
	int r;

	/* Sanity check */
	if (!dev) {
		dev_err(&adap->dev, "%s: invalid omap_i2c_dev\n", __func__);
		return -EINVAL;
	}

	if (dev->suspended) {
		WARN(true, "%s: Access denied - device already suspended\n",
		     dev_name(dev->dev));
		return -EACCES;
	}

	r = omap_i2c_hwspinlock_lock(dev);
	/* To-Do: if we are unable to acquire the lock, we must
	try to recover somehow */
	if (r != 0)
		return r;

	r = pm_runtime_get_sync(dev->dev);
	if (r < 0) {
		goto err_pm;
	}

	/* We have the bus, enable IRQ */
	enable_irq(dev->irq);

	r = omap_i2c_wait_for_bb(dev);
	if (r < 0)
		r = omap_i2c_bus_clear(dev);
	if (r < 0)
		goto out;

	/*
	 * When waiting for completion of a i2c transfer, we need to
	 * set a wake up latency constraint for the MPU. This is to
	 * ensure quick enough wakeup from idle, when transfer
	 * completes.
	 */
	if (dev->latency)
		pm_qos_update_request(&dev->pm_qos_request, dev->latency);

	for (i = 0; i < num; i++) {
		r = omap_i2c_xfer_msg(adap, &msgs[i], (i == (num - 1)));
		if (r != 0)
			break;
	}

	if (dev->latency)
		pm_qos_update_request(&dev->pm_qos_request,
				      PM_QOS_DEFAULT_VALUE);

	if (r == 0)
		r = num;

	omap_i2c_wait_for_bb(dev);
out:
	disable_irq(dev->irq);
err_pm:
	pm_runtime_put_sync(dev->dev);
	omap_i2c_hwspinlock_unlock(dev);
	return r;
}