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