Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c6b38ec0 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull regmap updates from Mark Brown:
 "Quite a busy release for regmap this time around, the standout changes
  are:

   - A real implementation of regmap_multi_write() and a bypassed
     version of it for use by drivers doing patch-like things with more
     open coding for surrounding startup sequences.
   - Support fast_io on bulk operations.
   - Support split device binding and map initialisation for use by
     devices required in early init (mainly system controllers).
   - Fixes for some operations on maps with strides set.
   - Export the value parsing operations to help generic code built on
     top of the API.
   - Support for MMIO regmaps with non-32 bit register sizes.

  plus a few smaller fixes"

* tag 'regmap-v3.15' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap: (22 commits)
  regmap: mmio: Add regmap_mmio_regbits_check.
  regmap: mmio: Add support for 1/2/8 bytes wide register address.
  regmap: mmio: add regmap_mmio_{regsize, count}_check.
  regmap: cache: Don't attempt to sync non-writeable registers
  regmap: cache: Step by stride in default sync
  regmap: Fix possible sleep-in-atomic in regmap_bulk_write()
  regmap: Ensure regmap_register_patch() is compatible with fast_io
  regmap: irq: Set data pointer only on regmap_add_irq_chip success
  regmap: Implementation for regmap_multi_reg_write
  regmap: add regmap_parse_val api
  mfd: arizona: Use new regmap features for manual register patch
  regmap: Base regmap_register_patch on _regmap_multi_reg_write
  regmap: Add bypassed version of regmap_multi_reg_write
  regmap: Mark reg_defaults in regmap_multi_reg_write as const
  regmap: fix coccinelle warnings
  regmap: Check stride of register patch as we register it
  regmap: Clean up _regmap_update_bits()
  regmap: Separate regmap dev initialization
  regmap: Check readable regs in _regmap_read
  regmap: irq: Remove domain on exit
  ...
