static ssize_t reg_store()

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