blob: 19d2db0242bd1f9367401464a26f45c960c3493e [file] [log] [blame]
Simon Glass8d30fcd2012-02-15 15:51:13 -08001/*
2 * Copyright (c) 2011 The Chromium OS Authors.
3 * See file CREDITS for list of people who contributed to this
4 * project.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 2 of
9 * the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
19 * MA 02111-1307 USA
20 */
21
22#include <common.h>
23#include <asm/gpio.h>
24
25/* Flags for each GPIO */
26#define GPIOF_OUTPUT (1 << 0) /* Currently set as an output */
27#define GPIOF_HIGH (1 << 1) /* Currently set high */
28#define GPIOF_RESERVED (1 << 2) /* Is in use / requested */
29
30struct gpio_state {
31 const char *label; /* label given by requester */
32 u8 flags; /* flags (GPIOF_...) */
33};
34
35/*
36 * State of GPIOs
37 * TODO: Put this into sandbox state
38 */
39static struct gpio_state state[CONFIG_SANDBOX_GPIO_COUNT];
40
41/* Access routines for GPIO state */
42static u8 *get_gpio_flags(unsigned gp)
43{
44 /* assert()'s could be disabled, so make sure we handle that */
45 assert(gp < ARRAY_SIZE(state));
46 if (gp >= ARRAY_SIZE(state)) {
47 static u8 invalid_flags;
48 printf("sandbox_gpio: error: invalid gpio %u\n", gp);
49 return &invalid_flags;
50 }
51
52 return &state[gp].flags;
53}
54
55static int get_gpio_flag(unsigned gp, int flag)
56{
57 return (*get_gpio_flags(gp) & flag) != 0;
58}
59
60static int set_gpio_flag(unsigned gp, int flag, int value)
61{
62 u8 *gpio = get_gpio_flags(gp);
63
64 if (value)
65 *gpio |= flag;
66 else
67 *gpio &= ~flag;
68
69 return 0;
70}
71
72static int check_reserved(unsigned gpio, const char *func)
73{
74 if (!get_gpio_flag(gpio, GPIOF_RESERVED)) {
75 printf("sandbox_gpio: %s: error: gpio %u not reserved\n",
76 func, gpio);
77 return -1;
78 }
79
80 return 0;
81}
82
83/*
84 * Back-channel sandbox-internal-only access to GPIO state
85 */
86
87int sandbox_gpio_get_value(unsigned gp)
88{
89 if (get_gpio_flag(gp, GPIOF_OUTPUT))
90 debug("sandbox_gpio: get_value on output gpio %u\n", gp);
91 return get_gpio_flag(gp, GPIOF_HIGH);
92}
93
94int sandbox_gpio_set_value(unsigned gp, int value)
95{
96 return set_gpio_flag(gp, GPIOF_HIGH, value);
97}
98
99int sandbox_gpio_get_direction(unsigned gp)
100{
101 return get_gpio_flag(gp, GPIOF_OUTPUT);
102}
103
104int sandbox_gpio_set_direction(unsigned gp, int output)
105{
106 return set_gpio_flag(gp, GPIOF_OUTPUT, output);
107}
108
109/*
110 * These functions implement the public interface within U-Boot
111 */
112
113/* set GPIO port 'gp' as an input */
114int gpio_direction_input(unsigned gp)
115{
116 debug("%s: gp:%u\n", __func__, gp);
117
118 if (check_reserved(gp, __func__))
119 return -1;
120
121 return sandbox_gpio_set_direction(gp, 0);
122}
123
124/* set GPIO port 'gp' as an output, with polarity 'value' */
125int gpio_direction_output(unsigned gp, int value)
126{
127 debug("%s: gp:%u, value = %d\n", __func__, gp, value);
128
129 if (check_reserved(gp, __func__))
130 return -1;
131
132 return sandbox_gpio_set_direction(gp, 1) |
133 sandbox_gpio_set_value(gp, value);
134}
135
136/* read GPIO IN value of port 'gp' */
137int gpio_get_value(unsigned gp)
138{
139 debug("%s: gp:%u\n", __func__, gp);
140
141 if (check_reserved(gp, __func__))
142 return -1;
143
144 return sandbox_gpio_get_value(gp);
145}
146
147/* write GPIO OUT value to port 'gp' */
148int gpio_set_value(unsigned gp, int value)
149{
150 debug("%s: gp:%u, value = %d\n", __func__, gp, value);
151
152 if (check_reserved(gp, __func__))
153 return -1;
154
155 if (!sandbox_gpio_get_direction(gp)) {
156 printf("sandbox_gpio: error: set_value on input gpio %u\n", gp);
157 return -1;
158 }
159
160 return sandbox_gpio_set_value(gp, value);
161}
162
163int gpio_request(unsigned gp, const char *label)
164{
165 debug("%s: gp:%u, label:%s\n", __func__, gp, label);
166
167 if (gp >= ARRAY_SIZE(state)) {
168 printf("sandbox_gpio: error: invalid gpio %u\n", gp);
169 return -1;
170 }
171
172 if (get_gpio_flag(gp, GPIOF_RESERVED)) {
173 printf("sandbox_gpio: error: gpio %u already reserved\n", gp);
174 return -1;
175 }
176
177 state[gp].label = label;
178 return set_gpio_flag(gp, GPIOF_RESERVED, 1);
179}
180
181int gpio_free(unsigned gp)
182{
183 debug("%s: gp:%u\n", __func__, gp);
184
185 if (check_reserved(gp, __func__))
186 return -1;
187
188 state[gp].label = NULL;
189 return set_gpio_flag(gp, GPIOF_RESERVED, 0);
190}
191
192/* Display GPIO information */
193void gpio_info(void)
194{
195 unsigned gpio;
196
197 puts("Sandbox GPIOs\n");
198
199 for (gpio = 0; gpio < ARRAY_SIZE(state); ++gpio) {
200 const char *label = state[gpio].label;
201
202 printf("%4d: %s: %d [%c] %s\n",
203 gpio,
204 sandbox_gpio_get_direction(gpio) ? "out" : " in",
205 sandbox_gpio_get_value(gpio),
206 get_gpio_flag(gpio, GPIOF_RESERVED) ? 'x' : ' ',
207 label ? label : "");
208 }
209}