提交 98bc7dfd 编写于 作者: M 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: NMark Brown <broonie@opensource.wolfsonmicro.com>
上级 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% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册