Commit 98bc7dfd authored by Mark Brown's avatar Mark Brown

regmap: Factor range lookup out of page selection

This will support a subsequent update to allow bulk writes to cross window
boundaries.
Signed-off-by: default avatarMark Brown <broonie@opensource.wolfsonmicro.com>
parent 4b020b3f
...@@ -765,59 +765,57 @@ struct regmap *dev_get_regmap(struct device *dev, const char *name) ...@@ -765,59 +765,57 @@ struct regmap *dev_get_regmap(struct device *dev, const char *name)
EXPORT_SYMBOL_GPL(dev_get_regmap); EXPORT_SYMBOL_GPL(dev_get_regmap);
static int _regmap_select_page(struct regmap *map, unsigned int *reg, static int _regmap_select_page(struct regmap *map, unsigned int *reg,
struct regmap_range_node *range,
unsigned int val_num) unsigned int val_num)
{ {
struct regmap_range_node *range;
void *orig_work_buf; void *orig_work_buf;
unsigned int win_offset; unsigned int win_offset;
unsigned int win_page; unsigned int win_page;
bool page_chg; bool page_chg;
int ret; int ret;
range = _regmap_range_lookup(map, *reg); win_offset = (*reg - range->range_min) % range->window_len;
if (range) { win_page = (*reg - range->range_min) / range->window_len;
win_offset = (*reg - range->range_min) % range->window_len;
win_page = (*reg - range->range_min) / range->window_len;
if (val_num > 1) { if (val_num > 1) {
/* Bulk write shouldn't cross range boundary */ /* Bulk write shouldn't cross range boundary */
if (*reg + val_num - 1 > range->range_max) if (*reg + val_num - 1 > range->range_max)
return -EINVAL; return -EINVAL;
/* ... or single page boundary */ /* ... or single page boundary */
if (val_num > range->window_len - win_offset) if (val_num > range->window_len - win_offset)
return -EINVAL; return -EINVAL;
} }
/* It is possible to have selector register inside data window. /* It is possible to have selector register inside data window.
In that case, selector register is located on every page and In that case, selector register is located on every page and
it needs no page switching, when accessed alone. */ it needs no page switching, when accessed alone. */
if (val_num > 1 || if (val_num > 1 ||
range->window_start + win_offset != range->selector_reg) { range->window_start + win_offset != range->selector_reg) {
/* Use separate work_buf during page switching */ /* Use separate work_buf during page switching */
orig_work_buf = map->work_buf; orig_work_buf = map->work_buf;
map->work_buf = map->selector_work_buf; map->work_buf = map->selector_work_buf;
ret = _regmap_update_bits(map, range->selector_reg, ret = _regmap_update_bits(map, range->selector_reg,
range->selector_mask, range->selector_mask,
win_page << range->selector_shift, win_page << range->selector_shift,
&page_chg); &page_chg);
map->work_buf = orig_work_buf; map->work_buf = orig_work_buf;
if (ret < 0) if (ret < 0)
return ret; return ret;
}
*reg = range->window_start + win_offset;
} }
*reg = range->window_start + win_offset;
return 0; return 0;
} }
static int _regmap_raw_write(struct regmap *map, unsigned int reg, static int _regmap_raw_write(struct regmap *map, unsigned int reg,
const void *val, size_t val_len) const void *val, size_t val_len)
{ {
struct regmap_range_node *range;
u8 *u8 = map->work_buf; u8 *u8 = map->work_buf;
void *buf; void *buf;
int ret = -ENOTSUPP; int ret = -ENOTSUPP;
...@@ -852,9 +850,13 @@ static int _regmap_raw_write(struct regmap *map, unsigned int reg, ...@@ -852,9 +850,13 @@ static int _regmap_raw_write(struct regmap *map, unsigned int reg,
} }
} }
ret = _regmap_select_page(map, &reg, val_len / map->format.val_bytes); range = _regmap_range_lookup(map, reg);
if (ret < 0) if (range) {
return ret; ret = _regmap_select_page(map, &reg, range,
val_len / map->format.val_bytes);
if (ret < 0)
return ret;
}
map->format.format_reg(map->work_buf, reg, map->reg_shift); map->format.format_reg(map->work_buf, reg, map->reg_shift);
...@@ -903,6 +905,7 @@ static int _regmap_raw_write(struct regmap *map, unsigned int reg, ...@@ -903,6 +905,7 @@ static int _regmap_raw_write(struct regmap *map, unsigned int reg,
int _regmap_write(struct regmap *map, unsigned int reg, int _regmap_write(struct regmap *map, unsigned int reg,
unsigned int val) unsigned int val)
{ {
struct regmap_range_node *range;
int ret; int ret;
BUG_ON(!map->format.format_write && !map->format.format_val); BUG_ON(!map->format.format_write && !map->format.format_val);
...@@ -924,9 +927,12 @@ int _regmap_write(struct regmap *map, unsigned int reg, ...@@ -924,9 +927,12 @@ int _regmap_write(struct regmap *map, unsigned int reg,
trace_regmap_reg_write(map->dev, reg, val); trace_regmap_reg_write(map->dev, reg, val);
if (map->format.format_write) { if (map->format.format_write) {
ret = _regmap_select_page(map, &reg, 1); range = _regmap_range_lookup(map, reg);
if (ret < 0) if (range) {
return ret; ret = _regmap_select_page(map, &reg, range, 1);
if (ret < 0)
return ret;
}
map->format.format_write(map, reg, val); map->format.format_write(map, reg, val);
...@@ -1082,12 +1088,17 @@ EXPORT_SYMBOL_GPL(regmap_bulk_write); ...@@ -1082,12 +1088,17 @@ EXPORT_SYMBOL_GPL(regmap_bulk_write);
static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val, static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
unsigned int val_len) unsigned int val_len)
{ {
struct regmap_range_node *range;
u8 *u8 = map->work_buf; u8 *u8 = map->work_buf;
int ret; int ret;
ret = _regmap_select_page(map, &reg, val_len / map->format.val_bytes); range = _regmap_range_lookup(map, reg);
if (ret < 0) if (range) {
return ret; ret = _regmap_select_page(map, &reg, range,
val_len / map->format.val_bytes);
if (ret < 0)
return ret;
}
map->format.format_reg(map->work_buf, reg, map->reg_shift); map->format.format_reg(map->work_buf, reg, map->reg_shift);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment