Root/
1 | /* |
2 | * GPIO Abstraction Layer |
3 | * |
4 | * Copyright 2006-2010 Analog Devices Inc. |
5 | * |
6 | * Licensed under the GPL-2 or later |
7 | */ |
8 | |
9 | #include <linux/delay.h> |
10 | #include <linux/module.h> |
11 | #include <linux/err.h> |
12 | #include <linux/proc_fs.h> |
13 | #include <asm/blackfin.h> |
14 | #include <asm/gpio.h> |
15 | #include <asm/portmux.h> |
16 | #include <linux/irq.h> |
17 | |
18 | #if ANOMALY_05000311 || ANOMALY_05000323 |
19 | enum { |
20 | AWA_data = SYSCR, |
21 | AWA_data_clear = SYSCR, |
22 | AWA_data_set = SYSCR, |
23 | AWA_toggle = SYSCR, |
24 | AWA_maska = BFIN_UART_SCR, |
25 | AWA_maska_clear = BFIN_UART_SCR, |
26 | AWA_maska_set = BFIN_UART_SCR, |
27 | AWA_maska_toggle = BFIN_UART_SCR, |
28 | AWA_maskb = BFIN_UART_GCTL, |
29 | AWA_maskb_clear = BFIN_UART_GCTL, |
30 | AWA_maskb_set = BFIN_UART_GCTL, |
31 | AWA_maskb_toggle = BFIN_UART_GCTL, |
32 | AWA_dir = SPORT1_STAT, |
33 | AWA_polar = SPORT1_STAT, |
34 | AWA_edge = SPORT1_STAT, |
35 | AWA_both = SPORT1_STAT, |
36 | #if ANOMALY_05000311 |
37 | AWA_inen = TIMER_ENABLE, |
38 | #elif ANOMALY_05000323 |
39 | AWA_inen = DMA1_1_CONFIG, |
40 | #endif |
41 | }; |
42 | /* Anomaly Workaround */ |
43 | #define AWA_DUMMY_READ(name) bfin_read16(AWA_ ## name) |
44 | #else |
45 | #define AWA_DUMMY_READ(...) do { } while (0) |
46 | #endif |
47 | |
48 | static struct gpio_port_t * const gpio_array[] = { |
49 | #if defined(BF533_FAMILY) || defined(BF538_FAMILY) |
50 | (struct gpio_port_t *) FIO_FLAG_D, |
51 | #elif defined(CONFIG_BF52x) || defined(BF537_FAMILY) || defined(CONFIG_BF51x) |
52 | (struct gpio_port_t *) PORTFIO, |
53 | (struct gpio_port_t *) PORTGIO, |
54 | (struct gpio_port_t *) PORTHIO, |
55 | #elif defined(BF561_FAMILY) |
56 | (struct gpio_port_t *) FIO0_FLAG_D, |
57 | (struct gpio_port_t *) FIO1_FLAG_D, |
58 | (struct gpio_port_t *) FIO2_FLAG_D, |
59 | #elif defined(CONFIG_BF54x) |
60 | (struct gpio_port_t *)PORTA_FER, |
61 | (struct gpio_port_t *)PORTB_FER, |
62 | (struct gpio_port_t *)PORTC_FER, |
63 | (struct gpio_port_t *)PORTD_FER, |
64 | (struct gpio_port_t *)PORTE_FER, |
65 | (struct gpio_port_t *)PORTF_FER, |
66 | (struct gpio_port_t *)PORTG_FER, |
67 | (struct gpio_port_t *)PORTH_FER, |
68 | (struct gpio_port_t *)PORTI_FER, |
69 | (struct gpio_port_t *)PORTJ_FER, |
70 | #else |
71 | # error no gpio arrays defined |
72 | #endif |
73 | }; |
74 | |
75 | #if defined(CONFIG_BF52x) || defined(BF537_FAMILY) || defined(CONFIG_BF51x) |
76 | static unsigned short * const port_fer[] = { |
77 | (unsigned short *) PORTF_FER, |
78 | (unsigned short *) PORTG_FER, |
79 | (unsigned short *) PORTH_FER, |
80 | }; |
81 | |
82 | # if !defined(BF537_FAMILY) |
83 | static unsigned short * const port_mux[] = { |
84 | (unsigned short *) PORTF_MUX, |
85 | (unsigned short *) PORTG_MUX, |
86 | (unsigned short *) PORTH_MUX, |
87 | }; |
88 | |
89 | static const |
90 | u8 pmux_offset[][16] = { |
91 | # if defined(CONFIG_BF52x) |
92 | { 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 4, 6, 8, 8, 10, 10 }, /* PORTF */ |
93 | { 0, 0, 0, 0, 0, 2, 2, 4, 4, 6, 8, 10, 10, 10, 12, 12 }, /* PORTG */ |
94 | { 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 4, 4, 4, 4, 4, 4 }, /* PORTH */ |
95 | # elif defined(CONFIG_BF51x) |
96 | { 0, 2, 2, 2, 2, 2, 2, 4, 6, 6, 6, 8, 8, 8, 8, 10 }, /* PORTF */ |
97 | { 0, 0, 0, 2, 4, 6, 6, 6, 8, 10, 10, 12, 14, 14, 14, 14 }, /* PORTG */ |
98 | { 0, 0, 0, 0, 2, 2, 4, 6, 10, 10, 10, 10, 10, 10, 10, 10 }, /* PORTH */ |
99 | # endif |
100 | }; |
101 | # endif |
102 | |
103 | #elif defined(BF538_FAMILY) |
104 | static unsigned short * const port_fer[] = { |
105 | (unsigned short *) PORTCIO_FER, |
106 | (unsigned short *) PORTDIO_FER, |
107 | (unsigned short *) PORTEIO_FER, |
108 | }; |
109 | #endif |
110 | |
111 | #define RESOURCE_LABEL_SIZE 16 |
112 | |
113 | static struct str_ident { |
114 | char name[RESOURCE_LABEL_SIZE]; |
115 | } str_ident[MAX_RESOURCES]; |
116 | |
117 | #if defined(CONFIG_PM) |
118 | static struct gpio_port_s gpio_bank_saved[GPIO_BANK_NUM]; |
119 | #endif |
120 | |
121 | static void gpio_error(unsigned gpio) |
122 | { |
123 | printk(KERN_ERR "bfin-gpio: GPIO %d wasn't requested!\n", gpio); |
124 | } |
125 | |
126 | static void set_label(unsigned short ident, const char *label) |
127 | { |
128 | if (label) { |
129 | strncpy(str_ident[ident].name, label, |
130 | RESOURCE_LABEL_SIZE); |
131 | str_ident[ident].name[RESOURCE_LABEL_SIZE - 1] = 0; |
132 | } |
133 | } |
134 | |
135 | static char *get_label(unsigned short ident) |
136 | { |
137 | return (*str_ident[ident].name ? str_ident[ident].name : "UNKNOWN"); |
138 | } |
139 | |
140 | static int cmp_label(unsigned short ident, const char *label) |
141 | { |
142 | if (label == NULL) { |
143 | dump_stack(); |
144 | printk(KERN_ERR "Please provide none-null label\n"); |
145 | } |
146 | |
147 | if (label) |
148 | return strcmp(str_ident[ident].name, label); |
149 | else |
150 | return -EINVAL; |
151 | } |
152 | |
153 | #define map_entry(m, i) reserved_##m##_map[gpio_bank(i)] |
154 | #define is_reserved(m, i, e) (map_entry(m, i) & gpio_bit(i)) |
155 | #define reserve(m, i) (map_entry(m, i) |= gpio_bit(i)) |
156 | #define unreserve(m, i) (map_entry(m, i) &= ~gpio_bit(i)) |
157 | #define DECLARE_RESERVED_MAP(m, c) static unsigned short reserved_##m##_map[c] |
158 | |
159 | DECLARE_RESERVED_MAP(gpio, GPIO_BANK_NUM); |
160 | DECLARE_RESERVED_MAP(peri, DIV_ROUND_UP(MAX_RESOURCES, GPIO_BANKSIZE)); |
161 | DECLARE_RESERVED_MAP(gpio_irq, GPIO_BANK_NUM); |
162 | |
163 | inline int check_gpio(unsigned gpio) |
164 | { |
165 | #if defined(CONFIG_BF54x) |
166 | if (gpio == GPIO_PB15 || gpio == GPIO_PC14 || gpio == GPIO_PC15 |
167 | || gpio == GPIO_PH14 || gpio == GPIO_PH15 |
168 | || gpio == GPIO_PJ14 || gpio == GPIO_PJ15) |
169 | return -EINVAL; |
170 | #endif |
171 | if (gpio >= MAX_BLACKFIN_GPIOS) |
172 | return -EINVAL; |
173 | return 0; |
174 | } |
175 | |
176 | static void port_setup(unsigned gpio, unsigned short usage) |
177 | { |
178 | #if defined(BF538_FAMILY) |
179 | /* |
180 | * BF538/9 Port C,D and E are special. |
181 | * Inverted PORT_FER polarity on CDE and no PORF_FER on F |
182 | * Regular PORT F GPIOs are handled here, CDE are exclusively |
183 | * managed by GPIOLIB |
184 | */ |
185 | |
186 | if (gpio < MAX_BLACKFIN_GPIOS || gpio >= MAX_RESOURCES) |
187 | return; |
188 | |
189 | gpio -= MAX_BLACKFIN_GPIOS; |
190 | |
191 | if (usage == GPIO_USAGE) |
192 | *port_fer[gpio_bank(gpio)] |= gpio_bit(gpio); |
193 | else |
194 | *port_fer[gpio_bank(gpio)] &= ~gpio_bit(gpio); |
195 | SSYNC(); |
196 | return; |
197 | #endif |
198 | |
199 | if (check_gpio(gpio)) |
200 | return; |
201 | |
202 | #if defined(CONFIG_BF52x) || defined(BF537_FAMILY) || defined(CONFIG_BF51x) |
203 | if (usage == GPIO_USAGE) |
204 | *port_fer[gpio_bank(gpio)] &= ~gpio_bit(gpio); |
205 | else |
206 | *port_fer[gpio_bank(gpio)] |= gpio_bit(gpio); |
207 | SSYNC(); |
208 | #elif defined(CONFIG_BF54x) |
209 | if (usage == GPIO_USAGE) |
210 | gpio_array[gpio_bank(gpio)]->port_fer &= ~gpio_bit(gpio); |
211 | else |
212 | gpio_array[gpio_bank(gpio)]->port_fer |= gpio_bit(gpio); |
213 | SSYNC(); |
214 | #endif |
215 | } |
216 | |
217 | #ifdef BF537_FAMILY |
218 | static const s8 port_mux[] = { |
219 | [GPIO_PF0] = 3, |
220 | [GPIO_PF1] = 3, |
221 | [GPIO_PF2] = 4, |
222 | [GPIO_PF3] = 4, |
223 | [GPIO_PF4] = 5, |
224 | [GPIO_PF5] = 6, |
225 | [GPIO_PF6] = 7, |
226 | [GPIO_PF7] = 8, |
227 | [GPIO_PF8 ... GPIO_PF15] = -1, |
228 | [GPIO_PG0 ... GPIO_PG7] = -1, |
229 | [GPIO_PG8] = 9, |
230 | [GPIO_PG9] = 9, |
231 | [GPIO_PG10] = 10, |
232 | [GPIO_PG11] = 10, |
233 | [GPIO_PG12] = 10, |
234 | [GPIO_PG13] = 11, |
235 | [GPIO_PG14] = 11, |
236 | [GPIO_PG15] = 11, |
237 | [GPIO_PH0 ... GPIO_PH15] = -1, |
238 | [PORT_PJ0 ... PORT_PJ3] = -1, |
239 | [PORT_PJ4] = 1, |
240 | [PORT_PJ5] = 1, |
241 | [PORT_PJ6 ... PORT_PJ9] = -1, |
242 | [PORT_PJ10] = 0, |
243 | [PORT_PJ11] = 0, |
244 | }; |
245 | |
246 | static int portmux_group_check(unsigned short per) |
247 | { |
248 | u16 ident = P_IDENT(per); |
249 | u16 function = P_FUNCT2MUX(per); |
250 | s8 offset = port_mux[ident]; |
251 | u16 m, pmux, pfunc; |
252 | |
253 | if (offset < 0) |
254 | return 0; |
255 | |
256 | pmux = bfin_read_PORT_MUX(); |
257 | for (m = 0; m < ARRAY_SIZE(port_mux); ++m) { |
258 | if (m == ident) |
259 | continue; |
260 | if (port_mux[m] != offset) |
261 | continue; |
262 | if (!is_reserved(peri, m, 1)) |
263 | continue; |
264 | |
265 | if (offset == 1) |
266 | pfunc = (pmux >> offset) & 3; |
267 | else |
268 | pfunc = (pmux >> offset) & 1; |
269 | if (pfunc != function) { |
270 | pr_err("pin group conflict! request pin %d func %d conflict with pin %d func %d\n", |
271 | ident, function, m, pfunc); |
272 | return -EINVAL; |
273 | } |
274 | } |
275 | |
276 | return 0; |
277 | } |
278 | |
279 | static void portmux_setup(unsigned short per) |
280 | { |
281 | u16 ident = P_IDENT(per); |
282 | u16 function = P_FUNCT2MUX(per); |
283 | s8 offset = port_mux[ident]; |
284 | u16 pmux; |
285 | |
286 | if (offset == -1) |
287 | return; |
288 | |
289 | pmux = bfin_read_PORT_MUX(); |
290 | if (offset != 1) |
291 | pmux &= ~(1 << offset); |
292 | else |
293 | pmux &= ~(3 << 1); |
294 | pmux |= (function << offset); |
295 | bfin_write_PORT_MUX(pmux); |
296 | } |
297 | #elif defined(CONFIG_BF54x) |
298 | inline void portmux_setup(unsigned short per) |
299 | { |
300 | u16 ident = P_IDENT(per); |
301 | u16 function = P_FUNCT2MUX(per); |
302 | u32 pmux; |
303 | |
304 | pmux = gpio_array[gpio_bank(ident)]->port_mux; |
305 | |
306 | pmux &= ~(0x3 << (2 * gpio_sub_n(ident))); |
307 | pmux |= (function & 0x3) << (2 * gpio_sub_n(ident)); |
308 | |
309 | gpio_array[gpio_bank(ident)]->port_mux = pmux; |
310 | } |
311 | |
312 | inline u16 get_portmux(unsigned short per) |
313 | { |
314 | u16 ident = P_IDENT(per); |
315 | u32 pmux = gpio_array[gpio_bank(ident)]->port_mux; |
316 | return (pmux >> (2 * gpio_sub_n(ident)) & 0x3); |
317 | } |
318 | static int portmux_group_check(unsigned short per) |
319 | { |
320 | return 0; |
321 | } |
322 | #elif defined(CONFIG_BF52x) || defined(CONFIG_BF51x) |
323 | static int portmux_group_check(unsigned short per) |
324 | { |
325 | u16 ident = P_IDENT(per); |
326 | u16 function = P_FUNCT2MUX(per); |
327 | u8 offset = pmux_offset[gpio_bank(ident)][gpio_sub_n(ident)]; |
328 | u16 pin, gpiopin, pfunc; |
329 | |
330 | for (pin = 0; pin < GPIO_BANKSIZE; ++pin) { |
331 | if (offset != pmux_offset[gpio_bank(ident)][pin]) |
332 | continue; |
333 | |
334 | gpiopin = gpio_bank(ident) * GPIO_BANKSIZE + pin; |
335 | if (gpiopin == ident) |
336 | continue; |
337 | if (!is_reserved(peri, gpiopin, 1)) |
338 | continue; |
339 | |
340 | pfunc = *port_mux[gpio_bank(ident)]; |
341 | pfunc = (pfunc >> offset) & 3; |
342 | if (pfunc != function) { |
343 | pr_err("pin group conflict! request pin %d func %d conflict with pin %d func %d\n", |
344 | ident, function, gpiopin, pfunc); |
345 | return -EINVAL; |
346 | } |
347 | } |
348 | |
349 | return 0; |
350 | } |
351 | |
352 | inline void portmux_setup(unsigned short per) |
353 | { |
354 | u16 ident = P_IDENT(per); |
355 | u16 function = P_FUNCT2MUX(per); |
356 | u8 offset = pmux_offset[gpio_bank(ident)][gpio_sub_n(ident)]; |
357 | u16 pmux; |
358 | |
359 | pmux = *port_mux[gpio_bank(ident)]; |
360 | if (((pmux >> offset) & 3) == function) |
361 | return; |
362 | pmux &= ~(3 << offset); |
363 | pmux |= (function & 3) << offset; |
364 | *port_mux[gpio_bank(ident)] = pmux; |
365 | SSYNC(); |
366 | } |
367 | #else |
368 | # define portmux_setup(...) do { } while (0) |
369 | static int portmux_group_check(unsigned short per) |
370 | { |
371 | return 0; |
372 | } |
373 | #endif |
374 | |
375 | #ifndef CONFIG_BF54x |
376 | /*********************************************************** |
377 | * |
378 | * FUNCTIONS: Blackfin General Purpose Ports Access Functions |
379 | * |
380 | * INPUTS/OUTPUTS: |
381 | * gpio - GPIO Number between 0 and MAX_BLACKFIN_GPIOS |
382 | * |
383 | * |
384 | * DESCRIPTION: These functions abstract direct register access |
385 | * to Blackfin processor General Purpose |
386 | * Ports Regsiters |
387 | * |
388 | * CAUTION: These functions do not belong to the GPIO Driver API |
389 | ************************************************************* |
390 | * MODIFICATION HISTORY : |
391 | **************************************************************/ |
392 | |
393 | /* Set a specific bit */ |
394 | |
395 | #define SET_GPIO(name) \ |
396 | void set_gpio_ ## name(unsigned gpio, unsigned short arg) \ |
397 | { \ |
398 | unsigned long flags; \ |
399 | flags = hard_local_irq_save(); \ |
400 | if (arg) \ |
401 | gpio_array[gpio_bank(gpio)]->name |= gpio_bit(gpio); \ |
402 | else \ |
403 | gpio_array[gpio_bank(gpio)]->name &= ~gpio_bit(gpio); \ |
404 | AWA_DUMMY_READ(name); \ |
405 | hard_local_irq_restore(flags); \ |
406 | } \ |
407 | EXPORT_SYMBOL(set_gpio_ ## name); |
408 | |
409 | SET_GPIO(dir) /* set_gpio_dir() */ |
410 | SET_GPIO(inen) /* set_gpio_inen() */ |
411 | SET_GPIO(polar) /* set_gpio_polar() */ |
412 | SET_GPIO(edge) /* set_gpio_edge() */ |
413 | SET_GPIO(both) /* set_gpio_both() */ |
414 | |
415 | |
416 | #define SET_GPIO_SC(name) \ |
417 | void set_gpio_ ## name(unsigned gpio, unsigned short arg) \ |
418 | { \ |
419 | unsigned long flags; \ |
420 | if (ANOMALY_05000311 || ANOMALY_05000323) \ |
421 | flags = hard_local_irq_save(); \ |
422 | if (arg) \ |
423 | gpio_array[gpio_bank(gpio)]->name ## _set = gpio_bit(gpio); \ |
424 | else \ |
425 | gpio_array[gpio_bank(gpio)]->name ## _clear = gpio_bit(gpio); \ |
426 | if (ANOMALY_05000311 || ANOMALY_05000323) { \ |
427 | AWA_DUMMY_READ(name); \ |
428 | hard_local_irq_restore(flags); \ |
429 | } \ |
430 | } \ |
431 | EXPORT_SYMBOL(set_gpio_ ## name); |
432 | |
433 | SET_GPIO_SC(maska) |
434 | SET_GPIO_SC(maskb) |
435 | SET_GPIO_SC(data) |
436 | |
437 | void set_gpio_toggle(unsigned gpio) |
438 | { |
439 | unsigned long flags; |
440 | if (ANOMALY_05000311 || ANOMALY_05000323) |
441 | flags = hard_local_irq_save(); |
442 | gpio_array[gpio_bank(gpio)]->toggle = gpio_bit(gpio); |
443 | if (ANOMALY_05000311 || ANOMALY_05000323) { |
444 | AWA_DUMMY_READ(toggle); |
445 | hard_local_irq_restore(flags); |
446 | } |
447 | } |
448 | EXPORT_SYMBOL(set_gpio_toggle); |
449 | |
450 | |
451 | /*Set current PORT date (16-bit word)*/ |
452 | |
453 | #define SET_GPIO_P(name) \ |
454 | void set_gpiop_ ## name(unsigned gpio, unsigned short arg) \ |
455 | { \ |
456 | unsigned long flags; \ |
457 | if (ANOMALY_05000311 || ANOMALY_05000323) \ |
458 | flags = hard_local_irq_save(); \ |
459 | gpio_array[gpio_bank(gpio)]->name = arg; \ |
460 | if (ANOMALY_05000311 || ANOMALY_05000323) { \ |
461 | AWA_DUMMY_READ(name); \ |
462 | hard_local_irq_restore(flags); \ |
463 | } \ |
464 | } \ |
465 | EXPORT_SYMBOL(set_gpiop_ ## name); |
466 | |
467 | SET_GPIO_P(data) |
468 | SET_GPIO_P(dir) |
469 | SET_GPIO_P(inen) |
470 | SET_GPIO_P(polar) |
471 | SET_GPIO_P(edge) |
472 | SET_GPIO_P(both) |
473 | SET_GPIO_P(maska) |
474 | SET_GPIO_P(maskb) |
475 | |
476 | /* Get a specific bit */ |
477 | #define GET_GPIO(name) \ |
478 | unsigned short get_gpio_ ## name(unsigned gpio) \ |
479 | { \ |
480 | unsigned long flags; \ |
481 | unsigned short ret; \ |
482 | if (ANOMALY_05000311 || ANOMALY_05000323) \ |
483 | flags = hard_local_irq_save(); \ |
484 | ret = 0x01 & (gpio_array[gpio_bank(gpio)]->name >> gpio_sub_n(gpio)); \ |
485 | if (ANOMALY_05000311 || ANOMALY_05000323) { \ |
486 | AWA_DUMMY_READ(name); \ |
487 | hard_local_irq_restore(flags); \ |
488 | } \ |
489 | return ret; \ |
490 | } \ |
491 | EXPORT_SYMBOL(get_gpio_ ## name); |
492 | |
493 | GET_GPIO(data) |
494 | GET_GPIO(dir) |
495 | GET_GPIO(inen) |
496 | GET_GPIO(polar) |
497 | GET_GPIO(edge) |
498 | GET_GPIO(both) |
499 | GET_GPIO(maska) |
500 | GET_GPIO(maskb) |
501 | |
502 | /*Get current PORT date (16-bit word)*/ |
503 | |
504 | #define GET_GPIO_P(name) \ |
505 | unsigned short get_gpiop_ ## name(unsigned gpio) \ |
506 | { \ |
507 | unsigned long flags; \ |
508 | unsigned short ret; \ |
509 | if (ANOMALY_05000311 || ANOMALY_05000323) \ |
510 | flags = hard_local_irq_save(); \ |
511 | ret = (gpio_array[gpio_bank(gpio)]->name); \ |
512 | if (ANOMALY_05000311 || ANOMALY_05000323) { \ |
513 | AWA_DUMMY_READ(name); \ |
514 | hard_local_irq_restore(flags); \ |
515 | } \ |
516 | return ret; \ |
517 | } \ |
518 | EXPORT_SYMBOL(get_gpiop_ ## name); |
519 | |
520 | GET_GPIO_P(data) |
521 | GET_GPIO_P(dir) |
522 | GET_GPIO_P(inen) |
523 | GET_GPIO_P(polar) |
524 | GET_GPIO_P(edge) |
525 | GET_GPIO_P(both) |
526 | GET_GPIO_P(maska) |
527 | GET_GPIO_P(maskb) |
528 | |
529 | |
530 | #ifdef CONFIG_PM |
531 | DECLARE_RESERVED_MAP(wakeup, GPIO_BANK_NUM); |
532 | |
533 | static const unsigned int sic_iwr_irqs[] = { |
534 | #if defined(BF533_FAMILY) |
535 | IRQ_PROG_INTB |
536 | #elif defined(BF537_FAMILY) |
537 | IRQ_PROG_INTB, IRQ_PORTG_INTB, IRQ_MAC_TX |
538 | #elif defined(BF538_FAMILY) |
539 | IRQ_PORTF_INTB |
540 | #elif defined(CONFIG_BF52x) || defined(CONFIG_BF51x) |
541 | IRQ_PORTF_INTB, IRQ_PORTG_INTB, IRQ_PORTH_INTB |
542 | #elif defined(BF561_FAMILY) |
543 | IRQ_PROG0_INTB, IRQ_PROG1_INTB, IRQ_PROG2_INTB |
544 | #else |
545 | # error no SIC_IWR defined |
546 | #endif |
547 | }; |
548 | |
549 | /*********************************************************** |
550 | * |
551 | * FUNCTIONS: Blackfin PM Setup API |
552 | * |
553 | * INPUTS/OUTPUTS: |
554 | * gpio - GPIO Number between 0 and MAX_BLACKFIN_GPIOS |
555 | * type - |
556 | * PM_WAKE_RISING |
557 | * PM_WAKE_FALLING |
558 | * PM_WAKE_HIGH |
559 | * PM_WAKE_LOW |
560 | * PM_WAKE_BOTH_EDGES |
561 | * |
562 | * DESCRIPTION: Blackfin PM Driver API |
563 | * |
564 | * CAUTION: |
565 | ************************************************************* |
566 | * MODIFICATION HISTORY : |
567 | **************************************************************/ |
568 | int gpio_pm_wakeup_ctrl(unsigned gpio, unsigned ctrl) |
569 | { |
570 | unsigned long flags; |
571 | |
572 | if (check_gpio(gpio) < 0) |
573 | return -EINVAL; |
574 | |
575 | flags = hard_local_irq_save(); |
576 | if (ctrl) |
577 | reserve(wakeup, gpio); |
578 | else |
579 | unreserve(wakeup, gpio); |
580 | |
581 | set_gpio_maskb(gpio, ctrl); |
582 | hard_local_irq_restore(flags); |
583 | |
584 | return 0; |
585 | } |
586 | |
587 | int bfin_pm_standby_ctrl(unsigned ctrl) |
588 | { |
589 | u16 bank, mask, i; |
590 | |
591 | for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) { |
592 | mask = map_entry(wakeup, i); |
593 | bank = gpio_bank(i); |
594 | |
595 | if (mask) |
596 | bfin_internal_set_wake(sic_iwr_irqs[bank], ctrl); |
597 | } |
598 | return 0; |
599 | } |
600 | |
601 | void bfin_gpio_pm_hibernate_suspend(void) |
602 | { |
603 | int i, bank; |
604 | |
605 | for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) { |
606 | bank = gpio_bank(i); |
607 | |
608 | #if defined(CONFIG_BF52x) || defined(BF537_FAMILY) || defined(CONFIG_BF51x) |
609 | gpio_bank_saved[bank].fer = *port_fer[bank]; |
610 | #if defined(CONFIG_BF52x) || defined(CONFIG_BF51x) |
611 | gpio_bank_saved[bank].mux = *port_mux[bank]; |
612 | #else |
613 | if (bank == 0) |
614 | gpio_bank_saved[bank].mux = bfin_read_PORT_MUX(); |
615 | #endif |
616 | #endif |
617 | gpio_bank_saved[bank].data = gpio_array[bank]->data; |
618 | gpio_bank_saved[bank].inen = gpio_array[bank]->inen; |
619 | gpio_bank_saved[bank].polar = gpio_array[bank]->polar; |
620 | gpio_bank_saved[bank].dir = gpio_array[bank]->dir; |
621 | gpio_bank_saved[bank].edge = gpio_array[bank]->edge; |
622 | gpio_bank_saved[bank].both = gpio_array[bank]->both; |
623 | gpio_bank_saved[bank].maska = gpio_array[bank]->maska; |
624 | } |
625 | |
626 | AWA_DUMMY_READ(maska); |
627 | } |
628 | |
629 | void bfin_gpio_pm_hibernate_restore(void) |
630 | { |
631 | int i, bank; |
632 | |
633 | for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) { |
634 | bank = gpio_bank(i); |
635 | |
636 | #if defined(CONFIG_BF52x) || defined(BF537_FAMILY) || defined(CONFIG_BF51x) |
637 | #if defined(CONFIG_BF52x) || defined(CONFIG_BF51x) |
638 | *port_mux[bank] = gpio_bank_saved[bank].mux; |
639 | #else |
640 | if (bank == 0) |
641 | bfin_write_PORT_MUX(gpio_bank_saved[bank].mux); |
642 | #endif |
643 | *port_fer[bank] = gpio_bank_saved[bank].fer; |
644 | #endif |
645 | gpio_array[bank]->inen = gpio_bank_saved[bank].inen; |
646 | gpio_array[bank]->data_set = gpio_bank_saved[bank].data |
647 | & gpio_bank_saved[bank].dir; |
648 | gpio_array[bank]->dir = gpio_bank_saved[bank].dir; |
649 | gpio_array[bank]->polar = gpio_bank_saved[bank].polar; |
650 | gpio_array[bank]->edge = gpio_bank_saved[bank].edge; |
651 | gpio_array[bank]->both = gpio_bank_saved[bank].both; |
652 | gpio_array[bank]->maska = gpio_bank_saved[bank].maska; |
653 | } |
654 | AWA_DUMMY_READ(maska); |
655 | } |
656 | |
657 | |
658 | #endif |
659 | #else /* CONFIG_BF54x */ |
660 | #ifdef CONFIG_PM |
661 | |
662 | int bfin_pm_standby_ctrl(unsigned ctrl) |
663 | { |
664 | return 0; |
665 | } |
666 | |
667 | void bfin_gpio_pm_hibernate_suspend(void) |
668 | { |
669 | int i, bank; |
670 | |
671 | for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) { |
672 | bank = gpio_bank(i); |
673 | |
674 | gpio_bank_saved[bank].fer = gpio_array[bank]->port_fer; |
675 | gpio_bank_saved[bank].mux = gpio_array[bank]->port_mux; |
676 | gpio_bank_saved[bank].data = gpio_array[bank]->data; |
677 | gpio_bank_saved[bank].inen = gpio_array[bank]->inen; |
678 | gpio_bank_saved[bank].dir = gpio_array[bank]->dir_set; |
679 | } |
680 | } |
681 | |
682 | void bfin_gpio_pm_hibernate_restore(void) |
683 | { |
684 | int i, bank; |
685 | |
686 | for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) { |
687 | bank = gpio_bank(i); |
688 | |
689 | gpio_array[bank]->port_mux = gpio_bank_saved[bank].mux; |
690 | gpio_array[bank]->port_fer = gpio_bank_saved[bank].fer; |
691 | gpio_array[bank]->inen = gpio_bank_saved[bank].inen; |
692 | gpio_array[bank]->dir_set = gpio_bank_saved[bank].dir; |
693 | gpio_array[bank]->data_set = gpio_bank_saved[bank].data |
694 | | gpio_bank_saved[bank].dir; |
695 | } |
696 | } |
697 | #endif |
698 | |
699 | unsigned short get_gpio_dir(unsigned gpio) |
700 | { |
701 | return (0x01 & (gpio_array[gpio_bank(gpio)]->dir_clear >> gpio_sub_n(gpio))); |
702 | } |
703 | EXPORT_SYMBOL(get_gpio_dir); |
704 | |
705 | #endif /* CONFIG_BF54x */ |
706 | |
707 | /*********************************************************** |
708 | * |
709 | * FUNCTIONS: Blackfin Peripheral Resource Allocation |
710 | * and PortMux Setup |
711 | * |
712 | * INPUTS/OUTPUTS: |
713 | * per Peripheral Identifier |
714 | * label String |
715 | * |
716 | * DESCRIPTION: Blackfin Peripheral Resource Allocation and Setup API |
717 | * |
718 | * CAUTION: |
719 | ************************************************************* |
720 | * MODIFICATION HISTORY : |
721 | **************************************************************/ |
722 | |
723 | int peripheral_request(unsigned short per, const char *label) |
724 | { |
725 | unsigned long flags; |
726 | unsigned short ident = P_IDENT(per); |
727 | |
728 | /* |
729 | * Don't cares are pins with only one dedicated function |
730 | */ |
731 | |
732 | if (per & P_DONTCARE) |
733 | return 0; |
734 | |
735 | if (!(per & P_DEFINED)) |
736 | return -ENODEV; |
737 | |
738 | BUG_ON(ident >= MAX_RESOURCES); |
739 | |
740 | flags = hard_local_irq_save(); |
741 | |
742 | /* If a pin can be muxed as either GPIO or peripheral, make |
743 | * sure it is not already a GPIO pin when we request it. |
744 | */ |
745 | if (unlikely(!check_gpio(ident) && is_reserved(gpio, ident, 1))) { |
746 | if (system_state == SYSTEM_BOOTING) |
747 | dump_stack(); |
748 | printk(KERN_ERR |
749 | "%s: Peripheral %d is already reserved as GPIO by %s !\n", |
750 | __func__, ident, get_label(ident)); |
751 | hard_local_irq_restore(flags); |
752 | return -EBUSY; |
753 | } |
754 | |
755 | if (unlikely(is_reserved(peri, ident, 1))) { |
756 | |
757 | /* |
758 | * Pin functions like AMC address strobes my |
759 | * be requested and used by several drivers |
760 | */ |
761 | |
762 | #ifdef CONFIG_BF54x |
763 | if (!((per & P_MAYSHARE) && get_portmux(per) == P_FUNCT2MUX(per))) { |
764 | #else |
765 | if (!(per & P_MAYSHARE)) { |
766 | #endif |
767 | /* |
768 | * Allow that the identical pin function can |
769 | * be requested from the same driver twice |
770 | */ |
771 | |
772 | if (cmp_label(ident, label) == 0) |
773 | goto anyway; |
774 | |
775 | if (system_state == SYSTEM_BOOTING) |
776 | dump_stack(); |
777 | printk(KERN_ERR |
778 | "%s: Peripheral %d function %d is already reserved by %s !\n", |
779 | __func__, ident, P_FUNCT2MUX(per), get_label(ident)); |
780 | hard_local_irq_restore(flags); |
781 | return -EBUSY; |
782 | } |
783 | } |
784 | |
785 | if (unlikely(portmux_group_check(per))) { |
786 | hard_local_irq_restore(flags); |
787 | return -EBUSY; |
788 | } |
789 | anyway: |
790 | reserve(peri, ident); |
791 | |
792 | portmux_setup(per); |
793 | port_setup(ident, PERIPHERAL_USAGE); |
794 | |
795 | hard_local_irq_restore(flags); |
796 | set_label(ident, label); |
797 | |
798 | return 0; |
799 | } |
800 | EXPORT_SYMBOL(peripheral_request); |
801 | |
802 | int peripheral_request_list(const unsigned short per[], const char *label) |
803 | { |
804 | u16 cnt; |
805 | int ret; |
806 | |
807 | for (cnt = 0; per[cnt] != 0; cnt++) { |
808 | |
809 | ret = peripheral_request(per[cnt], label); |
810 | |
811 | if (ret < 0) { |
812 | for ( ; cnt > 0; cnt--) |
813 | peripheral_free(per[cnt - 1]); |
814 | |
815 | return ret; |
816 | } |
817 | } |
818 | |
819 | return 0; |
820 | } |
821 | EXPORT_SYMBOL(peripheral_request_list); |
822 | |
823 | void peripheral_free(unsigned short per) |
824 | { |
825 | unsigned long flags; |
826 | unsigned short ident = P_IDENT(per); |
827 | |
828 | if (per & P_DONTCARE) |
829 | return; |
830 | |
831 | if (!(per & P_DEFINED)) |
832 | return; |
833 | |
834 | flags = hard_local_irq_save(); |
835 | |
836 | if (unlikely(!is_reserved(peri, ident, 0))) { |
837 | hard_local_irq_restore(flags); |
838 | return; |
839 | } |
840 | |
841 | if (!(per & P_MAYSHARE)) |
842 | port_setup(ident, GPIO_USAGE); |
843 | |
844 | unreserve(peri, ident); |
845 | |
846 | set_label(ident, "free"); |
847 | |
848 | hard_local_irq_restore(flags); |
849 | } |
850 | EXPORT_SYMBOL(peripheral_free); |
851 | |
852 | void peripheral_free_list(const unsigned short per[]) |
853 | { |
854 | u16 cnt; |
855 | for (cnt = 0; per[cnt] != 0; cnt++) |
856 | peripheral_free(per[cnt]); |
857 | } |
858 | EXPORT_SYMBOL(peripheral_free_list); |
859 | |
860 | /*********************************************************** |
861 | * |
862 | * FUNCTIONS: Blackfin GPIO Driver |
863 | * |
864 | * INPUTS/OUTPUTS: |
865 | * gpio PIO Number between 0 and MAX_BLACKFIN_GPIOS |
866 | * label String |
867 | * |
868 | * DESCRIPTION: Blackfin GPIO Driver API |
869 | * |
870 | * CAUTION: |
871 | ************************************************************* |
872 | * MODIFICATION HISTORY : |
873 | **************************************************************/ |
874 | |
875 | int bfin_gpio_request(unsigned gpio, const char *label) |
876 | { |
877 | unsigned long flags; |
878 | |
879 | if (check_gpio(gpio) < 0) |
880 | return -EINVAL; |
881 | |
882 | flags = hard_local_irq_save(); |
883 | |
884 | /* |
885 | * Allow that the identical GPIO can |
886 | * be requested from the same driver twice |
887 | * Do nothing and return - |
888 | */ |
889 | |
890 | if (cmp_label(gpio, label) == 0) { |
891 | hard_local_irq_restore(flags); |
892 | return 0; |
893 | } |
894 | |
895 | if (unlikely(is_reserved(gpio, gpio, 1))) { |
896 | if (system_state == SYSTEM_BOOTING) |
897 | dump_stack(); |
898 | printk(KERN_ERR "bfin-gpio: GPIO %d is already reserved by %s !\n", |
899 | gpio, get_label(gpio)); |
900 | hard_local_irq_restore(flags); |
901 | return -EBUSY; |
902 | } |
903 | if (unlikely(is_reserved(peri, gpio, 1))) { |
904 | if (system_state == SYSTEM_BOOTING) |
905 | dump_stack(); |
906 | printk(KERN_ERR |
907 | "bfin-gpio: GPIO %d is already reserved as Peripheral by %s !\n", |
908 | gpio, get_label(gpio)); |
909 | hard_local_irq_restore(flags); |
910 | return -EBUSY; |
911 | } |
912 | if (unlikely(is_reserved(gpio_irq, gpio, 1))) { |
913 | printk(KERN_NOTICE "bfin-gpio: GPIO %d is already reserved as gpio-irq!" |
914 | " (Documentation/blackfin/bfin-gpio-notes.txt)\n", gpio); |
915 | } |
916 | #ifndef CONFIG_BF54x |
917 | else { /* Reset POLAR setting when acquiring a gpio for the first time */ |
918 | set_gpio_polar(gpio, 0); |
919 | } |
920 | #endif |
921 | |
922 | reserve(gpio, gpio); |
923 | set_label(gpio, label); |
924 | |
925 | hard_local_irq_restore(flags); |
926 | |
927 | port_setup(gpio, GPIO_USAGE); |
928 | |
929 | return 0; |
930 | } |
931 | EXPORT_SYMBOL(bfin_gpio_request); |
932 | |
933 | void bfin_gpio_free(unsigned gpio) |
934 | { |
935 | unsigned long flags; |
936 | |
937 | if (check_gpio(gpio) < 0) |
938 | return; |
939 | |
940 | might_sleep(); |
941 | |
942 | flags = hard_local_irq_save(); |
943 | |
944 | if (unlikely(!is_reserved(gpio, gpio, 0))) { |
945 | if (system_state == SYSTEM_BOOTING) |
946 | dump_stack(); |
947 | gpio_error(gpio); |
948 | hard_local_irq_restore(flags); |
949 | return; |
950 | } |
951 | |
952 | unreserve(gpio, gpio); |
953 | |
954 | set_label(gpio, "free"); |
955 | |
956 | hard_local_irq_restore(flags); |
957 | } |
958 | EXPORT_SYMBOL(bfin_gpio_free); |
959 | |
960 | #ifdef BFIN_SPECIAL_GPIO_BANKS |
961 | DECLARE_RESERVED_MAP(special_gpio, gpio_bank(MAX_RESOURCES)); |
962 | |
963 | int bfin_special_gpio_request(unsigned gpio, const char *label) |
964 | { |
965 | unsigned long flags; |
966 | |
967 | flags = hard_local_irq_save(); |
968 | |
969 | /* |
970 | * Allow that the identical GPIO can |
971 | * be requested from the same driver twice |
972 | * Do nothing and return - |
973 | */ |
974 | |
975 | if (cmp_label(gpio, label) == 0) { |
976 | hard_local_irq_restore(flags); |
977 | return 0; |
978 | } |
979 | |
980 | if (unlikely(is_reserved(special_gpio, gpio, 1))) { |
981 | hard_local_irq_restore(flags); |
982 | printk(KERN_ERR "bfin-gpio: GPIO %d is already reserved by %s !\n", |
983 | gpio, get_label(gpio)); |
984 | |
985 | return -EBUSY; |
986 | } |
987 | if (unlikely(is_reserved(peri, gpio, 1))) { |
988 | hard_local_irq_restore(flags); |
989 | printk(KERN_ERR |
990 | "bfin-gpio: GPIO %d is already reserved as Peripheral by %s !\n", |
991 | gpio, get_label(gpio)); |
992 | |
993 | return -EBUSY; |
994 | } |
995 | |
996 | reserve(special_gpio, gpio); |
997 | reserve(peri, gpio); |
998 | |
999 | set_label(gpio, label); |
1000 | hard_local_irq_restore(flags); |
1001 | port_setup(gpio, GPIO_USAGE); |
1002 | |
1003 | return 0; |
1004 | } |
1005 | EXPORT_SYMBOL(bfin_special_gpio_request); |
1006 | |
1007 | void bfin_special_gpio_free(unsigned gpio) |
1008 | { |
1009 | unsigned long flags; |
1010 | |
1011 | might_sleep(); |
1012 | |
1013 | flags = hard_local_irq_save(); |
1014 | |
1015 | if (unlikely(!is_reserved(special_gpio, gpio, 0))) { |
1016 | gpio_error(gpio); |
1017 | hard_local_irq_restore(flags); |
1018 | return; |
1019 | } |
1020 | |
1021 | unreserve(special_gpio, gpio); |
1022 | unreserve(peri, gpio); |
1023 | set_label(gpio, "free"); |
1024 | hard_local_irq_restore(flags); |
1025 | } |
1026 | EXPORT_SYMBOL(bfin_special_gpio_free); |
1027 | #endif |
1028 | |
1029 | |
1030 | int bfin_gpio_irq_request(unsigned gpio, const char *label) |
1031 | { |
1032 | unsigned long flags; |
1033 | |
1034 | if (check_gpio(gpio) < 0) |
1035 | return -EINVAL; |
1036 | |
1037 | flags = hard_local_irq_save(); |
1038 | |
1039 | if (unlikely(is_reserved(peri, gpio, 1))) { |
1040 | if (system_state == SYSTEM_BOOTING) |
1041 | dump_stack(); |
1042 | printk(KERN_ERR |
1043 | "bfin-gpio: GPIO %d is already reserved as Peripheral by %s !\n", |
1044 | gpio, get_label(gpio)); |
1045 | hard_local_irq_restore(flags); |
1046 | return -EBUSY; |
1047 | } |
1048 | if (unlikely(is_reserved(gpio, gpio, 1))) |
1049 | printk(KERN_NOTICE "bfin-gpio: GPIO %d is already reserved by %s! " |
1050 | "(Documentation/blackfin/bfin-gpio-notes.txt)\n", |
1051 | gpio, get_label(gpio)); |
1052 | |
1053 | reserve(gpio_irq, gpio); |
1054 | set_label(gpio, label); |
1055 | |
1056 | hard_local_irq_restore(flags); |
1057 | |
1058 | port_setup(gpio, GPIO_USAGE); |
1059 | |
1060 | return 0; |
1061 | } |
1062 | |
1063 | void bfin_gpio_irq_free(unsigned gpio) |
1064 | { |
1065 | unsigned long flags; |
1066 | |
1067 | if (check_gpio(gpio) < 0) |
1068 | return; |
1069 | |
1070 | flags = hard_local_irq_save(); |
1071 | |
1072 | if (unlikely(!is_reserved(gpio_irq, gpio, 0))) { |
1073 | if (system_state == SYSTEM_BOOTING) |
1074 | dump_stack(); |
1075 | gpio_error(gpio); |
1076 | hard_local_irq_restore(flags); |
1077 | return; |
1078 | } |
1079 | |
1080 | unreserve(gpio_irq, gpio); |
1081 | |
1082 | set_label(gpio, "free"); |
1083 | |
1084 | hard_local_irq_restore(flags); |
1085 | } |
1086 | |
1087 | static inline void __bfin_gpio_direction_input(unsigned gpio) |
1088 | { |
1089 | #ifdef CONFIG_BF54x |
1090 | gpio_array[gpio_bank(gpio)]->dir_clear = gpio_bit(gpio); |
1091 | #else |
1092 | gpio_array[gpio_bank(gpio)]->dir &= ~gpio_bit(gpio); |
1093 | #endif |
1094 | gpio_array[gpio_bank(gpio)]->inen |= gpio_bit(gpio); |
1095 | } |
1096 | |
1097 | int bfin_gpio_direction_input(unsigned gpio) |
1098 | { |
1099 | unsigned long flags; |
1100 | |
1101 | if (unlikely(!is_reserved(gpio, gpio, 0))) { |
1102 | gpio_error(gpio); |
1103 | return -EINVAL; |
1104 | } |
1105 | |
1106 | flags = hard_local_irq_save(); |
1107 | __bfin_gpio_direction_input(gpio); |
1108 | AWA_DUMMY_READ(inen); |
1109 | hard_local_irq_restore(flags); |
1110 | |
1111 | return 0; |
1112 | } |
1113 | EXPORT_SYMBOL(bfin_gpio_direction_input); |
1114 | |
1115 | void bfin_gpio_irq_prepare(unsigned gpio) |
1116 | { |
1117 | #ifdef CONFIG_BF54x |
1118 | unsigned long flags; |
1119 | #endif |
1120 | |
1121 | port_setup(gpio, GPIO_USAGE); |
1122 | |
1123 | #ifdef CONFIG_BF54x |
1124 | flags = hard_local_irq_save(); |
1125 | __bfin_gpio_direction_input(gpio); |
1126 | hard_local_irq_restore(flags); |
1127 | #endif |
1128 | } |
1129 | |
1130 | void bfin_gpio_set_value(unsigned gpio, int arg) |
1131 | { |
1132 | if (arg) |
1133 | gpio_array[gpio_bank(gpio)]->data_set = gpio_bit(gpio); |
1134 | else |
1135 | gpio_array[gpio_bank(gpio)]->data_clear = gpio_bit(gpio); |
1136 | } |
1137 | EXPORT_SYMBOL(bfin_gpio_set_value); |
1138 | |
1139 | int bfin_gpio_direction_output(unsigned gpio, int value) |
1140 | { |
1141 | unsigned long flags; |
1142 | |
1143 | if (unlikely(!is_reserved(gpio, gpio, 0))) { |
1144 | gpio_error(gpio); |
1145 | return -EINVAL; |
1146 | } |
1147 | |
1148 | flags = hard_local_irq_save(); |
1149 | |
1150 | gpio_array[gpio_bank(gpio)]->inen &= ~gpio_bit(gpio); |
1151 | gpio_set_value(gpio, value); |
1152 | #ifdef CONFIG_BF54x |
1153 | gpio_array[gpio_bank(gpio)]->dir_set = gpio_bit(gpio); |
1154 | #else |
1155 | gpio_array[gpio_bank(gpio)]->dir |= gpio_bit(gpio); |
1156 | #endif |
1157 | |
1158 | AWA_DUMMY_READ(dir); |
1159 | hard_local_irq_restore(flags); |
1160 | |
1161 | return 0; |
1162 | } |
1163 | EXPORT_SYMBOL(bfin_gpio_direction_output); |
1164 | |
1165 | int bfin_gpio_get_value(unsigned gpio) |
1166 | { |
1167 | #ifdef CONFIG_BF54x |
1168 | return (1 & (gpio_array[gpio_bank(gpio)]->data >> gpio_sub_n(gpio))); |
1169 | #else |
1170 | unsigned long flags; |
1171 | |
1172 | if (unlikely(get_gpio_edge(gpio))) { |
1173 | int ret; |
1174 | flags = hard_local_irq_save(); |
1175 | set_gpio_edge(gpio, 0); |
1176 | ret = get_gpio_data(gpio); |
1177 | set_gpio_edge(gpio, 1); |
1178 | hard_local_irq_restore(flags); |
1179 | return ret; |
1180 | } else |
1181 | return get_gpio_data(gpio); |
1182 | #endif |
1183 | } |
1184 | EXPORT_SYMBOL(bfin_gpio_get_value); |
1185 | |
1186 | /* If we are booting from SPI and our board lacks a strong enough pull up, |
1187 | * the core can reset and execute the bootrom faster than the resistor can |
1188 | * pull the signal logically high. To work around this (common) error in |
1189 | * board design, we explicitly set the pin back to GPIO mode, force /CS |
1190 | * high, and wait for the electrons to do their thing. |
1191 | * |
1192 | * This function only makes sense to be called from reset code, but it |
1193 | * lives here as we need to force all the GPIO states w/out going through |
1194 | * BUG() checks and such. |
1195 | */ |
1196 | void bfin_reset_boot_spi_cs(unsigned short pin) |
1197 | { |
1198 | unsigned short gpio = P_IDENT(pin); |
1199 | port_setup(gpio, GPIO_USAGE); |
1200 | gpio_array[gpio_bank(gpio)]->data_set = gpio_bit(gpio); |
1201 | AWA_DUMMY_READ(data_set); |
1202 | udelay(1); |
1203 | } |
1204 | |
1205 | #if defined(CONFIG_PROC_FS) |
1206 | static int gpio_proc_read(char *buf, char **start, off_t offset, |
1207 | int len, int *unused_i, void *unused_v) |
1208 | { |
1209 | int c, irq, gpio, outlen = 0; |
1210 | |
1211 | for (c = 0; c < MAX_RESOURCES; c++) { |
1212 | irq = is_reserved(gpio_irq, c, 1); |
1213 | gpio = is_reserved(gpio, c, 1); |
1214 | if (!check_gpio(c) && (gpio || irq)) |
1215 | len = sprintf(buf, "GPIO_%d: \t%s%s \t\tGPIO %s\n", c, |
1216 | get_label(c), (gpio && irq) ? " *" : "", |
1217 | get_gpio_dir(c) ? "OUTPUT" : "INPUT"); |
1218 | else if (is_reserved(peri, c, 1)) |
1219 | len = sprintf(buf, "GPIO_%d: \t%s \t\tPeripheral\n", c, get_label(c)); |
1220 | else |
1221 | continue; |
1222 | buf += len; |
1223 | outlen += len; |
1224 | } |
1225 | return outlen; |
1226 | } |
1227 | |
1228 | static __init int gpio_register_proc(void) |
1229 | { |
1230 | struct proc_dir_entry *proc_gpio; |
1231 | |
1232 | proc_gpio = create_proc_entry("gpio", S_IRUGO, NULL); |
1233 | if (proc_gpio) |
1234 | proc_gpio->read_proc = gpio_proc_read; |
1235 | return proc_gpio != NULL; |
1236 | } |
1237 | __initcall(gpio_register_proc); |
1238 | #endif |
1239 | |
1240 | #ifdef CONFIG_GPIOLIB |
1241 | static int bfin_gpiolib_direction_input(struct gpio_chip *chip, unsigned gpio) |
1242 | { |
1243 | return bfin_gpio_direction_input(gpio); |
1244 | } |
1245 | |
1246 | static int bfin_gpiolib_direction_output(struct gpio_chip *chip, unsigned gpio, int level) |
1247 | { |
1248 | return bfin_gpio_direction_output(gpio, level); |
1249 | } |
1250 | |
1251 | static int bfin_gpiolib_get_value(struct gpio_chip *chip, unsigned gpio) |
1252 | { |
1253 | return bfin_gpio_get_value(gpio); |
1254 | } |
1255 | |
1256 | static void bfin_gpiolib_set_value(struct gpio_chip *chip, unsigned gpio, int value) |
1257 | { |
1258 | return bfin_gpio_set_value(gpio, value); |
1259 | } |
1260 | |
1261 | static int bfin_gpiolib_gpio_request(struct gpio_chip *chip, unsigned gpio) |
1262 | { |
1263 | return bfin_gpio_request(gpio, chip->label); |
1264 | } |
1265 | |
1266 | static void bfin_gpiolib_gpio_free(struct gpio_chip *chip, unsigned gpio) |
1267 | { |
1268 | return bfin_gpio_free(gpio); |
1269 | } |
1270 | |
1271 | static int bfin_gpiolib_gpio_to_irq(struct gpio_chip *chip, unsigned gpio) |
1272 | { |
1273 | return gpio + GPIO_IRQ_BASE; |
1274 | } |
1275 | |
1276 | static struct gpio_chip bfin_chip = { |
1277 | .label = "BFIN-GPIO", |
1278 | .direction_input = bfin_gpiolib_direction_input, |
1279 | .get = bfin_gpiolib_get_value, |
1280 | .direction_output = bfin_gpiolib_direction_output, |
1281 | .set = bfin_gpiolib_set_value, |
1282 | .request = bfin_gpiolib_gpio_request, |
1283 | .free = bfin_gpiolib_gpio_free, |
1284 | .to_irq = bfin_gpiolib_gpio_to_irq, |
1285 | .base = 0, |
1286 | .ngpio = MAX_BLACKFIN_GPIOS, |
1287 | }; |
1288 | |
1289 | static int __init bfin_gpiolib_setup(void) |
1290 | { |
1291 | return gpiochip_add(&bfin_chip); |
1292 | } |
1293 | arch_initcall(bfin_gpiolib_setup); |
1294 | #endif |
1295 |
Branches:
ben-wpan
ben-wpan-stefan
javiroman/ks7010
jz-2.6.34
jz-2.6.34-rc5
jz-2.6.34-rc6
jz-2.6.34-rc7
jz-2.6.35
jz-2.6.36
jz-2.6.37
jz-2.6.38
jz-2.6.39
jz-3.0
jz-3.1
jz-3.11
jz-3.12
jz-3.13
jz-3.15
jz-3.16
jz-3.18-dt
jz-3.2
jz-3.3
jz-3.4
jz-3.5
jz-3.6
jz-3.6-rc2-pwm
jz-3.9
jz-3.9-clk
jz-3.9-rc8
jz47xx
jz47xx-2.6.38
master
Tags:
od-2011-09-04
od-2011-09-18
v2.6.34-rc5
v2.6.34-rc6
v2.6.34-rc7
v3.9