|
@@ -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) {
|