]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - drivers/gpio/omap_gpio.c
d2d2640db89e39275536b8940b474b764c7aabb2
[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 <asm/gpio.h>
23 #include <asm/io.h>
24 #include <asm/errno.h>
25
26 #define OMAP_GPIO_DIR_OUT       0
27 #define OMAP_GPIO_DIR_IN        1
28
29 static inline int get_gpio_index(int gpio)
30 {
31         return gpio & 0x1f;
32 }
33
34 int gpio_is_valid(int gpio)
35 {
36         return (gpio >= 0) && (gpio < OMAP_MAX_GPIO);
37 }
38
39 static void _set_gpio_direction(const struct gpio_bank *bank, int gpio,
40                                 int is_input)
41 {
42         void *reg = bank->base;
43         u32 l;
44
45         switch (bank->method) {
46         case METHOD_GPIO_24XX:
47                 reg += OMAP_GPIO_OE;
48                 break;
49         default:
50                 return;
51         }
52         l = __raw_readl(reg);
53         if (is_input)
54                 l |= 1 << gpio;
55         else
56                 l &= ~(1 << gpio);
57         __raw_writel(l, reg);
58 }
59
60 /**
61  * Get the direction of the GPIO by reading the GPIO_OE register
62  * corresponding to the specified bank.
63  */
64 static int _get_gpio_direction(const struct gpio_bank *bank, int gpio)
65 {
66         void *reg = bank->base;
67         u32 v;
68
69         switch (bank->method) {
70         case METHOD_GPIO_24XX:
71                 reg += OMAP_GPIO_OE;
72                 break;
73         default:
74                 return -1;
75         }
76
77         v = __raw_readl(reg);
78
79         if (v & (1 << gpio))
80                 return OMAP_GPIO_DIR_IN;
81         else
82                 return OMAP_GPIO_DIR_OUT;
83 }
84
85 static void _set_gpio_dataout(const struct gpio_bank *bank, int gpio,
86                                 int enable)
87 {
88         void *reg = bank->base;
89         u32 l = 0;
90
91         switch (bank->method) {
92         case METHOD_GPIO_24XX:
93                 if (enable)
94                         reg += OMAP_GPIO_SETDATAOUT;
95                 else
96                         reg += OMAP_GPIO_CLEARDATAOUT;
97                 l = 1 << gpio;
98                 break;
99         default:
100                 printf("omap3-gpio unknown bank method %s %d\n",
101                        __FILE__, __LINE__);
102                 return;
103         }
104         __raw_writel(l, reg);
105 }
106
107 static int _get_gpio_value(const struct gpio_bank *bank, int gpio)
108 {
109         void *reg = bank->base;
110         int input;
111
112         switch (bank->method) {
113         case METHOD_GPIO_24XX:
114                 input = _get_gpio_direction(bank, gpio);
115                 switch (input) {
116                 case OMAP_GPIO_DIR_IN:
117                         reg += OMAP_GPIO_DATAIN;
118                         break;
119                 case OMAP_GPIO_DIR_OUT:
120                         reg += OMAP_GPIO_DATAOUT;
121                         break;
122                 default:
123                         return -1;
124                 }
125                 break;
126         default:
127                 return -1;
128         }
129
130         return (__raw_readl(reg) & (1 << gpio)) != 0;
131 }
132
133 static inline const struct gpio_bank *get_gpio_bank(int gpio)
134 {
135         return &omap_gpio_bank[gpio >> 5];
136 }
137
138 static int check_gpio(int gpio)
139 {
140         if (!gpio_is_valid(gpio)) {
141                 printf("ERROR : check_gpio: invalid GPIO %d\n", gpio);
142                 return -1;
143         }
144         return 0;
145 }
146
147 /**
148  * Set value of the specified gpio
149  */
150 int gpio_set_value(unsigned gpio, int value)
151 {
152         const struct gpio_bank *bank;
153
154         if (check_gpio(gpio) < 0)
155                 return -1;
156         bank = get_gpio_bank(gpio);
157         _set_gpio_dataout(bank, get_gpio_index(gpio), value);
158
159         return 0;
160 }
161
162 /**
163  * Get value of the specified gpio
164  */
165 int gpio_get_value(unsigned gpio)
166 {
167         const struct gpio_bank *bank;
168
169         if (check_gpio(gpio) < 0)
170                 return -1;
171         bank = get_gpio_bank(gpio);
172
173         return _get_gpio_value(bank, get_gpio_index(gpio));
174 }
175
176 /**
177  * Set gpio direction as input
178  */
179 int gpio_direction_input(unsigned gpio)
180 {
181         const struct gpio_bank *bank;
182
183         if (check_gpio(gpio) < 0)
184                 return -1;
185
186         bank = get_gpio_bank(gpio);
187         _set_gpio_direction(bank, get_gpio_index(gpio), 1);
188
189         return 0;
190 }
191
192 /**
193  * Set gpio direction as output
194  */
195 int gpio_direction_output(unsigned gpio, int value)
196 {
197         const struct gpio_bank *bank;
198
199         if (check_gpio(gpio) < 0)
200                 return -1;
201
202         bank = get_gpio_bank(gpio);
203         _set_gpio_dataout(bank, get_gpio_index(gpio), value);
204         _set_gpio_direction(bank, get_gpio_index(gpio), 0);
205
206         return 0;
207 }
208
209 /**
210  * Request a gpio before using it.
211  *
212  * NOTE: Argument 'label' is unused.
213  */
214 int gpio_request(unsigned gpio, const char *label)
215 {
216         if (check_gpio(gpio) < 0)
217                 return -1;
218
219         return 0;
220 }
221
222 /**
223  * Reset and free the gpio after using it.
224  */
225 int gpio_free(unsigned gpio)
226 {
227         return 0;
228 }