Commit f5e4e20faa1eee3feaa0394897bbd1aca544e809
Exists in
master
and in
38 other branches
Merge tag 'gpio-for-linus' of git://git.secretlab.ca/git/linux-2.6
2nd round of GPIO changes for v3.3 merge window * tag 'gpio-for-linus' of git://git.secretlab.ca/git/linux-2.6: GPIO: sa1100: implement proper gpiolib gpio_to_irq conversion gpio: pl061: remove combined interrupt gpio: pl061: convert to use generic irq chip GPIO: add bindings for managed devices ARM: realview: convert pl061 no irq to 0 instead of -1 gpio: pl061: convert to use 0 for no irq gpio: pl061: use chained_irq_* functions in irq handler GPIO/pl061: Add suspend resume capability drivers/gpio/gpio-tegra.c: use devm_request_and_ioremap
Showing 14 changed files Side-by-side Diff
- arch/arm/mach-realview/realview_eb.c
- arch/arm/mach-realview/realview_pb1176.c
- arch/arm/mach-realview/realview_pb11mp.c
- arch/arm/mach-realview/realview_pba8.c
- arch/arm/mach-realview/realview_pbx.c
- arch/arm/mach-sa1100/include/mach/gpio.h
- drivers/gpio/Kconfig
- drivers/gpio/Makefile
- drivers/gpio/devres.c
- drivers/gpio/gpio-pl061.c
- drivers/gpio/gpio-sa1100.c
- drivers/gpio/gpio-tegra.c
- include/asm-generic/gpio.h
- include/linux/amba/pl061.h
arch/arm/mach-realview/realview_eb.c
... | ... | @@ -117,17 +117,14 @@ |
117 | 117 | |
118 | 118 | static struct pl061_platform_data gpio0_plat_data = { |
119 | 119 | .gpio_base = 0, |
120 | - .irq_base = -1, | |
121 | 120 | }; |
122 | 121 | |
123 | 122 | static struct pl061_platform_data gpio1_plat_data = { |
124 | 123 | .gpio_base = 8, |
125 | - .irq_base = -1, | |
126 | 124 | }; |
127 | 125 | |
128 | 126 | static struct pl061_platform_data gpio2_plat_data = { |
129 | 127 | .gpio_base = 16, |
130 | - .irq_base = -1, | |
131 | 128 | }; |
132 | 129 | |
133 | 130 | static struct pl022_ssp_controller ssp0_plat_data = { |
arch/arm/mach-realview/realview_pb1176.c
... | ... | @@ -113,17 +113,14 @@ |
113 | 113 | |
114 | 114 | static struct pl061_platform_data gpio0_plat_data = { |
115 | 115 | .gpio_base = 0, |
116 | - .irq_base = -1, | |
117 | 116 | }; |
118 | 117 | |
119 | 118 | static struct pl061_platform_data gpio1_plat_data = { |
120 | 119 | .gpio_base = 8, |
121 | - .irq_base = -1, | |
122 | 120 | }; |
123 | 121 | |
124 | 122 | static struct pl061_platform_data gpio2_plat_data = { |
125 | 123 | .gpio_base = 16, |
126 | - .irq_base = -1, | |
127 | 124 | }; |
128 | 125 | |
129 | 126 | static struct pl022_ssp_controller ssp0_plat_data = { |
arch/arm/mach-realview/realview_pb11mp.c
... | ... | @@ -112,17 +112,14 @@ |
112 | 112 | |
113 | 113 | static struct pl061_platform_data gpio0_plat_data = { |
114 | 114 | .gpio_base = 0, |
115 | - .irq_base = -1, | |
116 | 115 | }; |
117 | 116 | |
118 | 117 | static struct pl061_platform_data gpio1_plat_data = { |
119 | 118 | .gpio_base = 8, |
120 | - .irq_base = -1, | |
121 | 119 | }; |
122 | 120 | |
123 | 121 | static struct pl061_platform_data gpio2_plat_data = { |
124 | 122 | .gpio_base = 16, |
125 | - .irq_base = -1, | |
126 | 123 | }; |
127 | 124 | |
128 | 125 | static struct pl022_ssp_controller ssp0_plat_data = { |
arch/arm/mach-realview/realview_pba8.c
... | ... | @@ -102,17 +102,14 @@ |
102 | 102 | |
103 | 103 | static struct pl061_platform_data gpio0_plat_data = { |
104 | 104 | .gpio_base = 0, |
105 | - .irq_base = -1, | |
106 | 105 | }; |
107 | 106 | |
108 | 107 | static struct pl061_platform_data gpio1_plat_data = { |
109 | 108 | .gpio_base = 8, |
110 | - .irq_base = -1, | |
111 | 109 | }; |
112 | 110 | |
113 | 111 | static struct pl061_platform_data gpio2_plat_data = { |
114 | 112 | .gpio_base = 16, |
115 | - .irq_base = -1, | |
116 | 113 | }; |
117 | 114 | |
118 | 115 | static struct pl022_ssp_controller ssp0_plat_data = { |
arch/arm/mach-realview/realview_pbx.c
... | ... | @@ -124,17 +124,14 @@ |
124 | 124 | |
125 | 125 | static struct pl061_platform_data gpio0_plat_data = { |
126 | 126 | .gpio_base = 0, |
127 | - .irq_base = -1, | |
128 | 127 | }; |
129 | 128 | |
130 | 129 | static struct pl061_platform_data gpio1_plat_data = { |
131 | 130 | .gpio_base = 8, |
132 | - .irq_base = -1, | |
133 | 131 | }; |
134 | 132 | |
135 | 133 | static struct pl061_platform_data gpio2_plat_data = { |
136 | 134 | .gpio_base = 16, |
137 | - .irq_base = -1, | |
138 | 135 | }; |
139 | 136 | |
140 | 137 | static struct pl022_ssp_controller ssp0_plat_data = { |
arch/arm/mach-sa1100/include/mach/gpio.h
drivers/gpio/Kconfig
drivers/gpio/Makefile
drivers/gpio/devres.c
1 | +/* | |
2 | + * drivers/gpio/devres.c - managed gpio resources | |
3 | + * | |
4 | + * This program is free software; you can redistribute it and/or modify | |
5 | + * it under the terms of the GNU General Public License version 2 | |
6 | + * as published by the Free Software Foundation. | |
7 | + * | |
8 | + * You should have received a copy of the GNU General Public License | |
9 | + * along with this program; if not, write to the Free Software | |
10 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
11 | + * | |
12 | + * This file is based on kernel/irq/devres.c | |
13 | + * | |
14 | + * Copyright (c) 2011 John Crispin <blogic@openwrt.org> | |
15 | + */ | |
16 | + | |
17 | +#include <linux/module.h> | |
18 | +#include <linux/gpio.h> | |
19 | +#include <linux/device.h> | |
20 | +#include <linux/gfp.h> | |
21 | + | |
22 | +static void devm_gpio_release(struct device *dev, void *res) | |
23 | +{ | |
24 | + unsigned *gpio = res; | |
25 | + | |
26 | + gpio_free(*gpio); | |
27 | +} | |
28 | + | |
29 | +static int devm_gpio_match(struct device *dev, void *res, void *data) | |
30 | +{ | |
31 | + unsigned *this = res, *gpio = data; | |
32 | + | |
33 | + return *this == *gpio; | |
34 | +} | |
35 | + | |
36 | +/** | |
37 | + * devm_gpio_request - request a gpio for a managed device | |
38 | + * @dev: device to request the gpio for | |
39 | + * @gpio: gpio to allocate | |
40 | + * @label: the name of the requested gpio | |
41 | + * | |
42 | + * Except for the extra @dev argument, this function takes the | |
43 | + * same arguments and performs the same function as | |
44 | + * gpio_request(). GPIOs requested with this function will be | |
45 | + * automatically freed on driver detach. | |
46 | + * | |
47 | + * If an GPIO allocated with this function needs to be freed | |
48 | + * separately, devm_gpio_free() must be used. | |
49 | + */ | |
50 | + | |
51 | +int devm_gpio_request(struct device *dev, unsigned gpio, const char *label) | |
52 | +{ | |
53 | + unsigned *dr; | |
54 | + int rc; | |
55 | + | |
56 | + dr = devres_alloc(devm_gpio_release, sizeof(unsigned), GFP_KERNEL); | |
57 | + if (!dr) | |
58 | + return -ENOMEM; | |
59 | + | |
60 | + rc = gpio_request(gpio, label); | |
61 | + if (rc) { | |
62 | + devres_free(dr); | |
63 | + return rc; | |
64 | + } | |
65 | + | |
66 | + *dr = gpio; | |
67 | + devres_add(dev, dr); | |
68 | + | |
69 | + return 0; | |
70 | +} | |
71 | +EXPORT_SYMBOL(devm_gpio_request); | |
72 | + | |
73 | +/** | |
74 | + * devm_gpio_free - free an interrupt | |
75 | + * @dev: device to free gpio for | |
76 | + * @gpio: gpio to free | |
77 | + * | |
78 | + * Except for the extra @dev argument, this function takes the | |
79 | + * same arguments and performs the same function as gpio_free(). | |
80 | + * This function instead of gpio_free() should be used to manually | |
81 | + * free GPIOs allocated with devm_gpio_request(). | |
82 | + */ | |
83 | +void devm_gpio_free(struct device *dev, unsigned int gpio) | |
84 | +{ | |
85 | + | |
86 | + WARN_ON(devres_destroy(dev, devm_gpio_release, devm_gpio_match, | |
87 | + &gpio)); | |
88 | + gpio_free(gpio); | |
89 | +} | |
90 | +EXPORT_SYMBOL(devm_gpio_free); |
drivers/gpio/gpio-pl061.c
... | ... | @@ -12,7 +12,6 @@ |
12 | 12 | #include <linux/spinlock.h> |
13 | 13 | #include <linux/errno.h> |
14 | 14 | #include <linux/module.h> |
15 | -#include <linux/list.h> | |
16 | 15 | #include <linux/io.h> |
17 | 16 | #include <linux/ioport.h> |
18 | 17 | #include <linux/irq.h> |
... | ... | @@ -23,6 +22,8 @@ |
23 | 22 | #include <linux/amba/bus.h> |
24 | 23 | #include <linux/amba/pl061.h> |
25 | 24 | #include <linux/slab.h> |
25 | +#include <linux/pm.h> | |
26 | +#include <asm/mach/irq.h> | |
26 | 27 | |
27 | 28 | #define GPIODIR 0x400 |
28 | 29 | #define GPIOIS 0x404 |
29 | 30 | |
30 | 31 | |
31 | 32 | |
32 | 33 | |
... | ... | @@ -35,25 +36,33 @@ |
35 | 36 | |
36 | 37 | #define PL061_GPIO_NR 8 |
37 | 38 | |
38 | -struct pl061_gpio { | |
39 | - /* We use a list of pl061_gpio structs for each trigger IRQ in the main | |
40 | - * interrupts controller of the system. We need this to support systems | |
41 | - * in which more that one PL061s are connected to the same IRQ. The ISR | |
42 | - * interates through this list to find the source of the interrupt. | |
43 | - */ | |
44 | - struct list_head list; | |
39 | +#ifdef CONFIG_PM | |
40 | +struct pl061_context_save_regs { | |
41 | + u8 gpio_data; | |
42 | + u8 gpio_dir; | |
43 | + u8 gpio_is; | |
44 | + u8 gpio_ibe; | |
45 | + u8 gpio_iev; | |
46 | + u8 gpio_ie; | |
47 | +}; | |
48 | +#endif | |
45 | 49 | |
50 | +struct pl061_gpio { | |
46 | 51 | /* Each of the two spinlocks protects a different set of hardware |
47 | 52 | * regiters and data structurs. This decouples the code of the IRQ from |
48 | 53 | * the GPIO code. This also makes the case of a GPIO routine call from |
49 | 54 | * the IRQ code simpler. |
50 | 55 | */ |
51 | 56 | spinlock_t lock; /* GPIO registers */ |
52 | - spinlock_t irq_lock; /* IRQ registers */ | |
53 | 57 | |
54 | 58 | void __iomem *base; |
55 | - unsigned irq_base; | |
59 | + int irq_base; | |
60 | + struct irq_chip_generic *irq_gc; | |
56 | 61 | struct gpio_chip gc; |
62 | + | |
63 | +#ifdef CONFIG_PM | |
64 | + struct pl061_context_save_regs csave_regs; | |
65 | +#endif | |
57 | 66 | }; |
58 | 67 | |
59 | 68 | static int pl061_direction_input(struct gpio_chip *gc, unsigned offset) |
60 | 69 | |
61 | 70 | |
... | ... | @@ -118,46 +127,16 @@ |
118 | 127 | { |
119 | 128 | struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc); |
120 | 129 | |
121 | - if (chip->irq_base == NO_IRQ) | |
130 | + if (chip->irq_base <= 0) | |
122 | 131 | return -EINVAL; |
123 | 132 | |
124 | 133 | return chip->irq_base + offset; |
125 | 134 | } |
126 | 135 | |
127 | -/* | |
128 | - * PL061 GPIO IRQ | |
129 | - */ | |
130 | -static void pl061_irq_disable(struct irq_data *d) | |
131 | -{ | |
132 | - struct pl061_gpio *chip = irq_data_get_irq_chip_data(d); | |
133 | - int offset = d->irq - chip->irq_base; | |
134 | - unsigned long flags; | |
135 | - u8 gpioie; | |
136 | - | |
137 | - spin_lock_irqsave(&chip->irq_lock, flags); | |
138 | - gpioie = readb(chip->base + GPIOIE); | |
139 | - gpioie &= ~(1 << offset); | |
140 | - writeb(gpioie, chip->base + GPIOIE); | |
141 | - spin_unlock_irqrestore(&chip->irq_lock, flags); | |
142 | -} | |
143 | - | |
144 | -static void pl061_irq_enable(struct irq_data *d) | |
145 | -{ | |
146 | - struct pl061_gpio *chip = irq_data_get_irq_chip_data(d); | |
147 | - int offset = d->irq - chip->irq_base; | |
148 | - unsigned long flags; | |
149 | - u8 gpioie; | |
150 | - | |
151 | - spin_lock_irqsave(&chip->irq_lock, flags); | |
152 | - gpioie = readb(chip->base + GPIOIE); | |
153 | - gpioie |= 1 << offset; | |
154 | - writeb(gpioie, chip->base + GPIOIE); | |
155 | - spin_unlock_irqrestore(&chip->irq_lock, flags); | |
156 | -} | |
157 | - | |
158 | 136 | static int pl061_irq_type(struct irq_data *d, unsigned trigger) |
159 | 137 | { |
160 | - struct pl061_gpio *chip = irq_data_get_irq_chip_data(d); | |
138 | + struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); | |
139 | + struct pl061_gpio *chip = gc->private; | |
161 | 140 | int offset = d->irq - chip->irq_base; |
162 | 141 | unsigned long flags; |
163 | 142 | u8 gpiois, gpioibe, gpioiev; |
... | ... | @@ -165,7 +144,7 @@ |
165 | 144 | if (offset < 0 || offset >= PL061_GPIO_NR) |
166 | 145 | return -EINVAL; |
167 | 146 | |
168 | - spin_lock_irqsave(&chip->irq_lock, flags); | |
147 | + raw_spin_lock_irqsave(&gc->lock, flags); | |
169 | 148 | |
170 | 149 | gpioiev = readb(chip->base + GPIOIEV); |
171 | 150 | |
172 | 151 | |
173 | 152 | |
174 | 153 | |
175 | 154 | |
176 | 155 | |
177 | 156 | |
178 | 157 | |
179 | 158 | |
... | ... | @@ -194,49 +173,54 @@ |
194 | 173 | |
195 | 174 | writeb(gpioiev, chip->base + GPIOIEV); |
196 | 175 | |
197 | - spin_unlock_irqrestore(&chip->irq_lock, flags); | |
176 | + raw_spin_unlock_irqrestore(&gc->lock, flags); | |
198 | 177 | |
199 | 178 | return 0; |
200 | 179 | } |
201 | 180 | |
202 | -static struct irq_chip pl061_irqchip = { | |
203 | - .name = "GPIO", | |
204 | - .irq_enable = pl061_irq_enable, | |
205 | - .irq_disable = pl061_irq_disable, | |
206 | - .irq_set_type = pl061_irq_type, | |
207 | -}; | |
208 | - | |
209 | 181 | static void pl061_irq_handler(unsigned irq, struct irq_desc *desc) |
210 | 182 | { |
211 | - struct list_head *chip_list = irq_get_handler_data(irq); | |
212 | - struct list_head *ptr; | |
213 | - struct pl061_gpio *chip; | |
183 | + unsigned long pending; | |
184 | + int offset; | |
185 | + struct pl061_gpio *chip = irq_desc_get_handler_data(desc); | |
186 | + struct irq_chip *irqchip = irq_desc_get_chip(desc); | |
214 | 187 | |
215 | - desc->irq_data.chip->irq_ack(&desc->irq_data); | |
216 | - list_for_each(ptr, chip_list) { | |
217 | - unsigned long pending; | |
218 | - int offset; | |
188 | + chained_irq_enter(irqchip, desc); | |
219 | 189 | |
220 | - chip = list_entry(ptr, struct pl061_gpio, list); | |
221 | - pending = readb(chip->base + GPIOMIS); | |
222 | - writeb(pending, chip->base + GPIOIC); | |
223 | - | |
224 | - if (pending == 0) | |
225 | - continue; | |
226 | - | |
190 | + pending = readb(chip->base + GPIOMIS); | |
191 | + writeb(pending, chip->base + GPIOIC); | |
192 | + if (pending) { | |
227 | 193 | for_each_set_bit(offset, &pending, PL061_GPIO_NR) |
228 | 194 | generic_handle_irq(pl061_to_irq(&chip->gc, offset)); |
229 | 195 | } |
230 | - desc->irq_data.chip->irq_unmask(&desc->irq_data); | |
196 | + | |
197 | + chained_irq_exit(irqchip, desc); | |
231 | 198 | } |
232 | 199 | |
200 | +static void __init pl061_init_gc(struct pl061_gpio *chip, int irq_base) | |
201 | +{ | |
202 | + struct irq_chip_type *ct; | |
203 | + | |
204 | + chip->irq_gc = irq_alloc_generic_chip("gpio-pl061", 1, irq_base, | |
205 | + chip->base, handle_simple_irq); | |
206 | + chip->irq_gc->private = chip; | |
207 | + | |
208 | + ct = chip->irq_gc->chip_types; | |
209 | + ct->chip.irq_mask = irq_gc_mask_clr_bit; | |
210 | + ct->chip.irq_unmask = irq_gc_mask_set_bit; | |
211 | + ct->chip.irq_set_type = pl061_irq_type; | |
212 | + ct->chip.irq_set_wake = irq_gc_set_wake; | |
213 | + ct->regs.mask = GPIOIE; | |
214 | + | |
215 | + irq_setup_generic_chip(chip->irq_gc, IRQ_MSK(PL061_GPIO_NR), | |
216 | + IRQ_GC_INIT_NESTED_LOCK, IRQ_NOREQUEST, 0); | |
217 | +} | |
218 | + | |
233 | 219 | static int pl061_probe(struct amba_device *dev, const struct amba_id *id) |
234 | 220 | { |
235 | 221 | struct pl061_platform_data *pdata; |
236 | 222 | struct pl061_gpio *chip; |
237 | - struct list_head *chip_list; | |
238 | 223 | int ret, irq, i; |
239 | - static DECLARE_BITMAP(init_irq, NR_IRQS); | |
240 | 224 | |
241 | 225 | chip = kzalloc(sizeof(*chip), GFP_KERNEL); |
242 | 226 | if (chip == NULL) |
... | ... | @@ -248,7 +232,7 @@ |
248 | 232 | chip->irq_base = pdata->irq_base; |
249 | 233 | } else if (dev->dev.of_node) { |
250 | 234 | chip->gc.base = -1; |
251 | - chip->irq_base = NO_IRQ; | |
235 | + chip->irq_base = 0; | |
252 | 236 | } else { |
253 | 237 | ret = -ENODEV; |
254 | 238 | goto free_mem; |
... | ... | @@ -267,8 +251,6 @@ |
267 | 251 | } |
268 | 252 | |
269 | 253 | spin_lock_init(&chip->lock); |
270 | - spin_lock_init(&chip->irq_lock); | |
271 | - INIT_LIST_HEAD(&chip->list); | |
272 | 254 | |
273 | 255 | chip->gc.direction_input = pl061_direction_input; |
274 | 256 | chip->gc.direction_output = pl061_direction_output; |
275 | 257 | |
... | ... | @@ -288,9 +270,11 @@ |
288 | 270 | * irq_chip support |
289 | 271 | */ |
290 | 272 | |
291 | - if (chip->irq_base == NO_IRQ) | |
273 | + if (chip->irq_base <= 0) | |
292 | 274 | return 0; |
293 | 275 | |
276 | + pl061_init_gc(chip, chip->irq_base); | |
277 | + | |
294 | 278 | writeb(0, chip->base + GPIOIE); /* disable irqs */ |
295 | 279 | irq = dev->irq[0]; |
296 | 280 | if (irq < 0) { |
... | ... | @@ -298,18 +282,7 @@ |
298 | 282 | goto iounmap; |
299 | 283 | } |
300 | 284 | irq_set_chained_handler(irq, pl061_irq_handler); |
301 | - if (!test_and_set_bit(irq, init_irq)) { /* list initialized? */ | |
302 | - chip_list = kmalloc(sizeof(*chip_list), GFP_KERNEL); | |
303 | - if (chip_list == NULL) { | |
304 | - clear_bit(irq, init_irq); | |
305 | - ret = -ENOMEM; | |
306 | - goto iounmap; | |
307 | - } | |
308 | - INIT_LIST_HEAD(chip_list); | |
309 | - irq_set_handler_data(irq, chip_list); | |
310 | - } else | |
311 | - chip_list = irq_get_handler_data(irq); | |
312 | - list_add(&chip->list, chip_list); | |
285 | + irq_set_handler_data(irq, chip); | |
313 | 286 | |
314 | 287 | for (i = 0; i < PL061_GPIO_NR; i++) { |
315 | 288 | if (pdata) { |
316 | 289 | |
... | ... | @@ -319,13 +292,10 @@ |
319 | 292 | else |
320 | 293 | pl061_direction_input(&chip->gc, i); |
321 | 294 | } |
322 | - | |
323 | - irq_set_chip_and_handler(i + chip->irq_base, &pl061_irqchip, | |
324 | - handle_simple_irq); | |
325 | - set_irq_flags(i+chip->irq_base, IRQF_VALID); | |
326 | - irq_set_chip_data(i + chip->irq_base, chip); | |
327 | 295 | } |
328 | 296 | |
297 | + amba_set_drvdata(dev, chip); | |
298 | + | |
329 | 299 | return 0; |
330 | 300 | |
331 | 301 | iounmap: |
... | ... | @@ -338,6 +308,53 @@ |
338 | 308 | return ret; |
339 | 309 | } |
340 | 310 | |
311 | +#ifdef CONFIG_PM | |
312 | +static int pl061_suspend(struct device *dev) | |
313 | +{ | |
314 | + struct pl061_gpio *chip = dev_get_drvdata(dev); | |
315 | + int offset; | |
316 | + | |
317 | + chip->csave_regs.gpio_data = 0; | |
318 | + chip->csave_regs.gpio_dir = readb(chip->base + GPIODIR); | |
319 | + chip->csave_regs.gpio_is = readb(chip->base + GPIOIS); | |
320 | + chip->csave_regs.gpio_ibe = readb(chip->base + GPIOIBE); | |
321 | + chip->csave_regs.gpio_iev = readb(chip->base + GPIOIEV); | |
322 | + chip->csave_regs.gpio_ie = readb(chip->base + GPIOIE); | |
323 | + | |
324 | + for (offset = 0; offset < PL061_GPIO_NR; offset++) { | |
325 | + if (chip->csave_regs.gpio_dir & (1 << offset)) | |
326 | + chip->csave_regs.gpio_data |= | |
327 | + pl061_get_value(&chip->gc, offset) << offset; | |
328 | + } | |
329 | + | |
330 | + return 0; | |
331 | +} | |
332 | + | |
333 | +static int pl061_resume(struct device *dev) | |
334 | +{ | |
335 | + struct pl061_gpio *chip = dev_get_drvdata(dev); | |
336 | + int offset; | |
337 | + | |
338 | + for (offset = 0; offset < PL061_GPIO_NR; offset++) { | |
339 | + if (chip->csave_regs.gpio_dir & (1 << offset)) | |
340 | + pl061_direction_output(&chip->gc, offset, | |
341 | + chip->csave_regs.gpio_data & | |
342 | + (1 << offset)); | |
343 | + else | |
344 | + pl061_direction_input(&chip->gc, offset); | |
345 | + } | |
346 | + | |
347 | + writeb(chip->csave_regs.gpio_is, chip->base + GPIOIS); | |
348 | + writeb(chip->csave_regs.gpio_ibe, chip->base + GPIOIBE); | |
349 | + writeb(chip->csave_regs.gpio_iev, chip->base + GPIOIEV); | |
350 | + writeb(chip->csave_regs.gpio_ie, chip->base + GPIOIE); | |
351 | + | |
352 | + return 0; | |
353 | +} | |
354 | + | |
355 | +static SIMPLE_DEV_PM_OPS(pl061_dev_pm_ops, pl061_suspend, pl061_resume); | |
356 | +#endif | |
357 | + | |
341 | 358 | static struct amba_id pl061_ids[] = { |
342 | 359 | { |
343 | 360 | .id = 0x00041061, |
... | ... | @@ -351,6 +368,9 @@ |
351 | 368 | static struct amba_driver pl061_gpio_driver = { |
352 | 369 | .drv = { |
353 | 370 | .name = "pl061_gpio", |
371 | +#ifdef CONFIG_PM | |
372 | + .pm = &pl061_dev_pm_ops, | |
373 | +#endif | |
354 | 374 | }, |
355 | 375 | .id_table = pl061_ids, |
356 | 376 | .probe = pl061_probe, |
drivers/gpio/gpio-sa1100.c
... | ... | @@ -47,12 +47,18 @@ |
47 | 47 | return 0; |
48 | 48 | } |
49 | 49 | |
50 | +static int sa1100_to_irq(struct gpio_chip *chip, unsigned offset) | |
51 | +{ | |
52 | + return offset < 11 ? (IRQ_GPIO0 + offset) : (IRQ_GPIO11 - 11 + offset); | |
53 | +} | |
54 | + | |
50 | 55 | static struct gpio_chip sa1100_gpio_chip = { |
51 | 56 | .label = "gpio", |
52 | 57 | .direction_input = sa1100_direction_input, |
53 | 58 | .direction_output = sa1100_direction_output, |
54 | 59 | .set = sa1100_gpio_set, |
55 | 60 | .get = sa1100_gpio_get, |
61 | + .to_irq = sa1100_to_irq, | |
56 | 62 | .base = 0, |
57 | 63 | .ngpio = GPIO_MAX + 1, |
58 | 64 | }; |
drivers/gpio/gpio-tegra.c
... | ... | @@ -361,14 +361,7 @@ |
361 | 361 | return -ENODEV; |
362 | 362 | } |
363 | 363 | |
364 | - if (!devm_request_mem_region(&pdev->dev, res->start, | |
365 | - resource_size(res), | |
366 | - dev_name(&pdev->dev))) { | |
367 | - dev_err(&pdev->dev, "Couldn't request MEM resource\n"); | |
368 | - return -ENODEV; | |
369 | - } | |
370 | - | |
371 | - regs = devm_ioremap(&pdev->dev, res->start, resource_size(res)); | |
364 | + regs = devm_request_and_ioremap(&pdev->dev, res); | |
372 | 365 | if (!regs) { |
373 | 366 | dev_err(&pdev->dev, "Couldn't ioremap regs\n"); |
374 | 367 | return -ENODEV; |
include/asm-generic/gpio.h
... | ... | @@ -177,6 +177,10 @@ |
177 | 177 | extern int gpio_request_array(const struct gpio *array, size_t num); |
178 | 178 | extern void gpio_free_array(const struct gpio *array, size_t num); |
179 | 179 | |
180 | +/* bindings for managed devices that want to request gpios */ | |
181 | +int devm_gpio_request(struct device *dev, unsigned gpio, const char *label); | |
182 | +void devm_gpio_free(struct device *dev, unsigned int gpio); | |
183 | + | |
180 | 184 | #ifdef CONFIG_GPIO_SYSFS |
181 | 185 | |
182 | 186 | /* |
include/linux/amba/pl061.h