]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - drivers/gpio/mxc_gpio.c
karo: merge with Ka-Ro specific tree for secure boot support
[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_PER_BANK                   32
24
25 struct mxc_gpio_plat {
26         struct gpio_regs *regs;
27 };
28
29 struct mxc_bank_info {
30         struct gpio_regs *regs;
31 };
32
33 #ifndef CONFIG_DM_GPIO
34 #define GPIO_TO_PORT(n)         ((n) / 32)
35
36 /* GPIO port description */
37 static unsigned long gpio_ports[] = {
38         [0] = GPIO1_BASE_ADDR,
39         [1] = GPIO2_BASE_ADDR,
40         [2] = GPIO3_BASE_ADDR,
41 #if defined(CONFIG_MX25) || defined(CONFIG_MX27) || defined(CONFIG_MX51) || \
42                 defined(CONFIG_MX53) || defined(CONFIG_MX6)
43         [3] = GPIO4_BASE_ADDR,
44 #endif
45 #if defined(CONFIG_MX27) || defined(CONFIG_MX53) || defined(CONFIG_MX6)
46         [4] = GPIO5_BASE_ADDR,
47         [5] = GPIO6_BASE_ADDR,
48 #endif
49 #if defined(CONFIG_MX53) || defined(CONFIG_MX6)
50         [6] = GPIO7_BASE_ADDR,
51 #endif
52 };
53
54 static int mxc_gpio_direction(unsigned int gpio,
55         enum mxc_gpio_direction direction)
56 {
57         unsigned int port = GPIO_TO_PORT(gpio);
58         struct gpio_regs *regs;
59         u32 l;
60
61         if (port >= ARRAY_SIZE(gpio_ports)) {
62                 printf("%s: Invalid GPIO %d\n", __func__, gpio);
63                 return -1;
64         }
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                 printf("%s: Invalid GPIO %d\n", __func__, gpio);
92                 return -1;
93         }
94
95         gpio &= 0x1f;
96
97         regs = (struct gpio_regs *)gpio_ports[port];
98
99         l = readl(&regs->gpio_dr);
100         if (value)
101                 l |= 1 << gpio;
102         else
103                 l &= ~(1 << gpio);
104         writel(l, &regs->gpio_dr);
105
106         return 0;
107 }
108
109 int gpio_get_value(unsigned gpio)
110 {
111         unsigned int port = GPIO_TO_PORT(gpio);
112         struct gpio_regs *regs;
113         u32 val;
114
115         if (port >= ARRAY_SIZE(gpio_ports)) {
116                 printf("%s: Invalid GPIO %d\n", __func__, gpio);
117                 return -1;
118         }
119
120         gpio &= 0x1f;
121
122         regs = (struct gpio_regs *)gpio_ports[port];
123
124         if (readl(&regs->gpio_dir) & (1 << gpio)) {
125                 printf("WARNING: Reading status of output GPIO_%d_%d\n",
126                         port - GPIO_TO_PORT(0), gpio);
127                 val = (readl(&regs->gpio_dr) >> gpio) & 0x01;
128         } else {
129                 val = (readl(&regs->gpio_psr) >> gpio) & 0x01;
130         }
131         return val;
132 }
133
134 int gpio_request(unsigned gpio, const char *label)
135 {
136         unsigned int port = GPIO_TO_PORT(gpio);
137         if (port >= ARRAY_SIZE(gpio_ports)) {
138                 printf("%s: Invalid GPIO %d\n", __func__, gpio);
139                 return -1;
140         }
141         return 0;
142 }
143
144 int gpio_free(unsigned gpio)
145 {
146         unsigned int port = GPIO_TO_PORT(gpio);
147         if (port >= ARRAY_SIZE(gpio_ports)) {
148                 printf("%s: Invalid GPIO %d\n", __func__, gpio);
149                 return -1;
150         }
151         return 0;
152 }
153
154 int gpio_direction_input(unsigned gpio)
155 {
156         return mxc_gpio_direction(gpio, MXC_GPIO_DIRECTION_IN);
157 }
158
159 int gpio_direction_output(unsigned gpio, int value)
160 {
161         int ret = gpio_set_value(gpio, value);
162
163         if (ret < 0)
164                 return ret;
165
166         return mxc_gpio_direction(gpio, MXC_GPIO_DIRECTION_OUT);
167 }
168 #endif
169
170 #ifdef CONFIG_DM_GPIO
171 static int mxc_gpio_is_output(struct gpio_regs *regs, int offset)
172 {
173         u32 val;
174
175         val = readl(&regs->gpio_dir);
176
177         return val & (1 << offset) ? 1 : 0;
178 }
179
180 static void mxc_gpio_bank_direction(struct gpio_regs *regs, int offset,
181                                     enum mxc_gpio_direction direction)
182 {
183         u32 l;
184
185         l = readl(&regs->gpio_dir);
186
187         switch (direction) {
188         case MXC_GPIO_DIRECTION_OUT:
189                 l |= 1 << offset;
190                 break;
191         case MXC_GPIO_DIRECTION_IN:
192                 l &= ~(1 << offset);
193         }
194         writel(l, &regs->gpio_dir);
195 }
196
197 static void mxc_gpio_bank_set_value(struct gpio_regs *regs, int offset,
198                                     int value)
199 {
200         u32 l;
201
202         l = readl(&regs->gpio_dr);
203         if (value)
204                 l |= 1 << offset;
205         else
206                 l &= ~(1 << offset);
207         writel(l, &regs->gpio_dr);
208 }
209
210 static int mxc_gpio_bank_get_value(struct gpio_regs *regs, int offset)
211 {
212         return (readl(&regs->gpio_psr) >> offset) & 0x01;
213 }
214
215 /* set GPIO pin 'gpio' as an input */
216 static int mxc_gpio_direction_input(struct udevice *dev, unsigned offset)
217 {
218         struct mxc_bank_info *bank = dev_get_priv(dev);
219
220         /* Configure GPIO direction as input. */
221         mxc_gpio_bank_direction(bank->regs, offset, MXC_GPIO_DIRECTION_IN);
222
223         return 0;
224 }
225
226 /* set GPIO pin 'gpio' as an output, with polarity 'value' */
227 static int mxc_gpio_direction_output(struct udevice *dev, unsigned offset,
228                                        int value)
229 {
230         struct mxc_bank_info *bank = dev_get_priv(dev);
231
232         /* Configure GPIO output value. */
233         mxc_gpio_bank_set_value(bank->regs, offset, value);
234
235         /* Configure GPIO direction as output. */
236         mxc_gpio_bank_direction(bank->regs, offset, MXC_GPIO_DIRECTION_OUT);
237
238         return 0;
239 }
240
241 /* read GPIO IN value of pin 'gpio' */
242 static int mxc_gpio_get_value(struct udevice *dev, unsigned offset)
243 {
244         struct mxc_bank_info *bank = dev_get_priv(dev);
245
246         return mxc_gpio_bank_get_value(bank->regs, offset);
247 }
248
249 /* write GPIO OUT value to pin 'gpio' */
250 static int mxc_gpio_set_value(struct udevice *dev, unsigned offset,
251                                  int value)
252 {
253         struct mxc_bank_info *bank = dev_get_priv(dev);
254
255         mxc_gpio_bank_set_value(bank->regs, offset, value);
256
257         return 0;
258 }
259
260 static int mxc_gpio_get_function(struct udevice *dev, unsigned offset)
261 {
262         struct mxc_bank_info *bank = dev_get_priv(dev);
263
264         /* GPIOF_FUNC is not implemented yet */
265         if (mxc_gpio_is_output(bank->regs, offset))
266                 return GPIOF_OUTPUT;
267         else
268                 return GPIOF_INPUT;
269 }
270
271 static const struct dm_gpio_ops gpio_mxc_ops = {
272         .direction_input        = mxc_gpio_direction_input,
273         .direction_output       = mxc_gpio_direction_output,
274         .get_value              = mxc_gpio_get_value,
275         .set_value              = mxc_gpio_set_value,
276         .get_function           = mxc_gpio_get_function,
277 };
278
279 static const struct mxc_gpio_plat mxc_plat[] = {
280         { (struct gpio_regs *)GPIO1_BASE_ADDR },
281         { (struct gpio_regs *)GPIO2_BASE_ADDR },
282         { (struct gpio_regs *)GPIO3_BASE_ADDR },
283 #if defined(CONFIG_MX25) || defined(CONFIG_MX27) || defined(CONFIG_MX51) || \
284                 defined(CONFIG_MX53) || defined(CONFIG_MX6)
285         { (struct gpio_regs *)GPIO4_BASE_ADDR },
286 #endif
287 #if defined(CONFIG_MX27) || defined(CONFIG_MX53) || defined(CONFIG_MX6)
288         { (struct gpio_regs *)GPIO5_BASE_ADDR },
289         { (struct gpio_regs *)GPIO6_BASE_ADDR },
290 #endif
291 #if defined(CONFIG_MX53) || defined(CONFIG_MX6)
292         { (struct gpio_regs *)GPIO7_BASE_ADDR },
293 #endif
294 };
295
296 static int mxc_gpio_probe(struct udevice *dev)
297 {
298         struct mxc_bank_info *bank = dev_get_priv(dev);
299         struct mxc_gpio_plat *plat = dev_get_platdata(dev);
300         struct gpio_dev_priv *uc_priv = dev->uclass_priv;
301         int banknum;
302         char name[18], *str;
303
304         banknum = plat - mxc_plat;
305         sprintf(name, "GPIO%d_", banknum + 1);
306         str = strdup(name);
307         if (!str)
308                 return -ENOMEM;
309         uc_priv->bank_name = str;
310         uc_priv->gpio_count = GPIO_PER_BANK;
311         bank->regs = plat->regs;
312
313         return 0;
314 }
315
316 U_BOOT_DRIVER(gpio_mxc) = {
317         .name   = "gpio_mxc",
318         .id     = UCLASS_GPIO,
319         .ops    = &gpio_mxc_ops,
320         .probe  = mxc_gpio_probe,
321         .priv_auto_alloc_size = sizeof(struct mxc_bank_info),
322 };
323
324 U_BOOT_DEVICES(mxc_gpios) = {
325         { "gpio_mxc", &mxc_plat[0] },
326         { "gpio_mxc", &mxc_plat[1] },
327         { "gpio_mxc", &mxc_plat[2] },
328 #if defined(CONFIG_MX25) || defined(CONFIG_MX27) || defined(CONFIG_MX51) || \
329                 defined(CONFIG_MX53) || defined(CONFIG_MX6)
330         { "gpio_mxc", &mxc_plat[3] },
331 #endif
332 #if defined(CONFIG_MX27) || defined(CONFIG_MX53) || defined(CONFIG_MX6)
333         { "gpio_mxc", &mxc_plat[4] },
334         { "gpio_mxc", &mxc_plat[5] },
335 #endif
336 #if defined(CONFIG_MX53) || defined(CONFIG_MX6)
337         { "gpio_mxc", &mxc_plat[6] },
338 #endif
339 };
340 #endif