All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/2 v3] regmap: Support accelerated noinc operations
@ 2022-08-16 13:08 Linus Walleij
  2022-08-16 13:08 ` [PATCH 2/2 v3] regmap: mmio: Support accelerared " Linus Walleij
  2022-08-17 13:34 ` [PATCH 1/2 v3] regmap: Support accelerated " Mark Brown
  0 siblings, 2 replies; 8+ messages in thread
From: Linus Walleij @ 2022-08-16 13:08 UTC (permalink / raw)
  To: Mark Brown; +Cc: linux-kernel, Linus Walleij

Several architectures have accelerated operations for MMIO
operations writing to a single register, such as writesb, writesw,
writesl, writesq, readsb, readsw, readsl and readsq but regmap
currently cannot use them because we have no hooks for providing
an accelerated noinc back-end for MMIO.

Solve this by providing reg_[read/write]_noinc callbacks for
the bus abstraction, so that the regmap-mmio bus can use this.

Currently I do not see a need to support this for custom regmaps
so it is only added to the bus.

Callbacks are passed a void * with the array of values and a
count which is the number of items of the byte chunk size for
the specific register width.

Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
ChangeLog v2->v3:
- Rebase on kernel v6.0-rc1
ChangeLog v1->v2:
- Factor out and reuse the code to format and read or write a
  buffer of data to a noinc register at the cost of dropping
  const from the buffer pointer in the write call. This is a
  deadly sin in Rust and therefore impossible, but hey, this is
  C, and dropping a const is a lesser evil than not being
  able to reuse code.
---
 drivers/base/regmap/regmap.c | 123 ++++++++++++++++++++++++++++++++++-
 include/linux/regmap.h       |   8 +++
 2 files changed, 128 insertions(+), 3 deletions(-)

diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
index fee221c5008c..dbe2042f92f3 100644
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -2132,6 +2132,99 @@ int regmap_raw_write(struct regmap *map, unsigned int reg,
 }
 EXPORT_SYMBOL_GPL(regmap_raw_write);
 
