コード例 #1
0
ファイル: regcache.c プロジェクト: TheDarkCode/linux
static int regcache_default_sync(struct regmap *map, unsigned int min,
				 unsigned int max)
{
	unsigned int reg;

	for (reg = min; reg <= max; reg += map->reg_stride) {
		unsigned int val;
		int ret;

		if (regmap_volatile(map, reg) ||
		    !regmap_writeable(map, reg))
			continue;

		ret = regcache_read(map, reg, &val);
		if (ret)
			return ret;

		if (!regcache_reg_needs_sync(map, reg, val))
			continue;

		map->cache_bypass = true;
		ret = _regmap_write(map, reg, val);
		map->cache_bypass = false;
		if (ret) {
			dev_err(map->dev, "Unable to sync register %#x. %d\n",
				reg, ret);
			return ret;
		}
		dev_dbg(map->dev, "Synced register %#x, value %#x\n", reg, val);
	}

	return 0;
}
コード例 #2
0
ファイル: regcache.c プロジェクト: FEDEVEL/openrex-linux-3.14
static int regcache_default_sync(struct regmap *map, unsigned int min,
				 unsigned int max)
{
	unsigned int reg;

	for (reg = min; reg <= max; reg++) {
		unsigned int val;
		int ret;

		if (regmap_volatile(map, reg))
			continue;

		ret = regcache_read(map, reg, &val);
		if (ret)
			return ret;

		if (!regcache_reg_needs_sync(map, reg, val))
			continue;

		map->cache_bypass = 1;
		ret = _regmap_write(map, reg, val);
		map->cache_bypass = 0;
		if (ret)
			return ret;
		dev_dbg(map->dev, "Synced register %#x, value %#x\n", reg, val);
	}

	return 0;
}
コード例 #3
0
ファイル: regcache.c プロジェクト: FrozenCow/FIRE-ICE
static int regcache_default_sync(struct regmap *map, unsigned int min,
				 unsigned int max)
{
	unsigned int reg;

	for (reg = min; reg <= max; reg += map->reg_stride) {
		unsigned int val;
		int ret;

		if (regmap_volatile(map, reg) ||
		    !regmap_writeable(map, reg))
			continue;

		ret = regcache_read(map, reg, &val);
		if (ret)
			return ret;

		/* Is this the hardware default?  If so skip. */
		ret = regcache_lookup_reg(map, reg);
		if (ret >= 0 && val == map->reg_defaults[ret].def)
			continue;

		map->cache_bypass = 1;
		ret = _regmap_write(map, reg, val);
		map->cache_bypass = 0;
		if (ret)
			return ret;
		dev_dbg(map->dev, "Synced register %#x, value %#x\n", reg, val);
	}

	return 0;
}
コード例 #4
0
ファイル: regmap.c プロジェクト: faisalomar/linux-3.2.0
/**
 * regmap_bulk_read(): Read multiple registers from the device
 *
 * @map: Register map to write to
 * @reg: First register to be read from
 * @val: Pointer to store read value, in native register size for device
 * @val_count: Number of registers to read
 *
 * A value of zero will be returned on success, a negative errno will
 * be returned in error cases.
 */
int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val,
		     size_t val_count)
{
	int ret, i;
	size_t val_bytes = map->format.val_bytes;
	bool vol = true;

	if (!map->format.parse_val)
		return -EINVAL;

	/* Is this a block of volatile registers? */
	for (i = 0; i < val_count; i++)
		if (!regmap_volatile(map, reg + i))
			vol = false;

	if (vol || map->cache_type == REGCACHE_NONE) {
		ret = regmap_raw_read(map, reg, val, val_bytes * val_count);
		if (ret != 0)
			return ret;

		for (i = 0; i < val_count * val_bytes; i += val_bytes)
			map->format.parse_val(val + i);
	} else {
		for (i = 0; i < val_count; i++) {
			ret = regmap_read(map, reg + i, val + (i * val_bytes));
			if (ret != 0)
				return ret;
		}
	}

	return 0;
}
コード例 #5
0
ファイル: regcache.c プロジェクト: TheDarkCode/linux
/**
 * regcache_write: Set the value of a given register in the cache.
 *
 * @map: map to configure.
 * @reg: The register index.
 * @value: The new register value.
 *
 * Return a negative value on failure, 0 on success.
 */
int regcache_write(struct regmap *map,
		   unsigned int reg, unsigned int value)
{
	if (map->cache_type == REGCACHE_NONE)
		return 0;

	BUG_ON(!map->cache_ops);

	if (!regmap_volatile(map, reg))
		return map->cache_ops->write(map, reg, value);

	return 0;
}
コード例 #6
0
ファイル: regcache.c プロジェクト: 08opt/linux
/**
 * regcache_read: Fetch the value of a given register from the cache.
 *
 * @map: map to configure.
 * @reg: The register index.
 * @value: The value to be returned.
 *
 * Return a negative value on failure, 0 on success.
 */
int regcache_read(struct regmap *map,
		  unsigned int reg, unsigned int *value)
{
	if (map->cache_type == REGCACHE_NONE)
		return -ENOSYS;

	BUG_ON(!map->cache_ops);

	if (!regmap_readable(map, reg))
		return -EIO;

	if (!regmap_volatile(map, reg))
		return map->cache_ops->read(map, reg, value);

	return -EINVAL;
}
コード例 #7
0
ファイル: regcache.c プロジェクト: Alex-V2/Alex-V_SE_OneX
/**
 * regcache_read: Fetch the value of a given register from the cache.
 *
 * @map: map to configure.
 * @reg: The register index.
 * @value: The value to be returned.
 *
 * Return a negative value on failure, 0 on success.
 */
int regcache_read(struct regmap *map,
		  unsigned int reg, unsigned int *value)
{
	int ret;

	if (map->cache_type == REGCACHE_NONE)
		return -ENOSYS;

	BUG_ON(!map->cache_ops);

	if (!regmap_volatile(map, reg)) {
		ret = map->cache_ops->read(map, reg, value);

		if (ret == 0)
			trace_regmap_reg_read_cache(map->dev, reg, *value);

		return ret;
	}

	return -EINVAL;
}
コード例 #8
0
ファイル: regcache.c プロジェクト: FrozenCow/FIRE-ICE
static int _regcache_volatile_set(struct regmap *map, unsigned int reg,
				  bool is_volatile)
{
	int ret;

	if (is_volatile == regmap_volatile(map, reg))
		return 0;

	if (!map->reg_volatile_set)
		return -ENOSYS;

	if (!map->cache_present)
		return -ENOENT;

	ret = map->reg_volatile_set(map->dev, reg, is_volatile);
	if (ret)
		return ret;

	regcache_clear_reg_present(map, reg);
	return 0;
}
コード例 #9
0
ファイル: regmap.c プロジェクト: faisalomar/linux-3.2.0
/**
 * regmap_raw_read(): Read raw data from the device
 *
 * @map: Register map to write to
 * @reg: First register to be read from
 * @val: Pointer to store read value
 * @val_len: Size of data to read
 *
 * A value of zero will be returned on success, a negative errno will
 * be returned in error cases.
 */
int regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
		    size_t val_len)
{
	int ret;
	int i;
	bool vol = true;

	for (i = 0; i < val_len / map->format.val_bytes; i++)
		if (!regmap_volatile(map, reg + i))
			vol = false;

	WARN_ON(!vol && map->cache_type != REGCACHE_NONE);

	mutex_lock(&map->lock);

	ret = _regmap_raw_read(map, reg, val, val_len);

	mutex_unlock(&map->lock);

	return ret;
}
コード例 #10
0
ファイル: regcache.c プロジェクト: Alex-V2/Alex-V_SE_OneX
static int regcache_hw_init(struct regmap *map)
{
	int i, j;
	int ret;
	int count;
	unsigned int val;
	void *tmp_buf;

	if (!map->num_reg_defaults_raw)
		return -EINVAL;

	if (!map->reg_defaults_raw) {
		u32 cache_bypass = map->cache_bypass;
		dev_warn(map->dev, "No cache defaults, reading back from HW\n");

		/* Bypass the cache access till data read from HW*/
		map->cache_bypass = 1;
		tmp_buf = kmalloc(map->cache_size_raw, GFP_KERNEL);
		if (!tmp_buf)
			return -EINVAL;
		ret = regmap_bulk_read(map, 0, tmp_buf,
				       map->num_reg_defaults_raw);
		map->cache_bypass = cache_bypass;
		if (ret < 0) {
			kfree(tmp_buf);
			return ret;
		}
		map->reg_defaults_raw = tmp_buf;
		map->cache_free = 1;
	}

	/* calculate the size of reg_defaults */
	for (count = 0, i = 0; i < map->num_reg_defaults_raw; i++) {
		val = regcache_get_val(map->reg_defaults_raw,
				       i, map->cache_word_size);
		if (regmap_volatile(map, i * map->reg_stride))
			continue;
		count++;
	}

	map->reg_defaults = kmalloc(count * sizeof(struct reg_default),
				      GFP_KERNEL);
	if (!map->reg_defaults) {
		ret = -ENOMEM;
		goto err_free;
	}

	/* fill the reg_defaults */
	map->num_reg_defaults = count;
	for (i = 0, j = 0; i < map->num_reg_defaults_raw; i++) {
		val = regcache_get_val(map->reg_defaults_raw,
				       i, map->cache_word_size);
		if (regmap_volatile(map, i * map->reg_stride))
			continue;
		map->reg_defaults[j].reg = i * map->reg_stride;
		map->reg_defaults[j].def = val;
		j++;
	}

	return 0;

err_free:
	if (map->cache_free)
		kfree(map->reg_defaults_raw);

	return ret;
}
コード例 #11
0
ファイル: regmap-debugfs.c プロジェクト: michaelkrebs/linux
static ssize_t regmap_access_read_file(struct file *file,
				       char __user *user_buf, size_t count,
				       loff_t *ppos)
{
	int reg_len, tot_len;
	size_t buf_pos = 0;
	loff_t p = 0;
	ssize_t ret;
	int i;
	struct regmap *map = file->private_data;
	char *buf;

	if (*ppos < 0 || !count)
		return -EINVAL;

	buf = kmalloc(count, GFP_KERNEL);
	if (!buf)
		return -ENOMEM;

	/* Calculate the length of a fixed format  */
	reg_len = regmap_calc_reg_len(map->max_register, buf, count);
	tot_len = reg_len + 10; /* ': R W V P\n' */

	for (i = 0; i < map->max_register + 1; i++) {
		/* Ignore registers which are neither readable nor writable */
		if (!regmap_readable(map, i) && !regmap_writeable(map, i))
			continue;

		/* If we're in the region the user is trying to read */
		if (p >= *ppos) {
			/* ...but not beyond it */
			if (buf_pos >= count - 1 - tot_len)
				break;

			/* Format the register */
			snprintf(buf + buf_pos, count - buf_pos,
				 "%.*x: %c %c %c %c\n",
				 reg_len, i,
				 regmap_readable(map, i) ? 'y' : 'n',
				 regmap_writeable(map, i) ? 'y' : 'n',
				 regmap_volatile(map, i) ? 'y' : 'n',
				 regmap_precious(map, i) ? 'y' : 'n');

			buf_pos += tot_len;
		}
		p += tot_len;
	}

	ret = buf_pos;

	if (copy_to_user(user_buf, buf, buf_pos)) {
		ret = -EFAULT;
		goto out;
	}

	*ppos += buf_pos;

out:
	kfree(buf);
	return ret;
}
コード例 #12
0
static ssize_t regmap_access_read_file(struct file *file,
				       char __user *user_buf, size_t count,
				       loff_t *ppos)
{
	int reg_len, tot_len;
	size_t buf_pos = 0;
	loff_t p = 0;
	ssize_t ret;
	int i;
	struct regmap *map = file->private_data;
	char *buf;

	if (*ppos < 0 || !count)
		return -EINVAL;

	buf = kmalloc(count, GFP_KERNEL);
	if (!buf)
		return -ENOMEM;

	
	reg_len = regmap_calc_reg_len(map->max_register, buf, count);
	tot_len = reg_len + 10; 

	for (i = 0; i < map->max_register + 1; i++) {
		
		if (!regmap_readable(map, i) && !regmap_writeable(map, i))
			continue;

		
		if (p >= *ppos) {
			
			if (buf_pos >= count - 1 - tot_len)
				break;

			
			snprintf(buf + buf_pos, count - buf_pos,
				 "%.*x: %c %c %c %c\n",
				 reg_len, i,
				 regmap_readable(map, i) ? 'y' : 'n',
				 regmap_writeable(map, i) ? 'y' : 'n',
				 regmap_volatile(map, i) ? 'y' : 'n',
				 regmap_precious(map, i) ? 'y' : 'n');

			buf_pos += tot_len;
		}
		p += tot_len;
	}

	ret = buf_pos;

	if (copy_to_user(user_buf, buf, buf_pos)) {
		ret = -EFAULT;
		goto out;
	}

	*ppos += buf_pos;

out:
	kfree(buf);
	return ret;
}
コード例 #13
0
ファイル: regcache.c プロジェクト: TheDarkCode/linux
static int regcache_hw_init(struct regmap *map)
{
	int i, j;
	int ret;
	int count;
	unsigned int reg, val;
	void *tmp_buf;

	if (!map->num_reg_defaults_raw)
		return -EINVAL;

	/* calculate the size of reg_defaults */
	for (count = 0, i = 0; i < map->num_reg_defaults_raw; i++)
		if (regmap_readable(map, i * map->reg_stride) &&
		    !regmap_volatile(map, i * map->reg_stride))
			count++;

	/* all registers are unreadable or volatile, so just bypass */
	if (!count) {
		map->cache_bypass = true;
		return 0;
	}

	map->num_reg_defaults = count;
	map->reg_defaults = kmalloc_array(count, sizeof(struct reg_default),
					  GFP_KERNEL);
	if (!map->reg_defaults)
		return -ENOMEM;

	if (!map->reg_defaults_raw) {
		bool cache_bypass = map->cache_bypass;
		dev_warn(map->dev, "No cache defaults, reading back from HW\n");

		/* Bypass the cache access till data read from HW */
		map->cache_bypass = true;
		tmp_buf = kmalloc(map->cache_size_raw, GFP_KERNEL);
		if (!tmp_buf) {
			ret = -ENOMEM;
			goto err_free;
		}
		ret = regmap_raw_read(map, 0, tmp_buf,
				      map->cache_size_raw);
		map->cache_bypass = cache_bypass;
		if (ret == 0) {
			map->reg_defaults_raw = tmp_buf;
			map->cache_free = 1;
		} else {
			kfree(tmp_buf);
		}
	}

	/* fill the reg_defaults */
	for (i = 0, j = 0; i < map->num_reg_defaults_raw; i++) {
		reg = i * map->reg_stride;

		if (!regmap_readable(map, reg))
			continue;

		if (regmap_volatile(map, reg))
			continue;

		if (map->reg_defaults_raw) {
			val = regcache_get_val(map, map->reg_defaults_raw, i);
		} else {
			bool cache_bypass = map->cache_bypass;

			map->cache_bypass = true;
			ret = regmap_read(map, reg, &val);
			map->cache_bypass = cache_bypass;
			if (ret != 0) {
				dev_err(map->dev, "Failed to read %d: %d\n",
					reg, ret);
				goto err_free;
			}
		}

		map->reg_defaults[j].reg = reg;
		map->reg_defaults[j].def = val;
		j++;
	}

	return 0;

err_free:
	kfree(map->reg_defaults);

	return ret;
}