blob: a4651bc700ba24247b09f7d30faeecb7d690966b [file] [log] [blame]
Tom Rix0c872ec2009-05-15 23:48:36 +02001/*
2 * Copyright (c) 2009 Wind River Systems, Inc.
3 * Tom Rix <Tom.Rix@windriver.com>
4 *
Wolfgang Denkbcd4d4e2013-07-28 22:12:44 +02005 * SPDX-License-Identifier: GPL-2.0
Tom Rix0c872ec2009-05-15 23:48:36 +02006 *
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>
Tom Rix0c872ec2009-05-15 23:48:36 +020020 */
21#include <common.h>
Simon Glass5915a2a2014-10-22 21:37:09 -060022#include <dm.h>
Joe Hershberger365d6072011-11-11 15:55:36 -060023#include <asm/gpio.h>
Tom Rix0c872ec2009-05-15 23:48:36 +020024#include <asm/io.h>
25#include <asm/errno.h>
26
Sanjeev Premi81bdc152011-09-08 10:47:25 -040027#define OMAP_GPIO_DIR_OUT 0
28#define OMAP_GPIO_DIR_IN 1
29
Simon Glass5915a2a2014-10-22 21:37:09 -060030#ifdef CONFIG_DM_GPIO
31
32#define GPIO_NAME_SIZE 20
33#define GPIO_PER_BANK 32
34
35struct 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
Tom Rix0c872ec2009-05-15 23:48:36 +020044static inline int get_gpio_index(int gpio)
45{
46 return gpio & 0x1f;
47}
48
Nikita Kiryanovdcee1ab2012-11-27 22:40:57 +000049int gpio_is_valid(int gpio)
Tom Rix0c872ec2009-05-15 23:48:36 +020050{
Axel Lin87bd05d2013-06-21 18:54:25 +080051 return (gpio >= 0) && (gpio < OMAP_MAX_GPIO);
Tom Rix0c872ec2009-05-15 23:48:36 +020052}
53
Aneesh V25223a62011-07-21 09:29:29 -040054static void _set_gpio_direction(const struct gpio_bank *bank, int gpio,
55 int is_input)
Tom Rix0c872ec2009-05-15 23:48:36 +020056{
57 void *reg = bank->base;
58 u32 l;
59
60 switch (bank->method) {
61 case METHOD_GPIO_24XX:
Aneesh V25223a62011-07-21 09:29:29 -040062 reg += OMAP_GPIO_OE;
Tom Rix0c872ec2009-05-15 23:48:36 +020063 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
Sanjeev Premi81bdc152011-09-08 10:47:25 -040075/**
76 * Get the direction of the GPIO by reading the GPIO_OE register
77 * corresponding to the specified bank.
78 */
79static int _get_gpio_direction(const struct gpio_bank *bank, int gpio)
Tom Rix0c872ec2009-05-15 23:48:36 +020080{
Sanjeev Premi81bdc152011-09-08 10:47:25 -040081 void *reg = bank->base;
82 u32 v;
Tom Rix0c872ec2009-05-15 23:48:36 +020083
Sanjeev Premi81bdc152011-09-08 10:47:25 -040084 switch (bank->method) {
85 case METHOD_GPIO_24XX:
86 reg += OMAP_GPIO_OE;
87 break;
88 default:
Joe Hershberger365d6072011-11-11 15:55:36 -060089 return -1;
Sanjeev Premi81bdc152011-09-08 10:47:25 -040090 }
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;
Tom Rix0c872ec2009-05-15 23:48:36 +020098}
99
Aneesh V25223a62011-07-21 09:29:29 -0400100static void _set_gpio_dataout(const struct gpio_bank *bank, int gpio,
101 int enable)
Tom Rix0c872ec2009-05-15 23:48:36 +0200102{
103 void *reg = bank->base;
104 u32 l = 0;
105
106 switch (bank->method) {
107 case METHOD_GPIO_24XX:
108 if (enable)
Aneesh V25223a62011-07-21 09:29:29 -0400109 reg += OMAP_GPIO_SETDATAOUT;
Tom Rix0c872ec2009-05-15 23:48:36 +0200110 else
Aneesh V25223a62011-07-21 09:29:29 -0400111 reg += OMAP_GPIO_CLEARDATAOUT;
Tom Rix0c872ec2009-05-15 23:48:36 +0200112 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
Simon Glassd57b6112014-10-22 21:37:08 -0600122static 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
Simon Glass5915a2a2014-10-22 21:37:09 -0600148#ifndef CONFIG_DM_GPIO
149
Simon Glassd57b6112014-10-22 21:37:08 -0600150static inline const struct gpio_bank *get_gpio_bank(int gpio)
151{
152 return &omap_gpio_bank[gpio >> 5];
153}
154
155static 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
Sanjeev Premi81bdc152011-09-08 10:47:25 -0400164/**
165 * Set value of the specified gpio
166 */
Joe Hershberger365d6072011-11-11 15:55:36 -0600167int gpio_set_value(unsigned gpio, int value)
Tom Rix0c872ec2009-05-15 23:48:36 +0200168{
Aneesh V25223a62011-07-21 09:29:29 -0400169 const struct gpio_bank *bank;
Tom Rix0c872ec2009-05-15 23:48:36 +0200170
171 if (check_gpio(gpio) < 0)
Joe Hershberger365d6072011-11-11 15:55:36 -0600172 return -1;
Tom Rix0c872ec2009-05-15 23:48:36 +0200173 bank = get_gpio_bank(gpio);
Sanjeev Premi81bdc152011-09-08 10:47:25 -0400174 _set_gpio_dataout(bank, get_gpio_index(gpio), value);
Joe Hershberger365d6072011-11-11 15:55:36 -0600175
176 return 0;
Tom Rix0c872ec2009-05-15 23:48:36 +0200177}
178
Sanjeev Premi81bdc152011-09-08 10:47:25 -0400179/**
180 * Get value of the specified gpio
181 */
Joe Hershberger365d6072011-11-11 15:55:36 -0600182int gpio_get_value(unsigned gpio)
Tom Rix0c872ec2009-05-15 23:48:36 +0200183{
Aneesh V25223a62011-07-21 09:29:29 -0400184 const struct gpio_bank *bank;
Tom Rix0c872ec2009-05-15 23:48:36 +0200185
186 if (check_gpio(gpio) < 0)
Joe Hershberger365d6072011-11-11 15:55:36 -0600187 return -1;
Tom Rix0c872ec2009-05-15 23:48:36 +0200188 bank = get_gpio_bank(gpio);
Simon Glassd57b6112014-10-22 21:37:08 -0600189
190 return _get_gpio_value(bank, get_gpio_index(gpio));
Tom Rix0c872ec2009-05-15 23:48:36 +0200191}
192
Sanjeev Premi81bdc152011-09-08 10:47:25 -0400193/**
194 * Set gpio direction as input
195 */
196int gpio_direction_input(unsigned gpio)
Joel A Fernandes569919d2011-09-04 11:10:03 -0500197{
Sanjeev Premi81bdc152011-09-08 10:47:25 -0400198 const struct gpio_bank *bank;
Joel A Fernandes569919d2011-09-04 11:10:03 -0500199
200 if (check_gpio(gpio) < 0)
Joe Hershberger365d6072011-11-11 15:55:36 -0600201 return -1;
Joel A Fernandes569919d2011-09-04 11:10:03 -0500202
Sanjeev Premi81bdc152011-09-08 10:47:25 -0400203 bank = get_gpio_bank(gpio);
Tom Rix0c872ec2009-05-15 23:48:36 +0200204 _set_gpio_direction(bank, get_gpio_index(gpio), 1);
Sanjeev Premi81bdc152011-09-08 10:47:25 -0400205
206 return 0;
Tom Rix0c872ec2009-05-15 23:48:36 +0200207}
208
Sanjeev Premi81bdc152011-09-08 10:47:25 -0400209/**
210 * Set gpio direction as output
211 */
212int gpio_direction_output(unsigned gpio, int value)
213{
214 const struct gpio_bank *bank;
215
216 if (check_gpio(gpio) < 0)
Joe Hershberger365d6072011-11-11 15:55:36 -0600217 return -1;
Sanjeev Premi81bdc152011-09-08 10:47:25 -0400218
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 */
Joe Hershberger365d6072011-11-11 15:55:36 -0600231int gpio_request(unsigned gpio, const char *label)
Tom Rix0c872ec2009-05-15 23:48:36 +0200232{
233 if (check_gpio(gpio) < 0)
Joe Hershberger365d6072011-11-11 15:55:36 -0600234 return -1;
Tom Rix0c872ec2009-05-15 23:48:36 +0200235
236 return 0;
237}
238
Sanjeev Premi81bdc152011-09-08 10:47:25 -0400239/**
240 * Reset and free the gpio after using it.
241 */
Joe Hershberger365d6072011-11-11 15:55:36 -0600242int gpio_free(unsigned gpio)
Tom Rix0c872ec2009-05-15 23:48:36 +0200243{
Joe Hershberger365d6072011-11-11 15:55:36 -0600244 return 0;
Tom Rix0c872ec2009-05-15 23:48:36 +0200245}
Simon Glass5915a2a2014-10-22 21:37:09 -0600246
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 */
256static inline bool gpio_is_requested(struct gpio_bank *bank, int offset)
257{
258 return *bank->label[offset] != '\0';
259}
260
261static 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
266static 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 */
282static 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' */
298static 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' */
315static 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' */
328static 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
343static 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
370static 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
384static 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
397static 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
411static 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
422static 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
441U_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 */