]> git.karo-electronics.de Git - karo-tx-uboot.git/blob - drivers/gpio/mxc_gpio.c
upgrade to upstream version 2013.07
[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 <asm/arch/imx-regs.h>
12 #include <asm/gpio.h>
13 #include <asm/io.h>
14 #include <errno.h>
15
16 enum mxc_gpio_direction {
17         MXC_GPIO_DIRECTION_IN,
18         MXC_GPIO_DIRECTION_OUT,
19 };
20
21 #define GPIO_TO_PORT(n)         ((n) / 32)
22
23 /* GPIO port description */
24 static unsigned long gpio_ports[] = {
25         [0] = GPIO1_BASE_ADDR,
26         [1] = GPIO2_BASE_ADDR,
27         [2] = GPIO3_BASE_ADDR,
28 #if defined(CONFIG_MX25) || defined(CONFIG_MX27) || defined(CONFIG_MX51) || \
29                 defined(CONFIG_MX53) || defined(CONFIG_MX6)
30         [3] = GPIO4_BASE_ADDR,
31 #endif
32 #if defined(CONFIG_MX27) || defined(CONFIG_MX53) || defined(CONFIG_MX6)
33         [4] = GPIO5_BASE_ADDR,
34         [5] = GPIO6_BASE_ADDR,
35 #endif
36 #if defined(CONFIG_MX53) || defined(CONFIG_MX6)
37         [6] = GPIO7_BASE_ADDR,
38 #endif
39 };
40
41 static int mxc_gpio_direction(unsigned int gpio,
42         enum mxc_gpio_direction direction)
43 {
44         unsigned int port = GPIO_TO_PORT(gpio);
45         struct gpio_regs *regs;
46         u32 l;
47
48         if (port >= ARRAY_SIZE(gpio_ports)) {
49                 printf("%s: Invalid GPIO %d\n", __func__, gpio);
50                 return -1;
51         }
52
53         gpio &= 0x1f;
54
55         regs = (struct gpio_regs *)gpio_ports[port];
56
57         l = readl(&regs->gpio_dir);
58
59         switch (direction) {
60         case MXC_GPIO_DIRECTION_OUT:
61                 l |= 1 << gpio;
62                 break;
63         case MXC_GPIO_DIRECTION_IN:
64                 l &= ~(1 << gpio);
65         }
66         writel(l, &regs->gpio_dir);
67
68         return 0;
69 }
70
71 int gpio_set_value(unsigned gpio, int value)
72 {
73         unsigned int port = GPIO_TO_PORT(gpio);
74         struct gpio_regs *regs;
75         u32 l;
76
77         if (port >= ARRAY_SIZE(gpio_ports)) {
78                 printf("%s: Invalid GPIO %d\n", __func__, gpio);
79                 return -1;
80         }
81
82         gpio &= 0x1f;
83
84         regs = (struct gpio_regs *)gpio_ports[port];
85
86         l = readl(&regs->gpio_dr);
87         if (value)
88                 l |= 1 << gpio;
89         else
90                 l &= ~(1 << gpio);
91         writel(l, &regs->gpio_dr);
92
93         return 0;
94 }
95
96 int gpio_get_value(unsigned gpio)
97 {
98         unsigned int port = GPIO_TO_PORT(gpio);
99         struct gpio_regs *regs;
100         u32 val;
101
102         if (port >= ARRAY_SIZE(gpio_ports)) {
103                 printf("%s: Invalid GPIO %d\n", __func__, gpio);
104                 return -1;
105         }
106
107         gpio &= 0x1f;
108
109         regs = (struct gpio_regs *)gpio_ports[port];
110
111         if (readl(&regs->gpio_dir) & (1 << gpio)) {
112                 printf("WARNING: Reading status of output GPIO_%d_%d\n",
113                         port - GPIO_TO_PORT(0), gpio);
114                 val = (readl(&regs->gpio_dr) >> gpio) & 0x01;
115         } else {
116                 val = (readl(&regs->gpio_psr) >> gpio) & 0x01;
117         }
118         return val;
119 }
120
121 int gpio_request(unsigned gpio, const char *label)
122 {
123         unsigned int port = GPIO_TO_PORT(gpio);
124         if (port >= ARRAY_SIZE(gpio_ports)) {
125                 printf("%s: Invalid GPIO %d\n", __func__, gpio);
126                 return -1;
127         }
128         return 0;
129 }
130
131 int gpio_free(unsigned gpio)
132 {
133         unsigned int port = GPIO_TO_PORT(gpio);
134         if (port >= ARRAY_SIZE(gpio_ports)) {
135                 printf("%s: Invalid GPIO %d\n", __func__, gpio);
136                 return -1;
137         }
138         return 0;
139 }
140
141 int gpio_direction_input(unsigned gpio)
142 {
143         return mxc_gpio_direction(gpio, MXC_GPIO_DIRECTION_IN);
144 }
145
146 int gpio_direction_output(unsigned gpio, int value)
147 {
148         int ret = gpio_set_value(gpio, value);
149
150         if (ret < 0)
151                 return ret;
152
153         return mxc_gpio_direction(gpio, MXC_GPIO_DIRECTION_OUT);
154 }