diff options
Diffstat (limited to 'drivers/base/regmap/regmap.c')
| -rw-r--r-- | drivers/base/regmap/regmap.c | 59 | 
1 files changed, 42 insertions, 17 deletions
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c index d2a54eb0efd9..fa2d3fba6ac9 100644 --- a/drivers/base/regmap/regmap.c +++ b/drivers/base/regmap/regmap.c @@ -814,7 +814,7 @@ struct regmap *__regmap_init(struct device *dev,  	map->format.reg_bytes = DIV_ROUND_UP(config->reg_bits, 8);  	map->format.pad_bytes = config->pad_bits / 8; -	map->format.reg_downshift = config->reg_downshift; +	map->format.reg_shift = config->reg_shift;  	map->format.val_bytes = DIV_ROUND_UP(config->val_bits, 8);  	map->format.buf_size = DIV_ROUND_UP(config->reg_bits +  			config->val_bits + config->pad_bits, 8); @@ -1676,6 +1676,18 @@ static void regmap_set_work_buf_flag_mask(struct regmap *map, int max_bytes,  		buf[i] |= (mask >> (8 * i)) & 0xff;  } +static unsigned int regmap_reg_addr(struct regmap *map, unsigned int reg) +{ +	reg += map->reg_base; + +	if (map->format.reg_shift > 0) +		reg >>= map->format.reg_shift; +	else if (map->format.reg_shift < 0) +		reg <<= -(map->format.reg_shift); + +	return reg; +} +  static int _regmap_raw_write_impl(struct regmap *map, unsigned int reg,  				  const void *val, size_t val_len, bool noinc)  { @@ -1753,8 +1765,7 @@ static int _regmap_raw_write_impl(struct regmap *map, unsigned int reg,  			return ret;  	} -	reg += map->reg_base; -	reg >>= map->format.reg_downshift; +	reg = regmap_reg_addr(map, reg);  	map->format.format_reg(map->work_buf, reg, map->reg_shift);  	regmap_set_work_buf_flag_mask(map, map->format.reg_bytes,  				      map->write_flag_mask); @@ -1924,8 +1935,7 @@ static int _regmap_bus_formatted_write(void *context, unsigned int reg,  			return ret;  	} -	reg += map->reg_base; -	reg >>= map->format.reg_downshift; +	reg = regmap_reg_addr(map, reg);  	map->format.format_write(map, reg, val);  	trace_regmap_hw_write_start(map, reg, 1); @@ -1941,9 +1951,17 @@ static int _regmap_bus_reg_write(void *context, unsigned int reg,  				 unsigned int val)  {  	struct regmap *map = context; +	struct regmap_range_node *range; +	int ret; -	reg += map->reg_base; -	reg >>= map->format.reg_downshift; +	range = _regmap_range_lookup(map, reg); +	if (range) { +		ret = _regmap_select_page(map, ®, range, 1); +		if (ret != 0) +			return ret; +	} + +	reg = regmap_reg_addr(map, reg);  	return map->bus->reg_write(map->bus_context, reg, val);  } @@ -2064,6 +2082,8 @@ int _regmap_raw_write(struct regmap *map, unsigned int reg,  	size_t val_count = val_len / val_bytes;  	size_t chunk_count, chunk_bytes;  	size_t chunk_regs = val_count; +	size_t max_data = map->max_raw_write - map->format.reg_bytes - +			map->format.pad_bytes;  	int ret, i;  	if (!val_count) @@ -2071,8 +2091,8 @@ int _regmap_raw_write(struct regmap *map, unsigned int reg,  	if (map->use_single_write)  		chunk_regs = 1; -	else if (map->max_raw_write && val_len > map->max_raw_write) -		chunk_regs = map->max_raw_write / val_bytes; +	else if (map->max_raw_write && val_len > max_data) +		chunk_regs = max_data / val_bytes;  	chunk_count = val_count / chunk_regs;  	chunk_bytes = chunk_regs * val_bytes; @@ -2494,8 +2514,7 @@ static int _regmap_raw_multi_reg_write(struct regmap *map,  		unsigned int reg = regs[i].reg;  		unsigned int val = regs[i].def;  		trace_regmap_hw_write_start(map, reg, 1); -		reg += map->reg_base; -		reg >>= map->format.reg_downshift; +		reg = regmap_reg_addr(map, reg);  		map->format.format_reg(u8, reg, map->reg_shift);  		u8 += reg_bytes + pad_bytes;  		map->format.format_val(u8, val, 0); @@ -2821,8 +2840,7 @@ static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val,  			return ret;  	} -	reg += map->reg_base; -	reg >>= map->format.reg_downshift; +	reg = regmap_reg_addr(map, reg);  	map->format.format_reg(map->work_buf, reg, map->reg_shift);  	regmap_set_work_buf_flag_mask(map, map->format.reg_bytes,  				      map->read_flag_mask); @@ -2841,9 +2859,17 @@ static int _regmap_bus_reg_read(void *context, unsigned int reg,  				unsigned int *val)  {  	struct regmap *map = context; +	struct regmap_range_node *range; +	int ret; -	reg += map->reg_base; -	reg >>= map->format.reg_downshift; +	range = _regmap_range_lookup(map, reg); +	if (range) { +		ret = _regmap_select_page(map, ®, range, 1); +		if (ret != 0) +			return ret; +	} + +	reg = regmap_reg_addr(map, reg);  	return map->bus->reg_read(map->bus_context, reg, val);  } @@ -3235,8 +3261,7 @@ static int _regmap_update_bits(struct regmap *map, unsigned int reg,  		*change = false;  	if (regmap_volatile(map, reg) && map->reg_update_bits) { -		reg += map->reg_base; -		reg >>= map->format.reg_downshift; +		reg = regmap_reg_addr(map, reg);  		ret = map->reg_update_bits(map->bus_context, reg, mask, val);  		if (ret == 0 && change)  			*change = true;  |