xref: /rk3399_rockchip-uboot/drivers/gpio/xilinx_gpio.c (revision 4e779ad2e54e39d5343c8c83b4fc686a7bb16859)
1*4e779ad2SMichal Simek /*
2*4e779ad2SMichal Simek  * Copyright (c) 2013 Xilinx, Michal Simek
3*4e779ad2SMichal Simek  *
4*4e779ad2SMichal Simek  * See file CREDITS for list of people who contributed to this
5*4e779ad2SMichal Simek  * project.
6*4e779ad2SMichal Simek  *
7*4e779ad2SMichal Simek  * This program is free software; you can redistribute it and/or
8*4e779ad2SMichal Simek  * modify it under the terms of the GNU General Public License as
9*4e779ad2SMichal Simek  * published by the Free Software Foundation; either version 2 of
10*4e779ad2SMichal Simek  * the License, or (at your option) any later version.
11*4e779ad2SMichal Simek  *
12*4e779ad2SMichal Simek  * This program is distributed in the hope that it will be useful,
13*4e779ad2SMichal Simek  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14*4e779ad2SMichal Simek  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15*4e779ad2SMichal Simek  * GNU General Public License for more details.
16*4e779ad2SMichal Simek  *
17*4e779ad2SMichal Simek  * You should have received a copy of the GNU General Public License
18*4e779ad2SMichal Simek  * along with this program; if not, write to the Free Software
19*4e779ad2SMichal Simek  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
20*4e779ad2SMichal Simek  * MA 02111-1307 USA
21*4e779ad2SMichal Simek  */
22*4e779ad2SMichal Simek 
23*4e779ad2SMichal Simek #include <common.h>
24*4e779ad2SMichal Simek #include <errno.h>
25*4e779ad2SMichal Simek #include <malloc.h>
26*4e779ad2SMichal Simek #include <linux/list.h>
27*4e779ad2SMichal Simek #include <asm/io.h>
28*4e779ad2SMichal Simek #include <asm/gpio.h>
29*4e779ad2SMichal Simek 
30*4e779ad2SMichal Simek static LIST_HEAD(gpio_list);
31*4e779ad2SMichal Simek 
32*4e779ad2SMichal Simek enum gpio_direction {
33*4e779ad2SMichal Simek 	GPIO_DIRECTION_OUT = 0,
34*4e779ad2SMichal Simek 	GPIO_DIRECTION_IN = 1,
35*4e779ad2SMichal Simek };
36*4e779ad2SMichal Simek 
37*4e779ad2SMichal Simek /* Gpio simple map */
38*4e779ad2SMichal Simek struct gpio_regs {
39*4e779ad2SMichal Simek 	u32 gpiodata;
40*4e779ad2SMichal Simek 	u32 gpiodir;
41*4e779ad2SMichal Simek };
42*4e779ad2SMichal Simek 
43*4e779ad2SMichal Simek #define GPIO_NAME_SIZE	10
44*4e779ad2SMichal Simek 
45*4e779ad2SMichal Simek struct gpio_names {
46*4e779ad2SMichal Simek 	char name[GPIO_NAME_SIZE];
47*4e779ad2SMichal Simek };
48*4e779ad2SMichal Simek 
49*4e779ad2SMichal Simek /* Initialized, rxbd_current, rx_first_buf must be 0 after init */
50*4e779ad2SMichal Simek struct xilinx_gpio_priv {
51*4e779ad2SMichal Simek 	struct gpio_regs *regs;
52*4e779ad2SMichal Simek 	u32 gpio_min;
53*4e779ad2SMichal Simek 	u32 gpio_max;
54*4e779ad2SMichal Simek 	u32 gpiodata_store;
55*4e779ad2SMichal Simek 	char name[GPIO_NAME_SIZE];
56*4e779ad2SMichal Simek 	struct list_head list;
57*4e779ad2SMichal Simek 	struct gpio_names *gpio_name;
58*4e779ad2SMichal Simek };
59*4e779ad2SMichal Simek 
60*4e779ad2SMichal Simek /* Store number of allocated gpio pins */
61*4e779ad2SMichal Simek static u32 xilinx_gpio_max;
62*4e779ad2SMichal Simek 
63*4e779ad2SMichal Simek /* Get associated gpio controller */
64*4e779ad2SMichal Simek static struct xilinx_gpio_priv *gpio_get_controller(unsigned gpio)
65*4e779ad2SMichal Simek {
66*4e779ad2SMichal Simek 	struct list_head *entry;
67*4e779ad2SMichal Simek 	struct xilinx_gpio_priv *priv = NULL;
68*4e779ad2SMichal Simek 
69*4e779ad2SMichal Simek 	list_for_each(entry, &gpio_list) {
70*4e779ad2SMichal Simek 		priv = list_entry(entry, struct xilinx_gpio_priv, list);
71*4e779ad2SMichal Simek 		if (gpio >= priv->gpio_min && gpio <= priv->gpio_max) {
72*4e779ad2SMichal Simek 			debug("%s: reg: %x, min-max: %d-%d\n", __func__,
73*4e779ad2SMichal Simek 			      (u32)priv->regs, priv->gpio_min, priv->gpio_max);
74*4e779ad2SMichal Simek 			return priv;
75*4e779ad2SMichal Simek 		}
76*4e779ad2SMichal Simek 	}
77*4e779ad2SMichal Simek 	puts("!!!Can't get gpio controller!!!\n");
78*4e779ad2SMichal Simek 	return NULL;
79*4e779ad2SMichal Simek }
80*4e779ad2SMichal Simek 
81*4e779ad2SMichal Simek /* Get gpio pin name if used/setup */
82*4e779ad2SMichal Simek static char *get_name(unsigned gpio)
83*4e779ad2SMichal Simek {
84*4e779ad2SMichal Simek 	u32 gpio_priv;
85*4e779ad2SMichal Simek 	struct xilinx_gpio_priv *priv;
86*4e779ad2SMichal Simek 
87*4e779ad2SMichal Simek 	debug("%s\n", __func__);
88*4e779ad2SMichal Simek 
89*4e779ad2SMichal Simek 	priv = gpio_get_controller(gpio);
90*4e779ad2SMichal Simek 	if (priv) {
91*4e779ad2SMichal Simek 		gpio_priv = gpio - priv->gpio_min;
92*4e779ad2SMichal Simek 
93*4e779ad2SMichal Simek 		return *priv->gpio_name[gpio_priv].name ?
94*4e779ad2SMichal Simek 			priv->gpio_name[gpio_priv].name : "UNKNOWN";
95*4e779ad2SMichal Simek 	}
96*4e779ad2SMichal Simek 	return "UNKNOWN";
97*4e779ad2SMichal Simek }
98*4e779ad2SMichal Simek 
99*4e779ad2SMichal Simek /* Get output value */
100*4e779ad2SMichal Simek static int gpio_get_output_value(unsigned gpio)
101*4e779ad2SMichal Simek {
102*4e779ad2SMichal Simek 	u32 val, gpio_priv;
103*4e779ad2SMichal Simek 	struct xilinx_gpio_priv *priv = gpio_get_controller(gpio);
104*4e779ad2SMichal Simek 
105*4e779ad2SMichal Simek 	if (priv) {
106*4e779ad2SMichal Simek 		gpio_priv = gpio - priv->gpio_min;
107*4e779ad2SMichal Simek 		val = !!(priv->gpiodata_store & (1 << gpio_priv));
108*4e779ad2SMichal Simek 		debug("%s: reg: %x, gpio_no: %d, dir: %d\n", __func__,
109*4e779ad2SMichal Simek 		      (u32)priv->regs, gpio_priv, val);
110*4e779ad2SMichal Simek 
111*4e779ad2SMichal Simek 		return val;
112*4e779ad2SMichal Simek 	}
113*4e779ad2SMichal Simek 	return -1;
114*4e779ad2SMichal Simek }
115*4e779ad2SMichal Simek 
116*4e779ad2SMichal Simek /* Get input value */
117*4e779ad2SMichal Simek static int gpio_get_input_value(unsigned gpio)
118*4e779ad2SMichal Simek {
119*4e779ad2SMichal Simek 	u32 val, gpio_priv;
120*4e779ad2SMichal Simek 	struct gpio_regs *regs;
121*4e779ad2SMichal Simek 	struct xilinx_gpio_priv *priv = gpio_get_controller(gpio);
122*4e779ad2SMichal Simek 
123*4e779ad2SMichal Simek 	if (priv) {
124*4e779ad2SMichal Simek 		regs = priv->regs;
125*4e779ad2SMichal Simek 		gpio_priv = gpio - priv->gpio_min;
126*4e779ad2SMichal Simek 		val = readl(&regs->gpiodata);
127*4e779ad2SMichal Simek 		val = !!(val & (1 << gpio_priv));
128*4e779ad2SMichal Simek 		debug("%s: reg: %x, gpio_no: %d, dir: %d\n", __func__,
129*4e779ad2SMichal Simek 		      (u32)priv->regs, gpio_priv, val);
130*4e779ad2SMichal Simek 
131*4e779ad2SMichal Simek 		return val;
132*4e779ad2SMichal Simek 	}
133*4e779ad2SMichal Simek 	return -1;
134*4e779ad2SMichal Simek }
135*4e779ad2SMichal Simek 
136*4e779ad2SMichal Simek /* Set gpio direction */
137*4e779ad2SMichal Simek static int gpio_set_direction(unsigned gpio, enum gpio_direction direction)
138*4e779ad2SMichal Simek {
139*4e779ad2SMichal Simek 	u32 val, gpio_priv;
140*4e779ad2SMichal Simek 	struct gpio_regs *regs;
141*4e779ad2SMichal Simek 	struct xilinx_gpio_priv *priv = gpio_get_controller(gpio);
142*4e779ad2SMichal Simek 
143*4e779ad2SMichal Simek 	if (priv) {
144*4e779ad2SMichal Simek 		regs = priv->regs;
145*4e779ad2SMichal Simek 		val = readl(&regs->gpiodir);
146*4e779ad2SMichal Simek 
147*4e779ad2SMichal Simek 		gpio_priv = gpio - priv->gpio_min;
148*4e779ad2SMichal Simek 		if (direction == GPIO_DIRECTION_OUT)
149*4e779ad2SMichal Simek 			val &= ~(1 << gpio_priv);
150*4e779ad2SMichal Simek 		else
151*4e779ad2SMichal Simek 			val |= 1 << gpio_priv;
152*4e779ad2SMichal Simek 
153*4e779ad2SMichal Simek 		writel(val, &regs->gpiodir);
154*4e779ad2SMichal Simek 		debug("%s: reg: %x, gpio_no: %d, dir: %d\n", __func__,
155*4e779ad2SMichal Simek 		      (u32)priv->regs, gpio_priv, val);
156*4e779ad2SMichal Simek 
157*4e779ad2SMichal Simek 		return 0;
158*4e779ad2SMichal Simek 	}
159*4e779ad2SMichal Simek 
160*4e779ad2SMichal Simek 	return -1;
161*4e779ad2SMichal Simek }
162*4e779ad2SMichal Simek 
163*4e779ad2SMichal Simek /* Get gpio direction */
164*4e779ad2SMichal Simek static int gpio_get_direction(unsigned gpio)
165*4e779ad2SMichal Simek {
166*4e779ad2SMichal Simek 	u32 val, gpio_priv;
167*4e779ad2SMichal Simek 	struct gpio_regs *regs;
168*4e779ad2SMichal Simek 	struct xilinx_gpio_priv *priv = gpio_get_controller(gpio);
169*4e779ad2SMichal Simek 
170*4e779ad2SMichal Simek 	if (priv) {
171*4e779ad2SMichal Simek 		regs = priv->regs;
172*4e779ad2SMichal Simek 		gpio_priv = gpio - priv->gpio_min;
173*4e779ad2SMichal Simek 		val = readl(&regs->gpiodir);
174*4e779ad2SMichal Simek 		val = !!(val & (1 << gpio_priv));
175*4e779ad2SMichal Simek 		debug("%s: reg: %x, gpio_no: %d, dir: %d\n", __func__,
176*4e779ad2SMichal Simek 		      (u32)priv->regs, gpio_priv, val);
177*4e779ad2SMichal Simek 
178*4e779ad2SMichal Simek 		return val;
179*4e779ad2SMichal Simek 	}
180*4e779ad2SMichal Simek 
181*4e779ad2SMichal Simek 	return -1;
182*4e779ad2SMichal Simek }
183*4e779ad2SMichal Simek 
184*4e779ad2SMichal Simek /*
185*4e779ad2SMichal Simek  * Get input value
186*4e779ad2SMichal Simek  * for example gpio setup to output only can't get input value
187*4e779ad2SMichal Simek  * which is breaking gpio toggle command
188*4e779ad2SMichal Simek  */
189*4e779ad2SMichal Simek int gpio_get_value(unsigned gpio)
190*4e779ad2SMichal Simek {
191*4e779ad2SMichal Simek 	u32 val;
192*4e779ad2SMichal Simek 
193*4e779ad2SMichal Simek 	if (gpio_get_direction(gpio) == GPIO_DIRECTION_OUT)
194*4e779ad2SMichal Simek 		val = gpio_get_output_value(gpio);
195*4e779ad2SMichal Simek 	else
196*4e779ad2SMichal Simek 		val = gpio_get_input_value(gpio);
197*4e779ad2SMichal Simek 
198*4e779ad2SMichal Simek 	return val;
199*4e779ad2SMichal Simek }
200*4e779ad2SMichal Simek 
201*4e779ad2SMichal Simek /* Set output value */
202*4e779ad2SMichal Simek static int gpio_set_output_value(unsigned gpio, int value)
203*4e779ad2SMichal Simek {
204*4e779ad2SMichal Simek 	u32 val, gpio_priv;
205*4e779ad2SMichal Simek 	struct gpio_regs *regs;
206*4e779ad2SMichal Simek 	struct xilinx_gpio_priv *priv = gpio_get_controller(gpio);
207*4e779ad2SMichal Simek 
208*4e779ad2SMichal Simek 	if (priv) {
209*4e779ad2SMichal Simek 		regs = priv->regs;
210*4e779ad2SMichal Simek 		gpio_priv = gpio - priv->gpio_min;
211*4e779ad2SMichal Simek 		val = priv->gpiodata_store;
212*4e779ad2SMichal Simek 		if (value)
213*4e779ad2SMichal Simek 			val |= 1 << gpio_priv;
214*4e779ad2SMichal Simek 		else
215*4e779ad2SMichal Simek 			val &= ~(1 << gpio_priv);
216*4e779ad2SMichal Simek 
217*4e779ad2SMichal Simek 		writel(val, &regs->gpiodata);
218*4e779ad2SMichal Simek 		debug("%s: reg: %x, gpio_no: %d, output_val: %d\n", __func__,
219*4e779ad2SMichal Simek 		      (u32)priv->regs, gpio_priv, val);
220*4e779ad2SMichal Simek 		priv->gpiodata_store = val;
221*4e779ad2SMichal Simek 
222*4e779ad2SMichal Simek 		return 0;
223*4e779ad2SMichal Simek 	}
224*4e779ad2SMichal Simek 
225*4e779ad2SMichal Simek 	return -1;
226*4e779ad2SMichal Simek }
227*4e779ad2SMichal Simek 
228*4e779ad2SMichal Simek int gpio_set_value(unsigned gpio, int value)
229*4e779ad2SMichal Simek {
230*4e779ad2SMichal Simek 	if (gpio_get_direction(gpio) == GPIO_DIRECTION_OUT)
231*4e779ad2SMichal Simek 		return gpio_set_output_value(gpio, value);
232*4e779ad2SMichal Simek 
233*4e779ad2SMichal Simek 	return -1;
234*4e779ad2SMichal Simek }
235*4e779ad2SMichal Simek 
236*4e779ad2SMichal Simek /* Set GPIO as input */
237*4e779ad2SMichal Simek int gpio_direction_input(unsigned gpio)
238*4e779ad2SMichal Simek {
239*4e779ad2SMichal Simek 	debug("%s\n", __func__);
240*4e779ad2SMichal Simek 	return gpio_set_direction(gpio, GPIO_DIRECTION_IN);
241*4e779ad2SMichal Simek }
242*4e779ad2SMichal Simek 
243*4e779ad2SMichal Simek /* Setup GPIO as output and set output value */
244*4e779ad2SMichal Simek int gpio_direction_output(unsigned gpio, int value)
245*4e779ad2SMichal Simek {
246*4e779ad2SMichal Simek 	int ret = gpio_set_direction(gpio, GPIO_DIRECTION_OUT);
247*4e779ad2SMichal Simek 
248*4e779ad2SMichal Simek 	debug("%s\n", __func__);
249*4e779ad2SMichal Simek 
250*4e779ad2SMichal Simek 	if (ret < 0)
251*4e779ad2SMichal Simek 		return ret;
252*4e779ad2SMichal Simek 
253*4e779ad2SMichal Simek 	return gpio_set_output_value(gpio, value);
254*4e779ad2SMichal Simek }
255*4e779ad2SMichal Simek 
256*4e779ad2SMichal Simek /* Show gpio status */
257*4e779ad2SMichal Simek void gpio_info(void)
258*4e779ad2SMichal Simek {
259*4e779ad2SMichal Simek 	unsigned gpio;
260*4e779ad2SMichal Simek 
261*4e779ad2SMichal Simek 	struct list_head *entry;
262*4e779ad2SMichal Simek 	struct xilinx_gpio_priv *priv = NULL;
263*4e779ad2SMichal Simek 
264*4e779ad2SMichal Simek 	list_for_each(entry, &gpio_list) {
265*4e779ad2SMichal Simek 		priv = list_entry(entry, struct xilinx_gpio_priv, list);
266*4e779ad2SMichal Simek 		printf("\n%s: %s/%x (%d-%d)\n", __func__, priv->name,
267*4e779ad2SMichal Simek 		       (u32)priv->regs, priv->gpio_min, priv->gpio_max);
268*4e779ad2SMichal Simek 
269*4e779ad2SMichal Simek 		for (gpio = priv->gpio_min; gpio <= priv->gpio_max; gpio++) {
270*4e779ad2SMichal Simek 			printf("GPIO_%d:\t%s is an ", gpio, get_name(gpio));
271*4e779ad2SMichal Simek 			if (gpio_get_direction(gpio) == GPIO_DIRECTION_OUT)
272*4e779ad2SMichal Simek 				printf("OUTPUT value = %d\n",
273*4e779ad2SMichal Simek 				       gpio_get_output_value(gpio));
274*4e779ad2SMichal Simek 			else
275*4e779ad2SMichal Simek 				printf("INPUT value = %d\n",
276*4e779ad2SMichal Simek 				       gpio_get_input_value(gpio));
277*4e779ad2SMichal Simek 		}
278*4e779ad2SMichal Simek 	}
279*4e779ad2SMichal Simek }
280*4e779ad2SMichal Simek 
281*4e779ad2SMichal Simek int gpio_request(unsigned gpio, const char *label)
282*4e779ad2SMichal Simek {
283*4e779ad2SMichal Simek 	u32 gpio_priv;
284*4e779ad2SMichal Simek 	struct xilinx_gpio_priv *priv;
285*4e779ad2SMichal Simek 
286*4e779ad2SMichal Simek 	if (gpio >= xilinx_gpio_max)
287*4e779ad2SMichal Simek 		return -EINVAL;
288*4e779ad2SMichal Simek 
289*4e779ad2SMichal Simek 	priv = gpio_get_controller(gpio);
290*4e779ad2SMichal Simek 	if (priv) {
291*4e779ad2SMichal Simek 		gpio_priv = gpio - priv->gpio_min;
292*4e779ad2SMichal Simek 
293*4e779ad2SMichal Simek 		if (label != NULL) {
294*4e779ad2SMichal Simek 			strncpy(priv->gpio_name[gpio_priv].name, label,
295*4e779ad2SMichal Simek 				GPIO_NAME_SIZE);
296*4e779ad2SMichal Simek 			priv->gpio_name[gpio_priv].name[GPIO_NAME_SIZE - 1] =
297*4e779ad2SMichal Simek 					'\0';
298*4e779ad2SMichal Simek 		}
299*4e779ad2SMichal Simek 		return 0;
300*4e779ad2SMichal Simek 	}
301*4e779ad2SMichal Simek 
302*4e779ad2SMichal Simek 	return -1;
303*4e779ad2SMichal Simek }
304*4e779ad2SMichal Simek 
305*4e779ad2SMichal Simek int gpio_free(unsigned gpio)
306*4e779ad2SMichal Simek {
307*4e779ad2SMichal Simek 	u32 gpio_priv;
308*4e779ad2SMichal Simek 	struct xilinx_gpio_priv *priv;
309*4e779ad2SMichal Simek 
310*4e779ad2SMichal Simek 	if (gpio >= xilinx_gpio_max)
311*4e779ad2SMichal Simek 		return -EINVAL;
312*4e779ad2SMichal Simek 
313*4e779ad2SMichal Simek 	priv = gpio_get_controller(gpio);
314*4e779ad2SMichal Simek 	if (priv) {
315*4e779ad2SMichal Simek 		gpio_priv = gpio - priv->gpio_min;
316*4e779ad2SMichal Simek 		priv->gpio_name[gpio_priv].name[0] = '\0';
317*4e779ad2SMichal Simek 
318*4e779ad2SMichal Simek 		/* Do nothing here */
319*4e779ad2SMichal Simek 		return 0;
320*4e779ad2SMichal Simek 	}
321*4e779ad2SMichal Simek 
322*4e779ad2SMichal Simek 	return -1;
323*4e779ad2SMichal Simek }
324*4e779ad2SMichal Simek 
325*4e779ad2SMichal Simek int gpio_alloc(u32 baseaddr, const char *name, u32 gpio_no)
326*4e779ad2SMichal Simek {
327*4e779ad2SMichal Simek 	struct xilinx_gpio_priv *priv;
328*4e779ad2SMichal Simek 
329*4e779ad2SMichal Simek 	priv = calloc(1, sizeof(struct xilinx_gpio_priv));
330*4e779ad2SMichal Simek 
331*4e779ad2SMichal Simek 	/* Setup gpio name */
332*4e779ad2SMichal Simek 	if (name != NULL) {
333*4e779ad2SMichal Simek 		strncpy(priv->name, name, GPIO_NAME_SIZE);
334*4e779ad2SMichal Simek 		priv->name[GPIO_NAME_SIZE - 1] = '\0';
335*4e779ad2SMichal Simek 	}
336*4e779ad2SMichal Simek 	priv->regs = (struct gpio_regs *)baseaddr;
337*4e779ad2SMichal Simek 
338*4e779ad2SMichal Simek 	priv->gpio_min = xilinx_gpio_max;
339*4e779ad2SMichal Simek 	xilinx_gpio_max = priv->gpio_min + gpio_no;
340*4e779ad2SMichal Simek 	priv->gpio_max = xilinx_gpio_max - 1;
341*4e779ad2SMichal Simek 
342*4e779ad2SMichal Simek 	priv->gpio_name = calloc(gpio_no, sizeof(struct gpio_names));
343*4e779ad2SMichal Simek 
344*4e779ad2SMichal Simek 	INIT_LIST_HEAD(&priv->list);
345*4e779ad2SMichal Simek 	list_add_tail(&priv->list, &gpio_list);
346*4e779ad2SMichal Simek 
347*4e779ad2SMichal Simek 	printf("%s: Add %s (%d-%d)\n", __func__, name,
348*4e779ad2SMichal Simek 	       priv->gpio_min, priv->gpio_max);
349*4e779ad2SMichal Simek 
350*4e779ad2SMichal Simek 	/* Return the first gpio allocated for this device */
351*4e779ad2SMichal Simek 	return priv->gpio_min;
352*4e779ad2SMichal Simek }
353*4e779ad2SMichal Simek 
354*4e779ad2SMichal Simek /* Dual channel gpio is one IP with two independent channels */
355*4e779ad2SMichal Simek int gpio_alloc_dual(u32 baseaddr, const char *name, u32 gpio_no0, u32 gpio_no1)
356*4e779ad2SMichal Simek {
357*4e779ad2SMichal Simek 	int ret;
358*4e779ad2SMichal Simek 
359*4e779ad2SMichal Simek 	ret = gpio_alloc(baseaddr, name, gpio_no0);
360*4e779ad2SMichal Simek 	gpio_alloc(baseaddr + 8, strcat((char *)name, "_1"), gpio_no1);
361*4e779ad2SMichal Simek 
362*4e779ad2SMichal Simek 	/* Return the first gpio allocated for this device */
363*4e779ad2SMichal Simek 	return ret;
364*4e779ad2SMichal Simek }
365