xref: /openbmc/u-boot/drivers/gpio/omap_gpio.c (revision 00a457b2)
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 <fdtdec.h>
24 #include <asm/gpio.h>
25 #include <asm/io.h>
26 #include <asm/errno.h>
27 #include <malloc.h>
28 #include <dt-bindings/gpio/gpio.h>
29 
30 DECLARE_GLOBAL_DATA_PTR;
31 
32 #define OMAP_GPIO_DIR_OUT	0
33 #define OMAP_GPIO_DIR_IN	1
34 
35 #ifdef CONFIG_DM_GPIO
36 
37 #define GPIO_PER_BANK			32
38 
39 struct gpio_bank {
40 	/* TODO(sjg@chromium.org): Can we use a struct here? */
41 	void *base;	/* address of registers in physical memory */
42 };
43 
44 #endif
45 
46 static inline int get_gpio_index(int gpio)
47 {
48 	return gpio & 0x1f;
49 }
50 
51 int gpio_is_valid(int gpio)
52 {
53 	return (gpio >= 0) && (gpio < OMAP_MAX_GPIO);
54 }
55 
56 static void _set_gpio_direction(const struct gpio_bank *bank, int gpio,
57 				int is_input)
58 {
59 	void *reg = bank->base;
60 	u32 l;
61 
62 	reg += OMAP_GPIO_OE;
63 
64 	l = __raw_readl(reg);
65 	if (is_input)
66 		l |= 1 << gpio;
67 	else
68 		l &= ~(1 << gpio);
69 	__raw_writel(l, reg);
70 }
71 
72 /**
73  * Get the direction of the GPIO by reading the GPIO_OE register
74  * corresponding to the specified bank.
75  */
76 static int _get_gpio_direction(const struct gpio_bank *bank, int gpio)
77 {
78 	void *reg = bank->base;
79 	u32 v;
80 
81 	reg += OMAP_GPIO_OE;
82 
83 	v = __raw_readl(reg);
84 
85 	if (v & (1 << gpio))
86 		return OMAP_GPIO_DIR_IN;
87 	else
88 		return OMAP_GPIO_DIR_OUT;
89 }
90 
91 static void _set_gpio_dataout(const struct gpio_bank *bank, int gpio,
92 				int enable)
93 {
94 	void *reg = bank->base;
95 	u32 l = 0;
96 
97 	if (enable)
98 		reg += OMAP_GPIO_SETDATAOUT;
99 	else
100 		reg += OMAP_GPIO_CLEARDATAOUT;
101 
102 	l = 1 << gpio;
103 	__raw_writel(l, reg);
104 }
105 
106 static int _get_gpio_value(const struct gpio_bank *bank, int gpio)
107 {
108 	void *reg = bank->base;
109 	int input;
110 
111 	input = _get_gpio_direction(bank, gpio);
112 	switch (input) {
113 	case OMAP_GPIO_DIR_IN:
114 		reg += OMAP_GPIO_DATAIN;
115 		break;
116 	case OMAP_GPIO_DIR_OUT:
117 		reg += OMAP_GPIO_DATAOUT;
118 		break;
119 	default:
120 		return -1;
121 	}
122 
123 	return (__raw_readl(reg) & (1 << gpio)) != 0;
124 }
125 
126 #ifndef CONFIG_DM_GPIO
127 
128 static inline const struct gpio_bank *get_gpio_bank(int gpio)
129 {
130 	return &omap_gpio_bank[gpio >> 5];
131 }
132 
133 static int check_gpio(int gpio)
134 {
135 	if (!gpio_is_valid(gpio)) {
136 		printf("ERROR : check_gpio: invalid GPIO %d\n", gpio);
137 		return -1;
138 	}
139 	return 0;
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 
164 	if (check_gpio(gpio) < 0)
165 		return -1;
166 	bank = get_gpio_bank(gpio);
167 
168 	return _get_gpio_value(bank, get_gpio_index(gpio));
169 }
170 
171 /**
172  * Set gpio direction as input
173  */
174 int gpio_direction_input(unsigned gpio)
175 {
176 	const struct gpio_bank *bank;
177 
178 	if (check_gpio(gpio) < 0)
179 		return -1;
180 
181 	bank = get_gpio_bank(gpio);
182 	_set_gpio_direction(bank, get_gpio_index(gpio), 1);
183 
184 	return 0;
185 }
186 
187 /**
188  * Set gpio direction as output
189  */
190 int gpio_direction_output(unsigned gpio, int value)
191 {
192 	const struct gpio_bank *bank;
193 
194 	if (check_gpio(gpio) < 0)
195 		return -1;
196 
197 	bank = get_gpio_bank(gpio);
198 	_set_gpio_dataout(bank, get_gpio_index(gpio), value);
199 	_set_gpio_direction(bank, get_gpio_index(gpio), 0);
200 
201 	return 0;
202 }
203 
204 /**
205  * Request a gpio before using it.
206  *
207  * NOTE: Argument 'label' is unused.
208  */
209 int gpio_request(unsigned gpio, const char *label)
210 {
211 	if (check_gpio(gpio) < 0)
212 		return -1;
213 
214 	return 0;
215 }
216 
217 /**
218  * Reset and free the gpio after using it.
219  */
220 int gpio_free(unsigned gpio)
221 {
222 	return 0;
223 }
224 
225 #else /* new driver model interface CONFIG_DM_GPIO */
226 
227 /* set GPIO pin 'gpio' as an input */
228 static int omap_gpio_direction_input(struct udevice *dev, unsigned offset)
229 {
230 	struct gpio_bank *bank = dev_get_priv(dev);
231 
232 	/* Configure GPIO direction as input. */
233 	_set_gpio_direction(bank, offset, 1);
234 
235 	return 0;
236 }
237 
238 /* set GPIO pin 'gpio' as an output, with polarity 'value' */
239 static int omap_gpio_direction_output(struct udevice *dev, unsigned offset,
240 				       int value)
241 {
242 	struct gpio_bank *bank = dev_get_priv(dev);
243 
244 	_set_gpio_dataout(bank, offset, value);
245 	_set_gpio_direction(bank, offset, 0);
246 
247 	return 0;
248 }
249 
250 /* read GPIO IN value of pin 'gpio' */
251 static int omap_gpio_get_value(struct udevice *dev, unsigned offset)
252 {
253 	struct gpio_bank *bank = dev_get_priv(dev);
254 
255 	return _get_gpio_value(bank, offset);
256 }
257 
258 /* write GPIO OUT value to pin 'gpio' */
259 static int omap_gpio_set_value(struct udevice *dev, unsigned offset,
260 				 int value)
261 {
262 	struct gpio_bank *bank = dev_get_priv(dev);
263 
264 	_set_gpio_dataout(bank, offset, value);
265 
266 	return 0;
267 }
268 
269 static int omap_gpio_get_function(struct udevice *dev, unsigned offset)
270 {
271 	struct gpio_bank *bank = dev_get_priv(dev);
272 
273 	/* GPIOF_FUNC is not implemented yet */
274 	if (_get_gpio_direction(bank, offset) == OMAP_GPIO_DIR_OUT)
275 		return GPIOF_OUTPUT;
276 	else
277 		return GPIOF_INPUT;
278 }
279 
280 static int omap_gpio_xlate(struct udevice *dev, struct gpio_desc *desc,
281 			   struct fdtdec_phandle_args *args)
282 {
283 	desc->offset = args->args[0];
284 	desc->flags = args->args[1] & GPIO_ACTIVE_LOW ? GPIOD_ACTIVE_LOW : 0;
285 
286 	return 0;
287 }
288 
289 static const struct dm_gpio_ops gpio_omap_ops = {
290 	.direction_input	= omap_gpio_direction_input,
291 	.direction_output	= omap_gpio_direction_output,
292 	.get_value		= omap_gpio_get_value,
293 	.set_value		= omap_gpio_set_value,
294 	.get_function		= omap_gpio_get_function,
295 	.xlate			= omap_gpio_xlate,
296 };
297 
298 static int omap_gpio_probe(struct udevice *dev)
299 {
300 	struct gpio_bank *bank = dev_get_priv(dev);
301 	struct omap_gpio_platdata *plat = dev_get_platdata(dev);
302 	struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
303 
304 	uc_priv->bank_name = plat->port_name;
305 	uc_priv->gpio_count = GPIO_PER_BANK;
306 	bank->base = (void *)plat->base;
307 
308 	return 0;
309 }
310 
311 static int omap_gpio_bind(struct udevice *dev)
312 {
313 	struct omap_gpio_platdata *plat = dev->platdata;
314 	fdt_addr_t base_addr;
315 
316 	if (plat)
317 		return 0;
318 
319 	base_addr = dev_get_addr(dev);
320 	if (base_addr == FDT_ADDR_T_NONE)
321 		return -ENODEV;
322 
323 	/*
324 	* TODO:
325 	* When every board is converted to driver model and DT is
326 	* supported, this can be done by auto-alloc feature, but
327 	* not using calloc to alloc memory for platdata.
328 	*/
329 	plat = calloc(1, sizeof(*plat));
330 	if (!plat)
331 		return -ENOMEM;
332 
333 	plat->base = base_addr;
334 	plat->port_name = fdt_get_name(gd->fdt_blob, dev->of_offset, NULL);
335 	dev->platdata = plat;
336 
337 	return 0;
338 }
339 
340 static const struct udevice_id omap_gpio_ids[] = {
341 	{ .compatible = "ti,omap3-gpio" },
342 	{ .compatible = "ti,omap4-gpio" },
343 	{ .compatible = "ti,am4372-gpio" },
344 	{ }
345 };
346 
347 U_BOOT_DRIVER(gpio_omap) = {
348 	.name	= "gpio_omap",
349 	.id	= UCLASS_GPIO,
350 	.ops	= &gpio_omap_ops,
351 	.of_match = omap_gpio_ids,
352 	.bind	= omap_gpio_bind,
353 	.probe	= omap_gpio_probe,
354 	.priv_auto_alloc_size = sizeof(struct gpio_bank),
355 };
356 
357 #endif /* CONFIG_DM_GPIO */
358