Annotation of sys/arch/armish/dev/i80321_mainbus.c, Revision 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