Merge branch 'master' of git://git.denx.de/u-boot-mpc83xx
[oweals/u-boot.git] / arch / arm / cpu / armv7 / omap-common / gpio.c
1 /*
2  * Copyright (c) 2009 Wind River Systems, Inc.
3  * Tom Rix <Tom.Rix@windriver.com>
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License as
7  * published by the Free Software Foundation; either version 2 of
8  * the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
18  * MA 02111-1307 USA
19  *
20  * This work is derived from the linux 2.6.27 kernel source
21  * To fetch, use the kernel repository
22  * git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
23  * Use the v2.6.27 tag.
24  *
25  * Below is the original's header including its copyright
26  *
27  *  linux/arch/arm/plat-omap/gpio.c
28  *
29  * Support functions for OMAP GPIO
30  *
31  * Copyright (C) 2003-2005 Nokia Corporation
32  * Written by Juha Yrjölä <juha.yrjola@nokia.com>
33  *
34  * This program is free software; you can redistribute it and/or modify
35  * it under the terms of the GNU General Public License version 2 as
36  * published by the Free Software Foundation.
37  */
38 #include <common.h>
39 #include <asm/arch/gpio.h>
40 #include <asm/io.h>
41 #include <asm/errno.h>
42
43 #define OMAP_GPIO_DIR_OUT       0
44 #define OMAP_GPIO_DIR_IN        1
45
46 static inline const struct gpio_bank *get_gpio_bank(int gpio)
47 {
48         return &omap_gpio_bank[gpio >> 5];
49 }
50
51 static inline int get_gpio_index(int gpio)
52 {
53         return gpio & 0x1f;
54 }
55
56 static inline int gpio_valid(int gpio)
57 {
58         if (gpio < 0)
59                 return -EINVAL;
60         if (gpio < 192)
61                 return 0;
62         return -EINVAL;
63 }
64
65 static int check_gpio(int gpio)
66 {
67         if (gpio_valid(gpio) < 0) {
68                 printf("ERROR : check_gpio: invalid GPIO %d\n", gpio);
69                 return -EINVAL;
70         }
71         return 0;
72 }
73
74 static void _set_gpio_direction(const struct gpio_bank *bank, int gpio,
75                                 int is_input)
76 {
77         void *reg = bank->base;
78         u32 l;
79
80         switch (bank->method) {
81         case METHOD_GPIO_24XX:
82                 reg += OMAP_GPIO_OE;
83                 break;
84         default:
85                 return;
86         }
87         l = __raw_readl(reg);
88         if (is_input)
89                 l |= 1 << gpio;
90         else
91                 l &= ~(1 << gpio);
92         __raw_writel(l, reg);
93 }
94
95 /**
96  * Get the direction of the GPIO by reading the GPIO_OE register
97  * corresponding to the specified bank.
98  */
99 static int _get_gpio_direction(const struct gpio_bank *bank, int gpio)
100 {
101         void *reg = bank->base;
102         u32 v;
103
104         switch (bank->method) {
105         case METHOD_GPIO_24XX:
106                 reg += OMAP_GPIO_OE;
107                 break;
108         default:
109                 return -EINVAL;
110         }
111
112         v = __raw_readl(reg);
113
114         if (v & (1 << gpio))
115                 return OMAP_GPIO_DIR_IN;
116         else
117                 return OMAP_GPIO_DIR_OUT;
118 }
119
120 static void _set_gpio_dataout(const struct gpio_bank *bank, int gpio,
121                                 int enable)
122 {
123         void *reg = bank->base;
124         u32 l = 0;
125
126         switch (bank->method) {
127         case METHOD_GPIO_24XX:
128                 if (enable)
129                         reg += OMAP_GPIO_SETDATAOUT;
130                 else
131                         reg += OMAP_GPIO_CLEARDATAOUT;
132                 l = 1 << gpio;
133                 break;
134         default:
135                 printf("omap3-gpio unknown bank method %s %d\n",
136                        __FILE__, __LINE__);
137                 return;
138         }
139         __raw_writel(l, reg);
140 }
141
142 /**
143  * Set value of the specified gpio
144  */
145 void gpio_set_value(int gpio, int value)
146 {
147         const struct gpio_bank *bank;
148
149         if (check_gpio(gpio) < 0)
150                 return;
151         bank = get_gpio_bank(gpio);
152         _set_gpio_dataout(bank, get_gpio_index(gpio), value);
153 }
154
155 /**
156  * Get value of the specified gpio
157  */
158 int gpio_get_value(int gpio)
159 {
160         const struct gpio_bank *bank;
161         void *reg;
162         int input;
163
164         if (check_gpio(gpio) < 0)
165                 return -EINVAL;
166         bank = get_gpio_bank(gpio);
167         reg = bank->base;
168         switch (bank->method) {
169         case METHOD_GPIO_24XX:
170                 input = _get_gpio_direction(bank, get_gpio_index(gpio));
171                 switch (input) {
172                 case OMAP_GPIO_DIR_IN:
173                         reg += OMAP_GPIO_DATAIN;
174                         break;
175                 case OMAP_GPIO_DIR_OUT:
176                         reg += OMAP_GPIO_DATAOUT;
177                         break;
178                 default:
179                         return -EINVAL;
180                 }
181                 break;
182         default:
183                 return -EINVAL;
184         }
185         return (__raw_readl(reg)
186                         & (1 << get_gpio_index(gpio))) != 0;
187 }
188
189 /**
190  * Set gpio direction as input
191  */
192 int gpio_direction_input(unsigned gpio)
193 {
194         const struct gpio_bank *bank;
195
196         if (check_gpio(gpio) < 0)
197                 return -EINVAL;
198
199         bank = get_gpio_bank(gpio);
200         _set_gpio_direction(bank, get_gpio_index(gpio), 1);
201
202         return 0;
203 }
204
205 /**
206  * Set gpio direction as output
207  */
208 int gpio_direction_output(unsigned gpio, int value)
209 {
210         const struct gpio_bank *bank;
211
212         if (check_gpio(gpio) < 0)
213                 return -EINVAL;
214
215         bank = get_gpio_bank(gpio);
216         _set_gpio_dataout(bank, get_gpio_index(gpio), value);
217         _set_gpio_direction(bank, get_gpio_index(gpio), 0);
218
219         return 0;
220 }
221
222 /**
223  * Request a gpio before using it.
224  *
225  * NOTE: Argument 'label' is unused.
226  */
227 int gpio_request(int gpio, const char *label)
228 {
229         if (check_gpio(gpio) < 0)
230                 return -EINVAL;
231
232         return 0;
233 }
234
235 /**
236  * Reset and free the gpio after using it.
237  */
238 void gpio_free(unsigned gpio)
239 {
240 }