regmap: Allow installing custom reg_update_bits function
Subsystems (4)
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
@@ -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
@@ -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
@@ -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
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
@@ -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
@@ -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
kbuild test robot
build botRe: [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
Mark Brown
maintainerQuoted 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_bitsfunction 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(-)
David Miller
maintainerFrom: 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_bitsfunction 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_busfor 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.gittags/regmap-offload-update-bits
I've pulled this into my 'net-next' tree, thanks.