regmap: Changes for v4.3
This has been a busy release for regmap. By far the biggest set of changes here are those from Markus Pargmann which implement support for block transfers in smbus devices. This required quite a bit of refactoring but leaves us better able to handle odd restrictions that controllers may have and with better performance on smbus. Other new features include: - Fix interactions with lockdep for nested regmaps (eg, when a device using regmap is connected to a bus where the bus controller has a separate regmap). Lockdep's default class identification is too crude to work without help. - Support for must write bitfield operations, useful for operations which require writing a bit to trigger them from Kuniori Morimoto. - Support for delaying during register patch application from Nariman Poushin. - Support for overriding cache state via the debugfs implementation from Richard Fitzgerald. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQEcBAABAgAGBQJV6cZyAAoJECTWi3JdVIfQM3sH/RSygzRIOoOuvro0U3qd4+nM qLzpuZNtuAP7xNc5yJZiixz1S6PqUNl+pK/u58s6x10GWDGsWZY6E0Lg94lYmfhA 26jqWSzrMHp42x+ZN7btLExzPTVnvRerrjtj4mqz6t4yun9SzqVymaZTUZ1hqPHB qxSNHs3rHPiqiEWpQKJXb+5dazYYJCbOUrlivxJCk60+ns1N88cA71aY+5/zq5uy 36e0iYe3s+lv0lptedarFCf9p7o1E6EQzhvEMfyquGXtvq8fl7Qdeo7riRFQ8Iiy sygCb3AYuZIiqnOC7+90xkr2Oq0iwdJUD91A9sl/SRiwgItG9jW03bWNHYIhQyk= =CbGt -----END PGP SIGNATURE----- Merge tag 'regmap-v4.3' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap Pull regmap updates from Mark Brown: "This has been a busy release for regmap. By far the biggest set of changes here are those from Markus Pargmann which implement support for block transfers in smbus devices. This required quite a bit of refactoring but leaves us better able to handle odd restrictions that controllers may have and with better performance on smbus. Other new features include: - Fix interactions with lockdep for nested regmaps (eg, when a device using regmap is connected to a bus where the bus controller has a separate regmap). Lockdep's default class identification is too crude to work without help. - Support for must write bitfield operations, useful for operations which require writing a bit to trigger them from Kuniori Morimoto. - Support for delaying during register patch application from Nariman Poushin. - Support for overriding cache state via the debugfs implementation from Richard Fitzgerald" * tag 'regmap-v4.3' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap: (25 commits) regmap: fix a NULL pointer dereference in __regmap_init regmap: Support bulk reads for devices without raw formatting regmap-i2c: Add smbus i2c block support regmap: Add raw_write/read checks for max_raw_write/read sizes regmap: regmap max_raw_read/write getter functions regmap: Introduce max_raw_read/write for regmap_bulk_read/write regmap: Add missing comments about struct regmap_bus regmap: No multi_write support if bus->write does not exist regmap: Split use_single_rw internally into use_single_read/write regmap: Fix regmap_bulk_write for bus writes regmap: regmap_raw_read return error on !bus->read regulator: core: Print at debug level on debugfs creation failure regmap: Fix regmap_can_raw_write check regmap: fix typos in regmap.c regmap: Fix integertypes for register address and value regmap: Move documentation to regmap.h regmap: Use different lockdep class for each regmap init call thermal: sti: Add parentheses around bridge->ops->regmap_init call mfd: vexpress: Add parentheses around bridge->ops->regmap_init call regmap: debugfs: Fix misuse of IS_ENABLED ...
This commit is contained in:
commit
e81b594cda
|
@ -139,11 +139,17 @@ struct regmap {
|
||||||
struct reg_sequence *patch;
|
struct reg_sequence *patch;
|
||||||
int patch_regs;
|
int patch_regs;
|
||||||
|
|
||||||
/* if set, converts bulk rw to single rw */
|
/* if set, converts bulk read to single read */
|
||||||
bool use_single_rw;
|
bool use_single_read;
|
||||||
|
/* if set, converts bulk read to single read */
|
||||||
|
bool use_single_write;
|
||||||
/* if set, the device supports multi write mode */
|
/* if set, the device supports multi write mode */
|
||||||
bool can_multi_write;
|
bool can_multi_write;
|
||||||
|
|
||||||
|
/* if set, raw reads/writes are limited to this size */
|
||||||
|
size_t max_raw_read;
|
||||||
|
size_t max_raw_write;
|
||||||
|
|
||||||
struct rb_root range_tree;
|
struct rb_root range_tree;
|
||||||
void *selector_work_buf; /* Scratch buffer used for selector */
|
void *selector_work_buf; /* Scratch buffer used for selector */
|
||||||
};
|
};
|
||||||
|
|
|
@ -729,7 +729,7 @@ int regcache_sync_block(struct regmap *map, void *block,
|
||||||
unsigned int block_base, unsigned int start,
|
unsigned int block_base, unsigned int start,
|
||||||
unsigned int end)
|
unsigned int end)
|
||||||
{
|
{
|
||||||
if (regmap_can_raw_write(map) && !map->use_single_rw)
|
if (regmap_can_raw_write(map) && !map->use_single_write)
|
||||||
return regcache_sync_block_raw(map, block, cache_present,
|
return regcache_sync_block_raw(map, block, cache_present,
|
||||||
block_base, start, end);
|
block_base, start, end);
|
||||||
else
|
else
|
||||||
|
|
|
@ -78,37 +78,24 @@ static const struct regmap_bus ac97_regmap_bus = {
|
||||||
.reg_read = regmap_ac97_reg_read,
|
.reg_read = regmap_ac97_reg_read,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
struct regmap *__regmap_init_ac97(struct snd_ac97 *ac97,
|
||||||
* regmap_init_ac97(): Initialise AC'97 register map
|
const struct regmap_config *config,
|
||||||
*
|
struct lock_class_key *lock_key,
|
||||||
* @ac97: Device that will be interacted with
|
const char *lock_name)
|
||||||
* @config: Configuration for register map
|
|
||||||
*
|
|
||||||
* The return value will be an ERR_PTR() on error or a valid pointer to
|
|
||||||
* a struct regmap.
|
|
||||||
*/
|
|
||||||
struct regmap *regmap_init_ac97(struct snd_ac97 *ac97,
|
|
||||||
const struct regmap_config *config)
|
|
||||||
{
|
{
|
||||||
return regmap_init(&ac97->dev, &ac97_regmap_bus, ac97, config);
|
return __regmap_init(&ac97->dev, &ac97_regmap_bus, ac97, config,
|
||||||
|
lock_key, lock_name);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(regmap_init_ac97);
|
EXPORT_SYMBOL_GPL(__regmap_init_ac97);
|
||||||
|
|
||||||
/**
|
struct regmap *__devm_regmap_init_ac97(struct snd_ac97 *ac97,
|
||||||
* devm_regmap_init_ac97(): Initialise AC'97 register map
|
const struct regmap_config *config,
|
||||||
*
|
struct lock_class_key *lock_key,
|
||||||
* @ac97: Device that will be interacted with
|
const char *lock_name)
|
||||||
* @config: Configuration for register map
|
|
||||||
*
|
|
||||||
* The return value will be an ERR_PTR() on error or a valid pointer
|
|
||||||
* to a struct regmap. The regmap will be automatically freed by the
|
|
||||||
* device management code.
|
|
||||||
*/
|
|
||||||
struct regmap *devm_regmap_init_ac97(struct snd_ac97 *ac97,
|
|
||||||
const struct regmap_config *config)
|
|
||||||
{
|
{
|
||||||
return devm_regmap_init(&ac97->dev, &ac97_regmap_bus, ac97, config);
|
return __devm_regmap_init(&ac97->dev, &ac97_regmap_bus, ac97, config,
|
||||||
|
lock_key, lock_name);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(devm_regmap_init_ac97);
|
EXPORT_SYMBOL_GPL(__devm_regmap_init_ac97);
|
||||||
|
|
||||||
MODULE_LICENSE("GPL v2");
|
MODULE_LICENSE("GPL v2");
|
||||||
|
|
|
@ -469,6 +469,87 @@ static const struct file_operations regmap_access_fops = {
|
||||||
.llseek = default_llseek,
|
.llseek = default_llseek,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static ssize_t regmap_cache_only_write_file(struct file *file,
|
||||||
|
const char __user *user_buf,
|
||||||
|
size_t count, loff_t *ppos)
|
||||||
|
{
|
||||||
|
struct regmap *map = container_of(file->private_data,
|
||||||
|
struct regmap, cache_only);
|
||||||
|
ssize_t result;
|
||||||
|
bool was_enabled, require_sync = false;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
map->lock(map->lock_arg);
|
||||||
|
|
||||||
|
was_enabled = map->cache_only;
|
||||||
|
|
||||||
|
result = debugfs_write_file_bool(file, user_buf, count, ppos);
|
||||||
|
if (result < 0) {
|
||||||
|
map->unlock(map->lock_arg);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (map->cache_only && !was_enabled) {
|
||||||
|
dev_warn(map->dev, "debugfs cache_only=Y forced\n");
|
||||||
|
add_taint(TAINT_USER, LOCKDEP_STILL_OK);
|
||||||
|
} else if (!map->cache_only && was_enabled) {
|
||||||
|
dev_warn(map->dev, "debugfs cache_only=N forced: syncing cache\n");
|
||||||
|
require_sync = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
map->unlock(map->lock_arg);
|
||||||
|
|
||||||
|
if (require_sync) {
|
||||||
|
err = regcache_sync(map);
|
||||||
|
if (err)
|
||||||
|
dev_err(map->dev, "Failed to sync cache %d\n", err);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct file_operations regmap_cache_only_fops = {
|
||||||
|
.open = simple_open,
|
||||||
|
.read = debugfs_read_file_bool,
|
||||||
|
.write = regmap_cache_only_write_file,
|
||||||
|
};
|
||||||
|
|
||||||
|
static ssize_t regmap_cache_bypass_write_file(struct file *file,
|
||||||
|
const char __user *user_buf,
|
||||||
|
size_t count, loff_t *ppos)
|
||||||
|
{
|
||||||
|
struct regmap *map = container_of(file->private_data,
|
||||||
|
struct regmap, cache_bypass);
|
||||||
|
ssize_t result;
|
||||||
|
bool was_enabled;
|
||||||
|
|
||||||
|
map->lock(map->lock_arg);
|
||||||
|
|
||||||
|
was_enabled = map->cache_bypass;
|
||||||
|
|
||||||
|
result = debugfs_write_file_bool(file, user_buf, count, ppos);
|
||||||
|
if (result < 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
if (map->cache_bypass && !was_enabled) {
|
||||||
|
dev_warn(map->dev, "debugfs cache_bypass=Y forced\n");
|
||||||
|
add_taint(TAINT_USER, LOCKDEP_STILL_OK);
|
||||||
|
} else if (!map->cache_bypass && was_enabled) {
|
||||||
|
dev_warn(map->dev, "debugfs cache_bypass=N forced\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
map->unlock(map->lock_arg);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct file_operations regmap_cache_bypass_fops = {
|
||||||
|
.open = simple_open,
|
||||||
|
.read = debugfs_read_file_bool,
|
||||||
|
.write = regmap_cache_bypass_write_file,
|
||||||
|
};
|
||||||
|
|
||||||
void regmap_debugfs_init(struct regmap *map, const char *name)
|
void regmap_debugfs_init(struct regmap *map, const char *name)
|
||||||
{
|
{
|
||||||
struct rb_node *next;
|
struct rb_node *next;
|
||||||
|
@ -518,10 +599,11 @@ void regmap_debugfs_init(struct regmap *map, const char *name)
|
||||||
if (map->max_register || regmap_readable(map, 0)) {
|
if (map->max_register || regmap_readable(map, 0)) {
|
||||||
umode_t registers_mode;
|
umode_t registers_mode;
|
||||||
|
|
||||||
if (IS_ENABLED(REGMAP_ALLOW_WRITE_DEBUGFS))
|
#if defined(REGMAP_ALLOW_WRITE_DEBUGFS)
|
||||||
registers_mode = 0600;
|
registers_mode = 0600;
|
||||||
else
|
#else
|
||||||
registers_mode = 0400;
|
registers_mode = 0400;
|
||||||
|
#endif
|
||||||
|
|
||||||
debugfs_create_file("registers", registers_mode, map->debugfs,
|
debugfs_create_file("registers", registers_mode, map->debugfs,
|
||||||
map, ®map_map_fops);
|
map, ®map_map_fops);
|
||||||
|
@ -530,12 +612,13 @@ void regmap_debugfs_init(struct regmap *map, const char *name)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (map->cache_type) {
|
if (map->cache_type) {
|
||||||
debugfs_create_bool("cache_only", 0400, map->debugfs,
|
debugfs_create_file("cache_only", 0600, map->debugfs,
|
||||||
&map->cache_only);
|
&map->cache_only, ®map_cache_only_fops);
|
||||||
debugfs_create_bool("cache_dirty", 0400, map->debugfs,
|
debugfs_create_bool("cache_dirty", 0400, map->debugfs,
|
||||||
&map->cache_dirty);
|
&map->cache_dirty);
|
||||||
debugfs_create_bool("cache_bypass", 0400, map->debugfs,
|
debugfs_create_file("cache_bypass", 0600, map->debugfs,
|
||||||
&map->cache_bypass);
|
&map->cache_bypass,
|
||||||
|
®map_cache_bypass_fops);
|
||||||
}
|
}
|
||||||
|
|
||||||
next = rb_first(&map->range_tree);
|
next = rb_first(&map->range_tree);
|
||||||
|
|
|
@ -209,11 +209,60 @@ static struct regmap_bus regmap_i2c = {
|
||||||
.val_format_endian_default = REGMAP_ENDIAN_BIG,
|
.val_format_endian_default = REGMAP_ENDIAN_BIG,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int regmap_i2c_smbus_i2c_write(void *context, const void *data,
|
||||||
|
size_t count)
|
||||||
|
{
|
||||||
|
struct device *dev = context;
|
||||||
|
struct i2c_client *i2c = to_i2c_client(dev);
|
||||||
|
|
||||||
|
if (count < 1)
|
||||||
|
return -EINVAL;
|
||||||
|
if (count >= I2C_SMBUS_BLOCK_MAX)
|
||||||
|
return -E2BIG;
|
||||||
|
|
||||||
|
--count;
|
||||||
|
return i2c_smbus_write_i2c_block_data(i2c, ((u8 *)data)[0], count,
|
||||||
|
((u8 *)data + 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int regmap_i2c_smbus_i2c_read(void *context, const void *reg,
|
||||||
|
size_t reg_size, void *val,
|
||||||
|
size_t val_size)
|
||||||
|
{
|
||||||
|
struct device *dev = context;
|
||||||
|
struct i2c_client *i2c = to_i2c_client(dev);
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (reg_size != 1 || val_size < 1)
|
||||||
|
return -EINVAL;
|
||||||
|
if (val_size >= I2C_SMBUS_BLOCK_MAX)
|
||||||
|
return -E2BIG;
|
||||||
|
|
||||||
|
ret = i2c_smbus_read_i2c_block_data(i2c, ((u8 *)reg)[0], val_size, val);
|
||||||
|
if (ret == val_size)
|
||||||
|
return 0;
|
||||||
|
else if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
else
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct regmap_bus regmap_i2c_smbus_i2c_block = {
|
||||||
|
.write = regmap_i2c_smbus_i2c_write,
|
||||||
|
.read = regmap_i2c_smbus_i2c_read,
|
||||||
|
.max_raw_read = I2C_SMBUS_BLOCK_MAX,
|
||||||
|
.max_raw_write = I2C_SMBUS_BLOCK_MAX,
|
||||||
|
};
|
||||||
|
|
||||||
static const struct regmap_bus *regmap_get_i2c_bus(struct i2c_client *i2c,
|
static const struct regmap_bus *regmap_get_i2c_bus(struct i2c_client *i2c,
|
||||||
const struct regmap_config *config)
|
const struct regmap_config *config)
|
||||||
{
|
{
|
||||||
if (i2c_check_functionality(i2c->adapter, I2C_FUNC_I2C))
|
if (i2c_check_functionality(i2c->adapter, I2C_FUNC_I2C))
|
||||||
return ®map_i2c;
|
return ®map_i2c;
|
||||||
|
else if (config->reg_bits == 8 &&
|
||||||
|
i2c_check_functionality(i2c->adapter,
|
||||||
|
I2C_FUNC_SMBUS_I2C_BLOCK))
|
||||||
|
return ®map_i2c_smbus_i2c_block;
|
||||||
else if (config->val_bits == 16 && config->reg_bits == 8 &&
|
else if (config->val_bits == 16 && config->reg_bits == 8 &&
|
||||||
i2c_check_functionality(i2c->adapter,
|
i2c_check_functionality(i2c->adapter,
|
||||||
I2C_FUNC_SMBUS_WORD_DATA))
|
I2C_FUNC_SMBUS_WORD_DATA))
|
||||||
|
@ -233,47 +282,34 @@ static const struct regmap_bus *regmap_get_i2c_bus(struct i2c_client *i2c,
|
||||||
return ERR_PTR(-ENOTSUPP);
|
return ERR_PTR(-ENOTSUPP);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
struct regmap *__regmap_init_i2c(struct i2c_client *i2c,
|
||||||
* regmap_init_i2c(): Initialise register map
|
const struct regmap_config *config,
|
||||||
*
|
struct lock_class_key *lock_key,
|
||||||
* @i2c: Device that will be interacted with
|
const char *lock_name)
|
||||||
* @config: Configuration for register map
|
|
||||||
*
|
|
||||||
* The return value will be an ERR_PTR() on error or a valid pointer to
|
|
||||||
* a struct regmap.
|
|
||||||
*/
|
|
||||||
struct regmap *regmap_init_i2c(struct i2c_client *i2c,
|
|
||||||
const struct regmap_config *config)
|
|
||||||
{
|
{
|
||||||
const struct regmap_bus *bus = regmap_get_i2c_bus(i2c, config);
|
const struct regmap_bus *bus = regmap_get_i2c_bus(i2c, config);
|
||||||
|
|
||||||
if (IS_ERR(bus))
|
if (IS_ERR(bus))
|
||||||
return ERR_CAST(bus);
|
return ERR_CAST(bus);
|
||||||
|
|
||||||
return regmap_init(&i2c->dev, bus, &i2c->dev, config);
|
return __regmap_init(&i2c->dev, bus, &i2c->dev, config,
|
||||||
|
lock_key, lock_name);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(regmap_init_i2c);
|
EXPORT_SYMBOL_GPL(__regmap_init_i2c);
|
||||||
|
|
||||||
/**
|
struct regmap *__devm_regmap_init_i2c(struct i2c_client *i2c,
|
||||||
* devm_regmap_init_i2c(): Initialise managed register map
|
const struct regmap_config *config,
|
||||||
*
|
struct lock_class_key *lock_key,
|
||||||
* @i2c: Device that will be interacted with
|
const char *lock_name)
|
||||||
* @config: Configuration for register map
|
|
||||||
*
|
|
||||||
* The return value will be an ERR_PTR() on error or a valid pointer
|
|
||||||
* to a struct regmap. The regmap will be automatically freed by the
|
|
||||||
* device management code.
|
|
||||||
*/
|
|
||||||
struct regmap *devm_regmap_init_i2c(struct i2c_client *i2c,
|
|
||||||
const struct regmap_config *config)
|
|
||||||
{
|
{
|
||||||
const struct regmap_bus *bus = regmap_get_i2c_bus(i2c, config);
|
const struct regmap_bus *bus = regmap_get_i2c_bus(i2c, config);
|
||||||
|
|
||||||
if (IS_ERR(bus))
|
if (IS_ERR(bus))
|
||||||
return ERR_CAST(bus);
|
return ERR_CAST(bus);
|
||||||
|
|
||||||
return devm_regmap_init(&i2c->dev, bus, &i2c->dev, config);
|
return __devm_regmap_init(&i2c->dev, bus, &i2c->dev, config,
|
||||||
|
lock_key, lock_name);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(devm_regmap_init_i2c);
|
EXPORT_SYMBOL_GPL(__devm_regmap_init_i2c);
|
||||||
|
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
|
|
|
@ -209,7 +209,7 @@ static irqreturn_t regmap_irq_thread(int irq, void *d)
|
||||||
* Read in the statuses, using a single bulk read if possible
|
* Read in the statuses, using a single bulk read if possible
|
||||||
* in order to reduce the I/O overheads.
|
* in order to reduce the I/O overheads.
|
||||||
*/
|
*/
|
||||||
if (!map->use_single_rw && map->reg_stride == 1 &&
|
if (!map->use_single_read && map->reg_stride == 1 &&
|
||||||
data->irq_reg_stride == 1) {
|
data->irq_reg_stride == 1) {
|
||||||
u8 *buf8 = data->status_reg_buf;
|
u8 *buf8 = data->status_reg_buf;
|
||||||
u16 *buf16 = data->status_reg_buf;
|
u16 *buf16 = data->status_reg_buf;
|
||||||
|
@ -398,7 +398,7 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags,
|
||||||
else
|
else
|
||||||
d->irq_reg_stride = 1;
|
d->irq_reg_stride = 1;
|
||||||
|
|
||||||
if (!map->use_single_rw && map->reg_stride == 1 &&
|
if (!map->use_single_read && map->reg_stride == 1 &&
|
||||||
d->irq_reg_stride == 1) {
|
d->irq_reg_stride == 1) {
|
||||||
d->status_reg_buf = kmalloc(map->format.val_bytes *
|
d->status_reg_buf = kmalloc(map->format.val_bytes *
|
||||||
chip->num_regs, GFP_KERNEL);
|
chip->num_regs, GFP_KERNEL);
|
||||||
|
|
|
@ -296,20 +296,11 @@ err_free:
|
||||||
return ERR_PTR(ret);
|
return ERR_PTR(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
struct regmap *__regmap_init_mmio_clk(struct device *dev, const char *clk_id,
|
||||||
* regmap_init_mmio_clk(): Initialise register map with register clock
|
|
||||||
*
|
|
||||||
* @dev: Device that will be interacted with
|
|
||||||
* @clk_id: register clock consumer ID
|
|
||||||
* @regs: Pointer to memory-mapped IO region
|
|
||||||
* @config: Configuration for register map
|
|
||||||
*
|
|
||||||
* The return value will be an ERR_PTR() on error or a valid pointer to
|
|
||||||
* a struct regmap.
|
|
||||||
*/
|
|
||||||
struct regmap *regmap_init_mmio_clk(struct device *dev, const char *clk_id,
|
|
||||||
void __iomem *regs,
|
void __iomem *regs,
|
||||||
const struct regmap_config *config)
|
const struct regmap_config *config,
|
||||||
|
struct lock_class_key *lock_key,
|
||||||
|
const char *lock_name)
|
||||||
{
|
{
|
||||||
struct regmap_mmio_context *ctx;
|
struct regmap_mmio_context *ctx;
|
||||||
|
|
||||||
|
@ -317,25 +308,17 @@ struct regmap *regmap_init_mmio_clk(struct device *dev, const char *clk_id,
|
||||||
if (IS_ERR(ctx))
|
if (IS_ERR(ctx))
|
||||||
return ERR_CAST(ctx);
|
return ERR_CAST(ctx);
|
||||||
|
|
||||||
return regmap_init(dev, ®map_mmio, ctx, config);
|
return __regmap_init(dev, ®map_mmio, ctx, config,
|
||||||
|
lock_key, lock_name);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(regmap_init_mmio_clk);
|
EXPORT_SYMBOL_GPL(__regmap_init_mmio_clk);
|
||||||
|
|
||||||
/**
|
struct regmap *__devm_regmap_init_mmio_clk(struct device *dev,
|
||||||
* devm_regmap_init_mmio_clk(): Initialise managed register map with clock
|
const char *clk_id,
|
||||||
*
|
|
||||||
* @dev: Device that will be interacted with
|
|
||||||
* @clk_id: register clock consumer ID
|
|
||||||
* @regs: Pointer to memory-mapped IO region
|
|
||||||
* @config: Configuration for register map
|
|
||||||
*
|
|
||||||
* The return value will be an ERR_PTR() on error or a valid pointer
|
|
||||||
* to a struct regmap. The regmap will be automatically freed by the
|
|
||||||
* device management code.
|
|
||||||
*/
|
|
||||||
struct regmap *devm_regmap_init_mmio_clk(struct device *dev, const char *clk_id,
|
|
||||||
void __iomem *regs,
|
void __iomem *regs,
|
||||||
const struct regmap_config *config)
|
const struct regmap_config *config,
|
||||||
|
struct lock_class_key *lock_key,
|
||||||
|
const char *lock_name)
|
||||||
{
|
{
|
||||||
struct regmap_mmio_context *ctx;
|
struct regmap_mmio_context *ctx;
|
||||||
|
|
||||||
|
@ -343,8 +326,9 @@ struct regmap *devm_regmap_init_mmio_clk(struct device *dev, const char *clk_id,
|
||||||
if (IS_ERR(ctx))
|
if (IS_ERR(ctx))
|
||||||
return ERR_CAST(ctx);
|
return ERR_CAST(ctx);
|
||||||
|
|
||||||
return devm_regmap_init(dev, ®map_mmio, ctx, config);
|
return __devm_regmap_init(dev, ®map_mmio, ctx, config,
|
||||||
|
lock_key, lock_name);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(devm_regmap_init_mmio_clk);
|
EXPORT_SYMBOL_GPL(__devm_regmap_init_mmio_clk);
|
||||||
|
|
||||||
MODULE_LICENSE("GPL v2");
|
MODULE_LICENSE("GPL v2");
|
||||||
|
|
|
@ -113,37 +113,24 @@ static struct regmap_bus regmap_spi = {
|
||||||
.val_format_endian_default = REGMAP_ENDIAN_BIG,
|
.val_format_endian_default = REGMAP_ENDIAN_BIG,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
struct regmap *__regmap_init_spi(struct spi_device *spi,
|
||||||
* regmap_init_spi(): Initialise register map
|
const struct regmap_config *config,
|
||||||
*
|
struct lock_class_key *lock_key,
|
||||||
* @spi: Device that will be interacted with
|
const char *lock_name)
|
||||||
* @config: Configuration for register map
|
|
||||||
*
|
|
||||||
* The return value will be an ERR_PTR() on error or a valid pointer to
|
|
||||||
* a struct regmap.
|
|
||||||
*/
|
|
||||||
struct regmap *regmap_init_spi(struct spi_device *spi,
|
|
||||||
const struct regmap_config *config)
|
|
||||||
{
|
{
|
||||||
return regmap_init(&spi->dev, ®map_spi, &spi->dev, config);
|
return __regmap_init(&spi->dev, ®map_spi, &spi->dev, config,
|
||||||
|
lock_key, lock_name);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(regmap_init_spi);
|
EXPORT_SYMBOL_GPL(__regmap_init_spi);
|
||||||
|
|
||||||
/**
|
struct regmap *__devm_regmap_init_spi(struct spi_device *spi,
|
||||||
* devm_regmap_init_spi(): Initialise register map
|
const struct regmap_config *config,
|
||||||
*
|
struct lock_class_key *lock_key,
|
||||||
* @spi: Device that will be interacted with
|
const char *lock_name)
|
||||||
* @config: Configuration for register map
|
|
||||||
*
|
|
||||||
* The return value will be an ERR_PTR() on error or a valid pointer
|
|
||||||
* to a struct regmap. The map will be automatically freed by the
|
|
||||||
* device management code.
|
|
||||||
*/
|
|
||||||
struct regmap *devm_regmap_init_spi(struct spi_device *spi,
|
|
||||||
const struct regmap_config *config)
|
|
||||||
{
|
{
|
||||||
return devm_regmap_init(&spi->dev, ®map_spi, &spi->dev, config);
|
return __devm_regmap_init(&spi->dev, ®map_spi, &spi->dev, config,
|
||||||
|
lock_key, lock_name);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(devm_regmap_init_spi);
|
EXPORT_SYMBOL_GPL(__devm_regmap_init_spi);
|
||||||
|
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
|
|
|
@ -91,36 +91,25 @@ static struct regmap_bus regmap_spmi_base = {
|
||||||
.val_format_endian_default = REGMAP_ENDIAN_NATIVE,
|
.val_format_endian_default = REGMAP_ENDIAN_NATIVE,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
struct regmap *__regmap_init_spmi_base(struct spmi_device *sdev,
|
||||||
* regmap_init_spmi_base(): Create regmap for the Base register space
|
const struct regmap_config *config,
|
||||||
* @sdev: SPMI device that will be interacted with
|
struct lock_class_key *lock_key,
|
||||||
* @config: Configuration for register map
|
const char *lock_name)
|
||||||
*
|
|
||||||
* The return value will be an ERR_PTR() on error or a valid pointer to
|
|
||||||
* a struct regmap.
|
|
||||||
*/
|
|
||||||
struct regmap *regmap_init_spmi_base(struct spmi_device *sdev,
|
|
||||||
const struct regmap_config *config)
|
|
||||||
{
|
{
|
||||||
return regmap_init(&sdev->dev, ®map_spmi_base, sdev, config);
|
return __regmap_init(&sdev->dev, ®map_spmi_base, sdev, config,
|
||||||
|
lock_key, lock_name);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(regmap_init_spmi_base);
|
EXPORT_SYMBOL_GPL(__regmap_init_spmi_base);
|
||||||
|
|
||||||
/**
|
struct regmap *__devm_regmap_init_spmi_base(struct spmi_device *sdev,
|
||||||
* devm_regmap_init_spmi_base(): Create managed regmap for Base register space
|
const struct regmap_config *config,
|
||||||
* @sdev: SPMI device that will be interacted with
|
struct lock_class_key *lock_key,
|
||||||
* @config: Configuration for register map
|
const char *lock_name)
|
||||||
*
|
|
||||||
* The return value will be an ERR_PTR() on error or a valid pointer
|
|
||||||
* to a struct regmap. The regmap will be automatically freed by the
|
|
||||||
* device management code.
|
|
||||||
*/
|
|
||||||
struct regmap *devm_regmap_init_spmi_base(struct spmi_device *sdev,
|
|
||||||
const struct regmap_config *config)
|
|
||||||
{
|
{
|
||||||
return devm_regmap_init(&sdev->dev, ®map_spmi_base, sdev, config);
|
return __devm_regmap_init(&sdev->dev, ®map_spmi_base, sdev, config,
|
||||||
|
lock_key, lock_name);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(devm_regmap_init_spmi_base);
|
EXPORT_SYMBOL_GPL(__devm_regmap_init_spmi_base);
|
||||||
|
|
||||||
static int regmap_spmi_ext_read(void *context,
|
static int regmap_spmi_ext_read(void *context,
|
||||||
const void *reg, size_t reg_size,
|
const void *reg, size_t reg_size,
|
||||||
|
@ -222,35 +211,24 @@ static struct regmap_bus regmap_spmi_ext = {
|
||||||
.val_format_endian_default = REGMAP_ENDIAN_NATIVE,
|
.val_format_endian_default = REGMAP_ENDIAN_NATIVE,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
struct regmap *__regmap_init_spmi_ext(struct spmi_device *sdev,
|
||||||
* regmap_init_spmi_ext(): Create regmap for Ext register space
|
const struct regmap_config *config,
|
||||||
* @sdev: Device that will be interacted with
|
struct lock_class_key *lock_key,
|
||||||
* @config: Configuration for register map
|
const char *lock_name)
|
||||||
*
|
|
||||||
* The return value will be an ERR_PTR() on error or a valid pointer to
|
|
||||||
* a struct regmap.
|
|
||||||
*/
|
|
||||||
struct regmap *regmap_init_spmi_ext(struct spmi_device *sdev,
|
|
||||||
const struct regmap_config *config)
|
|
||||||
{
|
{
|
||||||
return regmap_init(&sdev->dev, ®map_spmi_ext, sdev, config);
|
return __regmap_init(&sdev->dev, ®map_spmi_ext, sdev, config,
|
||||||
|
lock_key, lock_name);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(regmap_init_spmi_ext);
|
EXPORT_SYMBOL_GPL(__regmap_init_spmi_ext);
|
||||||
|
|
||||||
/**
|
struct regmap *__devm_regmap_init_spmi_ext(struct spmi_device *sdev,
|
||||||
* devm_regmap_init_spmi_ext(): Create managed regmap for Ext register space
|
const struct regmap_config *config,
|
||||||
* @sdev: SPMI device that will be interacted with
|
struct lock_class_key *lock_key,
|
||||||
* @config: Configuration for register map
|
const char *lock_name)
|
||||||
*
|
|
||||||
* The return value will be an ERR_PTR() on error or a valid pointer
|
|
||||||
* to a struct regmap. The regmap will be automatically freed by the
|
|
||||||
* device management code.
|
|
||||||
*/
|
|
||||||
struct regmap *devm_regmap_init_spmi_ext(struct spmi_device *sdev,
|
|
||||||
const struct regmap_config *config)
|
|
||||||
{
|
{
|
||||||
return devm_regmap_init(&sdev->dev, ®map_spmi_ext, sdev, config);
|
return __devm_regmap_init(&sdev->dev, ®map_spmi_ext, sdev, config,
|
||||||
|
lock_key, lock_name);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(devm_regmap_init_spmi_ext);
|
EXPORT_SYMBOL_GPL(__devm_regmap_init_spmi_ext);
|
||||||
|
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include <linux/of.h>
|
#include <linux/of.h>
|
||||||
#include <linux/rbtree.h>
|
#include <linux/rbtree.h>
|
||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
|
#include <linux/delay.h>
|
||||||
|
|
||||||
#define CREATE_TRACE_POINTS
|
#define CREATE_TRACE_POINTS
|
||||||
#include "trace.h"
|
#include "trace.h"
|
||||||
|
@ -93,6 +94,9 @@ bool regmap_writeable(struct regmap *map, unsigned int reg)
|
||||||
|
|
||||||
bool regmap_readable(struct regmap *map, unsigned int reg)
|
bool regmap_readable(struct regmap *map, unsigned int reg)
|
||||||
{
|
{
|
||||||
|
if (!map->reg_read)
|
||||||
|
return false;
|
||||||
|
|
||||||
if (map->max_register && reg > map->max_register)
|
if (map->max_register && reg > map->max_register)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -515,22 +519,12 @@ enum regmap_endian regmap_get_val_endian(struct device *dev,
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(regmap_get_val_endian);
|
EXPORT_SYMBOL_GPL(regmap_get_val_endian);
|
||||||
|
|
||||||
/**
|
struct regmap *__regmap_init(struct device *dev,
|
||||||
* regmap_init(): Initialise register map
|
|
||||||
*
|
|
||||||
* @dev: Device that will be interacted with
|
|
||||||
* @bus: Bus-specific callbacks to use with device
|
|
||||||
* @bus_context: Data passed to bus-specific callbacks
|
|
||||||
* @config: Configuration for register map
|
|
||||||
*
|
|
||||||
* The return value will be an ERR_PTR() on error or a valid pointer to
|
|
||||||
* a struct regmap. This function should generally not be called
|
|
||||||
* directly, it should be called by bus-specific init functions.
|
|
||||||
*/
|
|
||||||
struct regmap *regmap_init(struct device *dev,
|
|
||||||
const struct regmap_bus *bus,
|
const struct regmap_bus *bus,
|
||||||
void *bus_context,
|
void *bus_context,
|
||||||
const struct regmap_config *config)
|
const struct regmap_config *config,
|
||||||
|
struct lock_class_key *lock_key,
|
||||||
|
const char *lock_name)
|
||||||
{
|
{
|
||||||
struct regmap *map;
|
struct regmap *map;
|
||||||
int ret = -EINVAL;
|
int ret = -EINVAL;
|
||||||
|
@ -556,10 +550,14 @@ struct regmap *regmap_init(struct device *dev,
|
||||||
spin_lock_init(&map->spinlock);
|
spin_lock_init(&map->spinlock);
|
||||||
map->lock = regmap_lock_spinlock;
|
map->lock = regmap_lock_spinlock;
|
||||||
map->unlock = regmap_unlock_spinlock;
|
map->unlock = regmap_unlock_spinlock;
|
||||||
|
lockdep_set_class_and_name(&map->spinlock,
|
||||||
|
lock_key, lock_name);
|
||||||
} else {
|
} else {
|
||||||
mutex_init(&map->mutex);
|
mutex_init(&map->mutex);
|
||||||
map->lock = regmap_lock_mutex;
|
map->lock = regmap_lock_mutex;
|
||||||
map->unlock = regmap_unlock_mutex;
|
map->unlock = regmap_unlock_mutex;
|
||||||
|
lockdep_set_class_and_name(&map->mutex,
|
||||||
|
lock_key, lock_name);
|
||||||
}
|
}
|
||||||
map->lock_arg = map;
|
map->lock_arg = map;
|
||||||
}
|
}
|
||||||
|
@ -573,8 +571,13 @@ struct regmap *regmap_init(struct device *dev,
|
||||||
map->reg_stride = config->reg_stride;
|
map->reg_stride = config->reg_stride;
|
||||||
else
|
else
|
||||||
map->reg_stride = 1;
|
map->reg_stride = 1;
|
||||||
map->use_single_rw = config->use_single_rw;
|
map->use_single_read = config->use_single_rw || !bus || !bus->read;
|
||||||
map->can_multi_write = config->can_multi_write;
|
map->use_single_write = config->use_single_rw || !bus || !bus->write;
|
||||||
|
map->can_multi_write = config->can_multi_write && bus && bus->write;
|
||||||
|
if (bus) {
|
||||||
|
map->max_raw_read = bus->max_raw_read;
|
||||||
|
map->max_raw_write = bus->max_raw_write;
|
||||||
|
}
|
||||||
map->dev = dev;
|
map->dev = dev;
|
||||||
map->bus = bus;
|
map->bus = bus;
|
||||||
map->bus_context = bus_context;
|
map->bus_context = bus_context;
|
||||||
|
@ -763,7 +766,7 @@ struct regmap *regmap_init(struct device *dev,
|
||||||
if ((reg_endian != REGMAP_ENDIAN_BIG) ||
|
if ((reg_endian != REGMAP_ENDIAN_BIG) ||
|
||||||
(val_endian != REGMAP_ENDIAN_BIG))
|
(val_endian != REGMAP_ENDIAN_BIG))
|
||||||
goto err_map;
|
goto err_map;
|
||||||
map->use_single_rw = true;
|
map->use_single_write = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!map->format.format_write &&
|
if (!map->format.format_write &&
|
||||||
|
@ -899,30 +902,19 @@ err_map:
|
||||||
err:
|
err:
|
||||||
return ERR_PTR(ret);
|
return ERR_PTR(ret);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(regmap_init);
|
EXPORT_SYMBOL_GPL(__regmap_init);
|
||||||
|
|
||||||
static void devm_regmap_release(struct device *dev, void *res)
|
static void devm_regmap_release(struct device *dev, void *res)
|
||||||
{
|
{
|
||||||
regmap_exit(*(struct regmap **)res);
|
regmap_exit(*(struct regmap **)res);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
struct regmap *__devm_regmap_init(struct device *dev,
|
||||||
* devm_regmap_init(): Initialise managed register map
|
|
||||||
*
|
|
||||||
* @dev: Device that will be interacted with
|
|
||||||
* @bus: Bus-specific callbacks to use with device
|
|
||||||
* @bus_context: Data passed to bus-specific callbacks
|
|
||||||
* @config: Configuration for register map
|
|
||||||
*
|
|
||||||
* The return value will be an ERR_PTR() on error or a valid pointer
|
|
||||||
* to a struct regmap. This function should generally not be called
|
|
||||||
* directly, it should be called by bus-specific init functions. The
|
|
||||||
* map will be automatically freed by the device management code.
|
|
||||||
*/
|
|
||||||
struct regmap *devm_regmap_init(struct device *dev,
|
|
||||||
const struct regmap_bus *bus,
|
const struct regmap_bus *bus,
|
||||||
void *bus_context,
|
void *bus_context,
|
||||||
const struct regmap_config *config)
|
const struct regmap_config *config,
|
||||||
|
struct lock_class_key *lock_key,
|
||||||
|
const char *lock_name)
|
||||||
{
|
{
|
||||||
struct regmap **ptr, *regmap;
|
struct regmap **ptr, *regmap;
|
||||||
|
|
||||||
|
@ -930,7 +922,8 @@ struct regmap *devm_regmap_init(struct device *dev,
|
||||||
if (!ptr)
|
if (!ptr)
|
||||||
return ERR_PTR(-ENOMEM);
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
regmap = regmap_init(dev, bus, bus_context, config);
|
regmap = __regmap_init(dev, bus, bus_context, config,
|
||||||
|
lock_key, lock_name);
|
||||||
if (!IS_ERR(regmap)) {
|
if (!IS_ERR(regmap)) {
|
||||||
*ptr = regmap;
|
*ptr = regmap;
|
||||||
devres_add(dev, ptr);
|
devres_add(dev, ptr);
|
||||||
|
@ -940,7 +933,7 @@ struct regmap *devm_regmap_init(struct device *dev,
|
||||||
|
|
||||||
return regmap;
|
return regmap;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(devm_regmap_init);
|
EXPORT_SYMBOL_GPL(__devm_regmap_init);
|
||||||
|
|
||||||
static void regmap_field_init(struct regmap_field *rm_field,
|
static void regmap_field_init(struct regmap_field *rm_field,
|
||||||
struct regmap *regmap, struct reg_field reg_field)
|
struct regmap *regmap, struct reg_field reg_field)
|
||||||
|
@ -1382,10 +1375,33 @@ int _regmap_raw_write(struct regmap *map, unsigned int reg,
|
||||||
*/
|
*/
|
||||||
bool regmap_can_raw_write(struct regmap *map)
|
bool regmap_can_raw_write(struct regmap *map)
|
||||||
{
|
{
|
||||||
return map->bus && map->format.format_val && map->format.format_reg;
|
return map->bus && map->bus->write && map->format.format_val &&
|
||||||
|
map->format.format_reg;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(regmap_can_raw_write);
|
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);
|
||||||
|
|
||||||
static int _regmap_bus_formatted_write(void *context, unsigned int reg,
|
static int _regmap_bus_formatted_write(void *context, unsigned int reg,
|
||||||
unsigned int val)
|
unsigned int val)
|
||||||
{
|
{
|
||||||
|
@ -1555,6 +1571,8 @@ int regmap_raw_write(struct regmap *map, unsigned int reg,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
if (val_len % map->format.val_bytes)
|
if (val_len % map->format.val_bytes)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
if (map->max_raw_write && map->max_raw_write > val_len)
|
||||||
|
return -E2BIG;
|
||||||
|
|
||||||
map->lock(map->lock_arg);
|
map->lock(map->lock_arg);
|
||||||
|
|
||||||
|
@ -1681,6 +1699,7 @@ int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val,
|
||||||
{
|
{
|
||||||
int ret = 0, i;
|
int ret = 0, i;
|
||||||
size_t val_bytes = map->format.val_bytes;
|
size_t val_bytes = map->format.val_bytes;
|
||||||
|
size_t total_size = val_bytes * val_count;
|
||||||
|
|
||||||
if (map->bus && !map->format.parse_inplace)
|
if (map->bus && !map->format.parse_inplace)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -1689,9 +1708,15 @@ int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val,
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Some devices don't support bulk write, for
|
* Some devices don't support bulk write, for
|
||||||
* them we have a series of single write operations.
|
* them we have a series of single write operations in the first two if
|
||||||
|
* blocks.
|
||||||
|
*
|
||||||
|
* The first if block is used for memory mapped io. It does not allow
|
||||||
|
* val_bytes of 3 for example.
|
||||||
|
* The second one is used for busses which do not have this limitation
|
||||||
|
* and can write arbitrary value lengths.
|
||||||
*/
|
*/
|
||||||
if (!map->bus || map->use_single_rw) {
|
if (!map->bus) {
|
||||||
map->lock(map->lock_arg);
|
map->lock(map->lock_arg);
|
||||||
for (i = 0; i < val_count; i++) {
|
for (i = 0; i < val_count; i++) {
|
||||||
unsigned int ival;
|
unsigned int ival;
|
||||||
|
@ -1723,6 +1748,38 @@ int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val,
|
||||||
}
|
}
|
||||||
out:
|
out:
|
||||||
map->unlock(map->lock_arg);
|
map->unlock(map->lock_arg);
|
||||||
|
} else if (map->use_single_write ||
|
||||||
|
(map->max_raw_write && map->max_raw_write < total_size)) {
|
||||||
|
int chunk_stride = map->reg_stride;
|
||||||
|
size_t chunk_size = val_bytes;
|
||||||
|
size_t chunk_count = val_count;
|
||||||
|
|
||||||
|
if (!map->use_single_write) {
|
||||||
|
chunk_size = map->max_raw_write;
|
||||||
|
if (chunk_size % val_bytes)
|
||||||
|
chunk_size -= chunk_size % val_bytes;
|
||||||
|
chunk_count = total_size / chunk_size;
|
||||||
|
chunk_stride *= chunk_size / val_bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
map->lock(map->lock_arg);
|
||||||
|
/* Write as many bytes as possible with chunk_size */
|
||||||
|
for (i = 0; i < chunk_count; i++) {
|
||||||
|
ret = _regmap_raw_write(map,
|
||||||
|
reg + (i * chunk_stride),
|
||||||
|
val + (i * chunk_size),
|
||||||
|
chunk_size);
|
||||||
|
if (ret)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write remaining bytes */
|
||||||
|
if (!ret && chunk_size * i < total_size) {
|
||||||
|
ret = _regmap_raw_write(map, reg + (i * chunk_stride),
|
||||||
|
val + (i * chunk_size),
|
||||||
|
total_size - i * chunk_size);
|
||||||
|
}
|
||||||
|
map->unlock(map->lock_arg);
|
||||||
} else {
|
} else {
|
||||||
void *wval;
|
void *wval;
|
||||||
|
|
||||||
|
@ -1752,7 +1809,7 @@ EXPORT_SYMBOL_GPL(regmap_bulk_write);
|
||||||
*
|
*
|
||||||
* the (register,newvalue) pairs in regs have not been formatted, but
|
* 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
|
* they are all in the same page and have been changed to being page
|
||||||
* relative. The page register has been written if that was neccessary.
|
* relative. The page register has been written if that was necessary.
|
||||||
*/
|
*/
|
||||||
static int _regmap_raw_multi_reg_write(struct regmap *map,
|
static int _regmap_raw_multi_reg_write(struct regmap *map,
|
||||||
const struct reg_sequence *regs,
|
const struct reg_sequence *regs,
|
||||||
|
@ -1780,8 +1837,8 @@ static int _regmap_raw_multi_reg_write(struct regmap *map,
|
||||||
u8 = buf;
|
u8 = buf;
|
||||||
|
|
||||||
for (i = 0; i < num_regs; i++) {
|
for (i = 0; i < num_regs; i++) {
|
||||||
int reg = regs[i].reg;
|
unsigned int reg = regs[i].reg;
|
||||||
int val = regs[i].def;
|
unsigned int val = regs[i].def;
|
||||||
trace_regmap_hw_write_start(map, reg, 1);
|
trace_regmap_hw_write_start(map, reg, 1);
|
||||||
map->format.format_reg(u8, reg, map->reg_shift);
|
map->format.format_reg(u8, reg, map->reg_shift);
|
||||||
u8 += reg_bytes + pad_bytes;
|
u8 += reg_bytes + pad_bytes;
|
||||||
|
@ -1819,10 +1876,12 @@ static int _regmap_range_multi_paged_reg_write(struct regmap *map,
|
||||||
int i, n;
|
int i, n;
|
||||||
struct reg_sequence *base;
|
struct reg_sequence *base;
|
||||||
unsigned int this_page = 0;
|
unsigned int this_page = 0;
|
||||||
|
unsigned int page_change = 0;
|
||||||
/*
|
/*
|
||||||
* the set of registers are not neccessarily in order, but
|
* the set of registers are not neccessarily in order, but
|
||||||
* since the order of write must be preserved this algorithm
|
* since the order of write must be preserved this algorithm
|
||||||
* chops the set each time the page changes
|
* 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;
|
base = regs;
|
||||||
for (i = 0, n = 0; i < num_regs; i++, n++) {
|
for (i = 0, n = 0; i < num_regs; i++, n++) {
|
||||||
|
@ -1838,16 +1897,48 @@ static int _regmap_range_multi_paged_reg_write(struct regmap *map,
|
||||||
this_page = win_page;
|
this_page = win_page;
|
||||||
if (win_page != this_page) {
|
if (win_page != this_page) {
|
||||||
this_page = win_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);
|
ret = _regmap_raw_multi_reg_write(map, base, n);
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
if (regs[i].delay_us)
|
||||||
|
udelay(regs[i].delay_us);
|
||||||
|
|
||||||
base += n;
|
base += n;
|
||||||
n = 0;
|
n = 0;
|
||||||
}
|
|
||||||
ret = _regmap_select_page(map, &base[n].reg, range, 1);
|
if (page_change) {
|
||||||
|
ret = _regmap_select_page(map,
|
||||||
|
&base[n].reg,
|
||||||
|
range, 1);
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
page_change = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
if (n > 0)
|
if (n > 0)
|
||||||
return _regmap_raw_multi_reg_write(map, base, n);
|
return _regmap_raw_multi_reg_write(map, base, n);
|
||||||
|
@ -1866,6 +1957,9 @@ static int _regmap_multi_reg_write(struct regmap *map,
|
||||||
ret = _regmap_write(map, regs[i].reg, regs[i].def);
|
ret = _regmap_write(map, regs[i].reg, regs[i].def);
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
if (regs[i].delay_us)
|
||||||
|
udelay(regs[i].delay_us);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1905,8 +1999,12 @@ static int _regmap_multi_reg_write(struct regmap *map,
|
||||||
for (i = 0; i < num_regs; i++) {
|
for (i = 0; i < num_regs; i++) {
|
||||||
unsigned int reg = regs[i].reg;
|
unsigned int reg = regs[i].reg;
|
||||||
struct regmap_range_node *range;
|
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);
|
range = _regmap_range_lookup(map, reg);
|
||||||
if (range) {
|
if (range || regs[i].delay_us) {
|
||||||
size_t len = sizeof(struct reg_sequence)*num_regs;
|
size_t len = sizeof(struct reg_sequence)*num_regs;
|
||||||
struct reg_sequence *base = kmemdup(regs, len,
|
struct reg_sequence *base = kmemdup(regs, len,
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
|
@ -2062,7 +2160,7 @@ static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Some buses or devices flag reads by setting the high bits in the
|
* Some buses or devices flag reads by setting the high bits in the
|
||||||
* register addresss; since it's always the high bits for all
|
* register address; since it's always the high bits for all
|
||||||
* current formats we can do this here rather than in
|
* current formats we can do this here rather than in
|
||||||
* formatting. This may break if we get interesting formats.
|
* formatting. This may break if we get interesting formats.
|
||||||
*/
|
*/
|
||||||
|
@ -2109,8 +2207,6 @@ static int _regmap_read(struct regmap *map, unsigned int reg,
|
||||||
int ret;
|
int ret;
|
||||||
void *context = _regmap_map_get_context(map);
|
void *context = _regmap_map_get_context(map);
|
||||||
|
|
||||||
WARN_ON(!map->reg_read);
|
|
||||||
|
|
||||||
if (!map->cache_bypass) {
|
if (!map->cache_bypass) {
|
||||||
ret = regcache_read(map, reg, val);
|
ret = regcache_read(map, reg, val);
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
|
@ -2191,11 +2287,22 @@ int regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
if (reg % map->reg_stride)
|
if (reg % map->reg_stride)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
if (val_count == 0)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
map->lock(map->lock_arg);
|
map->lock(map->lock_arg);
|
||||||
|
|
||||||
if (regmap_volatile_range(map, reg, val_count) || map->cache_bypass ||
|
if (regmap_volatile_range(map, reg, val_count) || map->cache_bypass ||
|
||||||
map->cache_type == REGCACHE_NONE) {
|
map->cache_type == REGCACHE_NONE) {
|
||||||
|
if (!map->bus->read) {
|
||||||
|
ret = -ENOTSUPP;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if (map->max_raw_read && map->max_raw_read < val_len) {
|
||||||
|
ret = -E2BIG;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
/* Physical block read if there's no cache involved */
|
/* Physical block read if there's no cache involved */
|
||||||
ret = _regmap_raw_read(map, reg, val, val_len);
|
ret = _regmap_raw_read(map, reg, val, val_len);
|
||||||
|
|
||||||
|
@ -2304,20 +2411,51 @@ int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val,
|
||||||
* Some devices does not support bulk read, for
|
* Some devices does not support bulk read, for
|
||||||
* them we have a series of single read operations.
|
* them we have a series of single read operations.
|
||||||
*/
|
*/
|
||||||
if (map->use_single_rw) {
|
size_t total_size = val_bytes * val_count;
|
||||||
for (i = 0; i < val_count; i++) {
|
|
||||||
ret = regmap_raw_read(map,
|
if (!map->use_single_read &&
|
||||||
reg + (i * map->reg_stride),
|
(!map->max_raw_read || map->max_raw_read > total_size)) {
|
||||||
val + (i * val_bytes),
|
|
||||||
val_bytes);
|
|
||||||
if (ret != 0)
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ret = regmap_raw_read(map, reg, val,
|
ret = regmap_raw_read(map, reg, val,
|
||||||
val_bytes * val_count);
|
val_bytes * val_count);
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* Some devices do not support bulk read or do not
|
||||||
|
* support large bulk reads, for them we have a series
|
||||||
|
* of read operations.
|
||||||
|
*/
|
||||||
|
int chunk_stride = map->reg_stride;
|
||||||
|
size_t chunk_size = val_bytes;
|
||||||
|
size_t chunk_count = val_count;
|
||||||
|
|
||||||
|
if (!map->use_single_read) {
|
||||||
|
chunk_size = map->max_raw_read;
|
||||||
|
if (chunk_size % val_bytes)
|
||||||
|
chunk_size -= chunk_size % val_bytes;
|
||||||
|
chunk_count = total_size / chunk_size;
|
||||||
|
chunk_stride *= chunk_size / val_bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read bytes that fit into a multiple of chunk_size */
|
||||||
|
for (i = 0; i < chunk_count; i++) {
|
||||||
|
ret = regmap_raw_read(map,
|
||||||
|
reg + (i * chunk_stride),
|
||||||
|
val + (i * chunk_size),
|
||||||
|
chunk_size);
|
||||||
|
if (ret != 0)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read remaining bytes */
|
||||||
|
if (chunk_size * i < total_size) {
|
||||||
|
ret = regmap_raw_read(map,
|
||||||
|
reg + (i * chunk_stride),
|
||||||
|
val + (i * chunk_size),
|
||||||
|
total_size - i * chunk_size);
|
||||||
|
if (ret != 0)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < val_count * val_bytes; i += val_bytes)
|
for (i = 0; i < val_count * val_bytes; i += val_bytes)
|
||||||
|
@ -2329,7 +2467,34 @@ int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val,
|
||||||
&ival);
|
&ival);
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
if (map->format.format_val) {
|
||||||
map->format.format_val(val + (i * val_bytes), ival, 0);
|
map->format.format_val(val + (i * val_bytes), ival, 0);
|
||||||
|
} else {
|
||||||
|
/* Devices providing read and write
|
||||||
|
* operations can use the bulk I/O
|
||||||
|
* functions if they define a val_bytes,
|
||||||
|
* we assume that the values are native
|
||||||
|
* endian.
|
||||||
|
*/
|
||||||
|
u32 *u32 = val;
|
||||||
|
u16 *u16 = val;
|
||||||
|
u8 *u8 = val;
|
||||||
|
|
||||||
|
switch (map->format.val_bytes) {
|
||||||
|
case 4:
|
||||||
|
u32[i] = ival;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
u16[i] = ival;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
u8[i] = ival;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -107,7 +107,7 @@ struct regmap *devm_regmap_init_vexpress_config(struct device *dev)
|
||||||
if (!res)
|
if (!res)
|
||||||
return ERR_PTR(-ENOMEM);
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
regmap = bridge->ops->regmap_init(dev, bridge->context);
|
regmap = (bridge->ops->regmap_init)(dev, bridge->context);
|
||||||
if (IS_ERR(regmap)) {
|
if (IS_ERR(regmap)) {
|
||||||
devres_free(res);
|
devres_free(res);
|
||||||
return regmap;
|
return regmap;
|
||||||
|
|
|
@ -1262,7 +1262,7 @@ static struct regulator *create_regulator(struct regulator_dev *rdev,
|
||||||
regulator->debugfs = debugfs_create_dir(regulator->supply_name,
|
regulator->debugfs = debugfs_create_dir(regulator->supply_name,
|
||||||
rdev->debugfs);
|
rdev->debugfs);
|
||||||
if (!regulator->debugfs) {
|
if (!regulator->debugfs) {
|
||||||
rdev_warn(rdev, "Failed to create debugfs directory\n");
|
rdev_dbg(rdev, "Failed to create debugfs directory\n");
|
||||||
} else {
|
} else {
|
||||||
debugfs_create_u32("uA_load", 0444, regulator->debugfs,
|
debugfs_create_u32("uA_load", 0444, regulator->debugfs,
|
||||||
®ulator->uA_load);
|
®ulator->uA_load);
|
||||||
|
|
|
@ -214,7 +214,7 @@ int st_thermal_register(struct platform_device *pdev,
|
||||||
|
|
||||||
sensor->ops = sensor->cdata->ops;
|
sensor->ops = sensor->cdata->ops;
|
||||||
|
|
||||||
ret = sensor->ops->regmap_init(sensor);
|
ret = (sensor->ops->regmap_init)(sensor);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
|
|
@ -435,7 +435,7 @@ struct dentry *debugfs_create_atomic_t(const char *name, umode_t mode,
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(debugfs_create_atomic_t);
|
EXPORT_SYMBOL_GPL(debugfs_create_atomic_t);
|
||||||
|
|
||||||
static ssize_t read_file_bool(struct file *file, char __user *user_buf,
|
ssize_t debugfs_read_file_bool(struct file *file, char __user *user_buf,
|
||||||
size_t count, loff_t *ppos)
|
size_t count, loff_t *ppos)
|
||||||
{
|
{
|
||||||
char buf[3];
|
char buf[3];
|
||||||
|
@ -449,8 +449,9 @@ static ssize_t read_file_bool(struct file *file, char __user *user_buf,
|
||||||
buf[2] = 0x00;
|
buf[2] = 0x00;
|
||||||
return simple_read_from_buffer(user_buf, count, ppos, buf, 2);
|
return simple_read_from_buffer(user_buf, count, ppos, buf, 2);
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(debugfs_read_file_bool);
|
||||||
|
|
||||||
static ssize_t write_file_bool(struct file *file, const char __user *user_buf,
|
ssize_t debugfs_write_file_bool(struct file *file, const char __user *user_buf,
|
||||||
size_t count, loff_t *ppos)
|
size_t count, loff_t *ppos)
|
||||||
{
|
{
|
||||||
char buf[32];
|
char buf[32];
|
||||||
|
@ -468,10 +469,11 @@ static ssize_t write_file_bool(struct file *file, const char __user *user_buf,
|
||||||
|
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(debugfs_write_file_bool);
|
||||||
|
|
||||||
static const struct file_operations fops_bool = {
|
static const struct file_operations fops_bool = {
|
||||||
.read = read_file_bool,
|
.read = debugfs_read_file_bool,
|
||||||
.write = write_file_bool,
|
.write = debugfs_write_file_bool,
|
||||||
.open = simple_open,
|
.open = simple_open,
|
||||||
.llseek = default_llseek,
|
.llseek = default_llseek,
|
||||||
};
|
};
|
||||||
|
|
|
@ -116,6 +116,12 @@ struct dentry *debugfs_create_devm_seqfile(struct device *dev, const char *name,
|
||||||
|
|
||||||
bool debugfs_initialized(void);
|
bool debugfs_initialized(void);
|
||||||
|
|
||||||
|
ssize_t debugfs_read_file_bool(struct file *file, char __user *user_buf,
|
||||||
|
size_t count, loff_t *ppos);
|
||||||
|
|
||||||
|
ssize_t debugfs_write_file_bool(struct file *file, const char __user *user_buf,
|
||||||
|
size_t count, loff_t *ppos);
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#include <linux/err.h>
|
#include <linux/err.h>
|
||||||
|
@ -282,6 +288,20 @@ static inline struct dentry *debugfs_create_devm_seqfile(struct device *dev,
|
||||||
return ERR_PTR(-ENODEV);
|
return ERR_PTR(-ENODEV);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline ssize_t debugfs_read_file_bool(struct file *file,
|
||||||
|
char __user *user_buf,
|
||||||
|
size_t count, loff_t *ppos)
|
||||||
|
{
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline ssize_t debugfs_write_file_bool(struct file *file,
|
||||||
|
const char __user *user_buf,
|
||||||
|
size_t count, loff_t *ppos)
|
||||||
|
{
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#include <linux/rbtree.h>
|
#include <linux/rbtree.h>
|
||||||
#include <linux/err.h>
|
#include <linux/err.h>
|
||||||
#include <linux/bug.h>
|
#include <linux/bug.h>
|
||||||
|
#include <linux/lockdep.h>
|
||||||
|
|
||||||
struct module;
|
struct module;
|
||||||
struct device;
|
struct device;
|
||||||
|
@ -51,14 +52,17 @@ struct reg_default {
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register/value pairs for sequences of writes
|
* Register/value pairs for sequences of writes with an optional delay in
|
||||||
|
* microseconds to be applied after each write.
|
||||||
*
|
*
|
||||||
* @reg: Register address.
|
* @reg: Register address.
|
||||||
* @def: Register value.
|
* @def: Register value.
|
||||||
|
* @delay_us: Delay to be applied after the register write in microseconds
|
||||||
*/
|
*/
|
||||||
struct reg_sequence {
|
struct reg_sequence {
|
||||||
unsigned int reg;
|
unsigned int reg;
|
||||||
unsigned int def;
|
unsigned int def;
|
||||||
|
unsigned int delay_us;
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef CONFIG_REGMAP
|
#ifdef CONFIG_REGMAP
|
||||||
|
@ -307,8 +311,12 @@ typedef void (*regmap_hw_free_context)(void *context);
|
||||||
* if not implemented on a given device.
|
* if not implemented on a given device.
|
||||||
* @async_write: Write operation which completes asynchronously, optional and
|
* @async_write: Write operation which completes asynchronously, optional and
|
||||||
* must serialise with respect to non-async I/O.
|
* must serialise with respect to non-async I/O.
|
||||||
|
* @reg_write: Write a single register value to the given register address. This
|
||||||
|
* write operation has to complete when returning from the function.
|
||||||
* @read: Read operation. Data is returned in the buffer used to transmit
|
* @read: Read operation. Data is returned in the buffer used to transmit
|
||||||
* data.
|
* data.
|
||||||
|
* @reg_read: Read a single register value from a given register address.
|
||||||
|
* @free_context: Free context.
|
||||||
* @async_alloc: Allocate a regmap_async() structure.
|
* @async_alloc: Allocate a regmap_async() structure.
|
||||||
* @read_flag_mask: Mask to be set in the top byte of the register when doing
|
* @read_flag_mask: Mask to be set in the top byte of the register when doing
|
||||||
* a read.
|
* a read.
|
||||||
|
@ -318,7 +326,8 @@ typedef void (*regmap_hw_free_context)(void *context);
|
||||||
* @val_format_endian_default: Default endianness for formatted register
|
* @val_format_endian_default: Default endianness for formatted register
|
||||||
* values. Used when the regmap_config specifies DEFAULT. If this is
|
* values. Used when the regmap_config specifies DEFAULT. If this is
|
||||||
* DEFAULT, BIG is assumed.
|
* DEFAULT, BIG is assumed.
|
||||||
* @async_size: Size of struct used for async work.
|
* @max_raw_read: Max raw read size that can be used on the bus.
|
||||||
|
* @max_raw_write: Max raw write size that can be used on the bus.
|
||||||
*/
|
*/
|
||||||
struct regmap_bus {
|
struct regmap_bus {
|
||||||
bool fast_io;
|
bool fast_io;
|
||||||
|
@ -333,47 +342,186 @@ struct regmap_bus {
|
||||||
u8 read_flag_mask;
|
u8 read_flag_mask;
|
||||||
enum regmap_endian reg_format_endian_default;
|
enum regmap_endian reg_format_endian_default;
|
||||||
enum regmap_endian val_format_endian_default;
|
enum regmap_endian val_format_endian_default;
|
||||||
|
size_t max_raw_read;
|
||||||
|
size_t max_raw_write;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct regmap *regmap_init(struct device *dev,
|
/*
|
||||||
|
* __regmap_init functions.
|
||||||
|
*
|
||||||
|
* These functions take a lock key and name parameter, and should not be called
|
||||||
|
* directly. Instead, use the regmap_init macros that generate a key and name
|
||||||
|
* for each call.
|
||||||
|
*/
|
||||||
|
struct regmap *__regmap_init(struct device *dev,
|
||||||
const struct regmap_bus *bus,
|
const struct regmap_bus *bus,
|
||||||
void *bus_context,
|
void *bus_context,
|
||||||
const struct regmap_config *config);
|
const struct regmap_config *config,
|
||||||
|
struct lock_class_key *lock_key,
|
||||||
|
const char *lock_name);
|
||||||
|
struct regmap *__regmap_init_i2c(struct i2c_client *i2c,
|
||||||
|
const struct regmap_config *config,
|
||||||
|
struct lock_class_key *lock_key,
|
||||||
|
const char *lock_name);
|
||||||
|
struct regmap *__regmap_init_spi(struct spi_device *dev,
|
||||||
|
const struct regmap_config *config,
|
||||||
|
struct lock_class_key *lock_key,
|
||||||
|
const char *lock_name);
|
||||||
|
struct regmap *__regmap_init_spmi_base(struct spmi_device *dev,
|
||||||
|
const struct regmap_config *config,
|
||||||
|
struct lock_class_key *lock_key,
|
||||||
|
const char *lock_name);
|
||||||
|
struct regmap *__regmap_init_spmi_ext(struct spmi_device *dev,
|
||||||
|
const struct regmap_config *config,
|
||||||
|
struct lock_class_key *lock_key,
|
||||||
|
const char *lock_name);
|
||||||
|
struct regmap *__regmap_init_mmio_clk(struct device *dev, const char *clk_id,
|
||||||
|
void __iomem *regs,
|
||||||
|
const struct regmap_config *config,
|
||||||
|
struct lock_class_key *lock_key,
|
||||||
|
const char *lock_name);
|
||||||
|
struct regmap *__regmap_init_ac97(struct snd_ac97 *ac97,
|
||||||
|
const struct regmap_config *config,
|
||||||
|
struct lock_class_key *lock_key,
|
||||||
|
const char *lock_name);
|
||||||
|
|
||||||
|
struct regmap *__devm_regmap_init(struct device *dev,
|
||||||
|
const struct regmap_bus *bus,
|
||||||
|
void *bus_context,
|
||||||
|
const struct regmap_config *config,
|
||||||
|
struct lock_class_key *lock_key,
|
||||||
|
const char *lock_name);
|
||||||
|
struct regmap *__devm_regmap_init_i2c(struct i2c_client *i2c,
|
||||||
|
const struct regmap_config *config,
|
||||||
|
struct lock_class_key *lock_key,
|
||||||
|
const char *lock_name);
|
||||||
|
struct regmap *__devm_regmap_init_spi(struct spi_device *dev,
|
||||||
|
const struct regmap_config *config,
|
||||||
|
struct lock_class_key *lock_key,
|
||||||
|
const char *lock_name);
|
||||||
|
struct regmap *__devm_regmap_init_spmi_base(struct spmi_device *dev,
|
||||||
|
const struct regmap_config *config,
|
||||||
|
struct lock_class_key *lock_key,
|
||||||
|
const char *lock_name);
|
||||||
|
struct regmap *__devm_regmap_init_spmi_ext(struct spmi_device *dev,
|
||||||
|
const struct regmap_config *config,
|
||||||
|
struct lock_class_key *lock_key,
|
||||||
|
const char *lock_name);
|
||||||
|
struct regmap *__devm_regmap_init_mmio_clk(struct device *dev,
|
||||||
|
const char *clk_id,
|
||||||
|
void __iomem *regs,
|
||||||
|
const struct regmap_config *config,
|
||||||
|
struct lock_class_key *lock_key,
|
||||||
|
const char *lock_name);
|
||||||
|
struct regmap *__devm_regmap_init_ac97(struct snd_ac97 *ac97,
|
||||||
|
const struct regmap_config *config,
|
||||||
|
struct lock_class_key *lock_key,
|
||||||
|
const char *lock_name);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Wrapper for regmap_init macros to include a unique lockdep key and name
|
||||||
|
* for each call. No-op if CONFIG_LOCKDEP is not set.
|
||||||
|
*
|
||||||
|
* @fn: Real function to call (in the form __[*_]regmap_init[_*])
|
||||||
|
* @name: Config variable name (#config in the calling macro)
|
||||||
|
**/
|
||||||
|
#ifdef CONFIG_LOCKDEP
|
||||||
|
#define __regmap_lockdep_wrapper(fn, name, ...) \
|
||||||
|
( \
|
||||||
|
({ \
|
||||||
|
static struct lock_class_key _key; \
|
||||||
|
fn(__VA_ARGS__, &_key, \
|
||||||
|
KBUILD_BASENAME ":" \
|
||||||
|
__stringify(__LINE__) ":" \
|
||||||
|
"(" name ")->lock"); \
|
||||||
|
}) \
|
||||||
|
)
|
||||||
|
#else
|
||||||
|
#define __regmap_lockdep_wrapper(fn, name, ...) fn(__VA_ARGS__, NULL, NULL)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* regmap_init(): Initialise register map
|
||||||
|
*
|
||||||
|
* @dev: Device that will be interacted with
|
||||||
|
* @bus: Bus-specific callbacks to use with device
|
||||||
|
* @bus_context: Data passed to bus-specific callbacks
|
||||||
|
* @config: Configuration for register map
|
||||||
|
*
|
||||||
|
* The return value will be an ERR_PTR() on error or a valid pointer to
|
||||||
|
* a struct regmap. This function should generally not be called
|
||||||
|
* directly, it should be called by bus-specific init functions.
|
||||||
|
*/
|
||||||
|
#define regmap_init(dev, bus, bus_context, config) \
|
||||||
|
__regmap_lockdep_wrapper(__regmap_init, #config, \
|
||||||
|
dev, bus, bus_context, config)
|
||||||
int regmap_attach_dev(struct device *dev, struct regmap *map,
|
int regmap_attach_dev(struct device *dev, struct regmap *map,
|
||||||
const struct regmap_config *config);
|
const struct regmap_config *config);
|
||||||
struct regmap *regmap_init_i2c(struct i2c_client *i2c,
|
|
||||||
const struct regmap_config *config);
|
|
||||||
struct regmap *regmap_init_spi(struct spi_device *dev,
|
|
||||||
const struct regmap_config *config);
|
|
||||||
struct regmap *regmap_init_spmi_base(struct spmi_device *dev,
|
|
||||||
const struct regmap_config *config);
|
|
||||||
struct regmap *regmap_init_spmi_ext(struct spmi_device *dev,
|
|
||||||
const struct regmap_config *config);
|
|
||||||
struct regmap *regmap_init_mmio_clk(struct device *dev, const char *clk_id,
|
|
||||||
void __iomem *regs,
|
|
||||||
const struct regmap_config *config);
|
|
||||||
struct regmap *regmap_init_ac97(struct snd_ac97 *ac97,
|
|
||||||
const struct regmap_config *config);
|
|
||||||
|
|
||||||
struct regmap *devm_regmap_init(struct device *dev,
|
/**
|
||||||
const struct regmap_bus *bus,
|
* regmap_init_i2c(): Initialise register map
|
||||||
void *bus_context,
|
*
|
||||||
const struct regmap_config *config);
|
* @i2c: Device that will be interacted with
|
||||||
struct regmap *devm_regmap_init_i2c(struct i2c_client *i2c,
|
* @config: Configuration for register map
|
||||||
const struct regmap_config *config);
|
*
|
||||||
struct regmap *devm_regmap_init_spi(struct spi_device *dev,
|
* The return value will be an ERR_PTR() on error or a valid pointer to
|
||||||
const struct regmap_config *config);
|
* a struct regmap.
|
||||||
struct regmap *devm_regmap_init_spmi_base(struct spmi_device *dev,
|
*/
|
||||||
const struct regmap_config *config);
|
#define regmap_init_i2c(i2c, config) \
|
||||||
struct regmap *devm_regmap_init_spmi_ext(struct spmi_device *dev,
|
__regmap_lockdep_wrapper(__regmap_init_i2c, #config, \
|
||||||
const struct regmap_config *config);
|
i2c, config)
|
||||||
struct regmap *devm_regmap_init_mmio_clk(struct device *dev, const char *clk_id,
|
|
||||||
void __iomem *regs,
|
|
||||||
const struct regmap_config *config);
|
|
||||||
struct regmap *devm_regmap_init_ac97(struct snd_ac97 *ac97,
|
|
||||||
const struct regmap_config *config);
|
|
||||||
|
|
||||||
bool regmap_ac97_default_volatile(struct device *dev, unsigned int reg);
|
/**
|
||||||
|
* regmap_init_spi(): Initialise register map
|
||||||
|
*
|
||||||
|
* @spi: Device that will be interacted with
|
||||||
|
* @config: Configuration for register map
|
||||||
|
*
|
||||||
|
* The return value will be an ERR_PTR() on error or a valid pointer to
|
||||||
|
* a struct regmap.
|
||||||
|
*/
|
||||||
|
#define regmap_init_spi(dev, config) \
|
||||||
|
__regmap_lockdep_wrapper(__regmap_init_spi, #config, \
|
||||||
|
dev, config)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* regmap_init_spmi_base(): Create regmap for the Base register space
|
||||||
|
* @sdev: SPMI device that will be interacted with
|
||||||
|
* @config: Configuration for register map
|
||||||
|
*
|
||||||
|
* The return value will be an ERR_PTR() on error or a valid pointer to
|
||||||
|
* a struct regmap.
|
||||||
|
*/
|
||||||
|
#define regmap_init_spmi_base(dev, config) \
|
||||||
|
__regmap_lockdep_wrapper(__regmap_init_spmi_base, #config, \
|
||||||
|
dev, config)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* regmap_init_spmi_ext(): Create regmap for Ext register space
|
||||||
|
* @sdev: Device that will be interacted with
|
||||||
|
* @config: Configuration for register map
|
||||||
|
*
|
||||||
|
* The return value will be an ERR_PTR() on error or a valid pointer to
|
||||||
|
* a struct regmap.
|
||||||
|
*/
|
||||||
|
#define regmap_init_spmi_ext(dev, config) \
|
||||||
|
__regmap_lockdep_wrapper(__regmap_init_spmi_ext, #config, \
|
||||||
|
dev, config)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* regmap_init_mmio_clk(): Initialise register map with register clock
|
||||||
|
*
|
||||||
|
* @dev: Device that will be interacted with
|
||||||
|
* @clk_id: register clock consumer ID
|
||||||
|
* @regs: Pointer to memory-mapped IO region
|
||||||
|
* @config: Configuration for register map
|
||||||
|
*
|
||||||
|
* The return value will be an ERR_PTR() on error or a valid pointer to
|
||||||
|
* a struct regmap.
|
||||||
|
*/
|
||||||
|
#define regmap_init_mmio_clk(dev, clk_id, regs, config) \
|
||||||
|
__regmap_lockdep_wrapper(__regmap_init_mmio_clk, #config, \
|
||||||
|
dev, clk_id, regs, config)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* regmap_init_mmio(): Initialise register map
|
* regmap_init_mmio(): Initialise register map
|
||||||
|
@ -385,12 +533,109 @@ bool regmap_ac97_default_volatile(struct device *dev, unsigned int reg);
|
||||||
* The return value will be an ERR_PTR() on error or a valid pointer to
|
* The return value will be an ERR_PTR() on error or a valid pointer to
|
||||||
* a struct regmap.
|
* a struct regmap.
|
||||||
*/
|
*/
|
||||||
static inline struct regmap *regmap_init_mmio(struct device *dev,
|
#define regmap_init_mmio(dev, regs, config) \
|
||||||
void __iomem *regs,
|
regmap_init_mmio_clk(dev, NULL, regs, config)
|
||||||
const struct regmap_config *config)
|
|
||||||
{
|
/**
|
||||||
return regmap_init_mmio_clk(dev, NULL, regs, config);
|
* regmap_init_ac97(): Initialise AC'97 register map
|
||||||
}
|
*
|
||||||
|
* @ac97: Device that will be interacted with
|
||||||
|
* @config: Configuration for register map
|
||||||
|
*
|
||||||
|
* The return value will be an ERR_PTR() on error or a valid pointer to
|
||||||
|
* a struct regmap.
|
||||||
|
*/
|
||||||
|
#define regmap_init_ac97(ac97, config) \
|
||||||
|
__regmap_lockdep_wrapper(__regmap_init_ac97, #config, \
|
||||||
|
ac97, config)
|
||||||
|
bool regmap_ac97_default_volatile(struct device *dev, unsigned int reg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* devm_regmap_init(): Initialise managed register map
|
||||||
|
*
|
||||||
|
* @dev: Device that will be interacted with
|
||||||
|
* @bus: Bus-specific callbacks to use with device
|
||||||
|
* @bus_context: Data passed to bus-specific callbacks
|
||||||
|
* @config: Configuration for register map
|
||||||
|
*
|
||||||
|
* The return value will be an ERR_PTR() on error or a valid pointer
|
||||||
|
* to a struct regmap. This function should generally not be called
|
||||||
|
* directly, it should be called by bus-specific init functions. The
|
||||||
|
* map will be automatically freed by the device management code.
|
||||||
|
*/
|
||||||
|
#define devm_regmap_init(dev, bus, bus_context, config) \
|
||||||
|
__regmap_lockdep_wrapper(__devm_regmap_init, #config, \
|
||||||
|
dev, bus, bus_context, config)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* devm_regmap_init_i2c(): Initialise managed register map
|
||||||
|
*
|
||||||
|
* @i2c: Device that will be interacted with
|
||||||
|
* @config: Configuration for register map
|
||||||
|
*
|
||||||
|
* The return value will be an ERR_PTR() on error or a valid pointer
|
||||||
|
* to a struct regmap. The regmap will be automatically freed by the
|
||||||
|
* device management code.
|
||||||
|
*/
|
||||||
|
#define devm_regmap_init_i2c(i2c, config) \
|
||||||
|
__regmap_lockdep_wrapper(__devm_regmap_init_i2c, #config, \
|
||||||
|
i2c, config)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* devm_regmap_init_spi(): Initialise register map
|
||||||
|
*
|
||||||
|
* @spi: Device that will be interacted with
|
||||||
|
* @config: Configuration for register map
|
||||||
|
*
|
||||||
|
* The return value will be an ERR_PTR() on error or a valid pointer
|
||||||
|
* to a struct regmap. The map will be automatically freed by the
|
||||||
|
* device management code.
|
||||||
|
*/
|
||||||
|
#define devm_regmap_init_spi(dev, config) \
|
||||||
|
__regmap_lockdep_wrapper(__devm_regmap_init_spi, #config, \
|
||||||
|
dev, config)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* devm_regmap_init_spmi_base(): Create managed regmap for Base register space
|
||||||
|
* @sdev: SPMI device that will be interacted with
|
||||||
|
* @config: Configuration for register map
|
||||||
|
*
|
||||||
|
* The return value will be an ERR_PTR() on error or a valid pointer
|
||||||
|
* to a struct regmap. The regmap will be automatically freed by the
|
||||||
|
* device management code.
|
||||||
|
*/
|
||||||
|
#define devm_regmap_init_spmi_base(dev, config) \
|
||||||
|
__regmap_lockdep_wrapper(__devm_regmap_init_spmi_base, #config, \
|
||||||
|
dev, config)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* devm_regmap_init_spmi_ext(): Create managed regmap for Ext register space
|
||||||
|
* @sdev: SPMI device that will be interacted with
|
||||||
|
* @config: Configuration for register map
|
||||||
|
*
|
||||||
|
* The return value will be an ERR_PTR() on error or a valid pointer
|
||||||
|
* to a struct regmap. The regmap will be automatically freed by the
|
||||||
|
* device management code.
|
||||||
|
*/
|
||||||
|
#define devm_regmap_init_spmi_ext(dev, config) \
|
||||||
|
__regmap_lockdep_wrapper(__devm_regmap_init_spmi_ext, #config, \
|
||||||
|
dev, config)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* devm_regmap_init_mmio_clk(): Initialise managed register map with clock
|
||||||
|
*
|
||||||
|
* @dev: Device that will be interacted with
|
||||||
|
* @clk_id: register clock consumer ID
|
||||||
|
* @regs: Pointer to memory-mapped IO region
|
||||||
|
* @config: Configuration for register map
|
||||||
|
*
|
||||||
|
* The return value will be an ERR_PTR() on error or a valid pointer
|
||||||
|
* to a struct regmap. The regmap will be automatically freed by the
|
||||||
|
* device management code.
|
||||||
|
*/
|
||||||
|
#define devm_regmap_init_mmio_clk(dev, clk_id, regs, config) \
|
||||||
|
__regmap_lockdep_wrapper(__devm_regmap_init_mmio_clk, #config, \
|
||||||
|
dev, clk_id, regs, config)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* devm_regmap_init_mmio(): Initialise managed register map
|
* devm_regmap_init_mmio(): Initialise managed register map
|
||||||
|
@ -403,12 +648,22 @@ static inline struct regmap *regmap_init_mmio(struct device *dev,
|
||||||
* to a struct regmap. The regmap will be automatically freed by the
|
* to a struct regmap. The regmap will be automatically freed by the
|
||||||
* device management code.
|
* device management code.
|
||||||
*/
|
*/
|
||||||
static inline struct regmap *devm_regmap_init_mmio(struct device *dev,
|
#define devm_regmap_init_mmio(dev, regs, config) \
|
||||||
void __iomem *regs,
|
devm_regmap_init_mmio_clk(dev, NULL, regs, config)
|
||||||
const struct regmap_config *config)
|
|
||||||
{
|
/**
|
||||||
return devm_regmap_init_mmio_clk(dev, NULL, regs, config);
|
* devm_regmap_init_ac97(): Initialise AC'97 register map
|
||||||
}
|
*
|
||||||
|
* @ac97: Device that will be interacted with
|
||||||
|
* @config: Configuration for register map
|
||||||
|
*
|
||||||
|
* The return value will be an ERR_PTR() on error or a valid pointer
|
||||||
|
* to a struct regmap. The regmap will be automatically freed by the
|
||||||
|
* device management code.
|
||||||
|
*/
|
||||||
|
#define devm_regmap_init_ac97(ac97, config) \
|
||||||
|
__regmap_lockdep_wrapper(__devm_regmap_init_ac97, #config, \
|
||||||
|
ac97, config)
|
||||||
|
|
||||||
void regmap_exit(struct regmap *map);
|
void regmap_exit(struct regmap *map);
|
||||||
int regmap_reinit_cache(struct regmap *map,
|
int regmap_reinit_cache(struct regmap *map,
|
||||||
|
@ -450,6 +705,8 @@ int regmap_get_max_register(struct regmap *map);
|
||||||
int regmap_get_reg_stride(struct regmap *map);
|
int regmap_get_reg_stride(struct regmap *map);
|
||||||
int regmap_async_complete(struct regmap *map);
|
int regmap_async_complete(struct regmap *map);
|
||||||
bool regmap_can_raw_write(struct regmap *map);
|
bool regmap_can_raw_write(struct regmap *map);
|
||||||
|
size_t regmap_get_raw_read_max(struct regmap *map);
|
||||||
|
size_t regmap_get_raw_write_max(struct regmap *map);
|
||||||
|
|
||||||
int regcache_sync(struct regmap *map);
|
int regcache_sync(struct regmap *map);
|
||||||
int regcache_sync_region(struct regmap *map, unsigned int min,
|
int regcache_sync_region(struct regmap *map, unsigned int min,
|
||||||
|
|
Loading…
Reference in New Issue