]> git.sur5r.net Git - u-boot/blob - drivers/gpio/zynq_gpio.c
92c9f0ecd12e471212cd1c18d5f28bd946c866dd
[u-boot] / 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