gt_pci.c revision 302408
1168754Sbushman/* $NetBSD: gt_pci.c,v 1.4 2003/07/15 00:24:54 lukem Exp $ */ 2168754Sbushman 3251867Seadler/*- 4168754Sbushman * Copyright (c) 2001, 2002 Wasabi Systems, Inc. 5168754Sbushman * All rights reserved. 6168754Sbushman * 7168754Sbushman * Written by Jason R. Thorpe for Wasabi Systems, Inc. 8168754Sbushman * 9168754Sbushman * Redistribution and use in source and binary forms, with or without 10168754Sbushman * modification, are permitted provided that the following conditions 11168754Sbushman * are met: 12168754Sbushman * 1. Redistributions of source code must retain the above copyright 13168754Sbushman * notice, this list of conditions and the following disclaimer. 14168754Sbushman * 2. Redistributions in binary form must reproduce the above copyright 15168754Sbushman * notice, this list of conditions and the following disclaimer in the 16168754Sbushman * documentation and/or other materials provided with the distribution. 17168754Sbushman * 3. All advertising materials mentioning features or use of this software 18168754Sbushman * must display the following acknowledgement: 19168754Sbushman * This product includes software developed for the NetBSD Project by 20168754Sbushman * Wasabi Systems, Inc. 21168754Sbushman * 4. The name of Wasabi Systems, Inc. may not be used to endorse 22168754Sbushman * or promote products derived from this software without specific prior 23168754Sbushman * written permission. 24168754Sbushman * 25168754Sbushman * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND 26168754Sbushman * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 27168754Sbushman * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 28168754Sbushman * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC 29168754Sbushman * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 30168754Sbushman * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 31168754Sbushman * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 32168754Sbushman * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 33168754Sbushman * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 34168754Sbushman * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 35168754Sbushman * POSSIBILITY OF SUCH DAMAGE. 36168754Sbushman */ 37168754Sbushman 38168754Sbushman/* 39168754Sbushman * PCI configuration support for gt I/O Processor chip. 40292323Sngie */ 41292323Sngie 42292323Sngie#include <sys/cdefs.h> 43168754Sbushman__FBSDID("$FreeBSD: stable/11/sys/mips/malta/gt_pci.c 302287 2016-06-29 23:33:44Z gonzo $"); 44168754Sbushman 45168754Sbushman#include <sys/param.h> 46168754Sbushman#include <sys/systm.h> 47168754Sbushman 48168754Sbushman#include <sys/bus.h> 49168754Sbushman#include <sys/endian.h> 50168754Sbushman#include <sys/interrupt.h> 51168754Sbushman#include <sys/malloc.h> 52168754Sbushman#include <sys/kernel.h> 53168754Sbushman#include <sys/module.h> 54168754Sbushman#include <sys/rman.h> 55168754Sbushman 56168754Sbushman#include <vm/vm.h> 57168754Sbushman#include <vm/pmap.h> 58168754Sbushman#include <vm/vm_extern.h> 59168754Sbushman 60168754Sbushman#include <machine/bus.h> 61168754Sbushman#include <machine/cpu.h> 62168754Sbushman 63168754Sbushman#include <mips/malta/maltareg.h> 64168754Sbushman 65168754Sbushman#include <mips/malta/gtreg.h> 66291363Sngie#include <mips/malta/gtvar.h> 67168754Sbushman 68168754Sbushman#include <isa/isareg.h> 69168754Sbushman#include <dev/ic/i8259.h> 70168754Sbushman 71168754Sbushman#include <dev/pci/pcireg.h> 72168754Sbushman#include <dev/pci/pcivar.h> 73291363Sngie 74168754Sbushman#include <dev/pci/pcib_private.h> 75168754Sbushman#include "pcib_if.h" 76168754Sbushman 77168754Sbushman#include <mips/malta/gt_pci_bus_space.h> 78168754Sbushman 79168754Sbushman#define ICU_LEN 16 /* number of ISA IRQs */ 80168754Sbushman 81168754Sbushman/* 82168754Sbushman * XXX: These defines are from NetBSD's <dev/ic/i8259reg.h>. Respective file 83168754Sbushman * from FreeBSD src tree <dev/ic/i8259.h> lacks some definitions. 84291363Sngie */ 85168754Sbushman#define PIC_OCW1 1 86168754Sbushman#define PIC_OCW2 0 87291363Sngie#define PIC_OCW3 0 88168754Sbushman 89291363Sngie#define OCW2_SELECT 0 90168754Sbushman#define OCW2_ILS(x) ((x) << 0) /* interrupt level select */ 91168754Sbushman 92168754Sbushman#define OCW3_POLL_IRQ(x) ((x) & 0x7f) 93168754Sbushman#define OCW3_POLL_PENDING (1U << 7) 94291363Sngie 95168754Sbushman/* 96291363Sngie * Galileo controller's registers are LE so convert to then 97168754Sbushman * to/from native byte order. We rely on boot loader or emulator 98168754Sbushman * to set "swap bytes" configuration correctly for us 99168754Sbushman */ 100168754Sbushman#define GT_PCI_DATA(v) htole32((v)) 101291363Sngie#define GT_HOST_DATA(v) le32toh((v)) 102319298Sngie 103168754Sbushmanstruct gt_pci_softc; 104291363Sngie 105168754Sbushmanstruct gt_pci_intr_cookie { 106168754Sbushman int irq; 107168754Sbushman struct gt_pci_softc *sc; 108168754Sbushman}; 109168754Sbushman 110168754Sbushmanstruct gt_pci_softc { 111168754Sbushman device_t sc_dev; 112291363Sngie bus_space_tag_t sc_st; 113168754Sbushman bus_space_handle_t sc_ioh_icu1; 114168754Sbushman bus_space_handle_t sc_ioh_icu2; 115168754Sbushman bus_space_handle_t sc_ioh_elcr; 116291363Sngie 117168754Sbushman int sc_busno; 118291363Sngie struct rman sc_mem_rman; 119168754Sbushman struct rman sc_io_rman; 120291363Sngie struct rman sc_irq_rman; 121168754Sbushman unsigned long sc_mem; 122168754Sbushman bus_space_handle_t sc_io; 123168754Sbushman 124168754Sbushman struct resource *sc_irq; 125168754Sbushman struct intr_event *sc_eventstab[ICU_LEN]; 126291363Sngie struct gt_pci_intr_cookie sc_intr_cookies[ICU_LEN]; 127168754Sbushman uint16_t sc_imask; 128168754Sbushman uint16_t sc_elcr; 129168754Sbushman 130291363Sngie uint16_t sc_reserved; 131168754Sbushman 132168754Sbushman void *sc_ih; 133291363Sngie}; 134168754Sbushman 135168754Sbushmanstatic void gt_pci_set_icus(struct gt_pci_softc *); 136291363Sngiestatic int gt_pci_intr(void *v); 137168754Sbushmanstatic int gt_pci_probe(device_t); 138168754Sbushmanstatic int gt_pci_attach(device_t); 139168754Sbushmanstatic int gt_pci_activate_resource(device_t, device_t, int, int, 140291363Sngie struct resource *); 141168754Sbushmanstatic int gt_pci_setup_intr(device_t, device_t, struct resource *, 142168754Sbushman int, driver_filter_t *, driver_intr_t *, void *, void **); 143291363Sngiestatic int gt_pci_teardown_intr(device_t, device_t, struct resource *, void*); 144168754Sbushmanstatic int gt_pci_maxslots(device_t ); 145168754Sbushmanstatic int gt_pci_conf_setup(struct gt_pci_softc *, int, int, int, int, 146291363Sngie uint32_t *); 147168754Sbushmanstatic uint32_t gt_pci_read_config(device_t, u_int, u_int, u_int, u_int, int); 148168754Sbushmanstatic void gt_pci_write_config(device_t, u_int, u_int, u_int, u_int, 149168754Sbushman uint32_t, int); 150291363Sngiestatic int gt_pci_route_interrupt(device_t pcib, device_t dev, int pin); 151168754Sbushmanstatic struct resource * gt_pci_alloc_resource(device_t, device_t, int, 152168754Sbushman int *, rman_res_t, rman_res_t, rman_res_t, u_int); 153291363Sngie 154168754Sbushmanstatic void 155291363Sngiegt_pci_mask_irq(void *source) 156168754Sbushman{ 157292323Sngie struct gt_pci_intr_cookie *cookie = source; 158168754Sbushman struct gt_pci_softc *sc = cookie->sc; 159168754Sbushman int irq = cookie->irq; 160168754Sbushman 161168754Sbushman sc->sc_imask |= (1 << irq); 162168754Sbushman sc->sc_elcr |= (1 << irq); 163168754Sbushman 164168754Sbushman gt_pci_set_icus(sc); 165168754Sbushman} 166168754Sbushman 167168754Sbushmanstatic void 168168754Sbushmangt_pci_unmask_irq(void *source) 169168754Sbushman{ 170168754Sbushman struct gt_pci_intr_cookie *cookie = source; 171291363Sngie struct gt_pci_softc *sc = cookie->sc; 172168754Sbushman int irq = cookie->irq; 173291363Sngie 174168754Sbushman /* Enable it, set trigger mode. */ 175319298Sngie sc->sc_imask &= ~(1 << irq); 176168754Sbushman sc->sc_elcr &= ~(1 << irq); 177168754Sbushman 178291363Sngie gt_pci_set_icus(sc); 179168754Sbushman} 180168754Sbushman 181168754Sbushmanstatic void 182319298Sngiegt_pci_set_icus(struct gt_pci_softc *sc) 183168754Sbushman{ 184319298Sngie /* Enable the cascade IRQ (2) if 8-15 is enabled. */ 185168754Sbushman if ((sc->sc_imask & 0xff00) != 0xff00) 186168754Sbushman sc->sc_imask &= ~(1U << 2); 187291363Sngie else 188168754Sbushman sc->sc_imask |= (1U << 2); 189291363Sngie 190168754Sbushman bus_space_write_1(sc->sc_st, sc->sc_ioh_icu1, PIC_OCW1, 191168754Sbushman sc->sc_imask & 0xff); 192168754Sbushman bus_space_write_1(sc->sc_st, sc->sc_ioh_icu2, PIC_OCW1, 193168754Sbushman (sc->sc_imask >> 8) & 0xff); 194168754Sbushman 195168754Sbushman bus_space_write_1(sc->sc_st, sc->sc_ioh_elcr, 0, 196168754Sbushman sc->sc_elcr & 0xff); 197168754Sbushman bus_space_write_1(sc->sc_st, sc->sc_ioh_elcr, 1, 198168754Sbushman (sc->sc_elcr >> 8) & 0xff); 199168754Sbushman} 200168754Sbushman 201168754Sbushmanstatic int 202168754Sbushmangt_pci_intr(void *v) 203168754Sbushman{ 204292323Sngie struct gt_pci_softc *sc = v; 205291363Sngie struct intr_event *event; 206168754Sbushman int irq; 207168754Sbushman 208168754Sbushman for (;;) { 209168754Sbushman bus_space_write_1(sc->sc_st, sc->sc_ioh_icu1, PIC_OCW3, 210168754Sbushman OCW3_SEL | OCW3_P); 211168754Sbushman irq = bus_space_read_1(sc->sc_st, sc->sc_ioh_icu1, PIC_OCW3); 212168754Sbushman if ((irq & OCW3_POLL_PENDING) == 0) 213168754Sbushman { 214168754Sbushman return FILTER_HANDLED; 215168754Sbushman } 216168754Sbushman 217168754Sbushman irq = OCW3_POLL_IRQ(irq); 218168754Sbushman 219168754Sbushman if (irq == 2) { 220168754Sbushman bus_space_write_1(sc->sc_st, sc->sc_ioh_icu2, 221168754Sbushman PIC_OCW3, OCW3_SEL | OCW3_P); 222168754Sbushman irq = bus_space_read_1(sc->sc_st, sc->sc_ioh_icu2, 223168754Sbushman PIC_OCW3); 224168754Sbushman if (irq & OCW3_POLL_PENDING) 225168754Sbushman irq = OCW3_POLL_IRQ(irq) + 8; 226168754Sbushman else 227168754Sbushman irq = 2; 228168754Sbushman } 229291363Sngie 230168754Sbushman event = sc->sc_eventstab[irq]; 231168754Sbushman 232291363Sngie if (!event || TAILQ_EMPTY(&event->ie_handlers)) 233168754Sbushman continue; 234168754Sbushman 235168754Sbushman /* TODO: frame instead of NULL? */ 236168754Sbushman intr_event_handle(event, NULL); 237168754Sbushman /* XXX: Log stray IRQs */ 238168754Sbushman 239168754Sbushman /* Send a specific EOI to the 8259. */ 240168754Sbushman if (irq > 7) { 241168754Sbushman bus_space_write_1(sc->sc_st, sc->sc_ioh_icu2, 242168754Sbushman PIC_OCW2, OCW2_SELECT | OCW2_EOI | OCW2_SL | 243291363Sngie OCW2_ILS(irq & 7)); 244292323Sngie irq = 2; 245168754Sbushman } 246168754Sbushman 247168754Sbushman bus_space_write_1(sc->sc_st, sc->sc_ioh_icu1, PIC_OCW2, 248168754Sbushman OCW2_SELECT | OCW2_EOI | OCW2_SL | OCW2_ILS(irq)); 249168754Sbushman } 250168754Sbushman 251168754Sbushman return FILTER_HANDLED; 252168754Sbushman} 253291363Sngie 254168754Sbushmanstatic int 255168754Sbushmangt_pci_probe(device_t dev) 256168754Sbushman{ 257168754Sbushman device_set_desc(dev, "GT64120 PCI bridge"); 258291363Sngie return (0); 259168754Sbushman} 260168754Sbushman 261168754Sbushmanstatic int 262291363Sngiegt_pci_attach(device_t dev) 263168754Sbushman{ 264168754Sbushman 265168754Sbushman uint32_t busno; 266168754Sbushman struct gt_pci_softc *sc = device_get_softc(dev); 267168754Sbushman int rid; 268168754Sbushman 269168754Sbushman busno = 0; 270168754Sbushman sc->sc_dev = dev; 271168754Sbushman sc->sc_busno = busno; 272168754Sbushman sc->sc_st = mips_bus_space_generic; 273168754Sbushman 274168754Sbushman /* Use KSEG1 to access IO ports for it is uncached */ 275168754Sbushman sc->sc_io = MALTA_PCI0_IO_BASE; 276168754Sbushman sc->sc_io_rman.rm_type = RMAN_ARRAY; 277291363Sngie sc->sc_io_rman.rm_descr = "GT64120 PCI I/O Ports"; 278168754Sbushman /* 279168754Sbushman * First 256 bytes are ISA's registers: e.g. i8259's 280168754Sbushman * So do not use them for general purpose PCI I/O window 281168754Sbushman */ 282168754Sbushman if (rman_init(&sc->sc_io_rman) != 0 || 283168754Sbushman rman_manage_region(&sc->sc_io_rman, 0x100, 0xffff) != 0) { 284168754Sbushman panic("gt_pci_attach: failed to set up I/O rman"); 285168754Sbushman } 286291363Sngie 287168754Sbushman /* Use KSEG1 to access PCI memory for it is uncached */ 288168754Sbushman sc->sc_mem = MALTA_PCIMEM1_BASE; 289168754Sbushman sc->sc_mem_rman.rm_type = RMAN_ARRAY; 290168754Sbushman sc->sc_mem_rman.rm_descr = "GT64120 PCI Memory"; 291319298Sngie if (rman_init(&sc->sc_mem_rman) != 0 || 292168754Sbushman rman_manage_region(&sc->sc_mem_rman, 293292323Sngie sc->sc_mem, sc->sc_mem + MALTA_PCIMEM1_SIZE) != 0) { 294292323Sngie panic("gt_pci_attach: failed to set up memory rman"); 295291363Sngie } 296168754Sbushman sc->sc_irq_rman.rm_type = RMAN_ARRAY; 297168754Sbushman sc->sc_irq_rman.rm_descr = "GT64120 PCI IRQs"; 298291363Sngie if (rman_init(&sc->sc_irq_rman) != 0 || 299168754Sbushman rman_manage_region(&sc->sc_irq_rman, 1, 31) != 0) 300168754Sbushman panic("gt_pci_attach: failed to set up IRQ rman"); 301291363Sngie 302168754Sbushman /* 303168754Sbushman * Map the PIC/ELCR registers. 304291363Sngie */ 305168754Sbushman#if 0 306168754Sbushman if (bus_space_map(sc->sc_st, 0x4d0, 2, 0, &sc->sc_ioh_elcr) != 0) 307291363Sngie device_printf(dev, "unable to map ELCR registers\n"); 308292323Sngie if (bus_space_map(sc->sc_st, IO_ICU1, 2, 0, &sc->sc_ioh_icu1) != 0) 309291363Sngie device_printf(dev, "unable to map ICU1 registers\n"); 310291363Sngie if (bus_space_map(sc->sc_st, IO_ICU2, 2, 0, &sc->sc_ioh_icu2) != 0) 311168754Sbushman device_printf(dev, "unable to map ICU2 registers\n"); 312292323Sngie#else 313291363Sngie sc->sc_ioh_elcr = MIPS_PHYS_TO_KSEG1(sc->sc_io + 0x4d0); 314168754Sbushman sc->sc_ioh_icu1 = MIPS_PHYS_TO_KSEG1(sc->sc_io + IO_ICU1); 315168754Sbushman sc->sc_ioh_icu2 = MIPS_PHYS_TO_KSEG1(sc->sc_io + IO_ICU2); 316168754Sbushman#endif 317168754Sbushman 318168754Sbushman 319291363Sngie /* All interrupts default to "masked off". */ 320168754Sbushman sc->sc_imask = 0xffff; 321168754Sbushman 322168754Sbushman /* All interrupts default to edge-triggered. */ 323168754Sbushman sc->sc_elcr = 0; 324168754Sbushman 325291363Sngie /* 326168754Sbushman * Initialize the 8259s. 327168754Sbushman */ 328168754Sbushman /* reset, program device, 4 bytes */ 329168754Sbushman bus_space_write_1(sc->sc_st, sc->sc_ioh_icu1, 0, 330168754Sbushman ICW1_RESET | ICW1_IC4); 331168754Sbushman /* 332168754Sbushman * XXX: values from NetBSD's <dev/ic/i8259reg.h> 333168754Sbushman */ 334168754Sbushman bus_space_write_1(sc->sc_st, sc->sc_ioh_icu1, 1, 335291363Sngie 0/*XXX*/); 336292323Sngie bus_space_write_1(sc->sc_st, sc->sc_ioh_icu1, 1, 337292323Sngie 1 << 2); 338168754Sbushman bus_space_write_1(sc->sc_st, sc->sc_ioh_icu1, 1, 339168754Sbushman ICW4_8086); 340168754Sbushman 341168754Sbushman /* mask all interrupts */ 342291363Sngie bus_space_write_1(sc->sc_st, sc->sc_ioh_icu1, 1, 343168754Sbushman sc->sc_imask & 0xff); 344291363Sngie 345168754Sbushman /* enable special mask mode */ 346168754Sbushman bus_space_write_1(sc->sc_st, sc->sc_ioh_icu1, 0, 347291363Sngie OCW3_SEL | OCW3_ESMM | OCW3_SMM); 348168754Sbushman 349168754Sbushman /* read IRR by default */ 350291363Sngie bus_space_write_1(sc->sc_st, sc->sc_ioh_icu1, 0, 351168754Sbushman OCW3_SEL | OCW3_RR); 352168754Sbushman 353291363Sngie /* reset, program device, 4 bytes */ 354168754Sbushman bus_space_write_1(sc->sc_st, sc->sc_ioh_icu2, 0, 355168754Sbushman ICW1_RESET | ICW1_IC4); 356168754Sbushman bus_space_write_1(sc->sc_st, sc->sc_ioh_icu2, 1, 357168754Sbushman 0/*XXX*/); 358168754Sbushman bus_space_write_1(sc->sc_st, sc->sc_ioh_icu2, 1, 359291363Sngie 1 << 2); 360292323Sngie bus_space_write_1(sc->sc_st, sc->sc_ioh_icu2, 1, 361168754Sbushman ICW4_8086); 362291363Sngie 363168754Sbushman /* mask all interrupts */ 364292323Sngie bus_space_write_1(sc->sc_st, sc->sc_ioh_icu2, 1, 365291363Sngie sc->sc_imask & 0xff); 366168754Sbushman 367168754Sbushman /* enable special mask mode */ 368168754Sbushman bus_space_write_1(sc->sc_st, sc->sc_ioh_icu2, 0, 369168754Sbushman OCW3_SEL | OCW3_ESMM | OCW3_SMM); 370168754Sbushman 371168754Sbushman /* read IRR by default */ 372168754Sbushman bus_space_write_1(sc->sc_st, sc->sc_ioh_icu2, 0, 373291363Sngie OCW3_SEL | OCW3_RR); 374292323Sngie 375292323Sngie /* 376291363Sngie * Default all interrupts to edge-triggered. 377168754Sbushman */ 378291363Sngie bus_space_write_1(sc->sc_st, sc->sc_ioh_elcr, 0, 379168754Sbushman sc->sc_elcr & 0xff); 380168754Sbushman bus_space_write_1(sc->sc_st, sc->sc_ioh_elcr, 1, 381168754Sbushman (sc->sc_elcr >> 8) & 0xff); 382168754Sbushman 383292323Sngie /* 384168754Sbushman * Some ISA interrupts are reserved for devices that 385168754Sbushman * we know are hard-wired to certain IRQs. 386292323Sngie */ 387168754Sbushman sc->sc_reserved = 388168754Sbushman (1U << 0) | /* timer */ 389168754Sbushman (1U << 1) | /* keyboard controller (keyboard) */ 390291363Sngie (1U << 2) | /* PIC cascade */ 391319298Sngie (1U << 3) | /* COM 2 */ 392168754Sbushman (1U << 4) | /* COM 1 */ 393168754Sbushman (1U << 6) | /* floppy */ 394168754Sbushman (1U << 7) | /* centronics */ 395168754Sbushman (1U << 8) | /* RTC */ 396168754Sbushman (1U << 9) | /* I2C */ 397168754Sbushman (1U << 12) | /* keyboard controller (mouse) */ 398319298Sngie (1U << 14) | /* IDE primary */ 399292323Sngie (1U << 15); /* IDE secondary */ 400168754Sbushman 401168754Sbushman /* Hook up our interrupt handler. */ 402168754Sbushman if ((sc->sc_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 403291363Sngie MALTA_SOUTHBRIDGE_INTR, MALTA_SOUTHBRIDGE_INTR, 1, 404168754Sbushman RF_SHAREABLE | RF_ACTIVE)) == NULL) { 405168754Sbushman device_printf(dev, "unable to allocate IRQ resource\n"); 406168754Sbushman return ENXIO; 407291363Sngie } 408168754Sbushman 409168754Sbushman if ((bus_setup_intr(dev, sc->sc_irq, INTR_TYPE_MISC, 410168754Sbushman gt_pci_intr, NULL, sc, &sc->sc_ih))) { 411292323Sngie device_printf(dev, 412292323Sngie "WARNING: unable to register interrupt handler\n"); 413291363Sngie return ENXIO; 414168754Sbushman } 415168754Sbushman 416168754Sbushman /* Initialize memory and i/o rmans. */ 417168754Sbushman device_add_child(dev, "pci", -1); 418168754Sbushman return (bus_generic_attach(dev)); 419168754Sbushman} 420168754Sbushman 421168754Sbushmanstatic int 422291363Sngiegt_pci_maxslots(device_t dev) 423168754Sbushman{ 424168754Sbushman return (PCI_SLOTMAX); 425168754Sbushman} 426168754Sbushman 427291363Sngiestatic int 428168754Sbushmangt_pci_conf_setup(struct gt_pci_softc *sc, int bus, int slot, int func, 429168754Sbushman int reg, uint32_t *addr) 430168754Sbushman{ 431168754Sbushman *addr = (bus << 16) | (slot << 11) | (func << 8) | reg; 432168754Sbushman 433168754Sbushman return (0); 434168754Sbushman} 435168754Sbushman 436168754Sbushmanstatic uint32_t 437291363Sngiegt_pci_read_config(device_t dev, u_int bus, u_int slot, u_int func, u_int reg, 438168754Sbushman int bytes) 439168754Sbushman{ 440168754Sbushman struct gt_pci_softc *sc = device_get_softc(dev); 441168754Sbushman uint32_t data; 442168754Sbushman uint32_t addr; 443168754Sbushman uint32_t shift, mask; 444168754Sbushman 445291363Sngie if (gt_pci_conf_setup(sc, bus, slot, func, reg & ~3, &addr)) 446168754Sbushman return (uint32_t)(-1); 447168754Sbushman 448168754Sbushman /* Clear cause register bits. */ 449168754Sbushman GT_REGVAL(GT_INTR_CAUSE) = GT_PCI_DATA(0); 450291363Sngie GT_REGVAL(GT_PCI0_CFG_ADDR) = GT_PCI_DATA((1U << 31) | addr); 451168754Sbushman /* 452168754Sbushman * Galileo system controller is special 453168754Sbushman */ 454168754Sbushman if ((bus == 0) && (slot == 0)) 455168754Sbushman data = GT_PCI_DATA(GT_REGVAL(GT_PCI0_CFG_DATA)); 456168754Sbushman else 457292323Sngie data = GT_REGVAL(GT_PCI0_CFG_DATA); 458292323Sngie 459292323Sngie /* Check for master abort. */ 460292323Sngie if (GT_HOST_DATA(GT_REGVAL(GT_INTR_CAUSE)) & (GTIC_MASABORT0 | GTIC_TARABORT0)) 461292323Sngie data = (uint32_t) -1; 462292323Sngie 463292323Sngie switch(reg % 4) 464168754Sbushman { 465168754Sbushman case 3: 466168754Sbushman shift = 24; 467292323Sngie break; 468292323Sngie case 2: 469168754Sbushman shift = 16; 470168754Sbushman break; 471168754Sbushman case 1: 472168754Sbushman shift = 8; 473292323Sngie break; 474168754Sbushman default: 475168754Sbushman shift = 0; 476168754Sbushman break; 477168754Sbushman } 478292323Sngie 479168754Sbushman switch(bytes) 480168754Sbushman { 481292323Sngie case 1: 482292323Sngie mask = 0xff; 483292323Sngie data = (data >> shift) & mask; 484292323Sngie break; 485292323Sngie case 2: 486292323Sngie mask = 0xffff; 487292323Sngie if(reg % 4 == 0) 488292323Sngie data = data & mask; 489292323Sngie else 490292323Sngie data = (data >> 16) & mask; 491292323Sngie break; 492292323Sngie case 4: 493292323Sngie break; 494292323Sngie default: 495292323Sngie panic("gt_pci_readconfig: wrong bytes count"); 496292323Sngie break; 497292323Sngie } 498292323Sngie#if 0 499292323Sngie printf("PCICONF_READ(%02x:%02x.%02x[%04x] -> %02x(%d)\n", 500292323Sngie bus, slot, func, reg, data, bytes); 501292323Sngie#endif 502292323Sngie 503292323Sngie return (data); 504292323Sngie} 505292323Sngie 506292323Sngiestatic void 507292323Sngiegt_pci_write_config(device_t dev, u_int bus, u_int slot, u_int func, u_int reg, 508292323Sngie uint32_t data, int bytes) 509292323Sngie{ 510292323Sngie struct gt_pci_softc *sc = device_get_softc(dev); 511292323Sngie uint32_t addr; 512292323Sngie uint32_t reg_data; 513292323Sngie uint32_t shift, mask; 514292323Sngie 515292323Sngie if(bytes != 4) 516292323Sngie { 517292323Sngie reg_data = gt_pci_read_config(dev, bus, slot, func, reg, 4); 518292323Sngie 519292323Sngie shift = 8 * (reg & 3); 520292323Sngie 521292323Sngie switch(bytes) 522292323Sngie { 523292323Sngie case 1: 524292323Sngie mask = 0xff; 525292323Sngie data = (reg_data & ~ (mask << shift)) | (data << shift); 526292323Sngie break; 527292323Sngie case 2: 528292323Sngie mask = 0xffff; 529292323Sngie if(reg % 4 == 0) 530292323Sngie data = (reg_data & ~mask) | data; 531292323Sngie else 532292323Sngie data = (reg_data & ~ (mask << shift)) | 533292323Sngie (data << shift); 534292323Sngie break; 535292323Sngie case 4: 536292323Sngie break; 537292323Sngie default: 538292323Sngie panic("gt_pci_readconfig: wrong bytes count"); 539292323Sngie break; 540292323Sngie } 541292323Sngie } 542292323Sngie 543292323Sngie if (gt_pci_conf_setup(sc, bus, slot, func, reg & ~3, &addr)) 544292323Sngie return; 545292323Sngie 546292323Sngie /* The galileo has problems accessing device 31. */ 547292323Sngie if (bus == 0 && slot == 31) 548292323Sngie return; 549292323Sngie 550292323Sngie /* XXX: no support for bus > 0 yet */ 551292323Sngie if (bus > 0) 552292323Sngie return; 553292323Sngie 554292323Sngie /* Clear cause register bits. */ 555292323Sngie GT_REGVAL(GT_INTR_CAUSE) = GT_PCI_DATA(0); 556292323Sngie 557 GT_REGVAL(GT_PCI0_CFG_ADDR) = GT_PCI_DATA((1U << 31) | addr); 558 559 /* 560 * Galileo system controller is special 561 */ 562 if ((bus == 0) && (slot == 0)) 563 GT_REGVAL(GT_PCI0_CFG_DATA) = GT_PCI_DATA(data); 564 else 565 GT_REGVAL(GT_PCI0_CFG_DATA) = data; 566 567#if 0 568 printf("PCICONF_WRITE(%02x:%02x.%02x[%04x] -> %02x(%d)\n", 569 bus, slot, func, reg, data, bytes); 570#endif 571 572} 573 574static int 575gt_pci_route_interrupt(device_t pcib, device_t dev, int pin) 576{ 577 int bus; 578 int device; 579 int func; 580 /* struct gt_pci_softc *sc = device_get_softc(pcib); */ 581 bus = pci_get_bus(dev); 582 device = pci_get_slot(dev); 583 func = pci_get_function(dev); 584 /* 585 * XXXMIPS: We need routing logic. This is just a stub . 586 */ 587 switch (device) { 588 case 9: /* 589 * PIIX4 IDE adapter. HW IRQ0 590 */ 591 return 0; 592 case 11: /* Ethernet */ 593 return 10; 594 default: 595 device_printf(pcib, "no IRQ mapping for %d/%d/%d/%d\n", bus, device, func, pin); 596 597 } 598 return (0); 599 600} 601 602static int 603gt_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) 604{ 605 struct gt_pci_softc *sc = device_get_softc(dev); 606 switch (which) { 607 case PCIB_IVAR_DOMAIN: 608 *result = 0; 609 return (0); 610 case PCIB_IVAR_BUS: 611 *result = sc->sc_busno; 612 return (0); 613 614 } 615 return (ENOENT); 616} 617 618static int 619gt_write_ivar(device_t dev, device_t child, int which, uintptr_t result) 620{ 621 struct gt_pci_softc * sc = device_get_softc(dev); 622 623 switch (which) { 624 case PCIB_IVAR_BUS: 625 sc->sc_busno = result; 626 return (0); 627 } 628 return (ENOENT); 629} 630 631static struct resource * 632gt_pci_alloc_resource(device_t bus, device_t child, int type, int *rid, 633 rman_res_t start, rman_res_t end, rman_res_t count, u_int flags) 634{ 635 struct gt_pci_softc *sc = device_get_softc(bus); 636 struct resource *rv = NULL; 637 struct rman *rm; 638 bus_space_handle_t bh = 0; 639 640 switch (type) { 641 case SYS_RES_IRQ: 642 rm = &sc->sc_irq_rman; 643 break; 644 case SYS_RES_MEMORY: 645 rm = &sc->sc_mem_rman; 646 bh = sc->sc_mem; 647 break; 648 case SYS_RES_IOPORT: 649 rm = &sc->sc_io_rman; 650 bh = sc->sc_io; 651 break; 652 default: 653 return (NULL); 654 } 655 656 rv = rman_reserve_resource(rm, start, end, count, flags, child); 657 if (rv == NULL) 658 return (NULL); 659 rman_set_rid(rv, *rid); 660 if (type != SYS_RES_IRQ) { 661 bh += (rman_get_start(rv)); 662 663 rman_set_bustag(rv, gt_pci_bus_space); 664 rman_set_bushandle(rv, bh); 665 if (flags & RF_ACTIVE) { 666 if (bus_activate_resource(child, type, *rid, rv)) { 667 rman_release_resource(rv); 668 return (NULL); 669 } 670 } 671 } 672 return (rv); 673} 674 675static int 676gt_pci_activate_resource(device_t bus, device_t child, int type, int rid, 677 struct resource *r) 678{ 679 bus_space_handle_t p; 680 int error; 681 682 if ((type == SYS_RES_MEMORY) || (type == SYS_RES_IOPORT)) { 683 error = bus_space_map(rman_get_bustag(r), 684 rman_get_bushandle(r), rman_get_size(r), 0, &p); 685 if (error) 686 return (error); 687 rman_set_bushandle(r, p); 688 } 689 return (rman_activate_resource(r)); 690} 691 692static int 693gt_pci_setup_intr(device_t dev, device_t child, struct resource *ires, 694 int flags, driver_filter_t *filt, driver_intr_t *handler, 695 void *arg, void **cookiep) 696{ 697 struct gt_pci_softc *sc = device_get_softc(dev); 698 struct intr_event *event; 699 int irq, error; 700 701 irq = rman_get_start(ires); 702 if (irq >= ICU_LEN || irq == 2) 703 panic("%s: bad irq or type", __func__); 704 705 event = sc->sc_eventstab[irq]; 706 sc->sc_intr_cookies[irq].irq = irq; 707 sc->sc_intr_cookies[irq].sc = sc; 708 if (event == NULL) { 709 error = intr_event_create(&event, 710 (void *)&sc->sc_intr_cookies[irq], 0, irq, 711 gt_pci_mask_irq, gt_pci_unmask_irq, 712 NULL, NULL, "gt_pci intr%d:", irq); 713 if (error) 714 return 0; 715 sc->sc_eventstab[irq] = event; 716 } 717 718 intr_event_add_handler(event, device_get_nameunit(child), filt, 719 handler, arg, intr_priority(flags), flags, cookiep); 720 721 gt_pci_unmask_irq((void *)&sc->sc_intr_cookies[irq]); 722 return 0; 723} 724 725static int 726gt_pci_teardown_intr(device_t dev, device_t child, struct resource *res, 727 void *cookie) 728{ 729 struct gt_pci_softc *sc = device_get_softc(dev); 730 int irq; 731 732 irq = rman_get_start(res); 733 gt_pci_mask_irq((void *)&sc->sc_intr_cookies[irq]); 734 735 return (intr_event_remove_handler(cookie)); 736} 737 738static device_method_t gt_pci_methods[] = { 739 /* Device interface */ 740 DEVMETHOD(device_probe, gt_pci_probe), 741 DEVMETHOD(device_attach, gt_pci_attach), 742 DEVMETHOD(device_shutdown, bus_generic_shutdown), 743 DEVMETHOD(device_suspend, bus_generic_suspend), 744 DEVMETHOD(device_resume, bus_generic_resume), 745 746 /* Bus interface */ 747 DEVMETHOD(bus_read_ivar, gt_read_ivar), 748 DEVMETHOD(bus_write_ivar, gt_write_ivar), 749 DEVMETHOD(bus_alloc_resource, gt_pci_alloc_resource), 750 DEVMETHOD(bus_release_resource, bus_generic_release_resource), 751 DEVMETHOD(bus_activate_resource, gt_pci_activate_resource), 752 DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), 753 DEVMETHOD(bus_setup_intr, gt_pci_setup_intr), 754 DEVMETHOD(bus_teardown_intr, gt_pci_teardown_intr), 755 756 /* pcib interface */ 757 DEVMETHOD(pcib_maxslots, gt_pci_maxslots), 758 DEVMETHOD(pcib_read_config, gt_pci_read_config), 759 DEVMETHOD(pcib_write_config, gt_pci_write_config), 760 DEVMETHOD(pcib_route_interrupt, gt_pci_route_interrupt), 761 762 DEVMETHOD_END 763}; 764 765static driver_t gt_pci_driver = { 766 "pcib", 767 gt_pci_methods, 768 sizeof(struct gt_pci_softc), 769}; 770 771static devclass_t gt_pci_devclass; 772 773DRIVER_MODULE(gt_pci, gt, gt_pci_driver, gt_pci_devclass, 0, 0); 774