Skip to content

Commit 26b0477

Browse files
Srinivas Neelibrgl
authored andcommitted
gpio: gpio-xilinx: Add support for suspend and resume
Add support for suspend and resume, pm runtime suspend and resume. Added free and request calls. Signed-off-by: Srinivas Neeli <[email protected]> Reviewed-by: Linus Walleij <[email protected]> Signed-off-by: Bartosz Golaszewski <[email protected]>
1 parent a32c7ca commit 26b0477

File tree

1 file changed

+89
-3
lines changed

1 file changed

+89
-3
lines changed

drivers/gpio/gpio-xilinx.c

Lines changed: 89 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include <linux/module.h>
1717
#include <linux/of_device.h>
1818
#include <linux/of_platform.h>
19+
#include <linux/pm_runtime.h>
1920
#include <linux/slab.h>
2021

2122
/* Register Offset Definitions */
@@ -278,6 +279,39 @@ static void xgpio_save_regs(struct xgpio_instance *chip)
278279
chip->gpio_dir[1]);
279280
}
280281

282+
static int xgpio_request(struct gpio_chip *chip, unsigned int offset)
283+
{
284+
int ret;
285+
286+
ret = pm_runtime_get_sync(chip->parent);
287+
/*
288+
* If the device is already active pm_runtime_get() will return 1 on
289+
* success, but gpio_request still needs to return 0.
290+
*/
291+
return ret < 0 ? ret : 0;
292+
}
293+
294+
static void xgpio_free(struct gpio_chip *chip, unsigned int offset)
295+
{
296+
pm_runtime_put(chip->parent);
297+
}
298+
299+
static int __maybe_unused xgpio_suspend(struct device *dev)
300+
{
301+
struct xgpio_instance *gpio = dev_get_drvdata(dev);
302+
struct irq_data *data = irq_get_irq_data(gpio->irq);
303+
304+
if (!data) {
305+
dev_err(dev, "irq_get_irq_data() failed\n");
306+
return -EINVAL;
307+
}
308+
309+
if (!irqd_is_wakeup_set(data))
310+
return pm_runtime_force_suspend(dev);
311+
312+
return 0;
313+
}
314+
281315
/**
282316
* xgpio_remove - Remove method for the GPIO device.
283317
* @pdev: pointer to the platform device
@@ -290,6 +324,9 @@ static int xgpio_remove(struct platform_device *pdev)
290324
{
291325
struct xgpio_instance *gpio = platform_get_drvdata(pdev);
292326

327+
pm_runtime_get_sync(&pdev->dev);
328+
pm_runtime_put_noidle(&pdev->dev);
329+
pm_runtime_disable(&pdev->dev);
293330
clk_disable_unprepare(gpio->clk);
294331

295332
return 0;
@@ -305,6 +342,46 @@ static void xgpio_irq_ack(struct irq_data *irq_data)
305342
{
306343
}
307344

345+
static int __maybe_unused xgpio_resume(struct device *dev)
346+
{
347+
struct xgpio_instance *gpio = dev_get_drvdata(dev);
348+
struct irq_data *data = irq_get_irq_data(gpio->irq);
349+
350+
if (!data) {
351+
dev_err(dev, "irq_get_irq_data() failed\n");
352+
return -EINVAL;
353+
}
354+
355+
if (!irqd_is_wakeup_set(data))
356+
return pm_runtime_force_resume(dev);
357+
358+
return 0;
359+
}
360+
361+
static int __maybe_unused xgpio_runtime_suspend(struct device *dev)
362+
{
363+
struct platform_device *pdev = to_platform_device(dev);
364+
struct xgpio_instance *gpio = platform_get_drvdata(pdev);
365+
366+
clk_disable(gpio->clk);
367+
368+
return 0;
369+
}
370+
371+
static int __maybe_unused xgpio_runtime_resume(struct device *dev)
372+
{
373+
struct platform_device *pdev = to_platform_device(dev);
374+
struct xgpio_instance *gpio = platform_get_drvdata(pdev);
375+
376+
return clk_enable(gpio->clk);
377+
}
378+
379+
static const struct dev_pm_ops xgpio_dev_pm_ops = {
380+
SET_SYSTEM_SLEEP_PM_OPS(xgpio_suspend, xgpio_resume)
381+
SET_RUNTIME_PM_OPS(xgpio_runtime_suspend,
382+
xgpio_runtime_resume, NULL)
383+
};
384+
308385
/**
309386
* xgpio_irq_mask - Write the specified signal of the GPIO device.
310387
* @irq_data: per IRQ and chip data passed down to chip functions
@@ -546,6 +623,8 @@ static int xgpio_probe(struct platform_device *pdev)
546623
chip->gc.of_gpio_n_cells = cells;
547624
chip->gc.get = xgpio_get;
548625
chip->gc.set = xgpio_set;
626+
chip->gc.request = xgpio_request;
627+
chip->gc.free = xgpio_free;
549628
chip->gc.set_multiple = xgpio_set_multiple;
550629

551630
chip->gc.label = dev_name(&pdev->dev);
@@ -565,6 +644,9 @@ static int xgpio_probe(struct platform_device *pdev)
565644
dev_err(&pdev->dev, "Failed to prepare clk\n");
566645
return status;
567646
}
647+
pm_runtime_get_noresume(&pdev->dev);
648+
pm_runtime_set_active(&pdev->dev);
649+
pm_runtime_enable(&pdev->dev);
568650

569651
xgpio_save_regs(chip);
570652

@@ -595,7 +677,7 @@ static int xgpio_probe(struct platform_device *pdev)
595677
GFP_KERNEL);
596678
if (!girq->parents) {
597679
status = -ENOMEM;
598-
goto err_unprepare_clk;
680+
goto err_pm_put;
599681
}
600682
girq->parents[0] = chip->irq;
601683
girq->default_type = IRQ_TYPE_NONE;
@@ -605,12 +687,15 @@ static int xgpio_probe(struct platform_device *pdev)
605687
status = devm_gpiochip_add_data(&pdev->dev, &chip->gc, chip);
606688
if (status) {
607689
dev_err(&pdev->dev, "failed to add GPIO chip\n");
608-
goto err_unprepare_clk;
690+
goto err_pm_put;
609691
}
610692

693+
pm_runtime_put(&pdev->dev);
611694
return 0;
612695

613-
err_unprepare_clk:
696+
err_pm_put:
697+
pm_runtime_disable(&pdev->dev);
698+
pm_runtime_put_noidle(&pdev->dev);
614699
clk_disable_unprepare(chip->clk);
615700
return status;
616701
}
@@ -628,6 +713,7 @@ static struct platform_driver xgpio_plat_driver = {
628713
.driver = {
629714
.name = "gpio-xilinx",
630715
.of_match_table = xgpio_of_match,
716+
.pm = &xgpio_dev_pm_ops,
631717
},
632718
};
633719

0 commit comments

Comments
 (0)