aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpio
diff options
context:
space:
mode:
authorKristen Carlson Accardi <kristen@linux.intel.com>2011-05-10 09:23:45 -0400
committerGrant Likely <grant.likely@secretlab.ca>2011-05-26 16:24:36 -0400
commit7812803a3119f7cf375bd04bc019ce2395a7c2fc (patch)
tree3dccc17ad74ae134e17be4d23b1cece5b69d8e5d /drivers/gpio
parent33226ffd0726508da1eeb660170a63100f4456ac (diff)
langwell_gpio: add runtime pm support
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@linux.intel.com> Signed-off-by: Alan Cox <alan@linux.intel.com> Signed-off-by: Dirk Brandewie <dirk.brandewie@gmail.com> Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
Diffstat (limited to 'drivers/gpio')
-rw-r--r--drivers/gpio/langwell_gpio.c65
1 files changed, 65 insertions, 0 deletions
diff --git a/drivers/gpio/langwell_gpio.c b/drivers/gpio/langwell_gpio.c
index 1b06f67e1f69..bd6571e0097a 100644
--- a/drivers/gpio/langwell_gpio.c
+++ b/drivers/gpio/langwell_gpio.c
@@ -33,6 +33,7 @@
33#include <linux/io.h> 33#include <linux/io.h>
34#include <linux/gpio.h> 34#include <linux/gpio.h>
35#include <linux/slab.h> 35#include <linux/slab.h>
36#include <linux/pm_runtime.h>
36 37
37/* 38/*
38 * Langwell chip has 64 pins and thus there are 2 32bit registers to control 39 * Langwell chip has 64 pins and thus there are 2 32bit registers to control
@@ -63,6 +64,7 @@ struct lnw_gpio {
63 void *reg_base; 64 void *reg_base;
64 spinlock_t lock; 65 spinlock_t lock;
65 unsigned irq_base; 66 unsigned irq_base;
67 struct pci_dev *pdev;
66}; 68};
67 69
68static void __iomem *gpio_reg(struct gpio_chip *chip, unsigned offset, 70static 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)
104 u32 value; 106 u32 value;
105 unsigned long flags; 107 unsigned long flags;
106 108
109 if (lnw->pdev)
110 pm_runtime_get(&lnw->pdev->dev);
111
107 spin_lock_irqsave(&lnw->lock, flags); 112 spin_lock_irqsave(&lnw->lock, flags);
108 value = readl(gpdr); 113 value = readl(gpdr);
109 value &= ~BIT(offset % 32); 114 value &= ~BIT(offset % 32);
110 writel(value, gpdr); 115 writel(value, gpdr);
111 spin_unlock_irqrestore(&lnw->lock, flags); 116 spin_unlock_irqrestore(&lnw->lock, flags);
117
118 if (lnw->pdev)
119 pm_runtime_put(&lnw->pdev->dev);
120
112 return 0; 121 return 0;
113} 122}
114 123
@@ -120,11 +129,19 @@ static int lnw_gpio_direction_output(struct gpio_chip *chip,
120 unsigned long flags; 129 unsigned long flags;
121 130
122 lnw_gpio_set(chip, offset, value); 131 lnw_gpio_set(chip, offset, value);
132
133 if (lnw->pdev)
134 pm_runtime_get(&lnw->pdev->dev);
135
123 spin_lock_irqsave(&lnw->lock, flags); 136 spin_lock_irqsave(&lnw->lock, flags);
124 value = readl(gpdr); 137 value = readl(gpdr);
125 value |= BIT(offset % 32); 138 value |= BIT(offset % 32);
126 writel(value, gpdr); 139 writel(value, gpdr);
127 spin_unlock_irqrestore(&lnw->lock, flags); 140 spin_unlock_irqrestore(&lnw->lock, flags);
141
142 if (lnw->pdev)
143 pm_runtime_put(&lnw->pdev->dev);
144
128 return 0; 145 return 0;
129} 146}
130 147
@@ -145,6 +162,10 @@ static int lnw_irq_type(struct irq_data *d, unsigned type)
145 162
146 if (gpio >= lnw->chip.ngpio) 163 if (gpio >= lnw->chip.ngpio)
147 return -EINVAL; 164 return -EINVAL;
165
166 if (lnw->pdev)
167 pm_runtime_get(&lnw->pdev->dev);
168
148 spin_lock_irqsave(&lnw->lock, flags); 169 spin_lock_irqsave(&lnw->lock, flags);
149 if (type & IRQ_TYPE_EDGE_RISING) 170 if (type & IRQ_TYPE_EDGE_RISING)
150 value = readl(grer) | BIT(gpio % 32); 171 value = readl(grer) | BIT(gpio % 32);
@@ -159,6 +180,9 @@ static int lnw_irq_type(struct irq_data *d, unsigned type)
159 writel(value, gfer); 180 writel(value, gfer);
160 spin_unlock_irqrestore(&lnw->lock, flags); 181 spin_unlock_irqrestore(&lnw->lock, flags);
161 182
183 if (lnw->pdev)
184 pm_runtime_put(&lnw->pdev->dev);
185
162 return 0; 186 return 0;
163} 187}
164 188
@@ -211,6 +235,39 @@ static void lnw_irq_handler(unsigned irq, struct irq_desc *desc)
211 chip->irq_eoi(data); 235 chip->irq_eoi(data);
212} 236}
213 237
238#ifdef CONFIG_PM
239static int lnw_gpio_runtime_resume(struct device *dev)
240{
241 return 0;
242}
243
244static int lnw_gpio_runtime_suspend(struct device *dev)
245{
246 return 0;
247}
248
249static int lnw_gpio_runtime_idle(struct device *dev)
250{
251 int err = pm_schedule_suspend(dev, 500);
252
253 if (!err)
254 return 0;
255
256 return -EBUSY;
257}
258
259#else
260#define lnw_gpio_runtime_suspend NULL
261#define lnw_gpio_runtime_resume NULL
262#define lnw_gpio_runtime_idle NULL
263#endif
264
265static const struct dev_pm_ops lnw_gpio_pm_ops = {
266 .runtime_suspend = lnw_gpio_runtime_suspend,
267 .runtime_resume = lnw_gpio_runtime_resume,
268 .runtime_idle = lnw_gpio_runtime_idle,
269};
270
214static int __devinit lnw_gpio_probe(struct pci_dev *pdev, 271static int __devinit lnw_gpio_probe(struct pci_dev *pdev,
215 const struct pci_device_id *id) 272 const struct pci_device_id *id)
216{ 273{
@@ -270,6 +327,7 @@ static int __devinit lnw_gpio_probe(struct pci_dev *pdev,
270 lnw->chip.base = gpio_base; 327 lnw->chip.base = gpio_base;
271 lnw->chip.ngpio = id->driver_data; 328 lnw->chip.ngpio = id->driver_data;
272 lnw->chip.can_sleep = 0; 329 lnw->chip.can_sleep = 0;
330 lnw->pdev = pdev;
273 pci_set_drvdata(pdev, lnw); 331 pci_set_drvdata(pdev, lnw);
274 retval = gpiochip_add(&lnw->chip); 332 retval = gpiochip_add(&lnw->chip);
275 if (retval) { 333 if (retval) {
@@ -285,6 +343,10 @@ static int __devinit lnw_gpio_probe(struct pci_dev *pdev,
285 } 343 }
286 344
287 spin_lock_init(&lnw->lock); 345 spin_lock_init(&lnw->lock);
346
347 pm_runtime_put_noidle(&pdev->dev);
348 pm_runtime_allow(&pdev->dev);
349
288 goto done; 350 goto done;
289err5: 351err5:
290 kfree(lnw); 352 kfree(lnw);
@@ -302,6 +364,9 @@ static struct pci_driver lnw_gpio_driver = {
302 .name = "langwell_gpio", 364 .name = "langwell_gpio",
303 .id_table = lnw_gpio_ids, 365 .id_table = lnw_gpio_ids,
304 .probe = lnw_gpio_probe, 366 .probe = lnw_gpio_probe,
367 .driver = {
368 .pm = &lnw_gpio_pm_ops,
369 },
305}; 370};
306 371
307 372