Loading drivers/base/regmap/Kconfig +4 −0 Original line number Original line Diff line number Diff line Loading @@ -45,3 +45,7 @@ config REGMAP_IRQ config REGMAP_SOUNDWIRE config REGMAP_SOUNDWIRE tristate tristate depends on SOUNDWIRE_BUS depends on SOUNDWIRE_BUS config REGMAP_SCCB tristate depends on I2C drivers/base/regmap/Makefile +1 −0 Original line number Original line Diff line number Diff line Loading @@ -15,3 +15,4 @@ obj-$(CONFIG_REGMAP_MMIO) += regmap-mmio.o obj-$(CONFIG_REGMAP_IRQ) += regmap-irq.o obj-$(CONFIG_REGMAP_IRQ) += regmap-irq.o obj-$(CONFIG_REGMAP_W1) += regmap-w1.o obj-$(CONFIG_REGMAP_W1) += regmap-w1.o obj-$(CONFIG_REGMAP_SOUNDWIRE) += regmap-sdw.o obj-$(CONFIG_REGMAP_SOUNDWIRE) += regmap-sdw.o obj-$(CONFIG_REGMAP_SCCB) += regmap-sccb.o drivers/base/regmap/internal.h +3 −0 Original line number Original line Diff line number Diff line Loading @@ -94,10 +94,12 @@ struct regmap { bool (*readable_reg)(struct device *dev, unsigned int reg); bool (*readable_reg)(struct device *dev, unsigned int reg); bool (*volatile_reg)(struct device *dev, unsigned int reg); bool (*volatile_reg)(struct device *dev, unsigned int reg); bool (*precious_reg)(struct device *dev, unsigned int reg); bool (*precious_reg)(struct device *dev, unsigned int reg); bool (*readable_noinc_reg)(struct device *dev, unsigned int reg); const struct regmap_access_table *wr_table; const struct regmap_access_table *wr_table; const struct regmap_access_table *rd_table; const struct regmap_access_table *rd_table; const struct regmap_access_table *volatile_table; const struct regmap_access_table *volatile_table; const struct regmap_access_table *precious_table; const struct regmap_access_table *precious_table; const struct regmap_access_table *rd_noinc_table; int (*reg_read)(void *context, unsigned int reg, unsigned int *val); int (*reg_read)(void *context, unsigned int reg, unsigned int *val); int (*reg_write)(void *context, unsigned int reg, unsigned int val); int (*reg_write)(void *context, unsigned int reg, unsigned int val); Loading Loading @@ -181,6 +183,7 @@ bool regmap_writeable(struct regmap *map, unsigned int reg); bool regmap_readable(struct regmap *map, unsigned int reg); bool regmap_readable(struct regmap *map, unsigned int reg); bool regmap_volatile(struct regmap *map, unsigned int reg); bool regmap_volatile(struct regmap *map, unsigned int reg); bool regmap_precious(struct regmap *map, unsigned int reg); bool regmap_precious(struct regmap *map, unsigned int reg); bool regmap_readable_noinc(struct regmap *map, unsigned int reg); int _regmap_write(struct regmap *map, unsigned int reg, int _regmap_write(struct regmap *map, unsigned int reg, unsigned int val); unsigned int val); Loading drivers/base/regmap/regmap-sccb.c 0 → 100644 +128 −0 Original line number Original line Diff line number Diff line // SPDX-License-Identifier: GPL-2.0 // Register map access API - SCCB support #include <linux/i2c.h> #include <linux/module.h> #include <linux/regmap.h> #include "internal.h" /** * sccb_is_available - Check if the adapter supports SCCB protocol * @adap: I2C adapter * * Return true if the I2C adapter is capable of using SCCB helper functions, * false otherwise. */ static bool sccb_is_available(struct i2c_adapter *adap) { u32 needed_funcs = I2C_FUNC_SMBUS_BYTE | I2C_FUNC_SMBUS_WRITE_BYTE_DATA; /* * If we ever want support for hardware doing SCCB natively, we will * introduce a sccb_xfer() callback to struct i2c_algorithm and check * for it here. */ return (i2c_get_functionality(adap) & needed_funcs) == needed_funcs; } /** * regmap_sccb_read - Read data from SCCB slave device * @context: Device that will be interacted with * @reg: Register to be read from * @val: Pointer to store read value * * This executes the 2-phase write transmission cycle that is followed by a * 2-phase read transmission cycle, returning negative errno else zero on * success. */ static int regmap_sccb_read(void *context, unsigned int reg, unsigned int *val) { struct device *dev = context; struct i2c_client *i2c = to_i2c_client(dev); int ret; union i2c_smbus_data data; i2c_lock_bus(i2c->adapter, I2C_LOCK_SEGMENT); ret = __i2c_smbus_xfer(i2c->adapter, i2c->addr, i2c->flags, I2C_SMBUS_WRITE, reg, I2C_SMBUS_BYTE, NULL); if (ret < 0) goto out; ret = __i2c_smbus_xfer(i2c->adapter, i2c->addr, i2c->flags, I2C_SMBUS_READ, 0, I2C_SMBUS_BYTE, &data); if (ret < 0) goto out; *val = data.byte; out: i2c_unlock_bus(i2c->adapter, I2C_LOCK_SEGMENT); return ret; } /** * regmap_sccb_write - Write data to SCCB slave device * @context: Device that will be interacted with * @reg: Register to write to * @val: Value to be written * * This executes the SCCB 3-phase write transmission cycle, returning negative * errno else zero on success. */ static int regmap_sccb_write(void *context, unsigned int reg, unsigned int val) { struct device *dev = context; struct i2c_client *i2c = to_i2c_client(dev); return i2c_smbus_write_byte_data(i2c, reg, val); } static struct regmap_bus regmap_sccb_bus = { .reg_write = regmap_sccb_write, .reg_read = regmap_sccb_read, }; static const struct regmap_bus *regmap_get_sccb_bus(struct i2c_client *i2c, const struct regmap_config *config) { if (config->val_bits == 8 && config->reg_bits == 8 && sccb_is_available(i2c->adapter)) return ®map_sccb_bus; return ERR_PTR(-ENOTSUPP); } struct regmap *__regmap_init_sccb(struct i2c_client *i2c, const struct regmap_config *config, struct lock_class_key *lock_key, const char *lock_name) { const struct regmap_bus *bus = regmap_get_sccb_bus(i2c, config); if (IS_ERR(bus)) return ERR_CAST(bus); return __regmap_init(&i2c->dev, bus, &i2c->dev, config, lock_key, lock_name); } EXPORT_SYMBOL_GPL(__regmap_init_sccb); struct regmap *__devm_regmap_init_sccb(struct i2c_client *i2c, const struct regmap_config *config, struct lock_class_key *lock_key, const char *lock_name) { const struct regmap_bus *bus = regmap_get_sccb_bus(i2c, config); if (IS_ERR(bus)) return ERR_CAST(bus); return __devm_regmap_init(&i2c->dev, bus, &i2c->dev, config, lock_key, lock_name); } EXPORT_SYMBOL_GPL(__devm_regmap_init_sccb); MODULE_LICENSE("GPL v2"); drivers/base/regmap/regmap-slimbus.c +7 −16 Original line number Original line Diff line number Diff line Loading @@ -7,33 +7,24 @@ #include "internal.h" #include "internal.h" static int regmap_slimbus_byte_reg_read(void *context, unsigned int reg, static int regmap_slimbus_write(void *context, const void *data, size_t count) unsigned int *val) { { struct slim_device *sdev = context; struct slim_device *sdev = context; int v; v = slim_readb(sdev, reg); return slim_write(sdev, *(u16 *)data, count - 2, (u8 *)data + 2); if (v < 0) return v; *val = v; return 0; } } static int regmap_slimbus_byte_reg_write(void *context, unsigned int reg, static int regmap_slimbus_read(void *context, const void *reg, size_t reg_size, unsigned int val) void *val, size_t val_size) { { struct slim_device *sdev = context; struct slim_device *sdev = context; return slim_writeb(sdev, reg, val); return slim_read(sdev, *(u16 *)reg, val_size, val); } } static struct regmap_bus regmap_slimbus_bus = { static struct regmap_bus regmap_slimbus_bus = { .reg_write = regmap_slimbus_byte_reg_write, .write = regmap_slimbus_write, .reg_read = regmap_slimbus_byte_reg_read, .read = regmap_slimbus_read, .reg_format_endian_default = REGMAP_ENDIAN_LITTLE, .reg_format_endian_default = REGMAP_ENDIAN_LITTLE, .val_format_endian_default = REGMAP_ENDIAN_LITTLE, .val_format_endian_default = REGMAP_ENDIAN_LITTLE, }; }; Loading Loading
drivers/base/regmap/Kconfig +4 −0 Original line number Original line Diff line number Diff line Loading @@ -45,3 +45,7 @@ config REGMAP_IRQ config REGMAP_SOUNDWIRE config REGMAP_SOUNDWIRE tristate tristate depends on SOUNDWIRE_BUS depends on SOUNDWIRE_BUS config REGMAP_SCCB tristate depends on I2C
drivers/base/regmap/Makefile +1 −0 Original line number Original line Diff line number Diff line Loading @@ -15,3 +15,4 @@ obj-$(CONFIG_REGMAP_MMIO) += regmap-mmio.o obj-$(CONFIG_REGMAP_IRQ) += regmap-irq.o obj-$(CONFIG_REGMAP_IRQ) += regmap-irq.o obj-$(CONFIG_REGMAP_W1) += regmap-w1.o obj-$(CONFIG_REGMAP_W1) += regmap-w1.o obj-$(CONFIG_REGMAP_SOUNDWIRE) += regmap-sdw.o obj-$(CONFIG_REGMAP_SOUNDWIRE) += regmap-sdw.o obj-$(CONFIG_REGMAP_SCCB) += regmap-sccb.o
drivers/base/regmap/internal.h +3 −0 Original line number Original line Diff line number Diff line Loading @@ -94,10 +94,12 @@ struct regmap { bool (*readable_reg)(struct device *dev, unsigned int reg); bool (*readable_reg)(struct device *dev, unsigned int reg); bool (*volatile_reg)(struct device *dev, unsigned int reg); bool (*volatile_reg)(struct device *dev, unsigned int reg); bool (*precious_reg)(struct device *dev, unsigned int reg); bool (*precious_reg)(struct device *dev, unsigned int reg); bool (*readable_noinc_reg)(struct device *dev, unsigned int reg); const struct regmap_access_table *wr_table; const struct regmap_access_table *wr_table; const struct regmap_access_table *rd_table; const struct regmap_access_table *rd_table; const struct regmap_access_table *volatile_table; const struct regmap_access_table *volatile_table; const struct regmap_access_table *precious_table; const struct regmap_access_table *precious_table; const struct regmap_access_table *rd_noinc_table; int (*reg_read)(void *context, unsigned int reg, unsigned int *val); int (*reg_read)(void *context, unsigned int reg, unsigned int *val); int (*reg_write)(void *context, unsigned int reg, unsigned int val); int (*reg_write)(void *context, unsigned int reg, unsigned int val); Loading Loading @@ -181,6 +183,7 @@ bool regmap_writeable(struct regmap *map, unsigned int reg); bool regmap_readable(struct regmap *map, unsigned int reg); bool regmap_readable(struct regmap *map, unsigned int reg); bool regmap_volatile(struct regmap *map, unsigned int reg); bool regmap_volatile(struct regmap *map, unsigned int reg); bool regmap_precious(struct regmap *map, unsigned int reg); bool regmap_precious(struct regmap *map, unsigned int reg); bool regmap_readable_noinc(struct regmap *map, unsigned int reg); int _regmap_write(struct regmap *map, unsigned int reg, int _regmap_write(struct regmap *map, unsigned int reg, unsigned int val); unsigned int val); Loading
drivers/base/regmap/regmap-sccb.c 0 → 100644 +128 −0 Original line number Original line Diff line number Diff line // SPDX-License-Identifier: GPL-2.0 // Register map access API - SCCB support #include <linux/i2c.h> #include <linux/module.h> #include <linux/regmap.h> #include "internal.h" /** * sccb_is_available - Check if the adapter supports SCCB protocol * @adap: I2C adapter * * Return true if the I2C adapter is capable of using SCCB helper functions, * false otherwise. */ static bool sccb_is_available(struct i2c_adapter *adap) { u32 needed_funcs = I2C_FUNC_SMBUS_BYTE | I2C_FUNC_SMBUS_WRITE_BYTE_DATA; /* * If we ever want support for hardware doing SCCB natively, we will * introduce a sccb_xfer() callback to struct i2c_algorithm and check * for it here. */ return (i2c_get_functionality(adap) & needed_funcs) == needed_funcs; } /** * regmap_sccb_read - Read data from SCCB slave device * @context: Device that will be interacted with * @reg: Register to be read from * @val: Pointer to store read value * * This executes the 2-phase write transmission cycle that is followed by a * 2-phase read transmission cycle, returning negative errno else zero on * success. */ static int regmap_sccb_read(void *context, unsigned int reg, unsigned int *val) { struct device *dev = context; struct i2c_client *i2c = to_i2c_client(dev); int ret; union i2c_smbus_data data; i2c_lock_bus(i2c->adapter, I2C_LOCK_SEGMENT); ret = __i2c_smbus_xfer(i2c->adapter, i2c->addr, i2c->flags, I2C_SMBUS_WRITE, reg, I2C_SMBUS_BYTE, NULL); if (ret < 0) goto out; ret = __i2c_smbus_xfer(i2c->adapter, i2c->addr, i2c->flags, I2C_SMBUS_READ, 0, I2C_SMBUS_BYTE, &data); if (ret < 0) goto out; *val = data.byte; out: i2c_unlock_bus(i2c->adapter, I2C_LOCK_SEGMENT); return ret; } /** * regmap_sccb_write - Write data to SCCB slave device * @context: Device that will be interacted with * @reg: Register to write to * @val: Value to be written * * This executes the SCCB 3-phase write transmission cycle, returning negative * errno else zero on success. */ static int regmap_sccb_write(void *context, unsigned int reg, unsigned int val) { struct device *dev = context; struct i2c_client *i2c = to_i2c_client(dev); return i2c_smbus_write_byte_data(i2c, reg, val); } static struct regmap_bus regmap_sccb_bus = { .reg_write = regmap_sccb_write, .reg_read = regmap_sccb_read, }; static const struct regmap_bus *regmap_get_sccb_bus(struct i2c_client *i2c, const struct regmap_config *config) { if (config->val_bits == 8 && config->reg_bits == 8 && sccb_is_available(i2c->adapter)) return ®map_sccb_bus; return ERR_PTR(-ENOTSUPP); } struct regmap *__regmap_init_sccb(struct i2c_client *i2c, const struct regmap_config *config, struct lock_class_key *lock_key, const char *lock_name) { const struct regmap_bus *bus = regmap_get_sccb_bus(i2c, config); if (IS_ERR(bus)) return ERR_CAST(bus); return __regmap_init(&i2c->dev, bus, &i2c->dev, config, lock_key, lock_name); } EXPORT_SYMBOL_GPL(__regmap_init_sccb); struct regmap *__devm_regmap_init_sccb(struct i2c_client *i2c, const struct regmap_config *config, struct lock_class_key *lock_key, const char *lock_name) { const struct regmap_bus *bus = regmap_get_sccb_bus(i2c, config); if (IS_ERR(bus)) return ERR_CAST(bus); return __devm_regmap_init(&i2c->dev, bus, &i2c->dev, config, lock_key, lock_name); } EXPORT_SYMBOL_GPL(__devm_regmap_init_sccb); MODULE_LICENSE("GPL v2");
drivers/base/regmap/regmap-slimbus.c +7 −16 Original line number Original line Diff line number Diff line Loading @@ -7,33 +7,24 @@ #include "internal.h" #include "internal.h" static int regmap_slimbus_byte_reg_read(void *context, unsigned int reg, static int regmap_slimbus_write(void *context, const void *data, size_t count) unsigned int *val) { { struct slim_device *sdev = context; struct slim_device *sdev = context; int v; v = slim_readb(sdev, reg); return slim_write(sdev, *(u16 *)data, count - 2, (u8 *)data + 2); if (v < 0) return v; *val = v; return 0; } } static int regmap_slimbus_byte_reg_write(void *context, unsigned int reg, static int regmap_slimbus_read(void *context, const void *reg, size_t reg_size, unsigned int val) void *val, size_t val_size) { { struct slim_device *sdev = context; struct slim_device *sdev = context; return slim_writeb(sdev, reg, val); return slim_read(sdev, *(u16 *)reg, val_size, val); } } static struct regmap_bus regmap_slimbus_bus = { static struct regmap_bus regmap_slimbus_bus = { .reg_write = regmap_slimbus_byte_reg_write, .write = regmap_slimbus_write, .reg_read = regmap_slimbus_byte_reg_read, .read = regmap_slimbus_read, .reg_format_endian_default = REGMAP_ENDIAN_LITTLE, .reg_format_endian_default = REGMAP_ENDIAN_LITTLE, .val_format_endian_default = REGMAP_ENDIAN_LITTLE, .val_format_endian_default = REGMAP_ENDIAN_LITTLE, }; }; Loading