]> git.karo-electronics.de Git - karo-tx-redboot.git/blob - packages/hal/arm/mx27/var/v2_0/src/gpio_mux.c
Initial revision
[karo-tx-redboot.git] / packages / hal / arm / mx27 / var / v2_0 / src / gpio_mux.c
1 /*
2  * Copyright 2006 Freescale Semiconductor, Inc. All Rights Reserved.
3  */
4
5 /*
6  * The code contained herein is licensed under the GNU General Public
7  * License. You may obtain a copy of the GNU General Public License
8  * Version 2 or later at the following locations:
9  *
10  * http://www.opensource.org/licenses/gpl-license.html
11  * http://www.gnu.org/copyleft/gpl.html
12  */
13
14 /*!
15  * This structure defines the offset of registers in gpio module.
16  */
17  
18 #include <redboot.h>
19 #include <cyg/hal/hal_intr.h>
20 #include <cyg/hal/plf_mmap.h>
21 #include <cyg/hal/hal_soc.h>         // Hardware definitions
22 #include <cyg/hal/hal_cache.h>
23
24 #undef MXC_MUX_DEBUG
25 //#define MXC_MUX_DEBUG
26
27 #ifdef MXC_MUX_DEBUG
28 #define diag_printf1    diag_printf
29 #else
30 #define diag_printf1(fmt,args...)
31 #endif
32
33 typedef unsigned short u16;
34 typedef unsigned int u32;
35 typedef unsigned char u8;
36
37 struct mxc_gpio_port {
38         u32 num;                /*!< gpio port number */
39         u32 base;               /*!< gpio port base VA */
40         u16 irq;                /*!< irq number to the core */
41         u16 virtual_irq_start;  /*!< virtual irq start number */
42 };
43
44 /*!
45  * This enumeration data type defines the configuration for input mode.
46  */
47 typedef enum {
48         GPIO_INPUT_GPIO = 0x00,
49         GPIO_INPUT_INTR = 0x01,
50         GPIO_INPUT_LOW = 0x02,
51         GPIO_INPUT_HIGH = 0x03
52 } gpio_input_cfg_t;
53
54 /*!
55  * This enumeration data type defines the configuration for output mode.
56  */
57 typedef enum {
58         GPIO_OUTPUT_A = 0x00,
59         GPIO_OUTPUT_B = 0x01,
60         GPIO_OUTPUT_C = 0x02,
61         GPIO_OUTPUT_DR = 0x03
62 } gpio_output_cfg_t;
63
64 struct gpio_port {
65         u32 num;                /*!< gpio port number */
66         u32 base;               /*!< gpio port base VA */
67         u16 irq;                /*!< irq number to the core */
68         u16 virtual_irq_start;  /*!< virtual irq start number */
69         u32 reserved_map;       /*!< keep track of which pins are in use */
70         u32 irq_is_level_map;   /*!< if a pin's irq is level sensitive. default is edge */
71 };
72
73 #define IO_ADDRESS(x)       x
74 #define GPIO_BASE_ADDR      SOC_GPIOA_BASE
75
76 struct mxc_gpio_port mxc_gpio_ports[GPIO_PORT_NUM] = {
77         {
78          .num = 0,
79          .base = IO_ADDRESS(GPIO_BASE_ADDR),
80          },
81         {
82          .num = 1,
83          .base = IO_ADDRESS(GPIO_BASE_ADDR) + 0x100,
84          },
85         {
86          .num = 2,
87          .base = IO_ADDRESS(GPIO_BASE_ADDR) + 0x200,
88          },
89         {
90          .num = 3,
91          .base = IO_ADDRESS(GPIO_BASE_ADDR) + 0x300,
92          },
93         {
94          .num = 4,
95          .base = IO_ADDRESS(GPIO_BASE_ADDR) + 0x400,
96          },
97         {
98          .num = 5,
99          .base = IO_ADDRESS(GPIO_BASE_ADDR) + 0x500,
100          },
101 };
102
103 static struct gpio_port gpio_port[GPIO_PORT_NUM];
104
105
106 static inline int _request_gpio(struct gpio_port *port, u32 index)
107 {
108         if (port->reserved_map & (1 << index)) {
109                 diag_printf("GPIO port %d (0-based), pin %d is already reserved!\n",
110                        port->num, index);
111                 return -1;
112         }
113         port->reserved_map |= (1 << index);
114         return 0;
115 }
116
117 static inline struct gpio_port *get_gpio_port(u32 gpio)
118 {
119         return &gpio_port[GPIO_TO_PORT(gpio)];
120 }
121
122 static int check_gpio(u32 gpio)
123 {
124         if (gpio >= MXC_MAX_GPIO_LINES) {
125                 diag_printf("mxc-gpio: invalid GPIO %d\n", gpio);
126                 return -1;
127         }
128         return 0;
129 }
130
131 /*!
132  * Request ownership for a GPIO pin. The caller has to check the return value
133  * of this function to make sure it returns 0 before make use of that pin.
134  * @param pin           a name defined by \b iomux_pin_name_t
135  * @return              0 if successful; Non-zero otherwise
136  */
137 int mxc_request_gpio(iomux_pin_name_t pin)
138 {
139         struct gpio_port *port;
140         u32 index, gpio = IOMUX_TO_GPIO(pin);
141
142         if (check_gpio(gpio) < 0)
143                 return -1;
144
145         port = get_gpio_port(gpio);
146         index = GPIO_TO_INDEX(gpio);
147
148         return _request_gpio(port, index);
149 }
150
151 /*!
152  * This function enable or disable the pullup feature to the pin. 
153  * @param port          a pointer of gpio port
154  * @param index         the index of the  pin in the port
155  * @param en            0 if disable pullup, otherwise enable it.
156  * @return              none
157  */
158 static inline void _gpio_set_puen(struct mxc_gpio_port *port, u32 index,
159                                   bool en)
160 {
161         u32 reg;
162
163         reg = readl(port->base + GPIO_PUEN);
164         if (en) {
165                 reg |= 1 << index;
166         } else {
167                 reg &= ~(1 << index);
168         }
169         writel(reg, port->base + GPIO_PUEN);
170 }
171
172 /*!
173  * This function set the input configuration A. 
174  * @param port          a pointer of gpio port
175  * @param index         the index of the  pin in the port
176  * @param config        a mode as define in \b #gpio_input_cfg_t
177  * @return              none
178  */
179 static inline void _gpio_set_iconfa(struct mxc_gpio_port *port, u32 index,
180                                     gpio_input_cfg_t config)
181 {
182         u32 reg, val;
183         u32 mask;
184
185         mask = 0x3 << ((index % 16) << 1);
186
187         if (index >= 16) {
188                 reg = port->base + GPIO_ICONFA2;
189                 val = config << ((index - 16) * 2);
190         } else {
191                 reg = port->base + GPIO_ICONFA1;
192                 val = config << (index * 2);
193         }
194         val |= readl(reg) & ~(mask);
195         writel(val, reg);
196 }
197
198 /*!
199  * This function set the input configuration B. 
200  * @param port          a pointer of gpio port
201  * @param index         the index of the  pin in the port
202  * @param config        a mode as define in \b #gpio_input_cfg_t
203  * @return              none
204  */
205 static inline void _gpio_set_iconfb(struct mxc_gpio_port *port, u32 index,
206                                     gpio_input_cfg_t config)
207 {
208         u32 reg, val;
209         u32 mask;
210
211         mask = 0x3 << ((index % 16) << 1);
212
213         if (index >= 16) {
214                 reg = port->base + GPIO_ICONFB2;
215                 val = config << ((index - 16) * 2);
216         } else {
217                 reg = port->base + GPIO_ICONFB1;
218                 val = config << (index * 2);
219         }
220         val |= readl(reg) & (~mask);
221         writel(val, reg);
222 }
223
224 /*!
225  * This function set the output configuration. 
226  * @param port          a pointer of gpio port
227  * @param index         the index of the  pin in the port
228  * @param config        a mode as define in \b #gpio_output_cfg_t
229  * @return              none
230  */
231 static inline void _gpio_set_ocr(struct mxc_gpio_port *port, u32 index,
232                                  gpio_output_cfg_t config)
233 {
234         u32 reg, val;
235         u32 mask;
236
237         mask = 0x3 << ((index % 16) << 1);
238         if (index >= 16) {
239                 reg = port->base + GPIO_OCR2;
240                 val = config << ((index - 16) * 2);
241         } else {
242                 reg = port->base + GPIO_OCR1;
243                 val = config << (index * 2);
244         }
245         val |= readl(reg) & (~mask);
246         writel(val, reg);
247 }
248
249 /*!
250  *@brief gpio_config_mux - just configure the mode of the gpio pin.
251  *@param pin   a pin number as defined in \b #iomux_pin_name_t
252  *@param mode  a module as define in \b #gpio_mux_mode_t;
253  *      GPIO_MUX_PRIMARY set pin to work as primary function.
254  *      GPIO_MUX_ALT set pin to work as alternate function.
255  *      GPIO_MUX_GPIO set pin to work as output function based the data register
256  *      GPIO_MUX_INPUT1 set pin to work as input function connected with  A_OUT
257  *      GPIO_MUX_INPUT2 set pin to work as input function connected with B_OUT
258  *      GPIO_MUX_OUTPUT1 set pin to work as output function connected with A_IN
259  *      GPIO_MUX_OUTPUT2 set pin to work as output function connected with B_IN
260  *      GPIO_MUX_OUTPUT3 set pin to work as output function connected with C_IN
261  *@return      0 if successful, Non-zero otherwise
262  */
263
264 int gpio_config_mux(iomux_pin_name_t pin, gpio_mux_mode_t mode)
265 {
266         u32 gius_reg, gpr_reg;
267         struct mxc_gpio_port *port;
268         u32 index, gpio = IOMUX_TO_GPIO(pin);
269
270         port = &(mxc_gpio_ports[GPIO_TO_PORT(gpio)]);
271         index = GPIO_TO_INDEX(gpio);
272
273         diag_printf1("%s: Configuring PORT %c, bit %d\n",
274                  __FUNCTION__, port->num + 'A', index);
275
276         gius_reg = readl(port->base + GPIO_GIUS);
277         gpr_reg = readl(port->base + GPIO_GPR);
278
279         switch (mode) {
280         case GPIO_MUX_PRIMARY:
281                 gius_reg &= ~(1L << index);
282                 gpr_reg &= ~(1L << index);
283                 break;
284         case GPIO_MUX_ALT:
285                 gius_reg &= ~(1L << index);
286                 gpr_reg |= (1L << index);
287                 break;
288         case GPIO_MUX_GPIO:
289                 gius_reg |= (1L << index);
290                 _gpio_set_ocr(port, index, GPIO_OUTPUT_DR);
291                 break;
292         case GPIO_MUX_INPUT1:
293                 gius_reg |= (1L << index);
294                 _gpio_set_iconfa(port, index, GPIO_INPUT_GPIO);
295                 break;
296         case GPIO_MUX_INPUT2:
297                 gius_reg |= (1L << index);
298                 _gpio_set_iconfb(port, index, GPIO_INPUT_GPIO);
299                 break;
300         case GPIO_MUX_OUTPUT1:
301                 gius_reg |= (1L << index);
302                 _gpio_set_ocr(port, index, GPIO_OUTPUT_A);
303                 break;
304         case GPIO_MUX_OUTPUT2:
305                 gius_reg |= (1L << index);
306                 _gpio_set_ocr(port, index, GPIO_OUTPUT_B);
307                 break;
308         case GPIO_MUX_OUTPUT3:
309                 gius_reg |= (1L << index);
310                 _gpio_set_ocr(port, index, GPIO_OUTPUT_C);
311                 break;
312         default:
313                 return -1;
314         }
315
316         writel(gius_reg, port->base + GPIO_GIUS);
317         writel(gpr_reg, port->base + GPIO_GPR);
318
319         return 0;
320 }
321
322 /*!
323  * This function is just used to enable or disable the pull up feature .
324  * @param pin   a pin number as defined in \b #iomux_pin_name_t
325  * @param en    0 if disable, Non-zero enable
326  * @return      0 if successful, Non-zero otherwise
327  */
328 int gpio_set_puen(iomux_pin_name_t pin, bool en)
329 {
330         struct mxc_gpio_port *port;
331         u32 index, gpio = IOMUX_TO_GPIO(pin);
332
333         port = &(mxc_gpio_ports[GPIO_TO_PORT(gpio)]);
334         index = GPIO_TO_INDEX(gpio);
335
336 //      diag_printf("%s: Configuring output mode of PORT %c, bit %d\n",
337 //               __FUNCTION__, port->num + 'A', index);
338
339         _gpio_set_puen(port, index, en);
340         return 0;
341
342 }
343
344 /*!
345  * This function is just used to request a pin and configure it.
346  * @param pin   a pin number as defined in \b #iomux_pin_name_t
347  * @param mode  a module as define in \b #gpio_mux_mode_t;
348  * @return      0 if successful, Non-zero otherwise
349  */
350 int gpio_request_mux(iomux_pin_name_t pin, gpio_mux_mode_t mode)
351 {
352         int ret;
353         ret = mxc_request_gpio(pin);
354         if (ret == 0) {
355                 ret = gpio_config_mux(pin, mode);
356                 if (ret) {
357                         diag_printf("%s(pin=%d, mode=%d) failed\n", __FUNCTION__, pin, mode);
358                 }
359         }
360         return ret;
361 }