xref: /openbmc/u-boot/drivers/gpio/omap_gpio.c (revision b3f4ca11)
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 */
450