diff options
Diffstat (limited to 'drivers/gpio')
-rw-r--r-- | drivers/gpio/gpio-vf610.c | 37 |
1 files changed, 37 insertions, 0 deletions
diff --git a/drivers/gpio/gpio-vf610.c b/drivers/gpio/gpio-vf610.c index 87b950cec6ec..03b5dfa59a12 100644 --- a/drivers/gpio/gpio-vf610.c +++ b/drivers/gpio/gpio-vf610.c @@ -37,6 +37,7 @@ struct vf610_gpio_port { void __iomem *gpio_base; u8 irqc[VF610_GPIO_PER_PORT]; int irq; + u32 state; }; #define GPIO_PDOR 0x00 @@ -220,6 +221,40 @@ static struct irq_chip vf610_gpio_irq_chip = { .irq_set_wake = vf610_gpio_irq_set_wake, }; +static int __maybe_unused vf610_gpio_suspend(struct device *dev) +{ + struct vf610_gpio_port *port = dev_get_drvdata(dev); + + port->state = vf610_gpio_readl(port->gpio_base + GPIO_PDOR); + + /* + * There is no need to store Port state since we maintain the state + * alread in the irqc array + */ + + return 0; +} + +static int __maybe_unused vf610_gpio_resume(struct device *dev) +{ + struct vf610_gpio_port *port = dev_get_drvdata(dev); + int i; + + vf610_gpio_writel(port->state, port->gpio_base + GPIO_PDOR); + + for (i = 0; i < port->gc.ngpio; i++) { + u32 irqc = port->irqc[i] << PORT_PCR_IRQC_OFFSET; + + vf610_gpio_writel(irqc, port->base + PORT_PCR(i)); + } + + return 0; +} + +static const struct dev_pm_ops vf610_gpio_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(vf610_gpio_suspend, vf610_gpio_resume) +}; + static int vf610_gpio_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -277,6 +312,7 @@ static int vf610_gpio_probe(struct platform_device *pdev) } gpiochip_set_chained_irqchip(gc, &vf610_gpio_irq_chip, port->irq, vf610_gpio_irq_handler); + platform_set_drvdata(pdev, port); return 0; } @@ -284,6 +320,7 @@ static int vf610_gpio_probe(struct platform_device *pdev) static struct platform_driver vf610_gpio_driver = { .driver = { .name = "gpio-vf610", + .pm = &vf610_gpio_pm_ops, .of_match_table = vf610_gpio_dt_ids, }, .probe = vf610_gpio_probe, |