]> git.sur5r.net Git - u-boot/blob - drivers/gpio/adi_gpio2.c
gpio: omap_gpio: Add DM_FLAG_PRE_RELOC flag
[u-boot] / drivers / gpio / adi_gpio2.c
1 /*
2  * ADI GPIO2 Abstraction Layer
3  * Support BF54x, BF60x and future processors.
4  *
5  * Copyright 2008-2013 Analog Devices Inc.
6  *
7  * Licensed under the GPL-2 or later
8  */
9
10 #include <common.h>
11 #include <linux/errno.h>
12 #include <asm/gpio.h>
13
14 #define RESOURCE_LABEL_SIZE     16
15
16 static struct str_ident {
17         char name[RESOURCE_LABEL_SIZE];
18 } str_ident[MAX_RESOURCES];
19
20 static void gpio_error(unsigned gpio)
21 {
22         printf("adi_gpio2: GPIO %d wasn't requested!\n", gpio);
23 }
24
25 static void set_label(unsigned short ident, const char *label)
26 {
27         if (label) {
28                 strncpy(str_ident[ident].name, label,
29                         RESOURCE_LABEL_SIZE);
30                 str_ident[ident].name[RESOURCE_LABEL_SIZE - 1] = 0;
31         }
32 }
33
34 static char *get_label(unsigned short ident)
35 {
36         return *str_ident[ident].name ? str_ident[ident].name : "UNKNOWN";
37 }
38
39 static int cmp_label(unsigned short ident, const char *label)
40 {
41         if (label == NULL)
42                 printf("adi_gpio2: please provide none-null label\n");
43
44         if (label)
45                 return strcmp(str_ident[ident].name, label);
46         else
47                 return -EINVAL;
48 }
49
50 #define map_entry(m, i)      reserved_##m##_map[gpio_bank(i)]
51 #define is_reserved(m, i, e) (map_entry(m, i) & gpio_bit(i))
52 #define reserve(m, i)        (map_entry(m, i) |= gpio_bit(i))
53 #define unreserve(m, i)      (map_entry(m, i) &= ~gpio_bit(i))
54 #define DECLARE_RESERVED_MAP(m, c) unsigned short reserved_##m##_map[c]
55
56 static DECLARE_RESERVED_MAP(gpio, GPIO_BANK_NUM);
57 static DECLARE_RESERVED_MAP(peri, gpio_bank(MAX_RESOURCES));
58
59 inline int check_gpio(unsigned gpio)
60 {
61 #if defined(CONFIG_BF54x)
62         if (gpio == GPIO_PB15 || gpio == GPIO_PC14 || gpio == GPIO_PC15 ||
63                 gpio == GPIO_PH14 || gpio == GPIO_PH15 ||
64                 gpio == GPIO_PJ14 || gpio == GPIO_PJ15)
65                 return -EINVAL;
66 #endif
67         if (gpio >= MAX_GPIOS)
68                 return -EINVAL;
69         return 0;
70 }
71
72 static void port_setup(unsigned gpio, unsigned short usage)
73 {
74 #if defined(CONFIG_BF54x)
75         if (usage == GPIO_USAGE)
76                 gpio_array[gpio_bank(gpio)]->port_fer &= ~gpio_bit(gpio);
77         else
78                 gpio_array[gpio_bank(gpio)]->port_fer |= gpio_bit(gpio);
79 #else
80         if (usage == GPIO_USAGE)
81                 gpio_array[gpio_bank(gpio)]->port_fer_clear = gpio_bit(gpio);
82         else
83                 gpio_array[gpio_bank(gpio)]->port_fer_set = gpio_bit(gpio);
84 #endif
85 }
86
87 inline void portmux_setup(unsigned short per)
88 {
89         u32 pmux;
90         u16 ident = P_IDENT(per);
91         u16 function = P_FUNCT2MUX(per);
92
93         pmux = gpio_array[gpio_bank(ident)]->port_mux;
94
95         pmux &= ~(0x3 << (2 * gpio_sub_n(ident)));
96         pmux |= (function & 0x3) << (2 * gpio_sub_n(ident));
97
98         gpio_array[gpio_bank(ident)]->port_mux = pmux;
99 }
100
101 inline u16 get_portmux(unsigned short per)
102 {
103         u32 pmux;
104         u16 ident = P_IDENT(per);
105
106         pmux = gpio_array[gpio_bank(ident)]->port_mux;
107
108         return pmux >> (2 * gpio_sub_n(ident)) & 0x3;
109 }
110
111 unsigned short get_gpio_dir(unsigned gpio)
112 {
113         return 0x01 &
114                 (gpio_array[gpio_bank(gpio)]->dir_clear >> gpio_sub_n(gpio));
115 }
116
117 /***********************************************************
118 *
119 * FUNCTIONS:    Peripheral Resource Allocation
120 *               and PortMux Setup
121 *
122 * INPUTS/OUTPUTS:
123 * per   Peripheral Identifier
124 * label String
125 *
126 * DESCRIPTION: Peripheral Resource Allocation and Setup API
127 **************************************************************/
128
129 int peripheral_request(unsigned short per, const char *label)
130 {
131         unsigned short ident = P_IDENT(per);
132
133         /*
134          * Don't cares are pins with only one dedicated function
135          */
136
137         if (per & P_DONTCARE)
138                 return 0;
139
140         if (!(per & P_DEFINED))
141                 return -EINVAL;
142
143         BUG_ON(ident >= MAX_RESOURCES);
144
145         /* If a pin can be muxed as either GPIO or peripheral, make
146          * sure it is not already a GPIO pin when we request it.
147          */
148         if (unlikely(!check_gpio(ident) && is_reserved(gpio, ident, 1))) {
149                 printf("%s: Peripheral %d is already reserved as GPIO by %s!\n",
150                        __func__, ident, get_label(ident));
151                 return -EBUSY;
152         }
153
154         if (unlikely(is_reserved(peri, ident, 1))) {
155                 /*
156                  * Pin functions like AMC address strobes my
157                  * be requested and used by several drivers
158                  */
159
160                 if (!((per & P_MAYSHARE) &&
161                         get_portmux(per) == P_FUNCT2MUX(per))) {
162                         /*
163                          * Allow that the identical pin function can
164                          * be requested from the same driver twice
165                          */
166
167                         if (cmp_label(ident, label) == 0)
168                                 goto anyway;
169
170                         printf("%s: Peripheral %d function %d is already "
171                                 "reserved by %s!\n", __func__, ident,
172                                 P_FUNCT2MUX(per), get_label(ident));
173                         return -EBUSY;
174                 }
175         }
176
177  anyway:
178         reserve(peri, ident);
179
180         portmux_setup(per);
181         port_setup(ident, PERIPHERAL_USAGE);
182
183         set_label(ident, label);
184
185         return 0;
186 }
187
188 int peripheral_request_list(const unsigned short per[], const char *label)
189 {
190         u16 cnt;
191         int ret;
192
193         for (cnt = 0; per[cnt] != 0; cnt++) {
194                 ret = peripheral_request(per[cnt], label);
195
196                 if (ret < 0) {
197                         for (; cnt > 0; cnt--)
198                                 peripheral_free(per[cnt - 1]);
199
200                         return ret;
201                 }
202         }
203
204         return 0;
205 }
206
207 void peripheral_free(unsigned short per)
208 {
209         unsigned short ident = P_IDENT(per);
210
211         if (per & P_DONTCARE)
212                 return;
213
214         if (!(per & P_DEFINED))
215                 return;
216
217         if (unlikely(!is_reserved(peri, ident, 0)))
218                 return;
219
220         if (!(per & P_MAYSHARE))
221                 port_setup(ident, GPIO_USAGE);
222
223         unreserve(peri, ident);
224
225         set_label(ident, "free");
226 }
227
228 void peripheral_free_list(const unsigned short per[])
229 {
230         u16 cnt;
231         for (cnt = 0; per[cnt] != 0; cnt++)
232                 peripheral_free(per[cnt]);
233 }
234
235 /***********************************************************
236 *
237 * FUNCTIONS: GPIO Driver
238 *
239 * INPUTS/OUTPUTS:
240 * gpio  PIO Number between 0 and MAX_GPIOS
241 * label String
242 *
243 * DESCRIPTION: GPIO Driver API
244 **************************************************************/
245
246 int gpio_request(unsigned gpio, const char *label)
247 {
248         if (check_gpio(gpio) < 0)
249                 return -EINVAL;
250
251         /*
252          * Allow that the identical GPIO can
253          * be requested from the same driver twice
254          * Do nothing and return -
255          */
256
257         if (cmp_label(gpio, label) == 0)
258                 return 0;
259
260         if (unlikely(is_reserved(gpio, gpio, 1))) {
261                 printf("adi_gpio2: GPIO %d is already reserved by %s!\n",
262                         gpio, get_label(gpio));
263                 return -EBUSY;
264         }
265         if (unlikely(is_reserved(peri, gpio, 1))) {
266                 printf("adi_gpio2: GPIO %d is already reserved as Peripheral "
267                         "by %s!\n", gpio, get_label(gpio));
268                 return -EBUSY;
269         }
270
271         reserve(gpio, gpio);
272         set_label(gpio, label);
273
274         port_setup(gpio, GPIO_USAGE);
275
276         return 0;
277 }
278
279 int gpio_free(unsigned gpio)
280 {
281         if (check_gpio(gpio) < 0)
282                 return -1;
283
284         if (unlikely(!is_reserved(gpio, gpio, 0))) {
285                 gpio_error(gpio);
286                 return -1;
287         }
288
289         unreserve(gpio, gpio);
290
291         set_label(gpio, "free");
292
293         return 0;
294 }
295
296 #ifdef ADI_SPECIAL_GPIO_BANKS
297 static DECLARE_RESERVED_MAP(special_gpio, gpio_bank(MAX_RESOURCES));
298
299 int special_gpio_request(unsigned gpio, const char *label)
300 {
301         /*
302          * Allow that the identical GPIO can
303          * be requested from the same driver twice
304          * Do nothing and return -
305          */
306
307         if (cmp_label(gpio, label) == 0)
308                 return 0;
309
310         if (unlikely(is_reserved(special_gpio, gpio, 1))) {
311                 printf("adi_gpio2: GPIO %d is already reserved by %s!\n",
312                         gpio, get_label(gpio));
313                 return -EBUSY;
314         }
315         if (unlikely(is_reserved(peri, gpio, 1))) {
316                 printf("adi_gpio2: GPIO %d is already reserved as Peripheral "
317                         "by %s!\n", gpio, get_label(gpio));
318
319                 return -EBUSY;
320         }
321
322         reserve(special_gpio, gpio);
323         reserve(peri, gpio);
324
325         set_label(gpio, label);
326         port_setup(gpio, GPIO_USAGE);
327
328         return 0;
329 }
330
331 void special_gpio_free(unsigned gpio)
332 {
333         if (unlikely(!is_reserved(special_gpio, gpio, 0))) {
334                 gpio_error(gpio);
335                 return;
336         }
337
338         unreserve(special_gpio, gpio);
339         unreserve(peri, gpio);
340         set_label(gpio, "free");
341 }
342 #endif
343
344 static inline void __gpio_direction_input(unsigned gpio)
345 {
346         gpio_array[gpio_bank(gpio)]->dir_clear = gpio_bit(gpio);
347 #if defined(CONFIG_BF54x)
348         gpio_array[gpio_bank(gpio)]->inen |= gpio_bit(gpio);
349 #else
350         gpio_array[gpio_bank(gpio)]->inen_set = gpio_bit(gpio);
351 #endif
352 }
353
354 int gpio_direction_input(unsigned gpio)
355 {
356         unsigned long flags;
357
358         if (!is_reserved(gpio, gpio, 0)) {
359                 gpio_error(gpio);
360                 return -EINVAL;
361         }
362
363         local_irq_save(flags);
364         __gpio_direction_input(gpio);
365         local_irq_restore(flags);
366
367         return 0;
368 }
369
370 int gpio_set_value(unsigned gpio, int arg)
371 {
372         if (arg)
373                 gpio_array[gpio_bank(gpio)]->data_set = gpio_bit(gpio);
374         else
375                 gpio_array[gpio_bank(gpio)]->data_clear = gpio_bit(gpio);
376
377         return 0;
378 }
379
380 int gpio_direction_output(unsigned gpio, int value)
381 {
382         unsigned long flags;
383
384         if (!is_reserved(gpio, gpio, 0)) {
385                 gpio_error(gpio);
386                 return -EINVAL;
387         }
388
389         local_irq_save(flags);
390
391 #if defined(CONFIG_BF54x)
392         gpio_array[gpio_bank(gpio)]->inen &= ~gpio_bit(gpio);
393 #else
394         gpio_array[gpio_bank(gpio)]->inen_clear = gpio_bit(gpio);
395 #endif
396         gpio_set_value(gpio, value);
397         gpio_array[gpio_bank(gpio)]->dir_set = gpio_bit(gpio);
398
399         local_irq_restore(flags);
400
401         return 0;
402 }
403
404 int gpio_get_value(unsigned gpio)
405 {
406         return 1 & (gpio_array[gpio_bank(gpio)]->data >> gpio_sub_n(gpio));
407 }
408
409 void gpio_labels(void)
410 {
411         int c, gpio;
412
413         for (c = 0; c < MAX_RESOURCES; c++) {
414                 gpio = is_reserved(gpio, c, 1);
415                 if (!check_gpio(c) && gpio)
416                         printf("GPIO_%d:\t%s\tGPIO %s\n", c, get_label(c),
417                                 get_gpio_dir(c) ? "OUTPUT" : "INPUT");
418                 else if (is_reserved(peri, c, 1))
419                         printf("GPIO_%d:\t%s\tPeripheral\n", c, get_label(c));
420                 else
421                         continue;
422         }
423 }