~pmdj/ubuntu/trusty/qemu/2.9+applesmc+fadtv3

« back to all changes in this revision

Viewing changes to roms/u-boot/drivers/gpio/adi_gpio2.c

  • Committer: Phil Dennis-Jordan
  • Date: 2017-07-21 08:03:43 UTC
  • mfrom: (1.1.1)
  • Revision ID: phil@philjordan.eu-20170721080343-2yr2vdj7713czahv
New upstream release 2.9.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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 <asm/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 -ENODEV;
 
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
}