Annotation of sys/arch/armish/dev/i80321_mainbus.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: i80321_mainbus.c,v 1.10 2006/09/15 23:36:11 drahn Exp $ */
2: /* $NetBSD: i80321_mainbus.c,v 1.16 2005/12/15 01:44:00 briggs Exp $ */
3:
4: /*
5: * Copyright (c) 2001, 2002 Wasabi Systems, Inc.
6: * All rights reserved.
7: *
8: * Written by Jason R. Thorpe for Wasabi Systems, Inc.
9: *
10: * Redistribution and use in source and binary forms, with or without
11: * modification, are permitted provided that the following conditions
12: * are met:
13: * 1. Redistributions of source code must retain the above copyright
14: * notice, this list of conditions and the following disclaimer.
15: * 2. Redistributions in binary form must reproduce the above copyright
16: * notice, this list of conditions and the following disclaimer in the
17: * documentation and/or other materials provided with the distribution.
18: * 3. All advertising materials mentioning features or use of this software
19: * must display the following acknowledgement:
20: * This product includes software developed for the NetBSD Project by
21: * Wasabi Systems, Inc.
22: * 4. The name of Wasabi Systems, Inc. may not be used to endorse
23: * or promote products derived from this software without specific prior
24: * written permission.
25: *
26: * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
27: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
30: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36: * POSSIBILITY OF SUCH DAMAGE.
37: */
38:
39: /*
40: * IQ80321 front-end for the i80321 I/O Processor. We take care
41: * of setting up the i80321 memory map, PCI interrupt routing, etc.,
42: * which are all specific to the board the i80321 is wired up to.
43: */
44:
45: #include <sys/param.h>
46: #include <sys/systm.h>
47: #include <sys/device.h>
48: #include <sys/gpio.h>
49:
50: #include <machine/bus.h>
51:
52: #include <arm/mainbus/mainbus.h>
53: #include <armish/dev/iq80321reg.h>
54: #include <armish/dev/iq80321var.h>
55:
56: #include <arm/xscale/i80321reg.h>
57: #include <arm/xscale/i80321var.h>
58:
59: #include <dev/pci/pcireg.h>
60: #include <dev/pci/pcidevs.h>
61: #include <dev/gpio/gpiovar.h>
62:
63: #include "gpio.h"
64:
65: int i80321_mainbus_match(struct device *, void *, void *);
66: void i80321_mainbus_attach(struct device *, struct device *, void *);
67:
68: void i80321_gpio_init (struct i80321_softc *sc);
69: int i80321_gpio_pin_read (void *, int);
70: void i80321_gpio_pin_write (void *, int, int);
71: void i80321_gpio_pin_ctl (void *, int, int);
72:
73: /* XXX */
74: #define I80219_REG_GPOE 0x7C4
75: #define I80219_REG_GPID 0x7C8
76: #define I80219_REG_GPOD 0x7CC
77:
78: struct cfattach iopxs_mainbus_ca = {
79: sizeof(struct i80321_softc), i80321_mainbus_match,
80: i80321_mainbus_attach
81: };
82:
83: struct cfdriver iopxs_cd = {
84: NULL, "iopxs", DV_DULL
85: };
86:
87:
88: /* There can be only one. */
89: int i80321_mainbus_found;
90:
91: int
92: i80321_mainbus_match(struct device *parent, void *match, void *aux)
93: {
94: struct mainbus_attach_args *ma = aux;
95: struct cfdata *cf = match;
96:
97: if (i80321_mainbus_found)
98: return (0);
99:
100: if (strcmp(cf->cf_driver->cd_name, ma->ma_name) == 0)
101: return (1);
102:
103: return (0);
104: }
105:
106: /* XXX */
107: bus_space_handle_t sc_pld_sh;
108:
109: void
110: i80321_mainbus_attach(struct device *parent, struct device *self, void *aux)
111: {
112: struct i80321_softc *sc = (void *) self;
113: struct gpiobus_attach_args gba;
114: pcireg_t b0u, b0l, b1u, b1l;
115: paddr_t memstart;
116: psize_t memsize;
117: pcireg_t atumembase;
118: pcireg_t atuiobase;
119:
120: i80321_mainbus_found = 1;
121:
122: /*
123: * Fill in the space tag for the i80321's own devices,
124: * and hand-craft the space handle for it (the device
125: * was mapped during early bootstrap).
126: */
127: i80321_bs_init(&i80321_bs_tag, sc);
128: sc->sc_st = &i80321_bs_tag;
129: if (bus_space_map(sc->sc_st, VERDE_PMMR_BASE, VERDE_PMMR_SIZE, 0,
130: &sc->sc_sh))
131: panic("%s: unable to map VERDE registers", sc->sc_dev.dv_xname);
132:
133: /*
134: * Slice off a subregion for the Memory Controller -- we need it
135: * here in order read the memory size.
136: */
137: if (bus_space_subregion(sc->sc_st, sc->sc_sh, VERDE_MCU_BASE,
138: VERDE_MCU_SIZE, &sc->sc_mcu_sh))
139: panic("%s: unable to subregion MCU registers",
140: sc->sc_dev.dv_xname);
141:
142: if (bus_space_subregion(sc->sc_st, sc->sc_sh, VERDE_ATU_BASE,
143: VERDE_ATU_SIZE, &sc->sc_atu_sh))
144: panic("%s: unable to subregion ATU registers",
145: sc->sc_dev.dv_xname);
146:
147: if(bus_space_map(sc->sc_st, VERDE_OUT_XLATE_IO_WIN0_BASE,
148: VERDE_OUT_XLATE_IO_WIN_SIZE, 0, &sc->sc_io_sh))
149: panic("%s: unable to map IOW registers", sc->sc_dev.dv_xname);
150:
151: // printf ("PIRSR %x\n", bus_space_read_4(sc->sc_st, sc->sc_sh, ICU_PIRSR));
152:
153: // printf("mapping bus io to %x - %x\n", sc->sc_io_sh, sc->sc_io_sh+VERDE_OUT_XLATE_IO_WIN_SIZE);
154:
155: /*
156: * Initialize the interrupt part of our PCI chipset tag.
157: */
158: iq80321_pci_init(&sc->sc_pci_chipset, sc);
159:
160: /* Initialize the PCI chipset tag. */
161: i80321_pci_init(&sc->sc_pci_chipset, sc);
162:
163: iq80321_pci_init2(&sc->sc_pci_chipset, sc);
164:
165: atumembase = bus_space_read_4(sc->sc_st, sc->sc_atu_sh,
166: PCI_MAPREG_START + 0x08);
167: atuiobase = bus_space_read_4(sc->sc_st, sc->sc_atu_sh,
168: ATU_OIOWTVR);
169:
170: sc->sc_membus_space.bus_base = PCI_MAPREG_MEM_ADDR(atumembase);
171: sc->sc_membus_space.bus_size = 0x04000000;
172: sc->sc_iobus_space.bus_base = PCI_MAPREG_IO_ADDR(atuiobase);
173: sc->sc_iobus_space.bus_size = 0x00010000;
174: pci_addr_fixup(sc, 2/*XXX*/);
175:
176: /*
177: * Check the configuration of the ATU to see if another BIOS
178: * has configured us. If a PC BIOS didn't configure us, then:
179: * IQ80321: BAR0 00000000.0000000c BAR1 is 00000000.8000000c.
180: * IQ31244: BAR0 00000000.00000004 BAR1 is 00000000.0000000c.
181: * If a BIOS has configured us, at least one of those should be
182: * different. This is pretty fragile, but it's not clear what
183: * would work better.
184: */
185: b0l = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, PCI_MAPREG_START+0x0);
186: b0u = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, PCI_MAPREG_START+0x4);
187: b1l = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, PCI_MAPREG_START+0x8);
188: b1u = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, PCI_MAPREG_START+0xc);
189: b0l &= PCI_MAPREG_MEM_ADDR_MASK;
190: b0u &= PCI_MAPREG_MEM_ADDR_MASK;
191: b1l &= PCI_MAPREG_MEM_ADDR_MASK;
192: b1u &= PCI_MAPREG_MEM_ADDR_MASK;
193:
194: printf(": i80321 I/O Processor\n");
195:
196: i80321_sdram_bounds(sc->sc_st, sc->sc_mcu_sh, &memstart, &memsize);
197:
198: /*
199: * We set up the Inbound Windows as follows:
200: *
201: * 0 Access to i80321 PMMRs
202: *
203: * 1 Reserve space for private devices
204: *
205: * 2 RAM access
206: *
207: * 3 Unused.
208: *
209: * This chunk needs to be customized for each IOP321 application.
210: */
211:
212: atumembase = bus_space_read_4(sc->sc_st, sc->sc_atu_sh,
213: PCI_MAPREG_START + 0x08);
214:
215: if (atumembase == 0x8000000c) {
216: /* iodata: intel std config */
217:
218: /* map device registers */
219: sc->sc_iwin[0].iwin_base_lo = 0x00000004;
220: sc->sc_iwin[0].iwin_base_hi = 0x00000000;
221: sc->sc_iwin[0].iwin_xlate = 0xff000000;
222: sc->sc_iwin[0].iwin_size = 0x01000000;
223:
224: /* Map PCI:Local 1:1. */
225: sc->sc_iwin[1].iwin_base_lo = VERDE_OUT_XLATE_MEM_WIN0_BASE |
226: PCI_MAPREG_MEM_PREFETCHABLE_MASK |
227: PCI_MAPREG_MEM_TYPE_64BIT;
228: sc->sc_iwin[1].iwin_base_hi = 0;
229:
230: sc->sc_iwin[1].iwin_xlate = VERDE_OUT_XLATE_MEM_WIN0_BASE;
231: sc->sc_iwin[1].iwin_size = VERDE_OUT_XLATE_MEM_WIN_SIZE;
232:
233:
234: sc->sc_iwin[2].iwin_base_lo = memstart |
235: PCI_MAPREG_MEM_PREFETCHABLE_MASK |
236: PCI_MAPREG_MEM_TYPE_64BIT;
237: sc->sc_iwin[2].iwin_base_hi = 0;
238:
239: sc->sc_iwin[2].iwin_xlate = memstart;
240: sc->sc_iwin[2].iwin_size = memsize;
241:
242: sc->sc_iwin[3].iwin_base_lo = 0;
243: #if 0
244: PCI_MAPREG_MEM_PREFETCHABLE_MASK |
245: PCI_MAPREG_MEM_TYPE_64BIT;
246: #endif
247:
248: sc->sc_iwin[3].iwin_base_hi = 0;
249: sc->sc_iwin[3].iwin_xlate = 0;
250: sc->sc_iwin[3].iwin_size = 0;
251:
252: /*
253: * We set up the Outbound Windows as follows:
254: *
255: * 0 Access to private PCI space.
256: *
257: * 1 Unused.
258: */
259: sc->sc_owin[0].owin_xlate_lo =
260: PCI_MAPREG_MEM_ADDR(sc->sc_iwin[1].iwin_base_lo);
261: sc->sc_owin[0].owin_xlate_hi = sc->sc_iwin[1].iwin_base_hi;
262:
263: /*
264: * Set the Secondary Outbound I/O window to map
265: * to PCI address 0 for all 64K of the I/O space.
266: */
267: sc->sc_ioout_xlate = 0x90000000;
268: sc->sc_ioout_xlate_offset = 0x1000;
269: } else if (atumembase == 0x40000004) {
270: /* thecus */
271:
272: /* dont map device registers */
273: sc->sc_iwin[0].iwin_base_lo = 0;
274: sc->sc_iwin[0].iwin_base_hi = 0;
275: sc->sc_iwin[0].iwin_xlate = 0;
276: sc->sc_iwin[0].iwin_size = 0;
277:
278: /* Map PCI:Local 1:1. */
279: sc->sc_iwin[1].iwin_base_lo = 0x40000000 |
280: #if 0
281: PCI_MAPREG_MEM_PREFETCHABLE_MASK |
282: PCI_MAPREG_MEM_TYPE_64BIT;
283: #else
284: 0;
285: #endif
286: sc->sc_iwin[1].iwin_base_hi = 0;
287:
288: sc->sc_iwin[1].iwin_xlate = 0;
289: sc->sc_iwin[1].iwin_size = 0x08000000;
290:
291: sc->sc_iwin[2].iwin_base_lo = 0 |
292: PCI_MAPREG_MEM_PREFETCHABLE_MASK |
293: PCI_MAPREG_MEM_TYPE_64BIT;
294: sc->sc_iwin[2].iwin_base_hi = 0;
295:
296: sc->sc_iwin[2].iwin_xlate = memstart;
297: sc->sc_iwin[2].iwin_size = memsize;
298:
299: sc->sc_iwin[3].iwin_base_lo = 0;
300: sc->sc_iwin[3].iwin_base_hi = 0;
301: sc->sc_iwin[3].iwin_xlate = 0;
302: sc->sc_iwin[3].iwin_size = 0;
303:
304: /*
305: * We set up the Outbound Windows as follows:
306: *
307: * 0 Access to private PCI space.
308: *
309: * 1 Unused.
310: */
311: sc->sc_owin[0].owin_xlate_lo =
312: PCI_MAPREG_MEM_ADDR(sc->sc_iwin[1].iwin_base_lo);
313: sc->sc_owin[0].owin_xlate_hi = sc->sc_iwin[1].iwin_base_hi;
314:
315: /*
316: * Set the Secondary Outbound I/O window to map
317: * to PCI address 0 for all 64K of the I/O space.
318: */
319: sc->sc_ioout_xlate = 0x90000000;
320: sc->sc_ioout_xlate_offset = 0x1000;
321:
322: }
323:
324: i80321_attach(sc);
325:
326: i80321_gpio_init (sc);
327:
328: /* if 80219 */ {
329: gba.gba_name = "gpio";
330: gba.gba_gc = &sc->sc_gpio_gc;
331: gba.gba_pins = sc->sc_gpio_pins;
332: gba.gba_npins = I80219_GPIO_NPINS;
333: #if NGPIO > 0
334: config_found(&sc->sc_dev, &gba, gpiobus_print);
335: #endif
336: }
337: {
338: #define I80321_PLD 0xfe8d0000UL
339: #define I80321_PLD_SIZE 0x1000
340:
341: #define PLD_LED 0
342: #define PLD_PLED 1
343: #define PLD_BTN 2
344: #define PLD_INTEN 3
345: #define PLD_PWRMNG 4
346:
347: #if 0
348: uint8_t val;
349: #endif
350:
351: if (bus_space_map(sc->sc_st, I80321_PLD, I80321_PLD_SIZE, 0,
352: /* &sc->sc_pld_sh */ &sc_pld_sh))
353: panic("%s: unable to map PLD registers",
354: sc->sc_dev.dv_xname);
355:
356: #if 0
357: printf("dlectl %x\n", bus_space_read_1(sc->sc_st, sc_pld_sh,
358: PLD_LED));
359: val = bus_space_read_1(sc->sc_st, sc_pld_sh, PLD_LED);
360: val |= 0x3;
361: bus_space_write_1(sc->sc_st, sc_pld_sh, PLD_LED, val);
362: printf("dlectl %x\n", bus_space_read_1(sc->sc_st, sc_pld_sh,
363: PLD_PLED));
364: printf("dlectl %x\n", bus_space_read_1(sc->sc_st, sc_pld_sh,
365: PLD_BTN));
366: #endif
367: }
368: {
369: extern struct cfdriver pcaled_cd;
370: void pcaled_gpio_pin_write(void *arg, int pin, int value);
371: if (pcaled_cd.cd_ndevs > 0 && pcaled_cd.cd_devs[0] != NULL) {
372: pcaled_gpio_pin_write(pcaled_cd.cd_devs[0], 13, 0);
373: pcaled_gpio_pin_write(pcaled_cd.cd_devs[0], 14, 0);
374: }
375: }
376: }
377:
378: void
379: i80321_gpio_init (struct i80321_softc *sc)
380: {
381: int i;
382: for (i = 0; i < I80219_GPIO_NPINS; i++) {
383: sc->sc_gpio_pins[i].pin_num = i;
384: sc->sc_gpio_pins[i].pin_caps = GPIO_PIN_INPUT | GPIO_PIN_OUTPUT;
385:
386: sc->sc_gpio_pins[i].pin_flags =
387: bus_space_read_4(sc->sc_st, sc->sc_sh, I80219_REG_GPOE) &
388: (1 << i) ? GPIO_PIN_INPUT : GPIO_PIN_OUTPUT;
389: sc->sc_gpio_pins[i].pin_state = i80321_gpio_pin_read(sc, i) ?
390: GPIO_PIN_HIGH : GPIO_PIN_LOW;
391: }
392: sc->sc_gpio_gc.gp_cookie = sc;
393: sc->sc_gpio_gc.gp_pin_read = i80321_gpio_pin_read;
394: sc->sc_gpio_gc.gp_pin_write = i80321_gpio_pin_write;
395: sc->sc_gpio_gc.gp_pin_ctl = i80321_gpio_pin_ctl;
396: }
397:
398: int
399: i80321_gpio_pin_read (void *arg, int pin)
400: {
401: struct i80321_softc *sc = arg;
402: u_int32_t regval;
403: int reg;
404:
405: if (bus_space_read_4(sc->sc_st, sc->sc_sh, I80219_REG_GPOE)
406: & (1 << pin)) {
407: reg = I80219_REG_GPID;
408: } else {
409: reg = I80219_REG_GPOD;
410: }
411: regval = bus_space_read_4(sc->sc_st, sc->sc_sh, reg);
412: #if 0
413: printf("read %x gpio %x\n", reg);
414: printf("gpio state %x %x %x\n",
415: bus_space_read_4(sc->sc_st, sc->sc_sh, I80219_REG_GPID),
416: bus_space_read_4(sc->sc_st, sc->sc_sh, I80219_REG_GPOD),
417: bus_space_read_4(sc->sc_st, sc->sc_sh, I80219_REG_GPOE));
418: #endif
419: return ((regval >> pin) & 1);
420: }
421:
422: void
423: i80321_gpio_pin_write (void *arg, int pin, int value)
424: {
425: struct i80321_softc *sc = arg;
426: u_int32_t regval;
427:
428: regval = bus_space_read_4(sc->sc_st, sc->sc_sh, I80219_REG_GPOD);
429: regval = (regval & ~(1 << pin)) | ((value & 1) << pin);
430: #if 0
431: printf("writing %x to gpioO %x\n", regval);
432: #endif
433: bus_space_write_4(sc->sc_st, sc->sc_sh, I80219_REG_GPOD, regval);
434: }
435: void
436: i80321_gpio_pin_ctl (void *arg, int pin, int flags)
437: {
438: struct i80321_softc *sc = arg;
439: u_int32_t regval;
440: int value = (flags == GPIO_PIN_INPUT) ? 1 : 0;
441:
442: regval = bus_space_read_4(sc->sc_st, sc->sc_sh, I80219_REG_GPOE);
443: regval = (regval & ~(1 << pin)) | ((value & 1) << pin);
444: #if 0
445: printf("writing %x to ctl %x\n", regval, value);
446: #endif
447: bus_space_write_4(sc->sc_st, sc->sc_sh, I80219_REG_GPOE, regval);
448: }
449:
450:
451: void board_reset(void); /* XXX */
452: void
453: board_reset()
454: {
455: struct i80321_softc *sc = i80321_softc;
456: uint32_t val;
457:
458: printf("attempting reset\n");
459: val = bus_space_read_4(sc->sc_st, sc->sc_sh, 0x7CC);
460: val &= ~0x10;
461: bus_space_write_4(sc->sc_st, sc->sc_sh, 0x7CC, val);
462: val = bus_space_read_4(sc->sc_st, sc->sc_sh, 0x7C4);
463: val &= ~0x10;
464: bus_space_write_4(sc->sc_st, sc->sc_sh, 0x7C4, val);
465:
466: bus_space_write_1(sc->sc_st, sc_pld_sh, PLD_PWRMNG, 0x2);
467:
468: }
469:
470: void board_powerdown(void); /* XXX */
471: void
472: board_powerdown(void)
473: {
474: void pcaled_gpio_pin_write(void *arg, int pin, int value);
475: extern struct cfdriver pcaled_cd;
476:
477: if (pcaled_cd.cd_ndevs > 0 && pcaled_cd.cd_devs[0] != NULL) {
478: pcaled_gpio_pin_write(pcaled_cd.cd_devs[0], 8, 1);
479: delay(500000);
480: }
481: }
CVSweb