Commit | Line | Data |
---|---|---|
1c44f5f1 | 1 | /* |
38f539a6 | 2 | * linux/arch/arm/plat-pxa/gpio.c |
1c44f5f1 PZ |
3 | * |
4 | * Generic PXA GPIO handling | |
5 | * | |
6 | * Author: Nicolas Pitre | |
7 | * Created: Jun 15, 2001 | |
8 | * Copyright: MontaVista Software Inc. | |
9 | * | |
10 | * This program is free software; you can redistribute it and/or modify | |
11 | * it under the terms of the GNU General Public License version 2 as | |
12 | * published by the Free Software Foundation. | |
13 | */ | |
2f8163ba | 14 | #include <linux/gpio.h> |
1c44f5f1 | 15 | #include <linux/init.h> |
e3630db1 | 16 | #include <linux/irq.h> |
fced80c7 | 17 | #include <linux/io.h> |
2eaa03b5 | 18 | #include <linux/syscore_ops.h> |
4aa78264 | 19 | #include <linux/slab.h> |
1c44f5f1 | 20 | |
f55be1bf | 21 | #include <mach/gpio-pxa.h> |
1c44f5f1 | 22 | |
3b8e285c EM |
23 | int pxa_last_gpio; |
24 | ||
1c44f5f1 PZ |
25 | struct pxa_gpio_chip { |
26 | struct gpio_chip chip; | |
0807da59 EM |
27 | void __iomem *regbase; |
28 | char label[10]; | |
29 | ||
30 | unsigned long irq_mask; | |
31 | unsigned long irq_edge_rise; | |
32 | unsigned long irq_edge_fall; | |
33 | ||
34 | #ifdef CONFIG_PM | |
35 | unsigned long saved_gplr; | |
36 | unsigned long saved_gpdr; | |
37 | unsigned long saved_grer; | |
38 | unsigned long saved_gfer; | |
39 | #endif | |
1c44f5f1 PZ |
40 | }; |
41 | ||
4929f5a8 HZ |
42 | enum { |
43 | PXA25X_GPIO = 0, | |
44 | PXA26X_GPIO, | |
45 | PXA27X_GPIO, | |
46 | PXA3XX_GPIO, | |
47 | PXA93X_GPIO, | |
48 | MMP_GPIO = 0x10, | |
49 | MMP2_GPIO, | |
50 | }; | |
51 | ||
0807da59 EM |
52 | static DEFINE_SPINLOCK(gpio_lock); |
53 | static struct pxa_gpio_chip *pxa_gpio_chips; | |
4929f5a8 | 54 | static int gpio_type; |
0807da59 EM |
55 | |
56 | #define for_each_gpio_chip(i, c) \ | |
57 | for (i = 0, c = &pxa_gpio_chips[0]; i <= pxa_last_gpio; i += 32, c++) | |
58 | ||
59 | static inline void __iomem *gpio_chip_base(struct gpio_chip *c) | |
60 | { | |
61 | return container_of(c, struct pxa_gpio_chip, chip)->regbase; | |
62 | } | |
63 | ||
a065685d | 64 | static inline struct pxa_gpio_chip *gpio_to_pxachip(unsigned gpio) |
0807da59 EM |
65 | { |
66 | return &pxa_gpio_chips[gpio_to_bank(gpio)]; | |
67 | } | |
68 | ||
4929f5a8 HZ |
69 | static inline int gpio_is_pxa_type(int type) |
70 | { | |
71 | return (type & MMP_GPIO) == 0; | |
72 | } | |
73 | ||
74 | static inline int gpio_is_mmp_type(int type) | |
75 | { | |
76 | return (type & MMP_GPIO) != 0; | |
77 | } | |
78 | ||
79 | #ifdef CONFIG_ARCH_PXA | |
80 | static inline int __pxa_gpio_to_irq(int gpio) | |
81 | { | |
82 | if (gpio_is_pxa_type(gpio_type)) | |
83 | return PXA_GPIO_TO_IRQ(gpio); | |
84 | return -1; | |
85 | } | |
86 | ||
87 | static inline int __pxa_irq_to_gpio(int irq) | |
88 | { | |
89 | if (gpio_is_pxa_type(gpio_type)) | |
90 | return irq - PXA_GPIO_TO_IRQ(0); | |
91 | return -1; | |
92 | } | |
93 | #else | |
94 | static inline int __pxa_gpio_to_irq(int gpio) { return -1; } | |
95 | static inline int __pxa_irq_to_gpio(int irq) { return -1; } | |
96 | #endif | |
97 | ||
98 | #ifdef CONFIG_ARCH_MMP | |
99 | static inline int __mmp_gpio_to_irq(int gpio) | |
100 | { | |
101 | if (gpio_is_mmp_type(gpio_type)) | |
102 | return MMP_GPIO_TO_IRQ(gpio); | |
103 | return -1; | |
104 | } | |
105 | ||
106 | static inline int __mmp_irq_to_gpio(int irq) | |
107 | { | |
108 | if (gpio_is_mmp_type(gpio_type)) | |
109 | return irq - MMP_GPIO_TO_IRQ(0); | |
110 | return -1; | |
111 | } | |
112 | #else | |
113 | static inline int __mmp_gpio_to_irq(int gpio) { return -1; } | |
114 | static inline int __mmp_irq_to_gpio(int irq) { return -1; } | |
115 | #endif | |
116 | ||
117 | static int pxa_gpio_to_irq(struct gpio_chip *chip, unsigned offset) | |
118 | { | |
119 | int gpio, ret; | |
120 | ||
121 | gpio = chip->base + offset; | |
122 | ret = __pxa_gpio_to_irq(gpio); | |
123 | if (ret >= 0) | |
124 | return ret; | |
125 | return __mmp_gpio_to_irq(gpio); | |
126 | } | |
127 | ||
128 | int pxa_irq_to_gpio(int irq) | |
129 | { | |
130 | int ret; | |
131 | ||
132 | ret = __pxa_irq_to_gpio(irq); | |
133 | if (ret >= 0) | |
134 | return ret; | |
135 | return __mmp_irq_to_gpio(irq); | |
136 | } | |
137 | ||
1c44f5f1 PZ |
138 | static int pxa_gpio_direction_input(struct gpio_chip *chip, unsigned offset) |
139 | { | |
0807da59 EM |
140 | void __iomem *base = gpio_chip_base(chip); |
141 | uint32_t value, mask = 1 << offset; | |
142 | unsigned long flags; | |
143 | ||
144 | spin_lock_irqsave(&gpio_lock, flags); | |
145 | ||
df664d20 | 146 | value = readl_relaxed(base + GPDR_OFFSET); |
067455aa EM |
147 | if (__gpio_is_inverted(chip->base + offset)) |
148 | value |= mask; | |
149 | else | |
150 | value &= ~mask; | |
df664d20 | 151 | writel_relaxed(value, base + GPDR_OFFSET); |
1c44f5f1 | 152 | |
0807da59 | 153 | spin_unlock_irqrestore(&gpio_lock, flags); |
1c44f5f1 PZ |
154 | return 0; |
155 | } | |
156 | ||
157 | static int pxa_gpio_direction_output(struct gpio_chip *chip, | |
0807da59 | 158 | unsigned offset, int value) |
1c44f5f1 | 159 | { |
0807da59 EM |
160 | void __iomem *base = gpio_chip_base(chip); |
161 | uint32_t tmp, mask = 1 << offset; | |
162 | unsigned long flags; | |
163 | ||
df664d20 | 164 | writel_relaxed(mask, base + (value ? GPSR_OFFSET : GPCR_OFFSET)); |
0807da59 EM |
165 | |
166 | spin_lock_irqsave(&gpio_lock, flags); | |
167 | ||
df664d20 | 168 | tmp = readl_relaxed(base + GPDR_OFFSET); |
067455aa EM |
169 | if (__gpio_is_inverted(chip->base + offset)) |
170 | tmp &= ~mask; | |
171 | else | |
172 | tmp |= mask; | |
df664d20 | 173 | writel_relaxed(tmp, base + GPDR_OFFSET); |
1c44f5f1 | 174 | |
0807da59 | 175 | spin_unlock_irqrestore(&gpio_lock, flags); |
1c44f5f1 PZ |
176 | return 0; |
177 | } | |
178 | ||
1c44f5f1 PZ |
179 | static int pxa_gpio_get(struct gpio_chip *chip, unsigned offset) |
180 | { | |
df664d20 | 181 | return readl_relaxed(gpio_chip_base(chip) + GPLR_OFFSET) & (1 << offset); |
1c44f5f1 PZ |
182 | } |
183 | ||
1c44f5f1 PZ |
184 | static void pxa_gpio_set(struct gpio_chip *chip, unsigned offset, int value) |
185 | { | |
df664d20 | 186 | writel_relaxed(1 << offset, gpio_chip_base(chip) + |
0807da59 | 187 | (value ? GPSR_OFFSET : GPCR_OFFSET)); |
1c44f5f1 PZ |
188 | } |
189 | ||
0807da59 | 190 | static int __init pxa_init_gpio_chip(int gpio_end) |
a58fbcd8 | 191 | { |
0807da59 EM |
192 | int i, gpio, nbanks = gpio_to_bank(gpio_end) + 1; |
193 | struct pxa_gpio_chip *chips; | |
a58fbcd8 | 194 | |
4aa78264 | 195 | chips = kzalloc(nbanks * sizeof(struct pxa_gpio_chip), GFP_KERNEL); |
0807da59 EM |
196 | if (chips == NULL) { |
197 | pr_err("%s: failed to allocate GPIO chips\n", __func__); | |
198 | return -ENOMEM; | |
a58fbcd8 | 199 | } |
a58fbcd8 | 200 | |
0807da59 EM |
201 | for (i = 0, gpio = 0; i < nbanks; i++, gpio += 32) { |
202 | struct gpio_chip *c = &chips[i].chip; | |
e3630db1 | 203 | |
0807da59 | 204 | sprintf(chips[i].label, "gpio-%d", i); |
97b09da4 | 205 | chips[i].regbase = GPIO_BANK(i); |
0807da59 EM |
206 | |
207 | c->base = gpio; | |
208 | c->label = chips[i].label; | |
209 | ||
210 | c->direction_input = pxa_gpio_direction_input; | |
211 | c->direction_output = pxa_gpio_direction_output; | |
212 | c->get = pxa_gpio_get; | |
213 | c->set = pxa_gpio_set; | |
4929f5a8 | 214 | c->to_irq = pxa_gpio_to_irq; |
0807da59 EM |
215 | |
216 | /* number of GPIOs on last bank may be less than 32 */ | |
217 | c->ngpio = (gpio + 31 > gpio_end) ? (gpio_end - gpio + 1) : 32; | |
218 | gpiochip_add(c); | |
219 | } | |
220 | pxa_gpio_chips = chips; | |
221 | return 0; | |
222 | } | |
e3630db1 | 223 | |
a8f6faeb EM |
224 | /* Update only those GRERx and GFERx edge detection register bits if those |
225 | * bits are set in c->irq_mask | |
226 | */ | |
227 | static inline void update_edge_detect(struct pxa_gpio_chip *c) | |
228 | { | |
229 | uint32_t grer, gfer; | |
230 | ||
df664d20 HZ |
231 | grer = readl_relaxed(c->regbase + GRER_OFFSET) & ~c->irq_mask; |
232 | gfer = readl_relaxed(c->regbase + GFER_OFFSET) & ~c->irq_mask; | |
a8f6faeb EM |
233 | grer |= c->irq_edge_rise & c->irq_mask; |
234 | gfer |= c->irq_edge_fall & c->irq_mask; | |
df664d20 HZ |
235 | writel_relaxed(grer, c->regbase + GRER_OFFSET); |
236 | writel_relaxed(gfer, c->regbase + GFER_OFFSET); | |
a8f6faeb EM |
237 | } |
238 | ||
a3f4c927 | 239 | static int pxa_gpio_irq_type(struct irq_data *d, unsigned int type) |
e3630db1 | 240 | { |
0807da59 | 241 | struct pxa_gpio_chip *c; |
4929f5a8 | 242 | int gpio = pxa_irq_to_gpio(d->irq); |
0807da59 | 243 | unsigned long gpdr, mask = GPIO_bit(gpio); |
e3630db1 | 244 | |
a065685d | 245 | c = gpio_to_pxachip(gpio); |
e3630db1 | 246 | |
247 | if (type == IRQ_TYPE_PROBE) { | |
248 | /* Don't mess with enabled GPIOs using preconfigured edges or | |
249 | * GPIOs set to alternate function or to output during probe | |
250 | */ | |
0807da59 | 251 | if ((c->irq_edge_rise | c->irq_edge_fall) & GPIO_bit(gpio)) |
e3630db1 | 252 | return 0; |
689c04a3 | 253 | |
254 | if (__gpio_is_occupied(gpio)) | |
e3630db1 | 255 | return 0; |
689c04a3 | 256 | |
e3630db1 | 257 | type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING; |
258 | } | |
259 | ||
df664d20 | 260 | gpdr = readl_relaxed(c->regbase + GPDR_OFFSET); |
0807da59 | 261 | |
067455aa | 262 | if (__gpio_is_inverted(gpio)) |
df664d20 | 263 | writel_relaxed(gpdr | mask, c->regbase + GPDR_OFFSET); |
067455aa | 264 | else |
df664d20 | 265 | writel_relaxed(gpdr & ~mask, c->regbase + GPDR_OFFSET); |
e3630db1 | 266 | |
267 | if (type & IRQ_TYPE_EDGE_RISING) | |
0807da59 | 268 | c->irq_edge_rise |= mask; |
e3630db1 | 269 | else |
0807da59 | 270 | c->irq_edge_rise &= ~mask; |
e3630db1 | 271 | |
272 | if (type & IRQ_TYPE_EDGE_FALLING) | |
0807da59 | 273 | c->irq_edge_fall |= mask; |
e3630db1 | 274 | else |
0807da59 | 275 | c->irq_edge_fall &= ~mask; |
e3630db1 | 276 | |
a8f6faeb | 277 | update_edge_detect(c); |
e3630db1 | 278 | |
a3f4c927 | 279 | pr_debug("%s: IRQ%d (GPIO%d) - edge%s%s\n", __func__, d->irq, gpio, |
e3630db1 | 280 | ((type & IRQ_TYPE_EDGE_RISING) ? " rising" : ""), |
281 | ((type & IRQ_TYPE_EDGE_FALLING) ? " falling" : "")); | |
282 | return 0; | |
283 | } | |
284 | ||
e3630db1 | 285 | static void pxa_gpio_demux_handler(unsigned int irq, struct irq_desc *desc) |
286 | { | |
0807da59 EM |
287 | struct pxa_gpio_chip *c; |
288 | int loop, gpio, gpio_base, n; | |
289 | unsigned long gedr; | |
e3630db1 | 290 | |
291 | do { | |
e3630db1 | 292 | loop = 0; |
0807da59 EM |
293 | for_each_gpio_chip(gpio, c) { |
294 | gpio_base = c->chip.base; | |
295 | ||
df664d20 | 296 | gedr = readl_relaxed(c->regbase + GEDR_OFFSET); |
0807da59 | 297 | gedr = gedr & c->irq_mask; |
df664d20 | 298 | writel_relaxed(gedr, c->regbase + GEDR_OFFSET); |
e3630db1 | 299 | |
0807da59 EM |
300 | n = find_first_bit(&gedr, BITS_PER_LONG); |
301 | while (n < BITS_PER_LONG) { | |
302 | loop = 1; | |
e3630db1 | 303 | |
0807da59 EM |
304 | generic_handle_irq(gpio_to_irq(gpio_base + n)); |
305 | n = find_next_bit(&gedr, BITS_PER_LONG, n + 1); | |
306 | } | |
e3630db1 | 307 | } |
308 | } while (loop); | |
309 | } | |
310 | ||
a3f4c927 | 311 | static void pxa_ack_muxed_gpio(struct irq_data *d) |
e3630db1 | 312 | { |
4929f5a8 | 313 | int gpio = pxa_irq_to_gpio(d->irq); |
a065685d | 314 | struct pxa_gpio_chip *c = gpio_to_pxachip(gpio); |
0807da59 | 315 | |
df664d20 | 316 | writel_relaxed(GPIO_bit(gpio), c->regbase + GEDR_OFFSET); |
e3630db1 | 317 | } |
318 | ||
a3f4c927 | 319 | static void pxa_mask_muxed_gpio(struct irq_data *d) |
e3630db1 | 320 | { |
4929f5a8 | 321 | int gpio = pxa_irq_to_gpio(d->irq); |
a065685d | 322 | struct pxa_gpio_chip *c = gpio_to_pxachip(gpio); |
0807da59 EM |
323 | uint32_t grer, gfer; |
324 | ||
325 | c->irq_mask &= ~GPIO_bit(gpio); | |
326 | ||
df664d20 HZ |
327 | grer = readl_relaxed(c->regbase + GRER_OFFSET) & ~GPIO_bit(gpio); |
328 | gfer = readl_relaxed(c->regbase + GFER_OFFSET) & ~GPIO_bit(gpio); | |
329 | writel_relaxed(grer, c->regbase + GRER_OFFSET); | |
330 | writel_relaxed(gfer, c->regbase + GFER_OFFSET); | |
e3630db1 | 331 | } |
332 | ||
a3f4c927 | 333 | static void pxa_unmask_muxed_gpio(struct irq_data *d) |
e3630db1 | 334 | { |
4929f5a8 | 335 | int gpio = pxa_irq_to_gpio(d->irq); |
a065685d | 336 | struct pxa_gpio_chip *c = gpio_to_pxachip(gpio); |
0807da59 EM |
337 | |
338 | c->irq_mask |= GPIO_bit(gpio); | |
a8f6faeb | 339 | update_edge_detect(c); |
e3630db1 | 340 | } |
341 | ||
342 | static struct irq_chip pxa_muxed_gpio_chip = { | |
343 | .name = "GPIO", | |
a3f4c927 LB |
344 | .irq_ack = pxa_ack_muxed_gpio, |
345 | .irq_mask = pxa_mask_muxed_gpio, | |
346 | .irq_unmask = pxa_unmask_muxed_gpio, | |
347 | .irq_set_type = pxa_gpio_irq_type, | |
e3630db1 | 348 | }; |
349 | ||
478e223c HZ |
350 | static int pxa_gpio_nums(void) |
351 | { | |
352 | int count = 0; | |
353 | ||
354 | #ifdef CONFIG_ARCH_PXA | |
355 | if (cpu_is_pxa25x()) { | |
356 | #ifdef CONFIG_CPU_PXA26x | |
357 | count = 89; | |
358 | gpio_type = PXA26X_GPIO; | |
359 | #elif defined(CONFIG_PXA25x) | |
360 | count = 84; | |
361 | gpio_type = PXA26X_GPIO; | |
362 | #endif /* CONFIG_CPU_PXA26x */ | |
363 | } else if (cpu_is_pxa27x()) { | |
364 | count = 120; | |
365 | gpio_type = PXA27X_GPIO; | |
366 | } else if (cpu_is_pxa93x() || cpu_is_pxa95x()) { | |
367 | count = 191; | |
368 | gpio_type = PXA93X_GPIO; | |
369 | } else if (cpu_is_pxa3xx()) { | |
370 | count = 127; | |
371 | gpio_type = PXA3XX_GPIO; | |
372 | } | |
373 | #endif /* CONFIG_ARCH_PXA */ | |
374 | ||
375 | #ifdef CONFIG_ARCH_MMP | |
376 | if (cpu_is_pxa168() || cpu_is_pxa910()) { | |
377 | count = 127; | |
378 | gpio_type = MMP_GPIO; | |
379 | } else if (cpu_is_mmp2()) { | |
380 | count = 191; | |
381 | gpio_type = MMP2_GPIO; | |
382 | } | |
383 | #endif /* CONFIG_ARCH_MMP */ | |
384 | return count; | |
385 | } | |
386 | ||
a58fbcd8 | 387 | void __init pxa_init_gpio(int mux_irq, int start, int end, set_wake_t fn) |
e3630db1 | 388 | { |
0807da59 EM |
389 | struct pxa_gpio_chip *c; |
390 | int gpio, irq; | |
e3630db1 | 391 | |
478e223c HZ |
392 | pxa_last_gpio = pxa_gpio_nums(); |
393 | if (!pxa_last_gpio) | |
394 | return; | |
e3630db1 | 395 | |
0807da59 EM |
396 | /* Initialize GPIO chips */ |
397 | pxa_init_gpio_chip(end); | |
398 | ||
e3630db1 | 399 | /* clear all GPIO edge detects */ |
0807da59 | 400 | for_each_gpio_chip(gpio, c) { |
df664d20 HZ |
401 | writel_relaxed(0, c->regbase + GFER_OFFSET); |
402 | writel_relaxed(0, c->regbase + GRER_OFFSET); | |
403 | writel_relaxed(~0,c->regbase + GEDR_OFFSET); | |
e3630db1 | 404 | } |
405 | ||
87c49e20 HZ |
406 | #ifdef CONFIG_ARCH_PXA |
407 | irq = gpio_to_irq(0); | |
408 | irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip, | |
409 | handle_edge_irq); | |
410 | set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); | |
411 | irq_set_chained_handler(IRQ_GPIO0, pxa_gpio_demux_handler); | |
412 | ||
413 | irq = gpio_to_irq(1); | |
414 | irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip, | |
415 | handle_edge_irq); | |
416 | set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); | |
417 | irq_set_chained_handler(IRQ_GPIO1, pxa_gpio_demux_handler); | |
418 | #endif | |
419 | ||
a58fbcd8 | 420 | for (irq = gpio_to_irq(start); irq <= gpio_to_irq(end); irq++) { |
f38c02f3 TG |
421 | irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip, |
422 | handle_edge_irq); | |
e3630db1 | 423 | set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); |
424 | } | |
425 | ||
426 | /* Install handler for GPIO>=2 edge detect interrupts */ | |
6845664a | 427 | irq_set_chained_handler(mux_irq, pxa_gpio_demux_handler); |
a3f4c927 | 428 | pxa_muxed_gpio_chip.irq_set_wake = fn; |
e3630db1 | 429 | } |
663707c1 | 430 | |
431 | #ifdef CONFIG_PM | |
2eaa03b5 | 432 | static int pxa_gpio_suspend(void) |
663707c1 | 433 | { |
0807da59 EM |
434 | struct pxa_gpio_chip *c; |
435 | int gpio; | |
663707c1 | 436 | |
0807da59 | 437 | for_each_gpio_chip(gpio, c) { |
df664d20 HZ |
438 | c->saved_gplr = readl_relaxed(c->regbase + GPLR_OFFSET); |
439 | c->saved_gpdr = readl_relaxed(c->regbase + GPDR_OFFSET); | |
440 | c->saved_grer = readl_relaxed(c->regbase + GRER_OFFSET); | |
441 | c->saved_gfer = readl_relaxed(c->regbase + GFER_OFFSET); | |
663707c1 | 442 | |
443 | /* Clear GPIO transition detect bits */ | |
df664d20 | 444 | writel_relaxed(0xffffffff, c->regbase + GEDR_OFFSET); |
663707c1 | 445 | } |
446 | return 0; | |
447 | } | |
448 | ||
2eaa03b5 | 449 | static void pxa_gpio_resume(void) |
663707c1 | 450 | { |
0807da59 EM |
451 | struct pxa_gpio_chip *c; |
452 | int gpio; | |
663707c1 | 453 | |
0807da59 | 454 | for_each_gpio_chip(gpio, c) { |
663707c1 | 455 | /* restore level with set/clear */ |
df664d20 HZ |
456 | writel_relaxed( c->saved_gplr, c->regbase + GPSR_OFFSET); |
457 | writel_relaxed(~c->saved_gplr, c->regbase + GPCR_OFFSET); | |
663707c1 | 458 | |
df664d20 HZ |
459 | writel_relaxed(c->saved_grer, c->regbase + GRER_OFFSET); |
460 | writel_relaxed(c->saved_gfer, c->regbase + GFER_OFFSET); | |
461 | writel_relaxed(c->saved_gpdr, c->regbase + GPDR_OFFSET); | |
663707c1 | 462 | } |
663707c1 | 463 | } |
464 | #else | |
465 | #define pxa_gpio_suspend NULL | |
466 | #define pxa_gpio_resume NULL | |
467 | #endif | |
468 | ||
2eaa03b5 | 469 | struct syscore_ops pxa_gpio_syscore_ops = { |
663707c1 | 470 | .suspend = pxa_gpio_suspend, |
471 | .resume = pxa_gpio_resume, | |
472 | }; |