3.0: remove mfd_data
[linux-2.6.git] / drivers / mfd / tps6586x.c
index 627cf57..6d842fa 100644 (file)
 #include <linux/mfd/core.h>
 #include <linux/mfd/tps6586x.h>
 
+#define TPS6586X_SUPPLYENE  0x14
+#define EXITSLREQ_BIT       BIT(1) /* Exit sleep mode request */
+#define SLEEP_MODE_BIT      BIT(3) /* Sleep mode */
+
 /* GPIO control registers */
 #define TPS6586X_GPIOSET1      0x5d
 #define TPS6586X_GPIOSET2      0x5e
@@ -150,12 +154,12 @@ static inline int __tps6586x_write(struct i2c_client *client,
 static inline int __tps6586x_writes(struct i2c_client *client, int reg,
                                  int len, uint8_t *val)
 {
-       int ret;
+       int ret, i;
 
-       ret = i2c_smbus_write_i2c_block_data(client, reg, len, val);
-       if (ret < 0) {
-               dev_err(&client->dev, "failed writings to 0x%02x\n", reg);
-               return ret;
+       for (i = 0; i < len; i++) {
+               ret = __tps6586x_write(client, reg + i, *(val + i));
+               if (ret < 0)
+                       return ret;
        }
 
        return 0;
@@ -251,6 +255,28 @@ out:
 }
 EXPORT_SYMBOL_GPL(tps6586x_update);
 
+static struct i2c_client *tps6586x_i2c_client = NULL;
+int tps6586x_power_off(void)
+{
+       struct device *dev = NULL;
+       int ret = -EINVAL;
+
+       if (!tps6586x_i2c_client)
+               return ret;
+
+       dev = &tps6586x_i2c_client->dev;
+
+       ret = tps6586x_clr_bits(dev, TPS6586X_SUPPLYENE, EXITSLREQ_BIT);
+       if (ret)
+               return ret;
+
+       ret = tps6586x_set_bits(dev, TPS6586X_SUPPLYENE, SLEEP_MODE_BIT);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
 static int tps6586x_gpio_get(struct gpio_chip *gc, unsigned offset)
 {
        struct tps6586x *tps6586x = container_of(gc, struct tps6586x, gpio);
@@ -270,8 +296,14 @@ static void tps6586x_gpio_set(struct gpio_chip *chip, unsigned offset,
 {
        struct tps6586x *tps6586x = container_of(chip, struct tps6586x, gpio);
 
-       __tps6586x_write(tps6586x->client, TPS6586X_GPIOSET2,
-                        value << offset);
+       tps6586x_update(tps6586x->dev, TPS6586X_GPIOSET2,
+                       value << offset, 1 << offset);
+}
+
+static int tps6586x_gpio_input(struct gpio_chip *gc, unsigned offset)
+{
+       /* FIXME: add handling of GPIOs as dedicated inputs */
+       return -ENOSYS;
 }
 
 static int tps6586x_gpio_output(struct gpio_chip *gc, unsigned offset,
@@ -279,8 +311,13 @@ static int tps6586x_gpio_output(struct gpio_chip *gc, unsigned offset,
 {
        struct tps6586x *tps6586x = container_of(gc, struct tps6586x, gpio);
        uint8_t val, mask;
+       int ret;
 
-       tps6586x_gpio_set(gc, offset, value);
+       val = value << offset;
+       mask = 0x1 << offset;
+       ret = tps6586x_update(tps6586x->dev, TPS6586X_GPIOSET2, val, mask);
+       if (ret)
+               return ret;
 
        val = 0x1 << (offset * 2);
        mask = 0x3 << (offset * 2);
@@ -288,12 +325,10 @@ static int tps6586x_gpio_output(struct gpio_chip *gc, unsigned offset,
        return tps6586x_update(tps6586x->dev, TPS6586X_GPIOSET1, val, mask);
 }
 
-static void tps6586x_gpio_init(struct tps6586x *tps6586x, int gpio_base)
+static int tps6586x_gpio_init(struct tps6586x *tps6586x, int gpio_base)
 {
-       int ret;
-
        if (!gpio_base)
-               return;
+               return 0;
 
        tps6586x->gpio.owner            = THIS_MODULE;
        tps6586x->gpio.label            = tps6586x->client->name;
@@ -302,14 +337,12 @@ static void tps6586x_gpio_init(struct tps6586x *tps6586x, int gpio_base)
        tps6586x->gpio.ngpio            = 4;
        tps6586x->gpio.can_sleep        = 1;
 
-       /* FIXME: add handling of GPIOs as dedicated inputs */
+       tps6586x->gpio.direction_input  = tps6586x_gpio_input;
        tps6586x->gpio.direction_output = tps6586x_gpio_output;
        tps6586x->gpio.set              = tps6586x_gpio_set;
        tps6586x->gpio.get              = tps6586x_gpio_get;
 
-       ret = gpiochip_add(&tps6586x->gpio);
-       if (ret)
-               dev_warn(tps6586x->dev, "GPIO registration failed: %d\n", ret);
+       return gpiochip_add(&tps6586x->gpio);
 }
 
 static int __remove_subdev(struct device *dev, void *unused)
@@ -426,10 +459,10 @@ static int __devinit tps6586x_irq_init(struct tps6586x *tps6586x, int irq,
 
        for (i = 0; i < ARRAY_SIZE(tps6586x_irqs); i++) {
                int __irq = i + tps6586x->irq_base;
-               set_irq_chip_data(__irq, tps6586x);
-               set_irq_chip_and_handler(__irq, &tps6586x->irq_chip,
+               irq_set_chip_data(__irq, tps6586x);
+               irq_set_chip_and_handler(__irq, &tps6586x->irq_chip,
                                         handle_simple_irq);
-               set_irq_nested_thread(__irq, 1);
+               irq_set_nested_thread(__irq, 1);
 #ifdef CONFIG_ARM
                set_irq_flags(__irq, IRQF_VALID);
 #endif
@@ -517,17 +550,30 @@ static int __devinit tps6586x_i2c_probe(struct i2c_client *client,
                }
        }
 
+       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 = tps6586x_add_subdevs(tps6586x, pdata);
        if (ret) {
                dev_err(&client->dev, "add devices failed: %d\n", ret);
                goto err_add_devs;
        }
 
-       tps6586x_gpio_init(tps6586x, pdata->gpio_base);
+       tps6586x_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:
        if (client->irq)
                free_irq(client->irq, tps6586x);
 err_irq_init:
@@ -587,4 +633,3 @@ module_exit(tps6586x_exit);
 MODULE_DESCRIPTION("TPS6586X core driver");
 MODULE_AUTHOR("Mike Rapoport <mike@compulab.co.il>");
 MODULE_LICENSE("GPL");
-