xref: /rk3399_rockchip-uboot/drivers/gpio/tegra_gpio.c (revision 52a8b82074d1c3a3dcde8e3d90e6a04f7eb3a1f8)
1*52a8b820STom Warren /*
2*52a8b820STom Warren  * NVIDIA Tegra2 GPIO handling.
3*52a8b820STom Warren  *  (C) Copyright 2010-2012
4*52a8b820STom Warren  *  NVIDIA Corporation <www.nvidia.com>
5*52a8b820STom Warren  *
6*52a8b820STom Warren  * See file CREDITS for list of people who contributed to this
7*52a8b820STom Warren  * project.
8*52a8b820STom Warren  *
9*52a8b820STom Warren  * This program is free software; you can redistribute it and/or
10*52a8b820STom Warren  * modify it under the terms of the GNU General Public License as
11*52a8b820STom Warren  * published by the Free Software Foundation; either version 2 of
12*52a8b820STom Warren  * the License, or (at your option) any later version.
13*52a8b820STom Warren  *
14*52a8b820STom Warren  * This program is distributed in the hope that it will be useful,
15*52a8b820STom Warren  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16*52a8b820STom Warren  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17*52a8b820STom Warren  * GNU General Public License for more details.
18*52a8b820STom Warren  *
19*52a8b820STom Warren  * You should have received a copy of the GNU General Public License
20*52a8b820STom Warren  * along with this program; if not, write to the Free Software
21*52a8b820STom Warren  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
22*52a8b820STom Warren  * MA 02111-1307 USA
23*52a8b820STom Warren  */
24*52a8b820STom Warren 
25*52a8b820STom Warren /*
26*52a8b820STom Warren  * Based on (mostly copied from) kw_gpio.c based Linux 2.6 kernel driver.
27*52a8b820STom Warren  * Tom Warren (twarren@nvidia.com)
28*52a8b820STom Warren  */
29*52a8b820STom Warren 
30*52a8b820STom Warren #include <common.h>
31*52a8b820STom Warren #include <asm/io.h>
32*52a8b820STom Warren #include <asm/bitops.h>
33*52a8b820STom Warren #include <asm/arch/tegra2.h>
34*52a8b820STom Warren #include <asm/gpio.h>
35*52a8b820STom Warren 
36*52a8b820STom Warren enum {
37*52a8b820STom Warren 	TEGRA2_CMD_INFO,
38*52a8b820STom Warren 	TEGRA2_CMD_PORT,
39*52a8b820STom Warren 	TEGRA2_CMD_OUTPUT,
40*52a8b820STom Warren 	TEGRA2_CMD_INPUT,
41*52a8b820STom Warren };
42*52a8b820STom Warren 
43*52a8b820STom Warren static struct gpio_names {
44*52a8b820STom Warren 	char name[GPIO_NAME_SIZE];
45*52a8b820STom Warren } gpio_names[MAX_NUM_GPIOS];
46*52a8b820STom Warren 
47*52a8b820STom Warren static char *get_name(int i)
48*52a8b820STom Warren {
49*52a8b820STom Warren 	return *gpio_names[i].name ? gpio_names[i].name : "UNKNOWN";
50*52a8b820STom Warren }
51*52a8b820STom Warren 
52*52a8b820STom Warren /* Return config of pin 'gpio' as GPIO (1) or SFPIO (0) */
53*52a8b820STom Warren static int get_config(unsigned gpio)
54*52a8b820STom Warren {
55*52a8b820STom Warren 	struct gpio_ctlr *ctlr = (struct gpio_ctlr *)NV_PA_GPIO_BASE;
56*52a8b820STom Warren 	struct gpio_ctlr_bank *bank = &ctlr->gpio_bank[GPIO_BANK(gpio)];
57*52a8b820STom Warren 	u32 u;
58*52a8b820STom Warren 	int type;
59*52a8b820STom Warren 
60*52a8b820STom Warren 	u = readl(&bank->gpio_config[GPIO_PORT(gpio)]);
61*52a8b820STom Warren 	type =  (u >> GPIO_BIT(gpio)) & 1;
62*52a8b820STom Warren 
63*52a8b820STom Warren 	debug("get_config: port = %d, bit = %d is %s\n",
64*52a8b820STom Warren 		GPIO_FULLPORT(gpio), GPIO_BIT(gpio), type ? "GPIO" : "SFPIO");
65*52a8b820STom Warren 
66*52a8b820STom Warren 	return type;
67*52a8b820STom Warren }
68*52a8b820STom Warren 
69*52a8b820STom Warren /* Config pin 'gpio' as GPIO or SFPIO, based on 'type' */
70*52a8b820STom Warren static void set_config(unsigned gpio, int type)
71*52a8b820STom Warren {
72*52a8b820STom Warren 	struct gpio_ctlr *ctlr = (struct gpio_ctlr *)NV_PA_GPIO_BASE;
73*52a8b820STom Warren 	struct gpio_ctlr_bank *bank = &ctlr->gpio_bank[GPIO_BANK(gpio)];
74*52a8b820STom Warren 	u32 u;
75*52a8b820STom Warren 
76*52a8b820STom Warren 	debug("set_config: port = %d, bit = %d, %s\n",
77*52a8b820STom Warren 		GPIO_FULLPORT(gpio), GPIO_BIT(gpio), type ? "GPIO" : "SFPIO");
78*52a8b820STom Warren 
79*52a8b820STom Warren 	u = readl(&bank->gpio_config[GPIO_PORT(gpio)]);
80*52a8b820STom Warren 	if (type)				/* GPIO */
81*52a8b820STom Warren 		u |= 1 << GPIO_BIT(gpio);
82*52a8b820STom Warren 	else
83*52a8b820STom Warren 		u &= ~(1 << GPIO_BIT(gpio));
84*52a8b820STom Warren 	writel(u, &bank->gpio_config[GPIO_PORT(gpio)]);
85*52a8b820STom Warren }
86*52a8b820STom Warren 
87*52a8b820STom Warren /* Return GPIO pin 'gpio' direction - 0 = input or 1 = output */
88*52a8b820STom Warren static int get_direction(unsigned gpio)
89*52a8b820STom Warren {
90*52a8b820STom Warren 	struct gpio_ctlr *ctlr = (struct gpio_ctlr *)NV_PA_GPIO_BASE;
91*52a8b820STom Warren 	struct gpio_ctlr_bank *bank = &ctlr->gpio_bank[GPIO_BANK(gpio)];
92*52a8b820STom Warren 	u32 u;
93*52a8b820STom Warren 	int dir;
94*52a8b820STom Warren 
95*52a8b820STom Warren 	u = readl(&bank->gpio_dir_out[GPIO_PORT(gpio)]);
96*52a8b820STom Warren 	dir =  (u >> GPIO_BIT(gpio)) & 1;
97*52a8b820STom Warren 
98*52a8b820STom Warren 	debug("get_direction: port = %d, bit = %d, %s\n",
99*52a8b820STom Warren 		GPIO_FULLPORT(gpio), GPIO_BIT(gpio), dir ? "OUT" : "IN");
100*52a8b820STom Warren 
101*52a8b820STom Warren 	return dir;
102*52a8b820STom Warren }
103*52a8b820STom Warren 
104*52a8b820STom Warren /* Config GPIO pin 'gpio' as input or output (OE) as per 'output' */
105*52a8b820STom Warren static void set_direction(unsigned gpio, int output)
106*52a8b820STom Warren {
107*52a8b820STom Warren 	struct gpio_ctlr *ctlr = (struct gpio_ctlr *)NV_PA_GPIO_BASE;
108*52a8b820STom Warren 	struct gpio_ctlr_bank *bank = &ctlr->gpio_bank[GPIO_BANK(gpio)];
109*52a8b820STom Warren 	u32 u;
110*52a8b820STom Warren 
111*52a8b820STom Warren 	debug("set_direction: port = %d, bit = %d, %s\n",
112*52a8b820STom Warren 		GPIO_FULLPORT(gpio), GPIO_BIT(gpio), output ? "OUT" : "IN");
113*52a8b820STom Warren 
114*52a8b820STom Warren 	u = readl(&bank->gpio_dir_out[GPIO_PORT(gpio)]);
115*52a8b820STom Warren 	if (output)
116*52a8b820STom Warren 		u |= 1 << GPIO_BIT(gpio);
117*52a8b820STom Warren 	else
118*52a8b820STom Warren 		u &= ~(1 << GPIO_BIT(gpio));
119*52a8b820STom Warren 	writel(u, &bank->gpio_dir_out[GPIO_PORT(gpio)]);
120*52a8b820STom Warren }
121*52a8b820STom Warren 
122*52a8b820STom Warren /* set GPIO pin 'gpio' output bit as 0 or 1 as per 'high' */
123*52a8b820STom Warren static void set_level(unsigned gpio, int high)
124*52a8b820STom Warren {
125*52a8b820STom Warren 	struct gpio_ctlr *ctlr = (struct gpio_ctlr *)NV_PA_GPIO_BASE;
126*52a8b820STom Warren 	struct gpio_ctlr_bank *bank = &ctlr->gpio_bank[GPIO_BANK(gpio)];
127*52a8b820STom Warren 	u32 u;
128*52a8b820STom Warren 
129*52a8b820STom Warren 	debug("set_level: port = %d, bit %d == %d\n",
130*52a8b820STom Warren 		GPIO_FULLPORT(gpio), GPIO_BIT(gpio), high);
131*52a8b820STom Warren 
132*52a8b820STom Warren 	u = readl(&bank->gpio_out[GPIO_PORT(gpio)]);
133*52a8b820STom Warren 	if (high)
134*52a8b820STom Warren 		u |= 1 << GPIO_BIT(gpio);
135*52a8b820STom Warren 	else
136*52a8b820STom Warren 		u &= ~(1 << GPIO_BIT(gpio));
137*52a8b820STom Warren 	writel(u, &bank->gpio_out[GPIO_PORT(gpio)]);
138*52a8b820STom Warren }
139*52a8b820STom Warren 
140*52a8b820STom Warren /*
141*52a8b820STom Warren  * Generic_GPIO primitives.
142*52a8b820STom Warren  */
143*52a8b820STom Warren 
144*52a8b820STom Warren int gpio_request(unsigned gpio, const char *label)
145*52a8b820STom Warren {
146*52a8b820STom Warren 	if (gpio >= MAX_NUM_GPIOS)
147*52a8b820STom Warren 		return -1;
148*52a8b820STom Warren 
149*52a8b820STom Warren 	if (label != NULL) {
150*52a8b820STom Warren 		strncpy(gpio_names[gpio].name, label, GPIO_NAME_SIZE);
151*52a8b820STom Warren 		gpio_names[gpio].name[GPIO_NAME_SIZE - 1] = '\0';
152*52a8b820STom Warren 	}
153*52a8b820STom Warren 
154*52a8b820STom Warren 	/* Configure as a GPIO */
155*52a8b820STom Warren 	set_config(gpio, 1);
156*52a8b820STom Warren 
157*52a8b820STom Warren 	return 0;
158*52a8b820STom Warren }
159*52a8b820STom Warren 
160*52a8b820STom Warren int gpio_free(unsigned gpio)
161*52a8b820STom Warren {
162*52a8b820STom Warren 	if (gpio >= MAX_NUM_GPIOS)
163*52a8b820STom Warren 		return -1;
164*52a8b820STom Warren 
165*52a8b820STom Warren 	gpio_names[gpio].name[0] = '\0';
166*52a8b820STom Warren 	/* Do not configure as input or change pin mux here */
167*52a8b820STom Warren 	return 0;
168*52a8b820STom Warren }
169*52a8b820STom Warren 
170*52a8b820STom Warren /* read GPIO OUT value of pin 'gpio' */
171*52a8b820STom Warren static int gpio_get_output_value(unsigned gpio)
172*52a8b820STom Warren {
173*52a8b820STom Warren 	struct gpio_ctlr *ctlr = (struct gpio_ctlr *)NV_PA_GPIO_BASE;
174*52a8b820STom Warren 	struct gpio_ctlr_bank *bank = &ctlr->gpio_bank[GPIO_BANK(gpio)];
175*52a8b820STom Warren 	int val;
176*52a8b820STom Warren 
177*52a8b820STom Warren 	debug("gpio_get_output_value: pin = %d (port %d:bit %d)\n",
178*52a8b820STom Warren 		gpio, GPIO_FULLPORT(gpio), GPIO_BIT(gpio));
179*52a8b820STom Warren 
180*52a8b820STom Warren 	val = readl(&bank->gpio_out[GPIO_PORT(gpio)]);
181*52a8b820STom Warren 
182*52a8b820STom Warren 	return (val >> GPIO_BIT(gpio)) & 1;
183*52a8b820STom Warren }
184*52a8b820STom Warren 
185*52a8b820STom Warren /* set GPIO pin 'gpio' as an input */
186*52a8b820STom Warren int gpio_direction_input(unsigned gpio)
187*52a8b820STom Warren {
188*52a8b820STom Warren 	debug("gpio_direction_input: pin = %d (port %d:bit %d)\n",
189*52a8b820STom Warren 		gpio, GPIO_FULLPORT(gpio), GPIO_BIT(gpio));
190*52a8b820STom Warren 
191*52a8b820STom Warren 	/* Configure GPIO direction as input. */
192*52a8b820STom Warren 	set_direction(gpio, 0);
193*52a8b820STom Warren 
194*52a8b820STom Warren 	return 0;
195*52a8b820STom Warren }
196*52a8b820STom Warren 
197*52a8b820STom Warren /* set GPIO pin 'gpio' as an output, with polarity 'value' */
198*52a8b820STom Warren int gpio_direction_output(unsigned gpio, int value)
199*52a8b820STom Warren {
200*52a8b820STom Warren 	debug("gpio_direction_output: pin = %d (port %d:bit %d) = %s\n",
201*52a8b820STom Warren 		gpio, GPIO_FULLPORT(gpio), GPIO_BIT(gpio),
202*52a8b820STom Warren 		value ? "HIGH" : "LOW");
203*52a8b820STom Warren 
204*52a8b820STom Warren 	/* Configure GPIO output value. */
205*52a8b820STom Warren 	set_level(gpio, value);
206*52a8b820STom Warren 
207*52a8b820STom Warren 	/* Configure GPIO direction as output. */
208*52a8b820STom Warren 	set_direction(gpio, 1);
209*52a8b820STom Warren 
210*52a8b820STom Warren 	return 0;
211*52a8b820STom Warren }
212*52a8b820STom Warren 
213*52a8b820STom Warren /* read GPIO IN value of pin 'gpio' */
214*52a8b820STom Warren int gpio_get_value(unsigned gpio)
215*52a8b820STom Warren {
216*52a8b820STom Warren 	struct gpio_ctlr *ctlr = (struct gpio_ctlr *)NV_PA_GPIO_BASE;
217*52a8b820STom Warren 	struct gpio_ctlr_bank *bank = &ctlr->gpio_bank[GPIO_BANK(gpio)];
218*52a8b820STom Warren 	int val;
219*52a8b820STom Warren 
220*52a8b820STom Warren 	debug("gpio_get_value: pin = %d (port %d:bit %d)\n",
221*52a8b820STom Warren 		gpio, GPIO_FULLPORT(gpio), GPIO_BIT(gpio));
222*52a8b820STom Warren 
223*52a8b820STom Warren 	val = readl(&bank->gpio_in[GPIO_PORT(gpio)]);
224*52a8b820STom Warren 
225*52a8b820STom Warren 	return (val >> GPIO_BIT(gpio)) & 1;
226*52a8b820STom Warren }
227*52a8b820STom Warren 
228*52a8b820STom Warren /* write GPIO OUT value to pin 'gpio' */
229*52a8b820STom Warren int gpio_set_value(unsigned gpio, int value)
230*52a8b820STom Warren {
231*52a8b820STom Warren 	debug("gpio_set_value: pin = %d (port %d:bit %d), value = %d\n",
232*52a8b820STom Warren 		gpio, GPIO_FULLPORT(gpio), GPIO_BIT(gpio), value);
233*52a8b820STom Warren 
234*52a8b820STom Warren 	/* Configure GPIO output value. */
235*52a8b820STom Warren 	set_level(gpio, value);
236*52a8b820STom Warren 
237*52a8b820STom Warren 	return 0;
238*52a8b820STom Warren }
239*52a8b820STom Warren 
240*52a8b820STom Warren /*
241*52a8b820STom Warren  * Display Tegra GPIO information
242*52a8b820STom Warren  */
243*52a8b820STom Warren void gpio_info(void)
244*52a8b820STom Warren {
245*52a8b820STom Warren 	unsigned c;
246*52a8b820STom Warren 	int type;
247*52a8b820STom Warren 
248*52a8b820STom Warren 	for (c = 0; c < MAX_NUM_GPIOS; c++) {
249*52a8b820STom Warren 		type = get_config(c);		/* GPIO, not SFPIO */
250*52a8b820STom Warren 		if (type) {
251*52a8b820STom Warren 			printf("GPIO_%d:\t%s is an %s, ", c,
252*52a8b820STom Warren 				get_name(c),
253*52a8b820STom Warren 				get_direction(c) ? "OUTPUT" : "INPUT");
254*52a8b820STom Warren 			if (get_direction(c))
255*52a8b820STom Warren 				printf("value = %d", gpio_get_output_value(c));
256*52a8b820STom Warren 			else
257*52a8b820STom Warren 				printf("value = %d", gpio_get_value(c));
258*52a8b820STom Warren 			printf("\n");
259*52a8b820STom Warren 		} else
260*52a8b820STom Warren 			continue;
261*52a8b820STom Warren 	}
262*52a8b820STom Warren }
263