static int ca91cx42_lm_attach()

in bridges/vme_ca91cx42.c [1404:1449]


static int ca91cx42_lm_attach(struct vme_lm_resource *lm, int monitor,
	void (*callback)(void *), void *data)
{
	u32 lm_ctl, tmp;
	struct ca91cx42_driver *bridge;
	struct device *dev;

	bridge = lm->parent->driver_priv;
	dev = lm->parent->parent;

	mutex_lock(&lm->mtx);

	/* Ensure that the location monitor is configured - need PGM or DATA */
	lm_ctl = ioread32(bridge->base + LM_CTL);
	if ((lm_ctl & (CA91CX42_LM_CTL_PGM | CA91CX42_LM_CTL_DATA)) == 0) {
		mutex_unlock(&lm->mtx);
		dev_err(dev, "Location monitor not properly configured\n");
		return -EINVAL;
	}

	/* Check that a callback isn't already attached */
	if (bridge->lm_callback[monitor]) {
		mutex_unlock(&lm->mtx);
		dev_err(dev, "Existing callback attached\n");
		return -EBUSY;
	}

	/* Attach callback */
	bridge->lm_callback[monitor] = callback;
	bridge->lm_data[monitor] = data;

	/* Enable Location Monitor interrupt */
	tmp = ioread32(bridge->base + LINT_EN);
	tmp |= CA91CX42_LINT_LM[monitor];
	iowrite32(tmp, bridge->base + LINT_EN);

	/* Ensure that global Location Monitor Enable set */
	if ((lm_ctl & CA91CX42_LM_CTL_EN) == 0) {
		lm_ctl |= CA91CX42_LM_CTL_EN;
		iowrite32(lm_ctl, bridge->base + LM_CTL);
	}

	mutex_unlock(&lm->mtx);

	return 0;
}