xref: /rk3399_rockchip-uboot/drivers/gpio/mxc_gpio.c (revision e71c39def6a00ba3dee9a554ea85a8a5bd3dd300)
1c4ea1424SStefano Babic /*
2c4ea1424SStefano Babic  * Copyright (C) 2009
3c4ea1424SStefano Babic  * Guennadi Liakhovetski, DENX Software Engineering, <lg@denx.de>
4c4ea1424SStefano Babic  *
5d8e0ca85SStefano Babic  * Copyright (C) 2011
6d8e0ca85SStefano Babic  * Stefano Babic, DENX Software Engineering, <sbabic@denx.de>
7d8e0ca85SStefano Babic  *
8c4ea1424SStefano Babic  * See file CREDITS for list of people who contributed to this
9c4ea1424SStefano Babic  * project.
10c4ea1424SStefano Babic  *
11c4ea1424SStefano Babic  * This program is free software; you can redistribute it and/or
12c4ea1424SStefano Babic  * modify it under the terms of the GNU General Public License as
13c4ea1424SStefano Babic  * published by the Free Software Foundation; either version 2 of
14c4ea1424SStefano Babic  * the License, or (at your option) any later version.
15c4ea1424SStefano Babic  *
16c4ea1424SStefano Babic  * This program is distributed in the hope that it will be useful,
17c4ea1424SStefano Babic  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18c4ea1424SStefano Babic  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19c4ea1424SStefano Babic  * GNU General Public License for more details.
20c4ea1424SStefano Babic  *
21c4ea1424SStefano Babic  * You should have received a copy of the GNU General Public License
22c4ea1424SStefano Babic  * along with this program; if not, write to the Free Software
23c4ea1424SStefano Babic  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
24c4ea1424SStefano Babic  * MA 02111-1307 USA
25c4ea1424SStefano Babic  */
26c4ea1424SStefano Babic #include <common.h>
27c4ea1424SStefano Babic #include <asm/arch/imx-regs.h>
28d8e0ca85SStefano Babic #include <asm/gpio.h>
29c4ea1424SStefano Babic #include <asm/io.h>
30e53bcd94SFabio Estevam #include <errno.h>
31c4ea1424SStefano Babic 
32d8e0ca85SStefano Babic enum mxc_gpio_direction {
33d8e0ca85SStefano Babic 	MXC_GPIO_DIRECTION_IN,
34d8e0ca85SStefano Babic 	MXC_GPIO_DIRECTION_OUT,
35d8e0ca85SStefano Babic };
36d8e0ca85SStefano Babic 
378d28c211SVikram Narayanan #define GPIO_TO_PORT(n)		(n / 32)
38d8e0ca85SStefano Babic 
39c4ea1424SStefano Babic /* GPIO port description */
40c4ea1424SStefano Babic static unsigned long gpio_ports[] = {
41c4ea1424SStefano Babic 	[0] = GPIO1_BASE_ADDR,
42c4ea1424SStefano Babic 	[1] = GPIO2_BASE_ADDR,
43c4ea1424SStefano Babic 	[2] = GPIO3_BASE_ADDR,
44*e71c39deStrem #if defined(CONFIG_MX25) || defined(CONFIG_MX27) || defined(CONFIG_MX51) || \
45*e71c39deStrem 		defined(CONFIG_MX53) || defined(CONFIG_MX6Q)
46c4ea1424SStefano Babic 	[3] = GPIO4_BASE_ADDR,
47c4ea1424SStefano Babic #endif
48*e71c39deStrem #if defined(CONFIG_MX27) || defined(CONFIG_MX53) || defined(CONFIG_MX6Q)
4901643ec1SLiu Hui-R64343 	[4] = GPIO5_BASE_ADDR,
5001643ec1SLiu Hui-R64343 	[5] = GPIO6_BASE_ADDR,
51*e71c39deStrem #endif
52*e71c39deStrem #if defined(CONFIG_MX53) || defined(CONFIG_MX6Q)
5301643ec1SLiu Hui-R64343 	[6] = GPIO7_BASE_ADDR,
5401643ec1SLiu Hui-R64343 #endif
55c4ea1424SStefano Babic };
56c4ea1424SStefano Babic 
57d8e0ca85SStefano Babic static int mxc_gpio_direction(unsigned int gpio,
58d8e0ca85SStefano Babic 	enum mxc_gpio_direction direction)
59c4ea1424SStefano Babic {
60be282554SVikram Narayanan 	unsigned int port = GPIO_TO_PORT(gpio);
61c4ea1424SStefano Babic 	struct gpio_regs *regs;
62c4ea1424SStefano Babic 	u32 l;
63c4ea1424SStefano Babic 
64c4ea1424SStefano Babic 	if (port >= ARRAY_SIZE(gpio_ports))
65365d6070SJoe Hershberger 		return -1;
66c4ea1424SStefano Babic 
67c4ea1424SStefano Babic 	gpio &= 0x1f;
68c4ea1424SStefano Babic 
69c4ea1424SStefano Babic 	regs = (struct gpio_regs *)gpio_ports[port];
70c4ea1424SStefano Babic 
71c4ea1424SStefano Babic 	l = readl(&regs->gpio_dir);
72c4ea1424SStefano Babic 
73c4ea1424SStefano Babic 	switch (direction) {
74c4ea1424SStefano Babic 	case MXC_GPIO_DIRECTION_OUT:
75c4ea1424SStefano Babic 		l |= 1 << gpio;
76c4ea1424SStefano Babic 		break;
77c4ea1424SStefano Babic 	case MXC_GPIO_DIRECTION_IN:
78c4ea1424SStefano Babic 		l &= ~(1 << gpio);
79c4ea1424SStefano Babic 	}
80c4ea1424SStefano Babic 	writel(l, &regs->gpio_dir);
81c4ea1424SStefano Babic 
82c4ea1424SStefano Babic 	return 0;
83c4ea1424SStefano Babic }
84c4ea1424SStefano Babic 
85365d6070SJoe Hershberger int gpio_set_value(unsigned gpio, int value)
86c4ea1424SStefano Babic {
87be282554SVikram Narayanan 	unsigned int port = GPIO_TO_PORT(gpio);
88c4ea1424SStefano Babic 	struct gpio_regs *regs;
89c4ea1424SStefano Babic 	u32 l;
90c4ea1424SStefano Babic 
91c4ea1424SStefano Babic 	if (port >= ARRAY_SIZE(gpio_ports))
92365d6070SJoe Hershberger 		return -1;
93c4ea1424SStefano Babic 
94c4ea1424SStefano Babic 	gpio &= 0x1f;
95c4ea1424SStefano Babic 
96c4ea1424SStefano Babic 	regs = (struct gpio_regs *)gpio_ports[port];
97c4ea1424SStefano Babic 
98c4ea1424SStefano Babic 	l = readl(&regs->gpio_dr);
99c4ea1424SStefano Babic 	if (value)
100c4ea1424SStefano Babic 		l |= 1 << gpio;
101c4ea1424SStefano Babic 	else
102c4ea1424SStefano Babic 		l &= ~(1 << gpio);
103c4ea1424SStefano Babic 	writel(l, &regs->gpio_dr);
104365d6070SJoe Hershberger 
105365d6070SJoe Hershberger 	return 0;
106c4ea1424SStefano Babic }
107c4ea1424SStefano Babic 
108365d6070SJoe Hershberger int gpio_get_value(unsigned gpio)
109c4ea1424SStefano Babic {
110be282554SVikram Narayanan 	unsigned int port = GPIO_TO_PORT(gpio);
111c4ea1424SStefano Babic 	struct gpio_regs *regs;
112365d6070SJoe Hershberger 	u32 val;
113c4ea1424SStefano Babic 
114c4ea1424SStefano Babic 	if (port >= ARRAY_SIZE(gpio_ports))
115365d6070SJoe Hershberger 		return -1;
116c4ea1424SStefano Babic 
117c4ea1424SStefano Babic 	gpio &= 0x1f;
118c4ea1424SStefano Babic 
119c4ea1424SStefano Babic 	regs = (struct gpio_regs *)gpio_ports[port];
120c4ea1424SStefano Babic 
1215dafa454SBenoît Thébaudeau 	val = (readl(&regs->gpio_psr) >> gpio) & 0x01;
122c4ea1424SStefano Babic 
123365d6070SJoe Hershberger 	return val;
124c4ea1424SStefano Babic }
125d8e0ca85SStefano Babic 
126365d6070SJoe Hershberger int gpio_request(unsigned gpio, const char *label)
127d8e0ca85SStefano Babic {
128be282554SVikram Narayanan 	unsigned int port = GPIO_TO_PORT(gpio);
129d8e0ca85SStefano Babic 	if (port >= ARRAY_SIZE(gpio_ports))
130365d6070SJoe Hershberger 		return -1;
131d8e0ca85SStefano Babic 	return 0;
132d8e0ca85SStefano Babic }
133d8e0ca85SStefano Babic 
134365d6070SJoe Hershberger int gpio_free(unsigned gpio)
135d8e0ca85SStefano Babic {
136365d6070SJoe Hershberger 	return 0;
137d8e0ca85SStefano Babic }
138d8e0ca85SStefano Babic 
139365d6070SJoe Hershberger int gpio_direction_input(unsigned gpio)
140d8e0ca85SStefano Babic {
141365d6070SJoe Hershberger 	return mxc_gpio_direction(gpio, MXC_GPIO_DIRECTION_IN);
142d8e0ca85SStefano Babic }
143d8e0ca85SStefano Babic 
144365d6070SJoe Hershberger int gpio_direction_output(unsigned gpio, int value)
145d8e0ca85SStefano Babic {
146365d6070SJoe Hershberger 	int ret = mxc_gpio_direction(gpio, MXC_GPIO_DIRECTION_OUT);
147d8e0ca85SStefano Babic 
148d8e0ca85SStefano Babic 	if (ret < 0)
149d8e0ca85SStefano Babic 		return ret;
150d8e0ca85SStefano Babic 
151d71c9c9fSVikram Narayanan 	return gpio_set_value(gpio, value);
152d8e0ca85SStefano Babic }
153