xref: /rk3399_rockchip-uboot/drivers/gpio/xilinx_gpio.c (revision 326ea986ac150acdc7656d57fca647db80b50158)
14e779ad2SMichal Simek /*
24e779ad2SMichal Simek  * Copyright (c) 2013 Xilinx, Michal Simek
34e779ad2SMichal Simek  *
4*1a459660SWolfgang Denk  * SPDX-License-Identifier:	GPL-2.0+
54e779ad2SMichal Simek  */
64e779ad2SMichal Simek 
74e779ad2SMichal Simek #include <common.h>
84e779ad2SMichal Simek #include <errno.h>
94e779ad2SMichal Simek #include <malloc.h>
104e779ad2SMichal Simek #include <linux/list.h>
114e779ad2SMichal Simek #include <asm/io.h>
124e779ad2SMichal Simek #include <asm/gpio.h>
134e779ad2SMichal Simek 
144e779ad2SMichal Simek static LIST_HEAD(gpio_list);
154e779ad2SMichal Simek 
164e779ad2SMichal Simek enum gpio_direction {
174e779ad2SMichal Simek 	GPIO_DIRECTION_OUT = 0,
184e779ad2SMichal Simek 	GPIO_DIRECTION_IN = 1,
194e779ad2SMichal Simek };
204e779ad2SMichal Simek 
214e779ad2SMichal Simek /* Gpio simple map */
224e779ad2SMichal Simek struct gpio_regs {
234e779ad2SMichal Simek 	u32 gpiodata;
244e779ad2SMichal Simek 	u32 gpiodir;
254e779ad2SMichal Simek };
264e779ad2SMichal Simek 
274e779ad2SMichal Simek #define GPIO_NAME_SIZE	10
284e779ad2SMichal Simek 
294e779ad2SMichal Simek struct gpio_names {
304e779ad2SMichal Simek 	char name[GPIO_NAME_SIZE];
314e779ad2SMichal Simek };
324e779ad2SMichal Simek 
334e779ad2SMichal Simek /* Initialized, rxbd_current, rx_first_buf must be 0 after init */
344e779ad2SMichal Simek struct xilinx_gpio_priv {
354e779ad2SMichal Simek 	struct gpio_regs *regs;
364e779ad2SMichal Simek 	u32 gpio_min;
374e779ad2SMichal Simek 	u32 gpio_max;
384e779ad2SMichal Simek 	u32 gpiodata_store;
394e779ad2SMichal Simek 	char name[GPIO_NAME_SIZE];
404e779ad2SMichal Simek 	struct list_head list;
414e779ad2SMichal Simek 	struct gpio_names *gpio_name;
424e779ad2SMichal Simek };
434e779ad2SMichal Simek 
444e779ad2SMichal Simek /* Store number of allocated gpio pins */
454e779ad2SMichal Simek static u32 xilinx_gpio_max;
464e779ad2SMichal Simek 
474e779ad2SMichal Simek /* Get associated gpio controller */
gpio_get_controller(unsigned gpio)484e779ad2SMichal Simek static struct xilinx_gpio_priv *gpio_get_controller(unsigned gpio)
494e779ad2SMichal Simek {
504e779ad2SMichal Simek 	struct list_head *entry;
514e779ad2SMichal Simek 	struct xilinx_gpio_priv *priv = NULL;
524e779ad2SMichal Simek 
534e779ad2SMichal Simek 	list_for_each(entry, &gpio_list) {
544e779ad2SMichal Simek 		priv = list_entry(entry, struct xilinx_gpio_priv, list);
554e779ad2SMichal Simek 		if (gpio >= priv->gpio_min && gpio <= priv->gpio_max) {
564e779ad2SMichal Simek 			debug("%s: reg: %x, min-max: %d-%d\n", __func__,
574e779ad2SMichal Simek 			      (u32)priv->regs, priv->gpio_min, priv->gpio_max);
584e779ad2SMichal Simek 			return priv;
594e779ad2SMichal Simek 		}
604e779ad2SMichal Simek 	}
614e779ad2SMichal Simek 	puts("!!!Can't get gpio controller!!!\n");
624e779ad2SMichal Simek 	return NULL;
634e779ad2SMichal Simek }
644e779ad2SMichal Simek 
654e779ad2SMichal Simek /* Get gpio pin name if used/setup */
get_name(unsigned gpio)664e779ad2SMichal Simek static char *get_name(unsigned gpio)
674e779ad2SMichal Simek {
684e779ad2SMichal Simek 	u32 gpio_priv;
694e779ad2SMichal Simek 	struct xilinx_gpio_priv *priv;
704e779ad2SMichal Simek 
714e779ad2SMichal Simek 	debug("%s\n", __func__);
724e779ad2SMichal Simek 
734e779ad2SMichal Simek 	priv = gpio_get_controller(gpio);
744e779ad2SMichal Simek 	if (priv) {
754e779ad2SMichal Simek 		gpio_priv = gpio - priv->gpio_min;
764e779ad2SMichal Simek 
774e779ad2SMichal Simek 		return *priv->gpio_name[gpio_priv].name ?
784e779ad2SMichal Simek 			priv->gpio_name[gpio_priv].name : "UNKNOWN";
794e779ad2SMichal Simek 	}
804e779ad2SMichal Simek 	return "UNKNOWN";
814e779ad2SMichal Simek }
824e779ad2SMichal Simek 
834e779ad2SMichal Simek /* Get output value */
gpio_get_output_value(unsigned gpio)844e779ad2SMichal Simek static int gpio_get_output_value(unsigned gpio)
854e779ad2SMichal Simek {
864e779ad2SMichal Simek 	u32 val, gpio_priv;
874e779ad2SMichal Simek 	struct xilinx_gpio_priv *priv = gpio_get_controller(gpio);
884e779ad2SMichal Simek 
894e779ad2SMichal Simek 	if (priv) {
904e779ad2SMichal Simek 		gpio_priv = gpio - priv->gpio_min;
914e779ad2SMichal Simek 		val = !!(priv->gpiodata_store & (1 << gpio_priv));
924e779ad2SMichal Simek 		debug("%s: reg: %x, gpio_no: %d, dir: %d\n", __func__,
934e779ad2SMichal Simek 		      (u32)priv->regs, gpio_priv, val);
944e779ad2SMichal Simek 
954e779ad2SMichal Simek 		return val;
964e779ad2SMichal Simek 	}
974e779ad2SMichal Simek 	return -1;
984e779ad2SMichal Simek }
994e779ad2SMichal Simek 
1004e779ad2SMichal Simek /* Get input value */
gpio_get_input_value(unsigned gpio)1014e779ad2SMichal Simek static int gpio_get_input_value(unsigned gpio)
1024e779ad2SMichal Simek {
1034e779ad2SMichal Simek 	u32 val, gpio_priv;
1044e779ad2SMichal Simek 	struct gpio_regs *regs;
1054e779ad2SMichal Simek 	struct xilinx_gpio_priv *priv = gpio_get_controller(gpio);
1064e779ad2SMichal Simek 
1074e779ad2SMichal Simek 	if (priv) {
1084e779ad2SMichal Simek 		regs = priv->regs;
1094e779ad2SMichal Simek 		gpio_priv = gpio - priv->gpio_min;
1104e779ad2SMichal Simek 		val = readl(&regs->gpiodata);
1114e779ad2SMichal Simek 		val = !!(val & (1 << gpio_priv));
1124e779ad2SMichal Simek 		debug("%s: reg: %x, gpio_no: %d, dir: %d\n", __func__,
1134e779ad2SMichal Simek 		      (u32)priv->regs, gpio_priv, val);
1144e779ad2SMichal Simek 
1154e779ad2SMichal Simek 		return val;
1164e779ad2SMichal Simek 	}
1174e779ad2SMichal Simek 	return -1;
1184e779ad2SMichal Simek }
1194e779ad2SMichal Simek 
1204e779ad2SMichal Simek /* Set gpio direction */
gpio_set_direction(unsigned gpio,enum gpio_direction direction)1214e779ad2SMichal Simek static int gpio_set_direction(unsigned gpio, enum gpio_direction direction)
1224e779ad2SMichal Simek {
1234e779ad2SMichal Simek 	u32 val, gpio_priv;
1244e779ad2SMichal Simek 	struct gpio_regs *regs;
1254e779ad2SMichal Simek 	struct xilinx_gpio_priv *priv = gpio_get_controller(gpio);
1264e779ad2SMichal Simek 
1274e779ad2SMichal Simek 	if (priv) {
1284e779ad2SMichal Simek 		regs = priv->regs;
1294e779ad2SMichal Simek 		val = readl(&regs->gpiodir);
1304e779ad2SMichal Simek 
1314e779ad2SMichal Simek 		gpio_priv = gpio - priv->gpio_min;
1324e779ad2SMichal Simek 		if (direction == GPIO_DIRECTION_OUT)
1334e779ad2SMichal Simek 			val &= ~(1 << gpio_priv);
1344e779ad2SMichal Simek 		else
1354e779ad2SMichal Simek 			val |= 1 << gpio_priv;
1364e779ad2SMichal Simek 
1374e779ad2SMichal Simek 		writel(val, &regs->gpiodir);
1384e779ad2SMichal Simek 		debug("%s: reg: %x, gpio_no: %d, dir: %d\n", __func__,
1394e779ad2SMichal Simek 		      (u32)priv->regs, gpio_priv, val);
1404e779ad2SMichal Simek 
1414e779ad2SMichal Simek 		return 0;
1424e779ad2SMichal Simek 	}
1434e779ad2SMichal Simek 
1444e779ad2SMichal Simek 	return -1;
1454e779ad2SMichal Simek }
1464e779ad2SMichal Simek 
1474e779ad2SMichal Simek /* Get gpio direction */
gpio_get_direction(unsigned gpio)1484e779ad2SMichal Simek static int gpio_get_direction(unsigned gpio)
1494e779ad2SMichal Simek {
1504e779ad2SMichal Simek 	u32 val, gpio_priv;
1514e779ad2SMichal Simek 	struct gpio_regs *regs;
1524e779ad2SMichal Simek 	struct xilinx_gpio_priv *priv = gpio_get_controller(gpio);
1534e779ad2SMichal Simek 
1544e779ad2SMichal Simek 	if (priv) {
1554e779ad2SMichal Simek 		regs = priv->regs;
1564e779ad2SMichal Simek 		gpio_priv = gpio - priv->gpio_min;
1574e779ad2SMichal Simek 		val = readl(&regs->gpiodir);
1584e779ad2SMichal Simek 		val = !!(val & (1 << gpio_priv));
1594e779ad2SMichal Simek 		debug("%s: reg: %x, gpio_no: %d, dir: %d\n", __func__,
1604e779ad2SMichal Simek 		      (u32)priv->regs, gpio_priv, val);
1614e779ad2SMichal Simek 
1624e779ad2SMichal Simek 		return val;
1634e779ad2SMichal Simek 	}
1644e779ad2SMichal Simek 
1654e779ad2SMichal Simek 	return -1;
1664e779ad2SMichal Simek }
1674e779ad2SMichal Simek 
1684e779ad2SMichal Simek /*
1694e779ad2SMichal Simek  * Get input value
1704e779ad2SMichal Simek  * for example gpio setup to output only can't get input value
1714e779ad2SMichal Simek  * which is breaking gpio toggle command
1724e779ad2SMichal Simek  */
gpio_get_value(unsigned gpio)1734e779ad2SMichal Simek int gpio_get_value(unsigned gpio)
1744e779ad2SMichal Simek {
1754e779ad2SMichal Simek 	u32 val;
1764e779ad2SMichal Simek 
1774e779ad2SMichal Simek 	if (gpio_get_direction(gpio) == GPIO_DIRECTION_OUT)
1784e779ad2SMichal Simek 		val = gpio_get_output_value(gpio);
1794e779ad2SMichal Simek 	else
1804e779ad2SMichal Simek 		val = gpio_get_input_value(gpio);
1814e779ad2SMichal Simek 
1824e779ad2SMichal Simek 	return val;
1834e779ad2SMichal Simek }
1844e779ad2SMichal Simek 
1854e779ad2SMichal Simek /* Set output value */
gpio_set_output_value(unsigned gpio,int value)1864e779ad2SMichal Simek static int gpio_set_output_value(unsigned gpio, int value)
1874e779ad2SMichal Simek {
1884e779ad2SMichal Simek 	u32 val, gpio_priv;
1894e779ad2SMichal Simek 	struct gpio_regs *regs;
1904e779ad2SMichal Simek 	struct xilinx_gpio_priv *priv = gpio_get_controller(gpio);
1914e779ad2SMichal Simek 
1924e779ad2SMichal Simek 	if (priv) {
1934e779ad2SMichal Simek 		regs = priv->regs;
1944e779ad2SMichal Simek 		gpio_priv = gpio - priv->gpio_min;
1954e779ad2SMichal Simek 		val = priv->gpiodata_store;
1964e779ad2SMichal Simek 		if (value)
1974e779ad2SMichal Simek 			val |= 1 << gpio_priv;
1984e779ad2SMichal Simek 		else
1994e779ad2SMichal Simek 			val &= ~(1 << gpio_priv);
2004e779ad2SMichal Simek 
2014e779ad2SMichal Simek 		writel(val, &regs->gpiodata);
2024e779ad2SMichal Simek 		debug("%s: reg: %x, gpio_no: %d, output_val: %d\n", __func__,
2034e779ad2SMichal Simek 		      (u32)priv->regs, gpio_priv, val);
2044e779ad2SMichal Simek 		priv->gpiodata_store = val;
2054e779ad2SMichal Simek 
2064e779ad2SMichal Simek 		return 0;
2074e779ad2SMichal Simek 	}
2084e779ad2SMichal Simek 
2094e779ad2SMichal Simek 	return -1;
2104e779ad2SMichal Simek }
2114e779ad2SMichal Simek 
gpio_set_value(unsigned gpio,int value)2124e779ad2SMichal Simek int gpio_set_value(unsigned gpio, int value)
2134e779ad2SMichal Simek {
2144e779ad2SMichal Simek 	if (gpio_get_direction(gpio) == GPIO_DIRECTION_OUT)
2154e779ad2SMichal Simek 		return gpio_set_output_value(gpio, value);
2164e779ad2SMichal Simek 
2174e779ad2SMichal Simek 	return -1;
2184e779ad2SMichal Simek }
2194e779ad2SMichal Simek 
2204e779ad2SMichal Simek /* Set GPIO as input */
gpio_direction_input(unsigned gpio)2214e779ad2SMichal Simek int gpio_direction_input(unsigned gpio)
2224e779ad2SMichal Simek {
2234e779ad2SMichal Simek 	debug("%s\n", __func__);
2244e779ad2SMichal Simek 	return gpio_set_direction(gpio, GPIO_DIRECTION_IN);
2254e779ad2SMichal Simek }
2264e779ad2SMichal Simek 
2274e779ad2SMichal Simek /* Setup GPIO as output and set output value */
gpio_direction_output(unsigned gpio,int value)2284e779ad2SMichal Simek int gpio_direction_output(unsigned gpio, int value)
2294e779ad2SMichal Simek {
2304e779ad2SMichal Simek 	int ret = gpio_set_direction(gpio, GPIO_DIRECTION_OUT);
2314e779ad2SMichal Simek 
2324e779ad2SMichal Simek 	debug("%s\n", __func__);
2334e779ad2SMichal Simek 
2344e779ad2SMichal Simek 	if (ret < 0)
2354e779ad2SMichal Simek 		return ret;
2364e779ad2SMichal Simek 
2374e779ad2SMichal Simek 	return gpio_set_output_value(gpio, value);
2384e779ad2SMichal Simek }
2394e779ad2SMichal Simek 
2404e779ad2SMichal Simek /* Show gpio status */
gpio_info(void)2414e779ad2SMichal Simek void gpio_info(void)
2424e779ad2SMichal Simek {
2434e779ad2SMichal Simek 	unsigned gpio;
2444e779ad2SMichal Simek 
2454e779ad2SMichal Simek 	struct list_head *entry;
2464e779ad2SMichal Simek 	struct xilinx_gpio_priv *priv = NULL;
2474e779ad2SMichal Simek 
2484e779ad2SMichal Simek 	list_for_each(entry, &gpio_list) {
2494e779ad2SMichal Simek 		priv = list_entry(entry, struct xilinx_gpio_priv, list);
2504e779ad2SMichal Simek 		printf("\n%s: %s/%x (%d-%d)\n", __func__, priv->name,
2514e779ad2SMichal Simek 		       (u32)priv->regs, priv->gpio_min, priv->gpio_max);
2524e779ad2SMichal Simek 
2534e779ad2SMichal Simek 		for (gpio = priv->gpio_min; gpio <= priv->gpio_max; gpio++) {
2544e779ad2SMichal Simek 			printf("GPIO_%d:\t%s is an ", gpio, get_name(gpio));
2554e779ad2SMichal Simek 			if (gpio_get_direction(gpio) == GPIO_DIRECTION_OUT)
2564e779ad2SMichal Simek 				printf("OUTPUT value = %d\n",
2574e779ad2SMichal Simek 				       gpio_get_output_value(gpio));
2584e779ad2SMichal Simek 			else
2594e779ad2SMichal Simek 				printf("INPUT value = %d\n",
2604e779ad2SMichal Simek 				       gpio_get_input_value(gpio));
2614e779ad2SMichal Simek 		}
2624e779ad2SMichal Simek 	}
2634e779ad2SMichal Simek }
2644e779ad2SMichal Simek 
gpio_request(unsigned gpio,const char * label)2654e779ad2SMichal Simek int gpio_request(unsigned gpio, const char *label)
2664e779ad2SMichal Simek {
2674e779ad2SMichal Simek 	u32 gpio_priv;
2684e779ad2SMichal Simek 	struct xilinx_gpio_priv *priv;
2694e779ad2SMichal Simek 
2704e779ad2SMichal Simek 	if (gpio >= xilinx_gpio_max)
2714e779ad2SMichal Simek 		return -EINVAL;
2724e779ad2SMichal Simek 
2734e779ad2SMichal Simek 	priv = gpio_get_controller(gpio);
2744e779ad2SMichal Simek 	if (priv) {
2754e779ad2SMichal Simek 		gpio_priv = gpio - priv->gpio_min;
2764e779ad2SMichal Simek 
2774e779ad2SMichal Simek 		if (label != NULL) {
2784e779ad2SMichal Simek 			strncpy(priv->gpio_name[gpio_priv].name, label,
2794e779ad2SMichal Simek 				GPIO_NAME_SIZE);
2804e779ad2SMichal Simek 			priv->gpio_name[gpio_priv].name[GPIO_NAME_SIZE - 1] =
2814e779ad2SMichal Simek 					'\0';
2824e779ad2SMichal Simek 		}
2834e779ad2SMichal Simek 		return 0;
2844e779ad2SMichal Simek 	}
2854e779ad2SMichal Simek 
2864e779ad2SMichal Simek 	return -1;
2874e779ad2SMichal Simek }
2884e779ad2SMichal Simek 
gpio_free(unsigned gpio)2894e779ad2SMichal Simek int gpio_free(unsigned gpio)
2904e779ad2SMichal Simek {
2914e779ad2SMichal Simek 	u32 gpio_priv;
2924e779ad2SMichal Simek 	struct xilinx_gpio_priv *priv;
2934e779ad2SMichal Simek 
2944e779ad2SMichal Simek 	if (gpio >= xilinx_gpio_max)
2954e779ad2SMichal Simek 		return -EINVAL;
2964e779ad2SMichal Simek 
2974e779ad2SMichal Simek 	priv = gpio_get_controller(gpio);
2984e779ad2SMichal Simek 	if (priv) {
2994e779ad2SMichal Simek 		gpio_priv = gpio - priv->gpio_min;
3004e779ad2SMichal Simek 		priv->gpio_name[gpio_priv].name[0] = '\0';
3014e779ad2SMichal Simek 
3024e779ad2SMichal Simek 		/* Do nothing here */
3034e779ad2SMichal Simek 		return 0;
3044e779ad2SMichal Simek 	}
3054e779ad2SMichal Simek 
3064e779ad2SMichal Simek 	return -1;
3074e779ad2SMichal Simek }
3084e779ad2SMichal Simek 
gpio_alloc(u32 baseaddr,const char * name,u32 gpio_no)3094e779ad2SMichal Simek int gpio_alloc(u32 baseaddr, const char *name, u32 gpio_no)
3104e779ad2SMichal Simek {
3114e779ad2SMichal Simek 	struct xilinx_gpio_priv *priv;
3124e779ad2SMichal Simek 
3134e779ad2SMichal Simek 	priv = calloc(1, sizeof(struct xilinx_gpio_priv));
3144e779ad2SMichal Simek 
3154e779ad2SMichal Simek 	/* Setup gpio name */
3164e779ad2SMichal Simek 	if (name != NULL) {
3174e779ad2SMichal Simek 		strncpy(priv->name, name, GPIO_NAME_SIZE);
3184e779ad2SMichal Simek 		priv->name[GPIO_NAME_SIZE - 1] = '\0';
3194e779ad2SMichal Simek 	}
3204e779ad2SMichal Simek 	priv->regs = (struct gpio_regs *)baseaddr;
3214e779ad2SMichal Simek 
3224e779ad2SMichal Simek 	priv->gpio_min = xilinx_gpio_max;
3234e779ad2SMichal Simek 	xilinx_gpio_max = priv->gpio_min + gpio_no;
3244e779ad2SMichal Simek 	priv->gpio_max = xilinx_gpio_max - 1;
3254e779ad2SMichal Simek 
3264e779ad2SMichal Simek 	priv->gpio_name = calloc(gpio_no, sizeof(struct gpio_names));
3274e779ad2SMichal Simek 
3284e779ad2SMichal Simek 	INIT_LIST_HEAD(&priv->list);
3294e779ad2SMichal Simek 	list_add_tail(&priv->list, &gpio_list);
3304e779ad2SMichal Simek 
3314e779ad2SMichal Simek 	printf("%s: Add %s (%d-%d)\n", __func__, name,
3324e779ad2SMichal Simek 	       priv->gpio_min, priv->gpio_max);
3334e779ad2SMichal Simek 
3344e779ad2SMichal Simek 	/* Return the first gpio allocated for this device */
3354e779ad2SMichal Simek 	return priv->gpio_min;
3364e779ad2SMichal Simek }
3374e779ad2SMichal Simek 
3384e779ad2SMichal Simek /* Dual channel gpio is one IP with two independent channels */
gpio_alloc_dual(u32 baseaddr,const char * name,u32 gpio_no0,u32 gpio_no1)3394e779ad2SMichal Simek int gpio_alloc_dual(u32 baseaddr, const char *name, u32 gpio_no0, u32 gpio_no1)
3404e779ad2SMichal Simek {
3414e779ad2SMichal Simek 	int ret;
3424e779ad2SMichal Simek 
3434e779ad2SMichal Simek 	ret = gpio_alloc(baseaddr, name, gpio_no0);
3444e779ad2SMichal Simek 	gpio_alloc(baseaddr + 8, strcat((char *)name, "_1"), gpio_no1);
3454e779ad2SMichal Simek 
3464e779ad2SMichal Simek 	/* Return the first gpio allocated for this device */
3474e779ad2SMichal Simek 	return ret;
3484e779ad2SMichal Simek }
349