xref: /openbmc/u-boot/drivers/gpio/zynq_gpio.c (revision fdbb740d)
1 /*
2  * Xilinx Zynq GPIO device driver
3  *
4  * Copyright (C) 2015 DAVE Embedded Systems <devel@dave.eu>
5  *
6  * Most of code taken from linux kernel driver (linux/drivers/gpio/gpio-zynq.c)
7  * Copyright (C) 2009 - 2014 Xilinx, Inc.
8  *
9  * SPDX-License-Identifier:	GPL-2.0+
10  */
11 
12 #include <common.h>
13 #include <asm/gpio.h>
14 #include <asm/io.h>
15 #include <asm/errno.h>
16 
17 /**
18  * zynq_gpio_get_bank_pin - Get the bank number and pin number within that bank
19  * for a given pin in the GPIO device
20  * @pin_num:	gpio pin number within the device
21  * @bank_num:	an output parameter used to return the bank number of the gpio
22  *		pin
23  * @bank_pin_num: an output parameter used to return pin number within a bank
24  *		  for the given gpio pin
25  *
26  * Returns the bank number and pin offset within the bank.
27  */
28 static inline void zynq_gpio_get_bank_pin(unsigned int pin_num,
29 					  unsigned int *bank_num,
30 					  unsigned int *bank_pin_num)
31 {
32 	switch (pin_num) {
33 	case ZYNQ_GPIO_BANK0_PIN_MIN ... ZYNQ_GPIO_BANK0_PIN_MAX:
34 		*bank_num = 0;
35 		*bank_pin_num = pin_num;
36 		break;
37 	case ZYNQ_GPIO_BANK1_PIN_MIN ... ZYNQ_GPIO_BANK1_PIN_MAX:
38 		*bank_num = 1;
39 		*bank_pin_num = pin_num - ZYNQ_GPIO_BANK1_PIN_MIN;
40 		break;
41 	case ZYNQ_GPIO_BANK2_PIN_MIN ... ZYNQ_GPIO_BANK2_PIN_MAX:
42 		*bank_num = 2;
43 		*bank_pin_num = pin_num - ZYNQ_GPIO_BANK2_PIN_MIN;
44 		break;
45 	case ZYNQ_GPIO_BANK3_PIN_MIN ... ZYNQ_GPIO_BANK3_PIN_MAX:
46 		*bank_num = 3;
47 		*bank_pin_num = pin_num - ZYNQ_GPIO_BANK3_PIN_MIN;
48 		break;
49 	default:
50 		printf("invalid GPIO pin number: %u\n", pin_num);
51 		*bank_num = 0;
52 		*bank_pin_num = 0;
53 		break;
54 	}
55 }
56 
57 int gpio_is_valid(unsigned gpio)
58 {
59 	return (gpio >= 0) && (gpio < ZYNQ_GPIO_NR_GPIOS);
60 }
61 
62 static int check_gpio(unsigned gpio)
63 {
64 	if (!gpio_is_valid(gpio)) {
65 		printf("ERROR : check_gpio: invalid GPIO %d\n", gpio);
66 		return -1;
67 	}
68 	return 0;
69 }
70 
71 /**
72  * gpio_get_value - Get the state of the specified pin of GPIO device
73  * @gpio:	gpio pin number within the device
74  *
75  * This function reads the state of the specified pin of the GPIO device.
76  *
77  * Return: 0 if the pin is low, 1 if pin is high.
78  */
79 int gpio_get_value(unsigned gpio)
80 {
81 	u32 data;
82 	unsigned int bank_num, bank_pin_num;
83 
84 	if (check_gpio(gpio) < 0)
85 		return -1;
86 
87 	zynq_gpio_get_bank_pin(gpio, &bank_num, &bank_pin_num);
88 
89 	data = readl(ZYNQ_GPIO_BASE_ADDRESS +
90 			     ZYNQ_GPIO_DATA_RO_OFFSET(bank_num));
91 
92 	return (data >> bank_pin_num) & 1;
93 }
94 
95 /**
96  * gpio_set_value - Modify the value of the pin with specified value
97  * @gpio:	gpio pin number within the device
98  * @value:	value used to modify the value of the specified pin
99  *
100  * This function calculates the register offset (i.e to lower 16 bits or
101  * upper 16 bits) based on the given pin number and sets the value of a
102  * gpio pin to the specified value. The value is either 0 or non-zero.
103  */
104 int gpio_set_value(unsigned gpio, int value)
105 {
106 	unsigned int reg_offset, bank_num, bank_pin_num;
107 
108 	if (check_gpio(gpio) < 0)
109 		return -1;
110 
111 	zynq_gpio_get_bank_pin(gpio, &bank_num, &bank_pin_num);
112 
113 	if (bank_pin_num >= ZYNQ_GPIO_MID_PIN_NUM) {
114 		/* only 16 data bits in bit maskable reg */
115 		bank_pin_num -= ZYNQ_GPIO_MID_PIN_NUM;
116 		reg_offset = ZYNQ_GPIO_DATA_MSW_OFFSET(bank_num);
117 	} else {
118 		reg_offset = ZYNQ_GPIO_DATA_LSW_OFFSET(bank_num);
119 	}
120 
121 	/*
122 	 * get the 32 bit value to be written to the mask/data register where
123 	 * the upper 16 bits is the mask and lower 16 bits is the data
124 	 */
125 	value = !!value;
126 	value = ~(1 << (bank_pin_num + ZYNQ_GPIO_MID_PIN_NUM)) &
127 		((value << bank_pin_num) | ZYNQ_GPIO_UPPER_MASK);
128 
129 	writel(value, ZYNQ_GPIO_BASE_ADDRESS + reg_offset);
130 
131 	return 0;
132 }
133 
134 /**
135  * gpio_direction_input - Set the direction of the specified GPIO pin as input
136  * @gpio:	gpio pin number within the device
137  *
138  * This function uses the read-modify-write sequence to set the direction of
139  * the gpio pin as input.
140  *
141  * Return: -1 if invalid gpio specified, 0 if successul
142  */
143 int gpio_direction_input(unsigned gpio)
144 {
145 	u32 reg;
146 	unsigned int bank_num, bank_pin_num;
147 
148 	if (check_gpio(gpio) < 0)
149 		return -1;
150 
151 	zynq_gpio_get_bank_pin(gpio, &bank_num, &bank_pin_num);
152 
153 	/* bank 0 pins 7 and 8 are special and cannot be used as inputs */
154 	if (bank_num == 0 && (bank_pin_num == 7 || bank_pin_num == 8))
155 		return -1;
156 
157 	/* clear the bit in direction mode reg to set the pin as input */
158 	reg = readl(ZYNQ_GPIO_BASE_ADDRESS + ZYNQ_GPIO_DIRM_OFFSET(bank_num));
159 	reg &= ~BIT(bank_pin_num);
160 	writel(reg, ZYNQ_GPIO_BASE_ADDRESS + ZYNQ_GPIO_DIRM_OFFSET(bank_num));
161 
162 	return 0;
163 }
164 
165 /**
166  * gpio_direction_output - Set the direction of the specified GPIO pin as output
167  * @gpio:	gpio pin number within the device
168  * @value:	value to be written to specified pin
169  *
170  * This function sets the direction of specified GPIO pin as output, configures
171  * the Output Enable register for the pin and uses zynq_gpio_set to set
172  * the value of the pin to the value specified.
173  *
174  * Return: 0 always
175  */
176 int gpio_direction_output(unsigned gpio, int value)
177 {
178 	u32 reg;
179 	unsigned int bank_num, bank_pin_num;
180 
181 	if (check_gpio(gpio) < 0)
182 		return -1;
183 
184 	zynq_gpio_get_bank_pin(gpio, &bank_num, &bank_pin_num);
185 
186 	/* set the GPIO pin as output */
187 	reg = readl(ZYNQ_GPIO_BASE_ADDRESS + ZYNQ_GPIO_DIRM_OFFSET(bank_num));
188 	reg |= BIT(bank_pin_num);
189 	writel(reg, ZYNQ_GPIO_BASE_ADDRESS + ZYNQ_GPIO_DIRM_OFFSET(bank_num));
190 
191 	/* configure the output enable reg for the pin */
192 	reg = readl(ZYNQ_GPIO_BASE_ADDRESS + ZYNQ_GPIO_OUTEN_OFFSET(bank_num));
193 	reg |= BIT(bank_pin_num);
194 	writel(reg, ZYNQ_GPIO_BASE_ADDRESS + ZYNQ_GPIO_OUTEN_OFFSET(bank_num));
195 
196 	/* set the state of the pin */
197 	gpio_set_value(gpio, value);
198 	return 0;
199 }
200 
201 /**
202  * Request a gpio before using it.
203  *
204  * NOTE: Argument 'label' is unused.
205  */
206 int gpio_request(unsigned gpio, const char *label)
207 {
208 	if (check_gpio(gpio) < 0)
209 		return -1;
210 
211 	return 0;
212 }
213 
214 /**
215  * Reset and free the gpio after using it.
216  */
217 int gpio_free(unsigned gpio)
218 {
219 	return 0;
220 }
221