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;
}