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_try_external(struct vlynq_device *dev) { vlynq_reset(dev); if (!vlynq_linked(dev)) return -ENODEV; writel((readl(&dev->remote->control) & ~VLYNQ_CTRL_CLOCK_INT), &dev->remote->control); writel((readl(&dev->local->control) & ~VLYNQ_CTRL_CLOCK_INT), &dev->local->control); if (vlynq_linked(dev)) { printk(KERN_DEBUG "%s: using external clock\n", dev_name(&dev->dev)); dev->divisor = vlynq_div_external; return 0; } 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; }
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; }