arm: Remove aspenite board
[platform/kernel/u-boot.git] / drivers / gpio / xilinx_gpio.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (c) 2013 - 2018 Xilinx, Michal Simek
4  */
5
6 #include <common.h>
7 #include <errno.h>
8 #include <log.h>
9 #include <malloc.h>
10 #include <linux/list.h>
11 #include <asm/io.h>
12 #include <asm/gpio.h>
13 #include <dm.h>
14 #include <dt-bindings/gpio/gpio.h>
15
16 #define XILINX_GPIO_MAX_BANK    2
17
18 /* Gpio simple map */
19 struct gpio_regs {
20         u32 gpiodata;
21         u32 gpiodir;
22 };
23
24 struct xilinx_gpio_plat {
25         struct gpio_regs *regs;
26         int bank_max[XILINX_GPIO_MAX_BANK];
27         int bank_input[XILINX_GPIO_MAX_BANK];
28         int bank_output[XILINX_GPIO_MAX_BANK];
29         u32 dout_default[XILINX_GPIO_MAX_BANK];
30 };
31
32 struct xilinx_gpio_privdata {
33         u32 output_val[XILINX_GPIO_MAX_BANK];
34 };
35
36 static int xilinx_gpio_get_bank_pin(unsigned offset, u32 *bank_num,
37                                     u32 *bank_pin_num, struct udevice *dev)
38 {
39         struct xilinx_gpio_plat *plat = dev_get_plat(dev);
40         u32 bank, max_pins;
41         /* the first gpio is 0 not 1 */
42         u32 pin_num = offset;
43
44         for (bank = 0; bank < XILINX_GPIO_MAX_BANK; bank++) {
45                 max_pins = plat->bank_max[bank];
46                 if (pin_num < max_pins) {
47                         debug("%s: found at bank 0x%x pin 0x%x\n", __func__,
48                               bank, pin_num);
49                         *bank_num = bank;
50                         *bank_pin_num = pin_num;
51                         return 0;
52                 }
53                 pin_num -= max_pins;
54         }
55
56         return -EINVAL;
57 }
58
59 static int xilinx_gpio_set_value(struct udevice *dev, unsigned offset,
60                                  int value)
61 {
62         struct xilinx_gpio_plat *plat = dev_get_plat(dev);
63         struct xilinx_gpio_privdata *priv = dev_get_priv(dev);
64         int val, ret;
65         u32 bank, pin;
66
67         ret = xilinx_gpio_get_bank_pin(offset, &bank, &pin, dev);
68         if (ret)
69                 return ret;
70
71         val = priv->output_val[bank];
72
73         debug("%s: regs: %lx, value: %x, gpio: %x, bank %x, pin %x, out %x\n",
74               __func__, (ulong)plat->regs, value, offset, bank, pin, val);
75
76         if (value)
77                 val = val | (1 << pin);
78         else
79                 val = val & ~(1 << pin);
80
81         writel(val, &plat->regs->gpiodata + bank * 2);
82
83         priv->output_val[bank] = val;
84
85         return 0;
86 };
87
88 static int xilinx_gpio_get_value(struct udevice *dev, unsigned offset)
89 {
90         struct xilinx_gpio_plat *plat = dev_get_plat(dev);
91         struct xilinx_gpio_privdata *priv = dev_get_priv(dev);
92         int val, ret;
93         u32 bank, pin;
94
95         ret = xilinx_gpio_get_bank_pin(offset, &bank, &pin, dev);
96         if (ret)
97                 return ret;
98
99         debug("%s: regs: %lx, gpio: %x, bank %x, pin %x\n", __func__,
100               (ulong)plat->regs, offset, bank, pin);
101
102         if (plat->bank_output[bank]) {
103                 debug("%s: Read saved output value\n", __func__);
104                 val = priv->output_val[bank];
105         } else {
106                 debug("%s: Read input value from reg\n", __func__);
107                 val = readl(&plat->regs->gpiodata + bank * 2);
108         }
109
110         val = !!(val & (1 << pin));
111
112         return val;
113 };
114
115 static int xilinx_gpio_get_function(struct udevice *dev, unsigned offset)
116 {
117         struct xilinx_gpio_plat *plat = dev_get_plat(dev);
118         int val, ret;
119         u32 bank, pin;
120
121         ret = xilinx_gpio_get_bank_pin(offset, &bank, &pin, dev);
122         if (ret)
123                 return ret;
124
125         /* Check if all pins are inputs */
126         if (plat->bank_input[bank])
127                 return GPIOF_INPUT;
128
129         /* Check if all pins are outputs */
130         if (plat->bank_output[bank])
131                 return GPIOF_OUTPUT;
132
133         /* FIXME test on dual */
134         val = readl(&plat->regs->gpiodir + bank * 2);
135         val = !(val & (1 << pin));
136
137         /* input is 1 in reg but GPIOF_INPUT is 0 */
138         /* output is 0 in reg but GPIOF_OUTPUT is 1 */
139
140         return val;
141 }
142
143 static int xilinx_gpio_direction_output(struct udevice *dev, unsigned offset,
144                                         int value)
145 {
146         struct xilinx_gpio_plat *plat = dev_get_plat(dev);
147         int val, ret;
148         u32 bank, pin;
149
150         ret = xilinx_gpio_get_bank_pin(offset, &bank, &pin, dev);
151         if (ret)
152                 return ret;
153
154         /* can't change it if all is input by default */
155         if (plat->bank_input[bank])
156                 return -EINVAL;
157
158         xilinx_gpio_set_value(dev, offset, value);
159
160         if (!plat->bank_output[bank]) {
161                 val = readl(&plat->regs->gpiodir + bank * 2);
162                 val = val & ~(1 << pin);
163                 writel(val, &plat->regs->gpiodir + bank * 2);
164         }
165
166         return 0;
167 }
168
169 static int xilinx_gpio_direction_input(struct udevice *dev, unsigned offset)
170 {
171         struct xilinx_gpio_plat *plat = dev_get_plat(dev);
172         int val, ret;
173         u32 bank, pin;
174
175         ret = xilinx_gpio_get_bank_pin(offset, &bank, &pin, dev);
176         if (ret)
177                 return ret;
178
179         /* Already input */
180         if (plat->bank_input[bank])
181                 return 0;
182
183         /* can't change it if all is output by default */
184         if (plat->bank_output[bank])
185                 return -EINVAL;
186
187         val = readl(&plat->regs->gpiodir + bank * 2);
188         val = val | (1 << pin);
189         writel(val, &plat->regs->gpiodir + bank * 2);
190
191         return 0;
192 }
193
194 static int xilinx_gpio_xlate(struct udevice *dev, struct gpio_desc *desc,
195                              struct ofnode_phandle_args *args)
196 {
197         struct xilinx_gpio_plat *plat = dev_get_plat(dev);
198
199         desc->offset = args->args[0];
200
201         debug("%s: argc: %x, [0]: %x, [1]: %x, [2]: %x\n", __func__,
202               args->args_count, args->args[0], args->args[1], args->args[2]);
203
204         /*
205          * The second cell is channel offset:
206          *  0 is first channel, 8 is second channel
207          *
208          * U-Boot driver just combine channels together that's why simply
209          * add amount of pins in second channel if present.
210          */
211         if (args->args[1]) {
212                 if (!plat->bank_max[1]) {
213                         printf("%s: %s has no second channel\n",
214                                __func__, dev->name);
215                         return -EINVAL;
216                 }
217
218                 desc->offset += plat->bank_max[0];
219         }
220
221         /* The third cell is optional */
222         if (args->args_count > 2)
223                 desc->flags = (args->args[2] &
224                                GPIO_ACTIVE_LOW ? GPIOD_ACTIVE_LOW : 0);
225
226         debug("%s: offset %x, flags %lx\n",
227               __func__, desc->offset, desc->flags);
228         return 0;
229 }
230
231 static const struct dm_gpio_ops xilinx_gpio_ops = {
232         .direction_input = xilinx_gpio_direction_input,
233         .direction_output = xilinx_gpio_direction_output,
234         .get_value = xilinx_gpio_get_value,
235         .set_value = xilinx_gpio_set_value,
236         .get_function = xilinx_gpio_get_function,
237         .xlate = xilinx_gpio_xlate,
238 };
239
240 static int xilinx_gpio_probe(struct udevice *dev)
241 {
242         struct xilinx_gpio_plat *plat = dev_get_plat(dev);
243         struct xilinx_gpio_privdata *priv = dev_get_priv(dev);
244         struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
245         const void *label_ptr;
246
247         label_ptr = dev_read_prop(dev, "label", NULL);
248         if (label_ptr) {
249                 uc_priv->bank_name = strdup(label_ptr);
250                 if (!uc_priv->bank_name)
251                         return -ENOMEM;
252         } else {
253                 uc_priv->bank_name = dev->name;
254         }
255
256         uc_priv->gpio_count = plat->bank_max[0] + plat->bank_max[1];
257
258         priv->output_val[0] = plat->dout_default[0];
259
260         if (plat->bank_max[1])
261                 priv->output_val[1] = plat->dout_default[1];
262
263         return 0;
264 }
265
266 static int xilinx_gpio_of_to_plat(struct udevice *dev)
267 {
268         struct xilinx_gpio_plat *plat = dev_get_plat(dev);
269         int is_dual;
270
271         plat->regs = (struct gpio_regs *)dev_read_addr(dev);
272
273         plat->bank_max[0] = dev_read_u32_default(dev, "xlnx,gpio-width", 0);
274         plat->bank_input[0] = dev_read_u32_default(dev, "xlnx,all-inputs", 0);
275         plat->bank_output[0] = dev_read_u32_default(dev, "xlnx,all-outputs", 0);
276         plat->dout_default[0] = dev_read_u32_default(dev, "xlnx,dout-default",
277                                                      0);
278
279         is_dual = dev_read_u32_default(dev, "xlnx,is-dual", 0);
280         if (is_dual) {
281                 plat->bank_max[1] = dev_read_u32_default(dev,
282                                                          "xlnx,gpio2-width", 0);
283                 plat->bank_input[1] = dev_read_u32_default(dev,
284                                                 "xlnx,all-inputs-2", 0);
285                 plat->bank_output[1] = dev_read_u32_default(dev,
286                                                 "xlnx,all-outputs-2", 0);
287                 plat->dout_default[1] = dev_read_u32_default(dev,
288                                                 "xlnx,dout-default-2", 0);
289         }
290
291         return 0;
292 }
293
294 static const struct udevice_id xilinx_gpio_ids[] = {
295         { .compatible = "xlnx,xps-gpio-1.00.a",},
296         { }
297 };
298
299 U_BOOT_DRIVER(xilinx_gpio) = {
300         .name = "xlnx_gpio",
301         .id = UCLASS_GPIO,
302         .ops = &xilinx_gpio_ops,
303         .of_match = xilinx_gpio_ids,
304         .of_to_plat = xilinx_gpio_of_to_plat,
305         .probe = xilinx_gpio_probe,
306         .plat_auto      = sizeof(struct xilinx_gpio_plat),
307         .priv_auto      = sizeof(struct xilinx_gpio_privdata),
308 };