xref: /openbmc/u-boot/drivers/gpio/omap_gpio.c (revision ecd4551f)
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/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 -1;
60 	if (gpio < 192)
61 		return 0;
62 	return -1;
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 -1;
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 -1;
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 int gpio_set_value(unsigned gpio, int value)
146 {
147 	const struct gpio_bank *bank;
148 
149 	if (check_gpio(gpio) < 0)
150 		return -1;
151 	bank = get_gpio_bank(gpio);
152 	_set_gpio_dataout(bank, get_gpio_index(gpio), value);
153 
154 	return 0;
155 }
156 
157 /**
158  * Get value of the specified gpio
159  */
160 int gpio_get_value(unsigned gpio)
161 {
162 	const struct gpio_bank *bank;
163 	void *reg;
164 	int input;
165 
166 	if (check_gpio(gpio) < 0)
167 		return -1;
168 	bank = get_gpio_bank(gpio);
169 	reg = bank->base;
170 	switch (bank->method) {
171 	case METHOD_GPIO_24XX:
172 		input = _get_gpio_direction(bank, get_gpio_index(gpio));
173 		switch (input) {
174 		case OMAP_GPIO_DIR_IN:
175 			reg += OMAP_GPIO_DATAIN;
176 			break;
177 		case OMAP_GPIO_DIR_OUT:
178 			reg += OMAP_GPIO_DATAOUT;
179 			break;
180 		default:
181 			return -1;
182 		}
183 		break;
184 	default:
185 		return -1;
186 	}
187 	return (__raw_readl(reg)
188 			& (1 << get_gpio_index(gpio))) != 0;
189 }
190 
191 /**
192  * Set gpio direction as input
193  */
194 int gpio_direction_input(unsigned gpio)
195 {
196 	const struct gpio_bank *bank;
197 
198 	if (check_gpio(gpio) < 0)
199 		return -1;
200 
201 	bank = get_gpio_bank(gpio);
202 	_set_gpio_direction(bank, get_gpio_index(gpio), 1);
203 
204 	return 0;
205 }
206 
207 /**
208  * Set gpio direction as output
209  */
210 int gpio_direction_output(unsigned gpio, int value)
211 {
212 	const struct gpio_bank *bank;
213 
214 	if (check_gpio(gpio) < 0)
215 		return -1;
216 
217 	bank = get_gpio_bank(gpio);
218 	_set_gpio_dataout(bank, get_gpio_index(gpio), value);
219 	_set_gpio_direction(bank, get_gpio_index(gpio), 0);
220 
221 	return 0;
222 }
223 
224 /**
225  * Request a gpio before using it.
226  *
227  * NOTE: Argument 'label' is unused.
228  */
229 int gpio_request(unsigned gpio, const char *label)
230 {
231 	if (check_gpio(gpio) < 0)
232 		return -1;
233 
234 	return 0;
235 }
236 
237 /**
238  * Reset and free the gpio after using it.
239  */
240 int gpio_free(unsigned gpio)
241 {
242 	return 0;
243 }
244