Commit 0135bbcc authored by Stephen Warren's avatar Stephen Warren Committed by Mark Brown

regmap: introduce explicit bus_context for bus callbacks

The only context needed by I2C and SPI bus definitions is the device
itself; this can be converted to an i2c_client or spi_device in order
to perform IO on the device. However, other bus types may need more
context in order to perform IO. Enable this by having regmap_init accept
a bus_context parameter, and pass this to all bus callbacks. The
existing callbacks simply pass the struct device here. Future bus types
may pass something else.
Signed-off-by: default avatarStephen Warren <swarren@nvidia.com>
Signed-off-by: default avatarMark Brown <broonie@opensource.wolfsonmicro.com>
parent dd775ae2
...@@ -38,6 +38,7 @@ struct regmap { ...@@ -38,6 +38,7 @@ struct regmap {
void *work_buf; /* Scratch buffer used to format I/O */ void *work_buf; /* Scratch buffer used to format I/O */
struct regmap_format format; /* Buffer format */ struct regmap_format format; /* Buffer format */
const struct regmap_bus *bus; const struct regmap_bus *bus;
void *bus_context;
#ifdef CONFIG_DEBUG_FS #ifdef CONFIG_DEBUG_FS
struct dentry *debugfs; struct dentry *debugfs;
......
...@@ -15,8 +15,9 @@ ...@@ -15,8 +15,9 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/init.h> #include <linux/init.h>
static int regmap_i2c_write(struct device *dev, const void *data, size_t count) static int regmap_i2c_write(void *context, const void *data, size_t count)
{ {
struct device *dev = context;
struct i2c_client *i2c = to_i2c_client(dev); struct i2c_client *i2c = to_i2c_client(dev);
int ret; int ret;
...@@ -29,10 +30,11 @@ static int regmap_i2c_write(struct device *dev, const void *data, size_t count) ...@@ -29,10 +30,11 @@ static int regmap_i2c_write(struct device *dev, const void *data, size_t count)
return -EIO; return -EIO;
} }
static int regmap_i2c_gather_write(struct device *dev, static int regmap_i2c_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)
{ {
struct device *dev = context;
struct i2c_client *i2c = to_i2c_client(dev); struct i2c_client *i2c = to_i2c_client(dev);
struct i2c_msg xfer[2]; struct i2c_msg xfer[2];
int ret; int ret;
...@@ -62,10 +64,11 @@ static int regmap_i2c_gather_write(struct device *dev, ...@@ -62,10 +64,11 @@ static int regmap_i2c_gather_write(struct device *dev,
return -EIO; return -EIO;
} }
static int regmap_i2c_read(struct device *dev, static int regmap_i2c_read(void *context,
const void *reg, size_t reg_size, const void *reg, size_t reg_size,
void *val, size_t val_size) void *val, size_t val_size)
{ {
struct device *dev = context;
struct i2c_client *i2c = to_i2c_client(dev); struct i2c_client *i2c = to_i2c_client(dev);
struct i2c_msg xfer[2]; struct i2c_msg xfer[2];
int ret; int ret;
...@@ -107,7 +110,7 @@ static struct regmap_bus regmap_i2c = { ...@@ -107,7 +110,7 @@ static struct regmap_bus regmap_i2c = {
struct regmap *regmap_init_i2c(struct i2c_client *i2c, struct regmap *regmap_init_i2c(struct i2c_client *i2c,
const struct regmap_config *config) const struct regmap_config *config)
{ {
return regmap_init(&i2c->dev, &regmap_i2c, config); return regmap_init(&i2c->dev, &regmap_i2c, &i2c->dev, config);
} }
EXPORT_SYMBOL_GPL(regmap_init_i2c); EXPORT_SYMBOL_GPL(regmap_init_i2c);
...@@ -124,7 +127,7 @@ EXPORT_SYMBOL_GPL(regmap_init_i2c); ...@@ -124,7 +127,7 @@ EXPORT_SYMBOL_GPL(regmap_init_i2c);
struct regmap *devm_regmap_init_i2c(struct i2c_client *i2c, struct regmap *devm_regmap_init_i2c(struct i2c_client *i2c,
const struct regmap_config *config) const struct regmap_config *config)
{ {
return devm_regmap_init(&i2c->dev, &regmap_i2c, config); return devm_regmap_init(&i2c->dev, &regmap_i2c, &i2c->dev, config);
} }
EXPORT_SYMBOL_GPL(devm_regmap_init_i2c); EXPORT_SYMBOL_GPL(devm_regmap_init_i2c);
......
...@@ -15,17 +15,19 @@ ...@@ -15,17 +15,19 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/module.h> #include <linux/module.h>
static int regmap_spi_write(struct device *dev, const void *data, size_t count) static int regmap_spi_write(void *context, const void *data, size_t count)
{ {
struct device *dev = context;
struct spi_device *spi = to_spi_device(dev); struct spi_device *spi = to_spi_device(dev);
return spi_write(spi, data, count); return spi_write(spi, data, count);
} }
static int regmap_spi_gather_write(struct device *dev, static int regmap_spi_gather_write(void *context,
const void *reg, size_t reg_len, const void *reg, size_t reg_len,
const void *val, size_t val_len) const void *val, size_t val_len)
{ {
struct device *dev = context;
struct spi_device *spi = to_spi_device(dev); struct spi_device *spi = to_spi_device(dev);
struct spi_message m; struct spi_message m;
struct spi_transfer t[2] = { { .tx_buf = reg, .len = reg_len, }, struct spi_transfer t[2] = { { .tx_buf = reg, .len = reg_len, },
...@@ -38,10 +40,11 @@ static int regmap_spi_gather_write(struct device *dev, ...@@ -38,10 +40,11 @@ static int regmap_spi_gather_write(struct device *dev,
return spi_sync(spi, &m); return spi_sync(spi, &m);
} }
static int regmap_spi_read(struct device *dev, static int regmap_spi_read(void *context,
const void *reg, size_t reg_size, const void *reg, size_t reg_size,
void *val, size_t val_size) void *val, size_t val_size)
{ {
struct device *dev = context;
struct spi_device *spi = to_spi_device(dev); struct spi_device *spi = to_spi_device(dev);
return spi_write_then_read(spi, reg, reg_size, val, val_size); return spi_write_then_read(spi, reg, reg_size, val, val_size);
...@@ -66,7 +69,7 @@ static struct regmap_bus regmap_spi = { ...@@ -66,7 +69,7 @@ static struct regmap_bus regmap_spi = {
struct regmap *regmap_init_spi(struct spi_device *spi, struct regmap *regmap_init_spi(struct spi_device *spi,
const struct regmap_config *config) const struct regmap_config *config)
{ {
return regmap_init(&spi->dev, &regmap_spi, config); return regmap_init(&spi->dev, &regmap_spi, &spi->dev, config);
} }
EXPORT_SYMBOL_GPL(regmap_init_spi); EXPORT_SYMBOL_GPL(regmap_init_spi);
...@@ -83,7 +86,7 @@ EXPORT_SYMBOL_GPL(regmap_init_spi); ...@@ -83,7 +86,7 @@ EXPORT_SYMBOL_GPL(regmap_init_spi);
struct regmap *devm_regmap_init_spi(struct spi_device *spi, struct regmap *devm_regmap_init_spi(struct spi_device *spi,
const struct regmap_config *config) const struct regmap_config *config)
{ {
return devm_regmap_init(&spi->dev, &regmap_spi, config); return devm_regmap_init(&spi->dev, &regmap_spi, &spi->dev, config);
} }
EXPORT_SYMBOL_GPL(devm_regmap_init_spi); EXPORT_SYMBOL_GPL(devm_regmap_init_spi);
......
...@@ -163,6 +163,7 @@ static unsigned int regmap_parse_32(void *buf) ...@@ -163,6 +163,7 @@ static unsigned int regmap_parse_32(void *buf)
* *
* @dev: Device that will be interacted with * @dev: Device that will be interacted with
* @bus: Bus-specific callbacks to use with device * @bus: Bus-specific callbacks to use with device
* @bus_context: Data passed to bus-specific callbacks
* @config: Configuration for register map * @config: Configuration for register map
* *
* The return value will be an ERR_PTR() on error or a valid pointer to * The return value will be an ERR_PTR() on error or a valid pointer to
...@@ -171,6 +172,7 @@ static unsigned int regmap_parse_32(void *buf) ...@@ -171,6 +172,7 @@ static unsigned int regmap_parse_32(void *buf)
*/ */
struct regmap *regmap_init(struct device *dev, struct regmap *regmap_init(struct device *dev,
const struct regmap_bus *bus, const struct regmap_bus *bus,
void *bus_context,
const struct regmap_config *config) const struct regmap_config *config)
{ {
struct regmap *map; struct regmap *map;
...@@ -193,6 +195,7 @@ struct regmap *regmap_init(struct device *dev, ...@@ -193,6 +195,7 @@ struct regmap *regmap_init(struct device *dev,
map->format.buf_size += map->format.pad_bytes; map->format.buf_size += map->format.pad_bytes;
map->dev = dev; map->dev = dev;
map->bus = bus; map->bus = bus;
map->bus_context = bus_context;
map->max_register = config->max_register; map->max_register = config->max_register;
map->writeable_reg = config->writeable_reg; map->writeable_reg = config->writeable_reg;
map->readable_reg = config->readable_reg; map->readable_reg = config->readable_reg;
...@@ -316,6 +319,7 @@ static void devm_regmap_release(struct device *dev, void *res) ...@@ -316,6 +319,7 @@ static void devm_regmap_release(struct device *dev, void *res)
* *
* @dev: Device that will be interacted with * @dev: Device that will be interacted with
* @bus: Bus-specific callbacks to use with device * @bus: Bus-specific callbacks to use with device
* @bus_context: Data passed to bus-specific callbacks
* @config: Configuration for register map * @config: Configuration for register map
* *
* The return value will be an ERR_PTR() on error or a valid pointer * The return value will be an ERR_PTR() on error or a valid pointer
...@@ -325,6 +329,7 @@ static void devm_regmap_release(struct device *dev, void *res) ...@@ -325,6 +329,7 @@ static void devm_regmap_release(struct device *dev, void *res)
*/ */
struct regmap *devm_regmap_init(struct device *dev, struct regmap *devm_regmap_init(struct device *dev,
const struct regmap_bus *bus, const struct regmap_bus *bus,
void *bus_context,
const struct regmap_config *config) const struct regmap_config *config)
{ {
struct regmap **ptr, *regmap; struct regmap **ptr, *regmap;
...@@ -333,7 +338,7 @@ struct regmap *devm_regmap_init(struct device *dev, ...@@ -333,7 +338,7 @@ struct regmap *devm_regmap_init(struct device *dev,
if (!ptr) if (!ptr)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
regmap = regmap_init(dev, bus, config); regmap = regmap_init(dev, bus, bus_context, config);
if (!IS_ERR(regmap)) { if (!IS_ERR(regmap)) {
*ptr = regmap; *ptr = regmap;
devres_add(dev, ptr); devres_add(dev, ptr);
...@@ -391,6 +396,8 @@ void regmap_exit(struct regmap *map) ...@@ -391,6 +396,8 @@ void regmap_exit(struct regmap *map)
{ {
regcache_exit(map); regcache_exit(map);
regmap_debugfs_exit(map); regmap_debugfs_exit(map);
if (map->bus->free_context)
map->bus->free_context(map->bus_context);
kfree(map->work_buf); kfree(map->work_buf);
kfree(map); kfree(map);
} }
...@@ -444,12 +451,12 @@ static int _regmap_raw_write(struct regmap *map, unsigned int reg, ...@@ -444,12 +451,12 @@ static int _regmap_raw_write(struct regmap *map, unsigned int reg,
*/ */
if (val == (map->work_buf + map->format.pad_bytes + if (val == (map->work_buf + map->format.pad_bytes +
map->format.reg_bytes)) map->format.reg_bytes))
ret = map->bus->write(map->dev, map->work_buf, ret = map->bus->write(map->bus_context, map->work_buf,
map->format.reg_bytes + map->format.reg_bytes +
map->format.pad_bytes + map->format.pad_bytes +
val_len); val_len);
else if (map->bus->gather_write) else if (map->bus->gather_write)
ret = map->bus->gather_write(map->dev, map->work_buf, ret = map->bus->gather_write(map->bus_context, map->work_buf,
map->format.reg_bytes + map->format.reg_bytes +
map->format.pad_bytes, map->format.pad_bytes,
val, val_len); val, val_len);
...@@ -464,7 +471,7 @@ static int _regmap_raw_write(struct regmap *map, unsigned int reg, ...@@ -464,7 +471,7 @@ static int _regmap_raw_write(struct regmap *map, unsigned int reg,
memcpy(buf, map->work_buf, map->format.reg_bytes); memcpy(buf, map->work_buf, map->format.reg_bytes);
memcpy(buf + map->format.reg_bytes + map->format.pad_bytes, memcpy(buf + map->format.reg_bytes + map->format.pad_bytes,
val, val_len); val, val_len);
ret = map->bus->write(map->dev, buf, len); ret = map->bus->write(map->bus_context, buf, len);
kfree(buf); kfree(buf);
} }
...@@ -498,7 +505,7 @@ int _regmap_write(struct regmap *map, unsigned int reg, ...@@ -498,7 +505,7 @@ int _regmap_write(struct regmap *map, unsigned int reg,
trace_regmap_hw_write_start(map->dev, reg, 1); trace_regmap_hw_write_start(map->dev, reg, 1);
ret = map->bus->write(map->dev, map->work_buf, ret = map->bus->write(map->bus_context, map->work_buf,
map->format.buf_size); map->format.buf_size);
trace_regmap_hw_write_done(map->dev, reg, 1); trace_regmap_hw_write_done(map->dev, reg, 1);
...@@ -639,7 +646,7 @@ static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val, ...@@ -639,7 +646,7 @@ static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
trace_regmap_hw_read_start(map->dev, reg, trace_regmap_hw_read_start(map->dev, reg,
val_len / map->format.val_bytes); val_len / map->format.val_bytes);
ret = map->bus->read(map->dev, map->work_buf, ret = map->bus->read(map->bus_context, map->work_buf,
map->format.reg_bytes + map->format.pad_bytes, map->format.reg_bytes + map->format.pad_bytes,
val, val_len); val, val_len);
......
...@@ -97,14 +97,15 @@ struct regmap_config { ...@@ -97,14 +97,15 @@ struct regmap_config {
u8 write_flag_mask; u8 write_flag_mask;
}; };
typedef int (*regmap_hw_write)(struct device *dev, const void *data, typedef int (*regmap_hw_write)(void *context, const void *data,
size_t count); size_t count);
typedef int (*regmap_hw_gather_write)(struct device *dev, typedef int (*regmap_hw_gather_write)(void *context,
const void *reg, size_t reg_len, const void *reg, size_t reg_len,
const void *val, size_t val_len); const void *val, size_t val_len);
typedef int (*regmap_hw_read)(struct device *dev, typedef int (*regmap_hw_read)(void *context,
const void *reg_buf, size_t reg_size, const void *reg_buf, size_t reg_size,
void *val_buf, size_t val_size); void *val_buf, size_t val_size);
typedef void (*regmap_hw_free_context)(void *context);
/** /**
* Description of a hardware bus for the register map infrastructure. * Description of a hardware bus for the register map infrastructure.
...@@ -121,11 +122,13 @@ struct regmap_bus { ...@@ -121,11 +122,13 @@ struct regmap_bus {
regmap_hw_write write; regmap_hw_write write;
regmap_hw_gather_write gather_write; regmap_hw_gather_write gather_write;
regmap_hw_read read; regmap_hw_read read;
regmap_hw_free_context free_context;
u8 read_flag_mask; u8 read_flag_mask;
}; };
struct regmap *regmap_init(struct device *dev, struct regmap *regmap_init(struct device *dev,
const struct regmap_bus *bus, const struct regmap_bus *bus,
void *bus_context,
const struct regmap_config *config); const struct regmap_config *config);
struct regmap *regmap_init_i2c(struct i2c_client *i2c, struct regmap *regmap_init_i2c(struct i2c_client *i2c,
const struct regmap_config *config); const struct regmap_config *config);
...@@ -134,6 +137,7 @@ struct regmap *regmap_init_spi(struct spi_device *dev, ...@@ -134,6 +137,7 @@ struct regmap *regmap_init_spi(struct spi_device *dev,
struct regmap *devm_regmap_init(struct device *dev, struct regmap *devm_regmap_init(struct device *dev,
const struct regmap_bus *bus, const struct regmap_bus *bus,
void *bus_context,
const struct regmap_config *config); const struct regmap_config *config);
struct regmap *devm_regmap_init_i2c(struct i2c_client *i2c, struct regmap *devm_regmap_init_i2c(struct i2c_client *i2c,
const struct regmap_config *config); const struct regmap_config *config);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment