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