Newer
Older
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
* device. No formatting will be done on the data provided.
*
* If supported by the underlying bus the write will be scheduled
* asynchronously, helping maximise I/O speed on higher speed buses
* like SPI. regmap_async_complete() can be called to ensure that all
* asynchrnous writes have been completed.
*
* A value of zero will be returned on success, a negative errno will
* be returned in error cases.
*/
int regmap_raw_write_async(struct regmap *map, unsigned int reg,
const void *val, size_t val_len)
{
int ret;
if (val_len % map->format.val_bytes)
return -EINVAL;
if (reg % map->reg_stride)
return -EINVAL;
map->lock(map->lock_arg);
map->async = true;
ret = _regmap_raw_write(map, reg, val, val_len);
map->async = false;
map->unlock(map->lock_arg);
return ret;
}
EXPORT_SYMBOL_GPL(regmap_raw_write_async);
static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
unsigned int val_len)
{
struct regmap_range_node *range;
u8 *u8 = map->work_buf;
int ret;
range = _regmap_range_lookup(map, reg);
if (range) {
ret = _regmap_select_page(map, ®, range,
val_len / map->format.val_bytes);
map->format.format_reg(map->work_buf, reg, map->reg_shift);
* Some buses or devices flag reads by setting the high bits in the
* register addresss; since it's always the high bits for all
* current formats we can do this here rather than in
* formatting. This may break if we get interesting formats.
*/
u8[0] |= map->read_flag_mask;
trace_regmap_hw_read_start(map, reg, val_len / map->format.val_bytes);
ret = map->bus->read(map->bus_context, map->work_buf,
map->format.reg_bytes + map->format.pad_bytes,
trace_regmap_hw_read_done(map, reg, val_len / map->format.val_bytes);
static int _regmap_bus_reg_read(void *context, unsigned int reg,
unsigned int *val)
{
struct regmap *map = context;
return map->bus->reg_read(map->bus_context, reg, val);
}
static int _regmap_bus_read(void *context, unsigned int reg,
unsigned int *val)
{
int ret;
struct regmap *map = context;
if (!map->format.parse_val)
return -EINVAL;
ret = _regmap_raw_read(map, reg, map->work_buf, map->format.val_bytes);
if (ret == 0)
*val = map->format.parse_val(map->work_buf);
return ret;
}
static int _regmap_read(struct regmap *map, unsigned int reg,
unsigned int *val)
{
int ret;
void *context = _regmap_map_get_context(map);
if (!map->cache_bypass) {
ret = regcache_read(map, reg, val);
if (ret == 0)
return 0;
}
if (map->cache_only)
return -EBUSY;
if (!regmap_readable(map, reg))
return -EIO;
ret = map->reg_read(context, reg, val);
#ifdef LOG_DEVICE
if (map->dev && strcmp(dev_name(map->dev), LOG_DEVICE) == 0)
dev_info(map->dev, "%x => %x\n", reg, *val);
#endif
trace_regmap_reg_read(map, reg, *val);
if (!map->cache_bypass)
regcache_write(map, reg, *val);
}
return ret;
}
/**
* regmap_read(): Read a value from a single register
*
* @map: Register map to read from
* @reg: Register to be read from
* @val: Pointer to store read value
*
* A value of zero will be returned on success, a negative errno will
* be returned in error cases.
*/
int regmap_read(struct regmap *map, unsigned int reg, unsigned int *val)
{
int ret;
if (reg % map->reg_stride)
return -EINVAL;
map->lock(map->lock_arg);
ret = _regmap_read(map, reg, val);
map->unlock(map->lock_arg);
return ret;
}
EXPORT_SYMBOL_GPL(regmap_read);
/**
* regmap_raw_read(): Read raw data from the device
*
* @map: Register map to read from
* @reg: First register to be read from
* @val: Pointer to store read value
* @val_len: Size of data to read
*
* A value of zero will be returned on success, a negative errno will
* be returned in error cases.
*/
int regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
size_t val_len)
{
size_t val_bytes = map->format.val_bytes;
size_t val_count = val_len / val_bytes;
unsigned int v;
int ret, i;
if (!map->bus)
return -EINVAL;
if (val_len % map->format.val_bytes)
return -EINVAL;
if (reg % map->reg_stride)
return -EINVAL;
map->lock(map->lock_arg);
if (regmap_volatile_range(map, reg, val_count) || map->cache_bypass ||
map->cache_type == REGCACHE_NONE) {
/* Physical block read if there's no cache involved */
ret = _regmap_raw_read(map, reg, val, val_len);
} else {
/* Otherwise go word by word for the cache; should be low
* cost as we expect to hit the cache.
*/
for (i = 0; i < val_count; i++) {
ret = _regmap_read(map, reg + (i * map->reg_stride),
&v);
if (ret != 0)
goto out;
map->format.format_val(val + (i * val_bytes), v, 0);
map->unlock(map->lock_arg);
return ret;
}
EXPORT_SYMBOL_GPL(regmap_raw_read);
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
/**
* regmap_field_read(): Read a value to a single register field
*
* @field: Register field to read from
* @val: Pointer to store read value
*
* A value of zero will be returned on success, a negative errno will
* be returned in error cases.
*/
int regmap_field_read(struct regmap_field *field, unsigned int *val)
{
int ret;
unsigned int reg_val;
ret = regmap_read(field->regmap, field->reg, ®_val);
if (ret != 0)
return ret;
reg_val &= field->mask;
reg_val >>= field->shift;
*val = reg_val;
return ret;
}
EXPORT_SYMBOL_GPL(regmap_field_read);
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
/**
* regmap_fields_read(): Read a value to a single register field with port ID
*
* @field: Register field to read from
* @id: port ID
* @val: Pointer to store read value
*
* A value of zero will be returned on success, a negative errno will
* be returned in error cases.
*/
int regmap_fields_read(struct regmap_field *field, unsigned int id,
unsigned int *val)
{
int ret;
unsigned int reg_val;
if (id >= field->id_size)
return -EINVAL;
ret = regmap_read(field->regmap,
field->reg + (field->id_offset * id),
®_val);
if (ret != 0)
return ret;
reg_val &= field->mask;
reg_val >>= field->shift;
*val = reg_val;
return ret;
}
EXPORT_SYMBOL_GPL(regmap_fields_read);
/**
* regmap_bulk_read(): Read multiple registers from the device
*
* @map: Register map to read from
* @reg: First register to be read from
* @val: Pointer to store read value, in native register size for device
* @val_count: Number of registers to read
*
* A value of zero will be returned on success, a negative errno will
* be returned in error cases.
*/
int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val,
size_t val_count)
{
int ret, i;
size_t val_bytes = map->format.val_bytes;
Lars-Peter Clausen
committed
bool vol = regmap_volatile_range(map, reg, val_count);
if (reg % map->reg_stride)
return -EINVAL;
if (map->bus && map->format.parse_inplace && (vol || map->cache_type == REGCACHE_NONE)) {
/*
* Some devices does not support bulk read, for
* them we have a series of single read operations.
*/
if (map->use_single_rw) {
for (i = 0; i < val_count; i++) {
ret = regmap_raw_read(map,
reg + (i * map->reg_stride),
val + (i * val_bytes),
val_bytes);
if (ret != 0)
return ret;
}
} else {
ret = regmap_raw_read(map, reg, val,
val_bytes * val_count);
if (ret != 0)
return ret;
}
for (i = 0; i < val_count * val_bytes; i += val_bytes)
map->format.parse_inplace(val + i);
} else {
for (i = 0; i < val_count; i++) {
unsigned int ival;
ret = regmap_read(map, reg + (i * map->reg_stride),
if (ret != 0)
return ret;
map->format.format_val(val + (i * val_bytes), ival, 0);
return 0;
}
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)
unsigned int tmp, orig;
ret = _regmap_read(map, reg, &orig);
return ret;
tmp |= val & mask;
if (tmp != orig) {
ret = _regmap_write(map, reg, tmp);
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);
map->unlock(map->lock_arg);
return ret;
EXPORT_SYMBOL_GPL(regmap_update_bits);
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
/**
* 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);
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);
map->unlock(map->lock_arg);
return ret;
}
EXPORT_SYMBOL_GPL(regmap_update_bits_check);
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
/**
* regmap_update_bits_check_async: Perform a read/modify/write cycle on the
* register map asynchronously 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
*
* 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 ret;
map->lock(map->lock_arg);
map->async = true;
ret = _regmap_update_bits(map, reg, mask, val, change);
map->async = false;
map->unlock(map->lock_arg);
return ret;
}
EXPORT_SYMBOL_GPL(regmap_update_bits_check_async);
void regmap_async_complete_cb(struct regmap_async *async, int ret)
{
struct regmap *map = async->map;
bool wake;
trace_regmap_async_io_complete(map);
list_move(&async->list, &map->async_free);
wake = list_empty(&map->async_list);
if (ret != 0)
map->async_ret = ret;
spin_unlock(&map->async_lock);
if (wake)
wake_up(&map->async_waitq);
}
EXPORT_SYMBOL_GPL(regmap_async_complete_cb);
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
static int regmap_async_is_done(struct regmap *map)
{
unsigned long flags;
int ret;
spin_lock_irqsave(&map->async_lock, flags);
ret = list_empty(&map->async_list);
spin_unlock_irqrestore(&map->async_lock, flags);
return ret;
}
/**
* regmap_async_complete: Ensure all asynchronous I/O has completed.
*
* @map: Map to operate on.
*
* Blocks until any pending asynchronous I/O has completed. Returns
* an error code for any failed I/O operations.
*/
int regmap_async_complete(struct regmap *map)
{
unsigned long flags;
int ret;
/* Nothing to do with no async support */
if (!map->bus || !map->bus->async_write)
trace_regmap_async_complete_start(map);
wait_event(map->async_waitq, regmap_async_is_done(map));
spin_lock_irqsave(&map->async_lock, flags);
ret = map->async_ret;
map->async_ret = 0;
spin_unlock_irqrestore(&map->async_lock, flags);
trace_regmap_async_complete_done(map);
EXPORT_SYMBOL_GPL(regmap_async_complete);
/**
* regmap_register_patch: Register and apply register updates to be applied
* on device initialistion
*
* @map: Register map to apply updates to.
* @regs: Values to update.
* @num_regs: Number of entries in regs.
*
* Register a set of register updates to be applied to the device
* whenever the device registers are synchronised with the cache and
* apply them immediately. Typically this is used to apply
* corrections to be applied to the device defaults on startup, such
* as the updates some vendors provide to undocumented registers.
*
* 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 num_regs)
{
int ret;
if (WARN_ONCE(num_regs <= 0, "invalid registers number (%d)\n",
num_regs))
return 0;
p = krealloc(map->patch,
sizeof(struct reg_default) * (map->patch_regs + num_regs),
GFP_KERNEL);
if (p) {
memcpy(p + map->patch_regs, regs, num_regs * sizeof(*regs));
map->patch = p;
map->patch_regs += num_regs;
return -ENOMEM;
map->lock(map->lock_arg);
bypass = map->cache_bypass;
map->cache_bypass = true;
ret = _regmap_multi_reg_write(map, regs, num_regs);
map->unlock(map->lock_arg);
regmap_async_complete(map);
return ret;
}
EXPORT_SYMBOL_GPL(regmap_register_patch);
/*
* regmap_get_val_bytes(): Report the size of a register value
*
* Report the size of a register value, mainly intended to for use by
* generic infrastructure built on top of regmap.
*/
int regmap_get_val_bytes(struct regmap *map)
{
if (map->format.format_write)
return -EINVAL;
return map->format.val_bytes;
}
EXPORT_SYMBOL_GPL(regmap_get_val_bytes);
/**
* regmap_get_max_register(): Report the max register value
*
* Report the max register value, mainly intended to for use by
* generic infrastructure built on top of regmap.
*/
int regmap_get_max_register(struct regmap *map)
{
return map->max_register ? map->max_register : -EINVAL;
}
EXPORT_SYMBOL_GPL(regmap_get_max_register);
/**
* regmap_get_reg_stride(): Report the register address stride
*
* Report the register address stride, mainly intended to for use by
* generic infrastructure built on top of regmap.
*/
int regmap_get_reg_stride(struct regmap *map)
{
return map->reg_stride;
}
EXPORT_SYMBOL_GPL(regmap_get_reg_stride);
int regmap_parse_val(struct regmap *map, const void *buf,
unsigned int *val)
{
if (!map->format.parse_val)
return -EINVAL;
*val = map->format.parse_val(buf);
return 0;
}
EXPORT_SYMBOL_GPL(regmap_parse_val);
static int __init regmap_initcall(void)
{
regmap_debugfs_initcall();
return 0;
}
postcore_initcall(regmap_initcall);