From 6112fe60ac1bd1e68da8cc4248289d6e48015f9b Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Fri, 20 Sep 2013 18:00:10 +0530 Subject: regmap: add helper macro to set min/max range of register Add helper macro to set the min and max value of the register range. This is useful when initialising the register ranges of the device like static const struct regmap_range readable_ranges[] = { regmap_reg_range(DEVICE_REG0, DEVICE_REG10), }; Signed-off-by: Laxman Dewangan Signed-off-by: Mark Brown --- include/linux/regmap.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include/linux/regmap.h') diff --git a/include/linux/regmap.h b/include/linux/regmap.h index a10380bfbeac..7d3ae2be6869 100644 --- a/include/linux/regmap.h +++ b/include/linux/regmap.h @@ -70,6 +70,8 @@ struct regmap_range { unsigned int range_max; }; +#define regmap_reg_range(low, high) { .range_min = low, .range_max = high, } + /* * A table of ranges including some yes ranges and some no ranges. * If a register belongs to a no_range, the corresponding check function -- cgit v1.2.3-71-gd317 From e33fabd365596178e72f62bb4b89f0aaad0509ad Mon Sep 17 00:00:00 2001 From: Anthony Olech Date: Fri, 11 Oct 2013 15:31:11 +0100 Subject: regmap: new API regmap_multi_reg_write() definition New API regmap_multi_reg_write() is defined that allows a set of reg,val pairs to be written to a I2C client device as one block transfer from the point of view of a single I2C master system. A simple demonstration implementation is included that just splits the block write request into a sequence of single register writes. The implementation will be modified later to support those I2C clients that implement the alternative non-standard MULTIWRITE block write mode so to achieve a single I2C transfer that will be atomic even in multiple I2C master systems. Signed-off-by: Anthony Olech Signed-off-by: David Dajun Chen Signed-off-by: Mark Brown --- drivers/base/regmap/regmap.c | 41 +++++++++++++++++++++++++++++++++++++++++ include/linux/regmap.h | 2 ++ 2 files changed, 43 insertions(+) (limited to 'include/linux/regmap.h') diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c index 7d689a15c500..c42ad69e527f 100644 --- a/drivers/base/regmap/regmap.c +++ b/drivers/base/regmap/regmap.c @@ -1439,6 +1439,47 @@ out: } EXPORT_SYMBOL_GPL(regmap_bulk_write); +/* + * regmap_multi_reg_write(): Write multiple registers to the device + * + * where the set of register are supplied in any order + * + * @map: Register map to write to + * @regs: Array of structures containing register,value to be written + * @num_regs: Number of registers to write + * + * This function is intended to be used for writing a large block of data + * atomically to the device in single transfer for those I2C client devices + * that implement this alternative block write mode. + * + * A value of zero will be returned on success, a negative errno will + * be returned in error cases. + */ +int regmap_multi_reg_write(struct regmap *map, struct reg_default *regs, + int num_regs) +{ + int ret = 0, i; + + for (i = 0; i < num_regs; i++) { + int reg = regs[i].reg; + if (reg % map->reg_stride) + return -EINVAL; + } + + map->lock(map->lock_arg); + + for (i = 0; i < num_regs; i++) { + ret = _regmap_write(map, regs[i].reg, regs[i].def); + if (ret != 0) + goto out; + } +out: + map->unlock(map->lock_arg); + + return ret; +} +EXPORT_SYMBOL_GPL(regmap_multi_reg_write); + /** * regmap_raw_write_async(): Write raw values to one or more registers * asynchronously diff --git a/include/linux/regmap.h b/include/linux/regmap.h index a10380bfbeac..4b933a31f84f 100644 --- a/include/linux/regmap.h +++ b/include/linux/regmap.h @@ -378,6 +378,8 @@ int regmap_raw_write(struct regmap *map, unsigned int reg, const void *val, size_t val_len); int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val, size_t val_count); +int regmap_multi_reg_write(struct regmap *map, struct reg_default *regs, + int num_regs); int regmap_raw_write_async(struct regmap *map, unsigned int reg, const void *val, size_t val_len); int regmap_read(struct regmap *map, unsigned int reg, unsigned int *val); -- cgit v1.2.3-71-gd317 From a01779f89fc8a2225cb82dca0fc7b8451851cb7b Mon Sep 17 00:00:00 2001 From: Josh Cartwright Date: Mon, 28 Oct 2013 13:12:35 -0500 Subject: regmap: add SPMI support Add basic support for the System Power Management Interface (SPMI) bus. This is a simple implementation which only implements register accesses via the Extended Register Read/Write Long commands. Signed-off-by: Josh Cartwright Signed-off-by: Mark Brown --- drivers/base/regmap/Kconfig | 5 ++- drivers/base/regmap/Makefile | 1 + drivers/base/regmap/regmap-spmi.c | 90 +++++++++++++++++++++++++++++++++++++++ include/linux/regmap.h | 5 +++ 4 files changed, 100 insertions(+), 1 deletion(-) create mode 100644 drivers/base/regmap/regmap-spmi.c (limited to 'include/linux/regmap.h') diff --git a/drivers/base/regmap/Kconfig b/drivers/base/regmap/Kconfig index f0d30543fcce..4251570610c9 100644 --- a/drivers/base/regmap/Kconfig +++ b/drivers/base/regmap/Kconfig @@ -3,7 +3,7 @@ # subsystems should select the appropriate symbols. config REGMAP - default y if (REGMAP_I2C || REGMAP_SPI || REGMAP_MMIO || REGMAP_IRQ) + default y if (REGMAP_I2C || REGMAP_SPI || REGMAP_SPMI || REGMAP_MMIO || REGMAP_IRQ) select LZO_COMPRESS select LZO_DECOMPRESS select IRQ_DOMAIN if REGMAP_IRQ @@ -15,6 +15,9 @@ config REGMAP_I2C config REGMAP_SPI tristate +config REGMAP_SPMI + tristate + config REGMAP_MMIO tristate diff --git a/drivers/base/regmap/Makefile b/drivers/base/regmap/Makefile index cf129980abd0..a7c670b4123a 100644 --- a/drivers/base/regmap/Makefile +++ b/drivers/base/regmap/Makefile @@ -3,5 +3,6 @@ obj-$(CONFIG_REGMAP) += regcache-rbtree.o regcache-lzo.o regcache-flat.o obj-$(CONFIG_DEBUG_FS) += regmap-debugfs.o obj-$(CONFIG_REGMAP_I2C) += regmap-i2c.o obj-$(CONFIG_REGMAP_SPI) += regmap-spi.o +obj-$(CONFIG_REGMAP_SPMI) += regmap-spmi.o obj-$(CONFIG_REGMAP_MMIO) += regmap-mmio.o obj-$(CONFIG_REGMAP_IRQ) += regmap-irq.o diff --git a/drivers/base/regmap/regmap-spmi.c b/drivers/base/regmap/regmap-spmi.c new file mode 100644 index 000000000000..ac2391013db1 --- /dev/null +++ b/drivers/base/regmap/regmap-spmi.c @@ -0,0 +1,90 @@ +/* + * Register map access API - SPMI support + * + * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. + * + * Based on regmap-i2c.c: + * Copyright 2011 Wolfson Microelectronics plc + * Author: Mark Brown + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ +#include +#include +#include +#include + +static int regmap_spmi_read(void *context, + const void *reg, size_t reg_size, + void *val, size_t val_size) +{ + BUG_ON(reg_size != 2); + return spmi_ext_register_readl(context, *(u16 *)reg, + val, val_size); +} + +static int regmap_spmi_gather_write(void *context, + const void *reg, size_t reg_size, + const void *val, size_t val_size) +{ + BUG_ON(reg_size != 2); + return spmi_ext_register_writel(context, *(u16 *)reg, val, val_size); +} + +static int regmap_spmi_write(void *context, const void *data, + size_t count) +{ + BUG_ON(count < 2); + return regmap_spmi_gather_write(context, data, 2, data + 2, count - 2); +} + +static struct regmap_bus regmap_spmi = { + .read = regmap_spmi_read, + .write = regmap_spmi_write, + .gather_write = regmap_spmi_gather_write, + .reg_format_endian_default = REGMAP_ENDIAN_NATIVE, + .val_format_endian_default = REGMAP_ENDIAN_NATIVE, +}; + +/** + * regmap_init_spmi(): Initialize register map + * + * @sdev: Device that will be interacted with + * @config: Configuration for register map + * + * The return value will be an ERR_PTR() on error or a valid pointer to + * a struct regmap. + */ +struct regmap *regmap_init_spmi(struct spmi_device *sdev, + const struct regmap_config *config) +{ + return regmap_init(&sdev->dev, ®map_spmi, sdev, config); +} +EXPORT_SYMBOL_GPL(regmap_init_spmi); + +/** + * devm_regmap_init_spmi(): Initialise managed register map + * + * @sdev: Device that will be interacted with + * @config: Configuration for register map + * + * The return value will be an ERR_PTR() on error or a valid pointer + * to a struct regmap. The regmap will be automatically freed by the + * device management code. + */ +struct regmap *devm_regmap_init_spmi(struct spmi_device *sdev, + const struct regmap_config *config) +{ + return devm_regmap_init(&sdev->dev, ®map_spmi, sdev, config); +} +EXPORT_SYMBOL_GPL(devm_regmap_init_spmi); + +MODULE_LICENSE("GPL"); diff --git a/include/linux/regmap.h b/include/linux/regmap.h index a10380bfbeac..3f5abc86b6b5 100644 --- a/include/linux/regmap.h +++ b/include/linux/regmap.h @@ -23,6 +23,7 @@ struct device; struct i2c_client; struct irq_domain; struct spi_device; +struct spmi_device; struct regmap; struct regmap_range_cfg; struct regmap_field; @@ -318,6 +319,8 @@ struct regmap *regmap_init_i2c(struct i2c_client *i2c, const struct regmap_config *config); struct regmap *regmap_init_spi(struct spi_device *dev, const struct regmap_config *config); +struct regmap *regmap_init_spmi(struct spmi_device *dev, + const struct regmap_config *config); struct regmap *regmap_init_mmio_clk(struct device *dev, const char *clk_id, void __iomem *regs, const struct regmap_config *config); @@ -330,6 +333,8 @@ struct regmap *devm_regmap_init_i2c(struct i2c_client *i2c, const struct regmap_config *config); struct regmap *devm_regmap_init_spi(struct spi_device *dev, const struct regmap_config *config); +struct regmap *devm_regmap_init_spmi(struct spmi_device *dev, + const struct regmap_config *config); struct regmap *devm_regmap_init_mmio_clk(struct device *dev, const char *clk_id, void __iomem *regs, const struct regmap_config *config); -- cgit v1.2.3-71-gd317