Re: [PATCH] langwell_gpio: add runtime pm support
From: Grant Likely
Date: Thu May 26 2011 - 16:24:59 EST
On Tue, May 10, 2011 at 02:23:45PM +0100, Alan Cox wrote:
> From: Kristen Carlson Accardi <kristen@xxxxxxxxxxxxxxx>
>
> While this is essentially a no-op for this driver, it has the
> side effect of letting the PMU driver snoop D3 requests from
> the PCI core for this driver.
>
> This is only for langwell, not for whitney point.
>
> Signed-off-by: Kristen Carlson Accardi <kristen@xxxxxxxxxxxxxxx>
> Signed-off-by: Alan Cox <alan@xxxxxxxxxxxxxxx>
> Signed-off-by: Dirk Brandewie <dirk.brandewie@xxxxxxxxx>
>
> [This went me->Dirk->me->upstream before the signed off confuses]
Applied, thanks
g.
> ---
>
> drivers/gpio/langwell_gpio.c | 65 ++++++++++++++++++++++++++++++++++++++++++
> 1 files changed, 65 insertions(+), 0 deletions(-)
>
> diff --git a/drivers/gpio/langwell_gpio.c b/drivers/gpio/langwell_gpio.c
> index 560ab64..6f88e37 100644
> --- a/drivers/gpio/langwell_gpio.c
> +++ b/drivers/gpio/langwell_gpio.c
> @@ -33,6 +33,7 @@
> #include <linux/io.h>
> #include <linux/gpio.h>
> #include <linux/slab.h>
> +#include <linux/pm_runtime.h>
>
> /*
> * Langwell chip has 64 pins and thus there are 2 32bit registers to control
> @@ -63,6 +64,7 @@ struct lnw_gpio {
> void *reg_base;
> spinlock_t lock;
> unsigned irq_base;
> + struct pci_dev *pdev;
> };
>
> static void __iomem *gpio_reg(struct gpio_chip *chip, unsigned offset,
> @@ -104,11 +106,18 @@ static int lnw_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
> u32 value;
> unsigned long flags;
>
> + if (lnw->pdev)
> + pm_runtime_get(&lnw->pdev->dev);
> +
> spin_lock_irqsave(&lnw->lock, flags);
> value = readl(gpdr);
> value &= ~BIT(offset % 32);
> writel(value, gpdr);
> spin_unlock_irqrestore(&lnw->lock, flags);
> +
> + if (lnw->pdev)
> + pm_runtime_put(&lnw->pdev->dev);
> +
> return 0;
> }
>
> @@ -120,11 +129,19 @@ static int lnw_gpio_direction_output(struct gpio_chip *chip,
> unsigned long flags;
>
> lnw_gpio_set(chip, offset, value);
> +
> + if (lnw->pdev)
> + pm_runtime_get(&lnw->pdev->dev);
> +
> spin_lock_irqsave(&lnw->lock, flags);
> value = readl(gpdr);
> value |= BIT(offset % 32);;
> writel(value, gpdr);
> spin_unlock_irqrestore(&lnw->lock, flags);
> +
> + if (lnw->pdev)
> + pm_runtime_put(&lnw->pdev->dev);
> +
> return 0;
> }
>
> @@ -145,6 +162,10 @@ static int lnw_irq_type(struct irq_data *d, unsigned type)
>
> if (gpio >= lnw->chip.ngpio)
> return -EINVAL;
> +
> + if (lnw->pdev)
> + pm_runtime_get(&lnw->pdev->dev);
> +
> spin_lock_irqsave(&lnw->lock, flags);
> if (type & IRQ_TYPE_EDGE_RISING)
> value = readl(grer) | BIT(gpio % 32);
> @@ -159,6 +180,9 @@ static int lnw_irq_type(struct irq_data *d, unsigned type)
> writel(value, gfer);
> spin_unlock_irqrestore(&lnw->lock, flags);
>
> + if (lnw->pdev)
> + pm_runtime_put(&lnw->pdev->dev);
> +
> return 0;
> }
>
> @@ -211,6 +235,39 @@ static void lnw_irq_handler(unsigned irq, struct irq_desc *desc)
> chip->irq_eoi(data);
> }
>
> +#ifdef CONFIG_PM
> +static int lnw_gpio_runtime_resume(struct device *dev)
> +{
> + return 0;
> +}
> +
> +static int lnw_gpio_runtime_suspend(struct device *dev)
> +{
> + return 0;
> +}
> +
> +static int lnw_gpio_runtime_idle(struct device *dev)
> +{
> + int err = pm_schedule_suspend(dev, 500);
> +
> + if (!err)
> + return 0;
> +
> + return -EBUSY;
> +}
> +
> +#else
> +#define lnw_gpio_runtime_suspend NULL
> +#define lnw_gpio_runtime_resume NULL
> +#define lnw_gpio_runtime_idle NULL
> +#endif
> +
> +static const struct dev_pm_ops lnw_gpio_pm_ops = {
> + .runtime_suspend = lnw_gpio_runtime_suspend,
> + .runtime_resume = lnw_gpio_runtime_resume,
> + .runtime_idle = lnw_gpio_runtime_idle,
> +};
> +
> static int __devinit lnw_gpio_probe(struct pci_dev *pdev,
> const struct pci_device_id *id)
> {
> @@ -270,6 +327,7 @@ static int __devinit lnw_gpio_probe(struct pci_dev *pdev,
> lnw->chip.base = gpio_base;
> lnw->chip.ngpio = id->driver_data;
> lnw->chip.can_sleep = 0;
> + lnw->pdev = pdev;
> pci_set_drvdata(pdev, lnw);
> retval = gpiochip_add(&lnw->chip);
> if (retval) {
> @@ -285,6 +343,10 @@ static int __devinit lnw_gpio_probe(struct pci_dev *pdev,
> }
>
> spin_lock_init(&lnw->lock);
> +
> + pm_runtime_put_noidle(&pdev->dev);
> + pm_runtime_allow(&pdev->dev);
> +
> goto done;
> err5:
> kfree(lnw);
> @@ -302,6 +364,9 @@ static struct pci_driver lnw_gpio_driver = {
> .name = "langwell_gpio",
> .id_table = lnw_gpio_ids,
> .probe = lnw_gpio_probe,
> + .driver = {
> + .pm = &lnw_gpio_pm_ops,
> + },
> };
>
>
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@xxxxxxxxxxxxxxx
> More majordomo info at http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at http://www.tux.org/lkml/
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/