]> git.ipfire.org Git - people/ms/u-boot.git/blob - drivers/gpio/zynq_gpio.c
gpio: zynq: Convert Zynq GPIO to driver model
[people/ms/u-boot.git] / drivers / gpio / zynq_gpio.c
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 #ifdef CONFIG_DM_GPIO
18 #include <dm.h>
19 #include <fdtdec.h>
20
21 DECLARE_GLOBAL_DATA_PTR;
22
23 struct zynq_gpio_privdata {
24 phys_addr_t base;
25 };
26 #endif
27
28 /**
29 * zynq_gpio_get_bank_pin - Get the bank number and pin number within that bank
30 * for a given pin in the GPIO device
31 * @pin_num: gpio pin number within the device
32 * @bank_num: an output parameter used to return the bank number of the gpio
33 * pin
34 * @bank_pin_num: an output parameter used to return pin number within a bank
35 * for the given gpio pin
36 *
37 * Returns the bank number and pin offset within the bank.
38 */
39 static inline void zynq_gpio_get_bank_pin(unsigned int pin_num,
40 unsigned int *bank_num,
41 unsigned int *bank_pin_num)
42 {
43 switch (pin_num) {
44 case ZYNQ_GPIO_BANK0_PIN_MIN ... ZYNQ_GPIO_BANK0_PIN_MAX:
45 *bank_num = 0;
46 *bank_pin_num = pin_num;
47 break;
48 case ZYNQ_GPIO_BANK1_PIN_MIN ... ZYNQ_GPIO_BANK1_PIN_MAX:
49 *bank_num = 1;
50 *bank_pin_num = pin_num - ZYNQ_GPIO_BANK1_PIN_MIN;
51 break;
52 case ZYNQ_GPIO_BANK2_PIN_MIN ... ZYNQ_GPIO_BANK2_PIN_MAX:
53 *bank_num = 2;
54 *bank_pin_num = pin_num - ZYNQ_GPIO_BANK2_PIN_MIN;
55 break;
56 case ZYNQ_GPIO_BANK3_PIN_MIN ... ZYNQ_GPIO_BANK3_PIN_MAX:
57 *bank_num = 3;
58 *bank_pin_num = pin_num - ZYNQ_GPIO_BANK3_PIN_MIN;
59 break;
60 default:
61 printf("invalid GPIO pin number: %u\n", pin_num);
62 *bank_num = 0;
63 *bank_pin_num = 0;
64 break;
65 }
66 }
67
68 int gpio_is_valid(unsigned gpio)
69 {
70 return (gpio >= 0) && (gpio < ZYNQ_GPIO_NR_GPIOS);
71 }
72
73 static int check_gpio(unsigned gpio)
74 {
75 if (!gpio_is_valid(gpio)) {
76 printf("ERROR : check_gpio: invalid GPIO %d\n", gpio);
77 return -1;
78 }
79 return 0;
80 }
81
82 #ifndef CONFIG_DM_GPIO
83 /**
84 * gpio_get_value - Get the state of the specified pin of GPIO device
85 * @gpio: gpio pin number within the device
86 *
87 * This function reads the state of the specified pin of the GPIO device.
88 *
89 * Return: 0 if the pin is low, 1 if pin is high.
90 */
91 int gpio_get_value(unsigned gpio)
92 {
93 u32 data;
94 unsigned int bank_num, bank_pin_num;
95
96 if (check_gpio(gpio) < 0)
97 return -1;
98
99 zynq_gpio_get_bank_pin(gpio, &bank_num, &bank_pin_num);
100
101 data = readl(ZYNQ_GPIO_BASE_ADDRESS +
102 ZYNQ_GPIO_DATA_RO_OFFSET(bank_num));
103
104 return (data >> bank_pin_num) & 1;
105 }
106
107 /**
108 * gpio_set_value - Modify the value of the pin with specified value
109 * @gpio: gpio pin number within the device
110 * @value: value used to modify the value of the specified pin
111 *
112 * This function calculates the register offset (i.e to lower 16 bits or
113 * upper 16 bits) based on the given pin number and sets the value of a
114 * gpio pin to the specified value. The value is either 0 or non-zero.
115 */
116 int gpio_set_value(unsigned gpio, int value)
117 {
118 unsigned int reg_offset, bank_num, bank_pin_num;
119
120 if (check_gpio(gpio) < 0)
121 return -1;
122
123 zynq_gpio_get_bank_pin(gpio, &bank_num, &bank_pin_num);
124
125 if (bank_pin_num >= ZYNQ_GPIO_MID_PIN_NUM) {
126 /* only 16 data bits in bit maskable reg */
127 bank_pin_num -= ZYNQ_GPIO_MID_PIN_NUM;
128 reg_offset = ZYNQ_GPIO_DATA_MSW_OFFSET(bank_num);
129 } else {
130 reg_offset = ZYNQ_GPIO_DATA_LSW_OFFSET(bank_num);
131 }
132
133 /*
134 * get the 32 bit value to be written to the mask/data register where
135 * the upper 16 bits is the mask and lower 16 bits is the data
136 */
137 value = !!value;
138 value = ~(1 << (bank_pin_num + ZYNQ_GPIO_MID_PIN_NUM)) &
139 ((value << bank_pin_num) | ZYNQ_GPIO_UPPER_MASK);
140
141 writel(value, ZYNQ_GPIO_BASE_ADDRESS + reg_offset);
142
143 return 0;
144 }
145
146 /**
147 * gpio_direction_input - Set the direction of the specified GPIO pin as input
148 * @gpio: gpio pin number within the device
149 *
150 * This function uses the read-modify-write sequence to set the direction of
151 * the gpio pin as input.
152 *
153 * Return: -1 if invalid gpio specified, 0 if successul
154 */
155 int gpio_direction_input(unsigned gpio)
156 {
157 u32 reg;
158 unsigned int bank_num, bank_pin_num;
159
160 if (check_gpio(gpio) < 0)
161 return -1;
162
163 zynq_gpio_get_bank_pin(gpio, &bank_num, &bank_pin_num);
164
165 /* bank 0 pins 7 and 8 are special and cannot be used as inputs */
166 if (bank_num == 0 && (bank_pin_num == 7 || bank_pin_num == 8))
167 return -1;
168
169 /* clear the bit in direction mode reg to set the pin as input */
170 reg = readl(ZYNQ_GPIO_BASE_ADDRESS + ZYNQ_GPIO_DIRM_OFFSET(bank_num));
171 reg &= ~BIT(bank_pin_num);
172 writel(reg, ZYNQ_GPIO_BASE_ADDRESS + ZYNQ_GPIO_DIRM_OFFSET(bank_num));
173
174 return 0;
175 }
176
177 /**
178 * gpio_direction_output - Set the direction of the specified GPIO pin as output
179 * @gpio: gpio pin number within the device
180 * @value: value to be written to specified pin
181 *
182 * This function sets the direction of specified GPIO pin as output, configures
183 * the Output Enable register for the pin and uses zynq_gpio_set to set
184 * the value of the pin to the value specified.
185 *
186 * Return: 0 always
187 */
188 int gpio_direction_output(unsigned gpio, int value)
189 {
190 u32 reg;
191 unsigned int bank_num, bank_pin_num;
192
193 if (check_gpio(gpio) < 0)
194 return -1;
195
196 zynq_gpio_get_bank_pin(gpio, &bank_num, &bank_pin_num);
197
198 /* set the GPIO pin as output */
199 reg = readl(ZYNQ_GPIO_BASE_ADDRESS + ZYNQ_GPIO_DIRM_OFFSET(bank_num));
200 reg |= BIT(bank_pin_num);
201 writel(reg, ZYNQ_GPIO_BASE_ADDRESS + ZYNQ_GPIO_DIRM_OFFSET(bank_num));
202
203 /* configure the output enable reg for the pin */
204 reg = readl(ZYNQ_GPIO_BASE_ADDRESS + ZYNQ_GPIO_OUTEN_OFFSET(bank_num));
205 reg |= BIT(bank_pin_num);
206 writel(reg, ZYNQ_GPIO_BASE_ADDRESS + ZYNQ_GPIO_OUTEN_OFFSET(bank_num));
207
208 /* set the state of the pin */
209 gpio_set_value(gpio, value);
210 return 0;
211 }
212
213 /**
214 * Request a gpio before using it.
215 *
216 * NOTE: Argument 'label' is unused.
217 */
218 int gpio_request(unsigned gpio, const char *label)
219 {
220 if (check_gpio(gpio) < 0)
221 return -1;
222
223 return 0;
224 }
225
226 /**
227 * Reset and free the gpio after using it.
228 */
229 int gpio_free(unsigned gpio)
230 {
231 return 0;
232 }
233 #else
234 static int zynq_gpio_get_value(struct udevice *dev, unsigned gpio)
235 {
236 u32 data;
237 unsigned int bank_num, bank_pin_num;
238 struct zynq_gpio_privdata *priv = dev_get_priv(dev);
239
240 if (check_gpio(gpio) < 0)
241 return -1;
242
243 zynq_gpio_get_bank_pin(gpio, &bank_num, &bank_pin_num);
244
245 data = readl(priv->base +
246 ZYNQ_GPIO_DATA_RO_OFFSET(bank_num));
247
248 return (data >> bank_pin_num) & 1;
249 }
250
251 static int zynq_gpio_set_value(struct udevice *dev, unsigned gpio, int value)
252 {
253 unsigned int reg_offset, bank_num, bank_pin_num;
254 struct zynq_gpio_privdata *priv = dev_get_priv(dev);
255
256 if (check_gpio(gpio) < 0)
257 return -1;
258
259 zynq_gpio_get_bank_pin(gpio, &bank_num, &bank_pin_num);
260
261 if (bank_pin_num >= ZYNQ_GPIO_MID_PIN_NUM) {
262 /* only 16 data bits in bit maskable reg */
263 bank_pin_num -= ZYNQ_GPIO_MID_PIN_NUM;
264 reg_offset = ZYNQ_GPIO_DATA_MSW_OFFSET(bank_num);
265 } else {
266 reg_offset = ZYNQ_GPIO_DATA_LSW_OFFSET(bank_num);
267 }
268
269 /*
270 * get the 32 bit value to be written to the mask/data register where
271 * the upper 16 bits is the mask and lower 16 bits is the data
272 */
273 value = !!value;
274 value = ~(1 << (bank_pin_num + ZYNQ_GPIO_MID_PIN_NUM)) &
275 ((value << bank_pin_num) | ZYNQ_GPIO_UPPER_MASK);
276
277 writel(value, priv->base + reg_offset);
278
279 return 0;
280 }
281
282 static int zynq_gpio_direction_input(struct udevice *dev, unsigned gpio)
283 {
284 u32 reg;
285 unsigned int bank_num, bank_pin_num;
286 struct zynq_gpio_privdata *priv = dev_get_priv(dev);
287
288 if (check_gpio(gpio) < 0)
289 return -1;
290
291 zynq_gpio_get_bank_pin(gpio, &bank_num, &bank_pin_num);
292
293 /* bank 0 pins 7 and 8 are special and cannot be used as inputs */
294 if (bank_num == 0 && (bank_pin_num == 7 || bank_pin_num == 8))
295 return -1;
296
297 /* clear the bit in direction mode reg to set the pin as input */
298 reg = readl(priv->base + ZYNQ_GPIO_DIRM_OFFSET(bank_num));
299 reg &= ~BIT(bank_pin_num);
300 writel(reg, priv->base + ZYNQ_GPIO_DIRM_OFFSET(bank_num));
301
302 return 0;
303 }
304
305 static int zynq_gpio_direction_output(struct udevice *dev, unsigned gpio,
306 int value)
307 {
308 u32 reg;
309 unsigned int bank_num, bank_pin_num;
310 struct zynq_gpio_privdata *priv = dev_get_priv(dev);
311
312 if (check_gpio(gpio) < 0)
313 return -1;
314
315 zynq_gpio_get_bank_pin(gpio, &bank_num, &bank_pin_num);
316
317 /* set the GPIO pin as output */
318 reg = readl(priv->base + ZYNQ_GPIO_DIRM_OFFSET(bank_num));
319 reg |= BIT(bank_pin_num);
320 writel(reg, priv->base + ZYNQ_GPIO_DIRM_OFFSET(bank_num));
321
322 /* configure the output enable reg for the pin */
323 reg = readl(priv->base + ZYNQ_GPIO_OUTEN_OFFSET(bank_num));
324 reg |= BIT(bank_pin_num);
325 writel(reg, priv->base + ZYNQ_GPIO_OUTEN_OFFSET(bank_num));
326
327 /* set the state of the pin */
328 gpio_set_value(gpio, value);
329 return 0;
330 }
331
332 static const struct dm_gpio_ops gpio_zynq_ops = {
333 .direction_input = zynq_gpio_direction_input,
334 .direction_output = zynq_gpio_direction_output,
335 .get_value = zynq_gpio_get_value,
336 .set_value = zynq_gpio_set_value,
337 };
338
339 static int zynq_gpio_probe(struct udevice *dev)
340 {
341 struct zynq_gpio_privdata *priv = dev_get_priv(dev);
342
343 priv->base = dev_get_addr(dev);
344
345 return 0;
346 }
347
348 static int zynq_gpio_ofdata_to_platdata(struct udevice *dev)
349 {
350 struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
351
352 uc_priv->gpio_count = ZYNQ_GPIO_NR_GPIOS;
353
354 return 0;
355 }
356
357 static const struct udevice_id zynq_gpio_ids[] = {
358 { .compatible = "xlnx,zynq-gpio-1.0" },
359 { }
360 };
361
362 U_BOOT_DRIVER(gpio_zynq) = {
363 .name = "gpio_zynq",
364 .id = UCLASS_GPIO,
365 .ops = &gpio_zynq_ops,
366 .of_match = zynq_gpio_ids,
367 .ofdata_to_platdata = zynq_gpio_ofdata_to_platdata,
368 .probe = zynq_gpio_probe,
369 .priv_auto_alloc_size = sizeof(struct zynq_gpio_privdata),
370 };
371 #endif