blob: 6d480dab8217f6c1c4543c024d91363d61323db1 [file] [log] [blame]
Stefan Roese3cb86f32007-03-24 15:45:34 +01001/*
Stefan Roeseaac7a502008-06-23 11:15:09 +02002 * (C) Copyright 2007-2008
Stefan Roese3cb86f32007-03-24 15:45:34 +01003 * Stefan Roese, DENX Software Engineering, sr@denx.de.
4 *
Wolfgang Denk1a459662013-07-08 09:37:19 +02005 * SPDX-License-Identifier: GPL-2.0+
Stefan Roese3cb86f32007-03-24 15:45:34 +01006 */
7
8#include <common.h>
9#include <asm/processor.h>
10#include <asm/io.h>
Stefan Roese09887762010-09-16 14:30:37 +020011#include <asm/ppc4xx-gpio.h>
Stefan Roese3cb86f32007-03-24 15:45:34 +010012
Stefan Roeseafabb492010-09-12 06:21:37 +020013/* Only compile this file for boards with GPIO support */
14#if defined(GPIO0_BASE)
15
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020016#if defined(CONFIG_SYS_4xx_GPIO_TABLE)
17gpio_param_s const gpio_tab[GPIO_GROUP_MAX][GPIO_MAX] = CONFIG_SYS_4xx_GPIO_TABLE;
Stefan Roese3cb86f32007-03-24 15:45:34 +010018#endif
19
20#if defined(GPIO0_OSRL)
21/* Only some 4xx variants support alternate funtions on the GPIO's */
22void 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) {
Stefan Roese3b9abdc2007-12-11 13:38:19 +010037 offs2 = 0x4;
Stefan Roese3cb86f32007-03-24 15:45:34 +010038 pin2 = (pin - GPIO_MAX/2) << 1;
39 }
40
41 mask = 0x80000000 >> pin;
Stefan Roeseaac7a502008-06-23 11:15:09 +020042 mask2 = 0xc0000000 >> pin2;
Stefan Roese3cb86f32007-03-24 15:45:34 +010043
44 /* first set TCR to 0 */
Stefan Roeseaee747f2007-11-15 14:23:55 +010045 out_be32((void *)GPIO0_TCR + offs, in_be32((void *)GPIO0_TCR + offs) & ~mask);
Stefan Roese3cb86f32007-03-24 15:45:34 +010046
47 if (in_out == GPIO_OUT) {
Stefan Roeseaee747f2007-11-15 14:23:55 +010048 val = in_be32((void *)GPIO0_OSRL + offs + offs2) & ~mask2;
Stefan Roese3cb86f32007-03-24 15:45:34 +010049 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 }
Stefan Roeseaee747f2007-11-15 14:23:55 +010060 out_be32((void *)GPIO0_OSRL + offs + offs2, val);
Stefan Roese3cb86f32007-03-24 15:45:34 +010061
62 /* setup requested output value */
63 if (out_val == GPIO_OUT_0)
Stefan Roeseaee747f2007-11-15 14:23:55 +010064 out_be32((void *)GPIO0_OR + offs,
65 in_be32((void *)GPIO0_OR + offs) & ~mask);
Stefan Roese3cb86f32007-03-24 15:45:34 +010066 else if (out_val == GPIO_OUT_1)
Stefan Roeseaee747f2007-11-15 14:23:55 +010067 out_be32((void *)GPIO0_OR + offs,
68 in_be32((void *)GPIO0_OR + offs) | mask);
Stefan Roese3cb86f32007-03-24 15:45:34 +010069
70 /* now configure TCR to drive output if selected */
Stefan Roeseaee747f2007-11-15 14:23:55 +010071 out_be32((void *)GPIO0_TCR + offs,
72 in_be32((void *)GPIO0_TCR + offs) | mask);
Stefan Roese3cb86f32007-03-24 15:45:34 +010073 } else {
Stefan Roeseaee747f2007-11-15 14:23:55 +010074 val = in_be32((void *)GPIO0_ISR1L + offs + offs2) & ~mask2;
Stefan Roese3cb86f32007-03-24 15:45:34 +010075 val |= GPIO_IN_SEL >> pin2;
Stefan Roeseaee747f2007-11-15 14:23:55 +010076 out_be32((void *)GPIO0_ISR1L + offs + offs2, val);
Stefan Roese3cb86f32007-03-24 15:45:34 +010077 }
78}
79#endif /* GPIO_OSRL */
80
81void 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)
Stefan Roeseaee747f2007-11-15 14:23:55 +010091 out_be32((void *)GPIO0_OR + offs,
92 in_be32((void *)GPIO0_OR + offs) | GPIO_VAL(pin));
Stefan Roese3cb86f32007-03-24 15:45:34 +010093 else
Stefan Roeseaee747f2007-11-15 14:23:55 +010094 out_be32((void *)GPIO0_OR + offs,
95 in_be32((void *)GPIO0_OR + offs) & ~GPIO_VAL(pin));
Stefan Roese3cb86f32007-03-24 15:45:34 +010096}
97
Stefan Roese85f73732007-06-15 07:39:43 +020098int 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
Stefan Roeseaee747f2007-11-15 14:23:55 +0100107 return (in_be32((void *)GPIO0_OR + offs) & GPIO_VAL(pin) ? 1 : 0);
Stefan Roese85f73732007-06-15 07:39:43 +0200108}
109
Lawrence R. Johnson5ab884b2008-01-03 18:54:00 -0500110int 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
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200122#if defined(CONFIG_SYS_4xx_GPIO_TABLE)
Stefan Roese3cb86f32007-03-24 15:45:34 +0100123void 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:
Stefan Roeseaee747f2007-11-15 14:23:55 +0100148 reg = in_be32((void *)GPIO_IS1(core_add+offs))
Stefan Roese3cb86f32007-03-24 15:45:34 +0100149 & ~(GPIO_MASK >> (j*2));
150 reg = reg | (GPIO_IN_SEL >> (j*2));
Stefan Roeseaee747f2007-11-15 14:23:55 +0100151 out_be32((void *)GPIO_IS1(core_add+offs), reg);
Stefan Roese3cb86f32007-03-24 15:45:34 +0100152 break;
153
154 case GPIO_ALT2:
Stefan Roeseaee747f2007-11-15 14:23:55 +0100155 reg = in_be32((void *)GPIO_IS2(core_add+offs))
Stefan Roese3cb86f32007-03-24 15:45:34 +0100156 & ~(GPIO_MASK >> (j*2));
157 reg = reg | (GPIO_IN_SEL >> (j*2));
Stefan Roeseaee747f2007-11-15 14:23:55 +0100158 out_be32((void *)GPIO_IS2(core_add+offs), reg);
Stefan Roese3cb86f32007-03-24 15:45:34 +0100159 break;
160
161 case GPIO_ALT3:
Stefan Roeseaee747f2007-11-15 14:23:55 +0100162 reg = in_be32((void *)GPIO_IS3(core_add+offs))
Stefan Roese3cb86f32007-03-24 15:45:34 +0100163 & ~(GPIO_MASK >> (j*2));
164 reg = reg | (GPIO_IN_SEL >> (j*2));
Stefan Roeseaee747f2007-11-15 14:23:55 +0100165 out_be32((void *)GPIO_IS3(core_add+offs), reg);
Stefan Roese3cb86f32007-03-24 15:45:34 +0100166 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
Lawrence R. Johnson5ab884b2008-01-03 18:54:00 -0500173 u32 gpio_alt_sel = 0;
174
Stefan Roese3cb86f32007-03-24 15:45:34 +0100175 switch (gpio_tab[gpio_core][i].alt_nb) {
176 case GPIO_SEL:
Stefan Roeseaee747f2007-11-15 14:23:55 +0100177 /*
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);
Stefan Roese85f73732007-06-15 07:39:43 +0200189
Stefan Roeseaee747f2007-11-15 14:23:55 +0100190 reg = in_be32((void *)GPIO_TCR(core_add)) |
191 (0x80000000 >> (i));
192 out_be32((void *)GPIO_TCR(core_add), reg);
Stefan Roese3cb86f32007-03-24 15:45:34 +0100193
Stefan Roeseaee747f2007-11-15 14:23:55 +0100194 reg = in_be32((void *)GPIO_OS(core_add+offs))
Stefan Roese3cb86f32007-03-24 15:45:34 +0100195 & ~(GPIO_MASK >> (j*2));
Stefan Roeseaee747f2007-11-15 14:23:55 +0100196 out_be32((void *)GPIO_OS(core_add+offs), reg);
197 reg = in_be32((void *)GPIO_TS(core_add+offs))
Stefan Roese3cb86f32007-03-24 15:45:34 +0100198 & ~(GPIO_MASK >> (j*2));
Stefan Roeseaee747f2007-11-15 14:23:55 +0100199 out_be32((void *)GPIO_TS(core_add+offs), reg);
Stefan Roese3cb86f32007-03-24 15:45:34 +0100200 break;
201
202 case GPIO_ALT1:
Lawrence R. Johnson5ab884b2008-01-03 18:54:00 -0500203 gpio_alt_sel = GPIO_ALT1_SEL;
Stefan Roese3cb86f32007-03-24 15:45:34 +0100204 break;
205
206 case GPIO_ALT2:
Lawrence R. Johnson5ab884b2008-01-03 18:54:00 -0500207 gpio_alt_sel = GPIO_ALT2_SEL;
Stefan Roese3cb86f32007-03-24 15:45:34 +0100208 break;
209
210 case GPIO_ALT3:
Lawrence R. Johnson5ab884b2008-01-03 18:54:00 -0500211 gpio_alt_sel = GPIO_ALT3_SEL;
212 break;
213 }
214
215 if (0 != gpio_alt_sel) {
Stefan Roeseaee747f2007-11-15 14:23:55 +0100216 reg = in_be32((void *)GPIO_OS(core_add+offs))
Stefan Roese3cb86f32007-03-24 15:45:34 +0100217 & ~(GPIO_MASK >> (j*2));
Lawrence R. Johnson5ab884b2008-01-03 18:54:00 -0500218 reg = reg | (gpio_alt_sel >> (j*2));
Stefan Roeseaee747f2007-11-15 14:23:55 +0100219 out_be32((void *)GPIO_OS(core_add+offs), reg);
Lawrence R. Johnson5ab884b2008-01-03 18:54:00 -0500220
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 }
Stefan Roese3cb86f32007-03-24 15:45:34 +0100237 }
238 }
239 }
240 }
241}
Stefan Roeseafabb492010-09-12 06:21:37 +0200242
243#endif /* GPIO0_BASE */
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200244#endif /* CONFIG_SYS_4xx_GPIO_TABLE */