Merge 'u-boot-microblaze/zynq' into (u-boot-arm/master'
[platform/kernel/u-boot.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                 return -1;
50
51         gpio &= 0x1f;
52
53         regs = (struct gpio_regs *)gpio_ports[port];
54
55         l = readl(&regs->gpio_dir);
56
57         switch (direction) {
58         case MXC_GPIO_DIRECTION_OUT:
59                 l |= 1 << gpio;
60                 break;
61         case MXC_GPIO_DIRECTION_IN:
62                 l &= ~(1 << gpio);
63         }
64         writel(l, &regs->gpio_dir);
65
66         return 0;
67 }
68
69 int gpio_set_value(unsigned gpio, int value)
70 {
71         unsigned int port = GPIO_TO_PORT(gpio);
72         struct gpio_regs *regs;
73         u32 l;
74
75         if (port >= ARRAY_SIZE(gpio_ports))
76                 return -1;
77
78         gpio &= 0x1f;
79
80         regs = (struct gpio_regs *)gpio_ports[port];
81
82         l = readl(&regs->gpio_dr);
83         if (value)
84                 l |= 1 << gpio;
85         else
86                 l &= ~(1 << gpio);
87         writel(l, &regs->gpio_dr);
88
89         return 0;
90 }
91
92 int gpio_get_value(unsigned gpio)
93 {
94         unsigned int port = GPIO_TO_PORT(gpio);
95         struct gpio_regs *regs;
96         u32 val;
97
98         if (port >= ARRAY_SIZE(gpio_ports))
99                 return -1;
100
101         gpio &= 0x1f;
102
103         regs = (struct gpio_regs *)gpio_ports[port];
104
105         val = (readl(&regs->gpio_psr) >> gpio) & 0x01;
106
107         return val;
108 }
109
110 int gpio_request(unsigned gpio, const char *label)
111 {
112         unsigned int port = GPIO_TO_PORT(gpio);
113         if (port >= ARRAY_SIZE(gpio_ports))
114                 return -1;
115         return 0;
116 }
117
118 int gpio_free(unsigned gpio)
119 {
120         return 0;
121 }
122
123 int gpio_direction_input(unsigned gpio)
124 {
125         return mxc_gpio_direction(gpio, MXC_GPIO_DIRECTION_IN);
126 }
127
128 int gpio_direction_output(unsigned gpio, int value)
129 {
130         int ret = gpio_set_value(gpio, value);
131
132         if (ret < 0)
133                 return ret;
134
135         return mxc_gpio_direction(gpio, MXC_GPIO_DIRECTION_OUT);
136 }