Commit ef98ae45 authored by Mark Brown's avatar Mark Brown

Merge remote-tracking branch 'regmap/topic/smbus' into regmap-next

parents 522168d1 b4226107
...@@ -14,6 +14,79 @@ ...@@ -14,6 +14,79 @@
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/module.h> #include <linux/module.h>
static int regmap_smbus_byte_reg_read(void *context, unsigned int reg,
unsigned int *val)
{
struct device *dev = context;
struct i2c_client *i2c = to_i2c_client(dev);
int ret;
if (reg > 0xff)
return -EINVAL;
ret = i2c_smbus_read_byte_data(i2c, reg);
if (ret < 0)
return ret;
*val = ret;
return 0;
}
static int regmap_smbus_byte_reg_write(void *context, unsigned int reg,
unsigned int val)
{
struct device *dev = context;
struct i2c_client *i2c = to_i2c_client(dev);
if (val > 0xff || reg > 0xff)
return -EINVAL;
return i2c_smbus_write_byte_data(i2c, reg, val);
}
static struct regmap_bus regmap_smbus_byte = {
.reg_write = regmap_smbus_byte_reg_write,
.reg_read = regmap_smbus_byte_reg_read,
};
static int regmap_smbus_word_reg_read(void *context, unsigned int reg,
unsigned int *val)
{
struct device *dev = context;
struct i2c_client *i2c = to_i2c_client(dev);
int ret;
if (reg > 0xff)
return -EINVAL;
ret = i2c_smbus_read_word_data(i2c, reg);
if (ret < 0)
return ret;
*val = ret;
return 0;
}
static int regmap_smbus_word_reg_write(void *context, unsigned int reg,
unsigned int val)
{
struct device *dev = context;
struct i2c_client *i2c = to_i2c_client(dev);
if (val > 0xffff || reg > 0xff)
return -EINVAL;
return i2c_smbus_write_word_data(i2c, reg, val);
}
static struct regmap_bus regmap_smbus_word = {
.reg_write = regmap_smbus_word_reg_write,
.reg_read = regmap_smbus_word_reg_read,
};
static int regmap_i2c_write(void *context, const void *data, size_t count) static int regmap_i2c_write(void *context, const void *data, size_t count)
{ {
struct device *dev = context; struct device *dev = context;
...@@ -97,6 +170,23 @@ static struct regmap_bus regmap_i2c = { ...@@ -97,6 +170,23 @@ static struct regmap_bus regmap_i2c = {
.read = regmap_i2c_read, .read = regmap_i2c_read,
}; };
static const struct regmap_bus *regmap_get_i2c_bus(struct i2c_client *i2c,
const struct regmap_config *config)
{
if (i2c_check_functionality(i2c->adapter, I2C_FUNC_I2C))
return &regmap_i2c;
else if (config->val_bits == 16 && config->reg_bits == 8 &&
i2c_check_functionality(i2c->adapter,
I2C_FUNC_SMBUS_WORD_DATA))
return &regmap_smbus_word;
else if (config->val_bits == 8 && config->reg_bits == 8 &&
i2c_check_functionality(i2c->adapter,
I2C_FUNC_SMBUS_BYTE_DATA))
return &regmap_smbus_byte;
return ERR_PTR(-ENOTSUPP);
}
/** /**
* regmap_init_i2c(): Initialise register map * regmap_init_i2c(): Initialise register map
* *
...@@ -109,7 +199,12 @@ static struct regmap_bus regmap_i2c = { ...@@ -109,7 +199,12 @@ 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, &i2c->dev, config); const struct regmap_bus *bus = regmap_get_i2c_bus(i2c, config);
if (IS_ERR(bus))
return ERR_CAST(bus);
return regmap_init(&i2c->dev, bus, &i2c->dev, config);
} }
EXPORT_SYMBOL_GPL(regmap_init_i2c); EXPORT_SYMBOL_GPL(regmap_init_i2c);
...@@ -126,7 +221,12 @@ EXPORT_SYMBOL_GPL(regmap_init_i2c); ...@@ -126,7 +221,12 @@ 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, &i2c->dev, config); const struct regmap_bus *bus = regmap_get_i2c_bus(i2c, config);
if (IS_ERR(bus))
return ERR_CAST(bus);
return devm_regmap_init(&i2c->dev, bus, &i2c->dev, config);
} }
EXPORT_SYMBOL_GPL(devm_regmap_init_i2c); EXPORT_SYMBOL_GPL(devm_regmap_init_i2c);
......
...@@ -35,10 +35,14 @@ static int _regmap_update_bits(struct regmap *map, unsigned int reg, ...@@ -35,10 +35,14 @@ static int _regmap_update_bits(struct regmap *map, unsigned int reg,
unsigned int mask, unsigned int val, unsigned int mask, unsigned int val,
bool *change); bool *change);
static int _regmap_bus_reg_read(void *context, unsigned int reg,
unsigned int *val);
static int _regmap_bus_read(void *context, unsigned int reg, static int _regmap_bus_read(void *context, unsigned int reg,
unsigned int *val); unsigned int *val);
static int _regmap_bus_formatted_write(void *context, unsigned int reg, static int _regmap_bus_formatted_write(void *context, unsigned int reg,
unsigned int val); unsigned int val);
static int _regmap_bus_reg_write(void *context, unsigned int reg,
unsigned int val);
static int _regmap_bus_raw_write(void *context, unsigned int reg, static int _regmap_bus_raw_write(void *context, unsigned int reg,
unsigned int val); unsigned int val);
...@@ -535,6 +539,12 @@ struct regmap *regmap_init(struct device *dev, ...@@ -535,6 +539,12 @@ struct regmap *regmap_init(struct device *dev,
map->reg_read = config->reg_read; map->reg_read = config->reg_read;
map->reg_write = config->reg_write; map->reg_write = config->reg_write;
map->defer_caching = false;
goto skip_format_initialization;
} else if (!bus->read || !bus->write) {
map->reg_read = _regmap_bus_reg_read;
map->reg_write = _regmap_bus_reg_write;
map->defer_caching = false; map->defer_caching = false;
goto skip_format_initialization; goto skip_format_initialization;
} else { } else {
...@@ -1336,6 +1346,14 @@ static int _regmap_bus_formatted_write(void *context, unsigned int reg, ...@@ -1336,6 +1346,14 @@ static int _regmap_bus_formatted_write(void *context, unsigned int reg,
return ret; return ret;
} }
static int _regmap_bus_reg_write(void *context, unsigned int reg,
unsigned int val)
{
struct regmap *map = context;
return map->bus->reg_write(map->bus_context, reg, val);
}
static int _regmap_bus_raw_write(void *context, unsigned int reg, static int _regmap_bus_raw_write(void *context, unsigned int reg,
unsigned int val) unsigned int val)
{ {
...@@ -1980,6 +1998,14 @@ static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val, ...@@ -1980,6 +1998,14 @@ static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
return ret; return ret;
} }
static int _regmap_bus_reg_read(void *context, unsigned int reg,
unsigned int *val)
{
struct regmap *map = context;
return map->bus->reg_read(map->bus_context, reg, val);
}
static int _regmap_bus_read(void *context, unsigned int reg, static int _regmap_bus_read(void *context, unsigned int reg,
unsigned int *val) unsigned int *val)
{ {
......
...@@ -276,6 +276,10 @@ typedef int (*regmap_hw_async_write)(void *context, ...@@ -276,6 +276,10 @@ typedef int (*regmap_hw_async_write)(void *context,
typedef int (*regmap_hw_read)(void *context, 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 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 struct regmap_async *(*regmap_hw_async_alloc)(void); typedef struct regmap_async *(*regmap_hw_async_alloc)(void);
typedef void (*regmap_hw_free_context)(void *context); typedef void (*regmap_hw_free_context)(void *context);
...@@ -309,7 +313,9 @@ struct regmap_bus { ...@@ -309,7 +313,9 @@ 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_async_write async_write; regmap_hw_async_write async_write;
regmap_hw_reg_write reg_write;
regmap_hw_read read; regmap_hw_read read;
regmap_hw_reg_read reg_read;
regmap_hw_free_context free_context; regmap_hw_free_context free_context;
regmap_hw_async_alloc async_alloc; regmap_hw_async_alloc async_alloc;
u8 read_flag_mask; u8 read_flag_mask;
......
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