blob: f684be531c4b079e516016affde629f5ab0dfe1e [file] [log] [blame]
Mike Frysinger4638b212010-06-02 04:17:26 -04001/*
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 <common.h>
10#include <asm/errno.h>
11#include <asm/gpio.h>
12#include <asm/portmux.h>
13
14#if ANOMALY_05000311 || ANOMALY_05000323
15enum {
16 AWA_data = SYSCR,
17 AWA_data_clear = SYSCR,
18 AWA_data_set = SYSCR,
19 AWA_toggle = SYSCR,
20 AWA_maska = UART_SCR,
21 AWA_maska_clear = UART_SCR,
22 AWA_maska_set = UART_SCR,
23 AWA_maska_toggle = UART_SCR,
24 AWA_maskb = UART_GCTL,
25 AWA_maskb_clear = UART_GCTL,
26 AWA_maskb_set = UART_GCTL,
27 AWA_maskb_toggle = UART_GCTL,
28 AWA_dir = SPORT1_STAT,
29 AWA_polar = SPORT1_STAT,
30 AWA_edge = SPORT1_STAT,
31 AWA_both = SPORT1_STAT,
32#if ANOMALY_05000311
33 AWA_inen = TIMER_ENABLE,
34#elif ANOMALY_05000323
35 AWA_inen = DMA1_1_CONFIG,
36#endif
37};
38 /* Anomaly Workaround */
39#define AWA_DUMMY_READ(name) bfin_read16(AWA_ ## name)
40#else
41#define AWA_DUMMY_READ(...) do { } while (0)
42#endif
43
44static struct gpio_port_t * const gpio_array[] = {
45#if defined(BF533_FAMILY)
46 (struct gpio_port_t *) FIO_FLAG_D,
47#elif defined(CONFIG_BF52x) || defined(BF537_FAMILY) || defined(CONFIG_BF51x) \
Mike Frysingercca07412010-12-17 15:25:09 -050048 || defined(BF538_FAMILY) || defined(CONFIG_BF50x)
Mike Frysinger4638b212010-06-02 04:17:26 -040049 (struct gpio_port_t *) PORTFIO,
50# if !defined(BF538_FAMILY)
51 (struct gpio_port_t *) PORTGIO,
52 (struct gpio_port_t *) PORTHIO,
53# endif
54#elif defined(BF561_FAMILY)
55 (struct gpio_port_t *) FIO0_FLAG_D,
56 (struct gpio_port_t *) FIO1_FLAG_D,
57 (struct gpio_port_t *) FIO2_FLAG_D,
58#elif defined(CONFIG_BF54x)
59 (struct gpio_port_t *)PORTA_FER,
60 (struct gpio_port_t *)PORTB_FER,
61 (struct gpio_port_t *)PORTC_FER,
62 (struct gpio_port_t *)PORTD_FER,
63 (struct gpio_port_t *)PORTE_FER,
64 (struct gpio_port_t *)PORTF_FER,
65 (struct gpio_port_t *)PORTG_FER,
66 (struct gpio_port_t *)PORTH_FER,
67 (struct gpio_port_t *)PORTI_FER,
68 (struct gpio_port_t *)PORTJ_FER,
Bob Liuc34346d2012-08-16 11:40:30 +080069#elif defined(CONFIG_BF60x)
70 (struct gpio_port_t *)PORTA_FER,
71 (struct gpio_port_t *)PORTB_FER,
72 (struct gpio_port_t *)PORTC_FER,
73 (struct gpio_port_t *)PORTD_FER,
74 (struct gpio_port_t *)PORTE_FER,
75 (struct gpio_port_t *)PORTF_FER,
76 (struct gpio_port_t *)PORTG_FER,
Mike Frysinger4638b212010-06-02 04:17:26 -040077#else
78# error no gpio arrays defined
79#endif
80};
81
Mike Frysingercca07412010-12-17 15:25:09 -050082#if defined(CONFIG_BF52x) || defined(BF537_FAMILY) || defined(CONFIG_BF51x) || \
83 defined(CONFIG_BF50x)
Mike Frysinger4638b212010-06-02 04:17:26 -040084static unsigned short * const port_fer[] = {
85 (unsigned short *) PORTF_FER,
86 (unsigned short *) PORTG_FER,
87 (unsigned short *) PORTH_FER,
88};
89
90# if !defined(BF537_FAMILY)
91static unsigned short * const port_mux[] = {
92 (unsigned short *) PORTF_MUX,
93 (unsigned short *) PORTG_MUX,
94 (unsigned short *) PORTH_MUX,
95};
96
97static const
98u8 pmux_offset[][16] = {
99# if defined(CONFIG_BF52x)
100 { 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 4, 6, 8, 8, 10, 10 }, /* PORTF */
101 { 0, 0, 0, 0, 0, 2, 2, 4, 4, 6, 8, 10, 10, 10, 12, 12 }, /* PORTG */
102 { 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 4, 4, 4, 4, 4, 4 }, /* PORTH */
103# elif defined(CONFIG_BF51x)
104 { 0, 2, 2, 2, 2, 2, 2, 4, 6, 6, 6, 8, 8, 8, 8, 10 }, /* PORTF */
105 { 0, 0, 0, 2, 4, 6, 6, 6, 8, 10, 10, 12, 14, 14, 14, 14 }, /* PORTG */
106 { 0, 0, 0, 0, 2, 2, 4, 6, 10, 10, 10, 10, 10, 10, 10, 10 }, /* PORTH */
107# endif
108};
109# endif
110
111#elif defined(BF538_FAMILY)
112static unsigned short * const port_fer[] = {
113 (unsigned short *) PORTCIO_FER,
114 (unsigned short *) PORTDIO_FER,
115 (unsigned short *) PORTEIO_FER,
116};
117#endif
118
119#ifdef CONFIG_BFIN_GPIO_TRACK
120#define RESOURCE_LABEL_SIZE 16
121
122static struct str_ident {
123 char name[RESOURCE_LABEL_SIZE];
124} str_ident[MAX_RESOURCES];
125
126static void gpio_error(unsigned gpio)
127{
128 printf("bfin-gpio: GPIO %d wasn't requested!\n", gpio);
129}
130
131static void set_label(unsigned short ident, const char *label)
132{
133 if (label) {
134 strncpy(str_ident[ident].name, label,
135 RESOURCE_LABEL_SIZE);
136 str_ident[ident].name[RESOURCE_LABEL_SIZE - 1] = 0;
137 }
138}
139
140static char *get_label(unsigned short ident)
141{
142 return (*str_ident[ident].name ? str_ident[ident].name : "UNKNOWN");
143}
144
145static int cmp_label(unsigned short ident, const char *label)
146{
147 if (label == NULL)
148 printf("bfin-gpio: please provide none-null label\n");
149
150 if (label)
151 return strcmp(str_ident[ident].name, label);
152 else
153 return -EINVAL;
154}
155
156#define map_entry(m, i) reserved_##m##_map[gpio_bank(i)]
157#define is_reserved(m, i, e) (map_entry(m, i) & gpio_bit(i))
158#define reserve(m, i) (map_entry(m, i) |= gpio_bit(i))
159#define unreserve(m, i) (map_entry(m, i) &= ~gpio_bit(i))
160#define DECLARE_RESERVED_MAP(m, c) static unsigned short reserved_##m##_map[c]
161#else
162#define is_reserved(m, i, e) (!(e))
163#define reserve(m, i)
164#define unreserve(m, i)
165#define DECLARE_RESERVED_MAP(m, c)
166#define gpio_error(gpio)
167#define set_label(...)
168#define get_label(...) ""
169#define cmp_label(...) 1
170#endif
171
172DECLARE_RESERVED_MAP(gpio, GPIO_BANK_NUM);
173DECLARE_RESERVED_MAP(peri, gpio_bank(MAX_RESOURCES));
174
175inline int check_gpio(unsigned gpio)
176{
177#if defined(CONFIG_BF54x)
178 if (gpio == GPIO_PB15 || gpio == GPIO_PC14 || gpio == GPIO_PC15
179 || gpio == GPIO_PH14 || gpio == GPIO_PH15
180 || gpio == GPIO_PJ14 || gpio == GPIO_PJ15)
181 return -EINVAL;
182#endif
183 if (gpio >= MAX_BLACKFIN_GPIOS)
184 return -EINVAL;
185 return 0;
186}
187
188static void port_setup(unsigned gpio, unsigned short usage)
189{
190#if defined(BF538_FAMILY)
191 /*
192 * BF538/9 Port C,D and E are special.
193 * Inverted PORT_FER polarity on CDE and no PORF_FER on F
194 * Regular PORT F GPIOs are handled here, CDE are exclusively
195 * managed by GPIOLIB
196 */
197
198 if (gpio < MAX_BLACKFIN_GPIOS || gpio >= MAX_RESOURCES)
199 return;
200
201 gpio -= MAX_BLACKFIN_GPIOS;
202
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 return;
209#endif
210
211 if (check_gpio(gpio))
212 return;
213
Mike Frysingercca07412010-12-17 15:25:09 -0500214#if defined(CONFIG_BF52x) || defined(BF537_FAMILY) || defined(CONFIG_BF51x) || \
215 defined(CONFIG_BF50x)
Mike Frysinger4638b212010-06-02 04:17:26 -0400216 if (usage == GPIO_USAGE)
217 *port_fer[gpio_bank(gpio)] &= ~gpio_bit(gpio);
218 else
219 *port_fer[gpio_bank(gpio)] |= gpio_bit(gpio);
220 SSYNC();
221#elif defined(CONFIG_BF54x)
222 if (usage == GPIO_USAGE)
223 gpio_array[gpio_bank(gpio)]->port_fer &= ~gpio_bit(gpio);
224 else
225 gpio_array[gpio_bank(gpio)]->port_fer |= gpio_bit(gpio);
226 SSYNC();
Bob Liuc34346d2012-08-16 11:40:30 +0800227#elif defined(CONFIG_BF60x)
228 if (usage == GPIO_USAGE)
229 gpio_array[gpio_bank(gpio)]->port_fer_clear = gpio_bit(gpio);
230 else
231 gpio_array[gpio_bank(gpio)]->port_fer_set = gpio_bit(gpio);
232 SSYNC();
Mike Frysinger4638b212010-06-02 04:17:26 -0400233#endif
234}
235
236#ifdef BF537_FAMILY
237static struct {
238 unsigned short res;
239 unsigned short offset;
240} port_mux_lut[] = {
241 {.res = P_PPI0_D13, .offset = 11},
242 {.res = P_PPI0_D14, .offset = 11},
243 {.res = P_PPI0_D15, .offset = 11},
244 {.res = P_SPORT1_TFS, .offset = 11},
245 {.res = P_SPORT1_TSCLK, .offset = 11},
246 {.res = P_SPORT1_DTPRI, .offset = 11},
247 {.res = P_PPI0_D10, .offset = 10},
248 {.res = P_PPI0_D11, .offset = 10},
249 {.res = P_PPI0_D12, .offset = 10},
250 {.res = P_SPORT1_RSCLK, .offset = 10},
251 {.res = P_SPORT1_RFS, .offset = 10},
252 {.res = P_SPORT1_DRPRI, .offset = 10},
253 {.res = P_PPI0_D8, .offset = 9},
254 {.res = P_PPI0_D9, .offset = 9},
255 {.res = P_SPORT1_DRSEC, .offset = 9},
256 {.res = P_SPORT1_DTSEC, .offset = 9},
257 {.res = P_TMR2, .offset = 8},
258 {.res = P_PPI0_FS3, .offset = 8},
259 {.res = P_TMR3, .offset = 7},
260 {.res = P_SPI0_SSEL4, .offset = 7},
261 {.res = P_TMR4, .offset = 6},
262 {.res = P_SPI0_SSEL5, .offset = 6},
263 {.res = P_TMR5, .offset = 5},
264 {.res = P_SPI0_SSEL6, .offset = 5},
265 {.res = P_UART1_RX, .offset = 4},
266 {.res = P_UART1_TX, .offset = 4},
267 {.res = P_TMR6, .offset = 4},
268 {.res = P_TMR7, .offset = 4},
269 {.res = P_UART0_RX, .offset = 3},
270 {.res = P_UART0_TX, .offset = 3},
271 {.res = P_DMAR0, .offset = 3},
272 {.res = P_DMAR1, .offset = 3},
273 {.res = P_SPORT0_DTSEC, .offset = 1},
274 {.res = P_SPORT0_DRSEC, .offset = 1},
275 {.res = P_CAN0_RX, .offset = 1},
276 {.res = P_CAN0_TX, .offset = 1},
277 {.res = P_SPI0_SSEL7, .offset = 1},
278 {.res = P_SPORT0_TFS, .offset = 0},
279 {.res = P_SPORT0_DTPRI, .offset = 0},
280 {.res = P_SPI0_SSEL2, .offset = 0},
281 {.res = P_SPI0_SSEL3, .offset = 0},
282};
283
284static void portmux_setup(unsigned short per)
285{
286 u16 y, offset, muxreg;
287 u16 function = P_FUNCT2MUX(per);
288
289 for (y = 0; y < ARRAY_SIZE(port_mux_lut); y++) {
290 if (port_mux_lut[y].res == per) {
291
292 /* SET PORTMUX REG */
293
294 offset = port_mux_lut[y].offset;
295 muxreg = bfin_read_PORT_MUX();
296
297 if (offset != 1)
298 muxreg &= ~(1 << offset);
299 else
300 muxreg &= ~(3 << 1);
301
302 muxreg |= (function << offset);
303 bfin_write_PORT_MUX(muxreg);
304 }
305 }
306}
Bob Liuc34346d2012-08-16 11:40:30 +0800307#elif defined(CONFIG_BF54x) || defined(CONFIG_BF60x)
Mike Frysinger4638b212010-06-02 04:17:26 -0400308inline void portmux_setup(unsigned short per)
309{
310 u32 pmux;
311 u16 ident = P_IDENT(per);
312 u16 function = P_FUNCT2MUX(per);
313
314 pmux = gpio_array[gpio_bank(ident)]->port_mux;
315
316 pmux &= ~(0x3 << (2 * gpio_sub_n(ident)));
317 pmux |= (function & 0x3) << (2 * gpio_sub_n(ident));
318
319 gpio_array[gpio_bank(ident)]->port_mux = pmux;
320}
321
322inline u16 get_portmux(unsigned short per)
323{
324 u32 pmux;
325 u16 ident = P_IDENT(per);
326
327 pmux = gpio_array[gpio_bank(ident)]->port_mux;
328
329 return (pmux >> (2 * gpio_sub_n(ident)) & 0x3);
330}
331#elif defined(CONFIG_BF52x) || defined(CONFIG_BF51x)
332inline void portmux_setup(unsigned short per)
333{
334 u16 pmux, ident = P_IDENT(per), function = P_FUNCT2MUX(per);
335 u8 offset = pmux_offset[gpio_bank(ident)][gpio_sub_n(ident)];
336
337 pmux = *port_mux[gpio_bank(ident)];
338 pmux &= ~(3 << offset);
339 pmux |= (function & 3) << offset;
340 *port_mux[gpio_bank(ident)] = pmux;
341 SSYNC();
342}
343#else
344# define portmux_setup(...) do { } while (0)
345#endif
346
Bob Liuc34346d2012-08-16 11:40:30 +0800347#if !defined(CONFIG_BF54x) && !defined(CONFIG_BF60x)
Mike Frysinger4638b212010-06-02 04:17:26 -0400348/***********************************************************
349*
350* FUNCTIONS: Blackfin General Purpose Ports Access Functions
351*
352* INPUTS/OUTPUTS:
353* gpio - GPIO Number between 0 and MAX_BLACKFIN_GPIOS
354*
355*
356* DESCRIPTION: These functions abstract direct register access
357* to Blackfin processor General Purpose
358* Ports Regsiters
359*
360* CAUTION: These functions do not belong to the GPIO Driver API
361*************************************************************
362* MODIFICATION HISTORY :
363**************************************************************/
364
365/* Set a specific bit */
366
367#define SET_GPIO(name) \
368void set_gpio_ ## name(unsigned gpio, unsigned short arg) \
369{ \
370 unsigned long flags; \
371 local_irq_save(flags); \
372 if (arg) \
373 gpio_array[gpio_bank(gpio)]->name |= gpio_bit(gpio); \
374 else \
375 gpio_array[gpio_bank(gpio)]->name &= ~gpio_bit(gpio); \
376 AWA_DUMMY_READ(name); \
377 local_irq_restore(flags); \
378}
379
380SET_GPIO(dir) /* set_gpio_dir() */
381SET_GPIO(inen) /* set_gpio_inen() */
382SET_GPIO(polar) /* set_gpio_polar() */
383SET_GPIO(edge) /* set_gpio_edge() */
384SET_GPIO(both) /* set_gpio_both() */
385
386
387#define SET_GPIO_SC(name) \
388void set_gpio_ ## name(unsigned gpio, unsigned short arg) \
389{ \
390 unsigned long flags; \
391 if (ANOMALY_05000311 || ANOMALY_05000323) \
392 local_irq_save(flags); \
393 if (arg) \
394 gpio_array[gpio_bank(gpio)]->name ## _set = gpio_bit(gpio); \
395 else \
396 gpio_array[gpio_bank(gpio)]->name ## _clear = gpio_bit(gpio); \
397 if (ANOMALY_05000311 || ANOMALY_05000323) { \
398 AWA_DUMMY_READ(name); \
399 local_irq_restore(flags); \
400 } \
401}
402
403SET_GPIO_SC(maska)
404SET_GPIO_SC(maskb)
405SET_GPIO_SC(data)
406
407void set_gpio_toggle(unsigned gpio)
408{
409 unsigned long flags;
410 if (ANOMALY_05000311 || ANOMALY_05000323)
411 local_irq_save(flags);
412 gpio_array[gpio_bank(gpio)]->toggle = gpio_bit(gpio);
413 if (ANOMALY_05000311 || ANOMALY_05000323) {
414 AWA_DUMMY_READ(toggle);
415 local_irq_restore(flags);
416 }
417}
418
419/* Set current PORT date (16-bit word) */
420
421#define SET_GPIO_P(name) \
422void set_gpiop_ ## name(unsigned gpio, unsigned short arg) \
423{ \
424 unsigned long flags; \
425 if (ANOMALY_05000311 || ANOMALY_05000323) \
426 local_irq_save(flags); \
427 gpio_array[gpio_bank(gpio)]->name = arg; \
428 if (ANOMALY_05000311 || ANOMALY_05000323) { \
429 AWA_DUMMY_READ(name); \
430 local_irq_restore(flags); \
431 } \
432}
433
434SET_GPIO_P(data)
435SET_GPIO_P(dir)
436SET_GPIO_P(inen)
437SET_GPIO_P(polar)
438SET_GPIO_P(edge)
439SET_GPIO_P(both)
440SET_GPIO_P(maska)
441SET_GPIO_P(maskb)
442
443/* Get a specific bit */
444#define GET_GPIO(name) \
445unsigned short get_gpio_ ## name(unsigned gpio) \
446{ \
447 unsigned long flags; \
448 unsigned short ret; \
449 if (ANOMALY_05000311 || ANOMALY_05000323) \
450 local_irq_save(flags); \
451 ret = 0x01 & (gpio_array[gpio_bank(gpio)]->name >> gpio_sub_n(gpio)); \
452 if (ANOMALY_05000311 || ANOMALY_05000323) { \
453 AWA_DUMMY_READ(name); \
454 local_irq_restore(flags); \
455 } \
456 return ret; \
457}
458
459GET_GPIO(data)
460GET_GPIO(dir)
461GET_GPIO(inen)
462GET_GPIO(polar)
463GET_GPIO(edge)
464GET_GPIO(both)
465GET_GPIO(maska)
466GET_GPIO(maskb)
467
468/* Get current PORT date (16-bit word) */
469
470#define GET_GPIO_P(name) \
471unsigned short get_gpiop_ ## name(unsigned gpio) \
472{ \
473 unsigned long flags; \
474 unsigned short ret; \
475 if (ANOMALY_05000311 || ANOMALY_05000323) \
476 local_irq_save(flags); \
477 ret = (gpio_array[gpio_bank(gpio)]->name); \
478 if (ANOMALY_05000311 || ANOMALY_05000323) { \
479 AWA_DUMMY_READ(name); \
480 local_irq_restore(flags); \
481 } \
482 return ret; \
483}
484
485GET_GPIO_P(data)
486GET_GPIO_P(dir)
487GET_GPIO_P(inen)
488GET_GPIO_P(polar)
489GET_GPIO_P(edge)
490GET_GPIO_P(both)
491GET_GPIO_P(maska)
492GET_GPIO_P(maskb)
493
494#else /* CONFIG_BF54x */
495
496unsigned short get_gpio_dir(unsigned gpio)
497{
498 return (0x01 & (gpio_array[gpio_bank(gpio)]->dir_clear >> gpio_sub_n(gpio)));
499}
500
501#endif /* CONFIG_BF54x */
502
503/***********************************************************
504*
505* FUNCTIONS: Blackfin Peripheral Resource Allocation
506* and PortMux Setup
507*
508* INPUTS/OUTPUTS:
509* per Peripheral Identifier
510* label String
511*
512* DESCRIPTION: Blackfin Peripheral Resource Allocation and Setup API
513*
514* CAUTION:
515*************************************************************
516* MODIFICATION HISTORY :
517**************************************************************/
518
519int peripheral_request(unsigned short per, const char *label)
520{
521 unsigned short ident = P_IDENT(per);
522
523 /*
524 * Don't cares are pins with only one dedicated function
525 */
526
527 if (per & P_DONTCARE)
528 return 0;
529
530 if (!(per & P_DEFINED))
531 return -ENODEV;
532
533 BUG_ON(ident >= MAX_RESOURCES);
534
535 /* If a pin can be muxed as either GPIO or peripheral, make
536 * sure it is not already a GPIO pin when we request it.
537 */
538 if (unlikely(!check_gpio(ident) && is_reserved(gpio, ident, 1))) {
539 printf("%s: Peripheral %d is already reserved as GPIO by %s !\n",
540 __func__, ident, get_label(ident));
541 return -EBUSY;
542 }
543
544 if (unlikely(is_reserved(peri, ident, 1))) {
545
546 /*
547 * Pin functions like AMC address strobes my
548 * be requested and used by several drivers
549 */
550
Bob Liuc34346d2012-08-16 11:40:30 +0800551#if defined(CONFIG_BF54x) || defined(CONFIG_BF60x)
Mike Frysinger4638b212010-06-02 04:17:26 -0400552 if (!((per & P_MAYSHARE) && get_portmux(per) == P_FUNCT2MUX(per))) {
553#else
554 if (!(per & P_MAYSHARE)) {
555#endif
556 /*
557 * Allow that the identical pin function can
558 * be requested from the same driver twice
559 */
560
561 if (cmp_label(ident, label) == 0)
562 goto anyway;
563
564 printf("%s: Peripheral %d function %d is already reserved by %s !\n",
565 __func__, ident, P_FUNCT2MUX(per), get_label(ident));
566 return -EBUSY;
567 }
568 }
569
570 anyway:
571 reserve(peri, ident);
572
573 portmux_setup(per);
574 port_setup(ident, PERIPHERAL_USAGE);
575
576 set_label(ident, label);
577
578 return 0;
579}
580
581int peripheral_request_list(const unsigned short per[], const char *label)
582{
583 u16 cnt;
584 int ret;
585
586 for (cnt = 0; per[cnt] != 0; cnt++) {
587
588 ret = peripheral_request(per[cnt], label);
589
590 if (ret < 0) {
591 for ( ; cnt > 0; cnt--)
592 peripheral_free(per[cnt - 1]);
593
594 return ret;
595 }
596 }
597
598 return 0;
599}
600
601void peripheral_free(unsigned short per)
602{
603 unsigned short ident = P_IDENT(per);
604
605 if (per & P_DONTCARE)
606 return;
607
608 if (!(per & P_DEFINED))
609 return;
610
611 if (unlikely(!is_reserved(peri, ident, 0)))
612 return;
613
614 if (!(per & P_MAYSHARE))
615 port_setup(ident, GPIO_USAGE);
616
617 unreserve(peri, ident);
618
619 set_label(ident, "free");
620}
621
622void peripheral_free_list(const unsigned short per[])
623{
624 u16 cnt;
625 for (cnt = 0; per[cnt] != 0; cnt++)
626 peripheral_free(per[cnt]);
627}
628
629/***********************************************************
630*
631* FUNCTIONS: Blackfin GPIO Driver
632*
633* INPUTS/OUTPUTS:
634* gpio PIO Number between 0 and MAX_BLACKFIN_GPIOS
635* label String
636*
637* DESCRIPTION: Blackfin GPIO Driver API
638*
639* CAUTION:
640*************************************************************
641* MODIFICATION HISTORY :
642**************************************************************/
643
644int bfin_gpio_request(unsigned gpio, const char *label)
645{
646 if (check_gpio(gpio) < 0)
647 return -EINVAL;
648
649 /*
650 * Allow that the identical GPIO can
651 * be requested from the same driver twice
652 * Do nothing and return -
653 */
654
655 if (cmp_label(gpio, label) == 0)
656 return 0;
657
658 if (unlikely(is_reserved(gpio, gpio, 1))) {
659 printf("bfin-gpio: GPIO %d is already reserved by %s !\n",
660 gpio, get_label(gpio));
661 return -EBUSY;
662 }
663 if (unlikely(is_reserved(peri, gpio, 1))) {
664 printf("bfin-gpio: GPIO %d is already reserved as Peripheral by %s !\n",
665 gpio, get_label(gpio));
666 return -EBUSY;
667 }
Bob Liuc34346d2012-08-16 11:40:30 +0800668#if !defined(CONFIG_BF54x) && !defined(CONFIG_BF60x)
Mike Frysinger4638b212010-06-02 04:17:26 -0400669 else { /* Reset POLAR setting when acquiring a gpio for the first time */
670 set_gpio_polar(gpio, 0);
671 }
672#endif
673
674 reserve(gpio, gpio);
675 set_label(gpio, label);
676
677 port_setup(gpio, GPIO_USAGE);
678
679 return 0;
680}
681
Mike Frysinger95b4b9d2011-05-10 12:56:58 -0400682#ifdef CONFIG_BFIN_GPIO_TRACK
Mike Frysinger4638b212010-06-02 04:17:26 -0400683void bfin_gpio_free(unsigned gpio)
684{
685 if (check_gpio(gpio) < 0)
686 return;
687
688 if (unlikely(!is_reserved(gpio, gpio, 0))) {
689 gpio_error(gpio);
690 return;
691 }
692
693 unreserve(gpio, gpio);
694
695 set_label(gpio, "free");
696}
Mike Frysinger95b4b9d2011-05-10 12:56:58 -0400697#endif
Mike Frysinger4638b212010-06-02 04:17:26 -0400698
699#ifdef BFIN_SPECIAL_GPIO_BANKS
700DECLARE_RESERVED_MAP(special_gpio, gpio_bank(MAX_RESOURCES));
701
702int bfin_special_gpio_request(unsigned gpio, const char *label)
703{
704 /*
705 * Allow that the identical GPIO can
706 * be requested from the same driver twice
707 * Do nothing and return -
708 */
709
710 if (cmp_label(gpio, label) == 0)
711 return 0;
712
713 if (unlikely(is_reserved(special_gpio, gpio, 1))) {
714 printf("bfin-gpio: GPIO %d is already reserved by %s !\n",
715 gpio, get_label(gpio));
716 return -EBUSY;
717 }
718 if (unlikely(is_reserved(peri, gpio, 1))) {
719 printf("bfin-gpio: GPIO %d is already reserved as Peripheral by %s !\n",
720 gpio, get_label(gpio));
721
722 return -EBUSY;
723 }
724
725 reserve(special_gpio, gpio);
726 reserve(peri, gpio);
727
728 set_label(gpio, label);
729 port_setup(gpio, GPIO_USAGE);
730
731 return 0;
732}
733
734void bfin_special_gpio_free(unsigned gpio)
735{
736 if (unlikely(!is_reserved(special_gpio, gpio, 0))) {
737 gpio_error(gpio);
738 return;
739 }
740
741 reserve(special_gpio, gpio);
742 reserve(peri, gpio);
743 set_label(gpio, "free");
744}
745#endif
746
747static inline void __bfin_gpio_direction_input(unsigned gpio)
748{
Bob Liuc34346d2012-08-16 11:40:30 +0800749#if defined(CONFIG_BF54x) || defined(CONFIG_BF60x)
Mike Frysinger4638b212010-06-02 04:17:26 -0400750 gpio_array[gpio_bank(gpio)]->dir_clear = gpio_bit(gpio);
751#else
752 gpio_array[gpio_bank(gpio)]->dir &= ~gpio_bit(gpio);
753#endif
Bob Liuc34346d2012-08-16 11:40:30 +0800754#if defined(CONFIG_BF60x)
755 gpio_array[gpio_bank(gpio)]->inen_set = gpio_bit(gpio);
756#else
Mike Frysinger4638b212010-06-02 04:17:26 -0400757 gpio_array[gpio_bank(gpio)]->inen |= gpio_bit(gpio);
Bob Liuc34346d2012-08-16 11:40:30 +0800758#endif
Mike Frysinger4638b212010-06-02 04:17:26 -0400759}
760
761int bfin_gpio_direction_input(unsigned gpio)
762{
763 unsigned long flags;
764
765 if (!is_reserved(gpio, gpio, 0)) {
766 gpio_error(gpio);
767 return -EINVAL;
768 }
769
770 local_irq_save(flags);
771 __bfin_gpio_direction_input(gpio);
772 AWA_DUMMY_READ(inen);
773 local_irq_restore(flags);
774
775 return 0;
776}
777
778void bfin_gpio_toggle_value(unsigned gpio)
779{
780#ifdef CONFIG_BF54x
781 gpio_set_value(gpio, !gpio_get_value(gpio));
782#else
783 gpio_array[gpio_bank(gpio)]->toggle = gpio_bit(gpio);
784#endif
785}
786
787void bfin_gpio_set_value(unsigned gpio, int arg)
788{
789 if (arg)
790 gpio_array[gpio_bank(gpio)]->data_set = gpio_bit(gpio);
791 else
792 gpio_array[gpio_bank(gpio)]->data_clear = gpio_bit(gpio);
793}
794
795int bfin_gpio_direction_output(unsigned gpio, int value)
796{
797 unsigned long flags;
798
799 if (!is_reserved(gpio, gpio, 0)) {
800 gpio_error(gpio);
801 return -EINVAL;
802 }
803
804 local_irq_save(flags);
805
Bob Liuc34346d2012-08-16 11:40:30 +0800806#if defined(CONFIG_BF60x)
807 gpio_array[gpio_bank(gpio)]->inen_clear = gpio_bit(gpio);
808#else
Mike Frysinger4638b212010-06-02 04:17:26 -0400809 gpio_array[gpio_bank(gpio)]->inen &= ~gpio_bit(gpio);
Bob Liuc34346d2012-08-16 11:40:30 +0800810#endif
Mike Frysinger4638b212010-06-02 04:17:26 -0400811 gpio_set_value(gpio, value);
Bob Liuc34346d2012-08-16 11:40:30 +0800812#if defined(CONFIG_BF54x) || defined(CONFIG_BF60x)
Mike Frysinger4638b212010-06-02 04:17:26 -0400813 gpio_array[gpio_bank(gpio)]->dir_set = gpio_bit(gpio);
814#else
815 gpio_array[gpio_bank(gpio)]->dir |= gpio_bit(gpio);
816#endif
817
818 AWA_DUMMY_READ(dir);
819 local_irq_restore(flags);
820
821 return 0;
822}
823
824int bfin_gpio_get_value(unsigned gpio)
825{
Bob Liuc34346d2012-08-16 11:40:30 +0800826#if defined(CONFIG_BF54x) || defined(CONFIG_BF60x)
Mike Frysinger4638b212010-06-02 04:17:26 -0400827 return (1 & (gpio_array[gpio_bank(gpio)]->data >> gpio_sub_n(gpio)));
828#else
829 unsigned long flags;
830
831 if (unlikely(get_gpio_edge(gpio))) {
832 int ret;
833 local_irq_save(flags);
834 set_gpio_edge(gpio, 0);
835 ret = get_gpio_data(gpio);
836 set_gpio_edge(gpio, 1);
837 local_irq_restore(flags);
838 return ret;
839 } else
840 return get_gpio_data(gpio);
841#endif
842}
843
844/* If we are booting from SPI and our board lacks a strong enough pull up,
845 * the core can reset and execute the bootrom faster than the resistor can
846 * pull the signal logically high. To work around this (common) error in
847 * board design, we explicitly set the pin back to GPIO mode, force /CS
848 * high, and wait for the electrons to do their thing.
849 *
850 * This function only makes sense to be called from reset code, but it
851 * lives here as we need to force all the GPIO states w/out going through
852 * BUG() checks and such.
853 */
854void bfin_reset_boot_spi_cs(unsigned short pin)
855{
856 unsigned short gpio = P_IDENT(pin);
857 port_setup(gpio, GPIO_USAGE);
858 gpio_array[gpio_bank(gpio)]->data_set = gpio_bit(gpio);
859 AWA_DUMMY_READ(data_set);
860 udelay(1);
861}
862
863#ifdef CONFIG_BFIN_GPIO_TRACK
864void bfin_gpio_labels(void)
865{
866 int c, gpio;
867
868 for (c = 0; c < MAX_RESOURCES; c++) {
869 gpio = is_reserved(gpio, c, 1);
870 if (!check_gpio(c) && gpio)
871 printf("GPIO_%d:\t%s\tGPIO %s\n", c,
872 get_label(c),
873 get_gpio_dir(c) ? "OUTPUT" : "INPUT");
874 else if (is_reserved(peri, c, 1))
875 printf("GPIO_%d:\t%s\tPeripheral\n", c, get_label(c));
876 else
877 continue;
878 }
879}
880#endif