]> git.ipfire.org Git - people/ms/u-boot.git/blob - arch/powerpc/cpu/ppc4xx/gpio.c
6d480dab8217f6c1c4543c024d91363d61323db1
[people/ms/u-boot.git] / arch / powerpc / cpu / ppc4xx / gpio.c
1 /*
2 * (C) Copyright 2007-2008
3 * Stefan Roese, DENX Software Engineering, sr@denx.de.
4 *
5 * SPDX-License-Identifier: GPL-2.0+
6 */
7
8 #include <common.h>
9 #include <asm/processor.h>
10 #include <asm/io.h>
11 #include <asm/ppc4xx-gpio.h>
12
13 /* Only compile this file for boards with GPIO support */
14 #if defined(GPIO0_BASE)
15
16 #if defined(CONFIG_SYS_4xx_GPIO_TABLE)
17 gpio_param_s const gpio_tab[GPIO_GROUP_MAX][GPIO_MAX] = CONFIG_SYS_4xx_GPIO_TABLE;
18 #endif
19
20 #if defined(GPIO0_OSRL)
21 /* Only some 4xx variants support alternate funtions on the GPIO's */
22 void gpio_config(int pin, int in_out, int gpio_alt, int out_val)
23 {
24 u32 mask;
25 u32 mask2;
26 u32 val;
27 u32 offs = 0;
28 u32 offs2 = 0;
29 int pin2 = pin << 1;
30
31 if (pin >= GPIO_MAX) {
32 offs = 0x100;
33 pin -= GPIO_MAX;
34 }
35
36 if (pin >= GPIO_MAX/2) {
37 offs2 = 0x4;
38 pin2 = (pin - GPIO_MAX/2) << 1;
39 }
40
41 mask = 0x80000000 >> pin;
42 mask2 = 0xc0000000 >> pin2;
43
44 /* first set TCR to 0 */
45 out_be32((void *)GPIO0_TCR + offs, in_be32((void *)GPIO0_TCR + offs) & ~mask);
46
47 if (in_out == GPIO_OUT) {
48 val = in_be32((void *)GPIO0_OSRL + offs + offs2) & ~mask2;
49 switch (gpio_alt) {
50 case GPIO_ALT1:
51 val |= GPIO_ALT1_SEL >> pin2;
52 break;
53 case GPIO_ALT2:
54 val |= GPIO_ALT2_SEL >> pin2;
55 break;
56 case GPIO_ALT3:
57 val |= GPIO_ALT3_SEL >> pin2;
58 break;
59 }
60 out_be32((void *)GPIO0_OSRL + offs + offs2, val);
61
62 /* setup requested output value */
63 if (out_val == GPIO_OUT_0)
64 out_be32((void *)GPIO0_OR + offs,
65 in_be32((void *)GPIO0_OR + offs) & ~mask);
66 else if (out_val == GPIO_OUT_1)
67 out_be32((void *)GPIO0_OR + offs,
68 in_be32((void *)GPIO0_OR + offs) | mask);
69
70 /* now configure TCR to drive output if selected */
71 out_be32((void *)GPIO0_TCR + offs,
72 in_be32((void *)GPIO0_TCR + offs) | mask);
73 } else {
74 val = in_be32((void *)GPIO0_ISR1L + offs + offs2) & ~mask2;
75 val |= GPIO_IN_SEL >> pin2;
76 out_be32((void *)GPIO0_ISR1L + offs + offs2, val);
77 }
78 }
79 #endif /* GPIO_OSRL */
80
81 void gpio_write_bit(int pin, int val)
82 {
83 u32 offs = 0;
84
85 if (pin >= GPIO_MAX) {
86 offs = 0x100;
87 pin -= GPIO_MAX;
88 }
89
90 if (val)
91 out_be32((void *)GPIO0_OR + offs,
92 in_be32((void *)GPIO0_OR + offs) | GPIO_VAL(pin));
93 else
94 out_be32((void *)GPIO0_OR + offs,
95 in_be32((void *)GPIO0_OR + offs) & ~GPIO_VAL(pin));
96 }
97
98 int gpio_read_out_bit(int pin)
99 {
100 u32 offs = 0;
101
102 if (pin >= GPIO_MAX) {
103 offs = 0x100;
104 pin -= GPIO_MAX;
105 }
106
107 return (in_be32((void *)GPIO0_OR + offs) & GPIO_VAL(pin) ? 1 : 0);
108 }
109
110 int gpio_read_in_bit(int pin)
111 {
112 u32 offs = 0;
113
114 if (pin >= GPIO_MAX) {
115 offs = 0x100;
116 pin -= GPIO_MAX;
117 }
118
119 return (in_be32((void *)GPIO0_IR + offs) & GPIO_VAL(pin) ? 1 : 0);
120 }
121
122 #if defined(CONFIG_SYS_4xx_GPIO_TABLE)
123 void gpio_set_chip_configuration(void)
124 {
125 unsigned char i=0, j=0, offs=0, gpio_core;
126 unsigned long reg, core_add;
127
128 for (gpio_core=0; gpio_core<GPIO_GROUP_MAX; gpio_core++) {
129 j = 0;
130 offs = 0;
131 /* GPIO config of the GPIOs 0 to 31 */
132 for (i=0; i<GPIO_MAX; i++, j++) {
133 if (i == GPIO_MAX/2) {
134 offs = 4;
135 j = i-16;
136 }
137
138 core_add = gpio_tab[gpio_core][i].add;
139
140 if ((gpio_tab[gpio_core][i].in_out == GPIO_IN) ||
141 (gpio_tab[gpio_core][i].in_out == GPIO_BI)) {
142
143 switch (gpio_tab[gpio_core][i].alt_nb) {
144 case GPIO_SEL:
145 break;
146
147 case GPIO_ALT1:
148 reg = in_be32((void *)GPIO_IS1(core_add+offs))
149 & ~(GPIO_MASK >> (j*2));
150 reg = reg | (GPIO_IN_SEL >> (j*2));
151 out_be32((void *)GPIO_IS1(core_add+offs), reg);
152 break;
153
154 case GPIO_ALT2:
155 reg = in_be32((void *)GPIO_IS2(core_add+offs))
156 & ~(GPIO_MASK >> (j*2));
157 reg = reg | (GPIO_IN_SEL >> (j*2));
158 out_be32((void *)GPIO_IS2(core_add+offs), reg);
159 break;
160
161 case GPIO_ALT3:
162 reg = in_be32((void *)GPIO_IS3(core_add+offs))
163 & ~(GPIO_MASK >> (j*2));
164 reg = reg | (GPIO_IN_SEL >> (j*2));
165 out_be32((void *)GPIO_IS3(core_add+offs), reg);
166 break;
167 }
168 }
169
170 if ((gpio_tab[gpio_core][i].in_out == GPIO_OUT) ||
171 (gpio_tab[gpio_core][i].in_out == GPIO_BI)) {
172
173 u32 gpio_alt_sel = 0;
174
175 switch (gpio_tab[gpio_core][i].alt_nb) {
176 case GPIO_SEL:
177 /*
178 * Setup output value
179 * 1 -> high level
180 * 0 -> low level
181 * else -> don't touch
182 */
183 reg = in_be32((void *)GPIO_OR(core_add));
184 if (gpio_tab[gpio_core][i].out_val == GPIO_OUT_1)
185 reg |= (0x80000000 >> (i));
186 else if (gpio_tab[gpio_core][i].out_val == GPIO_OUT_0)
187 reg &= ~(0x80000000 >> (i));
188 out_be32((void *)GPIO_OR(core_add), reg);
189
190 reg = in_be32((void *)GPIO_TCR(core_add)) |
191 (0x80000000 >> (i));
192 out_be32((void *)GPIO_TCR(core_add), reg);
193
194 reg = in_be32((void *)GPIO_OS(core_add+offs))
195 & ~(GPIO_MASK >> (j*2));
196 out_be32((void *)GPIO_OS(core_add+offs), reg);
197 reg = in_be32((void *)GPIO_TS(core_add+offs))
198 & ~(GPIO_MASK >> (j*2));
199 out_be32((void *)GPIO_TS(core_add+offs), reg);
200 break;
201
202 case GPIO_ALT1:
203 gpio_alt_sel = GPIO_ALT1_SEL;
204 break;
205
206 case GPIO_ALT2:
207 gpio_alt_sel = GPIO_ALT2_SEL;
208 break;
209
210 case GPIO_ALT3:
211 gpio_alt_sel = GPIO_ALT3_SEL;
212 break;
213 }
214
215 if (0 != gpio_alt_sel) {
216 reg = in_be32((void *)GPIO_OS(core_add+offs))
217 & ~(GPIO_MASK >> (j*2));
218 reg = reg | (gpio_alt_sel >> (j*2));
219 out_be32((void *)GPIO_OS(core_add+offs), reg);
220
221 if (gpio_tab[gpio_core][i].out_val == GPIO_OUT_1) {
222 reg = in_be32((void *)GPIO_TCR(core_add))
223 | (0x80000000 >> (i));
224 out_be32((void *)GPIO_TCR(core_add), reg);
225 reg = in_be32((void *)GPIO_TS(core_add+offs))
226 & ~(GPIO_MASK >> (j*2));
227 out_be32((void *)GPIO_TS(core_add+offs), reg);
228 } else {
229 reg = in_be32((void *)GPIO_TCR(core_add))
230 & ~(0x80000000 >> (i));
231 out_be32((void *)GPIO_TCR(core_add), reg);
232 reg = in_be32((void *)GPIO_TS(core_add+offs))
233 & ~(GPIO_MASK >> (j*2));
234 reg = reg | (gpio_alt_sel >> (j*2));
235 out_be32((void *)GPIO_TS(core_add+offs), reg);
236 }
237 }
238 }
239 }
240 }
241 }
242
243 #endif /* GPIO0_BASE */
244 #endif /* CONFIG_SYS_4xx_GPIO_TABLE */