TTY: move allocations to tty_alloc_driver
[deliverable/linux.git] / drivers / mfd / tps6586x.c
index c84b5506d5fbd06ee82d12b476abc6239ae4508f..353c34812120fc46e37140c0b6a04babdd5cb080 100644 (file)
 #include <linux/module.h>
 #include <linux/mutex.h>
 #include <linux/slab.h>
-#include <linux/gpio.h>
+#include <linux/err.h>
 #include <linux/i2c.h>
+#include <linux/regmap.h>
 #include <linux/regulator/of_regulator.h>
 
 #include <linux/mfd/core.h>
 #include <linux/mfd/tps6586x.h>
 
-/* GPIO control registers */
-#define TPS6586X_GPIOSET1      0x5d
-#define TPS6586X_GPIOSET2      0x5e
-
 /* interrupt control registers */
 #define TPS6586X_INT_ACK1      0xb5
 #define TPS6586X_INT_ACK2      0xb6
@@ -48,6 +45,9 @@
 /* device id */
 #define TPS6586X_VERSIONCRC    0xcd
 
+/* Maximum register */
+#define TPS6586X_MAX_REGISTER  (TPS6586X_VERSIONCRC + 1)
+
 struct tps6586x_irq_data {
        u8      mask_reg;
        u8      mask_mask;
@@ -89,226 +89,96 @@ static const struct tps6586x_irq_data tps6586x_irqs[] = {
        [TPS6586X_INT_RTC_ALM2] = TPS6586X_IRQ(TPS6586X_INT_MASK4, 1 << 1),
 };
 
+static struct mfd_cell tps6586x_cell[] = {
+       {
+               .name = "tps6586x-gpio",
+       },
+       {
+               .name = "tps6586x-rtc",
+       },
+       {
+               .name = "tps6586x-onkey",
+       },
+};
+
 struct tps6586x {
-       struct mutex            lock;
        struct device           *dev;
        struct i2c_client       *client;
+       struct regmap           *regmap;
 
-       struct gpio_chip        gpio;
        struct irq_chip         irq_chip;
        struct mutex            irq_lock;
        int                     irq_base;
        u32                     irq_en;
-       u8                      mask_cache[5];
        u8                      mask_reg[5];
 };
 
-static inline int __tps6586x_read(struct i2c_client *client,
-                                 int reg, uint8_t *val)
-{
-       int ret;
-
-       ret = i2c_smbus_read_byte_data(client, reg);
-       if (ret < 0) {
-               dev_err(&client->dev, "failed reading at 0x%02x\n", reg);
-               return ret;
-       }
-
-       *val = (uint8_t)ret;
-
-       return 0;
-}
-
-static inline int __tps6586x_reads(struct i2c_client *client, int reg,
-                                  int len, uint8_t *val)
-{
-       int ret;
-
-       ret = i2c_smbus_read_i2c_block_data(client, reg, len, val);
-       if (ret < 0) {
-               dev_err(&client->dev, "failed reading from 0x%02x\n", reg);
-               return ret;
-       }
-
-       return 0;
-}
-
-static inline int __tps6586x_write(struct i2c_client *client,
-                                int reg, uint8_t val)
+static inline struct tps6586x *dev_to_tps6586x(struct device *dev)
 {
-       int ret;
-
-       ret = i2c_smbus_write_byte_data(client, reg, val);
-       if (ret < 0) {
-               dev_err(&client->dev, "failed writing 0x%02x to 0x%02x\n",
-                               val, reg);
-               return ret;
-       }
-
-       return 0;
-}
-
-static inline int __tps6586x_writes(struct i2c_client *client, int reg,
-                                 int len, uint8_t *val)
-{
-       int ret, i;
-
-       for (i = 0; i < len; i++) {
-               ret = __tps6586x_write(client, reg + i, *(val + i));
-               if (ret < 0)
-                       return ret;
-       }
-
-       return 0;
+       return i2c_get_clientdata(to_i2c_client(dev));
 }
 
 int tps6586x_write(struct device *dev, int reg, uint8_t val)
 {
-       return __tps6586x_write(to_i2c_client(dev), reg, val);
+       struct tps6586x *tps6586x = dev_to_tps6586x(dev);
+
+       return regmap_write(tps6586x->regmap, reg, val);
 }
 EXPORT_SYMBOL_GPL(tps6586x_write);
 
 int tps6586x_writes(struct device *dev, int reg, int len, uint8_t *val)
 {
-       return __tps6586x_writes(to_i2c_client(dev), reg, len, val);
+       struct tps6586x *tps6586x = dev_to_tps6586x(dev);
+
+       return regmap_bulk_write(tps6586x->regmap, reg, val, len);
 }
 EXPORT_SYMBOL_GPL(tps6586x_writes);
 
 int tps6586x_read(struct device *dev, int reg, uint8_t *val)
 {
-       return __tps6586x_read(to_i2c_client(dev), reg, val);
+       struct tps6586x *tps6586x = dev_to_tps6586x(dev);
+       unsigned int rval;
+       int ret;
+
+       ret = regmap_read(tps6586x->regmap, reg, &rval);
+       if (!ret)
+               *val = rval;
+       return ret;
 }
 EXPORT_SYMBOL_GPL(tps6586x_read);
 
 int tps6586x_reads(struct device *dev, int reg, int len, uint8_t *val)
 {
-       return __tps6586x_reads(to_i2c_client(dev), reg, len, val);
+       struct tps6586x *tps6586x = dev_to_tps6586x(dev);
+
+       return regmap_bulk_read(tps6586x->regmap, reg, val, len);
 }
 EXPORT_SYMBOL_GPL(tps6586x_reads);
 
 int tps6586x_set_bits(struct device *dev, int reg, uint8_t bit_mask)
 {
-       struct tps6586x *tps6586x = dev_get_drvdata(dev);
-       uint8_t reg_val;
-       int ret = 0;
-
-       mutex_lock(&tps6586x->lock);
+       struct tps6586x *tps6586x = dev_to_tps6586x(dev);
 
-       ret = __tps6586x_read(to_i2c_client(dev), reg, &reg_val);
-       if (ret)
-               goto out;
-
-       if ((reg_val & bit_mask) != bit_mask) {
-               reg_val |= bit_mask;
-               ret = __tps6586x_write(to_i2c_client(dev), reg, reg_val);
-       }
-out:
-       mutex_unlock(&tps6586x->lock);
-       return ret;
+       return regmap_update_bits(tps6586x->regmap, reg, bit_mask, bit_mask);
 }
 EXPORT_SYMBOL_GPL(tps6586x_set_bits);
 
 int tps6586x_clr_bits(struct device *dev, int reg, uint8_t bit_mask)
 {
-       struct tps6586x *tps6586x = dev_get_drvdata(dev);
-       uint8_t reg_val;
-       int ret = 0;
-
-       mutex_lock(&tps6586x->lock);
+       struct tps6586x *tps6586x = dev_to_tps6586x(dev);
 
-       ret = __tps6586x_read(to_i2c_client(dev), reg, &reg_val);
-       if (ret)
-               goto out;
-
-       if (reg_val & bit_mask) {
-               reg_val &= ~bit_mask;
-               ret = __tps6586x_write(to_i2c_client(dev), reg, reg_val);
-       }
-out:
-       mutex_unlock(&tps6586x->lock);
-       return ret;
+       return regmap_update_bits(tps6586x->regmap, reg, bit_mask, 0);
 }
 EXPORT_SYMBOL_GPL(tps6586x_clr_bits);
 
 int tps6586x_update(struct device *dev, int reg, uint8_t val, uint8_t mask)
 {
-       struct tps6586x *tps6586x = dev_get_drvdata(dev);
-       uint8_t reg_val;
-       int ret = 0;
-
-       mutex_lock(&tps6586x->lock);
+       struct tps6586x *tps6586x = dev_to_tps6586x(dev);
 
-       ret = __tps6586x_read(tps6586x->client, reg, &reg_val);
-       if (ret)
-               goto out;
-
-       if ((reg_val & mask) != val) {
-               reg_val = (reg_val & ~mask) | val;
-               ret = __tps6586x_write(tps6586x->client, reg, reg_val);
-       }
-out:
-       mutex_unlock(&tps6586x->lock);
-       return ret;
+       return regmap_update_bits(tps6586x->regmap, reg, mask, val);
 }
 EXPORT_SYMBOL_GPL(tps6586x_update);
 
-static int tps6586x_gpio_get(struct gpio_chip *gc, unsigned offset)
-{
-       struct tps6586x *tps6586x = container_of(gc, struct tps6586x, gpio);
-       uint8_t val;
-       int ret;
-
-       ret = __tps6586x_read(tps6586x->client, TPS6586X_GPIOSET2, &val);
-       if (ret)
-               return ret;
-
-       return !!(val & (1 << offset));
-}
-
-
-static void tps6586x_gpio_set(struct gpio_chip *chip, unsigned offset,
-                             int value)
-{
-       struct tps6586x *tps6586x = container_of(chip, struct tps6586x, gpio);
-
-       tps6586x_update(tps6586x->dev, TPS6586X_GPIOSET2,
-                       value << offset, 1 << offset);
-}
-
-static int tps6586x_gpio_output(struct gpio_chip *gc, unsigned offset,
-                               int value)
-{
-       struct tps6586x *tps6586x = container_of(gc, struct tps6586x, gpio);
-       uint8_t val, mask;
-
-       tps6586x_gpio_set(gc, offset, value);
-
-       val = 0x1 << (offset * 2);
-       mask = 0x3 << (offset * 2);
-
-       return tps6586x_update(tps6586x->dev, TPS6586X_GPIOSET1, val, mask);
-}
-
-static int tps6586x_gpio_init(struct tps6586x *tps6586x, int gpio_base)
-{
-       if (!gpio_base)
-               return 0;
-
-       tps6586x->gpio.owner            = THIS_MODULE;
-       tps6586x->gpio.label            = tps6586x->client->name;
-       tps6586x->gpio.dev              = tps6586x->dev;
-       tps6586x->gpio.base             = gpio_base;
-       tps6586x->gpio.ngpio            = 4;
-       tps6586x->gpio.can_sleep        = 1;
-
-       /* FIXME: add handling of GPIOs as dedicated inputs */
-       tps6586x->gpio.direction_output = tps6586x_gpio_output;
-       tps6586x->gpio.set              = tps6586x_gpio_set;
-       tps6586x->gpio.get              = tps6586x_gpio_get;
-
-       return gpiochip_add(&tps6586x->gpio);
-}
-
 static int __remove_subdev(struct device *dev, void *unused)
 {
        platform_device_unregister(to_platform_device(dev));
@@ -354,12 +224,11 @@ static void tps6586x_irq_sync_unlock(struct irq_data *data)
        int i;
 
        for (i = 0; i < ARRAY_SIZE(tps6586x->mask_reg); i++) {
-               if (tps6586x->mask_reg[i] != tps6586x->mask_cache[i]) {
-                       if (!WARN_ON(tps6586x_write(tps6586x->dev,
-                                                   TPS6586X_INT_MASK1 + i,
-                                                   tps6586x->mask_reg[i])))
-                               tps6586x->mask_cache[i] = tps6586x->mask_reg[i];
-               }
+               int ret;
+               ret = tps6586x_write(tps6586x->dev,
+                                           TPS6586X_INT_MASK1 + i,
+                                           tps6586x->mask_reg[i]);
+               WARN_ON(ret);
        }
 
        mutex_unlock(&tps6586x->irq_lock);
@@ -406,7 +275,6 @@ static int __devinit tps6586x_irq_init(struct tps6586x *tps6586x, int irq,
 
        mutex_init(&tps6586x->irq_lock);
        for (i = 0; i < 5; i++) {
-               tps6586x->mask_cache[i] = 0xff;
                tps6586x->mask_reg[i] = 0xff;
                tps6586x_write(tps6586x->dev, TPS6586X_INT_MASK1 + i, 0xff);
        }
@@ -556,6 +424,23 @@ static struct tps6586x_platform_data *tps6586x_parse_dt(struct i2c_client *clien
 }
 #endif
 
+static bool is_volatile_reg(struct device *dev, unsigned int reg)
+{
+       /* Cache all interrupt mask register */
+       if ((reg >= TPS6586X_INT_MASK1) && (reg <= TPS6586X_INT_MASK5))
+               return false;
+
+       return true;
+}
+
+static const struct regmap_config tps6586x_regmap_config = {
+       .reg_bits = 8,
+       .val_bits = 8,
+       .max_register = TPS6586X_MAX_REGISTER - 1,
+       .volatile_reg = is_volatile_reg,
+       .cache_type = REGCACHE_RBTREE,
+};
+
 static int __devinit tps6586x_i2c_probe(struct i2c_client *client,
                                        const struct i2c_device_id *id)
 {
@@ -579,29 +464,39 @@ static int __devinit tps6586x_i2c_probe(struct i2c_client *client,
 
        dev_info(&client->dev, "VERSIONCRC is %02x\n", ret);
 
-       tps6586x = kzalloc(sizeof(struct tps6586x), GFP_KERNEL);
-       if (tps6586x == NULL)
+       tps6586x = devm_kzalloc(&client->dev, sizeof(*tps6586x), GFP_KERNEL);
+       if (tps6586x == NULL) {
+               dev_err(&client->dev, "memory for tps6586x alloc failed\n");
                return -ENOMEM;
+       }
 
        tps6586x->client = client;
        tps6586x->dev = &client->dev;
        i2c_set_clientdata(client, tps6586x);
 
-       mutex_init(&tps6586x->lock);
+       tps6586x->regmap = devm_regmap_init_i2c(client,
+                                       &tps6586x_regmap_config);
+       if (IS_ERR(tps6586x->regmap)) {
+               ret = PTR_ERR(tps6586x->regmap);
+               dev_err(&client->dev, "regmap init failed: %d\n", ret);
+               return ret;
+       }
+
 
        if (client->irq) {
                ret = tps6586x_irq_init(tps6586x, client->irq,
                                        pdata->irq_base);
                if (ret) {
                        dev_err(&client->dev, "IRQ init failed: %d\n", ret);
-                       goto err_irq_init;
+                       return ret;
                }
        }
 
-       ret = tps6586x_gpio_init(tps6586x, pdata->gpio_base);
-       if (ret) {
-               dev_err(&client->dev, "GPIO registration failed: %d\n", ret);
-               goto err_gpio_init;
+       ret = mfd_add_devices(tps6586x->dev, -1,
+                       tps6586x_cell, ARRAY_SIZE(tps6586x_cell), NULL, 0);
+       if (ret < 0) {
+               dev_err(&client->dev, "mfd_add_devices failed: %d\n", ret);
+               goto err_mfd_add;
        }
 
        ret = tps6586x_add_subdevs(tps6586x, pdata);
@@ -613,38 +508,21 @@ static int __devinit tps6586x_i2c_probe(struct i2c_client *client,
        return 0;
 
 err_add_devs:
-       if (pdata->gpio_base) {
-               ret = gpiochip_remove(&tps6586x->gpio);
-               if (ret)
-                       dev_err(&client->dev, "Can't remove gpio chip: %d\n",
-                               ret);
-       }
-err_gpio_init:
+       mfd_remove_devices(tps6586x->dev);
+err_mfd_add:
        if (client->irq)
                free_irq(client->irq, tps6586x);
-err_irq_init:
-       kfree(tps6586x);
        return ret;
 }
 
 static int __devexit tps6586x_i2c_remove(struct i2c_client *client)
 {
        struct tps6586x *tps6586x = i2c_get_clientdata(client);
-       struct tps6586x_platform_data *pdata = client->dev.platform_data;
-       int ret;
 
+       tps6586x_remove_subdevs(tps6586x);
+       mfd_remove_devices(tps6586x->dev);
        if (client->irq)
                free_irq(client->irq, tps6586x);
-
-       if (pdata->gpio_base) {
-               ret = gpiochip_remove(&tps6586x->gpio);
-               if (ret)
-                       dev_err(&client->dev, "Can't remove gpio chip: %d\n",
-                               ret);
-       }
-
-       tps6586x_remove_subdevs(tps6586x);
-       kfree(tps6586x);
        return 0;
 }
 
This page took 0.031136 seconds and 5 git commands to generate.