]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - drivers/gpio/omap_gpio.c
a4651bc700ba24247b09f7d30faeecb7d690966b
[karo-tx-uboot.git] / drivers / gpio / omap_gpio.c
1 /*
2  * Copyright (c) 2009 Wind River Systems, Inc.
3  * Tom Rix <Tom.Rix@windriver.com>
4  *
5  * SPDX-License-Identifier:     GPL-2.0
6  *
7  * This work is derived from the linux 2.6.27 kernel source
8  * To fetch, use the kernel repository
9  * git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
10  * Use the v2.6.27 tag.
11  *
12  * Below is the original's header including its copyright
13  *
14  *  linux/arch/arm/plat-omap/gpio.c
15  *
16  * Support functions for OMAP GPIO
17  *
18  * Copyright (C) 2003-2005 Nokia Corporation
19  * Written by Juha Yrjölä <juha.yrjola@nokia.com>
20  */
21 #include <common.h>
22 #include <dm.h>
23 #include <asm/gpio.h>
24 #include <asm/io.h>
25 #include <asm/errno.h>
26
27 #define OMAP_GPIO_DIR_OUT       0
28 #define OMAP_GPIO_DIR_IN        1
29
30 #ifdef CONFIG_DM_GPIO
31
32 #define GPIO_NAME_SIZE                  20
33 #define GPIO_PER_BANK                   32
34
35 struct gpio_bank {
36         char label[GPIO_PER_BANK][GPIO_NAME_SIZE];
37         /* TODO(sjg@chromium.org): Can we use a struct here? */
38         void *base;     /* address of registers in physical memory */
39         enum gpio_method method;
40 };
41
42 #endif
43
44 static inline int get_gpio_index(int gpio)
45 {
46         return gpio & 0x1f;
47 }
48
49 int gpio_is_valid(int gpio)
50 {
51         return (gpio >= 0) && (gpio < OMAP_MAX_GPIO);
52 }
53
54 static void _set_gpio_direction(const struct gpio_bank *bank, int gpio,
55                                 int is_input)
56 {
57         void *reg = bank->base;
58         u32 l;
59
60         switch (bank->method) {
61         case METHOD_GPIO_24XX:
62                 reg += OMAP_GPIO_OE;
63                 break;
64         default:
65                 return;
66         }
67         l = __raw_readl(reg);
68         if (is_input)
69                 l |= 1 << gpio;
70         else
71                 l &= ~(1 << gpio);
72         __raw_writel(l, reg);
73 }
74
75 /**
76  * Get the direction of the GPIO by reading the GPIO_OE register
77  * corresponding to the specified bank.
78  */
79 static int _get_gpio_direction(const struct gpio_bank *bank, int gpio)
80 {
81         void *reg = bank->base;
82         u32 v;
83
84         switch (bank->method) {
85         case METHOD_GPIO_24XX:
86                 reg += OMAP_GPIO_OE;
87                 break;
88         default:
89                 return -1;
90         }
91
92         v = __raw_readl(reg);
93
94         if (v & (1 << gpio))
95                 return OMAP_GPIO_DIR_IN;
96         else
97                 return OMAP_GPIO_DIR_OUT;
98 }
99
100 static void _set_gpio_dataout(const struct gpio_bank *bank, int gpio,
101                                 int enable)
102 {
103         void *reg = bank->base;
104         u32 l = 0;
105
106         switch (bank->method) {
107         case METHOD_GPIO_24XX:
108                 if (enable)
109                         reg += OMAP_GPIO_SETDATAOUT;
110                 else
111                         reg += OMAP_GPIO_CLEARDATAOUT;
112                 l = 1 << gpio;
113                 break;
114         default:
115                 printf("omap3-gpio unknown bank method %s %d\n",
116                        __FILE__, __LINE__);
117                 return;
118         }
119         __raw_writel(l, reg);
120 }
121
122 static int _get_gpio_value(const struct gpio_bank *bank, int gpio)
123 {
124         void *reg = bank->base;
125         int input;
126
127         switch (bank->method) {
128         case METHOD_GPIO_24XX:
129                 input = _get_gpio_direction(bank, gpio);
130                 switch (input) {
131                 case OMAP_GPIO_DIR_IN:
132                         reg += OMAP_GPIO_DATAIN;
133                         break;
134                 case OMAP_GPIO_DIR_OUT:
135                         reg += OMAP_GPIO_DATAOUT;
136                         break;
137                 default:
138                         return -1;
139                 }
140                 break;
141         default:
142                 return -1;
143         }
144
145         return (__raw_readl(reg) & (1 << gpio)) != 0;
146 }
147
148 #ifndef CONFIG_DM_GPIO
149
150 static inline const struct gpio_bank *get_gpio_bank(int gpio)
151 {
152         return &omap_gpio_bank[gpio >> 5];
153 }
154
155 static int check_gpio(int gpio)
156 {
157         if (!gpio_is_valid(gpio)) {
158                 printf("ERROR : check_gpio: invalid GPIO %d\n", gpio);
159                 return -1;
160         }
161         return 0;
162 }
163
164 /**
165  * Set value of the specified gpio
166  */
167 int gpio_set_value(unsigned gpio, int value)
168 {
169         const struct gpio_bank *bank;
170
171         if (check_gpio(gpio) < 0)
172                 return -1;
173         bank = get_gpio_bank(gpio);
174         _set_gpio_dataout(bank, get_gpio_index(gpio), value);
175
176         return 0;
177 }
178
179 /**
180  * Get value of the specified gpio
181  */
182 int gpio_get_value(unsigned gpio)
183 {
184         const struct gpio_bank *bank;
185
186         if (check_gpio(gpio) < 0)
187                 return -1;
188         bank = get_gpio_bank(gpio);
189
190         return _get_gpio_value(bank, get_gpio_index(gpio));
191 }
192
193 /**
194  * Set gpio direction as input
195  */
196 int gpio_direction_input(unsigned gpio)
197 {
198         const struct gpio_bank *bank;
199
200         if (check_gpio(gpio) < 0)
201                 return -1;
202
203         bank = get_gpio_bank(gpio);
204         _set_gpio_direction(bank, get_gpio_index(gpio), 1);
205
206         return 0;
207 }
208
209 /**
210  * Set gpio direction as output
211  */
212 int gpio_direction_output(unsigned gpio, int value)
213 {
214         const struct gpio_bank *bank;
215
216         if (check_gpio(gpio) < 0)
217                 return -1;
218
219         bank = get_gpio_bank(gpio);
220         _set_gpio_dataout(bank, get_gpio_index(gpio), value);
221         _set_gpio_direction(bank, get_gpio_index(gpio), 0);
222
223         return 0;
224 }
225
226 /**
227  * Request a gpio before using it.
228  *
229  * NOTE: Argument 'label' is unused.
230  */
231 int gpio_request(unsigned gpio, const char *label)
232 {
233         if (check_gpio(gpio) < 0)
234                 return -1;
235
236         return 0;
237 }
238
239 /**
240  * Reset and free the gpio after using it.
241  */
242 int gpio_free(unsigned gpio)
243 {
244         return 0;
245 }
246
247 #else /* new driver model interface CONFIG_DM_GPIO */
248
249 /**
250  * gpio_is_requested() - check if a GPIO has been requested
251  *
252  * @bank:       Bank to check
253  * @offset:     GPIO offset within bank to check
254  * @return true if marked as requested, false if not
255  */
256 static inline bool gpio_is_requested(struct gpio_bank *bank, int offset)
257 {
258         return *bank->label[offset] != '\0';
259 }
260
261 static int omap_gpio_is_output(struct gpio_bank *bank, int offset)
262 {
263         return _get_gpio_direction(bank, offset) == OMAP_GPIO_DIR_OUT;
264 }
265
266 static int check_requested(struct udevice *dev, unsigned offset,
267                            const char *func)
268 {
269         struct gpio_bank *bank = dev_get_priv(dev);
270         struct gpio_dev_priv *uc_priv = dev->uclass_priv;
271
272         if (!gpio_is_requested(bank, offset)) {
273                 printf("omap_gpio: %s: error: gpio %s%d not requested\n",
274                        func, uc_priv->bank_name, offset);
275                 return -EPERM;
276         }
277
278         return 0;
279 }
280
281 /* set GPIO pin 'gpio' as an input */
282 static int omap_gpio_direction_input(struct udevice *dev, unsigned offset)
283 {
284         struct gpio_bank *bank = dev_get_priv(dev);
285         int ret;
286
287         ret = check_requested(dev, offset, __func__);
288         if (ret)
289                 return ret;
290
291         /* Configure GPIO direction as input. */
292         _set_gpio_direction(bank, offset, 1);
293
294         return 0;
295 }
296
297 /* set GPIO pin 'gpio' as an output, with polarity 'value' */
298 static int omap_gpio_direction_output(struct udevice *dev, unsigned offset,
299                                        int value)
300 {
301         struct gpio_bank *bank = dev_get_priv(dev);
302         int ret;
303
304         ret = check_requested(dev, offset, __func__);
305         if (ret)
306                 return ret;
307
308         _set_gpio_dataout(bank, offset, value);
309         _set_gpio_direction(bank, offset, 0);
310
311         return 0;
312 }
313
314 /* read GPIO IN value of pin 'gpio' */
315 static int omap_gpio_get_value(struct udevice *dev, unsigned offset)
316 {
317         struct gpio_bank *bank = dev_get_priv(dev);
318         int ret;
319
320         ret = check_requested(dev, offset, __func__);
321         if (ret)
322                 return ret;
323
324         return _get_gpio_value(bank, offset);
325 }
326
327 /* write GPIO OUT value to pin 'gpio' */
328 static int omap_gpio_set_value(struct udevice *dev, unsigned offset,
329                                  int value)
330 {
331         struct gpio_bank *bank = dev_get_priv(dev);
332         int ret;
333
334         ret = check_requested(dev, offset, __func__);
335         if (ret)
336                 return ret;
337
338         _set_gpio_dataout(bank, offset, value);
339
340         return 0;
341 }
342
343 static int omap_gpio_get_state(struct udevice *dev, unsigned int offset,
344                               char *buf, int bufsize)
345 {
346         struct gpio_dev_priv *uc_priv = dev->uclass_priv;
347         struct gpio_bank *bank = dev_get_priv(dev);
348         const char *label;
349         bool requested;
350         bool is_output;
351         int size;
352
353         label = bank->label[offset];
354         is_output = omap_gpio_is_output(bank->base, offset);
355         size = snprintf(buf, bufsize, "%s%d: ",
356                         uc_priv->bank_name ? uc_priv->bank_name : "", offset);
357         buf += size;
358         bufsize -= size;
359         requested = gpio_is_requested(bank, offset);
360         snprintf(buf, bufsize, "%s: %d [%c]%s%s",
361                  is_output ? "out" : " in",
362                  _get_gpio_value(bank, offset),
363                  requested ? 'x' : ' ',
364                  requested ? " " : "",
365                  label);
366
367         return 0;
368 }
369
370 static int omap_gpio_request(struct udevice *dev, unsigned offset,
371                               const char *label)
372 {
373         struct gpio_bank *bank = dev_get_priv(dev);
374
375         if (gpio_is_requested(bank, offset))
376                 return -EBUSY;
377
378         strncpy(bank->label[offset], label, GPIO_NAME_SIZE);
379         bank->label[offset][GPIO_NAME_SIZE - 1] = '\0';
380
381         return 0;
382 }
383
384 static int omap_gpio_free(struct udevice *dev, unsigned offset)
385 {
386         struct gpio_bank *bank = dev_get_priv(dev);
387         int ret;
388
389         ret = check_requested(dev, offset, __func__);
390         if (ret)
391                 return ret;
392         bank->label[offset][0] = '\0';
393
394         return 0;
395 }
396
397 static int omap_gpio_get_function(struct udevice *dev, unsigned offset)
398 {
399         struct gpio_bank *bank = dev_get_priv(dev);
400
401         if (!gpio_is_requested(bank, offset))
402                 return GPIOF_UNUSED;
403
404         /* GPIOF_FUNC is not implemented yet */
405         if (_get_gpio_direction(bank->base, offset))
406                 return GPIOF_OUTPUT;
407         else
408                 return GPIOF_INPUT;
409 }
410
411 static const struct dm_gpio_ops gpio_omap_ops = {
412         .request                = omap_gpio_request,
413         .free                   = omap_gpio_free,
414         .direction_input        = omap_gpio_direction_input,
415         .direction_output       = omap_gpio_direction_output,
416         .get_value              = omap_gpio_get_value,
417         .set_value              = omap_gpio_set_value,
418         .get_function           = omap_gpio_get_function,
419         .get_state              = omap_gpio_get_state,
420 };
421
422 static int omap_gpio_probe(struct udevice *dev)
423 {
424         struct gpio_bank *bank = dev_get_priv(dev);
425         struct omap_gpio_platdata *plat = dev_get_platdata(dev);
426         struct gpio_dev_priv *uc_priv = dev->uclass_priv;
427         char name[18], *str;
428
429         sprintf(name, "GPIO%d_", plat->bank_index);
430         str = strdup(name);
431         if (!str)
432                 return -ENOMEM;
433         uc_priv->bank_name = str;
434         uc_priv->gpio_count = GPIO_PER_BANK;
435         bank->base = (void *)plat->base;
436         bank->method = plat->method;
437
438         return 0;
439 }
440
441 U_BOOT_DRIVER(gpio_omap) = {
442         .name   = "gpio_omap",
443         .id     = UCLASS_GPIO,
444         .ops    = &gpio_omap_ops,
445         .probe  = omap_gpio_probe,
446         .priv_auto_alloc_size = sizeof(struct gpio_bank),
447 };
448
449 #endif /* CONFIG_DM_GPIO */