in uio_fsl_elbc_gpcm.c [100:147]
static ssize_t reg_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct uio_info *info = dev_get_drvdata(dev);
struct fsl_elbc_gpcm *priv = info->priv;
struct fsl_lbc_bank *bank = &priv->lbc->bank[priv->bank];
unsigned long val;
u32 reg_br_cur;
u32 reg_or_cur;
u32 reg_new;
/* parse use input */
if (kstrtoul(buf, 0, &val) != 0)
return -EINVAL;
reg_new = (u32)val;
/* read current values */
reg_br_cur = in_be32(&bank->br);
reg_or_cur = in_be32(&bank->or);
if (attr == &dev_attr_reg_br) {
/* not allowed to change effective base address */
if ((reg_br_cur & reg_or_cur & BR_BA) !=
(reg_new & reg_or_cur & BR_BA)) {
return -EINVAL;
}
/* not allowed to change mode */
if ((reg_new & BR_MSEL) != BR_MS_GPCM)
return -EINVAL;
/* write new value (force valid) */
out_be32(&bank->br, reg_new | BR_V);
} else if (attr == &dev_attr_reg_or) {
/* not allowed to change access mask */
if ((reg_or_cur & OR_GPCM_AM) != (reg_new & OR_GPCM_AM))
return -EINVAL;
/* write new value */
out_be32(&bank->or, reg_new);
} else {
return -EINVAL;
}
return count;
}