static int __vlynq_try_local(struct vlynq_device *dev)
{
	int i;

	vlynq_reset(dev);

	for (i = dev->dev_id ? vlynq_ldiv2 : vlynq_ldiv8; dev->dev_id ?
			i <= vlynq_ldiv8 : i >= vlynq_ldiv2;
		dev->dev_id ? i++ : i--) {

		writel((readl(&dev->local->control) &
				~VLYNQ_CTRL_CLOCK_MASK) |
				VLYNQ_CTRL_CLOCK_INT |
				VLYNQ_CTRL_CLOCK_DIV(i - vlynq_ldiv1),
				&dev->local->control);

		if (vlynq_linked(dev)) {
			printk(KERN_DEBUG
				"%s: using local clock divisor %d\n",
				dev_name(&dev->dev), i - vlynq_ldiv1 + 1);
			dev->divisor = i;
			return 0;
		} else {
			vlynq_reset(dev);
		}
	}

	return -ENODEV;
}
static int __vlynq_enable_device(struct vlynq_device *dev)
{
	int result;
	struct plat_vlynq_ops *ops = dev->dev.platform_data;

	result = ops->on(dev);
	if (result)
		return result;

	switch (dev->divisor) {
	case vlynq_div_external:
	case vlynq_div_auto:
		if (vlynq_linked(dev) && readl(&dev->remote->control) &
		   VLYNQ_CTRL_CLOCK_INT) {
			if (!__vlynq_try_remote(dev) ||
				!__vlynq_try_local(dev)  ||
				!__vlynq_try_external(dev))
				return 0;
		} else {
			if (!__vlynq_try_external(dev) ||
				!__vlynq_try_local(dev)    ||
				!__vlynq_try_remote(dev))
				return 0;
		}
		break;
	case vlynq_ldiv1:
	case vlynq_ldiv2:
	case vlynq_ldiv3:
	case vlynq_ldiv4:
	case vlynq_ldiv5:
	case vlynq_ldiv6:
	case vlynq_ldiv7:
	case vlynq_ldiv8:
		writel(VLYNQ_CTRL_CLOCK_INT |
			VLYNQ_CTRL_CLOCK_DIV(dev->divisor -
			vlynq_ldiv1), &dev->local->control);
		writel(0, &dev->remote->control);
		if (vlynq_linked(dev)) {
			printk(KERN_DEBUG
				"%s: using local clock divisor %d\n",
				dev_name(&dev->dev),
				dev->divisor - vlynq_ldiv1 + 1);
			return 0;
		}
		break;
	case vlynq_rdiv1:
	case vlynq_rdiv2:
	case vlynq_rdiv3:
	case vlynq_rdiv4:
	case vlynq_rdiv5:
	case vlynq_rdiv6:
	case vlynq_rdiv7:
	case vlynq_rdiv8:
		writel(0, &dev->local->control);
		writel(VLYNQ_CTRL_CLOCK_INT |
			VLYNQ_CTRL_CLOCK_DIV(dev->divisor -
			vlynq_rdiv1), &dev->remote->control);
		if (vlynq_linked(dev)) {
			printk(KERN_DEBUG
				"%s: using remote clock divisor %d\n",
				dev_name(&dev->dev),
				dev->divisor - vlynq_rdiv1 + 1);
			return 0;
		}
		break;
	}

	ops->off(dev);
	return -ENODEV;
}
Exemple #3
0
static int __vlynq_enable_device(struct vlynq_device *dev)
{
	int result;
	struct plat_vlynq_ops *ops = dev->dev.platform_data;

	result = ops->on(dev);
	if (result)
		return result;

	switch (dev->divisor) {
	case vlynq_div_external:
	case vlynq_div_auto:
		/* When the device is brought from reset it should have clock
		 * generation negotiated by hardware.
		 * Check which device is generating clocks and perform setup
		 * accordingly */
		if (vlynq_linked(dev) && readl(&dev->remote->control) &
		   VLYNQ_CTRL_CLOCK_INT) {
			if (!__vlynq_try_remote(dev) ||
				!__vlynq_try_local(dev)  ||
				!__vlynq_try_external(dev))
				return 0;
		} else {
			if (!__vlynq_try_external(dev) ||
				!__vlynq_try_local(dev)    ||
				!__vlynq_try_remote(dev))
				return 0;
		}
		break;
	case vlynq_ldiv1:
	case vlynq_ldiv2:
	case vlynq_ldiv3:
	case vlynq_ldiv4:
	case vlynq_ldiv5:
	case vlynq_ldiv6:
	case vlynq_ldiv7:
	case vlynq_ldiv8:
		writel(VLYNQ_CTRL_CLOCK_INT |
			VLYNQ_CTRL_CLOCK_DIV(dev->divisor -
			vlynq_ldiv1), &dev->local->control);
		writel(0, &dev->remote->control);
		if (vlynq_linked(dev)) {
			printk(KERN_DEBUG
				"%s: using local clock divisor %d\n",
				dev_name(&dev->dev),
				dev->divisor - vlynq_ldiv1 + 1);
			return 0;
		}
		break;
	case vlynq_rdiv1:
	case vlynq_rdiv2:
	case vlynq_rdiv3:
	case vlynq_rdiv4:
	case vlynq_rdiv5:
	case vlynq_rdiv6:
	case vlynq_rdiv7:
	case vlynq_rdiv8:
		writel(0, &dev->local->control);
		writel(VLYNQ_CTRL_CLOCK_INT |
			VLYNQ_CTRL_CLOCK_DIV(dev->divisor -
			vlynq_rdiv1), &dev->remote->control);
		if (vlynq_linked(dev)) {
			printk(KERN_DEBUG
				"%s: using remote clock divisor %d\n",
				dev_name(&dev->dev),
				dev->divisor - vlynq_rdiv1 + 1);
			return 0;
		}
		break;
	}

	ops->off(dev);
	return -ENODEV;
}