Loading drivers/base/regmap/regmap-i2c.c +102 −2 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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 * Loading @@ -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); Loading @@ -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); Loading drivers/base/regmap/regmap.c +26 −0 Original line number Diff line number Diff line Loading @@ -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); Loading Loading @@ -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 { Loading Loading @@ -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) { Loading Loading @@ -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) { Loading include/linux/regmap.h +6 −0 Original line number Diff line number Diff line Loading @@ -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); Loading Loading @@ -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 Loading
drivers/base/regmap/regmap-i2c.c +102 −2 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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 * Loading @@ -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); Loading @@ -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); Loading
drivers/base/regmap/regmap.c +26 −0 Original line number Diff line number Diff line Loading @@ -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); Loading Loading @@ -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 { Loading Loading @@ -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) { Loading Loading @@ -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) { Loading
include/linux/regmap.h +6 −0 Original line number Diff line number Diff line Loading @@ -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); Loading Loading @@ -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