]> git.ipfire.org Git - people/ms/u-boot.git/blame - drivers/gpio/tegra_gpio.c
Add GPL-2.0+ SPDX-License-Identifier to source files
[people/ms/u-boot.git] / drivers / gpio / tegra_gpio.c
CommitLineData
4e5ae09e 1/*
00a2749d 2 * NVIDIA Tegra20 GPIO handling.
52a8b820 3 * (C) Copyright 2010-2012
4e5ae09e
TW
4 * NVIDIA Corporation <www.nvidia.com>
5 *
1a459660 6 * SPDX-License-Identifier: GPL-2.0+
4e5ae09e
TW
7 */
8
9/*
10 * Based on (mostly copied from) kw_gpio.c based Linux 2.6 kernel driver.
11 * Tom Warren (twarren@nvidia.com)
12 */
13
14#include <common.h>
15#include <asm/io.h>
16#include <asm/bitops.h>
150c2493 17#include <asm/arch/tegra.h>
4e5ae09e
TW
18#include <asm/gpio.h>
19
20enum {
29f3e3f2
TW
21 TEGRA_CMD_INFO,
22 TEGRA_CMD_PORT,
23 TEGRA_CMD_OUTPUT,
24 TEGRA_CMD_INPUT,
4e5ae09e
TW
25};
26
27static struct gpio_names {
28 char name[GPIO_NAME_SIZE];
29} gpio_names[MAX_NUM_GPIOS];
30
31static char *get_name(int i)
32{
33 return *gpio_names[i].name ? gpio_names[i].name : "UNKNOWN";
34}
35
365d6070
JH
36/* Return config of pin 'gpio' as GPIO (1) or SFPIO (0) */
37static int get_config(unsigned gpio)
4e5ae09e 38{
365d6070
JH
39 struct gpio_ctlr *ctlr = (struct gpio_ctlr *)NV_PA_GPIO_BASE;
40 struct gpio_ctlr_bank *bank = &ctlr->gpio_bank[GPIO_BANK(gpio)];
4e5ae09e
TW
41 u32 u;
42 int type;
43
365d6070
JH
44 u = readl(&bank->gpio_config[GPIO_PORT(gpio)]);
45 type = (u >> GPIO_BIT(gpio)) & 1;
4e5ae09e
TW
46
47 debug("get_config: port = %d, bit = %d is %s\n",
365d6070 48 GPIO_FULLPORT(gpio), GPIO_BIT(gpio), type ? "GPIO" : "SFPIO");
4e5ae09e
TW
49
50 return type;
51}
52
365d6070
JH
53/* Config pin 'gpio' as GPIO or SFPIO, based on 'type' */
54static void set_config(unsigned gpio, int type)
4e5ae09e 55{
365d6070
JH
56 struct gpio_ctlr *ctlr = (struct gpio_ctlr *)NV_PA_GPIO_BASE;
57 struct gpio_ctlr_bank *bank = &ctlr->gpio_bank[GPIO_BANK(gpio)];
4e5ae09e
TW
58 u32 u;
59
60 debug("set_config: port = %d, bit = %d, %s\n",
365d6070 61 GPIO_FULLPORT(gpio), GPIO_BIT(gpio), type ? "GPIO" : "SFPIO");
4e5ae09e 62
365d6070 63 u = readl(&bank->gpio_config[GPIO_PORT(gpio)]);
4e5ae09e 64 if (type) /* GPIO */
365d6070 65 u |= 1 << GPIO_BIT(gpio);
4e5ae09e 66 else
365d6070
JH
67 u &= ~(1 << GPIO_BIT(gpio));
68 writel(u, &bank->gpio_config[GPIO_PORT(gpio)]);
4e5ae09e
TW
69}
70
365d6070
JH
71/* Return GPIO pin 'gpio' direction - 0 = input or 1 = output */
72static int get_direction(unsigned gpio)
4e5ae09e 73{
365d6070
JH
74 struct gpio_ctlr *ctlr = (struct gpio_ctlr *)NV_PA_GPIO_BASE;
75 struct gpio_ctlr_bank *bank = &ctlr->gpio_bank[GPIO_BANK(gpio)];
4e5ae09e
TW
76 u32 u;
77 int dir;
78
365d6070
JH
79 u = readl(&bank->gpio_dir_out[GPIO_PORT(gpio)]);
80 dir = (u >> GPIO_BIT(gpio)) & 1;
4e5ae09e
TW
81
82 debug("get_direction: port = %d, bit = %d, %s\n",
365d6070 83 GPIO_FULLPORT(gpio), GPIO_BIT(gpio), dir ? "OUT" : "IN");
4e5ae09e
TW
84
85 return dir;
86}
87
365d6070
JH
88/* Config GPIO pin 'gpio' as input or output (OE) as per 'output' */
89static void set_direction(unsigned gpio, int output)
4e5ae09e 90{
365d6070
JH
91 struct gpio_ctlr *ctlr = (struct gpio_ctlr *)NV_PA_GPIO_BASE;
92 struct gpio_ctlr_bank *bank = &ctlr->gpio_bank[GPIO_BANK(gpio)];
4e5ae09e
TW
93 u32 u;
94
95 debug("set_direction: port = %d, bit = %d, %s\n",
365d6070 96 GPIO_FULLPORT(gpio), GPIO_BIT(gpio), output ? "OUT" : "IN");
4e5ae09e 97
365d6070 98 u = readl(&bank->gpio_dir_out[GPIO_PORT(gpio)]);
4e5ae09e 99 if (output)
365d6070 100 u |= 1 << GPIO_BIT(gpio);
4e5ae09e 101 else
365d6070
JH
102 u &= ~(1 << GPIO_BIT(gpio));
103 writel(u, &bank->gpio_dir_out[GPIO_PORT(gpio)]);
4e5ae09e
TW
104}
105
365d6070
JH
106/* set GPIO pin 'gpio' output bit as 0 or 1 as per 'high' */
107static void set_level(unsigned gpio, int high)
4e5ae09e 108{
365d6070
JH
109 struct gpio_ctlr *ctlr = (struct gpio_ctlr *)NV_PA_GPIO_BASE;
110 struct gpio_ctlr_bank *bank = &ctlr->gpio_bank[GPIO_BANK(gpio)];
4e5ae09e
TW
111 u32 u;
112
113 debug("set_level: port = %d, bit %d == %d\n",
365d6070 114 GPIO_FULLPORT(gpio), GPIO_BIT(gpio), high);
4e5ae09e 115
365d6070 116 u = readl(&bank->gpio_out[GPIO_PORT(gpio)]);
4e5ae09e 117 if (high)
365d6070 118 u |= 1 << GPIO_BIT(gpio);
4e5ae09e 119 else
365d6070
JH
120 u &= ~(1 << GPIO_BIT(gpio));
121 writel(u, &bank->gpio_out[GPIO_PORT(gpio)]);
4e5ae09e
TW
122}
123
124/*
125 * Generic_GPIO primitives.
126 */
127
365d6070 128int gpio_request(unsigned gpio, const char *label)
4e5ae09e 129{
365d6070 130 if (gpio >= MAX_NUM_GPIOS)
4e5ae09e
TW
131 return -1;
132
5fac236a 133 if (label != NULL) {
365d6070
JH
134 strncpy(gpio_names[gpio].name, label, GPIO_NAME_SIZE);
135 gpio_names[gpio].name[GPIO_NAME_SIZE - 1] = '\0';
5fac236a 136 }
4e5ae09e
TW
137
138 /* Configure as a GPIO */
365d6070 139 set_config(gpio, 1);
4e5ae09e
TW
140
141 return 0;
142}
143
365d6070 144int gpio_free(unsigned gpio)
4e5ae09e 145{
365d6070
JH
146 if (gpio >= MAX_NUM_GPIOS)
147 return -1;
148
149 gpio_names[gpio].name[0] = '\0';
150 /* Do not configure as input or change pin mux here */
151 return 0;
4e5ae09e
TW
152}
153
365d6070
JH
154/* read GPIO OUT value of pin 'gpio' */
155static int gpio_get_output_value(unsigned gpio)
4e5ae09e 156{
365d6070
JH
157 struct gpio_ctlr *ctlr = (struct gpio_ctlr *)NV_PA_GPIO_BASE;
158 struct gpio_ctlr_bank *bank = &ctlr->gpio_bank[GPIO_BANK(gpio)];
4e5ae09e
TW
159 int val;
160
161 debug("gpio_get_output_value: pin = %d (port %d:bit %d)\n",
365d6070 162 gpio, GPIO_FULLPORT(gpio), GPIO_BIT(gpio));
4e5ae09e 163
365d6070 164 val = readl(&bank->gpio_out[GPIO_PORT(gpio)]);
4e5ae09e 165
365d6070 166 return (val >> GPIO_BIT(gpio)) & 1;
4e5ae09e
TW
167}
168
365d6070
JH
169/* set GPIO pin 'gpio' as an input */
170int gpio_direction_input(unsigned gpio)
4e5ae09e
TW
171{
172 debug("gpio_direction_input: pin = %d (port %d:bit %d)\n",
365d6070 173 gpio, GPIO_FULLPORT(gpio), GPIO_BIT(gpio));
4e5ae09e
TW
174
175 /* Configure GPIO direction as input. */
365d6070 176 set_direction(gpio, 0);
4e5ae09e
TW
177
178 return 0;
179}
180
365d6070
JH
181/* set GPIO pin 'gpio' as an output, with polarity 'value' */
182int gpio_direction_output(unsigned gpio, int value)
4e5ae09e
TW
183{
184 debug("gpio_direction_output: pin = %d (port %d:bit %d) = %s\n",
365d6070
JH
185 gpio, GPIO_FULLPORT(gpio), GPIO_BIT(gpio),
186 value ? "HIGH" : "LOW");
4e5ae09e
TW
187
188 /* Configure GPIO output value. */
365d6070 189 set_level(gpio, value);
4e5ae09e
TW
190
191 /* Configure GPIO direction as output. */
365d6070 192 set_direction(gpio, 1);
4e5ae09e
TW
193
194 return 0;
195}
196
365d6070
JH
197/* read GPIO IN value of pin 'gpio' */
198int gpio_get_value(unsigned gpio)
4e5ae09e 199{
365d6070
JH
200 struct gpio_ctlr *ctlr = (struct gpio_ctlr *)NV_PA_GPIO_BASE;
201 struct gpio_ctlr_bank *bank = &ctlr->gpio_bank[GPIO_BANK(gpio)];
4e5ae09e
TW
202 int val;
203
204 debug("gpio_get_value: pin = %d (port %d:bit %d)\n",
365d6070 205 gpio, GPIO_FULLPORT(gpio), GPIO_BIT(gpio));
4e5ae09e 206
365d6070 207 val = readl(&bank->gpio_in[GPIO_PORT(gpio)]);
4e5ae09e 208
365d6070 209 return (val >> GPIO_BIT(gpio)) & 1;
4e5ae09e
TW
210}
211
365d6070
JH
212/* write GPIO OUT value to pin 'gpio' */
213int gpio_set_value(unsigned gpio, int value)
4e5ae09e
TW
214{
215 debug("gpio_set_value: pin = %d (port %d:bit %d), value = %d\n",
365d6070 216 gpio, GPIO_FULLPORT(gpio), GPIO_BIT(gpio), value);
4e5ae09e
TW
217
218 /* Configure GPIO output value. */
365d6070
JH
219 set_level(gpio, value);
220
221 return 0;
4e5ae09e
TW
222}
223
224/*
225 * Display Tegra GPIO information
226 */
227void gpio_info(void)
228{
365d6070
JH
229 unsigned c;
230 int type;
4e5ae09e
TW
231
232 for (c = 0; c < MAX_NUM_GPIOS; c++) {
233 type = get_config(c); /* GPIO, not SFPIO */
234 if (type) {
235 printf("GPIO_%d:\t%s is an %s, ", c,
236 get_name(c),
237 get_direction(c) ? "OUTPUT" : "INPUT");
238 if (get_direction(c))
239 printf("value = %d", gpio_get_output_value(c));
240 else
241 printf("value = %d", gpio_get_value(c));
242 printf("\n");
243 } else
244 continue;
245 }
246}