]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - drivers/gpio/mxc_gpio.c
sunxi: Add CONFIG_OLD_SUNXI_KERNEL_COMPAT Kconfig option
[karo-tx-uboot.git] / drivers / gpio / mxc_gpio.c
1 /*
2  * Copyright (C) 2009
3  * Guennadi Liakhovetski, DENX Software Engineering, <lg@denx.de>
4  *
5  * Copyright (C) 2011
6  * Stefano Babic, DENX Software Engineering, <sbabic@denx.de>
7  *
8  * SPDX-License-Identifier:     GPL-2.0+
9  */
10 #include <common.h>
11 #include <errno.h>
12 #include <dm.h>
13 #include <malloc.h>
14 #include <asm/arch/imx-regs.h>
15 #include <asm/gpio.h>
16 #include <asm/io.h>
17
18 enum mxc_gpio_direction {
19         MXC_GPIO_DIRECTION_IN,
20         MXC_GPIO_DIRECTION_OUT,
21 };
22
23 #define GPIO_NAME_SIZE                  20
24 #define GPIO_PER_BANK                   32
25
26 struct mxc_gpio_plat {
27         struct gpio_regs *regs;
28 };
29
30 struct mxc_bank_info {
31         char label[GPIO_PER_BANK][GPIO_NAME_SIZE];
32         struct gpio_regs *regs;
33 };
34
35 #ifndef CONFIG_DM_GPIO
36 #define GPIO_TO_PORT(n)         (n / 32)
37
38 /* GPIO port description */
39 static unsigned long gpio_ports[] = {
40         [0] = GPIO1_BASE_ADDR,
41         [1] = GPIO2_BASE_ADDR,
42         [2] = GPIO3_BASE_ADDR,
43 #if defined(CONFIG_MX25) || defined(CONFIG_MX27) || defined(CONFIG_MX51) || \
44                 defined(CONFIG_MX53) || defined(CONFIG_MX6)
45         [3] = GPIO4_BASE_ADDR,
46 #endif
47 #if defined(CONFIG_MX27) || defined(CONFIG_MX53) || defined(CONFIG_MX6)
48         [4] = GPIO5_BASE_ADDR,
49         [5] = GPIO6_BASE_ADDR,
50 #endif
51 #if defined(CONFIG_MX53) || defined(CONFIG_MX6)
52         [6] = GPIO7_BASE_ADDR,
53 #endif
54 };
55
56 static int mxc_gpio_direction(unsigned int gpio,
57         enum mxc_gpio_direction direction)
58 {
59         unsigned int port = GPIO_TO_PORT(gpio);
60         struct gpio_regs *regs;
61         u32 l;
62
63         if (port >= ARRAY_SIZE(gpio_ports))
64                 return -1;
65
66         gpio &= 0x1f;
67
68         regs = (struct gpio_regs *)gpio_ports[port];
69
70         l = readl(&regs->gpio_dir);
71
72         switch (direction) {
73         case MXC_GPIO_DIRECTION_OUT:
74                 l |= 1 << gpio;
75                 break;
76         case MXC_GPIO_DIRECTION_IN:
77                 l &= ~(1 << gpio);
78         }
79         writel(l, &regs->gpio_dir);
80
81         return 0;
82 }
83
84 int gpio_set_value(unsigned gpio, int value)
85 {
86         unsigned int port = GPIO_TO_PORT(gpio);
87         struct gpio_regs *regs;
88         u32 l;
89
90         if (port >= ARRAY_SIZE(gpio_ports))
91                 return -1;
92
93         gpio &= 0x1f;
94
95         regs = (struct gpio_regs *)gpio_ports[port];
96
97         l = readl(&regs->gpio_dr);
98         if (value)
99                 l |= 1 << gpio;
100         else
101                 l &= ~(1 << gpio);
102         writel(l, &regs->gpio_dr);
103
104         return 0;
105 }
106
107 int gpio_get_value(unsigned gpio)
108 {
109         unsigned int port = GPIO_TO_PORT(gpio);
110         struct gpio_regs *regs;
111         u32 val;
112
113         if (port >= ARRAY_SIZE(gpio_ports))
114                 return -1;
115
116         gpio &= 0x1f;
117
118         regs = (struct gpio_regs *)gpio_ports[port];
119
120         val = (readl(&regs->gpio_psr) >> gpio) & 0x01;
121
122         return val;
123 }
124
125 int gpio_request(unsigned gpio, const char *label)
126 {
127         unsigned int port = GPIO_TO_PORT(gpio);
128         if (port >= ARRAY_SIZE(gpio_ports))
129                 return -1;
130         return 0;
131 }
132
133 int gpio_free(unsigned gpio)
134 {
135         return 0;
136 }
137
138 int gpio_direction_input(unsigned gpio)
139 {
140         return mxc_gpio_direction(gpio, MXC_GPIO_DIRECTION_IN);
141 }
142
143 int gpio_direction_output(unsigned gpio, int value)
144 {
145         int ret = gpio_set_value(gpio, value);
146
147         if (ret < 0)
148                 return ret;
149
150         return mxc_gpio_direction(gpio, MXC_GPIO_DIRECTION_OUT);
151 }
152 #endif
153
154 #ifdef CONFIG_DM_GPIO
155 /**
156  * gpio_is_requested() - check if a GPIO has been requested
157  *
158  * @bank:       Bank to check
159  * @offset:     GPIO offset within bank to check
160  * @return true if marked as requested, false if not
161  */
162 static inline bool gpio_is_requested(struct mxc_bank_info *bank, int offset)
163 {
164         return *bank->label[offset] != '\0';
165 }
166
167 static int mxc_gpio_is_output(struct gpio_regs *regs, int offset)
168 {
169         u32 val;
170
171         val = readl(&regs->gpio_dir);
172
173         return val & (1 << offset) ? 1 : 0;
174 }
175
176 static void mxc_gpio_bank_direction(struct gpio_regs *regs, int offset,
177                                     enum mxc_gpio_direction direction)
178 {
179         u32 l;
180
181         l = readl(&regs->gpio_dir);
182
183         switch (direction) {
184         case MXC_GPIO_DIRECTION_OUT:
185                 l |= 1 << offset;
186                 break;
187         case MXC_GPIO_DIRECTION_IN:
188                 l &= ~(1 << offset);
189         }
190         writel(l, &regs->gpio_dir);
191 }
192
193 static void mxc_gpio_bank_set_value(struct gpio_regs *regs, int offset,
194                                     int value)
195 {
196         u32 l;
197
198         l = readl(&regs->gpio_dr);
199         if (value)
200                 l |= 1 << offset;
201         else
202                 l &= ~(1 << offset);
203         writel(l, &regs->gpio_dr);
204 }
205
206 static int mxc_gpio_bank_get_value(struct gpio_regs *regs, int offset)
207 {
208         return (readl(&regs->gpio_psr) >> offset) & 0x01;
209 }
210
211 static int mxc_gpio_bank_get_output_value(struct gpio_regs *regs, int offset)
212 {
213         return (readl(&regs->gpio_dr) >> offset) & 0x01;
214 }
215
216 static int check_requested(struct udevice *dev, unsigned offset,
217                            const char *func)
218 {
219         struct mxc_bank_info *bank = dev_get_priv(dev);
220         struct gpio_dev_priv *uc_priv = dev->uclass_priv;
221
222         if (!gpio_is_requested(bank, offset)) {
223                 printf("mxc_gpio: %s: error: gpio %s%d not requested\n",
224                        func, uc_priv->bank_name, offset);
225                 return -EPERM;
226         }
227
228         return 0;
229 }
230
231 /* set GPIO pin 'gpio' as an input */
232 static int mxc_gpio_direction_input(struct udevice *dev, unsigned offset)
233 {
234         struct mxc_bank_info *bank = dev_get_priv(dev);
235         int ret;
236
237         ret = check_requested(dev, offset, __func__);
238         if (ret)
239                 return ret;
240
241         /* Configure GPIO direction as input. */
242         mxc_gpio_bank_direction(bank->regs, offset, MXC_GPIO_DIRECTION_IN);
243
244         return 0;
245 }
246
247 /* set GPIO pin 'gpio' as an output, with polarity 'value' */
248 static int mxc_gpio_direction_output(struct udevice *dev, unsigned offset,
249                                        int value)
250 {
251         struct mxc_bank_info *bank = dev_get_priv(dev);
252         int ret;
253
254         ret = check_requested(dev, offset, __func__);
255         if (ret)
256                 return ret;
257
258         /* Configure GPIO output value. */
259         mxc_gpio_bank_set_value(bank->regs, offset, value);
260
261         /* Configure GPIO direction as output. */
262         mxc_gpio_bank_direction(bank->regs, offset, MXC_GPIO_DIRECTION_OUT);
263
264         return 0;
265 }
266
267 /* read GPIO IN value of pin 'gpio' */
268 static int mxc_gpio_get_value(struct udevice *dev, unsigned offset)
269 {
270         struct mxc_bank_info *bank = dev_get_priv(dev);
271         int ret;
272
273         ret = check_requested(dev, offset, __func__);
274         if (ret)
275                 return ret;
276
277         return mxc_gpio_bank_get_value(bank->regs, offset);
278 }
279
280 /* write GPIO OUT value to pin 'gpio' */
281 static int mxc_gpio_set_value(struct udevice *dev, unsigned offset,
282                                  int value)
283 {
284         struct mxc_bank_info *bank = dev_get_priv(dev);
285         int ret;
286
287         ret = check_requested(dev, offset, __func__);
288         if (ret)
289                 return ret;
290
291         mxc_gpio_bank_set_value(bank->regs, offset, value);
292
293         return 0;
294 }
295
296 static int mxc_gpio_get_state(struct udevice *dev, unsigned int offset,
297                               char *buf, int bufsize)
298 {
299         struct gpio_dev_priv *uc_priv = dev->uclass_priv;
300         struct mxc_bank_info *bank = dev_get_priv(dev);
301         const char *label;
302         bool requested;
303         bool is_output;
304         int size;
305
306         label = bank->label[offset];
307         is_output = mxc_gpio_is_output(bank->regs, offset);
308         size = snprintf(buf, bufsize, "%s%d: ",
309                         uc_priv->bank_name ? uc_priv->bank_name : "", offset);
310         buf += size;
311         bufsize -= size;
312         requested = gpio_is_requested(bank, offset);
313         snprintf(buf, bufsize, "%s: %d [%c]%s%s",
314                  is_output ? "out" : " in",
315                  is_output ?
316                         mxc_gpio_bank_get_output_value(bank->regs, offset) :
317                         mxc_gpio_bank_get_value(bank->regs, offset),
318                  requested ? 'x' : ' ',
319                  requested ? " " : "",
320                  label);
321
322         return 0;
323 }
324
325 static int mxc_gpio_request(struct udevice *dev, unsigned offset,
326                               const char *label)
327 {
328         struct mxc_bank_info *bank = dev_get_priv(dev);
329
330         if (gpio_is_requested(bank, offset))
331                 return -EBUSY;
332
333         strncpy(bank->label[offset], label, GPIO_NAME_SIZE);
334         bank->label[offset][GPIO_NAME_SIZE - 1] = '\0';
335
336         return 0;
337 }
338
339 static int mxc_gpio_free(struct udevice *dev, unsigned offset)
340 {
341         struct mxc_bank_info *bank = dev_get_priv(dev);
342         int ret;
343
344         ret = check_requested(dev, offset, __func__);
345         if (ret)
346                 return ret;
347         bank->label[offset][0] = '\0';
348
349         return 0;
350 }
351
352 static int mxc_gpio_get_function(struct udevice *dev, unsigned offset)
353 {
354         struct mxc_bank_info *bank = dev_get_priv(dev);
355
356         if (!gpio_is_requested(bank, offset))
357                 return GPIOF_UNUSED;
358
359         /* GPIOF_FUNC is not implemented yet */
360         if (mxc_gpio_is_output(bank->regs, offset))
361                 return GPIOF_OUTPUT;
362         else
363                 return GPIOF_INPUT;
364 }
365
366 static const struct dm_gpio_ops gpio_mxc_ops = {
367         .request                = mxc_gpio_request,
368         .free                   = mxc_gpio_free,
369         .direction_input        = mxc_gpio_direction_input,
370         .direction_output       = mxc_gpio_direction_output,
371         .get_value              = mxc_gpio_get_value,
372         .set_value              = mxc_gpio_set_value,
373         .get_function           = mxc_gpio_get_function,
374         .get_state              = mxc_gpio_get_state,
375 };
376
377 static const struct mxc_gpio_plat mxc_plat[] = {
378         { (struct gpio_regs *)GPIO1_BASE_ADDR },
379         { (struct gpio_regs *)GPIO2_BASE_ADDR },
380         { (struct gpio_regs *)GPIO3_BASE_ADDR },
381 #if defined(CONFIG_MX25) || defined(CONFIG_MX27) || defined(CONFIG_MX51) || \
382                 defined(CONFIG_MX53) || defined(CONFIG_MX6)
383         { (struct gpio_regs *)GPIO4_BASE_ADDR },
384 #endif
385 #if defined(CONFIG_MX27) || defined(CONFIG_MX53) || defined(CONFIG_MX6)
386         { (struct gpio_regs *)GPIO5_BASE_ADDR },
387         { (struct gpio_regs *)GPIO6_BASE_ADDR },
388 #endif
389 #if defined(CONFIG_MX53) || defined(CONFIG_MX6)
390         { (struct gpio_regs *)GPIO7_BASE_ADDR },
391 #endif
392 };
393
394 static int mxc_gpio_probe(struct udevice *dev)
395 {
396         struct mxc_bank_info *bank = dev_get_priv(dev);
397         struct mxc_gpio_plat *plat = dev_get_platdata(dev);
398         struct gpio_dev_priv *uc_priv = dev->uclass_priv;
399         int banknum;
400         char name[18], *str;
401
402         banknum = plat - mxc_plat;
403         sprintf(name, "GPIO%d_", banknum + 1);
404         str = strdup(name);
405         if (!str)
406                 return -ENOMEM;
407         uc_priv->bank_name = str;
408         uc_priv->gpio_count = GPIO_PER_BANK;
409         bank->regs = plat->regs;
410
411         return 0;
412 }
413
414 U_BOOT_DRIVER(gpio_mxc) = {
415         .name   = "gpio_mxc",
416         .id     = UCLASS_GPIO,
417         .ops    = &gpio_mxc_ops,
418         .probe  = mxc_gpio_probe,
419         .priv_auto_alloc_size = sizeof(struct mxc_bank_info),
420 };
421
422 U_BOOT_DEVICES(mxc_gpios) = {
423         { "gpio_mxc", &mxc_plat[0] },
424         { "gpio_mxc", &mxc_plat[1] },
425         { "gpio_mxc", &mxc_plat[2] },
426 #if defined(CONFIG_MX25) || defined(CONFIG_MX27) || defined(CONFIG_MX51) || \
427                 defined(CONFIG_MX53) || defined(CONFIG_MX6)
428         { "gpio_mxc", &mxc_plat[3] },
429 #endif
430 #if defined(CONFIG_MX27) || defined(CONFIG_MX53) || defined(CONFIG_MX6)
431         { "gpio_mxc", &mxc_plat[4] },
432         { "gpio_mxc", &mxc_plat[5] },
433 #endif
434 #if defined(CONFIG_MX53) || defined(CONFIG_MX6)
435         { "gpio_mxc", &mxc_plat[6] },
436 #endif
437 };
438 #endif