mirror of https://gitee.com/openkylin/linux.git
Merge remote-tracking branch 'regmap/topic/smbus' into regmap-next
This commit is contained in:
commit
ef98ae45e6
|
@ -14,6 +14,79 @@
|
|||
#include <linux/i2c.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)
|
||||
{
|
||||
struct device *dev = context;
|
||||
|
@ -97,6 +170,23 @@ static struct regmap_bus regmap_i2c = {
|
|||
.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 ®map_i2c;
|
||||
else if (config->val_bits == 16 && config->reg_bits == 8 &&
|
||||
i2c_check_functionality(i2c->adapter,
|
||||
I2C_FUNC_SMBUS_WORD_DATA))
|
||||
return ®map_smbus_word;
|
||||
else if (config->val_bits == 8 && config->reg_bits == 8 &&
|
||||
i2c_check_functionality(i2c->adapter,
|
||||
I2C_FUNC_SMBUS_BYTE_DATA))
|
||||
return ®map_smbus_byte;
|
||||
|
||||
return ERR_PTR(-ENOTSUPP);
|
||||
}
|
||||
|
||||
/**
|
||||
* regmap_init_i2c(): Initialise register map
|
||||
*
|
||||
|
@ -109,7 +199,12 @@ static struct regmap_bus regmap_i2c = {
|
|||
struct regmap *regmap_init_i2c(struct i2c_client *i2c,
|
||||
const struct regmap_config *config)
|
||||
{
|
||||
return regmap_init(&i2c->dev, ®map_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);
|
||||
|
||||
|
@ -126,7 +221,12 @@ EXPORT_SYMBOL_GPL(regmap_init_i2c);
|
|||
struct regmap *devm_regmap_init_i2c(struct i2c_client *i2c,
|
||||
const struct regmap_config *config)
|
||||
{
|
||||
return devm_regmap_init(&i2c->dev, ®map_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);
|
||||
|
||||
|
|
|
@ -35,10 +35,14 @@ static int _regmap_update_bits(struct regmap *map, unsigned int reg,
|
|||
unsigned int mask, unsigned int val,
|
||||
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,
|
||||
unsigned int *val);
|
||||
static int _regmap_bus_formatted_write(void *context, unsigned int reg,
|
||||
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,
|
||||
unsigned int val);
|
||||
|
||||
|
@ -535,6 +539,12 @@ struct regmap *regmap_init(struct device *dev,
|
|||
map->reg_read = config->reg_read;
|
||||
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;
|
||||
goto skip_format_initialization;
|
||||
} else {
|
||||
|
@ -1336,6 +1346,14 @@ static int _regmap_bus_formatted_write(void *context, unsigned int reg,
|
|||
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,
|
||||
unsigned int val)
|
||||
{
|
||||
|
@ -1980,6 +1998,14 @@ static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
|
|||
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,
|
||||
unsigned int *val)
|
||||
{
|
||||
|
|
|
@ -276,6 +276,10 @@ typedef int (*regmap_hw_async_write)(void *context,
|
|||
typedef int (*regmap_hw_read)(void *context,
|
||||
const void *reg_buf, size_t reg_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 void (*regmap_hw_free_context)(void *context);
|
||||
|
||||
|
@ -309,7 +313,9 @@ struct regmap_bus {
|
|||
regmap_hw_write write;
|
||||
regmap_hw_gather_write gather_write;
|
||||
regmap_hw_async_write async_write;
|
||||
regmap_hw_reg_write reg_write;
|
||||
regmap_hw_read read;
|
||||
regmap_hw_reg_read reg_read;
|
||||
regmap_hw_free_context free_context;
|
||||
regmap_hw_async_alloc async_alloc;
|
||||
u8 read_flag_mask;
|
||||
|
|
Loading…
Reference in New Issue