Skip to contentSkip to conversation

regmap: Allow installing custom reg_update_bits function

PATCH In review [email protected] 4 participants 5 messages Oct 1, 2015 – Oct 8, 2015

Subsystems (4)
lore
Share & tools
lore
#0 lore raw

PATCH v3 1/2 regmap: Allow installing custom reg_update_bits function

From: Jon Ringle <[email protected]>

This commit allows installing a custom reg_update_bits function for cases where the hardware provides a mechanism to set or clear register bits without a read/modify/write cycle. Such is the case with the Microchip ENCX24J600.

If a custom reg_update_bits function is provided, it will only be used against volatile registers.

---

I am now only calling map->reg_update_bits() if the register is marked as being volatile, and therefore should have no impact on the reg cache.

Jon

 drivers/base/regmap/internal.h |  2 ++
 drivers/base/regmap/regmap.c   | 29 ++++++++++++++++++-----------
 include/linux/regmap.h         |  3 +++
 3 files changed, 23 insertions(+), 11 deletions(-)
drivers/base/regmap/internal.h +2 -0
index cc55788..628ad7a 100644
@@ -98,6 +98,8 @@ struct regmap {
 
 	int (*reg_read)(void *context, unsigned int reg, unsigned int *val);
 	int (*reg_write)(void *context, unsigned int reg, unsigned int val);
+	int (*reg_update_bits)(void *context, unsigned int reg,
+			       unsigned int mask, unsigned int val);
 
 	bool defer_caching;
 
drivers/base/regmap/regmap.c +18 -11
index afaf562..8cd155a 100644
@@ -619,6 +619,7 @@ struct regmap *__regmap_init(struct device *dev,
 		goto skip_format_initialization;
 	} else {
 		map->reg_read  = _regmap_bus_read;
+		map->reg_update_bits = bus->reg_update_bits;
 	}
 
 	reg_endian = regmap_get_reg_endian(bus, config);
@@ -2509,20 +2510,26 @@ static int _regmap_update_bits(struct regmap *map, unsigned int reg,
 	int ret;
 	unsigned int tmp, orig;
 
-	ret = _regmap_read(map, reg, &orig);
-	if (ret != 0)
-		return ret;
+	if (change)
+		*change = false;
 
-	tmp = orig & ~mask;
-	tmp |= val & mask;
-
-	if (force_write || (tmp != orig)) {
-		ret = _regmap_write(map, reg, tmp);
-		if (change)
+	if (regmap_volatile(map, reg) && map->reg_update_bits) {
+		ret = map->reg_update_bits(map->bus_context, reg, mask, val);
+		if (ret == 0 && change)
 			*change = true;
 	} else {
-		if (change)
-			*change = false;
+		ret = _regmap_read(map, reg, &orig);
+		if (ret != 0)
+			return ret;
+
+		tmp = orig & ~mask;
+		tmp |= val & mask;
+
+		if (force_write || (tmp != orig)) {
+			ret = _regmap_write(map, reg, tmp);
+			if (ret == 0 && change)
+				*change = true;
+		}
 	}
 
 	return ret;
include/linux/regmap.h +3 -0
index 8fc0bfd..b49d413 100644
@@ -296,6 +296,8 @@ typedef int (*regmap_hw_reg_read)(void *context, unsigned int reg,
 				  unsigned int *val);
 typedef int (*regmap_hw_reg_write)(void *context, unsigned int reg,
 				   unsigned int val);
+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);
 typedef void (*regmap_hw_free_context)(void *context);
 
@@ -335,6 +337,7 @@ struct regmap_bus {
 	regmap_hw_gather_write gather_write;
 	regmap_hw_async_write async_write;
 	regmap_hw_reg_write reg_write;
+	regmap_hw_reg_update_bits reg_update_bits;
 	regmap_hw_read read;
 	regmap_hw_reg_read reg_read;
 	regmap_hw_free_context free_context;
Signature · 1 line
2.4.1
#1 lore raw

PATCH v3 2/2 net: Microchip encx24j600 driver

From: Jon Ringle <[email protected]>

This ethernet driver supports the Micorchip enc424j600/626j600 Ethernet controller over a SPI bus interface. This driver makes use of the regmap API to optimize access to registers by caching registers where possible.

Datasheet:
http://ww1.microchip.com/downloads/en/DeviceDoc/39935b.pdf

---

Fixed several issues reported by kbuild bots and simplified the implementation of regmap_encx24j600_reg_update_bits() based on changes to _regmap_update_bits

Jon

 drivers/net/ethernet/microchip/Kconfig             |    9 +
 drivers/net/ethernet/microchip/Makefile            |    1 +
 drivers/net/ethernet/microchip/encx24j600-regmap.c |  513 +++++++++
 drivers/net/ethernet/microchip/encx24j600.c        | 1124 ++++++++++++++++++++
 drivers/net/ethernet/microchip/encx24j600_hw.h     |  437 ++++++++
 5 files changed, 2084 insertions(+)
 create mode 100644 drivers/net/ethernet/microchip/encx24j600-regmap.c
 create mode 100644 drivers/net/ethernet/microchip/encx24j600.c
 create mode 100644 drivers/net/ethernet/microchip/encx24j600_hw.h
drivers/net/ethernet/microchip/Kconfig +9 -0
index afaf0c0..b45b28a 100644
@@ -35,4 +35,13 @@ config ENC28J60_WRITEVERIFY
 	  Enable the verify after the buffer write useful for debugging purpose.
 	  If unsure, say N.
 
+config ENCX24J600
+    tristate "ENCX24J600 support"
+    depends on SPI
+    ---help---
+      Support for the Microchip ENC424J600 ethernet chip.
+
+      To compile this driver as a module, choose M here. The module will be
+      called enc424j600.
+
 endif # NET_VENDOR_MICROCHIP
drivers/net/ethernet/microchip/Makefile +1 -0
index 573d429..ff78f62 100644
@@ -3,3 +3,4 @@
 #
 
 obj-$(CONFIG_ENC28J60) += enc28j60.o
+obj-$(CONFIG_ENCX24J600) += encx24j600.o encx24j600-regmap.o
drivers/net/ethernet/microchip/encx24j600-regmap.c new file +513 -0

513 lines not on this page · raw message

drivers/net/ethernet/microchip/encx24j600.c new file +1124 -0

1,124 lines not on this page · raw message

drivers/net/ethernet/microchip/encx24j600_hw.h new file +437 -0

437 lines not on this page · raw message

Signature · 1 line
2.4.1
#2 lore raw

Re: [PATCH net-next v3 2/2] net: Microchip encx24j600 driver

config: mn10300-allmodconfig (attached as .config) reproduce: wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross…

Hi Jon,

[auto build test results on v4.3-rc3 -- if it's inappropriate base, please ignore]

config: mn10300-allmodconfig (attached as .config)
reproduce:
wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
make.cross ARCH=mn10300

All warnings (new ones prefixed by >>):

drivers/net/ethernet/microchip/encx24j600-regmap.c: In function 'regmap_encx24j600_read':

>> drivers/net/ethernet/microchip/encx24j600-regmap.c:272:3: warning: format '%zu' expects argument of type 'size_t', but argument 4 has type 'unsigned int' [-Wformat=]
      pr_err("%s: reg=%02x reg_size=%zu\n", __func__, reg, reg_size);
      ^
   drivers/net/ethernet/microchip/encx24j600-regmap.c:280:3: warning: format '%zu' expects argument of type 'size_t', but argument 4 has type 'unsigned int' [-Wformat=]
      pr_err("%s: reg=%02x val_size=%zu\n", __func__, reg, val_size);
      ^

vim +272 drivers/net/ethernet/microchip/encx24j600-regmap.c

256 if (reg > 0xa0)
257 return regmap_encx24j600_spi_write(context, reg, dout, len);
258
259 if (len > 2)
260 return -EINVAL;
261
262 return regmap_encx24j600_sfr_write(context, reg, dout, len);
263 }
264
265 static int regmap_encx24j600_read(void *context,
266 const void *reg_buf, size_t reg_size,
267 void *val, size_t val_size)
268 {
269 u8 reg = *(const u8 *)reg_buf;
270
271 if (reg_size != 1) {

 > 272			pr_err("%s: reg=%02x reg_size=%zu\n", __func__, reg, reg_size);

273 return -EINVAL;
274 }
275
276 if (reg > 0xa0)
277 return regmap_encx24j600_spi_read(context, reg, val, val_size);
278
279 if (val_size > 2) {
280 pr_err("%s: reg=%02x val_size=%zu\n", __func__, reg, val_size);

---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation

maintainer
#3 lore raw
In reply to [email protected]
Quoted 5 lines · On Thu, Oct 01, 2015 at 12:38:07PM -0400, [email protected] wrote:

From: Jon Ringle <[email protected]>

This commit allows installing a custom reg_update_bits function for cases where the hardware provides a mechanism to set or clear register bits without a read/modify/write cycle. Such is the case with the Microchip ENCX24J600.

Thanks, I've applied this. I'll extend it so that individual devices can do this as well - I've not looked at your driver but it might be that this is a better option than regmap_bus for your driver (but both are supported so meh). Dave, I've tagged the commit and there's a pull request for this below:

The following changes since commit 6ff33f3902c3b1c5d0db6b1e2c70b6d76fba357f:

Linux 4.3-rc1 (2015-09-12 16:35:56 -0700)

are available in the git repository at:

git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap.git tags/regmap-offload-update-bits

for you to fetch changes up to 77792b11409c9270d98e604b4314b85ce886ac7d:

regmap: Allow installing custom reg_update_bits function (2015-10-06 16:12:34 +0100)

----------------------------------------------------------------
regmap: Allow buses to provide a custom update_bits() operation

Some buses provide a native _update_bits() operation which for uncached registers is faster than doing a read/modify/write cycle as it is a single bus transaction. Add support for implementing this to regmap.

----------------------------------------------------------------
Jon Ringle (1):
regmap: Allow installing custom reg_update_bits function

 drivers/base/regmap/internal.h |  2 ++
 drivers/base/regmap/regmap.c   | 29 ++++++++++++++++++-----------
 include/linux/regmap.h         |  3 +++
 3 files changed, 23 insertions(+), 11 deletions(-)
maintainer
#4 lore raw

From: Mark Brown <[email protected]>
Date: Tue, 6 Oct 2015 17:30:11 +0100

Quoted 13 lines · On Thu, Oct 01, 2015 at 12:38:07PM -0400, [email protected] wrote:
Quoted 5 lines

From: Jon Ringle <[email protected]>

This commit allows installing a custom reg_update_bits function for cases where the hardware provides a mechanism to set or clear register bits without a read/modify/write cycle. Such is the case with the Microchip ENCX24J600.

Thanks, I've applied this. I'll extend it so that individual devices can do this as well - I've not looked at your driver but it might be that this is a better option than regmap_bus for your driver (but both are supported so meh). Dave, I've tagged the commit and there's a pull request for this below:

Quoted 7 lines

The following changes since commit 6ff33f3902c3b1c5d0db6b1e2c70b6d76fba357f:

Linux 4.3-rc1 (2015-09-12 16:35:56 -0700)

are available in the git repository at:

git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap.git tags/regmap-offload-update-bits

I've pulled this into my 'net-next' tree, thanks.