pq3gpio.c revision 1.13 1 1.13 thorpej /* $NetBSD: pq3gpio.c,v 1.13 2021/04/24 23:36:46 thorpej Exp $ */
2 1.2 matt /*-
3 1.2 matt * Copyright (c) 2010, 2011 The NetBSD Foundation, Inc.
4 1.2 matt * All rights reserved.
5 1.2 matt *
6 1.2 matt * This code is derived from software contributed to The NetBSD Foundation
7 1.2 matt * by Raytheon BBN Technologies Corp and Defense Advanced Research Projects
8 1.2 matt * Agency and which was developed by Matt Thomas of 3am Software Foundry.
9 1.2 matt *
10 1.2 matt * This material is based upon work supported by the Defense Advanced Research
11 1.2 matt * Projects Agency and Space and Naval Warfare Systems Center, Pacific, under
12 1.2 matt * Contract No. N66001-09-C-2073.
13 1.2 matt * Approved for Public Release, Distribution Unlimited
14 1.2 matt *
15 1.2 matt * Redistribution and use in source and binary forms, with or without
16 1.2 matt * modification, are permitted provided that the following conditions
17 1.2 matt * are met:
18 1.2 matt * 1. Redistributions of source code must retain the above copyright
19 1.2 matt * notice, this list of conditions and the following disclaimer.
20 1.2 matt * 2. Redistributions in binary form must reproduce the above copyright
21 1.2 matt * notice, this list of conditions and the following disclaimer in the
22 1.2 matt * documentation and/or other materials provided with the distribution.
23 1.2 matt *
24 1.2 matt * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
25 1.2 matt * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
26 1.2 matt * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
27 1.2 matt * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
28 1.2 matt * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 1.2 matt * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 1.2 matt * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 1.2 matt * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 1.2 matt * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 1.2 matt * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 1.2 matt * POSSIBILITY OF SUCH DAMAGE.
35 1.2 matt */
36 1.2 matt
37 1.2 matt #define GLOBAL_PRIVATE
38 1.5 matt #define GPIO_PRIVATE
39 1.2 matt
40 1.2 matt #include <sys/cdefs.h>
41 1.13 thorpej __KERNEL_RCSID(0, "$NetBSD: pq3gpio.c,v 1.13 2021/04/24 23:36:46 thorpej Exp $");
42 1.2 matt
43 1.12 rin #ifdef _KERNEL_OPT
44 1.12 rin #include "opt_mpc85xx.h"
45 1.12 rin #endif
46 1.2 matt
47 1.2 matt #include <sys/param.h>
48 1.2 matt #include <sys/cpu.h>
49 1.2 matt #include <sys/device.h>
50 1.2 matt #include <sys/tty.h>
51 1.2 matt #include <sys/kmem.h>
52 1.2 matt #include <sys/gpio.h>
53 1.2 matt #include <sys/bitops.h>
54 1.2 matt
55 1.2 matt #include "ioconf.h"
56 1.2 matt
57 1.2 matt #include <sys/intr.h>
58 1.2 matt #include <sys/bus.h>
59 1.2 matt
60 1.2 matt #include <dev/gpio/gpiovar.h>
61 1.2 matt
62 1.2 matt #include <powerpc/booke/cpuvar.h>
63 1.2 matt #include <powerpc/booke/spr.h>
64 1.2 matt #include <powerpc/booke/e500var.h>
65 1.2 matt #include <powerpc/booke/e500reg.h>
66 1.2 matt
67 1.2 matt struct pq3gpio_group {
68 1.2 matt struct gpio_chipset_tag gc_tag;
69 1.2 matt gpio_pin_t gc_pins[32];
70 1.2 matt bus_space_tag_t gc_bst;
71 1.2 matt bus_space_handle_t gc_bsh;
72 1.2 matt bus_size_t gc_reg;
73 1.2 matt };
74 1.2 matt
75 1.2 matt struct pq3gpio_softc {
76 1.2 matt device_t sc_dev;
77 1.2 matt bus_space_tag_t sc_bst;
78 1.2 matt bus_space_handle_t sc_bsh;
79 1.2 matt SIMPLEQ_HEAD(,pq3gpio_group) sc_gpios;
80 1.2 matt };
81 1.2 matt
82 1.2 matt static int
83 1.2 matt pq3gpio_pin_read(void *v, int num)
84 1.2 matt {
85 1.2 matt struct pq3gpio_group * const gc = v;
86 1.2 matt
87 1.2 matt uint32_t data = bus_space_read_4(gc->gc_bst, gc->gc_bsh, gc->gc_reg);
88 1.2 matt
89 1.2 matt return (data >> (gc->gc_pins[num].pin_num ^ 31)) & 1;
90 1.2 matt }
91 1.2 matt
92 1.2 matt static void
93 1.2 matt pq3gpio_pin_write(void *v, int num, int val)
94 1.2 matt {
95 1.2 matt struct pq3gpio_group * const gc = v;
96 1.2 matt const u_int mask = 1 << (gc->gc_pins[num].pin_num ^ 31);
97 1.2 matt
98 1.2 matt val = val ? mask : 0;
99 1.2 matt u_int data = bus_space_read_4(gc->gc_bst, gc->gc_bsh, gc->gc_reg);
100 1.2 matt if ((data & mask) != val) {
101 1.2 matt data = (data & ~mask) | val;
102 1.2 matt bus_space_write_4(gc->gc_bst, gc->gc_bsh, gc->gc_reg, data);
103 1.2 matt }
104 1.2 matt }
105 1.2 matt
106 1.6 matt #if defined(MPC8548) || defined(MPC8555) || defined(MPC8544)
107 1.6 matt static void
108 1.6 matt pq3gpio_null_pin_ctl(void *v, int num, int ctl)
109 1.6 matt {
110 1.6 matt }
111 1.6 matt #endif
112 1.6 matt
113 1.8 matt #if defined(P1025)
114 1.8 matt /*
115 1.8 matt * P1025 has controllable input/output pins
116 1.8 matt */
117 1.8 matt static void
118 1.8 matt pq3gpio_pin_ctl(void *v, int num, int ctl)
119 1.8 matt {
120 1.8 matt struct pq3gpio_group * const gc = v;
121 1.8 matt const size_t shift = gc->gc_pins[num].pin_num ^ 31;
122 1.8 matt
123 1.8 matt uint64_t old_dir =
124 1.8 matt ((uint64_t)bus_space_read_4(gc->gc_bst, gc->gc_bsh, CPDIR1) << 32)
125 1.8 matt | (bus_space_read_4(gc->gc_bst, gc->gc_bsh, CPDIR2) << 0);
126 1.8 matt
127 1.8 matt uint32_t dir = 0;
128 1.8 matt switch (ctl & (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) {
129 1.8 matt case GPIO_PIN_INPUT|GPIO_PIN_OUTPUT: dir = CPDIR_INOUT; break;
130 1.8 matt case GPIO_PIN_OUTPUT: dir = CPDIR_OUT; break;
131 1.8 matt case GPIO_PIN_INPUT: dir = CPDIR_INOUT; break;
132 1.8 matt case 0: dir = CPDIR_DIS; break;
133 1.8 matt }
134 1.8 matt
135 1.8 matt uint64_t new_dir = (old_dir & (3ULL << (2 * shift)))
136 1.8 matt | ((uint64_t)dir << (2 * shift));
137 1.8 matt
138 1.8 matt if ((uint32_t)old_dir != (uint32_t)new_dir)
139 1.8 matt bus_space_write_4(gc->gc_bst, gc->gc_bsh, CPDIR2,
140 1.8 matt (uint32_t)new_dir);
141 1.8 matt new_dir >>= 32;
142 1.8 matt old_dir >>= 32;
143 1.8 matt if ((uint32_t)old_dir != (uint32_t)new_dir)
144 1.8 matt bus_space_write_4(gc->gc_bst, gc->gc_bsh, CPDIR1,
145 1.8 matt (uint32_t)new_dir);
146 1.8 matt
147 1.8 matt /*
148 1.8 matt * Now handle opendrain
149 1.8 matt */
150 1.8 matt uint32_t old_odr = bus_space_read_4(gc->gc_bst, gc->gc_bsh, CPODR);
151 1.8 matt uint32_t new_odr = old_odr;
152 1.8 matt uint32_t odr_mask = 1UL << shift;
153 1.8 matt
154 1.8 matt if (ctl & GPIO_PIN_OPENDRAIN) {
155 1.8 matt new_odr |= odr_mask;
156 1.8 matt } else {
157 1.8 matt new_odr &= ~odr_mask;
158 1.8 matt }
159 1.8 matt
160 1.8 matt if (old_odr != new_odr)
161 1.8 matt bus_space_write_4(gc->gc_bst, gc->gc_bsh, CPODR, new_odr);
162 1.8 matt }
163 1.8 matt #endif
164 1.8 matt
165 1.11 nonaka #if defined(MPC8536) || defined(P2020) || defined(P1023)
166 1.6 matt /*
167 1.11 nonaka * MPC8536 / P20x0 / P1023 have controllable input/output pins
168 1.6 matt */
169 1.2 matt static void
170 1.2 matt pq3gpio_pin_ctl(void *v, int num, int ctl)
171 1.2 matt {
172 1.5 matt struct pq3gpio_group * const gc = v;
173 1.5 matt const u_int mask = 1 << (gc->gc_pins[num].pin_num ^ 31);
174 1.5 matt
175 1.6 matt uint32_t old_dir = bus_space_read_4(gc->gc_bst, gc->gc_bsh, GPDIR);
176 1.6 matt uint32_t new_dir = old_dir;
177 1.6 matt switch (ctl & (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) {
178 1.6 matt case GPIO_PIN_OUTPUT: new_dir |= mask; break;
179 1.6 matt case GPIO_PIN_INPUT: new_dir &= ~mask; break;
180 1.6 matt default: return;
181 1.6 matt }
182 1.6 matt if (old_dir != new_dir)
183 1.6 matt bus_space_write_4(gc->gc_bst, gc->gc_bsh, GPDIR, new_dir);
184 1.6 matt
185 1.6 matt /*
186 1.6 matt * Now handle opendrain
187 1.6 matt */
188 1.6 matt uint32_t old_odr = bus_space_read_4(gc->gc_bst, gc->gc_bsh, GPODR);
189 1.6 matt uint32_t new_odr = old_odr;
190 1.6 matt
191 1.6 matt if (ctl & GPIO_PIN_OPENDRAIN) {
192 1.6 matt new_odr |= mask;
193 1.6 matt } else {
194 1.6 matt new_odr &= ~mask;
195 1.6 matt }
196 1.6 matt
197 1.6 matt if (old_odr != new_odr)
198 1.6 matt bus_space_write_4(gc->gc_bst, gc->gc_bsh, GPODR, new_odr);
199 1.2 matt }
200 1.6 matt #endif
201 1.2 matt
202 1.2 matt static void
203 1.2 matt pq3gpio_group_create(device_t self, bus_space_tag_t bst, bus_space_handle_t bsh,
204 1.6 matt bus_size_t reg, uint32_t pinmask, int pincaps,
205 1.6 matt void (*pin_ctl)(void *, int, int))
206 1.2 matt {
207 1.2 matt struct pq3gpio_group * const gc = kmem_zalloc(sizeof(*gc), KM_SLEEP);
208 1.2 matt
209 1.2 matt gc->gc_bst = bst;
210 1.2 matt gc->gc_bsh = bsh;
211 1.2 matt gc->gc_reg = reg;
212 1.2 matt gc->gc_tag.gp_cookie = gc;
213 1.2 matt #if 0
214 1.2 matt gc->gc_tag.gp_gc_open = pq3gpio_gc_open;
215 1.2 matt gc->gc_tag.gp_gc_close = pq3gpio_gc_close;
216 1.2 matt #endif
217 1.2 matt gc->gc_tag.gp_pin_read = pq3gpio_pin_read;
218 1.2 matt gc->gc_tag.gp_pin_write = pq3gpio_pin_write;
219 1.7 matt gc->gc_tag.gp_pin_ctl = pin_ctl;
220 1.2 matt
221 1.2 matt u_int data = bus_space_read_4(gc->gc_bst, gc->gc_bsh, reg);
222 1.2 matt u_int mask = __BIT(31);
223 1.2 matt gpio_pin_t *pin = gc->gc_pins;
224 1.2 matt for (u_int i = 0; mask != 0; i++, mask >>= 1) {
225 1.2 matt if (mask & pinmask) {
226 1.2 matt pin->pin_num = i;
227 1.2 matt pin->pin_caps = pincaps;
228 1.2 matt pin->pin_flags = pincaps;
229 1.2 matt pin->pin_state = (data & mask) != 0;
230 1.2 matt pin++;
231 1.2 matt }
232 1.2 matt }
233 1.2 matt
234 1.2 matt struct gpiobus_attach_args gba = {
235 1.2 matt .gba_gc = &gc->gc_tag,
236 1.2 matt .gba_pins = gc->gc_pins,
237 1.2 matt .gba_npins = pin - gc->gc_pins,
238 1.2 matt };
239 1.2 matt
240 1.13 thorpej config_found(self, &gba, gpiobus_print,
241 1.13 thorpej CFARG_IATTR, "gpiobus",
242 1.13 thorpej CFARG_EOL);
243 1.2 matt }
244 1.2 matt
245 1.2 matt #ifdef MPC8536
246 1.2 matt static void
247 1.2 matt pq3gpio_mpc8536_attach(device_t self, bus_space_tag_t bst,
248 1.2 matt bus_space_handle_t bsh, u_int svr)
249 1.2 matt {
250 1.2 matt static const uint8_t gpio2pmuxcr_map[] = {
251 1.2 matt [0] = ilog2(PMUXCR_PCI_REQGNT3),
252 1.2 matt [1] = ilog2(PMUXCR_PCI_REQGNT4),
253 1.2 matt [2] = ilog2(PMUXCR_PCI_REQGNT3),
254 1.2 matt [3] = ilog2(PMUXCR_PCI_REQGNT4),
255 1.2 matt [4] = ilog2(PMUXCR_SDHC_CD),
256 1.2 matt [5] = ilog2(PMUXCR_SDHC_WP),
257 1.2 matt [6] = ilog2(PMUXCR_USB1),
258 1.2 matt [7] = ilog2(PMUXCR_USB1),
259 1.2 matt [8] = ilog2(PMUXCR_USB2),
260 1.2 matt [9] = ilog2(PMUXCR_USB2),
261 1.2 matt [10] = ilog2(PMUXCR_DMA0),
262 1.2 matt [11] = ilog2(PMUXCR_DMA1),
263 1.2 matt [12] = ilog2(PMUXCR_DMA0),
264 1.2 matt [13] = ilog2(PMUXCR_DMA1),
265 1.2 matt [14] = ilog2(PMUXCR_DMA0),
266 1.2 matt [15] = ilog2(PMUXCR_DMA1),
267 1.2 matt };
268 1.2 matt
269 1.6 matt uint32_t pinmask = 0xffff0000; /* assume all bits are valid */
270 1.2 matt uint32_t gpiomask = __BIT(31);
271 1.6 matt size_t pincnt = 16;
272 1.6 matt const uint32_t pmuxcr = cpu_read_4(GLOBAL_BASE + PMUXCR);
273 1.2 matt for (size_t i = 0; i < __arraycount(gpio2pmuxcr_map);
274 1.2 matt i++, gpiomask >>= 1) {
275 1.2 matt if (pmuxcr & __BIT(gpio2pmuxcr_map[i])) {
276 1.2 matt pinmask &= ~gpiomask;
277 1.2 matt pincnt--;
278 1.2 matt }
279 1.2 matt }
280 1.2 matt
281 1.2 matt /*
282 1.2 matt * Create GPIO pin groups
283 1.2 matt */
284 1.6 matt aprint_normal_dev(self, "%zu input/output/opendrain pins\n",
285 1.7 matt pincnt);
286 1.6 matt pq3gpio_group_create(self, bst, bsh, GPDAT, pinmask,
287 1.6 matt GPIO_PIN_INPUT | GPIO_PIN_OUTPUT | GPIO_PIN_OPENDRAIN,
288 1.6 matt pq3gpio_pin_ctl);
289 1.2 matt }
290 1.2 matt #endif /* MPC8536 */
291 1.2 matt
292 1.2 matt #ifdef MPC8544
293 1.2 matt static void
294 1.2 matt pq3gpio_mpc8544_attach(device_t self, bus_space_tag_t bst,
295 1.2 matt bus_space_handle_t bsh, u_int svr)
296 1.2 matt {
297 1.2 matt /*
298 1.2 matt * Enable GPOUT
299 1.2 matt */
300 1.2 matt uint32_t gpiocr = bus_space_read_4(bst, bsh, GPIOCR);
301 1.2 matt gpiocr |= GPIOCR_GPOUT;
302 1.2 matt bus_space_write_4(bst, bsh, GPIOCR, gpiocr);
303 1.2 matt
304 1.2 matt aprint_normal_dev(self, "8 input pins, 8 output pins\n");
305 1.2 matt
306 1.2 matt /*
307 1.2 matt * Create GPIO pin groups
308 1.2 matt */
309 1.6 matt pq3gpio_group_create(self, bst, bsh, GPINDR, 0xff000000,
310 1.6 matt GPIO_PIN_INPUT, pq3gpio_null_pin_ctl);
311 1.6 matt pq3gpio_group_create(self, bst, bsh, GPOUTDR, 0xff000000,
312 1.6 matt GPIO_PIN_OUTPUT, pq3gpio_null_pin_ctl);
313 1.2 matt }
314 1.2 matt #endif /* MPC8544 */
315 1.2 matt
316 1.2 matt #if defined(MPC8548) || defined(MPC8555)
317 1.2 matt static void
318 1.2 matt pq3gpio_mpc8548_attach(device_t self, bus_space_tag_t bst,
319 1.2 matt bus_space_handle_t bsh, u_int svr)
320 1.2 matt {
321 1.2 matt const uint32_t pordevsr = bus_space_read_4(bst, bsh, PORDEVSR);
322 1.2 matt const uint32_t devdisr = bus_space_read_4(bst, bsh, DEVDISR);
323 1.2 matt uint32_t gpiocr = bus_space_read_4(bst, bsh, GPIOCR);
324 1.2 matt
325 1.2 matt uint32_t inmask = 0;
326 1.2 matt uint32_t outmask = 0;
327 1.2 matt
328 1.2 matt size_t ipins = 0;
329 1.2 matt size_t opins = 0;
330 1.2 matt
331 1.2 matt aprint_normal_dev(self, "GPIOCR %#x, DEVDISR %#x, PORDEVSR %#x\n",
332 1.2 matt gpiocr, devdisr, pordevsr);
333 1.2 matt aprint_normal_dev(self, "GPINDR %#x, GPOUTDR %#x, GPPORCR %#x\n",
334 1.2 matt bus_space_read_4(bst, bsh, GPINDR),
335 1.2 matt bus_space_read_4(bst, bsh, GPOUTDR),
336 1.2 matt bus_space_read_4(bst, bsh, GPPORCR));
337 1.2 matt
338 1.2 matt /*
339 1.2 matt * Use PCI2 AD[15:0] as GPIO if PCI2 is disabled and
340 1.2 matt * PCI1 is either disabled or not 64bits wide.
341 1.2 matt */
342 1.2 matt if ((devdisr & DEVDISR_PCI2) &&
343 1.2 matt ((devdisr & DEVDISR_PCI1) || (pordevsr & PORDEVSR_PCI32))) {
344 1.2 matt gpiocr |= GPIOCR_PCIOUT;
345 1.2 matt gpiocr |= GPIOCR_PCIIN;
346 1.2 matt outmask |= 0x00ff0000;
347 1.2 matt inmask |= 0x00ff0000;
348 1.2 matt opins += 8;
349 1.2 matt ipins += 8;
350 1.2 matt }
351 1.2 matt if (devdisr & DEVDISR_TSEC2) {
352 1.2 matt gpiocr |= GPIOCR_TX2;
353 1.2 matt gpiocr |= GPIOCR_RX2;
354 1.2 matt outmask |= 0xff000000;
355 1.2 matt inmask |= 0xff000000;
356 1.2 matt opins += 8;
357 1.2 matt ipins += 8;
358 1.2 matt }
359 1.2 matt if (svr != (SVR_MPC8555v1 >> 16)) {
360 1.2 matt gpiocr |= GPIOCR_GPOUT;
361 1.2 matt outmask |= 0x000000ff;
362 1.2 matt opins += 8;
363 1.2 matt }
364 1.2 matt #if 1
365 1.2 matt aprint_normal_dev(self, "GPIOCR: %#x\n", gpiocr);
366 1.2 matt #else
367 1.2 matt bus_space_write_4(bst, bsh, GPIOCR, gpiocr);
368 1.2 matt #endif
369 1.2 matt
370 1.2 matt /*
371 1.2 matt * Create GPIO pin groups
372 1.2 matt */
373 1.2 matt aprint_normal_dev(self, "%zu input pins, %zu output pins\n",
374 1.2 matt ipins, opins);
375 1.2 matt
376 1.2 matt if (inmask)
377 1.6 matt pq3gpio_group_create(self, bst, bsh, GPINDR, inmask,
378 1.6 matt GPIO_PIN_INPUT, pq3gpio_null_pin_ctl);
379 1.2 matt if (outmask)
380 1.6 matt pq3gpio_group_create(self, bst, bsh, GPOUTDR, outmask,
381 1.6 matt GPIO_PIN_OUTPUT, pq3gpio_null_pin_ctl);
382 1.2 matt }
383 1.2 matt #endif /* MPC8548 */
384 1.2 matt
385 1.8 matt #ifdef P1025
386 1.8 matt static void
387 1.8 matt pq3gpio_p1025_attach(device_t self, bus_space_tag_t bst,
388 1.8 matt bus_space_handle_t bsh, u_int svr)
389 1.8 matt {
390 1.8 matt static const uint32_t gpio2pmuxcr_map[][4] = {
391 1.8 matt { 0, __BIT(12), 0, PMUXCR_SDHC_WP },
392 1.8 matt { __BIT(15), __BIT(8), 0, PMUXCR_USB1 },
393 1.8 matt { __BITS(14,4)|__BIT(16)|__BITS(27,17)|__BIT(30),
394 1.8 matt __BIT(1)|__BITS(3,2), 0, PMUXCR_QE0 },
395 1.8 matt { __BITS(3,1), 0, 0, PMUXCR_QE3 },
396 1.8 matt { 0, __BITS(17,14), 0, PMUXCR_QE8 },
397 1.8 matt { __BIT(29), __BITS(19,18), 0, PMUXCR_QE9 },
398 1.8 matt { 0, __BITS(22,21), 0, PMUXCR_QE10 },
399 1.8 matt { 0, __BITS(28,23), 0, PMUXCR_QE11 },
400 1.8 matt { 0, __BIT(20), 0, PMUXCR_QE12 },
401 1.8 matt };
402 1.8 matt
403 1.8 matt uint32_t pinmask[3] = {
404 1.8 matt 0xffffffff, 0xffffffff, 0xffffffff
405 1.8 matt }; /* assume all bits are valid */
406 1.8 matt const uint32_t pmuxcr = cpu_read_4(GLOBAL_BASE + PMUXCR);
407 1.8 matt for (size_t i = 0; i < __arraycount(gpio2pmuxcr_map); i++) {
408 1.8 matt if (pmuxcr & gpio2pmuxcr_map[i][3]) {
409 1.8 matt pinmask[0] &= ~gpio2pmuxcr_map[i][0];
410 1.8 matt pinmask[1] &= ~gpio2pmuxcr_map[i][1];
411 1.8 matt pinmask[2] &= ~gpio2pmuxcr_map[i][2];
412 1.8 matt }
413 1.8 matt }
414 1.8 matt
415 1.8 matt /*
416 1.8 matt * Create GPIO pin groups
417 1.8 matt */
418 1.8 matt for (size_t i = 0; i < 3; i++) {
419 1.8 matt if (pinmask[i]) {
420 1.8 matt bus_space_handle_t bsh2;
421 1.8 matt aprint_normal_dev(self,
422 1.8 matt "gpio[%c]: %zu input/output/opendrain pins\n",
423 1.8 matt "abc"[i], popcount32(pinmask[i]));
424 1.8 matt bus_space_subregion(bst, bsh, CPBASE(i), 0x20, &bsh2);
425 1.8 matt pq3gpio_group_create(self, bst, bsh2, CPDAT,
426 1.8 matt pinmask[0],
427 1.8 matt GPIO_PIN_INPUT|GPIO_PIN_OUTPUT|GPIO_PIN_OPENDRAIN,
428 1.8 matt pq3gpio_pin_ctl);
429 1.8 matt }
430 1.8 matt }
431 1.8 matt }
432 1.8 matt #endif /* P1025 */
433 1.8 matt
434 1.3 matt #ifdef P2020
435 1.3 matt static void
436 1.3 matt pq3gpio_p20x0_attach(device_t self, bus_space_tag_t bst,
437 1.3 matt bus_space_handle_t bsh, u_int svr)
438 1.3 matt {
439 1.3 matt static const uint32_t gpio2pmuxcr_map[][2] = {
440 1.5 matt { __BIT(8), PMUXCR_SDHC_CD },
441 1.5 matt { __BIT(9), PMUXCR_SDHC_WP },
442 1.5 matt /*
443 1.5 matt * These are really two bits but the low bit MBZ so we ignore
444 1.5 matt * it.
445 1.5 matt */
446 1.5 matt { __BIT(10), PMUXCR_TSEC3_TS },
447 1.5 matt { __BIT(11), PMUXCR_TSEC3_TS },
448 1.3 matt };
449 1.3 matt
450 1.5 matt uint32_t pinmask = 0xffff0000; /* assume all bits are valid */
451 1.5 matt size_t pincnt = 16;
452 1.6 matt const uint32_t pmuxcr = cpu_read_4(GLOBAL_BASE + PMUXCR);
453 1.3 matt for (size_t i = 0; i < __arraycount(gpio2pmuxcr_map); i++) {
454 1.6 matt if (pmuxcr & gpio2pmuxcr_map[i][1]) {
455 1.3 matt pinmask &= ~gpio2pmuxcr_map[i][0];
456 1.3 matt pincnt--;
457 1.3 matt }
458 1.3 matt }
459 1.3 matt
460 1.3 matt /*
461 1.3 matt * Create GPIO pin groups
462 1.3 matt */
463 1.6 matt aprint_normal_dev(self, "%zu input/output/opendrain pins\n",
464 1.5 matt pincnt);
465 1.5 matt pq3gpio_group_create(self, bst, bsh, GPDAT, pinmask,
466 1.6 matt GPIO_PIN_INPUT|GPIO_PIN_OUTPUT|GPIO_PIN_OPENDRAIN,
467 1.6 matt pq3gpio_pin_ctl);
468 1.3 matt }
469 1.3 matt #endif /* P2020 */
470 1.3 matt
471 1.11 nonaka #ifdef P1023
472 1.11 nonaka static void
473 1.11 nonaka pq3gpio_p1023_attach(device_t self, bus_space_tag_t bst,
474 1.11 nonaka bus_space_handle_t bsh, u_int svr)
475 1.11 nonaka {
476 1.11 nonaka static const uint32_t gpio2pmuxcr2_map[][3] = {
477 1.11 nonaka { __PPCBITS( 0, 1), __PPCBITS( 0, 1), 0 }, /* GPIO_1 */
478 1.11 nonaka { __PPCBIT(2), __PPCBITS( 2, 3), 0 }, /* GPUO_2 */
479 1.11 nonaka { __PPCBITS( 4, 5), __PPCBITS( 4, 5), 0 }, /* GPUO_3 */
480 1.11 nonaka { __PPCBITS( 6, 7), __PPCBITS( 6, 7), 0 }, /* GPUO_4 */
481 1.11 nonaka { __PPCBITS( 8, 9), __PPCBITS( 8, 9), 0 }, /* GPUO_5 */
482 1.11 nonaka { __PPCBITS(10,11), __PPCBITS(10,11), 0 }, /* GPUO_6 */
483 1.11 nonaka { __PPCBITS(12,13), __PPCBITS(12,13), 0 }, /* GPUO_7 */
484 1.11 nonaka { __PPCBITS(14,15), __PPCBITS(14,15), 0 }, /* GPUO_8 */
485 1.11 nonaka { __PPCBIT(3), __PPCBITS(18,19), 0 }, /* GPUO_9 */
486 1.11 nonaka };
487 1.11 nonaka
488 1.11 nonaka uint32_t pinmask = 0xffff0000; /* assume all bits are valid */
489 1.11 nonaka size_t pincnt = 16;
490 1.11 nonaka const uint32_t pmuxcr2 = cpu_read_4(GLOBAL_BASE + PMUXCR2);
491 1.11 nonaka for (size_t i = 0; i < __arraycount(gpio2pmuxcr2_map); i++) {
492 1.11 nonaka const uint32_t *map = gpio2pmuxcr2_map[i];
493 1.11 nonaka if ((pmuxcr2 & map[1]) != map[2]) {
494 1.11 nonaka pinmask &= ~map[0];
495 1.11 nonaka pincnt--;
496 1.11 nonaka }
497 1.11 nonaka }
498 1.11 nonaka
499 1.11 nonaka /*
500 1.11 nonaka * Create GPIO pin groups
501 1.11 nonaka */
502 1.11 nonaka aprint_normal_dev(self, "%zu input/output/opendrain pins\n", pincnt);
503 1.11 nonaka pq3gpio_group_create(self, bst, bsh, GPDAT, pinmask,
504 1.11 nonaka GPIO_PIN_INPUT|GPIO_PIN_OUTPUT|GPIO_PIN_OPENDRAIN, pq3gpio_pin_ctl);
505 1.11 nonaka }
506 1.11 nonaka #endif /* P1023 */
507 1.11 nonaka
508 1.6 matt static const struct pq3gpio_svr_info {
509 1.6 matt uint16_t si_svr;
510 1.6 matt void (*si_attach)(device_t, bus_space_tag_t, bus_space_handle_t, u_int);
511 1.6 matt bus_addr_t si_base;
512 1.6 matt bus_size_t si_size;
513 1.2 matt } pq3gpio_svrs[] = {
514 1.2 matt #ifdef MPC8548
515 1.6 matt { SVR_MPC8548v2 >> 16, pq3gpio_mpc8548_attach,
516 1.6 matt GLOBAL_BASE, GLOBAL_SIZE },
517 1.2 matt #endif
518 1.2 matt #ifdef MPC8555
519 1.6 matt { SVR_MPC8555v1 >> 16, pq3gpio_mpc8548_attach,
520 1.6 matt GLOBAL_BASE, GLOBAL_SIZE },
521 1.2 matt #endif
522 1.2 matt #ifdef MPC8544
523 1.6 matt { SVR_MPC8544v1 >> 16, pq3gpio_mpc8544_attach,
524 1.6 matt GLOBAL_BASE, GLOBAL_SIZE },
525 1.2 matt #endif
526 1.2 matt #ifdef MPC8536
527 1.6 matt { SVR_MPC8536v1 >> 16, pq3gpio_mpc8536_attach,
528 1.6 matt GPIO_BASE, GPIO_SIZE },
529 1.2 matt #endif
530 1.8 matt #ifdef P1025
531 1.8 matt { SVR_P1025v1 >> 16, pq3gpio_p1025_attach,
532 1.8 matt GLOBAL_BASE, GLOBAL_SIZE },
533 1.8 matt #endif
534 1.3 matt #ifdef P2020
535 1.6 matt { SVR_P2020v2 >> 16, pq3gpio_p20x0_attach,
536 1.6 matt GPIO_BASE, GPIO_SIZE },
537 1.3 matt #endif
538 1.11 nonaka #ifdef P1023
539 1.11 nonaka { SVR_P1023v1 >> 16, pq3gpio_p1023_attach,
540 1.11 nonaka GPIO_BASE, GPIO_SIZE },
541 1.11 nonaka #endif
542 1.2 matt };
543 1.2 matt
544 1.2 matt void
545 1.2 matt pq3gpio_attach(device_t parent, device_t self, void *aux)
546 1.2 matt {
547 1.2 matt struct mainbus_attach_args * const ma = aux;
548 1.2 matt bus_space_tag_t bst = ma->ma_memt;
549 1.2 matt bus_space_handle_t bsh;
550 1.2 matt
551 1.2 matt const uint16_t svr = e500_get_svr();
552 1.2 matt for (u_int i = 0; i < __arraycount(pq3gpio_svrs); i++) {
553 1.6 matt const struct pq3gpio_svr_info * const si = &pq3gpio_svrs[i];
554 1.6 matt if (si->si_svr == svr) {
555 1.6 matt int error = bus_space_map(bst, si->si_base,
556 1.6 matt si->si_size, 0, &bsh);
557 1.6 matt if (error) {
558 1.6 matt aprint_error_dev(self,
559 1.6 matt "can't map global registers for gpio: %d\n",
560 1.6 matt error);
561 1.6 matt return;
562 1.6 matt }
563 1.6 matt (*si->si_attach)(self, bst, bsh, svr);
564 1.2 matt return;
565 1.2 matt }
566 1.2 matt }
567 1.2 matt aprint_normal_dev(self,
568 1.2 matt "0 input groups, 0 output groups (unknown svr %#x)\n",
569 1.2 matt svr);
570 1.2 matt }
571