/* * Sometimes for failures during very early init the trace * infrastructure isn't available early enough to be used. For this * sort of problem defining LOG_DEVICE will add printks for basic * register I/O on a specific device.
*/ #undef LOG_DEVICE
staticvoid dev_get_regmap_release(struct device *dev, void *res)
{ /* * We don't actually have anything to do here; the goal here * is not to manage the regmap but to provide a simple way to * get the regmap back given a struct device.
*/
}
/* Retrieve the endianness specification from the regmap config */
endian = config->val_format_endian;
/* If the regmap config specified a non-default value, use that */ if (endian != REGMAP_ENDIAN_DEFAULT) return endian;
/* If the firmware node exist try to get endianness from it */ if (fwnode_property_read_bool(fwnode, "big-endian"))
endian = REGMAP_ENDIAN_BIG; elseif (fwnode_property_read_bool(fwnode, "little-endian"))
endian = REGMAP_ENDIAN_LITTLE; elseif (fwnode_property_read_bool(fwnode, "native-endian"))
endian = REGMAP_ENDIAN_NATIVE;
/* If the endianness was specified in fwnode, use that */ if (endian != REGMAP_ENDIAN_DEFAULT) return endian;
/* Retrieve the endianness specification from the bus config */ if (bus && bus->val_format_endian_default)
endian = bus->val_format_endian_default;
/* If the bus specified a non-default value, use that */ if (endian != REGMAP_ENDIAN_DEFAULT) return endian;
/* Use this if no other value was found */ return REGMAP_ENDIAN_BIG;
}
EXPORT_SYMBOL_GPL(regmap_get_val_endian);
struct regmap *__regmap_init(struct device *dev, conststruct regmap_bus *bus, void *bus_context, conststruct regmap_config *config, struct lock_class_key *lock_key, constchar *lock_name)
{ struct regmap *map; int ret = -EINVAL; enum regmap_endian reg_endian, val_endian; int i, j;
if (!config) goto err;
map = kzalloc(sizeof(*map), GFP_KERNEL); if (map == NULL) {
ret = -ENOMEM; goto err;
}
ret = regmap_set_name(map, config); if (ret) goto err_map;
ret = -EINVAL; /* Later error paths rely on this */
map->range_tree = RB_ROOT; for (i = 0; i < config->num_ranges; i++) { conststruct regmap_range_cfg *range_cfg = &config->ranges[i]; struct regmap_range_node *new;
/* Sanity check */ if (range_cfg->range_max < range_cfg->range_min) {
dev_err(map->dev, "Invalid range %d: %u < %u\n", i,
range_cfg->range_max, range_cfg->range_min); goto err_range;
}
if (range_cfg->range_max > map->max_register) {
dev_err(map->dev, "Invalid range %d: %u > %u\n", i,
range_cfg->range_max, map->max_register); goto err_range;
}
if (range_cfg->selector_reg > map->max_register) {
dev_err(map->dev, "Invalid range %d: selector out of map\n", i); goto err_range;
}
if (range_cfg->window_len == 0) {
dev_err(map->dev, "Invalid range %d: window_len 0\n",
i); goto err_range;
}
/* Make sure, that this register range has no selector
or data window within its boundary */ for (j = 0; j < config->num_ranges; j++) { unsignedint sel_reg = config->ranges[j].selector_reg; unsignedint win_min = config->ranges[j].window_start; unsignedint win_max = win_min +
config->ranges[j].window_len - 1;
/* Allow data window inside its own virtual range */ if (j == i) continue;
if (range_cfg->range_min <= sel_reg &&
sel_reg <= range_cfg->range_max) {
dev_err(map->dev, "Range %d: selector for %d in window\n",
i, j); goto err_range;
}
if (!(win_max < range_cfg->range_min ||
win_min > range_cfg->range_max)) {
dev_err(map->dev, "Range %d: window for %d in window\n",
i, j); goto err_range;
}
}
new = kzalloc(sizeof(*new), GFP_KERNEL); if (new == NULL) {
ret = -ENOMEM; goto err_range;
}
/** * devm_regmap_field_alloc() - Allocate and initialise a register field. * * @dev: Device that will be interacted with * @regmap: regmap bank in which this register field is located. * @reg_field: Register field with in the bank. * * The return value will be an ERR_PTR() on error or a valid pointer * to a struct regmap_field. The regmap_field will be automatically freed * by the device management code.
*/ struct regmap_field *devm_regmap_field_alloc(struct device *dev, struct regmap *regmap, struct reg_field reg_field)
{ struct regmap_field *rm_field = devm_kzalloc(dev, sizeof(*rm_field), GFP_KERNEL); if (!rm_field) return ERR_PTR(-ENOMEM);
regmap_field_init(rm_field, regmap, reg_field);
return rm_field;
}
EXPORT_SYMBOL_GPL(devm_regmap_field_alloc);
/** * regmap_field_bulk_alloc() - Allocate and initialise a bulk register field. * * @regmap: regmap bank in which this register field is located. * @rm_field: regmap register fields within the bank. * @reg_field: Register fields within the bank. * @num_fields: Number of register fields. * * The return value will be an -ENOMEM on error or zero for success. * Newly allocated regmap_fields should be freed by calling * regmap_field_bulk_free()
*/ int regmap_field_bulk_alloc(struct regmap *regmap, struct regmap_field **rm_field, conststruct reg_field *reg_field, int num_fields)
{ struct regmap_field *rf; int i;
rf = kcalloc(num_fields, sizeof(*rf), GFP_KERNEL); if (!rf) return -ENOMEM;
for (i = 0; i < num_fields; i++) {
regmap_field_init(&rf[i], regmap, reg_field[i]);
rm_field[i] = &rf[i];
}
/** * devm_regmap_field_bulk_alloc() - Allocate and initialise a bulk register * fields. * * @dev: Device that will be interacted with * @regmap: regmap bank in which this register field is located. * @rm_field: regmap register fields within the bank. * @reg_field: Register fields within the bank. * @num_fields: Number of register fields. * * The return value will be an -ENOMEM on error or zero for success. * Newly allocated regmap_fields will be automatically freed by the * device management code.
*/ int devm_regmap_field_bulk_alloc(struct device *dev, struct regmap *regmap, struct regmap_field **rm_field, conststruct reg_field *reg_field, int num_fields)
{ struct regmap_field *rf; int i;
rf = devm_kcalloc(dev, num_fields, sizeof(*rf), GFP_KERNEL); if (!rf) return -ENOMEM;
for (i = 0; i < num_fields; i++) {
regmap_field_init(&rf[i], regmap, reg_field[i]);
rm_field[i] = &rf[i];
}
/** * regmap_field_bulk_free() - Free register field allocated using * regmap_field_bulk_alloc. * * @field: regmap fields which should be freed.
*/ void regmap_field_bulk_free(struct regmap_field *field)
{
kfree(field);
}
EXPORT_SYMBOL_GPL(regmap_field_bulk_free);
/** * devm_regmap_field_bulk_free() - Free a bulk register field allocated using * devm_regmap_field_bulk_alloc. * * @dev: Device that will be interacted with * @field: regmap field which should be freed. * * Free register field allocated using devm_regmap_field_bulk_alloc(). Usually * drivers need not call this function, as the memory allocated via devm * will be freed as per device-driver life-cycle.
*/ void devm_regmap_field_bulk_free(struct device *dev, struct regmap_field *field)
{
devm_kfree(dev, field);
}
EXPORT_SYMBOL_GPL(devm_regmap_field_bulk_free);
/** * devm_regmap_field_free() - Free a register field allocated using * devm_regmap_field_alloc. * * @dev: Device that will be interacted with * @field: regmap field which should be freed. * * Free register field allocated using devm_regmap_field_alloc(). Usually * drivers need not call this function, as the memory allocated via devm * will be freed as per device-driver life-cyle.
*/ void devm_regmap_field_free(struct device *dev, struct regmap_field *field)
{
devm_kfree(dev, field);
}
EXPORT_SYMBOL_GPL(devm_regmap_field_free);
/** * regmap_field_alloc() - Allocate and initialise a register field. * * @regmap: regmap bank in which this register field is located. * @reg_field: Register field with in the bank. * * The return value will be an ERR_PTR() on error or a valid pointer * to a struct regmap_field. The regmap_field should be freed by the * user once its finished working with it using regmap_field_free().
*/ struct regmap_field *regmap_field_alloc(struct regmap *regmap, struct reg_field reg_field)
{ struct regmap_field *rm_field = kzalloc(sizeof(*rm_field), GFP_KERNEL);
/** * regmap_field_free() - Free register field allocated using * regmap_field_alloc. * * @field: regmap field which should be freed.
*/ void regmap_field_free(struct regmap_field *field)
{
kfree(field);
}
EXPORT_SYMBOL_GPL(regmap_field_free);
/** * regmap_reinit_cache() - Reinitialise the current register cache * * @map: Register map to operate on. * @config: New configuration. Only the cache data will be used. * * Discard any existing register cache for the map and initialize a * new cache. This can be used to restore the cache to defaults or to * update the cache configuration to reflect runtime discovery of the * hardware. * * No explicit locking is done here, the user needs to ensure that * this function will not race with other calls to regmap.
*/ int regmap_reinit_cache(struct regmap *map, conststruct regmap_config *config)
{ int ret;
/* If the user didn't specify a name match any */ if (data) return (*r)->name && !strcmp((*r)->name, data); else return 1;
}
/** * dev_get_regmap() - Obtain the regmap (if any) for a device * * @dev: Device to retrieve the map for * @name: Optional name for the register map, usually NULL. * * Returns the regmap for the device if one is present, or NULL. If * name is specified then it must match the name specified when * registering the device, if it is NULL then the first regmap found * will be used. Devices with multiple register maps are very rare, * generic code should normally not need to specify a name.
*/ struct regmap *dev_get_regmap(struct device *dev, constchar *name)
{ struct regmap **r = devres_find(dev, dev_get_regmap_release,
dev_get_regmap_match, (void *)name);
if (!r) return NULL; return *r;
}
EXPORT_SYMBOL_GPL(dev_get_regmap);
/** * regmap_get_device() - Obtain the device from a regmap * * @map: Register map to operate on. * * Returns the underlying device that the regmap has been created for.
*/ struct device *regmap_get_device(struct regmap *map)
{ return map->dev;
}
EXPORT_SYMBOL_GPL(regmap_get_device);
if (val_num > 1) { /* Bulk write shouldn't cross range boundary */ if (*reg + val_num - 1 > range->range_max) return -EINVAL;
/* ... or single page boundary */ if (val_num > range->window_len - win_offset) return -EINVAL;
}
/* It is possible to have selector register inside data window. In that case, selector register is located on every page and
it needs no page switching, when accessed alone. */ if (val_num > 1 ||
range->window_start + win_offset != range->selector_reg) { /* Use separate work_buf during page switching */
orig_work_buf = map->work_buf;
map->work_buf = map->selector_work_buf;
ret = _regmap_update_bits(map, range->selector_reg,
range->selector_mask,
win_page << range->selector_shift,
&page_chg, false);
map->work_buf = orig_work_buf;
if (ret != 0) return ret;
}
*reg = range->window_start + win_offset;
return 0;
}
staticvoid regmap_set_work_buf_flag_mask(struct regmap *map, int max_bytes, unsignedlong mask)
{
u8 *buf; int i;
if (!mask || !map->work_buf) return;
buf = map->work_buf;
for (i = 0; i < max_bytes; i++)
buf[i] |= (mask >> (8 * i)) & 0xff;
}
/* Check for unwritable or noinc registers in range * before we start
*/ if (!regmap_writeable_noinc(map, reg)) { for (i = 0; i < val_len / map->format.val_bytes; i++) { unsignedint element =
reg + regmap_get_offset(map, i); if (!regmap_writeable(map, element) ||
regmap_writeable_noinc(map, element)) return -EINVAL;
}
}
if (!map->cache_bypass && map->format.parse_val) { unsignedint ival, offset; int val_bytes = map->format.val_bytes;
/* Cache the last written value for noinc writes */
i = noinc ? val_len - val_bytes : 0; for (; i < val_len; i += val_bytes) {
ival = map->format.parse_val(val + i);
offset = noinc ? 0 : regmap_get_offset(map, i / val_bytes);
ret = regcache_write(map, reg + offset, ival); if (ret) {
dev_err(map->dev, "Error in caching of register: %x ret: %d\n",
reg + offset, ret); return ret;
}
} if (map->cache_only) {
map->cache_dirty = true; return 0;
}
}
range = _regmap_range_lookup(map, reg); if (range) { int val_num = val_len / map->format.val_bytes; int win_offset = (reg - range->range_min) % range->window_len; int win_residue = range->window_len - win_offset;
/* If the write goes beyond the end of the window split it */ while (val_num > win_residue) {
dev_dbg(map->dev, "Writing window %d/%zu\n",
win_residue, val_len / map->format.val_bytes);
ret = _regmap_raw_write_impl(map, reg, val,
win_residue *
map->format.val_bytes, noinc); if (ret != 0) return ret;
/* * Essentially all I/O mechanisms will be faster with a single * buffer to write. Since register syncs often generate raw * writes of single registers optimise that case.
*/ if (val != work_val && val_len == map->format.val_bytes) {
memcpy(work_val, val, map->format.val_bytes);
val = work_val;
}
if (map->async && map->bus && map->bus->async_write) { struct regmap_async *async;
/* If the caller supplied the value we can use it safely. */
memcpy(async->work_buf, map->work_buf, map->format.pad_bytes +
map->format.reg_bytes + map->format.val_bytes);
/* If we're doing a single register write we can probably just * send the work_buf directly, otherwise try to do a gather * write.
*/ if (val == work_val)
ret = map->write(map->bus_context, map->work_buf,
map->format.reg_bytes +
map->format.pad_bytes +
val_len); elseif (map->bus && map->bus->gather_write)
ret = map->bus->gather_write(map->bus_context, map->work_buf,
map->format.reg_bytes +
map->format.pad_bytes,
val, val_len); else
ret = -ENOTSUPP;
/* If that didn't work fall back on linearising by hand. */ if (ret == -ENOTSUPP) {
len = map->format.reg_bytes + map->format.pad_bytes + val_len;
buf = kzalloc(len, GFP_KERNEL); if (!buf) return -ENOMEM;
/** * regmap_can_raw_write - Test if regmap_raw_write() is supported * * @map: Map to check.
*/ bool regmap_can_raw_write(struct regmap *map)
{ return map->write && map->format.format_val && map->format.format_reg;
}
EXPORT_SYMBOL_GPL(regmap_can_raw_write);
/** * regmap_get_raw_read_max - Get the maximum size we can read * * @map: Map to check.
*/
size_t regmap_get_raw_read_max(struct regmap *map)
{ return map->max_raw_read;
}
EXPORT_SYMBOL_GPL(regmap_get_raw_read_max);
/** * regmap_get_raw_write_max - Get the maximum size we can read * * @map: Map to check.
*/
size_t regmap_get_raw_write_max(struct regmap *map)
{ return map->max_raw_write;
}
EXPORT_SYMBOL_GPL(regmap_get_raw_write_max);
int _regmap_write(struct regmap *map, unsignedint reg, unsignedint val)
{ int ret; void *context = _regmap_map_get_context(map);
if (!regmap_writeable(map, reg)) return -EIO;
if (!map->cache_bypass && !map->defer_caching) {
ret = regcache_write(map, reg, val); if (ret != 0) return ret; if (map->cache_only) {
map->cache_dirty = true; return 0;
}
}
ret = map->reg_write(context, reg, val); if (ret == 0) { if (regmap_should_log(map))
dev_info(map->dev, "%x <= %x\n", reg, val);
trace_regmap_reg_write(map, reg, val);
}
return ret;
}
/** * regmap_write() - Write a value to a single register * * @map: Register map to write to * @reg: Register 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_write(struct regmap *map, unsignedint reg, unsignedint val)
{ int ret;
if (!IS_ALIGNED(reg, map->reg_stride)) return -EINVAL;
map->lock(map->lock_arg);
ret = _regmap_write(map, reg, val);
map->unlock(map->lock_arg);
return ret;
}
EXPORT_SYMBOL_GPL(regmap_write);
/** * regmap_write_async() - Write a value to a single register asynchronously * * @map: Register map to write to * @reg: Register 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_write_async(struct regmap *map, unsignedint reg, unsignedint val)
{ int ret;
if (!IS_ALIGNED(reg, map->reg_stride)) return -EINVAL;
/* Write as many bytes as possible with chunk_size */ for (i = 0; i < chunk_count; i++) {
ret = _regmap_raw_write_impl(map, reg, val, chunk_bytes, noinc); if (ret) return ret;
/* Write remaining bytes */ if (val_len)
ret = _regmap_raw_write_impl(map, reg, val, val_len, noinc);
return ret;
}
/** * regmap_raw_write() - Write raw values to one or more registers * * @map: Register map to write to * @reg: Initial register to write to * @val: Block of data to be written, laid out for direct transmission to the * device * @val_len: Length of data pointed to by val. * * This function is intended to be used for things like firmware * download where a large block of data needs to be transferred to the * device. No formatting will be done on the data provided. * * A value of zero will be returned on success, a negative errno will * be returned in error cases.
*/ int regmap_raw_write(struct regmap *map, unsignedint reg, constvoid *val, size_t val_len)
{ int ret;
if (!regmap_can_raw_write(map)) return -EINVAL; if (val_len % map->format.val_bytes) return -EINVAL;
map->lock(map->lock_arg);
ret = _regmap_raw_write(map, reg, val, val_len, false);
switch (val_bytes) { case 1:
u8p = val; if (write)
lastval = (unsignedint)u8p[val_count - 1]; break; case 2:
u16p = val; if (write)
lastval = (unsignedint)u16p[val_count - 1]; break; case 4:
u32p = val; if (write)
lastval = (unsignedint)u32p[val_count - 1]; break; default: return -EINVAL;
}
/* * Update the cache with the last value we write, the rest is just * gone down in the hardware FIFO. We can't cache FIFOs. This makes * sure a single read from the cache will work.
*/ if (write) { if (!map->cache_bypass && !map->defer_caching) {
ret = regcache_write(map, reg, lastval); if (ret != 0) return ret; if (map->cache_only) {
map->cache_dirty = true; return 0;
}
}
ret = map->bus->reg_noinc_write(map->bus_context, reg, val, val_count);
} else {
ret = map->bus->reg_noinc_read(map->bus_context, reg, val, val_count);
}
if (!ret && regmap_should_log(map)) {
dev_info(map->dev, "%x %s [", reg, write ? "<=" : "=>"); for (i = 0; i < val_count; i++) { switch (val_bytes) { case 1:
pr_cont("%x", u8p[i]); break; case 2:
pr_cont("%x", u16p[i]); break; case 4:
pr_cont("%x", u32p[i]); break; default: break;
} if (i == (val_count - 1))
pr_cont("]\n"); else
pr_cont(",");
}
}
return 0;
}
/** * regmap_noinc_write(): Write data to a register without incrementing the * register number * * @map: Register map to write to * @reg: Register to write to * @val: Pointer to data buffer * @val_len: Length of output buffer in bytes. * * The regmap API usually assumes that bulk bus write operations will write a * range of registers. Some devices have certain registers for which a write * operation can write to an internal FIFO. * * The target register must be volatile but registers after it can be * completely unrelated cacheable registers. * * This will attempt multiple writes as required to write val_len bytes. * * A value of zero will be returned on success, a negative errno will be * returned in error cases.
*/ int regmap_noinc_write(struct regmap *map, unsignedint reg, constvoid *val, size_t val_len)
{
size_t write_len; int ret;
if (!map->write && !(map->bus && map->bus->reg_noinc_write)) return -EINVAL; if (val_len % map->format.val_bytes) return -EINVAL; if (!IS_ALIGNED(reg, map->reg_stride)) return -EINVAL; if (val_len == 0) return -EINVAL;
map->lock(map->lock_arg);
if (!regmap_volatile(map, reg) || !regmap_writeable_noinc(map, reg)) {
ret = -EINVAL; goto out_unlock;
}
/* * Use the accelerated operation if we can. The val drops the const * typing in order to facilitate code reuse in regmap_noinc_readwrite().
*/ if (map->bus->reg_noinc_write) {
ret = regmap_noinc_readwrite(map, reg, (void *)val, val_len, true); goto out_unlock;
}
while (val_len) { if (map->max_raw_write && map->max_raw_write < val_len)
write_len = map->max_raw_write; else
write_len = val_len;
ret = _regmap_raw_write(map, reg, val, write_len, true); if (ret) goto out_unlock;
val = ((u8 *)val) + write_len;
val_len -= write_len;
}
/** * regmap_field_update_bits_base() - Perform a read/modify/write cycle a * register field. * * @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 * * Perform a read/modify/write cycle on the register field with change, * async, force option. * * A value of zero will be returned on success, a negative errno will * be returned in error cases.
*/ int regmap_field_update_bits_base(struct regmap_field *field, unsignedint mask, unsignedint val, bool *change, bool async, bool force)
{
mask = (mask << field->shift) & field->mask;
/** * regmap_field_test_bits() - Check if all specified bits are set in a * register field. * * @field: Register field to operate on * @bits: Bits to test * * Returns -1 if the underlying regmap_field_read() fails, 0 if at least one of the * tested bits is not set and 1 if all tested bits are set.
*/ int regmap_field_test_bits(struct regmap_field *field, unsignedint bits)
{ unsignedint val, ret;
ret = regmap_field_read(field, &val); if (ret) return ret;
/** * regmap_fields_update_bits_base() - Perform a read/modify/write cycle a * register field with port ID * * @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_base(struct regmap_field *field, unsignedint id, unsignedint mask, unsignedint val, bool *change, bool async, bool force)
{ if (id >= field->id_size) return -EINVAL;
/** * regmap_bulk_write() - Write multiple registers to the device * * @map: Register map to write to * @reg: First register to be write from * @val: Block of data to be written, in native register size for device * @val_count: Number of registers to write * * This function is intended to be used for writing a large block of * data to the device either in single transfer or multiple transfer. * * A value of zero will be returned on success, a negative errno will * be returned in error cases.
*/ int regmap_bulk_write(struct regmap *map, unsignedint reg, constvoid *val,
size_t val_count)
{ int ret = 0, i;
size_t val_bytes = map->format.val_bytes;
if (!IS_ALIGNED(reg, map->reg_stride)) return -EINVAL;
/* * Some devices don't support bulk write, for them we have a series of * single write operations.
*/ if (!map->write || !map->format.parse_inplace) {
map->lock(map->lock_arg); for (i = 0; i < val_count; i++) { unsignedint ival;
switch (val_bytes) { case 1:
ival = *(u8 *)(val + (i * val_bytes)); break; case 2:
ival = *(u16 *)(val + (i * val_bytes)); break; case 4:
ival = *(u32 *)(val + (i * val_bytes)); break; default:
ret = -EINVAL; goto out;
}
/* * _regmap_raw_multi_reg_write() * * the (register,newvalue) pairs in regs have not been formatted, but * they are all in the same page and have been changed to being page * relative. The page register has been written if that was necessary.
*/ staticint _regmap_raw_multi_reg_write(struct regmap *map, conststruct reg_sequence *regs,
size_t num_regs)
{ int ret; void *buf; int i;
u8 *u8;
size_t val_bytes = map->format.val_bytes;
size_t reg_bytes = map->format.reg_bytes;
size_t pad_bytes = map->format.pad_bytes;
size_t pair_size = reg_bytes + pad_bytes + val_bytes;
size_t len = pair_size * num_regs;
if (!len) return -EINVAL;
buf = kzalloc(len, GFP_KERNEL); if (!buf) return -ENOMEM;
staticint _regmap_range_multi_paged_reg_write(struct regmap *map, struct reg_sequence *regs,
size_t num_regs)
{ int ret; int i, n; struct reg_sequence *base; unsignedint this_page = 0; unsignedint page_change = 0; /* * the set of registers are not neccessarily in order, but * since the order of write must be preserved this algorithm * chops the set each time the page changes. This also applies * if there is a delay required at any point in the sequence.
*/
base = regs; for (i = 0, n = 0; i < num_regs; i++, n++) { unsignedint reg = regs[i].reg; struct regmap_range_node *range;
range = _regmap_range_lookup(map, reg); if (range) { unsignedint win_page = _regmap_register_page(map, reg,
range);
if (i == 0)
this_page = win_page; if (win_page != this_page) {
this_page = win_page;
page_change = 1;
}
}
/* If we have both a page change and a delay make sure to * write the regs and apply the delay before we change the * page.
*/
if (page_change || regs[i].delay_us) {
/* For situations where the first write requires * a delay we need to make sure we don't call * raw_multi_reg_write with n=0 * This can't occur with page breaks as we * never write on the first iteration
*/ if (regs[i].delay_us && i == 0)
n = 1;
ret = _regmap_raw_multi_reg_write(map, base, n); if (ret != 0) return ret;
if (regs[i].delay_us) { if (map->can_sleep)
fsleep(regs[i].delay_us); else
udelay(regs[i].delay_us);
}
base += n;
n = 0;
if (page_change) {
ret = _regmap_select_page(map,
&base[n].reg,
range, 1); if (ret != 0) return ret;
staticint _regmap_multi_reg_write(struct regmap *map, conststruct reg_sequence *regs,
size_t num_regs)
{ int i; int ret;
if (!map->can_multi_write) { for (i = 0; i < num_regs; i++) {
ret = _regmap_write(map, regs[i].reg, regs[i].def); if (ret != 0) return ret;
if (regs[i].delay_us) { if (map->can_sleep)
fsleep(regs[i].delay_us); else
udelay(regs[i].delay_us);
}
} return 0;
}
if (!map->format.parse_inplace) return -EINVAL;
if (map->writeable_reg) for (i = 0; i < num_regs; i++) { int reg = regs[i].reg; if (!map->writeable_reg(map->dev, reg)) return -EINVAL; if (!IS_ALIGNED(reg, map->reg_stride)) return -EINVAL;
}
if (!map->cache_bypass) { for (i = 0; i < num_regs; i++) { unsignedint val = regs[i].def; unsignedint reg = regs[i].reg;
ret = regcache_write(map, reg, val); if (ret) {
dev_err(map->dev, "Error in caching of register: %x ret: %d\n",
reg, ret); return ret;
}
} if (map->cache_only) {
map->cache_dirty = true; return 0;
}
}
WARN_ON(!map->bus);
for (i = 0; i < num_regs; i++) { unsignedint reg = regs[i].reg; struct regmap_range_node *range;
/* Coalesce all the writes between a page break or a delay * in a sequence
*/
range = _regmap_range_lookup(map, reg); if (range || regs[i].delay_us) {
size_t len = sizeof(struct reg_sequence)*num_regs; struct reg_sequence *base = kmemdup(regs, len,
GFP_KERNEL); if (!base) return -ENOMEM;
ret = _regmap_range_multi_paged_reg_write(map, base,
num_regs);
kfree(base);
/** * regmap_multi_reg_write() - Write multiple registers to the device * * @map: Register map to write to * @regs: Array of structures containing register,value to be written * @num_regs: Number of registers to write * * Write multiple registers to the device where the set of register, value * pairs are supplied in any order, possibly not all in a single range. * * The 'normal' block write mode will send ultimately send data on the * target bus as R,V1,V2,V3,..,Vn where successively higher registers are * addressed. However, this alternative block multi write mode will send * the data as R1,V1,R2,V2,..,Rn,Vn on the target bus. The target device * must of course support the mode. * * A value of zero will be returned on success, a negative errno will be * returned in error cases.
*/
--> --------------------
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.