Using regmap apis for accessing the device register. using the RBTREE caching mechanims for caching registers. Also provided apis for enabling register cache from different sub devices of ts65910. Signed-off-by: Laxman Dewangan <ldewangan@xxxxxxxxxx> --- This patch is towards the performance improvements in the voltage change. drivers/mfd/Kconfig | 1 + drivers/mfd/tps65910.c | 136 +++++++++++++++++++----------------------- include/linux/mfd/tps65910.h | 3 + 3 files changed, 65 insertions(+), 75 deletions(-) diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index cd13e9f..0e066cd 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -162,6 +162,7 @@ config MFD_TPS65910 depends on I2C=y && GPIOLIB select MFD_CORE select GPIO_TPS65910 + select REGMAP_I2C help if you say yes here you get support for the TPS65910 series of Power Management chips. diff --git a/drivers/mfd/tps65910.c b/drivers/mfd/tps65910.c index 01cf501..1f2b004 100644 --- a/drivers/mfd/tps65910.c +++ b/drivers/mfd/tps65910.c @@ -16,10 +16,12 @@ #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/init.h> +#include <linux/err.h> #include <linux/slab.h> #include <linux/i2c.h> #include <linux/gpio.h> #include <linux/mfd/core.h> +#include <linux/regmap.h> #include <linux/mfd/tps65910.h> static struct mfd_cell tps65910s[] = { @@ -34,103 +36,76 @@ static struct mfd_cell tps65910s[] = { }, }; +static bool is_volatile_reg(struct device *dev, unsigned int reg) +{ + struct tps65910 *tps65910 = dev_get_drvdata(dev); + return test_bit(reg, tps65910->cache_reg) ? false : true; +} + +static bool regmap_volatile_range(struct tps65910 *tps65910, + unsigned int reg, unsigned int bytes) +{ + unsigned int i; + for (i = 0; i < bytes; i++) + if (!is_volatile_reg(tps65910->dev, reg + i)) + return false; + return true; +} static int tps65910_i2c_read(struct tps65910 *tps65910, u8 reg, int bytes, void *dest) { - struct i2c_client *i2c = tps65910->i2c_client; - struct i2c_msg xfer[2]; - int ret; - - /* Write register */ - xfer[0].addr = i2c->addr; - xfer[0].flags = 0; - xfer[0].len = 1; - xfer[0].buf = ® - - /* Read data */ - xfer[1].addr = i2c->addr; - xfer[1].flags = I2C_M_RD; - xfer[1].len = bytes; - xfer[1].buf = dest; - - ret = i2c_transfer(i2c->adapter, xfer, 2); - if (ret == 2) - ret = 0; - else if (ret >= 0) - ret = -EIO; - - return ret; + return regmap_bulk_read(tps65910->regmap, reg, dest, bytes); } static int tps65910_i2c_write(struct tps65910 *tps65910, u8 reg, - int bytes, void *src) + int bytes, void *src) { - struct i2c_client *i2c = tps65910->i2c_client; - /* we add 1 byte for device register */ - u8 msg[TPS65910_MAX_REGISTER + 1]; + int i; int ret; - - if (bytes > TPS65910_MAX_REGISTER) - return -EINVAL; - - msg[0] = reg; - memcpy(&msg[1], src, bytes); - - ret = i2c_master_send(i2c, msg, bytes + 1); - if (ret < 0) - return ret; - if (ret != bytes + 1) - return -EIO; + unsigned char *wbuf = src; + unsigned int ival; + + if (regmap_volatile_range(tps65910, reg, bytes)) + return regmap_raw_write(tps65910->regmap, reg, src, bytes); + + /* If any of register is non-volatile then use byte-wise transfer */ + for (i = 0; i < bytes; ++i) { + ival = (unsigned int) (*wbuf++); + ret = regmap_write(tps65910->regmap, reg, ival); + if (ret < 0) + return ret; + } return 0; } int tps65910_set_bits(struct tps65910 *tps65910, u8 reg, u8 mask) { - u8 data; - int err; - - mutex_lock(&tps65910->io_mutex); - err = tps65910_i2c_read(tps65910, reg, 1, &data); - if (err) { - dev_err(tps65910->dev, "read from reg %x failed\n", reg); - goto out; - } - - data |= mask; - err = tps65910_i2c_write(tps65910, reg, 1, &data); - if (err) - dev_err(tps65910->dev, "write to reg %x failed\n", reg); - -out: - mutex_unlock(&tps65910->io_mutex); - return err; + return regmap_update_bits(tps65910->regmap, reg, mask, mask); } EXPORT_SYMBOL_GPL(tps65910_set_bits); int tps65910_clear_bits(struct tps65910 *tps65910, u8 reg, u8 mask) { - u8 data; - int err; - - mutex_lock(&tps65910->io_mutex); - err = tps65910_i2c_read(tps65910, reg, 1, &data); - if (err) { - dev_err(tps65910->dev, "read from reg %x failed\n", reg); - goto out; - } - - data &= ~mask; - err = tps65910_i2c_write(tps65910, reg, 1, &data); - if (err) - dev_err(tps65910->dev, "write to reg %x failed\n", reg); - -out: - mutex_unlock(&tps65910->io_mutex); - return err; + return regmap_update_bits(tps65910->regmap, reg, mask, 0); } EXPORT_SYMBOL_GPL(tps65910_clear_bits); +void tps65910_enable_reg_cache(struct tps65910 *tps65910, int reg) +{ + set_bit(reg, tps65910->cache_reg); +} +EXPORT_SYMBOL_GPL(tps65910_enable_reg_cache); + +static const struct regmap_config rc5t583_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .volatile_reg = is_volatile_reg, + .max_register = TPS65910_MAX_REGISTER, + .num_reg_defaults_raw = TPS65910_MAX_REGISTER, + .cache_type = REGCACHE_RBTREE, +}; + static int tps65910_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { @@ -161,6 +136,13 @@ static int tps65910_i2c_probe(struct i2c_client *i2c, tps65910->write = tps65910_i2c_write; mutex_init(&tps65910->io_mutex); + tps65910->regmap = regmap_init_i2c(i2c, &rc5t583_regmap_config); + if (IS_ERR(tps65910->regmap)) { + ret = PTR_ERR(tps65910->regmap); + dev_err(&i2c->dev, "regmap initialization failed: %d\n", ret); + goto regmap_err; + } + ret = mfd_add_devices(tps65910->dev, -1, tps65910s, ARRAY_SIZE(tps65910s), NULL, 0); @@ -178,6 +160,9 @@ static int tps65910_i2c_probe(struct i2c_client *i2c, return ret; err: + mfd_remove_devices(tps65910->dev); + regmap_exit(tps65910->regmap); +regmap_err: kfree(tps65910); kfree(init_data); return ret; @@ -189,6 +174,7 @@ static int tps65910_i2c_remove(struct i2c_client *i2c) tps65910_irq_exit(tps65910); mfd_remove_devices(tps65910->dev); + regmap_exit(tps65910->regmap); kfree(tps65910); return 0; diff --git a/include/linux/mfd/tps65910.h b/include/linux/mfd/tps65910.h index 5c76b96..6c68e2e 100644 --- a/include/linux/mfd/tps65910.h +++ b/include/linux/mfd/tps65910.h @@ -805,6 +805,7 @@ struct tps65910_board { struct tps65910 { struct device *dev; struct i2c_client *i2c_client; + struct regmap *regmap; struct mutex io_mutex; unsigned int id; int (*read)(struct tps65910 *tps65910, u8 reg, int size, void *dest); @@ -824,6 +825,7 @@ struct tps65910 { int irq_base; int irq_num; u32 irq_mask; + unsigned long cache_reg[BITS_TO_LONGS(TPS65910_MAX_REGISTER)]; }; struct tps65910_platform_data { @@ -837,6 +839,7 @@ void tps65910_gpio_init(struct tps65910 *tps65910, int gpio_base); int tps65910_irq_init(struct tps65910 *tps65910, int irq, struct tps65910_platform_data *pdata); int tps65910_irq_exit(struct tps65910 *tps65910); +void tps65910_enable_reg_cache(struct tps65910 *tps65910, int reg); static inline int tps65910_chip_id(struct tps65910 *tps65910) { -- 1.7.1.1 -- To unsubscribe from this list: send the line "unsubscribe linux-tegra" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html