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