1178173Simp/* $NetBSD: gt_pci.c,v 1.4 2003/07/15 00:24:54 lukem Exp $ */ 2178173Simp 3178173Simp/*- 4178173Simp * Copyright (c) 2001, 2002 Wasabi Systems, Inc. 5178173Simp * All rights reserved. 6178173Simp * 7178173Simp * Written by Jason R. Thorpe for Wasabi Systems, Inc. 8178173Simp * 9178173Simp * Redistribution and use in source and binary forms, with or without 10178173Simp * modification, are permitted provided that the following conditions 11178173Simp * are met: 12178173Simp * 1. Redistributions of source code must retain the above copyright 13178173Simp * notice, this list of conditions and the following disclaimer. 14178173Simp * 2. Redistributions in binary form must reproduce the above copyright 15178173Simp * notice, this list of conditions and the following disclaimer in the 16178173Simp * documentation and/or other materials provided with the distribution. 17178173Simp * 3. All advertising materials mentioning features or use of this software 18178173Simp * must display the following acknowledgement: 19178173Simp * This product includes software developed for the NetBSD Project by 20178173Simp * Wasabi Systems, Inc. 21178173Simp * 4. The name of Wasabi Systems, Inc. may not be used to endorse 22178173Simp * or promote products derived from this software without specific prior 23178173Simp * written permission. 24178173Simp * 25178173Simp * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND 26178173Simp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 27178173Simp * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 28178173Simp * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC 29178173Simp * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 30178173Simp * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 31178173Simp * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 32178173Simp * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 33178173Simp * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 34178173Simp * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 35178173Simp * POSSIBILITY OF SUCH DAMAGE. 36178173Simp */ 37178173Simp 38178173Simp/* 39178173Simp * PCI configuration support for gt I/O Processor chip. 40178173Simp */ 41178173Simp 42178173Simp#include <sys/cdefs.h> 43178173Simp__FBSDID("$FreeBSD: releng/11.0/sys/mips/malta/gt_pci.c 302287 2016-06-29 23:33:44Z gonzo $"); 44178173Simp 45178173Simp#include <sys/param.h> 46178173Simp#include <sys/systm.h> 47178173Simp 48178173Simp#include <sys/bus.h> 49254983Sgonzo#include <sys/endian.h> 50178173Simp#include <sys/interrupt.h> 51178173Simp#include <sys/malloc.h> 52178173Simp#include <sys/kernel.h> 53178173Simp#include <sys/module.h> 54178173Simp#include <sys/rman.h> 55178173Simp 56178173Simp#include <vm/vm.h> 57178173Simp#include <vm/pmap.h> 58178173Simp#include <vm/vm_extern.h> 59178173Simp 60178173Simp#include <machine/bus.h> 61178173Simp#include <machine/cpu.h> 62178173Simp 63182901Sgonzo#include <mips/malta/maltareg.h> 64178173Simp 65182901Sgonzo#include <mips/malta/gtreg.h> 66182901Sgonzo#include <mips/malta/gtvar.h> 67178173Simp 68178173Simp#include <isa/isareg.h> 69178173Simp#include <dev/ic/i8259.h> 70178173Simp 71178173Simp#include <dev/pci/pcireg.h> 72178173Simp#include <dev/pci/pcivar.h> 73178173Simp 74178173Simp#include <dev/pci/pcib_private.h> 75178173Simp#include "pcib_if.h" 76178173Simp 77255083Sgonzo#include <mips/malta/gt_pci_bus_space.h> 78178173Simp 79178173Simp#define ICU_LEN 16 /* number of ISA IRQs */ 80178173Simp 81178173Simp/* 82178173Simp * XXX: These defines are from NetBSD's <dev/ic/i8259reg.h>. Respective file 83178173Simp * from FreeBSD src tree <dev/ic/i8259.h> lacks some definitions. 84178173Simp */ 85178173Simp#define PIC_OCW1 1 86178173Simp#define PIC_OCW2 0 87178173Simp#define PIC_OCW3 0 88178173Simp 89178173Simp#define OCW2_SELECT 0 90178173Simp#define OCW2_ILS(x) ((x) << 0) /* interrupt level select */ 91178173Simp 92178173Simp#define OCW3_POLL_IRQ(x) ((x) & 0x7f) 93178173Simp#define OCW3_POLL_PENDING (1U << 7) 94178173Simp 95254983Sgonzo/* 96254983Sgonzo * Galileo controller's registers are LE so convert to then 97254983Sgonzo * to/from native byte order. We rely on boot loader or emulator 98254983Sgonzo * to set "swap bytes" configuration correctly for us 99254983Sgonzo */ 100254983Sgonzo#define GT_PCI_DATA(v) htole32((v)) 101254983Sgonzo#define GT_HOST_DATA(v) le32toh((v)) 102254983Sgonzo 103202035Simpstruct gt_pci_softc; 104202035Simp 105202035Simpstruct gt_pci_intr_cookie { 106202035Simp int irq; 107202035Simp struct gt_pci_softc *sc; 108202035Simp}; 109202035Simp 110178173Simpstruct gt_pci_softc { 111178173Simp device_t sc_dev; 112178173Simp bus_space_tag_t sc_st; 113178173Simp bus_space_handle_t sc_ioh_icu1; 114178173Simp bus_space_handle_t sc_ioh_icu2; 115178173Simp bus_space_handle_t sc_ioh_elcr; 116178173Simp 117178173Simp int sc_busno; 118178173Simp struct rman sc_mem_rman; 119178173Simp struct rman sc_io_rman; 120178173Simp struct rman sc_irq_rman; 121206837Sjmallett unsigned long sc_mem; 122206837Sjmallett bus_space_handle_t sc_io; 123178173Simp 124178173Simp struct resource *sc_irq; 125178173Simp struct intr_event *sc_eventstab[ICU_LEN]; 126202035Simp struct gt_pci_intr_cookie sc_intr_cookies[ICU_LEN]; 127178173Simp uint16_t sc_imask; 128178173Simp uint16_t sc_elcr; 129178173Simp 130178173Simp uint16_t sc_reserved; 131178173Simp 132178173Simp void *sc_ih; 133178173Simp}; 134178173Simp 135202035Simpstatic void gt_pci_set_icus(struct gt_pci_softc *); 136202035Simpstatic int gt_pci_intr(void *v); 137202035Simpstatic int gt_pci_probe(device_t); 138202035Simpstatic int gt_pci_attach(device_t); 139202035Simpstatic int gt_pci_activate_resource(device_t, device_t, int, int, 140202035Simp struct resource *); 141202035Simpstatic int gt_pci_setup_intr(device_t, device_t, struct resource *, 142202035Simp int, driver_filter_t *, driver_intr_t *, void *, void **); 143202035Simpstatic int gt_pci_teardown_intr(device_t, device_t, struct resource *, void*); 144202035Simpstatic int gt_pci_maxslots(device_t ); 145202035Simpstatic int gt_pci_conf_setup(struct gt_pci_softc *, int, int, int, int, 146202035Simp uint32_t *); 147202035Simpstatic uint32_t gt_pci_read_config(device_t, u_int, u_int, u_int, u_int, int); 148202035Simpstatic void gt_pci_write_config(device_t, u_int, u_int, u_int, u_int, 149202035Simp uint32_t, int); 150202035Simpstatic int gt_pci_route_interrupt(device_t pcib, device_t dev, int pin); 151202035Simpstatic struct resource * gt_pci_alloc_resource(device_t, device_t, int, 152294883Sjhibbits int *, rman_res_t, rman_res_t, rman_res_t, u_int); 153202035Simp 154178173Simpstatic void 155202035Simpgt_pci_mask_irq(void *source) 156202035Simp{ 157202035Simp struct gt_pci_intr_cookie *cookie = source; 158202035Simp struct gt_pci_softc *sc = cookie->sc; 159202035Simp int irq = cookie->irq; 160202035Simp 161202035Simp sc->sc_imask |= (1 << irq); 162202035Simp sc->sc_elcr |= (1 << irq); 163202035Simp 164202035Simp gt_pci_set_icus(sc); 165202035Simp} 166202035Simp 167202035Simpstatic void 168202035Simpgt_pci_unmask_irq(void *source) 169202035Simp{ 170202035Simp struct gt_pci_intr_cookie *cookie = source; 171202035Simp struct gt_pci_softc *sc = cookie->sc; 172202035Simp int irq = cookie->irq; 173202035Simp 174202035Simp /* Enable it, set trigger mode. */ 175202035Simp sc->sc_imask &= ~(1 << irq); 176202035Simp sc->sc_elcr &= ~(1 << irq); 177202035Simp 178202035Simp gt_pci_set_icus(sc); 179202035Simp} 180202035Simp 181202035Simpstatic void 182178173Simpgt_pci_set_icus(struct gt_pci_softc *sc) 183178173Simp{ 184178173Simp /* Enable the cascade IRQ (2) if 8-15 is enabled. */ 185178173Simp if ((sc->sc_imask & 0xff00) != 0xff00) 186178173Simp sc->sc_imask &= ~(1U << 2); 187178173Simp else 188178173Simp sc->sc_imask |= (1U << 2); 189178173Simp 190202035Simp bus_space_write_1(sc->sc_st, sc->sc_ioh_icu1, PIC_OCW1, 191178173Simp sc->sc_imask & 0xff); 192202035Simp bus_space_write_1(sc->sc_st, sc->sc_ioh_icu2, PIC_OCW1, 193178173Simp (sc->sc_imask >> 8) & 0xff); 194178173Simp 195202035Simp bus_space_write_1(sc->sc_st, sc->sc_ioh_elcr, 0, 196178173Simp sc->sc_elcr & 0xff); 197202035Simp bus_space_write_1(sc->sc_st, sc->sc_ioh_elcr, 1, 198178173Simp (sc->sc_elcr >> 8) & 0xff); 199178173Simp} 200178173Simp 201178173Simpstatic int 202178173Simpgt_pci_intr(void *v) 203178173Simp{ 204178173Simp struct gt_pci_softc *sc = v; 205178173Simp struct intr_event *event; 206183174Simp int irq; 207178173Simp 208178173Simp for (;;) { 209202035Simp bus_space_write_1(sc->sc_st, sc->sc_ioh_icu1, PIC_OCW3, 210178173Simp OCW3_SEL | OCW3_P); 211202035Simp irq = bus_space_read_1(sc->sc_st, sc->sc_ioh_icu1, PIC_OCW3); 212178173Simp if ((irq & OCW3_POLL_PENDING) == 0) 213178173Simp { 214178173Simp return FILTER_HANDLED; 215178173Simp } 216178173Simp 217178173Simp irq = OCW3_POLL_IRQ(irq); 218178173Simp 219178173Simp if (irq == 2) { 220202035Simp bus_space_write_1(sc->sc_st, sc->sc_ioh_icu2, 221178173Simp PIC_OCW3, OCW3_SEL | OCW3_P); 222202035Simp irq = bus_space_read_1(sc->sc_st, sc->sc_ioh_icu2, 223178173Simp PIC_OCW3); 224178173Simp if (irq & OCW3_POLL_PENDING) 225178173Simp irq = OCW3_POLL_IRQ(irq) + 8; 226178173Simp else 227178173Simp irq = 2; 228178173Simp } 229178173Simp 230178173Simp event = sc->sc_eventstab[irq]; 231178173Simp 232183174Simp if (!event || TAILQ_EMPTY(&event->ie_handlers)) 233183174Simp continue; 234178173Simp 235183174Simp /* TODO: frame instead of NULL? */ 236183174Simp intr_event_handle(event, NULL); 237183174Simp /* XXX: Log stray IRQs */ 238178173Simp 239178173Simp /* Send a specific EOI to the 8259. */ 240178173Simp if (irq > 7) { 241202035Simp bus_space_write_1(sc->sc_st, sc->sc_ioh_icu2, 242178173Simp PIC_OCW2, OCW2_SELECT | OCW2_EOI | OCW2_SL | 243178173Simp OCW2_ILS(irq & 7)); 244178173Simp irq = 2; 245178173Simp } 246178173Simp 247202035Simp bus_space_write_1(sc->sc_st, sc->sc_ioh_icu1, PIC_OCW2, 248178173Simp OCW2_SELECT | OCW2_EOI | OCW2_SL | OCW2_ILS(irq)); 249178173Simp } 250178173Simp 251178173Simp return FILTER_HANDLED; 252178173Simp} 253178173Simp 254178173Simpstatic int 255178173Simpgt_pci_probe(device_t dev) 256178173Simp{ 257178173Simp device_set_desc(dev, "GT64120 PCI bridge"); 258178173Simp return (0); 259178173Simp} 260178173Simp 261178173Simpstatic int 262178173Simpgt_pci_attach(device_t dev) 263178173Simp{ 264178173Simp 265178173Simp uint32_t busno; 266178173Simp struct gt_pci_softc *sc = device_get_softc(dev); 267178173Simp int rid; 268178173Simp 269178173Simp busno = 0; 270178173Simp sc->sc_dev = dev; 271178173Simp sc->sc_busno = busno; 272202035Simp sc->sc_st = mips_bus_space_generic; 273178173Simp 274178173Simp /* Use KSEG1 to access IO ports for it is uncached */ 275302287Sgonzo sc->sc_io = MALTA_PCI0_IO_BASE; 276178173Simp sc->sc_io_rman.rm_type = RMAN_ARRAY; 277178173Simp sc->sc_io_rman.rm_descr = "GT64120 PCI I/O Ports"; 278254946Sgonzo /* 279254946Sgonzo * First 256 bytes are ISA's registers: e.g. i8259's 280254946Sgonzo * So do not use them for general purpose PCI I/O window 281254946Sgonzo */ 282178173Simp if (rman_init(&sc->sc_io_rman) != 0 || 283254946Sgonzo rman_manage_region(&sc->sc_io_rman, 0x100, 0xffff) != 0) { 284178173Simp panic("gt_pci_attach: failed to set up I/O rman"); 285178173Simp } 286178173Simp 287178173Simp /* Use KSEG1 to access PCI memory for it is uncached */ 288302287Sgonzo sc->sc_mem = MALTA_PCIMEM1_BASE; 289178173Simp sc->sc_mem_rman.rm_type = RMAN_ARRAY; 290178173Simp sc->sc_mem_rman.rm_descr = "GT64120 PCI Memory"; 291178173Simp if (rman_init(&sc->sc_mem_rman) != 0 || 292178173Simp rman_manage_region(&sc->sc_mem_rman, 293178173Simp sc->sc_mem, sc->sc_mem + MALTA_PCIMEM1_SIZE) != 0) { 294178173Simp panic("gt_pci_attach: failed to set up memory rman"); 295178173Simp } 296178173Simp sc->sc_irq_rman.rm_type = RMAN_ARRAY; 297178173Simp sc->sc_irq_rman.rm_descr = "GT64120 PCI IRQs"; 298178173Simp if (rman_init(&sc->sc_irq_rman) != 0 || 299178173Simp rman_manage_region(&sc->sc_irq_rman, 1, 31) != 0) 300178173Simp panic("gt_pci_attach: failed to set up IRQ rman"); 301178173Simp 302178173Simp /* 303178173Simp * Map the PIC/ELCR registers. 304178173Simp */ 305178173Simp#if 0 306202035Simp if (bus_space_map(sc->sc_st, 0x4d0, 2, 0, &sc->sc_ioh_elcr) != 0) 307178173Simp device_printf(dev, "unable to map ELCR registers\n"); 308202035Simp if (bus_space_map(sc->sc_st, IO_ICU1, 2, 0, &sc->sc_ioh_icu1) != 0) 309178173Simp device_printf(dev, "unable to map ICU1 registers\n"); 310202035Simp if (bus_space_map(sc->sc_st, IO_ICU2, 2, 0, &sc->sc_ioh_icu2) != 0) 311178173Simp device_printf(dev, "unable to map ICU2 registers\n"); 312178173Simp#else 313302287Sgonzo sc->sc_ioh_elcr = MIPS_PHYS_TO_KSEG1(sc->sc_io + 0x4d0); 314302287Sgonzo sc->sc_ioh_icu1 = MIPS_PHYS_TO_KSEG1(sc->sc_io + IO_ICU1); 315302287Sgonzo sc->sc_ioh_icu2 = MIPS_PHYS_TO_KSEG1(sc->sc_io + IO_ICU2); 316178173Simp#endif 317178173Simp 318178173Simp 319178173Simp /* All interrupts default to "masked off". */ 320178173Simp sc->sc_imask = 0xffff; 321178173Simp 322178173Simp /* All interrupts default to edge-triggered. */ 323178173Simp sc->sc_elcr = 0; 324178173Simp 325178173Simp /* 326178173Simp * Initialize the 8259s. 327178173Simp */ 328178173Simp /* reset, program device, 4 bytes */ 329202035Simp bus_space_write_1(sc->sc_st, sc->sc_ioh_icu1, 0, 330178173Simp ICW1_RESET | ICW1_IC4); 331178173Simp /* 332178173Simp * XXX: values from NetBSD's <dev/ic/i8259reg.h> 333178173Simp */ 334202035Simp bus_space_write_1(sc->sc_st, sc->sc_ioh_icu1, 1, 335178173Simp 0/*XXX*/); 336202035Simp bus_space_write_1(sc->sc_st, sc->sc_ioh_icu1, 1, 337178173Simp 1 << 2); 338202035Simp bus_space_write_1(sc->sc_st, sc->sc_ioh_icu1, 1, 339178173Simp ICW4_8086); 340178173Simp 341178173Simp /* mask all interrupts */ 342224072Sadrian bus_space_write_1(sc->sc_st, sc->sc_ioh_icu1, 1, 343178173Simp sc->sc_imask & 0xff); 344178173Simp 345178173Simp /* enable special mask mode */ 346224072Sadrian bus_space_write_1(sc->sc_st, sc->sc_ioh_icu1, 0, 347178173Simp OCW3_SEL | OCW3_ESMM | OCW3_SMM); 348178173Simp 349178173Simp /* read IRR by default */ 350224072Sadrian bus_space_write_1(sc->sc_st, sc->sc_ioh_icu1, 0, 351178173Simp OCW3_SEL | OCW3_RR); 352178173Simp 353178173Simp /* reset, program device, 4 bytes */ 354202035Simp bus_space_write_1(sc->sc_st, sc->sc_ioh_icu2, 0, 355178173Simp ICW1_RESET | ICW1_IC4); 356202035Simp bus_space_write_1(sc->sc_st, sc->sc_ioh_icu2, 1, 357178173Simp 0/*XXX*/); 358202035Simp bus_space_write_1(sc->sc_st, sc->sc_ioh_icu2, 1, 359178173Simp 1 << 2); 360202035Simp bus_space_write_1(sc->sc_st, sc->sc_ioh_icu2, 1, 361178173Simp ICW4_8086); 362178173Simp 363178173Simp /* mask all interrupts */ 364224072Sadrian bus_space_write_1(sc->sc_st, sc->sc_ioh_icu2, 1, 365178173Simp sc->sc_imask & 0xff); 366178173Simp 367178173Simp /* enable special mask mode */ 368224072Sadrian bus_space_write_1(sc->sc_st, sc->sc_ioh_icu2, 0, 369178173Simp OCW3_SEL | OCW3_ESMM | OCW3_SMM); 370178173Simp 371178173Simp /* read IRR by default */ 372224072Sadrian bus_space_write_1(sc->sc_st, sc->sc_ioh_icu2, 0, 373178173Simp OCW3_SEL | OCW3_RR); 374178173Simp 375178173Simp /* 376178173Simp * Default all interrupts to edge-triggered. 377178173Simp */ 378202035Simp bus_space_write_1(sc->sc_st, sc->sc_ioh_elcr, 0, 379178173Simp sc->sc_elcr & 0xff); 380202035Simp bus_space_write_1(sc->sc_st, sc->sc_ioh_elcr, 1, 381178173Simp (sc->sc_elcr >> 8) & 0xff); 382178173Simp 383178173Simp /* 384178173Simp * Some ISA interrupts are reserved for devices that 385178173Simp * we know are hard-wired to certain IRQs. 386178173Simp */ 387178173Simp sc->sc_reserved = 388178173Simp (1U << 0) | /* timer */ 389178173Simp (1U << 1) | /* keyboard controller (keyboard) */ 390178173Simp (1U << 2) | /* PIC cascade */ 391178173Simp (1U << 3) | /* COM 2 */ 392178173Simp (1U << 4) | /* COM 1 */ 393178173Simp (1U << 6) | /* floppy */ 394178173Simp (1U << 7) | /* centronics */ 395178173Simp (1U << 8) | /* RTC */ 396178173Simp (1U << 9) | /* I2C */ 397178173Simp (1U << 12) | /* keyboard controller (mouse) */ 398178173Simp (1U << 14) | /* IDE primary */ 399178173Simp (1U << 15); /* IDE secondary */ 400178173Simp 401178173Simp /* Hook up our interrupt handler. */ 402178173Simp if ((sc->sc_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 403178173Simp MALTA_SOUTHBRIDGE_INTR, MALTA_SOUTHBRIDGE_INTR, 1, 404178173Simp RF_SHAREABLE | RF_ACTIVE)) == NULL) { 405178173Simp device_printf(dev, "unable to allocate IRQ resource\n"); 406178173Simp return ENXIO; 407178173Simp } 408178173Simp 409178173Simp if ((bus_setup_intr(dev, sc->sc_irq, INTR_TYPE_MISC, 410178173Simp gt_pci_intr, NULL, sc, &sc->sc_ih))) { 411178173Simp device_printf(dev, 412178173Simp "WARNING: unable to register interrupt handler\n"); 413178173Simp return ENXIO; 414178173Simp } 415178173Simp 416178173Simp /* Initialize memory and i/o rmans. */ 417287882Szbb device_add_child(dev, "pci", -1); 418178173Simp return (bus_generic_attach(dev)); 419178173Simp} 420178173Simp 421178173Simpstatic int 422178173Simpgt_pci_maxslots(device_t dev) 423178173Simp{ 424178173Simp return (PCI_SLOTMAX); 425178173Simp} 426178173Simp 427178173Simpstatic int 428178173Simpgt_pci_conf_setup(struct gt_pci_softc *sc, int bus, int slot, int func, 429178173Simp int reg, uint32_t *addr) 430178173Simp{ 431178173Simp *addr = (bus << 16) | (slot << 11) | (func << 8) | reg; 432178173Simp 433178173Simp return (0); 434178173Simp} 435178173Simp 436178173Simpstatic uint32_t 437194082Sjmallettgt_pci_read_config(device_t dev, u_int bus, u_int slot, u_int func, u_int reg, 438178173Simp int bytes) 439178173Simp{ 440178173Simp struct gt_pci_softc *sc = device_get_softc(dev); 441178173Simp uint32_t data; 442178173Simp uint32_t addr; 443178173Simp uint32_t shift, mask; 444178173Simp 445178173Simp if (gt_pci_conf_setup(sc, bus, slot, func, reg & ~3, &addr)) 446178173Simp return (uint32_t)(-1); 447178173Simp 448178173Simp /* Clear cause register bits. */ 449254983Sgonzo GT_REGVAL(GT_INTR_CAUSE) = GT_PCI_DATA(0); 450258780Seadler GT_REGVAL(GT_PCI0_CFG_ADDR) = GT_PCI_DATA((1U << 31) | addr); 451254983Sgonzo /* 452254983Sgonzo * Galileo system controller is special 453254983Sgonzo */ 454254983Sgonzo if ((bus == 0) && (slot == 0)) 455254983Sgonzo data = GT_PCI_DATA(GT_REGVAL(GT_PCI0_CFG_DATA)); 456254983Sgonzo else 457254983Sgonzo data = GT_REGVAL(GT_PCI0_CFG_DATA); 458178173Simp 459178173Simp /* Check for master abort. */ 460254983Sgonzo if (GT_HOST_DATA(GT_REGVAL(GT_INTR_CAUSE)) & (GTIC_MASABORT0 | GTIC_TARABORT0)) 461178173Simp data = (uint32_t) -1; 462178173Simp 463178173Simp switch(reg % 4) 464178173Simp { 465178173Simp case 3: 466178173Simp shift = 24; 467178173Simp break; 468178173Simp case 2: 469178173Simp shift = 16; 470178173Simp break; 471178173Simp case 1: 472178173Simp shift = 8; 473178173Simp break; 474178173Simp default: 475178173Simp shift = 0; 476178173Simp break; 477178173Simp } 478178173Simp 479178173Simp switch(bytes) 480178173Simp { 481178173Simp case 1: 482178173Simp mask = 0xff; 483178173Simp data = (data >> shift) & mask; 484178173Simp break; 485178173Simp case 2: 486178173Simp mask = 0xffff; 487178173Simp if(reg % 4 == 0) 488178173Simp data = data & mask; 489178173Simp else 490178173Simp data = (data >> 16) & mask; 491178173Simp break; 492178173Simp case 4: 493178173Simp break; 494178173Simp default: 495178173Simp panic("gt_pci_readconfig: wrong bytes count"); 496178173Simp break; 497178173Simp } 498178173Simp#if 0 499178173Simp printf("PCICONF_READ(%02x:%02x.%02x[%04x] -> %02x(%d)\n", 500178173Simp bus, slot, func, reg, data, bytes); 501178173Simp#endif 502178173Simp 503178173Simp return (data); 504178173Simp} 505178173Simp 506178173Simpstatic void 507194082Sjmallettgt_pci_write_config(device_t dev, u_int bus, u_int slot, u_int func, u_int reg, 508178173Simp uint32_t data, int bytes) 509178173Simp{ 510178173Simp struct gt_pci_softc *sc = device_get_softc(dev); 511178173Simp uint32_t addr; 512178173Simp uint32_t reg_data; 513178173Simp uint32_t shift, mask; 514178173Simp 515178173Simp if(bytes != 4) 516178173Simp { 517178173Simp reg_data = gt_pci_read_config(dev, bus, slot, func, reg, 4); 518178173Simp 519187251Sgonzo shift = 8 * (reg & 3); 520178173Simp 521178173Simp switch(bytes) 522178173Simp { 523178173Simp case 1: 524178173Simp mask = 0xff; 525178173Simp data = (reg_data & ~ (mask << shift)) | (data << shift); 526178173Simp break; 527178173Simp case 2: 528178173Simp mask = 0xffff; 529178173Simp if(reg % 4 == 0) 530178173Simp data = (reg_data & ~mask) | data; 531178173Simp else 532178173Simp data = (reg_data & ~ (mask << shift)) | 533178173Simp (data << shift); 534178173Simp break; 535178173Simp case 4: 536178173Simp break; 537178173Simp default: 538178173Simp panic("gt_pci_readconfig: wrong bytes count"); 539178173Simp break; 540178173Simp } 541178173Simp } 542178173Simp 543178173Simp if (gt_pci_conf_setup(sc, bus, slot, func, reg & ~3, &addr)) 544178173Simp return; 545178173Simp 546178173Simp /* The galileo has problems accessing device 31. */ 547178173Simp if (bus == 0 && slot == 31) 548178173Simp return; 549178173Simp 550178173Simp /* XXX: no support for bus > 0 yet */ 551178173Simp if (bus > 0) 552178173Simp return; 553178173Simp 554178173Simp /* Clear cause register bits. */ 555254983Sgonzo GT_REGVAL(GT_INTR_CAUSE) = GT_PCI_DATA(0); 556178173Simp 557258780Seadler GT_REGVAL(GT_PCI0_CFG_ADDR) = GT_PCI_DATA((1U << 31) | addr); 558254983Sgonzo 559254983Sgonzo /* 560254983Sgonzo * Galileo system controller is special 561254983Sgonzo */ 562254983Sgonzo if ((bus == 0) && (slot == 0)) 563254983Sgonzo GT_REGVAL(GT_PCI0_CFG_DATA) = GT_PCI_DATA(data); 564254983Sgonzo else 565254983Sgonzo GT_REGVAL(GT_PCI0_CFG_DATA) = data; 566254983Sgonzo 567254983Sgonzo#if 0 568254983Sgonzo printf("PCICONF_WRITE(%02x:%02x.%02x[%04x] -> %02x(%d)\n", 569254983Sgonzo bus, slot, func, reg, data, bytes); 570254983Sgonzo#endif 571254983Sgonzo 572178173Simp} 573178173Simp 574178173Simpstatic int 575178173Simpgt_pci_route_interrupt(device_t pcib, device_t dev, int pin) 576178173Simp{ 577178173Simp int bus; 578178173Simp int device; 579178173Simp int func; 580178173Simp /* struct gt_pci_softc *sc = device_get_softc(pcib); */ 581178173Simp bus = pci_get_bus(dev); 582178173Simp device = pci_get_slot(dev); 583178173Simp func = pci_get_function(dev); 584178173Simp /* 585178173Simp * XXXMIPS: We need routing logic. This is just a stub . 586178173Simp */ 587178173Simp switch (device) { 588178173Simp case 9: /* 589178173Simp * PIIX4 IDE adapter. HW IRQ0 590178173Simp */ 591178173Simp return 0; 592254946Sgonzo case 11: /* Ethernet */ 593254946Sgonzo return 10; 594178173Simp default: 595254946Sgonzo device_printf(pcib, "no IRQ mapping for %d/%d/%d/%d\n", bus, device, func, pin); 596178173Simp 597178173Simp } 598178173Simp return (0); 599178173Simp 600178173Simp} 601178173Simp 602178173Simpstatic int 603178173Simpgt_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) 604178173Simp{ 605178173Simp struct gt_pci_softc *sc = device_get_softc(dev); 606178173Simp switch (which) { 607178173Simp case PCIB_IVAR_DOMAIN: 608178173Simp *result = 0; 609178173Simp return (0); 610178173Simp case PCIB_IVAR_BUS: 611178173Simp *result = sc->sc_busno; 612178173Simp return (0); 613178173Simp 614178173Simp } 615178173Simp return (ENOENT); 616178173Simp} 617178173Simp 618178173Simpstatic int 619178173Simpgt_write_ivar(device_t dev, device_t child, int which, uintptr_t result) 620178173Simp{ 621178173Simp struct gt_pci_softc * sc = device_get_softc(dev); 622178173Simp 623178173Simp switch (which) { 624178173Simp case PCIB_IVAR_BUS: 625178173Simp sc->sc_busno = result; 626178173Simp return (0); 627178173Simp } 628178173Simp return (ENOENT); 629178173Simp} 630178173Simp 631178173Simpstatic struct resource * 632178173Simpgt_pci_alloc_resource(device_t bus, device_t child, int type, int *rid, 633294883Sjhibbits rman_res_t start, rman_res_t end, rman_res_t count, u_int flags) 634178173Simp{ 635178173Simp struct gt_pci_softc *sc = device_get_softc(bus); 636178173Simp struct resource *rv = NULL; 637178173Simp struct rman *rm; 638178173Simp bus_space_handle_t bh = 0; 639178173Simp 640178173Simp switch (type) { 641178173Simp case SYS_RES_IRQ: 642178173Simp rm = &sc->sc_irq_rman; 643178173Simp break; 644178173Simp case SYS_RES_MEMORY: 645178173Simp rm = &sc->sc_mem_rman; 646178173Simp bh = sc->sc_mem; 647178173Simp break; 648178173Simp case SYS_RES_IOPORT: 649178173Simp rm = &sc->sc_io_rman; 650178173Simp bh = sc->sc_io; 651178173Simp break; 652178173Simp default: 653178173Simp return (NULL); 654178173Simp } 655178173Simp 656178173Simp rv = rman_reserve_resource(rm, start, end, count, flags, child); 657178173Simp if (rv == NULL) 658178173Simp return (NULL); 659178173Simp rman_set_rid(rv, *rid); 660178173Simp if (type != SYS_RES_IRQ) { 661178173Simp bh += (rman_get_start(rv)); 662178173Simp 663255083Sgonzo rman_set_bustag(rv, gt_pci_bus_space); 664178173Simp rman_set_bushandle(rv, bh); 665178173Simp if (flags & RF_ACTIVE) { 666178173Simp if (bus_activate_resource(child, type, *rid, rv)) { 667178173Simp rman_release_resource(rv); 668178173Simp return (NULL); 669178173Simp } 670178173Simp } 671178173Simp } 672178173Simp return (rv); 673178173Simp} 674178173Simp 675178173Simpstatic int 676178173Simpgt_pci_activate_resource(device_t bus, device_t child, int type, int rid, 677178173Simp struct resource *r) 678178173Simp{ 679178173Simp bus_space_handle_t p; 680178173Simp int error; 681178173Simp 682178173Simp if ((type == SYS_RES_MEMORY) || (type == SYS_RES_IOPORT)) { 683178173Simp error = bus_space_map(rman_get_bustag(r), 684178173Simp rman_get_bushandle(r), rman_get_size(r), 0, &p); 685178173Simp if (error) 686178173Simp return (error); 687178173Simp rman_set_bushandle(r, p); 688178173Simp } 689178173Simp return (rman_activate_resource(r)); 690178173Simp} 691178173Simp 692178173Simpstatic int 693178173Simpgt_pci_setup_intr(device_t dev, device_t child, struct resource *ires, 694178173Simp int flags, driver_filter_t *filt, driver_intr_t *handler, 695178173Simp void *arg, void **cookiep) 696178173Simp{ 697178173Simp struct gt_pci_softc *sc = device_get_softc(dev); 698178173Simp struct intr_event *event; 699178173Simp int irq, error; 700178173Simp 701178173Simp irq = rman_get_start(ires); 702178173Simp if (irq >= ICU_LEN || irq == 2) 703178173Simp panic("%s: bad irq or type", __func__); 704178173Simp 705178173Simp event = sc->sc_eventstab[irq]; 706202035Simp sc->sc_intr_cookies[irq].irq = irq; 707202035Simp sc->sc_intr_cookies[irq].sc = sc; 708178173Simp if (event == NULL) { 709202035Simp error = intr_event_create(&event, 710202035Simp (void *)&sc->sc_intr_cookies[irq], 0, irq, 711202035Simp gt_pci_mask_irq, gt_pci_unmask_irq, 712202035Simp NULL, NULL, "gt_pci intr%d:", irq); 713178173Simp if (error) 714178173Simp return 0; 715178173Simp sc->sc_eventstab[irq] = event; 716178173Simp } 717178173Simp 718178173Simp intr_event_add_handler(event, device_get_nameunit(child), filt, 719178173Simp handler, arg, intr_priority(flags), flags, cookiep); 720178173Simp 721202035Simp gt_pci_unmask_irq((void *)&sc->sc_intr_cookies[irq]); 722178173Simp return 0; 723178173Simp} 724178173Simp 725178173Simpstatic int 726178173Simpgt_pci_teardown_intr(device_t dev, device_t child, struct resource *res, 727178173Simp void *cookie) 728178173Simp{ 729202035Simp struct gt_pci_softc *sc = device_get_softc(dev); 730202035Simp int irq; 731202035Simp 732202035Simp irq = rman_get_start(res); 733202035Simp gt_pci_mask_irq((void *)&sc->sc_intr_cookies[irq]); 734202035Simp 735178173Simp return (intr_event_remove_handler(cookie)); 736178173Simp} 737178173Simp 738178173Simpstatic device_method_t gt_pci_methods[] = { 739178173Simp /* Device interface */ 740178173Simp DEVMETHOD(device_probe, gt_pci_probe), 741178173Simp DEVMETHOD(device_attach, gt_pci_attach), 742178173Simp DEVMETHOD(device_shutdown, bus_generic_shutdown), 743178173Simp DEVMETHOD(device_suspend, bus_generic_suspend), 744178173Simp DEVMETHOD(device_resume, bus_generic_resume), 745178173Simp 746178173Simp /* Bus interface */ 747178173Simp DEVMETHOD(bus_read_ivar, gt_read_ivar), 748178173Simp DEVMETHOD(bus_write_ivar, gt_write_ivar), 749178173Simp DEVMETHOD(bus_alloc_resource, gt_pci_alloc_resource), 750178173Simp DEVMETHOD(bus_release_resource, bus_generic_release_resource), 751178173Simp DEVMETHOD(bus_activate_resource, gt_pci_activate_resource), 752178173Simp DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), 753178173Simp DEVMETHOD(bus_setup_intr, gt_pci_setup_intr), 754178173Simp DEVMETHOD(bus_teardown_intr, gt_pci_teardown_intr), 755178173Simp 756178173Simp /* pcib interface */ 757178173Simp DEVMETHOD(pcib_maxslots, gt_pci_maxslots), 758178173Simp DEVMETHOD(pcib_read_config, gt_pci_read_config), 759178173Simp DEVMETHOD(pcib_write_config, gt_pci_write_config), 760178173Simp DEVMETHOD(pcib_route_interrupt, gt_pci_route_interrupt), 761178173Simp 762227843Smarius DEVMETHOD_END 763178173Simp}; 764178173Simp 765178173Simpstatic driver_t gt_pci_driver = { 766178173Simp "pcib", 767178173Simp gt_pci_methods, 768178173Simp sizeof(struct gt_pci_softc), 769178173Simp}; 770178173Simp 771178173Simpstatic devclass_t gt_pci_devclass; 772178173Simp 773178173SimpDRIVER_MODULE(gt_pci, gt, gt_pci_driver, gt_pci_devclass, 0, 0); 774