parents d64b3932 6012b1f3
Loading
Loading
Loading
Loading
+2 −0
Original line number Original line Diff line number Diff line
@@ -134,6 +134,8 @@ struct regmap {


	/* if set, converts bulk rw to single rw */
	/* if set, converts bulk rw to single rw */
	bool use_single_rw;
	bool use_single_rw;
	/* if set, the device supports multi write mode */
	bool can_multi_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 */
+5 −8
Original line number Original line Diff line number Diff line
@@ -249,11 +249,12 @@ static int regcache_default_sync(struct regmap *map, unsigned int min,
{
{
	unsigned int reg;
	unsigned int reg;


	for (reg = min; reg <= max; reg++) {
	for (reg = min; reg <= max; reg += map->reg_stride) {
		unsigned int val;
		unsigned int val;
		int ret;
		int ret;


		if (regmap_volatile(map, reg))
		if (regmap_volatile(map, reg) ||
		    !regmap_writeable(map, reg))
			continue;
			continue;


		ret = regcache_read(map, reg, &val);
		ret = regcache_read(map, reg, &val);
@@ -312,10 +313,6 @@ int regcache_sync(struct regmap *map)
	/* Apply any patch first */
	/* Apply any patch first */
	map->cache_bypass = 1;
	map->cache_bypass = 1;
	for (i = 0; i < map->patch_regs; i++) {
	for (i = 0; i < map->patch_regs; i++) {
		if (map->patch[i].reg % map->reg_stride) {
			ret = -EINVAL;
			goto out;
		}
		ret = _regmap_write(map, map->patch[i].reg, map->patch[i].def);
		ret = _regmap_write(map, map->patch[i].reg, map->patch[i].def);
		if (ret != 0) {
		if (ret != 0) {
			dev_err(map->dev, "Failed to write %x = %x: %d\n",
			dev_err(map->dev, "Failed to write %x = %x: %d\n",
@@ -636,10 +633,10 @@ static int regcache_sync_block_raw_flush(struct regmap *map, const void **data,
	if (*data == NULL)
	if (*data == NULL)
		return 0;
		return 0;


	count = cur - base;
	count = (cur - base) / map->reg_stride;


	dev_dbg(map->dev, "Writing %zu bytes for %d registers from 0x%x-0x%x\n",
	dev_dbg(map->dev, "Writing %zu bytes for %d registers from 0x%x-0x%x\n",
		count * val_bytes, count, base, cur - 1);
		count * val_bytes, count, base, cur - map->reg_stride);


	map->cache_bypass = 1;
	map->cache_bypass = 1;


+1 −1
Original line number Original line Diff line number Diff line
@@ -511,7 +511,7 @@ void regmap_debugfs_init(struct regmap *map, const char *name)
	debugfs_create_file("range", 0400, map->debugfs,
	debugfs_create_file("range", 0400, map->debugfs,
			    map, &regmap_reg_ranges_fops);
			    map, &regmap_reg_ranges_fops);


	if (map->max_register) {
	if (map->max_register || regmap_readable(map, 0)) {
		debugfs_create_file("registers", 0400, map->debugfs,
		debugfs_create_file("registers", 0400, map->debugfs,
				    map, &regmap_map_fops);
				    map, &regmap_map_fops);
		debugfs_create_file("access", 0400, map->debugfs,
		debugfs_create_file("access", 0400, map->debugfs,
+3 −3
Original line number Original line Diff line number Diff line
@@ -368,8 +368,6 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags,
	if (!d)
	if (!d)
		return -ENOMEM;
		return -ENOMEM;


	*data = d;

	d->status_buf = kzalloc(sizeof(unsigned int) * chip->num_regs,
	d->status_buf = kzalloc(sizeof(unsigned int) * chip->num_regs,
				GFP_KERNEL);
				GFP_KERNEL);
	if (!d->status_buf)
	if (!d->status_buf)
@@ -506,6 +504,8 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags,
		goto err_domain;
		goto err_domain;
	}
	}


	*data = d;

	return 0;
	return 0;


err_domain:
err_domain:
@@ -533,7 +533,7 @@ void regmap_del_irq_chip(int irq, struct regmap_irq_chip_data *d)
		return;
		return;


	free_irq(irq, d);
	free_irq(irq, d);
	/* We should unmap the domain but... */
	irq_domain_remove(d->domain);
	kfree(d->wake_buf);
	kfree(d->wake_buf);
	kfree(d->mask_buf_def);
	kfree(d->mask_buf_def);
	kfree(d->mask_buf);
	kfree(d->mask_buf);
+50 −6
Original line number Original line Diff line number Diff line
@@ -26,10 +26,47 @@


struct regmap_mmio_context {
struct regmap_mmio_context {
	void __iomem *regs;
	void __iomem *regs;
	unsigned reg_bytes;
	unsigned val_bytes;
	unsigned val_bytes;
	unsigned pad_bytes;
	struct clk *clk;
	struct clk *clk;
};
};


static inline void regmap_mmio_regsize_check(size_t reg_size)
{
	switch (reg_size) {
	case 1:
	case 2:
	case 4:
#ifdef CONFIG_64BIT
	case 8:
#endif
		break;
	default:
		BUG();
	}
}

static int regmap_mmio_regbits_check(size_t reg_bits)
{
	switch (reg_bits) {
	case 8:
	case 16:
	case 32:
#ifdef CONFIG_64BIT
	case 64:
#endif
		return 0;
	default:
		return -EINVAL;
	}
}

static inline void regmap_mmio_count_check(size_t count)
{
	BUG_ON(count % 2 != 0);
}

static int regmap_mmio_gather_write(void *context,
static int regmap_mmio_gather_write(void *context,
				    const void *reg, size_t reg_size,
				    const void *reg, size_t reg_size,
				    const void *val, size_t val_size)
				    const void *val, size_t val_size)
@@ -38,7 +75,7 @@ static int regmap_mmio_gather_write(void *context,
	u32 offset;
	u32 offset;
	int ret;
	int ret;


	BUG_ON(reg_size != 4);
	regmap_mmio_regsize_check(reg_size);


	if (!IS_ERR(ctx->clk)) {
	if (!IS_ERR(ctx->clk)) {
		ret = clk_enable(ctx->clk);
		ret = clk_enable(ctx->clk);
@@ -81,9 +118,13 @@ static int regmap_mmio_gather_write(void *context,


static int regmap_mmio_write(void *context, const void *data, size_t count)
static int regmap_mmio_write(void *context, const void *data, size_t count)
{
{
	BUG_ON(count < 4);
	struct regmap_mmio_context *ctx = context;
	u32 offset = ctx->reg_bytes + ctx->pad_bytes;

	regmap_mmio_count_check(count);


	return regmap_mmio_gather_write(context, data, 4, data + 4, count - 4);
	return regmap_mmio_gather_write(context, data, ctx->reg_bytes,
					data + offset, count - offset);
}
}


static int regmap_mmio_read(void *context,
static int regmap_mmio_read(void *context,
@@ -94,7 +135,7 @@ static int regmap_mmio_read(void *context,
	u32 offset;
	u32 offset;
	int ret;
	int ret;


	BUG_ON(reg_size != 4);
	regmap_mmio_regsize_check(reg_size);


	if (!IS_ERR(ctx->clk)) {
	if (!IS_ERR(ctx->clk)) {
		ret = clk_enable(ctx->clk);
		ret = clk_enable(ctx->clk);
@@ -165,8 +206,9 @@ static struct regmap_mmio_context *regmap_mmio_gen_context(struct device *dev,
	int min_stride;
	int min_stride;
	int ret;
	int ret;


	if (config->reg_bits != 32)
	ret = regmap_mmio_regbits_check(config->reg_bits);
		return ERR_PTR(-EINVAL);
	if (ret)
		return ERR_PTR(ret);


	if (config->pad_bits)
	if (config->pad_bits)
		return ERR_PTR(-EINVAL);
		return ERR_PTR(-EINVAL);
@@ -209,6 +251,8 @@ static struct regmap_mmio_context *regmap_mmio_gen_context(struct device *dev,


	ctx->regs = regs;
	ctx->regs = regs;
	ctx->val_bytes = config->val_bits / 8;
	ctx->val_bytes = config->val_bits / 8;
	ctx->reg_bytes = config->reg_bits / 8;
	ctx->pad_bytes = config->pad_bits / 8;
	ctx->clk = ERR_PTR(-ENODEV);
	ctx->clk = ERR_PTR(-ENODEV);


	if (clk_id == NULL)
	if (clk_id == NULL)
Loading