diff options
Diffstat (limited to 'drivers/base/regmap/regmap.c')
| -rw-r--r-- | drivers/base/regmap/regmap.c | 31 | 
1 files changed, 28 insertions, 3 deletions
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c index df2d2ef5d6b3..51fa7d66a393 100644 --- a/drivers/base/regmap/regmap.c +++ b/drivers/base/regmap/regmap.c @@ -1777,8 +1777,6 @@ int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val,  	size_t val_bytes = map->format.val_bytes;  	size_t total_size = val_bytes * val_count; -	if (map->bus && !map->format.parse_inplace) -		return -EINVAL;  	if (!IS_ALIGNED(reg, map->reg_stride))  		return -EINVAL; @@ -1789,7 +1787,8 @@ int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val,  	 *  	 * The first if block is used for memory mapped io. It does not allow  	 * val_bytes of 3 for example. -	 * The second one is used for busses which do not have this limitation +	 * The second one is for busses that do not provide raw I/O. +	 * The third one is used for busses which do not have these limitations  	 * and can write arbitrary value lengths.  	 */  	if (!map->bus) { @@ -1825,6 +1824,32 @@ int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val,  		}  out:  		map->unlock(map->lock_arg); +	} else if (map->bus && !map->format.parse_inplace) { +		const u8 *u8 = val; +		const u16 *u16 = val; +		const u32 *u32 = val; +		unsigned int ival; + +		for (i = 0; i < val_count; i++) { +			switch (map->format.val_bytes) { +			case 4: +				ival = u32[i]; +				break; +			case 2: +				ival = u16[i]; +				break; +			case 1: +				ival = u8[i]; +				break; +			default: +				return -EINVAL; +			} + +			ret = regmap_write(map, reg + (i * map->reg_stride), +					   ival); +			if (ret) +				return ret; +		}  	} else if (map->use_single_write ||  		   (map->max_raw_write && map->max_raw_write < total_size)) {  		int chunk_stride = map->reg_stride;  |