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