Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit addfd8a0 authored by Mark Brown's avatar Mark Brown
Browse files

Merge remote-tracking branch 'regmap/topic/bulk' into regmap-next

parents eae4b51b df00c79f
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -35,12 +35,17 @@ static int regcache_hw_init(struct regmap *map)
		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;
+71 −5
Original line number Diff line number Diff line
@@ -411,6 +411,26 @@ static int _regmap_raw_write(struct regmap *map, unsigned int reg,
			if (!map->writeable_reg(map->dev, reg + i))
				return -EINVAL;

	if (!map->cache_bypass && map->format.parse_val) {
		unsigned int ival;
		int val_bytes = map->format.val_bytes;
		for (i = 0; i < val_len / val_bytes; i++) {
			memcpy(map->work_buf, val + (i * val_bytes), val_bytes);
			ival = map->format.parse_val(map->work_buf);
			ret = regcache_write(map, reg + i, ival);
			if (ret) {
				dev_err(map->dev,
				   "Error in caching of register: %u ret: %d\n",
					reg + i, ret);
				return ret;
			}
		}
		if (map->cache_only) {
			map->cache_dirty = true;
			return 0;
		}
	}

	map->format.format_reg(map->work_buf, reg);

	u8[0] |= map->write_flag_mask;
@@ -461,7 +481,7 @@ int _regmap_write(struct regmap *map, unsigned int reg,
	int ret;
	BUG_ON(!map->format.format_write && !map->format.format_val);

	if (!map->cache_bypass) {
	if (!map->cache_bypass && map->format.format_write) {
		ret = regcache_write(map, reg, val);
		if (ret != 0)
			return ret;
@@ -538,12 +558,8 @@ EXPORT_SYMBOL_GPL(regmap_write);
int regmap_raw_write(struct regmap *map, unsigned int reg,
		     const void *val, size_t val_len)
{
	size_t val_count = val_len / map->format.val_bytes;
	int ret;

	WARN_ON(!regmap_volatile_range(map, reg, val_count) &&
		map->cache_type != REGCACHE_NONE);

	mutex_lock(&map->lock);

	ret = _regmap_raw_write(map, reg, val, val_len);
@@ -554,6 +570,56 @@ int regmap_raw_write(struct regmap *map, unsigned int reg,
}
EXPORT_SYMBOL_GPL(regmap_raw_write);

/*
 * regmap_bulk_write(): Write multiple registers to the device
 *
 * @map: Register map to write to
 * @reg: First register to be write from
 * @val: Block of data to be written, in native register size for device
 * @val_count: Number of registers to write
 *
 * This function is intended to be used for writing a large block of
 * data to be device either in single transfer or multiple transfer.
 *
 * A value of zero will be returned on success, a negative errno will
 * be returned in error cases.
 */
int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val,
		     size_t val_count)
{
	int ret = 0, i;
	size_t val_bytes = map->format.val_bytes;
	void *wval;

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

	mutex_lock(&map->lock);

	/* No formatting is require if val_byte is 1 */
	if (val_bytes == 1) {
		wval = (void *)val;
	} else {
		wval = kmemdup(val, val_count * val_bytes, GFP_KERNEL);
		if (!wval) {
			ret = -ENOMEM;
			dev_err(map->dev, "Error in memory allocation\n");
			goto out;
		}
		for (i = 0; i < val_count * val_bytes; i += val_bytes)
			map->format.parse_val(wval + i);
	}
	ret = _regmap_raw_write(map, reg, wval, val_bytes * val_count);

	if (val_bytes != 1)
		kfree(wval);

out:
	mutex_unlock(&map->lock);
	return ret;
}
EXPORT_SYMBOL_GPL(regmap_bulk_write);

static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
			    unsigned int val_len)
{
+2 −0
Original line number Diff line number Diff line
@@ -146,6 +146,8 @@ int regmap_reinit_cache(struct regmap *map,
int regmap_write(struct regmap *map, unsigned int reg, unsigned int val);
int regmap_raw_write(struct regmap *map, unsigned int reg,
		     const void *val, size_t val_len);
int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val,
			size_t val_count);
int regmap_read(struct regmap *map, unsigned int reg, unsigned int *val);
int regmap_raw_read(struct regmap *map, unsigned int reg,
		    void *val, size_t val_len);