From 0cd57553d631bbd3c0c5ddd6e331e644ef0f55c3 Mon Sep 17 00:00:00 2001 From: Deepak Sikri Date: Fri, 18 Nov 2011 15:20:12 +0530 Subject: [PATCH] --- yaml --- r: 284797 b: refs/heads/master c: e198a8de14d4bb122b821432fadb28eedd4b4507 h: refs/heads/master i: 284795: ee9914a77fde135c1d6a67048c217476a2092427 v: v3 --- [refs] | 2 +- trunk/drivers/gpio/gpio-pl061.c | 68 +++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+), 1 deletion(-) diff --git a/[refs] b/[refs] index 1df189638ead..43a9c191f872 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: aedd4fdf69293fc5379129294239b09da2a7c3ec +refs/heads/master: e198a8de14d4bb122b821432fadb28eedd4b4507 diff --git a/trunk/drivers/gpio/gpio-pl061.c b/trunk/drivers/gpio/gpio-pl061.c index 093c90bd3c1d..42a5d5672694 100644 --- a/trunk/drivers/gpio/gpio-pl061.c +++ b/trunk/drivers/gpio/gpio-pl061.c @@ -23,6 +23,7 @@ #include #include #include +#include #define GPIODIR 0x400 #define GPIOIS 0x404 @@ -35,6 +36,17 @@ #define PL061_GPIO_NR 8 +#ifdef CONFIG_PM +struct pl061_context_save_regs { + u8 gpio_data; + u8 gpio_dir; + u8 gpio_is; + u8 gpio_ibe; + u8 gpio_iev; + u8 gpio_ie; +}; +#endif + struct pl061_gpio { /* We use a list of pl061_gpio structs for each trigger IRQ in the main * interrupts controller of the system. We need this to support systems @@ -54,6 +66,10 @@ struct pl061_gpio { void __iomem *base; unsigned irq_base; struct gpio_chip gc; + +#ifdef CONFIG_PM + struct pl061_context_save_regs csave_regs; +#endif }; static int pl061_direction_input(struct gpio_chip *gc, unsigned offset) @@ -330,6 +346,8 @@ static int pl061_probe(struct amba_device *dev, const struct amba_id *id) irq_set_chip_data(i + chip->irq_base, chip); } + amba_set_drvdata(dev, chip); + return 0; iounmap: @@ -342,6 +360,53 @@ static int pl061_probe(struct amba_device *dev, const struct amba_id *id) return ret; } +#ifdef CONFIG_PM +static int pl061_suspend(struct device *dev) +{ + struct pl061_gpio *chip = dev_get_drvdata(dev); + int offset; + + chip->csave_regs.gpio_data = 0; + chip->csave_regs.gpio_dir = readb(chip->base + GPIODIR); + chip->csave_regs.gpio_is = readb(chip->base + GPIOIS); + chip->csave_regs.gpio_ibe = readb(chip->base + GPIOIBE); + chip->csave_regs.gpio_iev = readb(chip->base + GPIOIEV); + chip->csave_regs.gpio_ie = readb(chip->base + GPIOIE); + + for (offset = 0; offset < PL061_GPIO_NR; offset++) { + if (chip->csave_regs.gpio_dir & (1 << offset)) + chip->csave_regs.gpio_data |= + pl061_get_value(&chip->gc, offset) << offset; + } + + return 0; +} + +static int pl061_resume(struct device *dev) +{ + struct pl061_gpio *chip = dev_get_drvdata(dev); + int offset; + + for (offset = 0; offset < PL061_GPIO_NR; offset++) { + if (chip->csave_regs.gpio_dir & (1 << offset)) + pl061_direction_output(&chip->gc, offset, + chip->csave_regs.gpio_data & + (1 << offset)); + else + pl061_direction_input(&chip->gc, offset); + } + + writeb(chip->csave_regs.gpio_is, chip->base + GPIOIS); + writeb(chip->csave_regs.gpio_ibe, chip->base + GPIOIBE); + writeb(chip->csave_regs.gpio_iev, chip->base + GPIOIEV); + writeb(chip->csave_regs.gpio_ie, chip->base + GPIOIE); + + return 0; +} + +static SIMPLE_DEV_PM_OPS(pl061_dev_pm_ops, pl061_suspend, pl061_resume); +#endif + static struct amba_id pl061_ids[] = { { .id = 0x00041061, @@ -353,6 +418,9 @@ static struct amba_id pl061_ids[] = { static struct amba_driver pl061_gpio_driver = { .drv = { .name = "pl061_gpio", +#ifdef CONFIG_PM + .pm = &pl061_dev_pm_ops, +#endif }, .id_table = pl061_ids, .probe = pl061_probe,