#include <linux/rbtree.h>
#include <linux/sched.h>
#include <linux/delay.h>
+#include <linux/log2.h>
#define CREATE_TRACE_POINTS
#include "trace.h"
endian = REGMAP_ENDIAN_BIG;
else if (of_property_read_bool(np, "little-endian"))
endian = REGMAP_ENDIAN_LITTLE;
+ else if (of_property_read_bool(np, "native-endian"))
+ endian = REGMAP_ENDIAN_NATIVE;
/* If the endianness was specified in DT, use that */
if (endian != REGMAP_ENDIAN_DEFAULT)
map->reg_stride = config->reg_stride;
else
map->reg_stride = 1;
+ if (is_power_of_2(map->reg_stride))
+ map->reg_stride_order = ilog2(map->reg_stride);
+ else
+ map->reg_stride_order = -1;
map->use_single_read = config->use_single_rw || !bus || !bus->read;
map->use_single_write = config->use_single_rw || !bus || !bus->write;
map->can_multi_write = config->can_multi_write && bus && bus->write;
if (map->writeable_reg)
for (i = 0; i < val_len / map->format.val_bytes; i++)
if (!map->writeable_reg(map->dev,
- reg + (i * map->reg_stride)))
+ reg + regmap_get_offset(map, i)))
return -EINVAL;
if (!map->cache_bypass && map->format.parse_val) {
int val_bytes = map->format.val_bytes;
for (i = 0; i < val_len / val_bytes; i++) {
ival = map->format.parse_val(val + (i * val_bytes));
- ret = regcache_write(map, reg + (i * map->reg_stride),
+ ret = regcache_write(map,
+ reg + regmap_get_offset(map, i),
ival);
if (ret) {
dev_err(map->dev,
EXPORT_SYMBOL_GPL(regmap_raw_write);
/**
- * regmap_field_write(): Write a value to a single register field
- *
- * @field: Register field to write to
- * @val: Value to be written
- *
- * A value of zero will be returned on success, a negative errno will
- * be returned in error cases.
- */
- int regmap_field_write(struct regmap_field *field, unsigned int val)
- {
- return regmap_update_bits(field->regmap, field->reg,
- field->mask, val << field->shift);
- }
- EXPORT_SYMBOL_GPL(regmap_field_write);
-
- /**
- * regmap_field_update_bits(): Perform a read/modify/write cycle
- * on the register field
+ * regmap_field_update_bits_base():
+ * Perform a read/modify/write cycle on the register field
+ * with change, async, force option
*
* @field: Register field to write to
* @mask: Bitmask to change
* @val: Value to be written
+ * @change: Boolean indicating if a write was done
+ * @async: Boolean indicating asynchronously
+ * @force: Boolean indicating use force update
*
* A value of zero will be returned on success, a negative errno will
* be returned in error cases.
*/
- int regmap_field_update_bits(struct regmap_field *field, unsigned int mask, unsigned int val)
+ int regmap_field_update_bits_base(struct regmap_field *field,
+ unsigned int mask, unsigned int val,
+ bool *change, bool async, bool force)
{
mask = (mask << field->shift) & field->mask;
- return regmap_update_bits(field->regmap, field->reg,
- mask, val << field->shift);
- }
- EXPORT_SYMBOL_GPL(regmap_field_update_bits);
-
- /**
- * regmap_fields_write(): Write a value to a single register field with port ID
- *
- * @field: Register field to write to
- * @id: port ID
- * @val: Value to be written
- *
- * A value of zero will be returned on success, a negative errno will
- * be returned in error cases.
- */
- int regmap_fields_write(struct regmap_field *field, unsigned int id,
- unsigned int val)
- {
- if (id >= field->id_size)
- return -EINVAL;
-
- return regmap_update_bits(field->regmap,
- field->reg + (field->id_offset * id),
- field->mask, val << field->shift);
- }
- 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);
+ return regmap_update_bits_base(field->regmap, field->reg,
+ mask, val << field->shift,
+ change, async, force);
}
- EXPORT_SYMBOL_GPL(regmap_fields_force_write);
+ EXPORT_SYMBOL_GPL(regmap_field_update_bits_base);
/**
- * regmap_fields_update_bits(): Perform a read/modify/write cycle
- * on the register field
+ * regmap_fields_update_bits_base():
+ * Perform a read/modify/write cycle on the register field
+ * with change, async, force option
*
* @field: Register field to write to
* @id: port ID
* @mask: Bitmask to change
* @val: Value to be written
+ * @change: Boolean indicating if a write was done
+ * @async: Boolean indicating asynchronously
+ * @force: Boolean indicating use force update
*
* A value of zero will be returned on success, a negative errno will
* be returned in error cases.
*/
- int regmap_fields_update_bits(struct regmap_field *field, unsigned int id,
- unsigned int mask, unsigned int val)
+ int regmap_fields_update_bits_base(struct regmap_field *field, unsigned int id,
+ unsigned int mask, unsigned int val,
+ bool *change, bool async, bool force)
{
if (id >= field->id_size)
return -EINVAL;
mask = (mask << field->shift) & field->mask;
- return regmap_update_bits(field->regmap,
- field->reg + (field->id_offset * id),
- mask, val << field->shift);
+ return regmap_update_bits_base(field->regmap,
+ field->reg + (field->id_offset * id),
+ mask, val << field->shift,
+ change, async, force);
}
- EXPORT_SYMBOL_GPL(regmap_fields_update_bits);
+ EXPORT_SYMBOL_GPL(regmap_fields_update_bits_base);
/*
* regmap_bulk_write(): Write multiple registers to the device
goto out;
}
- ret = _regmap_write(map, reg + (i * map->reg_stride),
- ival);
+ ret = _regmap_write(map,
+ reg + regmap_get_offset(map, i),
+ ival);
if (ret != 0)
goto out;
}
WARN_ON(!map->bus);
+ if (!map->bus || !map->bus->read)
+ return -EINVAL;
+
range = _regmap_range_lookup(map, reg);
if (range) {
ret = _regmap_select_page(map, ®, range,
* cost as we expect to hit the cache.
*/
for (i = 0; i < val_count; i++) {
- ret = _regmap_read(map, reg + (i * map->reg_stride),
+ ret = _regmap_read(map, reg + regmap_get_offset(map, i),
&v);
if (ret != 0)
goto out;
} else {
for (i = 0; i < val_count; i++) {
unsigned int ival;
- ret = regmap_read(map, reg + (i * map->reg_stride),
+ ret = regmap_read(map, reg + regmap_get_offset(map, i),
&ival);
if (ret != 0)
return ret;
}
/**
- * regmap_update_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_update_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, 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
- *
- * @map: Register map to update
- * @reg: Register to update
- * @mask: Bitmask to change
- * @val: New value for bitmask
- *
- * With most buses the read must be done synchronously so this is most
- * useful for devices with a cache which do not need to interact with
- * the hardware to determine the current register value.
- *
- * Returns zero for success, a negative number on error.
- */
- int regmap_update_bits_async(struct regmap *map, unsigned int reg,
- unsigned int mask, unsigned int val)
- {
- int ret;
-
- map->lock(map->lock_arg);
-
- map->async = true;
-
- ret = _regmap_update_bits(map, reg, mask, val, NULL, false);
-
- map->async = false;
-
- map->unlock(map->lock_arg);
-
- return ret;
- }
- EXPORT_SYMBOL_GPL(regmap_update_bits_async);
-
- /**
- * regmap_update_bits_check: Perform a read/modify/write cycle on the
- * register map and report if updated
- *
- * @map: Register map to update
- * @reg: Register to update
- * @mask: Bitmask to change
- * @val: New value for bitmask
- * @change: Boolean indicating if a write was done
- *
- * Returns zero for success, a negative number on error.
- */
- int regmap_update_bits_check(struct regmap *map, unsigned int reg,
- unsigned int mask, unsigned int val,
- bool *change)
- {
- int ret;
-
- map->lock(map->lock_arg);
- ret = _regmap_update_bits(map, reg, mask, val, change, false);
- map->unlock(map->lock_arg);
- return ret;
- }
- EXPORT_SYMBOL_GPL(regmap_update_bits_check);
-
- /**
- * regmap_update_bits_check_async: Perform a read/modify/write cycle on the
- * register map asynchronously and report if
- * updated
+ * regmap_update_bits_base:
+ * Perform a read/modify/write cycle on the
+ * register map with change, async, force option
*
* @map: Register map to update
* @reg: Register to update
* @mask: Bitmask to change
* @val: New value for bitmask
* @change: Boolean indicating if a write was done
+ * @async: Boolean indicating asynchronously
+ * @force: Boolean indicating use force update
*
+ * if async was true,
* With most buses the read must be done synchronously so this is most
* useful for devices with a cache which do not need to interact with
* the hardware to determine the current register value.
*
* Returns zero for success, a negative number on error.
*/
- int regmap_update_bits_check_async(struct regmap *map, unsigned int reg,
- unsigned int mask, unsigned int val,
- bool *change)
+ int regmap_update_bits_base(struct regmap *map, unsigned int reg,
+ unsigned int mask, unsigned int val,
+ bool *change, bool async, bool force)
{
int ret;
map->lock(map->lock_arg);
- map->async = true;
+ map->async = async;
- ret = _regmap_update_bits(map, reg, mask, val, change, false);
+ ret = _regmap_update_bits(map, reg, mask, val, change, force);
map->async = false;
return ret;
}
- EXPORT_SYMBOL_GPL(regmap_update_bits_check_async);
+ EXPORT_SYMBOL_GPL(regmap_update_bits_base);
void regmap_async_complete_cb(struct regmap_async *async, int ret)
{
unsigned int delay_us;
};
+ #define regmap_update_bits(map, reg, mask, val) \
+ regmap_update_bits_base(map, reg, mask, val, NULL, false, false)
+ #define regmap_update_bits_async(map, reg, mask, val)\
+ regmap_update_bits_base(map, reg, mask, val, NULL, true, false)
+ #define regmap_update_bits_check(map, reg, mask, val, change)\
+ regmap_update_bits_base(map, reg, mask, val, change, false, false)
+ #define regmap_update_bits_check_async(map, reg, mask, val, change)\
+ regmap_update_bits_base(map, reg, mask, val, change, true, false)
+
+ #define regmap_write_bits(map, reg, mask, val) \
+ regmap_update_bits_base(map, reg, mask, val, NULL, false, true)
+
+ #define regmap_field_write(field, val) \
+ regmap_field_update_bits_base(field, ~0, val, NULL, false, false)
+ #define regmap_field_force_write(field, val) \
+ regmap_field_update_bits_base(field, ~0, val, NULL, false, true)
+ #define regmap_field_update_bits(field, mask, val)\
+ regmap_field_update_bits_base(field, mask, val, NULL, false, false)
+ #define regmap_field_force_update_bits(field, mask, val) \
+ regmap_field_update_bits_base(field, mask, val, NULL, false, true)
+
+ #define regmap_fields_write(field, id, val) \
+ regmap_fields_update_bits_base(field, id, ~0, val, NULL, false, false)
+ #define regmap_fields_force_write(field, id, val) \
+ regmap_fields_update_bits_base(field, id, ~0, val, NULL, false, true)
+ #define regmap_fields_update_bits(field, id, mask, val)\
+ regmap_fields_update_bits_base(field, id, mask, val, NULL, false, false)
+ #define regmap_fields_force_update_bits(field, id, mask, val) \
+ regmap_fields_update_bits_base(field, id, mask, val, NULL, false, true)
+
#ifdef CONFIG_REGMAP
enum regmap_endian {
* This field is a duplicate of a similar file in
* 'struct regmap_bus' and serves exact same purpose.
* Use it only for "no-bus" cases.
- * @max_register: Optional, specifies the maximum valid register index.
+ * @max_register: Optional, specifies the maximum valid register address.
* @wr_table: Optional, points to a struct regmap_access_table specifying
* valid ranges for write access.
* @rd_table: As above, for read access.
void *val, size_t val_len);
int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val,
size_t val_count);
- int regmap_update_bits(struct regmap *map, unsigned int reg,
- unsigned int mask, unsigned int val);
- int regmap_write_bits(struct regmap *map, unsigned int reg,
- unsigned int mask, unsigned int val);
- int regmap_update_bits_async(struct regmap *map, unsigned int reg,
- unsigned int mask, unsigned int val);
- int regmap_update_bits_check(struct regmap *map, unsigned int reg,
- unsigned int mask, unsigned int val,
- bool *change);
- int regmap_update_bits_check_async(struct regmap *map, unsigned int reg,
- unsigned int mask, unsigned int val,
- bool *change);
+ int regmap_update_bits_base(struct regmap *map, unsigned int reg,
+ unsigned int mask, unsigned int val,
+ bool *change, bool async, bool force);
int regmap_get_val_bytes(struct regmap *map);
int regmap_get_max_register(struct regmap *map);
int regmap_get_reg_stride(struct regmap *map);
void devm_regmap_field_free(struct device *dev, struct regmap_field *field);
int regmap_field_read(struct regmap_field *field, unsigned int *val);
- int regmap_field_write(struct regmap_field *field, unsigned int val);
- int regmap_field_update_bits(struct regmap_field *field,
- unsigned int mask, unsigned int val);
-
- int regmap_fields_write(struct regmap_field *field, unsigned int id,
- unsigned int val);
- int regmap_fields_force_write(struct regmap_field *field, unsigned int id,
- unsigned int val);
+ int regmap_field_update_bits_base(struct regmap_field *field,
+ unsigned int mask, unsigned int val,
+ bool *change, bool async, bool force);
int regmap_fields_read(struct regmap_field *field, unsigned int id,
unsigned int *val);
- int regmap_fields_update_bits(struct regmap_field *field, unsigned int id,
- unsigned int mask, unsigned int val);
+ int regmap_fields_update_bits_base(struct regmap_field *field, unsigned int id,
+ unsigned int mask, unsigned int val,
+ bool *change, bool async, bool force);
/**
* Description of an IRQ for the generic regmap irq_chip.
int irq_base, const struct regmap_irq_chip *chip,
struct regmap_irq_chip_data **data);
void regmap_del_irq_chip(int irq, struct regmap_irq_chip_data *data);
+
+int devm_regmap_add_irq_chip(struct device *dev, struct regmap *map, int irq,
+ int irq_flags, int irq_base,
+ const struct regmap_irq_chip *chip,
+ struct regmap_irq_chip_data **data);
+void devm_regmap_del_irq_chip(struct device *dev, int irq,
+ struct regmap_irq_chip_data *data);
+
int regmap_irq_chip_get_base(struct regmap_irq_chip_data *data);
int regmap_irq_get_virq(struct regmap_irq_chip_data *data, int irq);
struct irq_domain *regmap_irq_get_domain(struct regmap_irq_chip_data *data);
return -EINVAL;
}
- static inline int regmap_update_bits(struct regmap *map, unsigned int reg,
- unsigned int mask, unsigned int val)
- {
- WARN_ONCE(1, "regmap API is disabled");
- return -EINVAL;
- }
-
- static inline int regmap_write_bits(struct regmap *map, unsigned int reg,
- unsigned int mask, unsigned int val)
+ static inline int regmap_update_bits_base(struct regmap *map, unsigned int reg,
+ unsigned int mask, unsigned int val,
+ bool *change, bool async, bool force)
{
WARN_ONCE(1, "regmap API is disabled");
return -EINVAL;
}
- static inline int regmap_update_bits_async(struct regmap *map,
- unsigned int reg,
- unsigned int mask, unsigned int val)
+ static inline int regmap_field_update_bits_base(struct regmap_field *field,
+ unsigned int mask, unsigned int val,
+ bool *change, bool async, bool force)
{
WARN_ONCE(1, "regmap API is disabled");
return -EINVAL;
}
- static inline int regmap_update_bits_check(struct regmap *map,
- unsigned int reg,
- unsigned int mask, unsigned int val,
- bool *change)
- {
- WARN_ONCE(1, "regmap API is disabled");
- return -EINVAL;
- }
-
- static inline int regmap_update_bits_check_async(struct regmap *map,
- unsigned int reg,
- unsigned int mask,
- unsigned int val,
- bool *change)
+ static inline int regmap_fields_update_bits_base(struct regmap_field *field,
+ unsigned int id,
+ unsigned int mask, unsigned int val,
+ bool *change, bool async, bool force)
{
WARN_ONCE(1, "regmap API is disabled");
return -EINVAL;