|
@@ -34,7 +34,7 @@
|
|
|
|
|
|
static int _regmap_update_bits(struct regmap *map, unsigned int reg,
|
|
|
unsigned int mask, unsigned int val,
|
|
|
- bool *change);
|
|
|
+ bool *change, bool force_write);
|
|
|
|
|
|
static int _regmap_bus_reg_read(void *context, unsigned int reg,
|
|
|
unsigned int *val);
|
|
@@ -1178,7 +1178,7 @@ static int _regmap_select_page(struct regmap *map, unsigned int *reg,
|
|
|
ret = _regmap_update_bits(map, range->selector_reg,
|
|
|
range->selector_mask,
|
|
|
win_page << range->selector_shift,
|
|
|
- &page_chg);
|
|
|
+ &page_chg, false);
|
|
|
|
|
|
map->work_buf = orig_work_buf;
|
|
|
|
|
@@ -1624,6 +1624,18 @@ int regmap_fields_write(struct regmap_field *field, unsigned int id,
|
|
|
}
|
|
|
EXPORT_SYMBOL_GPL(regmap_fields_write);
|
|
|
|
|
|
+int regmap_fields_force_write(struct regmap_field *field, unsigned int id,
|
|
|
+ unsigned int val)
|
|
|
+{
|
|
|
+ if (id >= field->id_size)
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ return regmap_write_bits(field->regmap,
|
|
|
+ field->reg + (field->id_offset * id),
|
|
|
+ field->mask, val << field->shift);
|
|
|
+}
|
|
|
+EXPORT_SYMBOL_GPL(regmap_fields_force_write);
|
|
|
+
|
|
|
/**
|
|
|
* regmap_fields_update_bits(): Perform a read/modify/write cycle
|
|
|
* on the register field
|
|
@@ -1743,7 +1755,7 @@ EXPORT_SYMBOL_GPL(regmap_bulk_write);
|
|
|
* relative. The page register has been written if that was neccessary.
|
|
|
*/
|
|
|
static int _regmap_raw_multi_reg_write(struct regmap *map,
|
|
|
- const struct reg_default *regs,
|
|
|
+ const struct reg_sequence *regs,
|
|
|
size_t num_regs)
|
|
|
{
|
|
|
int ret;
|
|
@@ -1800,12 +1812,12 @@ static unsigned int _regmap_register_page(struct regmap *map,
|
|
|
}
|
|
|
|
|
|
static int _regmap_range_multi_paged_reg_write(struct regmap *map,
|
|
|
- struct reg_default *regs,
|
|
|
+ struct reg_sequence *regs,
|
|
|
size_t num_regs)
|
|
|
{
|
|
|
int ret;
|
|
|
int i, n;
|
|
|
- struct reg_default *base;
|
|
|
+ struct reg_sequence *base;
|
|
|
unsigned int this_page = 0;
|
|
|
/*
|
|
|
* the set of registers are not neccessarily in order, but
|
|
@@ -1843,7 +1855,7 @@ static int _regmap_range_multi_paged_reg_write(struct regmap *map,
|
|
|
}
|
|
|
|
|
|
static int _regmap_multi_reg_write(struct regmap *map,
|
|
|
- const struct reg_default *regs,
|
|
|
+ const struct reg_sequence *regs,
|
|
|
size_t num_regs)
|
|
|
{
|
|
|
int i;
|
|
@@ -1895,8 +1907,8 @@ static int _regmap_multi_reg_write(struct regmap *map,
|
|
|
struct regmap_range_node *range;
|
|
|
range = _regmap_range_lookup(map, reg);
|
|
|
if (range) {
|
|
|
- size_t len = sizeof(struct reg_default)*num_regs;
|
|
|
- struct reg_default *base = kmemdup(regs, len,
|
|
|
+ size_t len = sizeof(struct reg_sequence)*num_regs;
|
|
|
+ struct reg_sequence *base = kmemdup(regs, len,
|
|
|
GFP_KERNEL);
|
|
|
if (!base)
|
|
|
return -ENOMEM;
|
|
@@ -1929,7 +1941,7 @@ static int _regmap_multi_reg_write(struct regmap *map,
|
|
|
* A value of zero will be returned on success, a negative errno will be
|
|
|
* returned in error cases.
|
|
|
*/
|
|
|
-int regmap_multi_reg_write(struct regmap *map, const struct reg_default *regs,
|
|
|
+int regmap_multi_reg_write(struct regmap *map, const struct reg_sequence *regs,
|
|
|
int num_regs)
|
|
|
{
|
|
|
int ret;
|
|
@@ -1962,7 +1974,7 @@ EXPORT_SYMBOL_GPL(regmap_multi_reg_write);
|
|
|
* be returned in error cases.
|
|
|
*/
|
|
|
int regmap_multi_reg_write_bypassed(struct regmap *map,
|
|
|
- const struct reg_default *regs,
|
|
|
+ const struct reg_sequence *regs,
|
|
|
int num_regs)
|
|
|
{
|
|
|
int ret;
|
|
@@ -2327,7 +2339,7 @@ EXPORT_SYMBOL_GPL(regmap_bulk_read);
|
|
|
|
|
|
static int _regmap_update_bits(struct regmap *map, unsigned int reg,
|
|
|
unsigned int mask, unsigned int val,
|
|
|
- bool *change)
|
|
|
+ bool *change, bool force_write)
|
|
|
{
|
|
|
int ret;
|
|
|
unsigned int tmp, orig;
|
|
@@ -2339,7 +2351,7 @@ static int _regmap_update_bits(struct regmap *map, unsigned int reg,
|
|
|
tmp = orig & ~mask;
|
|
|
tmp |= val & mask;
|
|
|
|
|
|
- if (tmp != orig) {
|
|
|
+ if (force_write || (tmp != orig)) {
|
|
|
ret = _regmap_write(map, reg, tmp);
|
|
|
if (change)
|
|
|
*change = true;
|
|
@@ -2367,13 +2379,36 @@ int regmap_update_bits(struct regmap *map, unsigned int reg,
|
|
|
int ret;
|
|
|
|
|
|
map->lock(map->lock_arg);
|
|
|
- ret = _regmap_update_bits(map, reg, mask, val, NULL);
|
|
|
+ ret = _regmap_update_bits(map, reg, mask, val, NULL, false);
|
|
|
map->unlock(map->lock_arg);
|
|
|
|
|
|
return ret;
|
|
|
}
|
|
|
EXPORT_SYMBOL_GPL(regmap_update_bits);
|
|
|
|
|
|
+/**
|
|
|
+ * regmap_write_bits: Perform a read/modify/write cycle on the register map
|
|
|
+ *
|
|
|
+ * @map: Register map to update
|
|
|
+ * @reg: Register to update
|
|
|
+ * @mask: Bitmask to change
|
|
|
+ * @val: New value for bitmask
|
|
|
+ *
|
|
|
+ * Returns zero for success, a negative number on error.
|
|
|
+ */
|
|
|
+int regmap_write_bits(struct regmap *map, unsigned int reg,
|
|
|
+ unsigned int mask, unsigned int val)
|
|
|
+{
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ map->lock(map->lock_arg);
|
|
|
+ ret = _regmap_update_bits(map, reg, mask, val, NULL, true);
|
|
|
+ map->unlock(map->lock_arg);
|
|
|
+
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+EXPORT_SYMBOL_GPL(regmap_write_bits);
|
|
|
+
|
|
|
/**
|
|
|
* regmap_update_bits_async: Perform a read/modify/write cycle on the register
|
|
|
* map asynchronously
|
|
@@ -2398,7 +2433,7 @@ int regmap_update_bits_async(struct regmap *map, unsigned int reg,
|
|
|
|
|
|
map->async = true;
|
|
|
|
|
|
- ret = _regmap_update_bits(map, reg, mask, val, NULL);
|
|
|
+ ret = _regmap_update_bits(map, reg, mask, val, NULL, false);
|
|
|
|
|
|
map->async = false;
|
|
|
|
|
@@ -2427,7 +2462,7 @@ int regmap_update_bits_check(struct regmap *map, unsigned int reg,
|
|
|
int ret;
|
|
|
|
|
|
map->lock(map->lock_arg);
|
|
|
- ret = _regmap_update_bits(map, reg, mask, val, change);
|
|
|
+ ret = _regmap_update_bits(map, reg, mask, val, change, false);
|
|
|
map->unlock(map->lock_arg);
|
|
|
return ret;
|
|
|
}
|
|
@@ -2460,7 +2495,7 @@ int regmap_update_bits_check_async(struct regmap *map, unsigned int reg,
|
|
|
|
|
|
map->async = true;
|
|
|
|
|
|
- ret = _regmap_update_bits(map, reg, mask, val, change);
|
|
|
+ ret = _regmap_update_bits(map, reg, mask, val, change, false);
|
|
|
|
|
|
map->async = false;
|
|
|
|
|
@@ -2552,10 +2587,10 @@ EXPORT_SYMBOL_GPL(regmap_async_complete);
|
|
|
* The caller must ensure that this function cannot be called
|
|
|
* concurrently with either itself or regcache_sync().
|
|
|
*/
|
|
|
-int regmap_register_patch(struct regmap *map, const struct reg_default *regs,
|
|
|
+int regmap_register_patch(struct regmap *map, const struct reg_sequence *regs,
|
|
|
int num_regs)
|
|
|
{
|
|
|
- struct reg_default *p;
|
|
|
+ struct reg_sequence *p;
|
|
|
int ret;
|
|
|
bool bypass;
|
|
|
|
|
@@ -2564,7 +2599,7 @@ int regmap_register_patch(struct regmap *map, const struct reg_default *regs,
|
|
|
return 0;
|
|
|
|
|
|
p = krealloc(map->patch,
|
|
|
- sizeof(struct reg_default) * (map->patch_regs + num_regs),
|
|
|
+ sizeof(struct reg_sequence) * (map->patch_regs + num_regs),
|
|
|
GFP_KERNEL);
|
|
|
if (p) {
|
|
|
memcpy(p + map->patch_regs, regs, num_regs * sizeof(*regs));
|