gpio: arizona: Add support for GPIOs that need to be maintained
[linux-2.6-microblaze.git] / drivers / gpio / gpio-arizona.c
index cd23fd7..d4e6ba0 100644 (file)
@@ -33,9 +33,23 @@ static int arizona_gpio_direction_in(struct gpio_chip *chip, unsigned offset)
 {
        struct arizona_gpio *arizona_gpio = gpiochip_get_data(chip);
        struct arizona *arizona = arizona_gpio->arizona;
+       bool persistent = gpiochip_line_is_persistent(chip, offset);
+       bool change;
+       int ret;
 
-       return regmap_update_bits(arizona->regmap, ARIZONA_GPIO1_CTRL + offset,
-                                 ARIZONA_GPN_DIR, ARIZONA_GPN_DIR);
+       ret = regmap_update_bits_check(arizona->regmap,
+                                      ARIZONA_GPIO1_CTRL + offset,
+                                      ARIZONA_GPN_DIR, ARIZONA_GPN_DIR,
+                                      &change);
+       if (ret < 0)
+               return ret;
+
+       if (change && persistent) {
+               pm_runtime_mark_last_busy(chip->parent);
+               pm_runtime_put_autosuspend(chip->parent);
+       }
+
+       return 0;
 }
 
 static int arizona_gpio_get(struct gpio_chip *chip, unsigned offset)
@@ -85,6 +99,21 @@ static int arizona_gpio_direction_out(struct gpio_chip *chip,
 {
        struct arizona_gpio *arizona_gpio = gpiochip_get_data(chip);
        struct arizona *arizona = arizona_gpio->arizona;
+       bool persistent = gpiochip_line_is_persistent(chip, offset);
+       unsigned int val;
+       int ret;
+
+       ret = regmap_read(arizona->regmap, ARIZONA_GPIO1_CTRL + offset, &val);
+       if (ret < 0)
+               return ret;
+
+       if ((val & ARIZONA_GPN_DIR) && persistent) {
+               ret = pm_runtime_get_sync(chip->parent);
+               if (ret < 0) {
+                       dev_err(chip->parent, "Failed to resume: %d\n", ret);
+                       return ret;
+               }
+       }
 
        if (value)
                value = ARIZONA_GPN_LVL;
@@ -158,6 +187,8 @@ static int arizona_gpio_probe(struct platform_device *pdev)
        else
                arizona_gpio->gpio_chip.base = -1;
 
+       pm_runtime_enable(&pdev->dev);
+
        ret = devm_gpiochip_add_data(&pdev->dev, &arizona_gpio->gpio_chip,
                                     arizona_gpio);
        if (ret < 0) {