+static int regmap_noinc_readwrite(struct regmap *map, unsigned int reg,
+				  void *val, unsigned int val_len, bool write)
+{
+	size_t val_bytes = map->format.val_bytes;
+	size_t val_count = val_len / val_bytes;
+	unsigned int lastval;
+	u8 *u8p;
+	u16 *u16p;
+	u32 *u32p;
+#ifdef CONFIG_64BIT
+	u64 *u64p;
+#endif
+	int ret;
+	int i;
+
+	switch (val_bytes) {
+	case 1:
+		u8p = val;
+		if (write)
+			lastval = (unsigned int)u8p[val_count - 1];
+		break;
+	case 2:
+		u16p = val;
+		if (write)
+			lastval = (unsigned int)u16p[val_count - 1];
+		break;
+	case 4:
+		u32p = val;
+		if (write)
+			lastval = (unsigned int)u32p[val_count - 1];
+		break;
+#ifdef CONFIG_64BIT
+	case 8:
+		u64p = val;
+		if (write)
+			lastval = (unsigned int)u64p[val_count - 1];
+		break;
+#endif
+	default:
+		return -EINVAL;
+	}
+
+	/*
+	 * Update the cache with the last value we write, the rest is just
+	 * gone down in the hardware FIFO. We can't cache FIFOs. This makes
+	 * sure a single read from the cache will work.
+	 */
+	if (write) {
+		if (!map->cache_bypass && !map->defer_caching) {
+			ret = regcache_write(map, reg, lastval);
+			if (ret != 0)
+				return ret;
+			if (map->cache_only) {
+				map->cache_dirty = true;
+				return 0;
+			}
+		}
+		ret = map->bus->reg_noinc_write(map->bus_context, reg, val, val_count);
+	} else {
+		ret = map->bus->reg_noinc_read(map->bus_context, reg, val, val_count);
+	}
+
+	if (!ret && regmap_should_log(map)) {
+		dev_info(map->dev, "%x %s [", reg, write ? "<=" : "=>");
+		for (i = 0; i < val_len; i++) {
+			switch (val_bytes) {
+			case 1:
+				pr_cont("%x", u8p[i]);
+				break;
+			case 2:
+				pr_cont("%x", u16p[i]);
+				break;
+			case 4:
+				pr_cont("%x", u32p[i]);
+				break;
+#ifdef CONFIG_64BIT
+			case 8:
+				pr_cont("%llx", u64p[i]);
+				break;
+#endif
+			default:
+				break;
+			}
+			if (i == (val_len - 1))
+				pr_cont("]\n");
+			else
+				pr_cont(",");
+		}
+	}
+
+	return 0;
+}
+
 /**
  * regmap_noinc_write(): Write data from a register without incrementing the
  *			register number
@@ -2159,9 +2252,8 @@ int regmap_noinc_write(struct regmap *map, unsigned int reg,
 	size_t write_len;
 	int ret;
 
-	if (!map->write)
-		return -ENOTSUPP;
-
+	if (!map->write && !(map->bus && map->bus->reg_noinc_write))
+		return -EINVAL;
 	if (val_len % map->format.val_bytes)
 		return -EINVAL;
 	if (!IS_ALIGNED(reg, map->reg_stride))
@@ -2176,6 +2268,15 @@ int regmap_noinc_write(struct regmap *map, unsigned int reg,
 		goto out_unlock;
 	}
 
+	/*
+	 * Use the accelerated operation if we can. The val drops the const
+	 * typing in order to facilitate code reuse in regmap_noinc_readwrite().
+	 */
+	if (map->bus->reg_noinc_write) {
+		ret = regmap_noinc_readwrite(map, reg, (void *)val, val_len, true);
+		goto out_unlock;
+	}
+
 	while (val_len) {
 		if (map->max_raw_write && map->max_raw_write < val_len)
 			write_len = map->max_raw_write;
@@ -2946,6 +3047,22 @@ int regmap_noinc_read(struct regmap *map, unsigned int reg,
 		goto out_unlock;
 	}
 
+	/* Use the accelerated operation if we can */
+	if (map->bus->reg_noinc_read) {
+		/*
+		 * We have not defined the FIFO semantics for cache, as the
+		 * cache is just one value deep. Should we return the last
+		 * written value? Just avoid this by always reading the FIFO
+		 * even when using cache. Cache only will not work.
+		 */
+		if (map->cache_only) {
+			ret = -EBUSY;
+			goto out_unlock;
+		}
+		ret = regmap_noinc_readwrite(map, reg, val, val_len, false);
+		goto out_unlock;
+	}
+
 	while (val_len) {
 		if (map->max_raw_read && map->max_raw_read < val_len)
 			read_len = map->max_raw_read;
diff --git a/include/linux/regmap.h b/include/linux/regmap.h
index 7cf2157134ac..7d4d257b2bf9 100644
--- a/include/linux/regmap.h
+++ b/include/linux/regmap.h
@@ -489,8 +489,12 @@ typedef int (*regmap_hw_read)(void *context,
 			      void *val_buf, size_t val_size);
 typedef int (*regmap_hw_reg_read)(void *context, unsigned int reg,
 				  unsigned int *val);
+typedef int (*regmap_hw_reg_noinc_read)(void *context, unsigned int reg,
+					void *val, size_t val_count);
 typedef int (*regmap_hw_reg_write)(void *context, unsigned int reg,
 				   unsigned int val);
+typedef int (*regmap_hw_reg_noinc_write)(void *context, unsigned int reg,
+					 const void *val, size_t val_count);
 typedef int (*regmap_hw_reg_update_bits)(void *context, unsigned int reg,
 					 unsigned int mask, unsigned int val);
 typedef struct regmap_async *(*regmap_hw_async_alloc)(void);
@@ -511,6 +515,8 @@ typedef void (*regmap_hw_free_context)(void *context);
  *               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.
+ * @reg_write_noinc: Write multiple register value to the same register. This
+ *             write operation has to complete when returning from the function.
  * @reg_update_bits: Update bits operation to be used against volatile
  *                   registers, intended for devices supporting some mechanism
  *                   for setting clearing bits without having to
@@ -538,9 +544,11 @@ struct regmap_bus {
 	regmap_hw_gather_write gather_write;
 	regmap_hw_async_write async_write;
 	regmap_hw_reg_write reg_write;
+	regmap_hw_reg_noinc_write reg_noinc_write;
 	regmap_hw_reg_update_bits reg_update_bits;
 	regmap_hw_read read;
 	regmap_hw_reg_read reg_read;
+	regmap_hw_reg_noinc_read reg_noinc_read;
 	regmap_hw_free_context free_context;
 	regmap_hw_async_alloc async_alloc;
 	u8 read_flag_mask;
-- 
2.37.2


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 2/2 v3] regmap: mmio: Support accelerared noinc operations
  2022-08-16 13:08 [PATCH 1/2 v3] regmap: Support accelerated noinc operations Linus Walleij
@ 2022-08-16 13:08 ` Linus Walleij
  2022-08-16 13:13   ` Mark Brown
  2022-08-16 19:44   ` kernel test robot
  2022-08-17 13:34 ` [PATCH 1/2 v3] regmap: Support accelerated " Mark Brown
  1 sibling, 2 replies; 8+ messages in thread
From: Linus Walleij @ 2022-08-16 13:08 UTC (permalink / raw)
  To: Mark Brown; +Cc: linux-kernel, Linus Walleij

Use the newly added callback for accelerated noinc MMIO
to provide writesb, writesw, writesl, writesq, readsb, readsw,
readsl and readsq.

A special quirk is needed to deal with big endian regmaps: there
are no accelerated operations defined for big endian, so fall
back to calling the big endian operations itereatively for this
case.

Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
ChangeLog v2->v3:
- Rebase on kernel v6.0-rc1
ChangeLog v1->v2:
- No changes.
---
 drivers/base/regmap/regmap-mmio.c | 153 ++++++++++++++++++++++++++++++
 1 file changed, 153 insertions(+)

diff --git a/drivers/base/regmap/regmap-mmio.c b/drivers/base/regmap/regmap-mmio.c
index 71f16be7e717..031ee91020e8 100644
--- a/drivers/base/regmap/regmap-mmio.c
+++ b/drivers/base/regmap/regmap-mmio.c
@@ -17,6 +17,7 @@ struct regmap_mmio_context {
 	void __iomem *regs;
 	unsigned int val_bytes;
 	bool relaxed_mmio;
+	bool big_endian;
 
 	bool attached_clk;
 	struct clk *clk;
@@ -160,6 +161,79 @@ static int regmap_mmio_write(void *context, unsigned int reg, unsigned int val)
 	return 0;
 }
 
+static int regmap_mmio_noinc_write(void *context, unsigned int reg,
+				   const void *val, size_t val_count)
+{
+	struct regmap_mmio_context *ctx = context;
+	int ret = 0;
+	int i;
+
+	if (!IS_ERR(ctx->clk)) {
+		ret = clk_enable(ctx->clk);
+		if (ret < 0)
+			return ret;
+	}
+
+	/*
+	 * There are no native, assembly-optimized write single register
+	 * operations for big endian, so fall back to emulation if this
+	 * is needed. (Single bytes are fine, they are not affected by
+	 * endianness.)
+	 */
+	if (ctx->big_endian && (ctx->val_bytes > 1)) {
+		switch (ctx->val_bytes) {
+		case 2:
+		{
+			const u16 *valp = (const u16 *)val;
+			for (i = 0; i < val_count; i++)
+				iowrite16be(valp[i], ctx->regs + reg);
+			break;
+		}
+		case 4:
+		{
+			const u32 *valp = (const u32 *)val;
+			for (i = 0; i < val_count; i++)
+				iowrite32be(valp[i], ctx->regs + reg);
+			break;
+		}
+#ifdef CONFIG_64BIT
+		case 8:
+			/* This is just too esoteric */
+			fallthrough;
+#endif
+		default:
+			ret = -EINVAL;
+			goto out_clk;
+		}
+	}
+
+	switch (ctx->val_bytes) {
+	case 1:
+		writesb(ctx->regs + reg, (const u8 *)val, val_count);
+		break;
+	case 2:
+		writesw(ctx->regs + reg, (const u16 *)val, val_count);
+		break;
+	case 4:
+		writesl(ctx->regs + reg, (const u32 *)val, val_count);
+		break;
+#ifdef CONFIG_64BIT
+	case 8:
+		writesq(ctx->regs + reg, (const u64 *)val, val_count);
+		break;
+#endif
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+out_clk:
+	if (!IS_ERR(ctx->clk))
+		clk_disable(ctx->clk);
+
+	return ret;
+}
+
 static unsigned int regmap_mmio_read8(struct regmap_mmio_context *ctx,
 				      unsigned int reg)
 {
@@ -241,6 +315,82 @@ static int regmap_mmio_read(void *context, unsigned int reg, unsigned int *val)
 	return 0;
 }
 
+static int regmap_mmio_noinc_read(void *context, unsigned int reg,
+				  void *val, size_t val_count)
+{
+	struct regmap_mmio_context *ctx = context;
+	int ret = 0;
+	int i;
+
+	if (!IS_ERR(ctx->clk)) {
+		ret = clk_enable(ctx->clk);
+		if (ret < 0)
+			return ret;
+	}
+
+	/*
+	 * There are no native, assembly-optimized write single register
+	 * operations for big endian, so fall back to emulation if this
+	 * is needed. (Single bytes are fine, they are not affected by
+	 * endianness.)
+	 */
+	if (ctx->big_endian && (ctx->val_bytes > 1)) {
+		switch (ctx->val_bytes) {
+		case 2:
+		{
+			u16 *valp = (u16 *)val;
+			for (i = 0; i < val_count; i++)
+				valp[i] = ioread16be(ctx->regs + reg);
+			break;
+		}
+		case 4:
+		{
+			u32 *valp = (u32 *)val;
+			for (i = 0; i < val_count; i++)
+				valp[i] = ioread32be(ctx->regs + reg);
+			break;
+		}
+#ifdef CONFIG_64BIT
+		case 8:
+			/* This is just too esoteric */
+			fallthrough;
+#endif
+		default:
+			ret = -EINVAL;
+			goto out_clk;
+		}
+	}
+
+	switch (ctx->val_bytes) {
+	case 1:
+		readsb(ctx->regs + reg, (u8 *)val, val_count);
+		break;
+	case 2:
+		readsw(ctx->regs + reg, (u16 *)val, val_count);
+		break;
+	case 4:
+		readsl(ctx->regs + reg, (u32 *)val, val_count);
+		break;
+#ifdef CONFIG_64BIT
+	case 8:
+		readsq(ctx->regs + reg, (u64 *)val, val_count);
+		break;
+#endif
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+out_clk:
+	if (!IS_ERR(ctx->clk))
+		clk_disable(ctx->clk);
+
+	return ret;
+
+	return 0;
+}
+
+
 static void regmap_mmio_free_context(void *context)
 {
 	struct regmap_mmio_context *ctx = context;
@@ -257,6 +407,8 @@ static const struct regmap_bus regmap_mmio = {
 	.fast_io = true,
 	.reg_write = regmap_mmio_write,
 	.reg_read = regmap_mmio_read,
+	.reg_noinc_write = regmap_mmio_noinc_write,
+	.reg_noinc_read = regmap_mmio_noinc_read,
 	.free_context = regmap_mmio_free_context,
 	.val_format_endian_default = REGMAP_ENDIAN_LITTLE,
 };
@@ -347,6 +499,7 @@ static struct regmap_mmio_context *regmap_mmio_gen_context(struct device *dev,
 #ifdef __BIG_ENDIAN
 	case REGMAP_ENDIAN_NATIVE:
 #endif
+		ctx->big_endian = true;
 		switch (config->val_bits) {
 		case 8:
 			ctx->reg_read = regmap_mmio_read8;
-- 
2.37.2


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH 2/2 v3] regmap: mmio: Support accelerared noinc operations
  2022-08-16 13:08 ` [PATCH 2/2 v3] regmap: mmio: Support accelerared " Linus Walleij
@ 2022-08-16 13:13   ` Mark Brown
  2022-08-16 14:02     ` Linus Walleij
  2022-08-16 19:44   ` kernel test robot
  1 sibling, 1 reply; 8+ messages in thread
From: Mark Brown @ 2022-08-16 13:13 UTC (permalink / raw)
  To: Linus Walleij; +Cc: linux-kernel

[-- Attachment #1: Type: text/plain, Size: 220 bytes --]

On Tue, Aug 16, 2022 at 03:08:23PM +0200, Linus Walleij wrote:

> ChangeLog v2->v3:
> - Rebase on kernel v6.0-rc1

This doesn't apply against current code, please check and resend - I
already applied some other patches.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 2/2 v3] regmap: mmio: Support accelerared noinc operations
  2022-08-16 13:13   ` Mark Brown
@ 2022-08-16 14:02     ` Linus Walleij
  0 siblings, 0 replies; 8+ messages in thread
From: Linus Walleij @ 2022-08-16 14:02 UTC (permalink / raw)
  To: Mark Brown; +Cc: linux-kernel

On Tue, Aug 16, 2022 at 3:13 PM Mark Brown <broonie@kernel.org> wrote:
> On Tue, Aug 16, 2022 at 03:08:23PM +0200, Linus Walleij wrote:
>
> > ChangeLog v2->v3:
> > - Rebase on kernel v6.0-rc1
>
> This doesn't apply against current code, please check and resend - I
> already applied some other patches.

Oopsie I just assumed v6.0-rc1 was clean :D

I'll rebase on your regmap tree, just a sec.

Yours,
Linus Walleij

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 2/2 v3] regmap: mmio: Support accelerared noinc operations
  2022-08-16 13:08 ` [PATCH 2/2 v3] regmap: mmio: Support accelerared " Linus Walleij
  2022-08-16 13:13   ` Mark Brown
@ 2022-08-16 19:44   ` kernel test robot
  2022-08-16 20:50       ` Linus Walleij
  1 sibling, 1 reply; 8+ messages in thread
From: kernel test robot @ 2022-08-16 19:44 UTC (permalink / raw)
  To: Linus Walleij, Mark Brown; +Cc: llvm, kbuild-all, linux-kernel, Linus Walleij

Hi Linus,

I love your patch! Yet something to improve:

[auto build test ERROR on v6.0-rc1]
[also build test ERROR on linus/master]
[cannot apply to broonie-regmap/for-next next-20220816]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Linus-Walleij/regmap-Support-accelerated-noinc-operations/20220816-211403
base:    568035b01cfb107af8d2e4bd2fb9aea22cf5b868
config: hexagon-randconfig-r045-20220815 (https://download.01.org/0day-ci/archive/20220817/202208170316.UKonQfhi-lkp@intel.com/config)
compiler: clang version 16.0.0 (https://github.com/llvm/llvm-project aed5e3bea138ce581d682158eb61c27b3cfdd6ec)
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/intel-lab-lkp/linux/commit/8ab63711dfb48f91d79fff115511f7895ca39180
        git remote add linux-review https://github.com/intel-lab-lkp/linux
        git fetch --no-tags linux-review Linus-Walleij/regmap-Support-accelerated-noinc-operations/20220816-211403
        git checkout 8ab63711dfb48f91d79fff115511f7895ca39180
        # save the config file
        mkdir build_dir && cp config build_dir/.config
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=hexagon SHELL=/bin/bash drivers/base/regmap/

If you fix the issue, kindly add following tag where applicable
Reported-by: kernel test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

>> drivers/base/regmap/regmap-mmio.c:212:3: error: call to undeclared function 'writesb'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
                   writesb(ctx->regs + reg, (const u8 *)val, val_count);
                   ^
   drivers/base/regmap/regmap-mmio.c:212:3: note: did you mean 'writeb'?
   arch/hexagon/include/asm/io.h:122:20: note: 'writeb' declared here
   static inline void writeb(u8 data, volatile void __iomem *addr)
                      ^
>> drivers/base/regmap/regmap-mmio.c:366:3: error: call to undeclared function 'readsb'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
                   readsb(ctx->regs + reg, (u8 *)val, val_count);
                   ^
   drivers/base/regmap/regmap-mmio.c:366:3: note: did you mean 'readb'?
   arch/hexagon/include/asm/io.h:83:18: note: 'readb' declared here
   static inline u8 readb(const volatile void __iomem *addr)
                    ^
   2 errors generated.


vim +/writesb +212 drivers/base/regmap/regmap-mmio.c

   163	
   164	static int regmap_mmio_noinc_write(void *context, unsigned int reg,
   165					   const void *val, size_t val_count)
   166	{
   167		struct regmap_mmio_context *ctx = context;
   168		int ret = 0;
   169		int i;
   170	
   171		if (!IS_ERR(ctx->clk)) {
   172			ret = clk_enable(ctx->clk);
   173			if (ret < 0)
   174				return ret;
   175		}
   176	
   177		/*
   178		 * There are no native, assembly-optimized write single register
   179		 * operations for big endian, so fall back to emulation if this
   180		 * is needed. (Single bytes are fine, they are not affected by
   181		 * endianness.)
   182		 */
   183		if (ctx->big_endian && (ctx->val_bytes > 1)) {
   184			switch (ctx->val_bytes) {
   185			case 2:
   186			{
   187				const u16 *valp = (const u16 *)val;
   188				for (i = 0; i < val_count; i++)
   189					iowrite16be(valp[i], ctx->regs + reg);
   190				break;
   191			}
   192			case 4:
   193			{
   194				const u32 *valp = (const u32 *)val;
   195				for (i = 0; i < val_count; i++)
   196					iowrite32be(valp[i], ctx->regs + reg);
   197				break;
   198			}
   199	#ifdef CONFIG_64BIT
   200			case 8:
   201				/* This is just too esoteric */
   202				fallthrough;
   203	#endif
   204			default:
   205				ret = -EINVAL;
   206				goto out_clk;
   207			}
   208		}
   209	
   210		switch (ctx->val_bytes) {
   211		case 1:
 > 212			writesb(ctx->regs + reg, (const u8 *)val, val_count);
   213			break;
   214		case 2:
   215			writesw(ctx->regs + reg, (const u16 *)val, val_count);
   216			break;
   217		case 4:
   218			writesl(ctx->regs + reg, (const u32 *)val, val_count);
   219			break;
   220	#ifdef CONFIG_64BIT
   221		case 8:
   222			writesq(ctx->regs + reg, (const u64 *)val, val_count);
   223			break;
   224	#endif
   225		default:
   226			ret = -EINVAL;
   227			break;
   228		}
   229	
   230	out_clk:
   231		if (!IS_ERR(ctx->clk))
   232			clk_disable(ctx->clk);
   233	
   234		return ret;
   235	}
   236	
   237	static unsigned int regmap_mmio_read8(struct regmap_mmio_context *ctx,
   238					      unsigned int reg)
   239	{
   240		return readb(ctx->regs + reg);
   241	}
   242	
   243	static unsigned int regmap_mmio_read8_relaxed(struct regmap_mmio_context *ctx,
   244					      unsigned int reg)
   245	{
   246		return readb_relaxed(ctx->regs + reg);
   247	}
   248	
   249	static unsigned int regmap_mmio_read16le(struct regmap_mmio_context *ctx,
   250					         unsigned int reg)
   251	{
   252		return readw(ctx->regs + reg);
   253	}
   254	
   255	static unsigned int regmap_mmio_read16le_relaxed(struct regmap_mmio_context *ctx,
   256							 unsigned int reg)
   257	{
   258		return readw_relaxed(ctx->regs + reg);
   259	}
   260	
   261	static unsigned int regmap_mmio_read16be(struct regmap_mmio_context *ctx,
   262					         unsigned int reg)
   263	{
   264		return ioread16be(ctx->regs + reg);
   265	}
   266	
   267	static unsigned int regmap_mmio_read32le(struct regmap_mmio_context *ctx,
   268					         unsigned int reg)
   269	{
   270		return readl(ctx->regs + reg);
   271	}
   272	
   273	static unsigned int regmap_mmio_read32le_relaxed(struct regmap_mmio_context *ctx,
   274							 unsigned int reg)
   275	{
   276		return readl_relaxed(ctx->regs + reg);
   277	}
   278	
   279	static unsigned int regmap_mmio_read32be(struct regmap_mmio_context *ctx,
   280					         unsigned int reg)
   281	{
   282		return ioread32be(ctx->regs + reg);
   283	}
   284	
   285	#ifdef CONFIG_64BIT
   286	static unsigned int regmap_mmio_read64le(struct regmap_mmio_context *ctx,
   287					         unsigned int reg)
   288	{
   289		return readq(ctx->regs + reg);
   290	}
   291	
   292	static unsigned int regmap_mmio_read64le_relaxed(struct regmap_mmio_context *ctx,
   293							 unsigned int reg)
   294	{
   295		return readq_relaxed(ctx->regs + reg);
   296	}
   297	#endif
   298	
   299	static int regmap_mmio_read(void *context, unsigned int reg, unsigned int *val)
   300	{
   301		struct regmap_mmio_context *ctx = context;
   302		int ret;
   303	
   304		if (!IS_ERR(ctx->clk)) {
   305			ret = clk_enable(ctx->clk);
   306			if (ret < 0)
   307				return ret;
   308		}
   309	
   310		*val = ctx->reg_read(ctx, reg);
   311	
   312		if (!IS_ERR(ctx->clk))
   313			clk_disable(ctx->clk);
   314	
   315		return 0;
   316	}
   317	
   318	static int regmap_mmio_noinc_read(void *context, unsigned int reg,
   319					  void *val, size_t val_count)
   320	{
   321		struct regmap_mmio_context *ctx = context;
   322		int ret = 0;
   323		int i;
   324	
   325		if (!IS_ERR(ctx->clk)) {
   326			ret = clk_enable(ctx->clk);
   327			if (ret < 0)
   328				return ret;
   329		}
   330	
   331		/*
   332		 * There are no native, assembly-optimized write single register
   333		 * operations for big endian, so fall back to emulation if this
   334		 * is needed. (Single bytes are fine, they are not affected by
   335		 * endianness.)
   336		 */
   337		if (ctx->big_endian && (ctx->val_bytes > 1)) {
   338			switch (ctx->val_bytes) {
   339			case 2:
   340			{
   341				u16 *valp = (u16 *)val;
   342				for (i = 0; i < val_count; i++)
   343					valp[i] = ioread16be(ctx->regs + reg);
   344				break;
   345			}
   346			case 4:
   347			{
   348				u32 *valp = (u32 *)val;
   349				for (i = 0; i < val_count; i++)
   350					valp[i] = ioread32be(ctx->regs + reg);
   351				break;
   352			}
   353	#ifdef CONFIG_64BIT
   354			case 8:
   355				/* This is just too esoteric */
   356				fallthrough;
   357	#endif
   358			default:
   359				ret = -EINVAL;
   360				goto out_clk;
   361			}
   362		}
   363	
   364		switch (ctx->val_bytes) {
   365		case 1:
 > 366			readsb(ctx->regs + reg, (u8 *)val, val_count);
   367			break;
   368		case 2:
   369			readsw(ctx->regs + reg, (u16 *)val, val_count);
   370			break;
   371		case 4:
   372			readsl(ctx->regs + reg, (u32 *)val, val_count);
   373			break;
   374	#ifdef CONFIG_64BIT
   375		case 8:
   376			readsq(ctx->regs + reg, (u64 *)val, val_count);
   377			break;
   378	#endif
   379		default:
   380			ret = -EINVAL;
   381			break;
   382		}
   383	
   384	out_clk:
   385		if (!IS_ERR(ctx->clk))
   386			clk_disable(ctx->clk);
   387	
   388		return ret;
   389	
   390		return 0;
   391	}
   392	

-- 
0-DAY CI Kernel Test Service
https://01.org/lkp

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 2/2 v3] regmap: mmio: Support accelerared noinc operations
  2022-08-16 19:44   ` kernel test robot
@ 2022-08-16 20:50       ` Linus Walleij
  0 siblings, 0 replies; 8+ messages in thread
From: Linus Walleij @ 2022-08-16 20:50 UTC (permalink / raw)
  To: kernel test robot
  Cc: Mark Brown, llvm, kbuild-all, linux-kernel, linux-hexagon

On Tue, Aug 16, 2022 at 9:45 PM kernel test robot <lkp@intel.com> wrote:

> >> drivers/base/regmap/regmap-mmio.c:212:3: error: call to undeclared function 'writesb'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
>                    writesb(ctx->regs + reg, (const u8 *)val, val_count);
>                    ^
>    drivers/base/regmap/regmap-mmio.c:212:3: note: did you mean 'writeb'?
>    arch/hexagon/include/asm/io.h:122:20: note: 'writeb' declared here
>    static inline void writeb(u8 data, volatile void __iomem *addr)
>                       ^
> >> drivers/base/regmap/regmap-mmio.c:366:3: error: call to undeclared function 'readsb'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
>                    readsb(ctx->regs + reg, (u8 *)val, val_count);
>                    ^
>    drivers/base/regmap/regmap-mmio.c:366:3: note: did you mean 'readb'?
>    arch/hexagon/include/asm/io.h:83:18: note: 'readb' declared here
>    static inline u8 readb(const volatile void __iomem *addr)
>                     ^
>    2 errors generated.

Yeah Hexagon breaks the <asm/io.h> contract and does not provide
readsb/writesb.

OK I just fix Hexagon as part of patch 2, I hope.

Yours,
Linus Walleij

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 2/2 v3] regmap: mmio: Support accelerared noinc operations
@ 2022-08-16 20:50       ` Linus Walleij
  0 siblings, 0 replies; 8+ messages in thread
From: Linus Walleij @ 2022-08-16 20:50 UTC (permalink / raw)
  To: kbuild-all

[-- Attachment #1: Type: text/plain, Size: 1318 bytes --]

On Tue, Aug 16, 2022 at 9:45 PM kernel test robot <lkp@intel.com> wrote:

> >> drivers/base/regmap/regmap-mmio.c:212:3: error: call to undeclared function 'writesb'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
>                    writesb(ctx->regs + reg, (const u8 *)val, val_count);
>                    ^
>    drivers/base/regmap/regmap-mmio.c:212:3: note: did you mean 'writeb'?
>    arch/hexagon/include/asm/io.h:122:20: note: 'writeb' declared here
>    static inline void writeb(u8 data, volatile void __iomem *addr)
>                       ^
> >> drivers/base/regmap/regmap-mmio.c:366:3: error: call to undeclared function 'readsb'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
>                    readsb(ctx->regs + reg, (u8 *)val, val_count);
>                    ^
>    drivers/base/regmap/regmap-mmio.c:366:3: note: did you mean 'readb'?
>    arch/hexagon/include/asm/io.h:83:18: note: 'readb' declared here
>    static inline u8 readb(const volatile void __iomem *addr)
>                     ^
>    2 errors generated.

Yeah Hexagon breaks the <asm/io.h> contract and does not provide
readsb/writesb.

OK I just fix Hexagon as part of patch 2, I hope.

Yours,
Linus Walleij

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 1/2 v3] regmap: Support accelerated noinc operations
  2022-08-16 13:08 [PATCH 1/2 v3] regmap: Support accelerated noinc operations Linus Walleij
  2022-08-16 13:08 ` [PATCH 2/2 v3] regmap: mmio: Support accelerared " Linus Walleij
@ 2022-08-17 13:34 ` Mark Brown
  1 sibling, 0 replies; 8+ messages in thread
From: Mark Brown @ 2022-08-17 13:34 UTC (permalink / raw)
  To: Linus Walleij; +Cc: linux-kernel

On Tue, 16 Aug 2022 15:08:22 +0200, Linus Walleij wrote:
> Several architectures have accelerated operations for MMIO
> operations writing to a single register, such as writesb, writesw,
> writesl, writesq, readsb, readsw, readsl and readsq but regmap
> currently cannot use them because we have no hooks for providing
> an accelerated noinc back-end for MMIO.
> 
> Solve this by providing reg_[read/write]_noinc callbacks for
> the bus abstraction, so that the regmap-mmio bus can use this.
> 
> [...]

Applied to

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap.git for-next

Thanks!

[1/2] regmap: Support accelerated noinc operations
      commit: c20cc099b30abd50f563e422aa72edcd7f92da55
[2/2] regmap: mmio: Support accelerared noinc operations
      commit: 81c0386c1376da54f05d6916936db5220df9f97d

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2022-08-17 13:35 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-08-16 13:08 [PATCH 1/2 v3] regmap: Support accelerated noinc operations Linus Walleij
2022-08-16 13:08 ` [PATCH 2/2 v3] regmap: mmio: Support accelerared " Linus Walleij
2022-08-16 13:13   ` Mark Brown
2022-08-16 14:02     ` Linus Walleij
2022-08-16 19:44   ` kernel test robot
2022-08-16 20:50     ` Linus Walleij
2022-08-16 20:50       ` Linus Walleij
2022-08-17 13:34 ` [PATCH 1/2 v3] regmap: Support accelerated " Mark Brown

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.