]> git.sur5r.net Git - u-boot/blob - drivers/gpio/zynq_gpio.c
07c2eb54ff30a8dbff19ca79cdb2064014ed3f97
[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 #include <dm.h>
17 #include <fdtdec.h>
18
19 DECLARE_GLOBAL_DATA_PTR;
20
21 struct zynq_gpio_privdata {
22         phys_addr_t base;
23 };
24
25 /**
26  * zynq_gpio_get_bank_pin - Get the bank number and pin number within that bank
27  * for a given pin in the GPIO device
28  * @pin_num:    gpio pin number within the device
29  * @bank_num:   an output parameter used to return the bank number of the gpio
30  *              pin
31  * @bank_pin_num: an output parameter used to return pin number within a bank
32  *                for the given gpio pin
33  *
34  * Returns the bank number and pin offset within the bank.
35  */
36 static inline void zynq_gpio_get_bank_pin(unsigned int pin_num,
37                                           unsigned int *bank_num,
38                                           unsigned int *bank_pin_num)
39 {
40         switch (pin_num) {
41         case ZYNQ_GPIO_BANK0_PIN_MIN ... ZYNQ_GPIO_BANK0_PIN_MAX:
42                 *bank_num = 0;
43                 *bank_pin_num = pin_num;
44                 break;
45         case ZYNQ_GPIO_BANK1_PIN_MIN ... ZYNQ_GPIO_BANK1_PIN_MAX:
46                 *bank_num = 1;
47                 *bank_pin_num = pin_num - ZYNQ_GPIO_BANK1_PIN_MIN;
48                 break;
49         case ZYNQ_GPIO_BANK2_PIN_MIN ... ZYNQ_GPIO_BANK2_PIN_MAX:
50                 *bank_num = 2;
51                 *bank_pin_num = pin_num - ZYNQ_GPIO_BANK2_PIN_MIN;
52                 break;
53         case ZYNQ_GPIO_BANK3_PIN_MIN ... ZYNQ_GPIO_BANK3_PIN_MAX:
54                 *bank_num = 3;
55                 *bank_pin_num = pin_num - ZYNQ_GPIO_BANK3_PIN_MIN;
56                 break;
57         default:
58                 printf("invalid GPIO pin number: %u\n", pin_num);
59                 *bank_num = 0;
60                 *bank_pin_num = 0;
61                 break;
62         }
63 }
64
65 static int gpio_is_valid(unsigned gpio)
66 {
67         return (gpio >= 0) && (gpio < ZYNQ_GPIO_NR_GPIOS);
68 }
69
70 static int check_gpio(unsigned gpio)
71 {
72         if (!gpio_is_valid(gpio)) {
73                 printf("ERROR : check_gpio: invalid GPIO %d\n", gpio);
74                 return -1;
75         }
76         return 0;
77 }
78
79 static int zynq_gpio_get_value(struct udevice *dev, unsigned gpio)
80 {
81         u32 data;
82         unsigned int bank_num, bank_pin_num;
83         struct zynq_gpio_privdata *priv = dev_get_priv(dev);
84
85         if (check_gpio(gpio) < 0)
86                 return -1;
87
88         zynq_gpio_get_bank_pin(gpio, &bank_num, &bank_pin_num);
89
90         data = readl(priv->base +
91                              ZYNQ_GPIO_DATA_RO_OFFSET(bank_num));
92
93         return (data >> bank_pin_num) & 1;
94 }
95
96 static int zynq_gpio_set_value(struct udevice *dev, unsigned gpio, int value)
97 {
98         unsigned int reg_offset, bank_num, bank_pin_num;
99         struct zynq_gpio_privdata *priv = dev_get_priv(dev);
100
101         if (check_gpio(gpio) < 0)
102                 return -1;
103
104         zynq_gpio_get_bank_pin(gpio, &bank_num, &bank_pin_num);
105
106         if (bank_pin_num >= ZYNQ_GPIO_MID_PIN_NUM) {
107                 /* only 16 data bits in bit maskable reg */
108                 bank_pin_num -= ZYNQ_GPIO_MID_PIN_NUM;
109                 reg_offset = ZYNQ_GPIO_DATA_MSW_OFFSET(bank_num);
110         } else {
111                 reg_offset = ZYNQ_GPIO_DATA_LSW_OFFSET(bank_num);
112         }
113
114         /*
115          * get the 32 bit value to be written to the mask/data register where
116          * the upper 16 bits is the mask and lower 16 bits is the data
117          */
118         value = !!value;
119         value = ~(1 << (bank_pin_num + ZYNQ_GPIO_MID_PIN_NUM)) &
120                 ((value << bank_pin_num) | ZYNQ_GPIO_UPPER_MASK);
121
122         writel(value, priv->base + reg_offset);
123
124         return 0;
125 }
126
127 static int zynq_gpio_direction_input(struct udevice *dev, unsigned gpio)
128 {
129         u32 reg;
130         unsigned int bank_num, bank_pin_num;
131         struct zynq_gpio_privdata *priv = dev_get_priv(dev);
132
133         if (check_gpio(gpio) < 0)
134                 return -1;
135
136         zynq_gpio_get_bank_pin(gpio, &bank_num, &bank_pin_num);
137
138         /* bank 0 pins 7 and 8 are special and cannot be used as inputs */
139         if (bank_num == 0 && (bank_pin_num == 7 || bank_pin_num == 8))
140                 return -1;
141
142         /* clear the bit in direction mode reg to set the pin as input */
143         reg = readl(priv->base + ZYNQ_GPIO_DIRM_OFFSET(bank_num));
144         reg &= ~BIT(bank_pin_num);
145         writel(reg, priv->base + ZYNQ_GPIO_DIRM_OFFSET(bank_num));
146
147         return 0;
148 }
149
150 static int zynq_gpio_direction_output(struct udevice *dev, unsigned gpio,
151                                       int value)
152 {
153         u32 reg;
154         unsigned int bank_num, bank_pin_num;
155         struct zynq_gpio_privdata *priv = dev_get_priv(dev);
156
157         if (check_gpio(gpio) < 0)
158                 return -1;
159
160         zynq_gpio_get_bank_pin(gpio, &bank_num, &bank_pin_num);
161
162         /* set the GPIO pin as output */
163         reg = readl(priv->base + ZYNQ_GPIO_DIRM_OFFSET(bank_num));
164         reg |= BIT(bank_pin_num);
165         writel(reg, priv->base + ZYNQ_GPIO_DIRM_OFFSET(bank_num));
166
167         /* configure the output enable reg for the pin */
168         reg = readl(priv->base + ZYNQ_GPIO_OUTEN_OFFSET(bank_num));
169         reg |= BIT(bank_pin_num);
170         writel(reg, priv->base + ZYNQ_GPIO_OUTEN_OFFSET(bank_num));
171
172         /* set the state of the pin */
173         gpio_set_value(gpio, value);
174         return 0;
175 }
176
177 static const struct dm_gpio_ops gpio_zynq_ops = {
178         .direction_input        = zynq_gpio_direction_input,
179         .direction_output       = zynq_gpio_direction_output,
180         .get_value              = zynq_gpio_get_value,
181         .set_value              = zynq_gpio_set_value,
182 };
183
184 static int zynq_gpio_probe(struct udevice *dev)
185 {
186         struct zynq_gpio_privdata *priv = dev_get_priv(dev);
187
188         priv->base = dev_get_addr(dev);
189
190         return 0;
191 }
192
193 static int zynq_gpio_ofdata_to_platdata(struct udevice *dev)
194 {
195         struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
196
197         uc_priv->gpio_count = ZYNQ_GPIO_NR_GPIOS;
198
199         return 0;
200 }
201
202 static const struct udevice_id zynq_gpio_ids[] = {
203         { .compatible = "xlnx,zynq-gpio-1.0" },
204         { }
205 };
206
207 U_BOOT_DRIVER(gpio_zynq) = {
208         .name   = "gpio_zynq",
209         .id     = UCLASS_GPIO,
210         .ops    = &gpio_zynq_ops,
211         .of_match = zynq_gpio_ids,
212         .ofdata_to_platdata = zynq_gpio_ofdata_to_platdata,
213         .probe  = zynq_gpio_probe,
214         .priv_auto_alloc_size = sizeof(struct zynq_gpio_privdata),
215 };