diff options
Diffstat (limited to 'arch/mips/jz4740/gpio.c')
-rw-r--r-- | arch/mips/jz4740/gpio.c | 604 |
1 files changed, 604 insertions, 0 deletions
diff --git a/arch/mips/jz4740/gpio.c b/arch/mips/jz4740/gpio.c new file mode 100644 index 000000000000..38f60f35156c --- /dev/null +++ b/arch/mips/jz4740/gpio.c | |||
@@ -0,0 +1,604 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de> | ||
3 | * JZ4740 platform GPIO support | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of the GNU General Public License as published by the | ||
7 | * Free Software Foundation; either version 2 of the License, or (at your | ||
8 | * option) any later version. | ||
9 | * | ||
10 | * You should have received a copy of the GNU General Public License along | ||
11 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
12 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
13 | * | ||
14 | */ | ||
15 | |||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/init.h> | ||
19 | |||
20 | #include <linux/spinlock.h> | ||
21 | #include <linux/sysdev.h> | ||
22 | #include <linux/io.h> | ||
23 | #include <linux/gpio.h> | ||
24 | #include <linux/delay.h> | ||
25 | #include <linux/interrupt.h> | ||
26 | #include <linux/bitops.h> | ||
27 | |||
28 | #include <linux/debugfs.h> | ||
29 | #include <linux/seq_file.h> | ||
30 | |||
31 | #include <asm/mach-jz4740/base.h> | ||
32 | |||
33 | #define JZ4740_GPIO_BASE_A (32*0) | ||
34 | #define JZ4740_GPIO_BASE_B (32*1) | ||
35 | #define JZ4740_GPIO_BASE_C (32*2) | ||
36 | #define JZ4740_GPIO_BASE_D (32*3) | ||
37 | |||
38 | #define JZ4740_GPIO_NUM_A 32 | ||
39 | #define JZ4740_GPIO_NUM_B 32 | ||
40 | #define JZ4740_GPIO_NUM_C 31 | ||
41 | #define JZ4740_GPIO_NUM_D 32 | ||
42 | |||
43 | #define JZ4740_IRQ_GPIO_BASE_A (JZ4740_IRQ_GPIO(0) + JZ4740_GPIO_BASE_A) | ||
44 | #define JZ4740_IRQ_GPIO_BASE_B (JZ4740_IRQ_GPIO(0) + JZ4740_GPIO_BASE_B) | ||
45 | #define JZ4740_IRQ_GPIO_BASE_C (JZ4740_IRQ_GPIO(0) + JZ4740_GPIO_BASE_C) | ||
46 | #define JZ4740_IRQ_GPIO_BASE_D (JZ4740_IRQ_GPIO(0) + JZ4740_GPIO_BASE_D) | ||
47 | |||
48 | #define JZ_REG_GPIO_PIN 0x00 | ||
49 | #define JZ_REG_GPIO_DATA 0x10 | ||
50 | #define JZ_REG_GPIO_DATA_SET 0x14 | ||
51 | #define JZ_REG_GPIO_DATA_CLEAR 0x18 | ||
52 | #define JZ_REG_GPIO_MASK 0x20 | ||
53 | #define JZ_REG_GPIO_MASK_SET 0x24 | ||
54 | #define JZ_REG_GPIO_MASK_CLEAR 0x28 | ||
55 | #define JZ_REG_GPIO_PULL 0x30 | ||
56 | #define JZ_REG_GPIO_PULL_SET 0x34 | ||
57 | #define JZ_REG_GPIO_PULL_CLEAR 0x38 | ||
58 | #define JZ_REG_GPIO_FUNC 0x40 | ||
59 | #define JZ_REG_GPIO_FUNC_SET 0x44 | ||
60 | #define JZ_REG_GPIO_FUNC_CLEAR 0x48 | ||
61 | #define JZ_REG_GPIO_SELECT 0x50 | ||
62 | #define JZ_REG_GPIO_SELECT_SET 0x54 | ||
63 | #define JZ_REG_GPIO_SELECT_CLEAR 0x58 | ||
64 | #define JZ_REG_GPIO_DIRECTION 0x60 | ||
65 | #define JZ_REG_GPIO_DIRECTION_SET 0x64 | ||
66 | #define JZ_REG_GPIO_DIRECTION_CLEAR 0x68 | ||
67 | #define JZ_REG_GPIO_TRIGGER 0x70 | ||
68 | #define JZ_REG_GPIO_TRIGGER_SET 0x74 | ||
69 | #define JZ_REG_GPIO_TRIGGER_CLEAR 0x78 | ||
70 | #define JZ_REG_GPIO_FLAG 0x80 | ||
71 | #define JZ_REG_GPIO_FLAG_CLEAR 0x14 | ||
72 | |||
73 | #define GPIO_TO_BIT(gpio) BIT(gpio & 0x1f) | ||
74 | #define GPIO_TO_REG(gpio, reg) (gpio_to_jz_gpio_chip(gpio)->base + (reg)) | ||
75 | #define CHIP_TO_REG(chip, reg) (gpio_chip_to_jz_gpio_chip(chip)->base + (reg)) | ||
76 | |||
77 | struct jz_gpio_chip { | ||
78 | unsigned int irq; | ||
79 | unsigned int irq_base; | ||
80 | uint32_t wakeup; | ||
81 | uint32_t suspend_mask; | ||
82 | uint32_t edge_trigger_both; | ||
83 | |||
84 | void __iomem *base; | ||
85 | |||
86 | spinlock_t lock; | ||
87 | |||
88 | struct gpio_chip gpio_chip; | ||
89 | struct irq_chip irq_chip; | ||
90 | struct sys_device sysdev; | ||
91 | }; | ||
92 | |||
93 | static struct jz_gpio_chip jz4740_gpio_chips[]; | ||
94 | |||
95 | static inline struct jz_gpio_chip *gpio_to_jz_gpio_chip(unsigned int gpio) | ||
96 | { | ||
97 | return &jz4740_gpio_chips[gpio >> 5]; | ||
98 | } | ||
99 | |||
100 | static inline struct jz_gpio_chip *gpio_chip_to_jz_gpio_chip(struct gpio_chip *gpio_chip) | ||
101 | { | ||
102 | return container_of(gpio_chip, struct jz_gpio_chip, gpio_chip); | ||
103 | } | ||
104 | |||
105 | static inline struct jz_gpio_chip *irq_to_jz_gpio_chip(unsigned int irq) | ||
106 | { | ||
107 | return get_irq_chip_data(irq); | ||
108 | } | ||
109 | |||
110 | static inline void jz_gpio_write_bit(unsigned int gpio, unsigned int reg) | ||
111 | { | ||
112 | writel(GPIO_TO_BIT(gpio), GPIO_TO_REG(gpio, reg)); | ||
113 | } | ||
114 | |||
115 | int jz_gpio_set_function(int gpio, enum jz_gpio_function function) | ||
116 | { | ||
117 | if (function == JZ_GPIO_FUNC_NONE) { | ||
118 | jz_gpio_write_bit(gpio, JZ_REG_GPIO_FUNC_CLEAR); | ||
119 | jz_gpio_write_bit(gpio, JZ_REG_GPIO_SELECT_CLEAR); | ||
120 | jz_gpio_write_bit(gpio, JZ_REG_GPIO_TRIGGER_CLEAR); | ||
121 | } else { | ||
122 | jz_gpio_write_bit(gpio, JZ_REG_GPIO_FUNC_SET); | ||
123 | jz_gpio_write_bit(gpio, JZ_REG_GPIO_TRIGGER_CLEAR); | ||
124 | switch (function) { | ||
125 | case JZ_GPIO_FUNC1: | ||
126 | jz_gpio_write_bit(gpio, JZ_REG_GPIO_SELECT_CLEAR); | ||
127 | break; | ||
128 | case JZ_GPIO_FUNC3: | ||
129 | jz_gpio_write_bit(gpio, JZ_REG_GPIO_TRIGGER_SET); | ||
130 | case JZ_GPIO_FUNC2: /* Falltrough */ | ||
131 | jz_gpio_write_bit(gpio, JZ_REG_GPIO_SELECT_SET); | ||
132 | break; | ||
133 | default: | ||
134 | BUG(); | ||
135 | break; | ||
136 | } | ||
137 | } | ||
138 | |||
139 | return 0; | ||
140 | } | ||
141 | EXPORT_SYMBOL_GPL(jz_gpio_set_function); | ||
142 | |||
143 | int jz_gpio_bulk_request(const struct jz_gpio_bulk_request *request, size_t num) | ||
144 | { | ||
145 | size_t i; | ||
146 | int ret; | ||
147 | |||
148 | for (i = 0; i < num; ++i, ++request) { | ||
149 | ret = gpio_request(request->gpio, request->name); | ||
150 | if (ret) | ||
151 | goto err; | ||
152 | jz_gpio_set_function(request->gpio, request->function); | ||
153 | } | ||
154 | |||
155 | return 0; | ||
156 | |||
157 | err: | ||
158 | for (--request; i > 0; --i, --request) { | ||
159 | gpio_free(request->gpio); | ||
160 | jz_gpio_set_function(request->gpio, JZ_GPIO_FUNC_NONE); | ||
161 | } | ||
162 | |||
163 | return ret; | ||
164 | } | ||
165 | EXPORT_SYMBOL_GPL(jz_gpio_bulk_request); | ||
166 | |||
167 | void jz_gpio_bulk_free(const struct jz_gpio_bulk_request *request, size_t num) | ||
168 | { | ||
169 | size_t i; | ||
170 | |||
171 | for (i = 0; i < num; ++i, ++request) { | ||
172 | gpio_free(request->gpio); | ||
173 | jz_gpio_set_function(request->gpio, JZ_GPIO_FUNC_NONE); | ||
174 | } | ||
175 | |||
176 | } | ||
177 | EXPORT_SYMBOL_GPL(jz_gpio_bulk_free); | ||
178 | |||
179 | void jz_gpio_bulk_suspend(const struct jz_gpio_bulk_request *request, size_t num) | ||
180 | { | ||
181 | size_t i; | ||
182 | |||
183 | for (i = 0; i < num; ++i, ++request) { | ||
184 | jz_gpio_set_function(request->gpio, JZ_GPIO_FUNC_NONE); | ||
185 | jz_gpio_write_bit(request->gpio, JZ_REG_GPIO_DIRECTION_CLEAR); | ||
186 | jz_gpio_write_bit(request->gpio, JZ_REG_GPIO_PULL_SET); | ||
187 | } | ||
188 | } | ||
189 | EXPORT_SYMBOL_GPL(jz_gpio_bulk_suspend); | ||
190 | |||
191 | void jz_gpio_bulk_resume(const struct jz_gpio_bulk_request *request, size_t num) | ||
192 | { | ||
193 | size_t i; | ||
194 | |||
195 | for (i = 0; i < num; ++i, ++request) | ||
196 | jz_gpio_set_function(request->gpio, request->function); | ||
197 | } | ||
198 | EXPORT_SYMBOL_GPL(jz_gpio_bulk_resume); | ||
199 | |||
200 | void jz_gpio_enable_pullup(unsigned gpio) | ||
201 | { | ||
202 | jz_gpio_write_bit(gpio, JZ_REG_GPIO_PULL_CLEAR); | ||
203 | } | ||
204 | EXPORT_SYMBOL_GPL(jz_gpio_enable_pullup); | ||
205 | |||
206 | void jz_gpio_disable_pullup(unsigned gpio) | ||
207 | { | ||
208 | jz_gpio_write_bit(gpio, JZ_REG_GPIO_PULL_SET); | ||
209 | } | ||
210 | EXPORT_SYMBOL_GPL(jz_gpio_disable_pullup); | ||
211 | |||
212 | static int jz_gpio_get_value(struct gpio_chip *chip, unsigned gpio) | ||
213 | { | ||
214 | return !!(readl(CHIP_TO_REG(chip, JZ_REG_GPIO_PIN)) & BIT(gpio)); | ||
215 | } | ||
216 | |||
217 | static void jz_gpio_set_value(struct gpio_chip *chip, unsigned gpio, int value) | ||
218 | { | ||
219 | uint32_t __iomem *reg = CHIP_TO_REG(chip, JZ_REG_GPIO_DATA_SET); | ||
220 | reg += !value; | ||
221 | writel(BIT(gpio), reg); | ||
222 | } | ||
223 | |||
224 | static int jz_gpio_direction_output(struct gpio_chip *chip, unsigned gpio, | ||
225 | int value) | ||
226 | { | ||
227 | writel(BIT(gpio), CHIP_TO_REG(chip, JZ_REG_GPIO_DIRECTION_SET)); | ||
228 | jz_gpio_set_value(chip, gpio, value); | ||
229 | |||
230 | return 0; | ||
231 | } | ||
232 | |||
233 | static int jz_gpio_direction_input(struct gpio_chip *chip, unsigned gpio) | ||
234 | { | ||
235 | writel(BIT(gpio), CHIP_TO_REG(chip, JZ_REG_GPIO_DIRECTION_CLEAR)); | ||
236 | |||
237 | return 0; | ||
238 | } | ||
239 | |||
240 | int jz_gpio_port_direction_input(int port, uint32_t mask) | ||
241 | { | ||
242 | writel(mask, GPIO_TO_REG(port, JZ_REG_GPIO_DIRECTION_CLEAR)); | ||
243 | |||
244 | return 0; | ||
245 | } | ||
246 | EXPORT_SYMBOL(jz_gpio_port_direction_input); | ||
247 | |||
248 | int jz_gpio_port_direction_output(int port, uint32_t mask) | ||
249 | { | ||
250 | writel(mask, GPIO_TO_REG(port, JZ_REG_GPIO_DIRECTION_SET)); | ||
251 | |||
252 | return 0; | ||
253 | } | ||
254 | EXPORT_SYMBOL(jz_gpio_port_direction_output); | ||
255 | |||
256 | void jz_gpio_port_set_value(int port, uint32_t value, uint32_t mask) | ||
257 | { | ||
258 | writel(~value & mask, GPIO_TO_REG(port, JZ_REG_GPIO_DATA_CLEAR)); | ||
259 | writel(value & mask, GPIO_TO_REG(port, JZ_REG_GPIO_DATA_SET)); | ||
260 | } | ||
261 | EXPORT_SYMBOL(jz_gpio_port_set_value); | ||
262 | |||
263 | uint32_t jz_gpio_port_get_value(int port, uint32_t mask) | ||
264 | { | ||
265 | uint32_t value = readl(GPIO_TO_REG(port, JZ_REG_GPIO_PIN)); | ||
266 | |||
267 | return value & mask; | ||
268 | } | ||
269 | EXPORT_SYMBOL(jz_gpio_port_get_value); | ||
270 | |||
271 | int gpio_to_irq(unsigned gpio) | ||
272 | { | ||
273 | return JZ4740_IRQ_GPIO(0) + gpio; | ||
274 | } | ||
275 | EXPORT_SYMBOL_GPL(gpio_to_irq); | ||
276 | |||
277 | int irq_to_gpio(unsigned irq) | ||
278 | { | ||
279 | return irq - JZ4740_IRQ_GPIO(0); | ||
280 | } | ||
281 | EXPORT_SYMBOL_GPL(irq_to_gpio); | ||
282 | |||
283 | #define IRQ_TO_BIT(irq) BIT(irq_to_gpio(irq) & 0x1f) | ||
284 | |||
285 | static void jz_gpio_check_trigger_both(struct jz_gpio_chip *chip, unsigned int irq) | ||
286 | { | ||
287 | uint32_t value; | ||
288 | void __iomem *reg; | ||
289 | uint32_t mask = IRQ_TO_BIT(irq); | ||
290 | |||
291 | if (!(chip->edge_trigger_both & mask)) | ||
292 | return; | ||
293 | |||
294 | reg = chip->base; | ||
295 | |||
296 | value = readl(chip->base + JZ_REG_GPIO_PIN); | ||
297 | if (value & mask) | ||
298 | reg += JZ_REG_GPIO_DIRECTION_CLEAR; | ||
299 | else | ||
300 | reg += JZ_REG_GPIO_DIRECTION_SET; | ||
301 | |||
302 | writel(mask, reg); | ||
303 | } | ||
304 | |||
305 | static void jz_gpio_irq_demux_handler(unsigned int irq, struct irq_desc *desc) | ||
306 | { | ||
307 | uint32_t flag; | ||
308 | unsigned int gpio_irq; | ||
309 | unsigned int gpio_bank; | ||
310 | struct jz_gpio_chip *chip = get_irq_desc_data(desc); | ||
311 | |||
312 | gpio_bank = JZ4740_IRQ_GPIO0 - irq; | ||
313 | |||
314 | flag = readl(chip->base + JZ_REG_GPIO_FLAG); | ||
315 | |||
316 | if (!flag) | ||
317 | return; | ||
318 | |||
319 | gpio_irq = __fls(flag); | ||
320 | |||
321 | jz_gpio_check_trigger_both(chip, irq); | ||
322 | |||
323 | gpio_irq += (gpio_bank << 5) + JZ4740_IRQ_GPIO(0); | ||
324 | |||
325 | generic_handle_irq(gpio_irq); | ||
326 | }; | ||
327 | |||
328 | static inline void jz_gpio_set_irq_bit(unsigned int irq, unsigned int reg) | ||
329 | { | ||
330 | struct jz_gpio_chip *chip = irq_to_jz_gpio_chip(irq); | ||
331 | writel(IRQ_TO_BIT(irq), chip->base + reg); | ||
332 | } | ||
333 | |||
334 | static void jz_gpio_irq_mask(unsigned int irq) | ||
335 | { | ||
336 | jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_MASK_SET); | ||
337 | }; | ||
338 | |||
339 | static void jz_gpio_irq_unmask(unsigned int irq) | ||
340 | { | ||
341 | struct jz_gpio_chip *chip = irq_to_jz_gpio_chip(irq); | ||
342 | |||
343 | jz_gpio_check_trigger_both(chip, irq); | ||
344 | |||
345 | jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_MASK_CLEAR); | ||
346 | }; | ||
347 | |||
348 | /* TODO: Check if function is gpio */ | ||
349 | static unsigned int jz_gpio_irq_startup(unsigned int irq) | ||
350 | { | ||
351 | struct irq_desc *desc = irq_to_desc(irq); | ||
352 | |||
353 | jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_SELECT_SET); | ||
354 | |||
355 | desc->status &= ~IRQ_MASKED; | ||
356 | jz_gpio_irq_unmask(irq); | ||
357 | |||
358 | return 0; | ||
359 | } | ||
360 | |||
361 | static void jz_gpio_irq_shutdown(unsigned int irq) | ||
362 | { | ||
363 | struct irq_desc *desc = irq_to_desc(irq); | ||
364 | |||
365 | jz_gpio_irq_mask(irq); | ||
366 | desc->status |= IRQ_MASKED; | ||
367 | |||
368 | /* Set direction to input */ | ||
369 | jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_DIRECTION_CLEAR); | ||
370 | jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_SELECT_CLEAR); | ||
371 | } | ||
372 | |||
373 | static void jz_gpio_irq_ack(unsigned int irq) | ||
374 | { | ||
375 | jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_FLAG_CLEAR); | ||
376 | }; | ||
377 | |||
378 | static int jz_gpio_irq_set_type(unsigned int irq, unsigned int flow_type) | ||
379 | { | ||
380 | struct jz_gpio_chip *chip = irq_to_jz_gpio_chip(irq); | ||
381 | struct irq_desc *desc = irq_to_desc(irq); | ||
382 | |||
383 | jz_gpio_irq_mask(irq); | ||
384 | |||
385 | if (flow_type == IRQ_TYPE_EDGE_BOTH) { | ||
386 | uint32_t value = readl(chip->base + JZ_REG_GPIO_PIN); | ||
387 | if (value & IRQ_TO_BIT(irq)) | ||
388 | flow_type = IRQ_TYPE_EDGE_FALLING; | ||
389 | else | ||
390 | flow_type = IRQ_TYPE_EDGE_RISING; | ||
391 | chip->edge_trigger_both |= IRQ_TO_BIT(irq); | ||
392 | } else { | ||
393 | chip->edge_trigger_both &= ~IRQ_TO_BIT(irq); | ||
394 | } | ||
395 | |||
396 | switch (flow_type) { | ||
397 | case IRQ_TYPE_EDGE_RISING: | ||
398 | jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_DIRECTION_SET); | ||
399 | jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_TRIGGER_SET); | ||
400 | break; | ||
401 | case IRQ_TYPE_EDGE_FALLING: | ||
402 | jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_DIRECTION_CLEAR); | ||
403 | jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_TRIGGER_SET); | ||
404 | break; | ||
405 | case IRQ_TYPE_LEVEL_HIGH: | ||
406 | jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_DIRECTION_SET); | ||
407 | jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_TRIGGER_CLEAR); | ||
408 | break; | ||
409 | case IRQ_TYPE_LEVEL_LOW: | ||
410 | jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_DIRECTION_CLEAR); | ||
411 | jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_TRIGGER_CLEAR); | ||
412 | break; | ||
413 | default: | ||
414 | return -EINVAL; | ||
415 | } | ||
416 | |||
417 | if (!(desc->status & IRQ_MASKED)) | ||
418 | jz_gpio_irq_unmask(irq); | ||
419 | |||
420 | return 0; | ||
421 | } | ||
422 | |||
423 | static int jz_gpio_irq_set_wake(unsigned int irq, unsigned int on) | ||
424 | { | ||
425 | struct jz_gpio_chip *chip = irq_to_jz_gpio_chip(irq); | ||
426 | spin_lock(&chip->lock); | ||
427 | if (on) | ||
428 | chip->wakeup |= IRQ_TO_BIT(irq); | ||
429 | else | ||
430 | chip->wakeup &= ~IRQ_TO_BIT(irq); | ||
431 | spin_unlock(&chip->lock); | ||
432 | |||
433 | set_irq_wake(chip->irq, on); | ||
434 | return 0; | ||
435 | } | ||
436 | |||
437 | /* | ||
438 | * This lock class tells lockdep that GPIO irqs are in a different | ||
439 | * category than their parents, so it won't report false recursion. | ||
440 | */ | ||
441 | static struct lock_class_key gpio_lock_class; | ||
442 | |||
443 | #define JZ4740_GPIO_CHIP(_bank) { \ | ||
444 | .irq_base = JZ4740_IRQ_GPIO_BASE_ ## _bank, \ | ||
445 | .gpio_chip = { \ | ||
446 | .label = "Bank " # _bank, \ | ||
447 | .owner = THIS_MODULE, \ | ||
448 | .set = jz_gpio_set_value, \ | ||
449 | .get = jz_gpio_get_value, \ | ||
450 | .direction_output = jz_gpio_direction_output, \ | ||
451 | .direction_input = jz_gpio_direction_input, \ | ||
452 | .base = JZ4740_GPIO_BASE_ ## _bank, \ | ||
453 | .ngpio = JZ4740_GPIO_NUM_ ## _bank, \ | ||
454 | }, \ | ||
455 | .irq_chip = { \ | ||
456 | .name = "GPIO Bank " # _bank, \ | ||
457 | .mask = jz_gpio_irq_mask, \ | ||
458 | .unmask = jz_gpio_irq_unmask, \ | ||
459 | .ack = jz_gpio_irq_ack, \ | ||
460 | .startup = jz_gpio_irq_startup, \ | ||
461 | .shutdown = jz_gpio_irq_shutdown, \ | ||
462 | .set_type = jz_gpio_irq_set_type, \ | ||
463 | .set_wake = jz_gpio_irq_set_wake, \ | ||
464 | }, \ | ||
465 | } | ||
466 | |||
467 | static struct jz_gpio_chip jz4740_gpio_chips[] = { | ||
468 | JZ4740_GPIO_CHIP(A), | ||
469 | JZ4740_GPIO_CHIP(B), | ||
470 | JZ4740_GPIO_CHIP(C), | ||
471 | JZ4740_GPIO_CHIP(D), | ||
472 | }; | ||
473 | |||
474 | static inline struct jz_gpio_chip *sysdev_to_chip(struct sys_device *dev) | ||
475 | { | ||
476 | return container_of(dev, struct jz_gpio_chip, sysdev); | ||
477 | } | ||
478 | |||
479 | static int jz4740_gpio_suspend(struct sys_device *dev, pm_message_t state) | ||
480 | { | ||
481 | struct jz_gpio_chip *chip = sysdev_to_chip(dev); | ||
482 | |||
483 | chip->suspend_mask = readl(chip->base + JZ_REG_GPIO_MASK); | ||
484 | writel(~(chip->wakeup), chip->base + JZ_REG_GPIO_MASK_SET); | ||
485 | writel(chip->wakeup, chip->base + JZ_REG_GPIO_MASK_CLEAR); | ||
486 | |||
487 | return 0; | ||
488 | } | ||
489 | |||
490 | static int jz4740_gpio_resume(struct sys_device *dev) | ||
491 | { | ||
492 | struct jz_gpio_chip *chip = sysdev_to_chip(dev); | ||
493 | uint32_t mask = chip->suspend_mask; | ||
494 | |||
495 | writel(~mask, chip->base + JZ_REG_GPIO_MASK_CLEAR); | ||
496 | writel(mask, chip->base + JZ_REG_GPIO_MASK_SET); | ||
497 | |||
498 | return 0; | ||
499 | } | ||
500 | |||
501 | static struct sysdev_class jz4740_gpio_sysdev_class = { | ||
502 | .name = "gpio", | ||
503 | .suspend = jz4740_gpio_suspend, | ||
504 | .resume = jz4740_gpio_resume, | ||
505 | }; | ||
506 | |||
507 | static int jz4740_gpio_chip_init(struct jz_gpio_chip *chip, unsigned int id) | ||
508 | { | ||
509 | int ret, irq; | ||
510 | |||
511 | chip->sysdev.id = id; | ||
512 | chip->sysdev.cls = &jz4740_gpio_sysdev_class; | ||
513 | ret = sysdev_register(&chip->sysdev); | ||
514 | |||
515 | if (ret) | ||
516 | return ret; | ||
517 | |||
518 | spin_lock_init(&chip->lock); | ||
519 | |||
520 | chip->base = ioremap(JZ4740_GPIO_BASE_ADDR + (id * 0x100), 0x100); | ||
521 | |||
522 | gpiochip_add(&chip->gpio_chip); | ||
523 | |||
524 | chip->irq = JZ4740_IRQ_INTC_GPIO(id); | ||
525 | set_irq_data(chip->irq, chip); | ||
526 | set_irq_chained_handler(chip->irq, jz_gpio_irq_demux_handler); | ||
527 | |||
528 | for (irq = chip->irq_base; irq < chip->irq_base + chip->gpio_chip.ngpio; ++irq) { | ||
529 | lockdep_set_class(&irq_desc[irq].lock, &gpio_lock_class); | ||
530 | set_irq_chip_data(irq, chip); | ||
531 | set_irq_chip_and_handler(irq, &chip->irq_chip, handle_level_irq); | ||
532 | } | ||
533 | |||
534 | return 0; | ||
535 | } | ||
536 | |||
537 | static int __init jz4740_gpio_init(void) | ||
538 | { | ||
539 | unsigned int i; | ||
540 | int ret; | ||
541 | |||
542 | ret = sysdev_class_register(&jz4740_gpio_sysdev_class); | ||
543 | if (ret) | ||
544 | return ret; | ||
545 | |||
546 | for (i = 0; i < ARRAY_SIZE(jz4740_gpio_chips); ++i) | ||
547 | jz4740_gpio_chip_init(&jz4740_gpio_chips[i], i); | ||
548 | |||
549 | printk(KERN_INFO "JZ4740 GPIO initalized\n"); | ||
550 | |||
551 | return 0; | ||
552 | } | ||
553 | arch_initcall(jz4740_gpio_init); | ||
554 | |||
555 | #ifdef CONFIG_DEBUG_FS | ||
556 | |||
557 | static inline void gpio_seq_reg(struct seq_file *s, struct jz_gpio_chip *chip, | ||
558 | const char *name, unsigned int reg) | ||
559 | { | ||
560 | seq_printf(s, "\t%s: %08x\n", name, readl(chip->base + reg)); | ||
561 | } | ||
562 | |||
563 | static int gpio_regs_show(struct seq_file *s, void *unused) | ||
564 | { | ||
565 | struct jz_gpio_chip *chip = jz4740_gpio_chips; | ||
566 | int i; | ||
567 | |||
568 | for (i = 0; i < ARRAY_SIZE(jz4740_gpio_chips); ++i, ++chip) { | ||
569 | seq_printf(s, "==GPIO %d==\n", i); | ||
570 | gpio_seq_reg(s, chip, "Pin", JZ_REG_GPIO_PIN); | ||
571 | gpio_seq_reg(s, chip, "Data", JZ_REG_GPIO_DATA); | ||
572 | gpio_seq_reg(s, chip, "Mask", JZ_REG_GPIO_MASK); | ||
573 | gpio_seq_reg(s, chip, "Pull", JZ_REG_GPIO_PULL); | ||
574 | gpio_seq_reg(s, chip, "Func", JZ_REG_GPIO_FUNC); | ||
575 | gpio_seq_reg(s, chip, "Select", JZ_REG_GPIO_SELECT); | ||
576 | gpio_seq_reg(s, chip, "Direction", JZ_REG_GPIO_DIRECTION); | ||
577 | gpio_seq_reg(s, chip, "Trigger", JZ_REG_GPIO_TRIGGER); | ||
578 | gpio_seq_reg(s, chip, "Flag", JZ_REG_GPIO_FLAG); | ||
579 | } | ||
580 | |||
581 | return 0; | ||
582 | } | ||
583 | |||
584 | static int gpio_regs_open(struct inode *inode, struct file *file) | ||
585 | { | ||
586 | return single_open(file, gpio_regs_show, NULL); | ||
587 | } | ||
588 | |||
589 | static const struct file_operations gpio_regs_operations = { | ||
590 | .open = gpio_regs_open, | ||
591 | .read = seq_read, | ||
592 | .llseek = seq_lseek, | ||
593 | .release = single_release, | ||
594 | }; | ||
595 | |||
596 | static int __init gpio_debugfs_init(void) | ||
597 | { | ||
598 | (void) debugfs_create_file("jz_regs_gpio", S_IFREG | S_IRUGO, | ||
599 | NULL, NULL, &gpio_regs_operations); | ||
600 | return 0; | ||
601 | } | ||
602 | subsys_initcall(gpio_debugfs_init); | ||
603 | |||
604 | #endif | ||