Commit 9179b73a authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'regmap-v6.12' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap

Pull regmap updates from Mark Brown:
 "The main update here is Matti's work allowing regmap irqdomains to be
  given custom names (allowing multiple interrupt controllers associatd
  with a single struct device), this pulls in some commits from Thomas'
  tree which it depends on.

  Otherwise there's a bit of work on improving handling of regmaps
  protected with spinlocks when used with complex cache types, fixing
  some valid but harmless lockdep reports seen with some new driver
  work"

* tag 'regmap-v6.12' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap:
  regmap: kunit: Add coverage of spinlocked regmaps
  regcache: use map->alloc_flags also for allocating cache
  regmap: Use locking during kunit tests
  regmap: Hold the regmap lock when allocating and freeing the cache
  regmap: Allow setting IRQ domain name suffix
parents c903327d c7edb7ac
......@@ -27,7 +27,7 @@ static int regcache_flat_init(struct regmap *map)
return -EINVAL;
map->cache = kcalloc(regcache_flat_get_index(map, map->max_register)
+ 1, sizeof(unsigned int), GFP_KERNEL);
+ 1, sizeof(unsigned int), map->alloc_flags);
if (!map->cache)
return -ENOMEM;
......
......@@ -348,7 +348,7 @@ static int regcache_maple_init(struct regmap *map)
int ret;
int range_start;
mt = kmalloc(sizeof(*mt), GFP_KERNEL);
mt = kmalloc(sizeof(*mt), map->alloc_flags);
if (!mt)
return -ENOMEM;
map->cache = mt;
......
......@@ -187,7 +187,7 @@ static int regcache_rbtree_init(struct regmap *map)
int i;
int ret;
map->cache = kmalloc(sizeof *rbtree_ctx, GFP_KERNEL);
map->cache = kmalloc(sizeof *rbtree_ctx, map->alloc_flags);
if (!map->cache)
return -ENOMEM;
......
......@@ -195,7 +195,9 @@ int regcache_init(struct regmap *map, const struct regmap_config *config)
if (map->cache_ops->init) {
dev_dbg(map->dev, "Initializing %s cache\n",
map->cache_ops->name);
map->lock(map->lock_arg);
ret = map->cache_ops->init(map);
map->unlock(map->lock_arg);
if (ret)
goto err_free;
}
......@@ -223,7 +225,9 @@ void regcache_exit(struct regmap *map)
if (map->cache_ops->exit) {
dev_dbg(map->dev, "Destroying %s cache\n",
map->cache_ops->name);
map->lock(map->lock_arg);
map->cache_ops->exit(map);
map->unlock(map->lock_arg);
}
}
......
......@@ -608,6 +608,30 @@ int regmap_irq_set_type_config_simple(unsigned int **buf, unsigned int type,
}
EXPORT_SYMBOL_GPL(regmap_irq_set_type_config_simple);
static int regmap_irq_create_domain(struct fwnode_handle *fwnode, int irq_base,
const struct regmap_irq_chip *chip,
struct regmap_irq_chip_data *d)
{
struct irq_domain_info info = {
.fwnode = fwnode,
.size = chip->num_irqs,
.hwirq_max = chip->num_irqs,
.virq_base = irq_base,
.ops = &regmap_domain_ops,
.host_data = d,
.name_suffix = chip->domain_suffix,
};
d->domain = irq_domain_instantiate(&info);
if (IS_ERR(d->domain)) {
dev_err(d->map->dev, "Failed to create IRQ domain\n");
return PTR_ERR(d->domain);
}
return 0;
}
/**
* regmap_add_irq_chip_fwnode() - Use standard regmap IRQ controller handling
*
......@@ -856,18 +880,9 @@ int regmap_add_irq_chip_fwnode(struct fwnode_handle *fwnode,
}
}
if (irq_base)
d->domain = irq_domain_create_legacy(fwnode, chip->num_irqs,
irq_base, 0,
&regmap_domain_ops, d);
else
d->domain = irq_domain_create_linear(fwnode, chip->num_irqs,
&regmap_domain_ops, d);
if (!d->domain) {
dev_err(map->dev, "Failed to create IRQ domain\n");
ret = -ENOMEM;
ret = regmap_irq_create_domain(fwnode, irq_base, chip, d);
if (ret)
goto err_alloc;
}
ret = request_threaded_irq(irq, NULL, regmap_irq_thread,
irq_flags | IRQF_ONESHOT,
......
......@@ -22,6 +22,7 @@ struct regmap_test_param {
enum regmap_endian val_endian;
unsigned int from_reg;
bool fast_io;
};
static void get_changed_bytes(void *orig, void *new, size_t size)
......@@ -80,41 +81,52 @@ static const char *regmap_endian_name(enum regmap_endian endian)
static void param_to_desc(const struct regmap_test_param *param, char *desc)
{
snprintf(desc, KUNIT_PARAM_DESC_SIZE, "%s-%s @%#x",
snprintf(desc, KUNIT_PARAM_DESC_SIZE, "%s-%s%s @%#x",
regcache_type_name(param->cache),
regmap_endian_name(param->val_endian),
param->fast_io ? " fast I/O" : "",
param->from_reg);
}
static const struct regmap_test_param regcache_types_list[] = {
{ .cache = REGCACHE_NONE },
{ .cache = REGCACHE_NONE, .fast_io = true },
{ .cache = REGCACHE_FLAT },
{ .cache = REGCACHE_FLAT, .fast_io = true },
{ .cache = REGCACHE_RBTREE },
{ .cache = REGCACHE_RBTREE, .fast_io = true },
{ .cache = REGCACHE_MAPLE },
{ .cache = REGCACHE_MAPLE, .fast_io = true },
};
KUNIT_ARRAY_PARAM(regcache_types, regcache_types_list, param_to_desc);
static const struct regmap_test_param real_cache_types_only_list[] = {
{ .cache = REGCACHE_FLAT },
{ .cache = REGCACHE_FLAT, .fast_io = true },
{ .cache = REGCACHE_RBTREE },
{ .cache = REGCACHE_RBTREE, .fast_io = true },
{ .cache = REGCACHE_MAPLE },
{ .cache = REGCACHE_MAPLE, .fast_io = true },
};
KUNIT_ARRAY_PARAM(real_cache_types_only, real_cache_types_only_list, param_to_desc);
static const struct regmap_test_param real_cache_types_list[] = {
{ .cache = REGCACHE_FLAT, .from_reg = 0 },
{ .cache = REGCACHE_FLAT, .from_reg = 0, .fast_io = true },
{ .cache = REGCACHE_FLAT, .from_reg = 0x2001 },
{ .cache = REGCACHE_FLAT, .from_reg = 0x2002 },
{ .cache = REGCACHE_FLAT, .from_reg = 0x2003 },
{ .cache = REGCACHE_FLAT, .from_reg = 0x2004 },
{ .cache = REGCACHE_RBTREE, .from_reg = 0 },
{ .cache = REGCACHE_RBTREE, .from_reg = 0, .fast_io = true },
{ .cache = REGCACHE_RBTREE, .from_reg = 0x2001 },
{ .cache = REGCACHE_RBTREE, .from_reg = 0x2002 },
{ .cache = REGCACHE_RBTREE, .from_reg = 0x2003 },
{ .cache = REGCACHE_RBTREE, .from_reg = 0x2004 },
{ .cache = REGCACHE_MAPLE, .from_reg = 0 },
{ .cache = REGCACHE_RBTREE, .from_reg = 0, .fast_io = true },
{ .cache = REGCACHE_MAPLE, .from_reg = 0x2001 },
{ .cache = REGCACHE_MAPLE, .from_reg = 0x2002 },
{ .cache = REGCACHE_MAPLE, .from_reg = 0x2003 },
......@@ -125,11 +137,13 @@ KUNIT_ARRAY_PARAM(real_cache_types, real_cache_types_list, param_to_desc);
static const struct regmap_test_param sparse_cache_types_list[] = {
{ .cache = REGCACHE_RBTREE, .from_reg = 0 },
{ .cache = REGCACHE_RBTREE, .from_reg = 0, .fast_io = true },
{ .cache = REGCACHE_RBTREE, .from_reg = 0x2001 },
{ .cache = REGCACHE_RBTREE, .from_reg = 0x2002 },
{ .cache = REGCACHE_RBTREE, .from_reg = 0x2003 },
{ .cache = REGCACHE_RBTREE, .from_reg = 0x2004 },
{ .cache = REGCACHE_MAPLE, .from_reg = 0 },
{ .cache = REGCACHE_MAPLE, .from_reg = 0, .fast_io = true },
{ .cache = REGCACHE_MAPLE, .from_reg = 0x2001 },
{ .cache = REGCACHE_MAPLE, .from_reg = 0x2002 },
{ .cache = REGCACHE_MAPLE, .from_reg = 0x2003 },
......@@ -151,8 +165,7 @@ static struct regmap *gen_regmap(struct kunit *test,
struct reg_default *defaults;
config->cache_type = param->cache;
config->disable_locking = config->cache_type == REGCACHE_RBTREE ||
config->cache_type == REGCACHE_MAPLE;
config->fast_io = param->fast_io;
if (config->max_register == 0) {
config->max_register = param->from_reg;
......
......@@ -1445,6 +1445,7 @@ void regmap_exit(struct regmap *map)
struct regmap_async *async;
regcache_exit(map);
regmap_debugfs_exit(map);
regmap_range_exit(map);
if (map->bus && map->bus->free_context)
......
......@@ -1521,6 +1521,9 @@ struct regmap_irq_chip_data;
* struct regmap_irq_chip - Description of a generic regmap irq_chip.
*
* @name: Descriptive name for IRQ controller.
* @domain_suffix: Name suffix to be appended to end of IRQ domain name. Needed
* when multiple regmap-IRQ controllers are created from same
* device.
*
* @main_status: Base main status register address. For chips which have
* interrupts arranged in separate sub-irq blocks with own IRQ
......@@ -1606,6 +1609,7 @@ struct regmap_irq_chip_data;
*/
struct regmap_irq_chip {
const char *name;
const char *domain_suffix;
unsigned int main_status;
unsigned int num_main_status_bits;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment