Loading drivers/base/regmap/Kconfig +5 −1 Original line number Original line Diff line number Diff line Loading @@ -4,8 +4,9 @@ # subsystems should select the appropriate symbols. # subsystems should select the appropriate symbols. config REGMAP config REGMAP default y if (REGMAP_I2C || REGMAP_SPI || REGMAP_SPMI || REGMAP_W1 || REGMAP_AC97 || REGMAP_MMIO || REGMAP_IRQ || REGMAP_SOUNDWIRE || REGMAP_SOUNDWIRE_MBQ || REGMAP_SCCB || REGMAP_I3C || REGMAP_SPI_AVMM) default y if (REGMAP_I2C || REGMAP_SPI || REGMAP_SPMI || REGMAP_W1 || REGMAP_AC97 || REGMAP_MMIO || REGMAP_IRQ || REGMAP_SOUNDWIRE || REGMAP_SOUNDWIRE_MBQ || REGMAP_SCCB || REGMAP_I3C || REGMAP_SPI_AVMM || REGMAP_MDIO) select IRQ_DOMAIN if REGMAP_IRQ select IRQ_DOMAIN if REGMAP_IRQ select MDIO_BUS if REGMAP_MDIO bool bool config REGCACHE_COMPRESSED config REGCACHE_COMPRESSED Loading Loading @@ -36,6 +37,9 @@ config REGMAP_W1 tristate tristate depends on W1 depends on W1 config REGMAP_MDIO tristate config REGMAP_MMIO config REGMAP_MMIO tristate tristate Loading drivers/base/regmap/Makefile +1 −0 Original line number Original line Diff line number Diff line Loading @@ -19,3 +19,4 @@ obj-$(CONFIG_REGMAP_SOUNDWIRE_MBQ) += regmap-sdw-mbq.o obj-$(CONFIG_REGMAP_SCCB) += regmap-sccb.o obj-$(CONFIG_REGMAP_SCCB) += regmap-sccb.o obj-$(CONFIG_REGMAP_I3C) += regmap-i3c.o obj-$(CONFIG_REGMAP_I3C) += regmap-i3c.o obj-$(CONFIG_REGMAP_SPI_AVMM) += regmap-spi-avmm.o obj-$(CONFIG_REGMAP_SPI_AVMM) += regmap-spi-avmm.o obj-$(CONFIG_REGMAP_MDIO) += regmap-mdio.o drivers/base/regmap/regmap-i2c.c +38 −7 Original line number Original line Diff line number Diff line Loading @@ -306,33 +306,64 @@ static const struct regmap_bus regmap_i2c_smbus_i2c_block_reg16 = { static const struct regmap_bus *regmap_get_i2c_bus(struct i2c_client *i2c, static const struct regmap_bus *regmap_get_i2c_bus(struct i2c_client *i2c, const struct regmap_config *config) const struct regmap_config *config) { { const struct i2c_adapter_quirks *quirks; const struct regmap_bus *bus = NULL; struct regmap_bus *ret_bus; u16 max_read = 0, max_write = 0; if (i2c_check_functionality(i2c->adapter, I2C_FUNC_I2C)) if (i2c_check_functionality(i2c->adapter, I2C_FUNC_I2C)) return ®map_i2c; bus = ®map_i2c; else if (config->val_bits == 8 && config->reg_bits == 8 && else if (config->val_bits == 8 && config->reg_bits == 8 && i2c_check_functionality(i2c->adapter, i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) I2C_FUNC_SMBUS_I2C_BLOCK)) return ®map_i2c_smbus_i2c_block; bus = ®map_i2c_smbus_i2c_block; else if (config->val_bits == 8 && config->reg_bits == 16 && else if (config->val_bits == 8 && config->reg_bits == 16 && i2c_check_functionality(i2c->adapter, i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) I2C_FUNC_SMBUS_I2C_BLOCK)) return ®map_i2c_smbus_i2c_block_reg16; bus = ®map_i2c_smbus_i2c_block_reg16; else if (config->val_bits == 16 && config->reg_bits == 8 && else if (config->val_bits == 16 && config->reg_bits == 8 && i2c_check_functionality(i2c->adapter, i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_WORD_DATA)) I2C_FUNC_SMBUS_WORD_DATA)) switch (regmap_get_val_endian(&i2c->dev, NULL, config)) { switch (regmap_get_val_endian(&i2c->dev, NULL, config)) { case REGMAP_ENDIAN_LITTLE: case REGMAP_ENDIAN_LITTLE: return ®map_smbus_word; bus = ®map_smbus_word; break; case REGMAP_ENDIAN_BIG: case REGMAP_ENDIAN_BIG: return ®map_smbus_word_swapped; bus = ®map_smbus_word_swapped; break; default: /* everything else is not supported */ default: /* everything else is not supported */ break; break; } } else if (config->val_bits == 8 && config->reg_bits == 8 && else if (config->val_bits == 8 && config->reg_bits == 8 && i2c_check_functionality(i2c->adapter, i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) I2C_FUNC_SMBUS_BYTE_DATA)) return ®map_smbus_byte; bus = ®map_smbus_byte; if (!bus) return ERR_PTR(-ENOTSUPP); return ERR_PTR(-ENOTSUPP); quirks = i2c->adapter->quirks; if (quirks) { if (quirks->max_read_len && (bus->max_raw_read == 0 || bus->max_raw_read > quirks->max_read_len)) max_read = quirks->max_read_len; if (quirks->max_write_len && (bus->max_raw_write == 0 || bus->max_raw_write > quirks->max_write_len)) max_write = quirks->max_write_len; if (max_read || max_write) { ret_bus = kmemdup(bus, sizeof(*bus), GFP_KERNEL); if (!ret_bus) return ERR_PTR(-ENOMEM); ret_bus->free_on_exit = true; ret_bus->max_raw_read = max_read; ret_bus->max_raw_write = max_write; bus = ret_bus; } } return bus; } } struct regmap *__regmap_init_i2c(struct i2c_client *i2c, struct regmap *__regmap_init_i2c(struct i2c_client *i2c, Loading drivers/base/regmap/regmap-irq.c +7 −0 Original line number Original line Diff line number Diff line Loading @@ -531,6 +531,10 @@ static irqreturn_t regmap_irq_thread(int irq, void *d) } } } } if (chip->status_invert) for (i = 0; i < data->chip->num_regs; i++) data->status_buf[i] = ~data->status_buf[i]; /* /* * Ignore masked IRQs and ack if we need to; we ack early so * Ignore masked IRQs and ack if we need to; we ack early so * there is no race between handling and acknowleding the * there is no race between handling and acknowleding the Loading Loading @@ -800,6 +804,9 @@ int regmap_add_irq_chip_fwnode(struct fwnode_handle *fwnode, goto err_alloc; goto err_alloc; } } if (chip->status_invert) d->status_buf[i] = ~d->status_buf[i]; if (d->status_buf[i] && (chip->ack_base || chip->use_ack)) { if (d->status_buf[i] && (chip->ack_base || chip->use_ack)) { reg = sub_irq_reg(d, d->chip->ack_base, i); reg = sub_irq_reg(d, d->chip->ack_base, i); if (chip->ack_invert) if (chip->ack_invert) Loading drivers/base/regmap/regmap-mdio.c 0 → 100644 +116 −0 Original line number Original line Diff line number Diff line // SPDX-License-Identifier: GPL-2.0 #include <linux/errno.h> #include <linux/mdio.h> #include <linux/module.h> #include <linux/regmap.h> #define REGVAL_MASK GENMASK(15, 0) #define REGNUM_C22_MASK GENMASK(4, 0) /* Clause-45 mask includes the device type (5 bit) and actual register number (16 bit) */ #define REGNUM_C45_MASK GENMASK(20, 0) static int regmap_mdio_read(struct mdio_device *mdio_dev, u32 reg, unsigned int *val) { int ret; ret = mdiobus_read(mdio_dev->bus, mdio_dev->addr, reg); if (ret < 0) return ret; *val = ret & REGVAL_MASK; return 0; } static int regmap_mdio_write(struct mdio_device *mdio_dev, u32 reg, unsigned int val) { return mdiobus_write(mdio_dev->bus, mdio_dev->addr, reg, val); } static int regmap_mdio_c22_read(void *context, unsigned int reg, unsigned int *val) { struct mdio_device *mdio_dev = context; if (unlikely(reg & ~REGNUM_C22_MASK)) return -ENXIO; return regmap_mdio_read(mdio_dev, reg, val); } static int regmap_mdio_c22_write(void *context, unsigned int reg, unsigned int val) { struct mdio_device *mdio_dev = context; if (unlikely(reg & ~REGNUM_C22_MASK)) return -ENXIO; return mdiobus_write(mdio_dev->bus, mdio_dev->addr, reg, val); } static const struct regmap_bus regmap_mdio_c22_bus = { .reg_write = regmap_mdio_c22_write, .reg_read = regmap_mdio_c22_read, }; static int regmap_mdio_c45_read(void *context, unsigned int reg, unsigned int *val) { struct mdio_device *mdio_dev = context; if (unlikely(reg & ~REGNUM_C45_MASK)) return -ENXIO; return regmap_mdio_read(mdio_dev, MII_ADDR_C45 | reg, val); } static int regmap_mdio_c45_write(void *context, unsigned int reg, unsigned int val) { struct mdio_device *mdio_dev = context; if (unlikely(reg & ~REGNUM_C45_MASK)) return -ENXIO; return regmap_mdio_write(mdio_dev, MII_ADDR_C45 | reg, val); } static const struct regmap_bus regmap_mdio_c45_bus = { .reg_write = regmap_mdio_c45_write, .reg_read = regmap_mdio_c45_read, }; struct regmap *__regmap_init_mdio(struct mdio_device *mdio_dev, const struct regmap_config *config, struct lock_class_key *lock_key, const char *lock_name) { const struct regmap_bus *bus; if (config->reg_bits == 5 && config->val_bits == 16) bus = ®map_mdio_c22_bus; else if (config->reg_bits == 21 && config->val_bits == 16) bus = ®map_mdio_c45_bus; else return ERR_PTR(-EOPNOTSUPP); return __regmap_init(&mdio_dev->dev, bus, mdio_dev, config, lock_key, lock_name); } EXPORT_SYMBOL_GPL(__regmap_init_mdio); struct regmap *__devm_regmap_init_mdio(struct mdio_device *mdio_dev, const struct regmap_config *config, struct lock_class_key *lock_key, const char *lock_name) { const struct regmap_bus *bus; if (config->reg_bits == 5 && config->val_bits == 16) bus = ®map_mdio_c22_bus; else if (config->reg_bits == 21 && config->val_bits == 16) bus = ®map_mdio_c45_bus; else return ERR_PTR(-EOPNOTSUPP); return __devm_regmap_init(&mdio_dev->dev, bus, mdio_dev, config, lock_key, lock_name); } EXPORT_SYMBOL_GPL(__devm_regmap_init_mdio); MODULE_AUTHOR("Sander Vanheule <sander@svanheule.net>"); MODULE_DESCRIPTION("Regmap MDIO Module"); MODULE_LICENSE("GPL v2"); Loading
drivers/base/regmap/Kconfig +5 −1 Original line number Original line Diff line number Diff line Loading @@ -4,8 +4,9 @@ # subsystems should select the appropriate symbols. # subsystems should select the appropriate symbols. config REGMAP config REGMAP default y if (REGMAP_I2C || REGMAP_SPI || REGMAP_SPMI || REGMAP_W1 || REGMAP_AC97 || REGMAP_MMIO || REGMAP_IRQ || REGMAP_SOUNDWIRE || REGMAP_SOUNDWIRE_MBQ || REGMAP_SCCB || REGMAP_I3C || REGMAP_SPI_AVMM) default y if (REGMAP_I2C || REGMAP_SPI || REGMAP_SPMI || REGMAP_W1 || REGMAP_AC97 || REGMAP_MMIO || REGMAP_IRQ || REGMAP_SOUNDWIRE || REGMAP_SOUNDWIRE_MBQ || REGMAP_SCCB || REGMAP_I3C || REGMAP_SPI_AVMM || REGMAP_MDIO) select IRQ_DOMAIN if REGMAP_IRQ select IRQ_DOMAIN if REGMAP_IRQ select MDIO_BUS if REGMAP_MDIO bool bool config REGCACHE_COMPRESSED config REGCACHE_COMPRESSED Loading Loading @@ -36,6 +37,9 @@ config REGMAP_W1 tristate tristate depends on W1 depends on W1 config REGMAP_MDIO tristate config REGMAP_MMIO config REGMAP_MMIO tristate tristate Loading
drivers/base/regmap/Makefile +1 −0 Original line number Original line Diff line number Diff line Loading @@ -19,3 +19,4 @@ obj-$(CONFIG_REGMAP_SOUNDWIRE_MBQ) += regmap-sdw-mbq.o obj-$(CONFIG_REGMAP_SCCB) += regmap-sccb.o obj-$(CONFIG_REGMAP_SCCB) += regmap-sccb.o obj-$(CONFIG_REGMAP_I3C) += regmap-i3c.o obj-$(CONFIG_REGMAP_I3C) += regmap-i3c.o obj-$(CONFIG_REGMAP_SPI_AVMM) += regmap-spi-avmm.o obj-$(CONFIG_REGMAP_SPI_AVMM) += regmap-spi-avmm.o obj-$(CONFIG_REGMAP_MDIO) += regmap-mdio.o
drivers/base/regmap/regmap-i2c.c +38 −7 Original line number Original line Diff line number Diff line Loading @@ -306,33 +306,64 @@ static const struct regmap_bus regmap_i2c_smbus_i2c_block_reg16 = { static const struct regmap_bus *regmap_get_i2c_bus(struct i2c_client *i2c, static const struct regmap_bus *regmap_get_i2c_bus(struct i2c_client *i2c, const struct regmap_config *config) const struct regmap_config *config) { { const struct i2c_adapter_quirks *quirks; const struct regmap_bus *bus = NULL; struct regmap_bus *ret_bus; u16 max_read = 0, max_write = 0; if (i2c_check_functionality(i2c->adapter, I2C_FUNC_I2C)) if (i2c_check_functionality(i2c->adapter, I2C_FUNC_I2C)) return ®map_i2c; bus = ®map_i2c; else if (config->val_bits == 8 && config->reg_bits == 8 && else if (config->val_bits == 8 && config->reg_bits == 8 && i2c_check_functionality(i2c->adapter, i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) I2C_FUNC_SMBUS_I2C_BLOCK)) return ®map_i2c_smbus_i2c_block; bus = ®map_i2c_smbus_i2c_block; else if (config->val_bits == 8 && config->reg_bits == 16 && else if (config->val_bits == 8 && config->reg_bits == 16 && i2c_check_functionality(i2c->adapter, i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) I2C_FUNC_SMBUS_I2C_BLOCK)) return ®map_i2c_smbus_i2c_block_reg16; bus = ®map_i2c_smbus_i2c_block_reg16; else if (config->val_bits == 16 && config->reg_bits == 8 && else if (config->val_bits == 16 && config->reg_bits == 8 && i2c_check_functionality(i2c->adapter, i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_WORD_DATA)) I2C_FUNC_SMBUS_WORD_DATA)) switch (regmap_get_val_endian(&i2c->dev, NULL, config)) { switch (regmap_get_val_endian(&i2c->dev, NULL, config)) { case REGMAP_ENDIAN_LITTLE: case REGMAP_ENDIAN_LITTLE: return ®map_smbus_word; bus = ®map_smbus_word; break; case REGMAP_ENDIAN_BIG: case REGMAP_ENDIAN_BIG: return ®map_smbus_word_swapped; bus = ®map_smbus_word_swapped; break; default: /* everything else is not supported */ default: /* everything else is not supported */ break; break; } } else if (config->val_bits == 8 && config->reg_bits == 8 && else if (config->val_bits == 8 && config->reg_bits == 8 && i2c_check_functionality(i2c->adapter, i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) I2C_FUNC_SMBUS_BYTE_DATA)) return ®map_smbus_byte; bus = ®map_smbus_byte; if (!bus) return ERR_PTR(-ENOTSUPP); return ERR_PTR(-ENOTSUPP); quirks = i2c->adapter->quirks; if (quirks) { if (quirks->max_read_len && (bus->max_raw_read == 0 || bus->max_raw_read > quirks->max_read_len)) max_read = quirks->max_read_len; if (quirks->max_write_len && (bus->max_raw_write == 0 || bus->max_raw_write > quirks->max_write_len)) max_write = quirks->max_write_len; if (max_read || max_write) { ret_bus = kmemdup(bus, sizeof(*bus), GFP_KERNEL); if (!ret_bus) return ERR_PTR(-ENOMEM); ret_bus->free_on_exit = true; ret_bus->max_raw_read = max_read; ret_bus->max_raw_write = max_write; bus = ret_bus; } } return bus; } } struct regmap *__regmap_init_i2c(struct i2c_client *i2c, struct regmap *__regmap_init_i2c(struct i2c_client *i2c, Loading
drivers/base/regmap/regmap-irq.c +7 −0 Original line number Original line Diff line number Diff line Loading @@ -531,6 +531,10 @@ static irqreturn_t regmap_irq_thread(int irq, void *d) } } } } if (chip->status_invert) for (i = 0; i < data->chip->num_regs; i++) data->status_buf[i] = ~data->status_buf[i]; /* /* * Ignore masked IRQs and ack if we need to; we ack early so * Ignore masked IRQs and ack if we need to; we ack early so * there is no race between handling and acknowleding the * there is no race between handling and acknowleding the Loading Loading @@ -800,6 +804,9 @@ int regmap_add_irq_chip_fwnode(struct fwnode_handle *fwnode, goto err_alloc; goto err_alloc; } } if (chip->status_invert) d->status_buf[i] = ~d->status_buf[i]; if (d->status_buf[i] && (chip->ack_base || chip->use_ack)) { if (d->status_buf[i] && (chip->ack_base || chip->use_ack)) { reg = sub_irq_reg(d, d->chip->ack_base, i); reg = sub_irq_reg(d, d->chip->ack_base, i); if (chip->ack_invert) if (chip->ack_invert) Loading
drivers/base/regmap/regmap-mdio.c 0 → 100644 +116 −0 Original line number Original line Diff line number Diff line // SPDX-License-Identifier: GPL-2.0 #include <linux/errno.h> #include <linux/mdio.h> #include <linux/module.h> #include <linux/regmap.h> #define REGVAL_MASK GENMASK(15, 0) #define REGNUM_C22_MASK GENMASK(4, 0) /* Clause-45 mask includes the device type (5 bit) and actual register number (16 bit) */ #define REGNUM_C45_MASK GENMASK(20, 0) static int regmap_mdio_read(struct mdio_device *mdio_dev, u32 reg, unsigned int *val) { int ret; ret = mdiobus_read(mdio_dev->bus, mdio_dev->addr, reg); if (ret < 0) return ret; *val = ret & REGVAL_MASK; return 0; } static int regmap_mdio_write(struct mdio_device *mdio_dev, u32 reg, unsigned int val) { return mdiobus_write(mdio_dev->bus, mdio_dev->addr, reg, val); } static int regmap_mdio_c22_read(void *context, unsigned int reg, unsigned int *val) { struct mdio_device *mdio_dev = context; if (unlikely(reg & ~REGNUM_C22_MASK)) return -ENXIO; return regmap_mdio_read(mdio_dev, reg, val); } static int regmap_mdio_c22_write(void *context, unsigned int reg, unsigned int val) { struct mdio_device *mdio_dev = context; if (unlikely(reg & ~REGNUM_C22_MASK)) return -ENXIO; return mdiobus_write(mdio_dev->bus, mdio_dev->addr, reg, val); } static const struct regmap_bus regmap_mdio_c22_bus = { .reg_write = regmap_mdio_c22_write, .reg_read = regmap_mdio_c22_read, }; static int regmap_mdio_c45_read(void *context, unsigned int reg, unsigned int *val) { struct mdio_device *mdio_dev = context; if (unlikely(reg & ~REGNUM_C45_MASK)) return -ENXIO; return regmap_mdio_read(mdio_dev, MII_ADDR_C45 | reg, val); } static int regmap_mdio_c45_write(void *context, unsigned int reg, unsigned int val) { struct mdio_device *mdio_dev = context; if (unlikely(reg & ~REGNUM_C45_MASK)) return -ENXIO; return regmap_mdio_write(mdio_dev, MII_ADDR_C45 | reg, val); } static const struct regmap_bus regmap_mdio_c45_bus = { .reg_write = regmap_mdio_c45_write, .reg_read = regmap_mdio_c45_read, }; struct regmap *__regmap_init_mdio(struct mdio_device *mdio_dev, const struct regmap_config *config, struct lock_class_key *lock_key, const char *lock_name) { const struct regmap_bus *bus; if (config->reg_bits == 5 && config->val_bits == 16) bus = ®map_mdio_c22_bus; else if (config->reg_bits == 21 && config->val_bits == 16) bus = ®map_mdio_c45_bus; else return ERR_PTR(-EOPNOTSUPP); return __regmap_init(&mdio_dev->dev, bus, mdio_dev, config, lock_key, lock_name); } EXPORT_SYMBOL_GPL(__regmap_init_mdio); struct regmap *__devm_regmap_init_mdio(struct mdio_device *mdio_dev, const struct regmap_config *config, struct lock_class_key *lock_key, const char *lock_name) { const struct regmap_bus *bus; if (config->reg_bits == 5 && config->val_bits == 16) bus = ®map_mdio_c22_bus; else if (config->reg_bits == 21 && config->val_bits == 16) bus = ®map_mdio_c45_bus; else return ERR_PTR(-EOPNOTSUPP); return __devm_regmap_init(&mdio_dev->dev, bus, mdio_dev, config, lock_key, lock_name); } EXPORT_SYMBOL_GPL(__devm_regmap_init_mdio); MODULE_AUTHOR("Sander Vanheule <sander@svanheule.net>"); MODULE_DESCRIPTION("Regmap MDIO Module"); MODULE_LICENSE("GPL v2");