]> git.sur5r.net Git - u-boot/blob - drivers/gpio/lpc32xx_gpio.c
Merge git://git.denx.de/u-boot-dm
[u-boot] / drivers / gpio / lpc32xx_gpio.c
1 /*
2  * LPC32xxGPIO driver
3  *
4  * (C) Copyright 2014  DENX Software Engineering GmbH
5  * Written-by: Albert ARIBAUD <albert.aribaud@3adev.fr>
6  *
7  * SPDX-License-Identifier:     GPL-2.0+
8  */
9
10 #include <common.h>
11 #include <asm/io.h>
12 #include <asm/arch-lpc32xx/cpu.h>
13 #include <asm/arch-lpc32xx/gpio.h>
14 #include <asm-generic/gpio.h>
15 #include <dm.h>
16
17 /**
18  * LPC32xx GPIOs work in banks but are non-homogeneous:
19  * - each bank holds a different number of GPIOs
20  * - some GPIOs are input/ouput, some input only, some output only;
21  * - some GPIOs have different meanings as an input and as an output;
22  * - some GPIOs are controlled on a given port and bit index, but
23  *   read on another one.
24 *
25  * In order to keep this code simple, GPIOS are considered here as
26  * homogeneous and linear, from 0 to 159.
27  *
28  *      ** WARNING #1 **
29  *
30  * Client code is responsible for properly using valid GPIO numbers,
31  * including cases where a single physical GPIO has differing numbers
32  * for setting its direction, reading it and/or writing to it.
33  *
34  *      ** WARNING #2 **
35  *
36  * Please read NOTE in description of lpc32xx_gpio_get_function().
37  */
38
39 #define LPC32XX_GPIOS 160
40
41 struct lpc32xx_gpio_priv {
42         struct gpio_regs *regs;
43         /* GPIO FUNCTION: SEE WARNING #2 */
44         signed char function[LPC32XX_GPIOS];
45 };
46
47 /**
48  * We have 4 GPIO ports of 32 bits each
49  *
50  * Port mapping offset (32 bits each):
51  * - Port 0: 0
52  * - Port 1: 32
53  * - Port 2: 64
54  * - Port 3: GPO / GPIO (output): 96
55  * - Port 3: GPI: 128
56  */
57
58 #define MAX_GPIO 160
59
60 #define GPIO_TO_PORT(gpio) ((gpio / 32) & 7)
61 #define GPIO_TO_RANK(gpio) (gpio % 32)
62 #define GPIO_TO_MASK(gpio) (1 << (gpio % 32))
63
64 /**
65  * Configure a GPIO number 'offset' as input
66  */
67
68 static int lpc32xx_gpio_direction_input(struct udevice *dev, unsigned offset)
69 {
70         int port, mask;
71         struct lpc32xx_gpio_priv *gpio_priv = dev_get_priv(dev);
72         struct gpio_regs *regs = gpio_priv->regs;
73
74         port = GPIO_TO_PORT(offset);
75         mask = GPIO_TO_MASK(offset);
76
77         switch (port) {
78         case 0:
79                 writel(mask, &regs->p0_dir_clr);
80                 break;
81         case 1:
82                 writel(mask, &regs->p1_dir_clr);
83                 break;
84         case 2:
85                 /* ports 2 and 3 share a common direction */
86                 writel(mask, &regs->p2_p3_dir_clr);
87                 break;
88         case 3:
89                 /* Setup direction only for GPIO_xx. */
90                 if ((mask >= 25) && (mask <= 30))
91                         writel(mask, &regs->p2_p3_dir_clr);
92                 break;
93         case 4:
94                 /* GPI_xx; nothing to do. */
95                 break;
96         default:
97                 return -1;
98         }
99
100         /* GPIO FUNCTION: SEE WARNING #2 */
101         gpio_priv->function[offset] = GPIOF_INPUT;
102
103         return 0;
104 }
105
106 /**
107  * Get the value of a GPIO
108  */
109
110 static int lpc32xx_gpio_get_value(struct udevice *dev, unsigned offset)
111 {
112         int port, rank, mask, value;
113         struct lpc32xx_gpio_priv *gpio_priv = dev_get_priv(dev);
114         struct gpio_regs *regs = gpio_priv->regs;
115
116         port = GPIO_TO_PORT(offset);
117
118         switch (port) {
119         case 0:
120                 value = readl(&regs->p0_inp_state);
121                 break;
122         case 1:
123                 value = readl(&regs->p1_inp_state);
124                 break;
125         case 2:
126                 value = readl(&regs->p2_inp_state);
127                 break;
128         case 3:
129                 /* Read GPO_xx and GPIO_xx (as output) using p3_outp_state. */
130                 value = readl(&regs->p3_outp_state);
131                 break;
132         case 4:
133                 /* Read GPI_xx and GPIO_xx (as input) using p3_inp_state. */
134                 value = readl(&regs->p3_inp_state);
135                 break;
136         default:
137                 return -1;
138         }
139
140         rank = GPIO_TO_RANK(offset);
141         mask = GPIO_TO_MASK(offset);
142
143         return (value & mask) >> rank;
144 }
145
146 /**
147  * Set a GPIO
148  */
149
150 static int gpio_set(struct udevice *dev, unsigned gpio)
151 {
152         int port, mask;
153         struct lpc32xx_gpio_priv *gpio_priv = dev_get_priv(dev);
154         struct gpio_regs *regs = gpio_priv->regs;
155
156         port = GPIO_TO_PORT(gpio);
157         mask = GPIO_TO_MASK(gpio);
158
159         switch (port) {
160         case 0:
161                 writel(mask, &regs->p0_outp_set);
162                 break;
163         case 1:
164                 writel(mask, &regs->p1_outp_set);
165                 break;
166         case 2:
167                 writel(mask, &regs->p2_outp_set);
168                 break;
169         case 3:
170                 writel(mask, &regs->p3_outp_set);
171                 break;
172         case 4:
173                 /* GPI_xx; invalid. */
174         default:
175                 return -1;
176         }
177         return 0;
178 }
179
180 /**
181  * Clear a GPIO
182  */
183
184 static int gpio_clr(struct udevice *dev, unsigned gpio)
185 {
186         int port, mask;
187         struct lpc32xx_gpio_priv *gpio_priv = dev_get_priv(dev);
188         struct gpio_regs *regs = gpio_priv->regs;
189
190         port = GPIO_TO_PORT(gpio);
191         mask = GPIO_TO_MASK(gpio);
192
193         switch (port) {
194         case 0:
195                 writel(mask, &regs->p0_outp_clr);
196                 break;
197         case 1:
198                 writel(mask, &regs->p1_outp_clr);
199                 break;
200         case 2:
201                 writel(mask, &regs->p2_outp_clr);
202                 break;
203         case 3:
204                 writel(mask, &regs->p3_outp_clr);
205                 break;
206         case 4:
207                 /* GPI_xx; invalid. */
208         default:
209                 return -1;
210         }
211         return 0;
212 }
213
214 /**
215  * Set the value of a GPIO
216  */
217
218 static int lpc32xx_gpio_set_value(struct udevice *dev, unsigned offset,
219                                  int value)
220 {
221         if (value)
222                 return gpio_set(dev, offset);
223         else
224                 return gpio_clr(dev, offset);
225 }
226
227 /**
228  * Configure a GPIO number 'offset' as output with given initial value.
229  */
230
231 static int lpc32xx_gpio_direction_output(struct udevice *dev, unsigned offset,
232                                        int value)
233 {
234         int port, mask;
235         struct lpc32xx_gpio_priv *gpio_priv = dev_get_priv(dev);
236         struct gpio_regs *regs = gpio_priv->regs;
237
238         port = GPIO_TO_PORT(offset);
239         mask = GPIO_TO_MASK(offset);
240
241         switch (port) {
242         case 0:
243                 writel(mask, &regs->p0_dir_set);
244                 break;
245         case 1:
246                 writel(mask, &regs->p1_dir_set);
247                 break;
248         case 2:
249                 /* ports 2 and 3 share a common direction */
250                 writel(mask, &regs->p2_p3_dir_set);
251                 break;
252         case 3:
253                 /* Setup direction only for GPIO_xx. */
254                 if ((mask >= 25) && (mask <= 30))
255                         writel(mask, &regs->p2_p3_dir_set);
256                 break;
257         case 4:
258                 /* GPI_xx; invalid. */
259         default:
260                 return -1;
261         }
262
263         /* GPIO FUNCTION: SEE WARNING #2 */
264         gpio_priv->function[offset] = GPIOF_OUTPUT;
265
266         return lpc32xx_gpio_set_value(dev, offset, value);
267 }
268
269 /**
270  * GPIO functions are supposed to be computed from their current
271  * configuration, but that's way too complicated in LPC32XX. A simpler
272  * approach is used, where the GPIO functions are cached in an array.
273  * When the GPIO is in use, its function is either "input" or "output"
274  * depending on its direction, otherwise its function is "unknown".
275  *
276  *      ** NOTE **
277  *
278  * THIS APPROACH WAS CHOSEN DU TO THE COMPLEX NATURE OF THE LPC32XX
279  * GPIOS; DO NOT TAKE THIS AS AN EXAMPLE FOR NEW CODE.
280  */
281
282 static int lpc32xx_gpio_get_function(struct udevice *dev, unsigned offset)
283 {
284         struct lpc32xx_gpio_priv *gpio_priv = dev_get_priv(dev);
285         return gpio_priv->function[offset];
286 }
287
288 static const struct dm_gpio_ops gpio_lpc32xx_ops = {
289         .direction_input        = lpc32xx_gpio_direction_input,
290         .direction_output       = lpc32xx_gpio_direction_output,
291         .get_value              = lpc32xx_gpio_get_value,
292         .set_value              = lpc32xx_gpio_set_value,
293         .get_function           = lpc32xx_gpio_get_function,
294 };
295
296 static int lpc32xx_gpio_probe(struct udevice *dev)
297 {
298         struct lpc32xx_gpio_priv *gpio_priv = dev_get_priv(dev);
299         struct gpio_dev_priv *uc_priv = dev->uclass_priv;
300
301         if (dev_of_offset(dev) == -1) {
302                 /* Tell the uclass how many GPIOs we have */
303                 uc_priv->gpio_count = LPC32XX_GPIOS;
304         }
305
306         /* set base address for GPIO registers */
307         gpio_priv->regs = (struct gpio_regs *)GPIO_BASE;
308
309         /* all GPIO functions are unknown until requested */
310         /* GPIO FUNCTION: SEE WARNING #2 */
311         memset(gpio_priv->function, GPIOF_UNKNOWN, sizeof(gpio_priv->function));
312
313         return 0;
314 }
315
316 U_BOOT_DRIVER(gpio_lpc32xx) = {
317         .name   = "gpio_lpc32xx",
318         .id     = UCLASS_GPIO,
319         .ops    = &gpio_lpc32xx_ops,
320         .probe  = lpc32xx_gpio_probe,
321         .priv_auto_alloc_size = sizeof(struct lpc32xx_gpio_priv),
322 };