blob: d2d2640db89e39275536b8940b474b764c7aabb2 [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>
Joe Hershberger365d6072011-11-11 15:55:36 -060022#include <asm/gpio.h>
Tom Rix0c872ec2009-05-15 23:48:36 +020023#include <asm/io.h>
24#include <asm/errno.h>
25
Sanjeev Premi81bdc152011-09-08 10:47:25 -040026#define OMAP_GPIO_DIR_OUT 0
27#define OMAP_GPIO_DIR_IN 1
28
Tom Rix0c872ec2009-05-15 23:48:36 +020029static inline int get_gpio_index(int gpio)
30{
31 return gpio & 0x1f;
32}
33
Nikita Kiryanovdcee1ab2012-11-27 22:40:57 +000034int gpio_is_valid(int gpio)
Tom Rix0c872ec2009-05-15 23:48:36 +020035{
Axel Lin87bd05d2013-06-21 18:54:25 +080036 return (gpio >= 0) && (gpio < OMAP_MAX_GPIO);
Tom Rix0c872ec2009-05-15 23:48:36 +020037}
38
Aneesh V25223a62011-07-21 09:29:29 -040039static void _set_gpio_direction(const struct gpio_bank *bank, int gpio,
40 int is_input)
Tom Rix0c872ec2009-05-15 23:48:36 +020041{
42 void *reg = bank->base;
43 u32 l;
44
45 switch (bank->method) {
46 case METHOD_GPIO_24XX:
Aneesh V25223a62011-07-21 09:29:29 -040047 reg += OMAP_GPIO_OE;
Tom Rix0c872ec2009-05-15 23:48:36 +020048 break;
49 default:
50 return;
51 }
52 l = __raw_readl(reg);
53 if (is_input)
54 l |= 1 << gpio;
55 else
56 l &= ~(1 << gpio);
57 __raw_writel(l, reg);
58}
59
Sanjeev Premi81bdc152011-09-08 10:47:25 -040060/**
61 * Get the direction of the GPIO by reading the GPIO_OE register
62 * corresponding to the specified bank.
63 */
64static int _get_gpio_direction(const struct gpio_bank *bank, int gpio)
Tom Rix0c872ec2009-05-15 23:48:36 +020065{
Sanjeev Premi81bdc152011-09-08 10:47:25 -040066 void *reg = bank->base;
67 u32 v;
Tom Rix0c872ec2009-05-15 23:48:36 +020068
Sanjeev Premi81bdc152011-09-08 10:47:25 -040069 switch (bank->method) {
70 case METHOD_GPIO_24XX:
71 reg += OMAP_GPIO_OE;
72 break;
73 default:
Joe Hershberger365d6072011-11-11 15:55:36 -060074 return -1;
Sanjeev Premi81bdc152011-09-08 10:47:25 -040075 }
76
77 v = __raw_readl(reg);
78
79 if (v & (1 << gpio))
80 return OMAP_GPIO_DIR_IN;
81 else
82 return OMAP_GPIO_DIR_OUT;
Tom Rix0c872ec2009-05-15 23:48:36 +020083}
84
Aneesh V25223a62011-07-21 09:29:29 -040085static void _set_gpio_dataout(const struct gpio_bank *bank, int gpio,
86 int enable)
Tom Rix0c872ec2009-05-15 23:48:36 +020087{
88 void *reg = bank->base;
89 u32 l = 0;
90
91 switch (bank->method) {
92 case METHOD_GPIO_24XX:
93 if (enable)
Aneesh V25223a62011-07-21 09:29:29 -040094 reg += OMAP_GPIO_SETDATAOUT;
Tom Rix0c872ec2009-05-15 23:48:36 +020095 else
Aneesh V25223a62011-07-21 09:29:29 -040096 reg += OMAP_GPIO_CLEARDATAOUT;
Tom Rix0c872ec2009-05-15 23:48:36 +020097 l = 1 << gpio;
98 break;
99 default:
100 printf("omap3-gpio unknown bank method %s %d\n",
101 __FILE__, __LINE__);
102 return;
103 }
104 __raw_writel(l, reg);
105}
106
Simon Glassd57b6112014-10-22 21:37:08 -0600107static int _get_gpio_value(const struct gpio_bank *bank, int gpio)
108{
109 void *reg = bank->base;
110 int input;
111
112 switch (bank->method) {
113 case METHOD_GPIO_24XX:
114 input = _get_gpio_direction(bank, gpio);
115 switch (input) {
116 case OMAP_GPIO_DIR_IN:
117 reg += OMAP_GPIO_DATAIN;
118 break;
119 case OMAP_GPIO_DIR_OUT:
120 reg += OMAP_GPIO_DATAOUT;
121 break;
122 default:
123 return -1;
124 }
125 break;
126 default:
127 return -1;
128 }
129
130 return (__raw_readl(reg) & (1 << gpio)) != 0;
131}
132
133static inline const struct gpio_bank *get_gpio_bank(int gpio)
134{
135 return &omap_gpio_bank[gpio >> 5];
136}
137
138static int check_gpio(int gpio)
139{
140 if (!gpio_is_valid(gpio)) {
141 printf("ERROR : check_gpio: invalid GPIO %d\n", gpio);
142 return -1;
143 }
144 return 0;
145}
146
Sanjeev Premi81bdc152011-09-08 10:47:25 -0400147/**
148 * Set value of the specified gpio
149 */
Joe Hershberger365d6072011-11-11 15:55:36 -0600150int gpio_set_value(unsigned gpio, int value)
Tom Rix0c872ec2009-05-15 23:48:36 +0200151{
Aneesh V25223a62011-07-21 09:29:29 -0400152 const struct gpio_bank *bank;
Tom Rix0c872ec2009-05-15 23:48:36 +0200153
154 if (check_gpio(gpio) < 0)
Joe Hershberger365d6072011-11-11 15:55:36 -0600155 return -1;
Tom Rix0c872ec2009-05-15 23:48:36 +0200156 bank = get_gpio_bank(gpio);
Sanjeev Premi81bdc152011-09-08 10:47:25 -0400157 _set_gpio_dataout(bank, get_gpio_index(gpio), value);
Joe Hershberger365d6072011-11-11 15:55:36 -0600158
159 return 0;
Tom Rix0c872ec2009-05-15 23:48:36 +0200160}
161
Sanjeev Premi81bdc152011-09-08 10:47:25 -0400162/**
163 * Get value of the specified gpio
164 */
Joe Hershberger365d6072011-11-11 15:55:36 -0600165int gpio_get_value(unsigned gpio)
Tom Rix0c872ec2009-05-15 23:48:36 +0200166{
Aneesh V25223a62011-07-21 09:29:29 -0400167 const struct gpio_bank *bank;
Tom Rix0c872ec2009-05-15 23:48:36 +0200168
169 if (check_gpio(gpio) < 0)
Joe Hershberger365d6072011-11-11 15:55:36 -0600170 return -1;
Tom Rix0c872ec2009-05-15 23:48:36 +0200171 bank = get_gpio_bank(gpio);
Simon Glassd57b6112014-10-22 21:37:08 -0600172
173 return _get_gpio_value(bank, get_gpio_index(gpio));
Tom Rix0c872ec2009-05-15 23:48:36 +0200174}
175
Sanjeev Premi81bdc152011-09-08 10:47:25 -0400176/**
177 * Set gpio direction as input
178 */
179int gpio_direction_input(unsigned gpio)
Joel A Fernandes569919d2011-09-04 11:10:03 -0500180{
Sanjeev Premi81bdc152011-09-08 10:47:25 -0400181 const struct gpio_bank *bank;
Joel A Fernandes569919d2011-09-04 11:10:03 -0500182
183 if (check_gpio(gpio) < 0)
Joe Hershberger365d6072011-11-11 15:55:36 -0600184 return -1;
Joel A Fernandes569919d2011-09-04 11:10:03 -0500185
Sanjeev Premi81bdc152011-09-08 10:47:25 -0400186 bank = get_gpio_bank(gpio);
Tom Rix0c872ec2009-05-15 23:48:36 +0200187 _set_gpio_direction(bank, get_gpio_index(gpio), 1);
Sanjeev Premi81bdc152011-09-08 10:47:25 -0400188
189 return 0;
Tom Rix0c872ec2009-05-15 23:48:36 +0200190}
191
Sanjeev Premi81bdc152011-09-08 10:47:25 -0400192/**
193 * Set gpio direction as output
194 */
195int gpio_direction_output(unsigned gpio, int value)
196{
197 const struct gpio_bank *bank;
198
199 if (check_gpio(gpio) < 0)
Joe Hershberger365d6072011-11-11 15:55:36 -0600200 return -1;
Sanjeev Premi81bdc152011-09-08 10:47:25 -0400201
202 bank = get_gpio_bank(gpio);
203 _set_gpio_dataout(bank, get_gpio_index(gpio), value);
204 _set_gpio_direction(bank, get_gpio_index(gpio), 0);
205
206 return 0;
207}
208
209/**
210 * Request a gpio before using it.
211 *
212 * NOTE: Argument 'label' is unused.
213 */
Joe Hershberger365d6072011-11-11 15:55:36 -0600214int gpio_request(unsigned gpio, const char *label)
Tom Rix0c872ec2009-05-15 23:48:36 +0200215{
216 if (check_gpio(gpio) < 0)
Joe Hershberger365d6072011-11-11 15:55:36 -0600217 return -1;
Tom Rix0c872ec2009-05-15 23:48:36 +0200218
219 return 0;
220}
221
Sanjeev Premi81bdc152011-09-08 10:47:25 -0400222/**
223 * Reset and free the gpio after using it.
224 */
Joe Hershberger365d6072011-11-11 15:55:36 -0600225int gpio_free(unsigned gpio)
Tom Rix0c872ec2009-05-15 23:48:36 +0200226{
Joe Hershberger365d6072011-11-11 15:55:36 -0600227 return 0;
Tom Rix0c872ec2009-05-15 23:48:36 +0200228}