xref: /rk3399_rockchip-uboot/drivers/gpio/tegra_gpio.c (revision 00a2749d7be5b0e6cb6435187ec8fea600b44627)
152a8b820STom Warren /*
2*00a2749dSAllen Martin  * NVIDIA Tegra20 GPIO handling.
352a8b820STom Warren  *  (C) Copyright 2010-2012
452a8b820STom Warren  *  NVIDIA Corporation <www.nvidia.com>
552a8b820STom Warren  *
652a8b820STom Warren  * See file CREDITS for list of people who contributed to this
752a8b820STom Warren  * project.
852a8b820STom Warren  *
952a8b820STom Warren  * This program is free software; you can redistribute it and/or
1052a8b820STom Warren  * modify it under the terms of the GNU General Public License as
1152a8b820STom Warren  * published by the Free Software Foundation; either version 2 of
1252a8b820STom Warren  * the License, or (at your option) any later version.
1352a8b820STom Warren  *
1452a8b820STom Warren  * This program is distributed in the hope that it will be useful,
1552a8b820STom Warren  * but WITHOUT ANY WARRANTY; without even the implied warranty of
1652a8b820STom Warren  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1752a8b820STom Warren  * GNU General Public License for more details.
1852a8b820STom Warren  *
1952a8b820STom Warren  * You should have received a copy of the GNU General Public License
2052a8b820STom Warren  * along with this program; if not, write to the Free Software
2152a8b820STom Warren  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
2252a8b820STom Warren  * MA 02111-1307 USA
2352a8b820STom Warren  */
2452a8b820STom Warren 
2552a8b820STom Warren /*
2652a8b820STom Warren  * Based on (mostly copied from) kw_gpio.c based Linux 2.6 kernel driver.
2752a8b820STom Warren  * Tom Warren (twarren@nvidia.com)
2852a8b820STom Warren  */
2952a8b820STom Warren 
3052a8b820STom Warren #include <common.h>
3152a8b820STom Warren #include <asm/io.h>
3252a8b820STom Warren #include <asm/bitops.h>
33*00a2749dSAllen Martin #include <asm/arch/tegra20.h>
3452a8b820STom Warren #include <asm/gpio.h>
3552a8b820STom Warren 
3652a8b820STom Warren enum {
37*00a2749dSAllen Martin 	TEGRA20_CMD_INFO,
38*00a2749dSAllen Martin 	TEGRA20_CMD_PORT,
39*00a2749dSAllen Martin 	TEGRA20_CMD_OUTPUT,
40*00a2749dSAllen Martin 	TEGRA20_CMD_INPUT,
4152a8b820STom Warren };
4252a8b820STom Warren 
4352a8b820STom Warren static struct gpio_names {
4452a8b820STom Warren 	char name[GPIO_NAME_SIZE];
4552a8b820STom Warren } gpio_names[MAX_NUM_GPIOS];
4652a8b820STom Warren 
4752a8b820STom Warren static char *get_name(int i)
4852a8b820STom Warren {
4952a8b820STom Warren 	return *gpio_names[i].name ? gpio_names[i].name : "UNKNOWN";
5052a8b820STom Warren }
5152a8b820STom Warren 
5252a8b820STom Warren /* Return config of pin 'gpio' as GPIO (1) or SFPIO (0) */
5352a8b820STom Warren static int get_config(unsigned gpio)
5452a8b820STom Warren {
5552a8b820STom Warren 	struct gpio_ctlr *ctlr = (struct gpio_ctlr *)NV_PA_GPIO_BASE;
5652a8b820STom Warren 	struct gpio_ctlr_bank *bank = &ctlr->gpio_bank[GPIO_BANK(gpio)];
5752a8b820STom Warren 	u32 u;
5852a8b820STom Warren 	int type;
5952a8b820STom Warren 
6052a8b820STom Warren 	u = readl(&bank->gpio_config[GPIO_PORT(gpio)]);
6152a8b820STom Warren 	type =  (u >> GPIO_BIT(gpio)) & 1;
6252a8b820STom Warren 
6352a8b820STom Warren 	debug("get_config: port = %d, bit = %d is %s\n",
6452a8b820STom Warren 		GPIO_FULLPORT(gpio), GPIO_BIT(gpio), type ? "GPIO" : "SFPIO");
6552a8b820STom Warren 
6652a8b820STom Warren 	return type;
6752a8b820STom Warren }
6852a8b820STom Warren 
6952a8b820STom Warren /* Config pin 'gpio' as GPIO or SFPIO, based on 'type' */
7052a8b820STom Warren static void set_config(unsigned gpio, int type)
7152a8b820STom Warren {
7252a8b820STom Warren 	struct gpio_ctlr *ctlr = (struct gpio_ctlr *)NV_PA_GPIO_BASE;
7352a8b820STom Warren 	struct gpio_ctlr_bank *bank = &ctlr->gpio_bank[GPIO_BANK(gpio)];
7452a8b820STom Warren 	u32 u;
7552a8b820STom Warren 
7652a8b820STom Warren 	debug("set_config: port = %d, bit = %d, %s\n",
7752a8b820STom Warren 		GPIO_FULLPORT(gpio), GPIO_BIT(gpio), type ? "GPIO" : "SFPIO");
7852a8b820STom Warren 
7952a8b820STom Warren 	u = readl(&bank->gpio_config[GPIO_PORT(gpio)]);
8052a8b820STom Warren 	if (type)				/* GPIO */
8152a8b820STom Warren 		u |= 1 << GPIO_BIT(gpio);
8252a8b820STom Warren 	else
8352a8b820STom Warren 		u &= ~(1 << GPIO_BIT(gpio));
8452a8b820STom Warren 	writel(u, &bank->gpio_config[GPIO_PORT(gpio)]);
8552a8b820STom Warren }
8652a8b820STom Warren 
8752a8b820STom Warren /* Return GPIO pin 'gpio' direction - 0 = input or 1 = output */
8852a8b820STom Warren static int get_direction(unsigned gpio)
8952a8b820STom Warren {
9052a8b820STom Warren 	struct gpio_ctlr *ctlr = (struct gpio_ctlr *)NV_PA_GPIO_BASE;
9152a8b820STom Warren 	struct gpio_ctlr_bank *bank = &ctlr->gpio_bank[GPIO_BANK(gpio)];
9252a8b820STom Warren 	u32 u;
9352a8b820STom Warren 	int dir;
9452a8b820STom Warren 
9552a8b820STom Warren 	u = readl(&bank->gpio_dir_out[GPIO_PORT(gpio)]);
9652a8b820STom Warren 	dir =  (u >> GPIO_BIT(gpio)) & 1;
9752a8b820STom Warren 
9852a8b820STom Warren 	debug("get_direction: port = %d, bit = %d, %s\n",
9952a8b820STom Warren 		GPIO_FULLPORT(gpio), GPIO_BIT(gpio), dir ? "OUT" : "IN");
10052a8b820STom Warren 
10152a8b820STom Warren 	return dir;
10252a8b820STom Warren }
10352a8b820STom Warren 
10452a8b820STom Warren /* Config GPIO pin 'gpio' as input or output (OE) as per 'output' */
10552a8b820STom Warren static void set_direction(unsigned gpio, int output)
10652a8b820STom Warren {
10752a8b820STom Warren 	struct gpio_ctlr *ctlr = (struct gpio_ctlr *)NV_PA_GPIO_BASE;
10852a8b820STom Warren 	struct gpio_ctlr_bank *bank = &ctlr->gpio_bank[GPIO_BANK(gpio)];
10952a8b820STom Warren 	u32 u;
11052a8b820STom Warren 
11152a8b820STom Warren 	debug("set_direction: port = %d, bit = %d, %s\n",
11252a8b820STom Warren 		GPIO_FULLPORT(gpio), GPIO_BIT(gpio), output ? "OUT" : "IN");
11352a8b820STom Warren 
11452a8b820STom Warren 	u = readl(&bank->gpio_dir_out[GPIO_PORT(gpio)]);
11552a8b820STom Warren 	if (output)
11652a8b820STom Warren 		u |= 1 << GPIO_BIT(gpio);
11752a8b820STom Warren 	else
11852a8b820STom Warren 		u &= ~(1 << GPIO_BIT(gpio));
11952a8b820STom Warren 	writel(u, &bank->gpio_dir_out[GPIO_PORT(gpio)]);
12052a8b820STom Warren }
12152a8b820STom Warren 
12252a8b820STom Warren /* set GPIO pin 'gpio' output bit as 0 or 1 as per 'high' */
12352a8b820STom Warren static void set_level(unsigned gpio, int high)
12452a8b820STom Warren {
12552a8b820STom Warren 	struct gpio_ctlr *ctlr = (struct gpio_ctlr *)NV_PA_GPIO_BASE;
12652a8b820STom Warren 	struct gpio_ctlr_bank *bank = &ctlr->gpio_bank[GPIO_BANK(gpio)];
12752a8b820STom Warren 	u32 u;
12852a8b820STom Warren 
12952a8b820STom Warren 	debug("set_level: port = %d, bit %d == %d\n",
13052a8b820STom Warren 		GPIO_FULLPORT(gpio), GPIO_BIT(gpio), high);
13152a8b820STom Warren 
13252a8b820STom Warren 	u = readl(&bank->gpio_out[GPIO_PORT(gpio)]);
13352a8b820STom Warren 	if (high)
13452a8b820STom Warren 		u |= 1 << GPIO_BIT(gpio);
13552a8b820STom Warren 	else
13652a8b820STom Warren 		u &= ~(1 << GPIO_BIT(gpio));
13752a8b820STom Warren 	writel(u, &bank->gpio_out[GPIO_PORT(gpio)]);
13852a8b820STom Warren }
13952a8b820STom Warren 
14052a8b820STom Warren /*
14152a8b820STom Warren  * Generic_GPIO primitives.
14252a8b820STom Warren  */
14352a8b820STom Warren 
14452a8b820STom Warren int gpio_request(unsigned gpio, const char *label)
14552a8b820STom Warren {
14652a8b820STom Warren 	if (gpio >= MAX_NUM_GPIOS)
14752a8b820STom Warren 		return -1;
14852a8b820STom Warren 
14952a8b820STom Warren 	if (label != NULL) {
15052a8b820STom Warren 		strncpy(gpio_names[gpio].name, label, GPIO_NAME_SIZE);
15152a8b820STom Warren 		gpio_names[gpio].name[GPIO_NAME_SIZE - 1] = '\0';
15252a8b820STom Warren 	}
15352a8b820STom Warren 
15452a8b820STom Warren 	/* Configure as a GPIO */
15552a8b820STom Warren 	set_config(gpio, 1);
15652a8b820STom Warren 
15752a8b820STom Warren 	return 0;
15852a8b820STom Warren }
15952a8b820STom Warren 
16052a8b820STom Warren int gpio_free(unsigned gpio)
16152a8b820STom Warren {
16252a8b820STom Warren 	if (gpio >= MAX_NUM_GPIOS)
16352a8b820STom Warren 		return -1;
16452a8b820STom Warren 
16552a8b820STom Warren 	gpio_names[gpio].name[0] = '\0';
16652a8b820STom Warren 	/* Do not configure as input or change pin mux here */
16752a8b820STom Warren 	return 0;
16852a8b820STom Warren }
16952a8b820STom Warren 
17052a8b820STom Warren /* read GPIO OUT value of pin 'gpio' */
17152a8b820STom Warren static int gpio_get_output_value(unsigned gpio)
17252a8b820STom Warren {
17352a8b820STom Warren 	struct gpio_ctlr *ctlr = (struct gpio_ctlr *)NV_PA_GPIO_BASE;
17452a8b820STom Warren 	struct gpio_ctlr_bank *bank = &ctlr->gpio_bank[GPIO_BANK(gpio)];
17552a8b820STom Warren 	int val;
17652a8b820STom Warren 
17752a8b820STom Warren 	debug("gpio_get_output_value: pin = %d (port %d:bit %d)\n",
17852a8b820STom Warren 		gpio, GPIO_FULLPORT(gpio), GPIO_BIT(gpio));
17952a8b820STom Warren 
18052a8b820STom Warren 	val = readl(&bank->gpio_out[GPIO_PORT(gpio)]);
18152a8b820STom Warren 
18252a8b820STom Warren 	return (val >> GPIO_BIT(gpio)) & 1;
18352a8b820STom Warren }
18452a8b820STom Warren 
18552a8b820STom Warren /* set GPIO pin 'gpio' as an input */
18652a8b820STom Warren int gpio_direction_input(unsigned gpio)
18752a8b820STom Warren {
18852a8b820STom Warren 	debug("gpio_direction_input: pin = %d (port %d:bit %d)\n",
18952a8b820STom Warren 		gpio, GPIO_FULLPORT(gpio), GPIO_BIT(gpio));
19052a8b820STom Warren 
19152a8b820STom Warren 	/* Configure GPIO direction as input. */
19252a8b820STom Warren 	set_direction(gpio, 0);
19352a8b820STom Warren 
19452a8b820STom Warren 	return 0;
19552a8b820STom Warren }
19652a8b820STom Warren 
19752a8b820STom Warren /* set GPIO pin 'gpio' as an output, with polarity 'value' */
19852a8b820STom Warren int gpio_direction_output(unsigned gpio, int value)
19952a8b820STom Warren {
20052a8b820STom Warren 	debug("gpio_direction_output: pin = %d (port %d:bit %d) = %s\n",
20152a8b820STom Warren 		gpio, GPIO_FULLPORT(gpio), GPIO_BIT(gpio),
20252a8b820STom Warren 		value ? "HIGH" : "LOW");
20352a8b820STom Warren 
20452a8b820STom Warren 	/* Configure GPIO output value. */
20552a8b820STom Warren 	set_level(gpio, value);
20652a8b820STom Warren 
20752a8b820STom Warren 	/* Configure GPIO direction as output. */
20852a8b820STom Warren 	set_direction(gpio, 1);
20952a8b820STom Warren 
21052a8b820STom Warren 	return 0;
21152a8b820STom Warren }
21252a8b820STom Warren 
21352a8b820STom Warren /* read GPIO IN value of pin 'gpio' */
21452a8b820STom Warren int gpio_get_value(unsigned gpio)
21552a8b820STom Warren {
21652a8b820STom Warren 	struct gpio_ctlr *ctlr = (struct gpio_ctlr *)NV_PA_GPIO_BASE;
21752a8b820STom Warren 	struct gpio_ctlr_bank *bank = &ctlr->gpio_bank[GPIO_BANK(gpio)];
21852a8b820STom Warren 	int val;
21952a8b820STom Warren 
22052a8b820STom Warren 	debug("gpio_get_value: pin = %d (port %d:bit %d)\n",
22152a8b820STom Warren 		gpio, GPIO_FULLPORT(gpio), GPIO_BIT(gpio));
22252a8b820STom Warren 
22352a8b820STom Warren 	val = readl(&bank->gpio_in[GPIO_PORT(gpio)]);
22452a8b820STom Warren 
22552a8b820STom Warren 	return (val >> GPIO_BIT(gpio)) & 1;
22652a8b820STom Warren }
22752a8b820STom Warren 
22852a8b820STom Warren /* write GPIO OUT value to pin 'gpio' */
22952a8b820STom Warren int gpio_set_value(unsigned gpio, int value)
23052a8b820STom Warren {
23152a8b820STom Warren 	debug("gpio_set_value: pin = %d (port %d:bit %d), value = %d\n",
23252a8b820STom Warren 		gpio, GPIO_FULLPORT(gpio), GPIO_BIT(gpio), value);
23352a8b820STom Warren 
23452a8b820STom Warren 	/* Configure GPIO output value. */
23552a8b820STom Warren 	set_level(gpio, value);
23652a8b820STom Warren 
23752a8b820STom Warren 	return 0;
23852a8b820STom Warren }
23952a8b820STom Warren 
24052a8b820STom Warren /*
24152a8b820STom Warren  * Display Tegra GPIO information
24252a8b820STom Warren  */
24352a8b820STom Warren void gpio_info(void)
24452a8b820STom Warren {
24552a8b820STom Warren 	unsigned c;
24652a8b820STom Warren 	int type;
24752a8b820STom Warren 
24852a8b820STom Warren 	for (c = 0; c < MAX_NUM_GPIOS; c++) {
24952a8b820STom Warren 		type = get_config(c);		/* GPIO, not SFPIO */
25052a8b820STom Warren 		if (type) {
25152a8b820STom Warren 			printf("GPIO_%d:\t%s is an %s, ", c,
25252a8b820STom Warren 				get_name(c),
25352a8b820STom Warren 				get_direction(c) ? "OUTPUT" : "INPUT");
25452a8b820STom Warren 			if (get_direction(c))
25552a8b820STom Warren 				printf("value = %d", gpio_get_output_value(c));
25652a8b820STom Warren 			else
25752a8b820STom Warren 				printf("value = %d", gpio_get_value(c));
25852a8b820STom Warren 			printf("\n");
25952a8b820STom Warren 		} else
26052a8b820STom Warren 			continue;
26152a8b820STom Warren 	}
26252a8b820STom Warren }
263