]>
Commit | Line | Data |
---|---|---|
a55f4506 LPC |
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 | ||
b595076a | 549 | printk(KERN_INFO "JZ4740 GPIO initialized\n"); |
a55f4506 LPC |
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 |