]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - drivers/gpio/mxc_gpio.c
23568d56ba3821a6e3457eaa07efd2d992d9876e
[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         int bank_index;
27         struct gpio_regs *regs;
28 };
29
30 struct mxc_bank_info {
31         struct gpio_regs *regs;
32 };
33
34 #ifndef CONFIG_DM_GPIO
35 #define GPIO_TO_PORT(n)         ((n) / 32)
36
37 /* GPIO port description */
38 static unsigned long gpio_ports[] = {
39         [0] = GPIO1_BASE_ADDR,
40         [1] = GPIO2_BASE_ADDR,
41         [2] = GPIO3_BASE_ADDR,
42 #if defined(CONFIG_SOC_MX25) || defined(CONFIG_SOC_MX27) || defined(CONFIG_SOC_MX51) || \
43                 defined(CONFIG_SOC_MX53) || defined(CONFIG_SOC_MX6)
44         [3] = GPIO4_BASE_ADDR,
45 #endif
46 #if defined(CONFIG_SOC_MX27) || defined(CONFIG_SOC_MX53) || defined(CONFIG_SOC_MX6)
47         [4] = GPIO5_BASE_ADDR,
48 #ifndef CONFIG_SOX_MX6UL
49         [5] = GPIO6_BASE_ADDR,
50 #endif
51 #endif
52 #if defined(CONFIG_SOC_MX53) || defined(CONFIG_SOC_MX6)
53 #ifndef CONFIG_SOC_MX6UL
54         [6] = GPIO7_BASE_ADDR,
55 #endif
56 #endif
57 };
58
59 static int mxc_gpio_direction(unsigned int gpio,
60         enum mxc_gpio_direction direction)
61 {
62         unsigned int port = GPIO_TO_PORT(gpio);
63         struct gpio_regs *regs;
64         u32 l;
65
66         if (port >= ARRAY_SIZE(gpio_ports)) {
67                 printf("%s: Invalid GPIO %d\n", __func__, gpio);
68                 return -1;
69         }
70
71         gpio &= 0x1f;
72
73         regs = (struct gpio_regs *)gpio_ports[port];
74
75         l = readl(&regs->gpio_dir);
76
77         switch (direction) {
78         case MXC_GPIO_DIRECTION_OUT:
79                 l |= 1 << gpio;
80                 break;
81         case MXC_GPIO_DIRECTION_IN:
82                 l &= ~(1 << gpio);
83         }
84         writel(l, &regs->gpio_dir);
85
86         return 0;
87 }
88
89 int gpio_set_value(unsigned gpio, int value)
90 {
91         unsigned int port = GPIO_TO_PORT(gpio);
92         struct gpio_regs *regs;
93         u32 l;
94
95         if (port >= ARRAY_SIZE(gpio_ports)) {
96                 printf("%s: Invalid GPIO %d\n", __func__, gpio);
97                 return -1;
98         }
99
100         gpio &= 0x1f;
101
102         regs = (struct gpio_regs *)gpio_ports[port];
103
104         l = readl(&regs->gpio_dr);
105         if (value)
106                 l |= 1 << gpio;
107         else
108                 l &= ~(1 << gpio);
109         writel(l, &regs->gpio_dr);
110
111         return 0;
112 }
113
114 int gpio_get_value(unsigned gpio)
115 {
116         unsigned int port = GPIO_TO_PORT(gpio);
117         struct gpio_regs *regs;
118         u32 val;
119
120         if (port >= ARRAY_SIZE(gpio_ports)) {
121                 printf("%s: Invalid GPIO %d\n", __func__, gpio);
122                 return -1;
123         }
124
125         gpio &= 0x1f;
126
127         regs = (struct gpio_regs *)gpio_ports[port];
128
129         if (readl(&regs->gpio_dir) & (1 << gpio)) {
130                 printf("WARNING: Reading status of output GPIO_%d_%d\n",
131                         port - GPIO_TO_PORT(0), gpio);
132                 val = (readl(&regs->gpio_dr) >> gpio) & 0x01;
133         } else {
134                 val = (readl(&regs->gpio_psr) >> gpio) & 0x01;
135         }
136         return val;
137 }
138
139 int gpio_request(unsigned gpio, const char *label)
140 {
141         unsigned int port = GPIO_TO_PORT(gpio);
142         if (port >= ARRAY_SIZE(gpio_ports)) {
143                 printf("%s: Invalid GPIO %d\n", __func__, gpio);
144                 return -1;
145         }
146         return 0;
147 }
148
149 int gpio_free(unsigned gpio)
150 {
151         unsigned int port = GPIO_TO_PORT(gpio);
152         if (port >= ARRAY_SIZE(gpio_ports)) {
153                 printf("%s: Invalid GPIO %d\n", __func__, gpio);
154                 return -1;
155         }
156         return 0;
157 }
158
159 int gpio_direction_input(unsigned gpio)
160 {
161         return mxc_gpio_direction(gpio, MXC_GPIO_DIRECTION_IN);
162 }
163
164 int gpio_direction_output(unsigned gpio, int value)
165 {
166         int ret = gpio_set_value(gpio, value);
167
168         if (ret < 0)
169                 return ret;
170
171         return mxc_gpio_direction(gpio, MXC_GPIO_DIRECTION_OUT);
172 }
173 #endif
174
175 #ifdef CONFIG_DM_GPIO
176 #include <fdtdec.h>
177 DECLARE_GLOBAL_DATA_PTR;
178
179 static int mxc_gpio_is_output(struct gpio_regs *regs, int offset)
180 {
181         u32 val;
182
183         val = readl(&regs->gpio_dir);
184
185         return val & (1 << offset) ? 1 : 0;
186 }
187
188 static void mxc_gpio_bank_direction(struct gpio_regs *regs, int offset,
189                                     enum mxc_gpio_direction direction)
190 {
191         u32 l;
192
193         l = readl(&regs->gpio_dir);
194
195         switch (direction) {
196         case MXC_GPIO_DIRECTION_OUT:
197                 l |= 1 << offset;
198                 break;
199         case MXC_GPIO_DIRECTION_IN:
200                 l &= ~(1 << offset);
201         }
202         writel(l, &regs->gpio_dir);
203 }
204
205 static void mxc_gpio_bank_set_value(struct gpio_regs *regs, int offset,
206                                     int value)
207 {
208         u32 l;
209
210         l = readl(&regs->gpio_dr);
211         if (value)
212                 l |= 1 << offset;
213         else
214                 l &= ~(1 << offset);
215         writel(l, &regs->gpio_dr);
216 }
217
218 static int mxc_gpio_bank_get_value(struct gpio_regs *regs, int offset)
219 {
220         return (readl(&regs->gpio_psr) >> offset) & 0x01;
221 }
222
223 /* set GPIO pin 'gpio' as an input */
224 static int mxc_gpio_direction_input(struct udevice *dev, unsigned offset)
225 {
226         struct mxc_bank_info *bank = dev_get_priv(dev);
227
228         /* Configure GPIO direction as input. */
229         mxc_gpio_bank_direction(bank->regs, offset, MXC_GPIO_DIRECTION_IN);
230
231         return 0;
232 }
233
234 /* set GPIO pin 'gpio' as an output, with polarity 'value' */
235 static int mxc_gpio_direction_output(struct udevice *dev, unsigned offset,
236                                        int value)
237 {
238         struct mxc_bank_info *bank = dev_get_priv(dev);
239
240         /* Configure GPIO output value. */
241         mxc_gpio_bank_set_value(bank->regs, offset, value);
242
243         /* Configure GPIO direction as output. */
244         mxc_gpio_bank_direction(bank->regs, offset, MXC_GPIO_DIRECTION_OUT);
245
246         return 0;
247 }
248
249 /* read GPIO IN value of pin 'gpio' */
250 static int mxc_gpio_get_value(struct udevice *dev, unsigned offset)
251 {
252         struct mxc_bank_info *bank = dev_get_priv(dev);
253
254         return mxc_gpio_bank_get_value(bank->regs, offset);
255 }
256
257 /* write GPIO OUT value to pin 'gpio' */
258 static int mxc_gpio_set_value(struct udevice *dev, unsigned offset,
259                                  int value)
260 {
261         struct mxc_bank_info *bank = dev_get_priv(dev);
262
263         mxc_gpio_bank_set_value(bank->regs, offset, value);
264
265         return 0;
266 }
267
268 static int mxc_gpio_get_function(struct udevice *dev, unsigned offset)
269 {
270         struct mxc_bank_info *bank = dev_get_priv(dev);
271
272         /* GPIOF_FUNC is not implemented yet */
273         if (mxc_gpio_is_output(bank->regs, offset))
274                 return GPIOF_OUTPUT;
275         else
276                 return GPIOF_INPUT;
277 }
278
279 static const struct dm_gpio_ops gpio_mxc_ops = {
280         .direction_input        = mxc_gpio_direction_input,
281         .direction_output       = mxc_gpio_direction_output,
282         .get_value              = mxc_gpio_get_value,
283         .set_value              = mxc_gpio_set_value,
284         .get_function           = mxc_gpio_get_function,
285 };
286
287 static int mxc_gpio_probe(struct udevice *dev)
288 {
289         struct mxc_bank_info *bank = dev_get_priv(dev);
290         struct mxc_gpio_plat *plat = dev_get_platdata(dev);
291         struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
292         int banknum;
293         char name[18], *str;
294
295         banknum = plat->bank_index;
296         sprintf(name, "GPIO%d_", banknum + 1);
297         str = strdup(name);
298         if (!str)
299                 return -ENOMEM;
300         uc_priv->bank_name = str;
301         uc_priv->gpio_count = GPIO_PER_BANK;
302         bank->regs = plat->regs;
303
304         return 0;
305 }
306
307 static int mxc_gpio_bind(struct udevice *dev)
308 {
309         struct mxc_gpio_plat *plat = dev->platdata;
310         fdt_addr_t addr;
311
312         /*
313          * If platdata already exsits, directly return.
314          * Actually only when DT is not supported, platdata
315          * is statically initialized in U_BOOT_DEVICES.Here
316          * will return.
317          */
318         if (plat)
319                 return 0;
320
321         addr = dev_get_addr(dev);
322         if (addr == FDT_ADDR_T_NONE)
323                 return -ENODEV;
324
325         /*
326          * TODO:
327          * When every board is converted to driver model and DT is supported,
328          * this can be done by auto-alloc feature, but not using calloc
329          * to alloc memory for platdata.
330          */
331         plat = calloc(1, sizeof(*plat));
332         if (!plat)
333                 return -ENOMEM;
334
335         plat->regs = (struct gpio_regs *)addr;
336         plat->bank_index = dev->req_seq;
337         dev->platdata = plat;
338
339         return 0;
340 }
341
342 static const struct udevice_id mxc_gpio_ids[] = {
343         { .compatible = "fsl,imx35-gpio" },
344         { }
345 };
346
347 U_BOOT_DRIVER(gpio_mxc) = {
348         .name   = "gpio_mxc",
349         .id     = UCLASS_GPIO,
350         .ops    = &gpio_mxc_ops,
351         .probe  = mxc_gpio_probe,
352         .priv_auto_alloc_size = sizeof(struct mxc_bank_info),
353         .of_match = mxc_gpio_ids,
354         .bind   = mxc_gpio_bind,
355 };
356
357 #if !CONFIG_IS_ENABLED(OF_CONTROL)
358 static const struct mxc_gpio_plat mxc_plat[] = {
359         { 0, (struct gpio_regs *)GPIO1_BASE_ADDR },
360         { 1, (struct gpio_regs *)GPIO2_BASE_ADDR },
361         { 2, (struct gpio_regs *)GPIO3_BASE_ADDR },
362 #if defined(CONFIG_SOC_MX25) || defined(CONFIG_SOC_MX27) || defined(CONFIG_SOC_MX51) || \
363                 defined(CONFIG_SOC_MX53) || defined(CONFIG_SOC_MX6)
364         { 3, (struct gpio_regs *)GPIO4_BASE_ADDR },
365 #endif
366 #if defined(CONFIG_SOC_MX27) || defined(CONFIG_SOC_MX53) || defined(CONFIG_SOC_MX6)
367         { 4, (struct gpio_regs *)GPIO5_BASE_ADDR },
368         { 5, (struct gpio_regs *)GPIO6_BASE_ADDR },
369 #endif
370 #if defined(CONFIG_SOC_MX53) || defined(CONFIG_SOC_MX6)
371         { 6, (struct gpio_regs *)GPIO7_BASE_ADDR },
372 #endif
373 };
374
375 U_BOOT_DEVICES(mxc_gpios) = {
376         { "gpio_mxc", &mxc_plat[0] },
377         { "gpio_mxc", &mxc_plat[1] },
378         { "gpio_mxc", &mxc_plat[2] },
379 #if defined(CONFIG_SOC_MX25) || defined(CONFIG_SOC_MX27) || defined(CONFIG_SOC_MX51) || \
380                 defined(CONFIG_SOC_MX53) || defined(CONFIG_SOC_MX6)
381         { "gpio_mxc", &mxc_plat[3] },
382 #endif
383 #if defined(CONFIG_SOC_MX27) || defined(CONFIG_SOC_MX53) || defined(CONFIG_SOC_MX6)
384         { "gpio_mxc", &mxc_plat[4] },
385         { "gpio_mxc", &mxc_plat[5] },
386 #endif
387 #if defined(CONFIG_SOC_MX53) || defined(CONFIG_SOC_MX6)
388         { "gpio_mxc", &mxc_plat[6] },
389 #endif
390 };
391 #endif
392 #endif