static int tsi148_lm_attach()

in bridges/vme_tsi148.c [2037:2088]


static int tsi148_lm_attach(struct vme_lm_resource *lm, int monitor,
	void (*callback)(void *), void *data)
{
	u32 lm_ctl, tmp;
	struct vme_bridge *tsi148_bridge;
	struct tsi148_driver *bridge;

	tsi148_bridge = lm->parent;

	bridge = tsi148_bridge->driver_priv;

	mutex_lock(&lm->mtx);

	/* Ensure that the location monitor is configured - need PGM or DATA */
	lm_ctl = ioread32be(bridge->base + TSI148_LCSR_LMAT);
	if ((lm_ctl & (TSI148_LCSR_LMAT_PGM | TSI148_LCSR_LMAT_DATA)) == 0) {
		mutex_unlock(&lm->mtx);
		dev_err(tsi148_bridge->parent, "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(tsi148_bridge->parent, "Existing callback attached\n");
		return -EBUSY;
	}

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

	/* Enable Location Monitor interrupt */
	tmp = ioread32be(bridge->base + TSI148_LCSR_INTEN);
	tmp |= TSI148_LCSR_INTEN_LMEN[monitor];
	iowrite32be(tmp, bridge->base + TSI148_LCSR_INTEN);

	tmp = ioread32be(bridge->base + TSI148_LCSR_INTEO);
	tmp |= TSI148_LCSR_INTEO_LMEO[monitor];
	iowrite32be(tmp, bridge->base + TSI148_LCSR_INTEO);

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

	mutex_unlock(&lm->mtx);

	return 0;
}