1244197Sgonzo/* 2244197Sgonzo * Copyright (c) 2012 Oleksandr Tymoshenko <gonzo@freebsd.org> 3244197Sgonzo * All rights reserved. 4244197Sgonzo * 5244197Sgonzo * Redistribution and use in source and binary forms, with or without 6244197Sgonzo * modification, are permitted provided that the following conditions 7244197Sgonzo * are met: 8244197Sgonzo * 1. Redistributions of source code must retain the above copyright 9244197Sgonzo * notice, this list of conditions and the following disclaimer. 10244197Sgonzo * 2. Redistributions in binary form must reproduce the above copyright 11244197Sgonzo * notice, this list of conditions and the following disclaimer in the 12244197Sgonzo * documentation and/or other materials provided with the distribution. 13244197Sgonzo * 14244197Sgonzo * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15244197Sgonzo * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16244197Sgonzo * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17244197Sgonzo * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18244197Sgonzo * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19244197Sgonzo * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20244197Sgonzo * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21244197Sgonzo * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22244197Sgonzo * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23244197Sgonzo * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24244197Sgonzo * SUCH DAMAGE. 25244197Sgonzo */ 26244197Sgonzo 27244197Sgonzo#include <sys/cdefs.h> 28244197Sgonzo__FBSDID("$FreeBSD: releng/10.2/sys/arm/versatile/versatile_pci.c 278727 2015-02-13 22:32:02Z ian $"); 29244197Sgonzo 30244197Sgonzo#include <sys/param.h> 31244197Sgonzo#include <sys/systm.h> 32244197Sgonzo#include <sys/bus.h> 33244197Sgonzo#include <sys/kernel.h> 34244197Sgonzo#include <sys/module.h> 35244197Sgonzo#include <sys/malloc.h> 36244197Sgonzo#include <sys/rman.h> 37244197Sgonzo#include <sys/watchdog.h> 38244197Sgonzo#include <machine/bus.h> 39244197Sgonzo#include <machine/cpu.h> 40244197Sgonzo#include <machine/intr.h> 41244197Sgonzo 42244197Sgonzo#include <dev/pci/pcivar.h> 43244197Sgonzo#include <dev/pci/pcireg.h> 44244197Sgonzo 45244197Sgonzo#include <dev/pci/pcib_private.h> 46244197Sgonzo#include "pcib_if.h" 47244197Sgonzo 48244197Sgonzo#include <dev/fdt/fdt_common.h> 49244197Sgonzo#include <dev/ofw/openfirm.h> 50244197Sgonzo#include <dev/ofw/ofw_bus.h> 51244197Sgonzo#include <dev/ofw/ofw_bus_subr.h> 52244197Sgonzo 53244197Sgonzo#include <machine/bus.h> 54244197Sgonzo#include <machine/fdt.h> 55244197Sgonzo 56244197Sgonzo#define MEM_SYS 0 57244197Sgonzo#define MEM_CORE 1 58244197Sgonzo#define MEM_BASE 2 59244197Sgonzo#define MEM_CONF_BASE 3 60244197Sgonzo#define MEM_REGIONS 4 61244197Sgonzo 62244197Sgonzo#define SYS_PCICTL 0x00 63244197Sgonzo 64244197Sgonzo#define PCI_CORE_IMAP0 0x00 65244197Sgonzo#define PCI_CORE_IMAP1 0x04 66244197Sgonzo#define PCI_CORE_IMAP2 0x08 67244197Sgonzo#define PCI_CORE_SELFID 0x0C 68244197Sgonzo#define PCI_CORE_SMAP0 0x10 69244197Sgonzo#define PCI_CORE_SMAP1 0x14 70244197Sgonzo#define PCI_CORE_SMAP2 0x18 71244197Sgonzo 72244197Sgonzo#define VERSATILE_PCI_DEV 0x030010ee 73244197Sgonzo#define VERSATILE_PCI_CLASS 0x0b400000 74244197Sgonzo 75244197Sgonzo#define PCI_IO_WINDOW 0x44000000 76244197Sgonzo#define PCI_IO_SIZE 0x0c000000 77244197Sgonzo#define PCI_NPREFETCH_WINDOW 0x50000000 78244197Sgonzo#define PCI_NPREFETCH_SIZE 0x10000000 79244197Sgonzo#define PCI_PREFETCH_WINDOW 0x60000000 80244197Sgonzo#define PCI_PREFETCH_SIZE 0x10000000 81244197Sgonzo 82244197Sgonzo#define VERSATILE_PCI_IRQ_START 27 83244197Sgonzo#define VERSATILE_PCI_IRQ_END 30 84244197Sgonzo 85244197Sgonzo#ifdef DEBUG 86244197Sgonzo#define dprintf(fmt, args...) do { printf("%s(): ", __func__); \ 87244197Sgonzo printf(fmt,##args); } while (0) 88244197Sgonzo#else 89244197Sgonzo#define dprintf(fmt, args...) 90244197Sgonzo#endif 91244197Sgonzo 92244197Sgonzo 93244197Sgonzo#define versatile_pci_sys_read_4(reg) \ 94244197Sgonzo bus_read_4(sc->mem_res[MEM_SYS], (reg)) 95244197Sgonzo#define versatile_pci_sys_write_4(reg, val) \ 96244197Sgonzo bus_write_4(sc->mem_res[MEM_SYS], (reg), (val)) 97244197Sgonzo 98244197Sgonzo#define versatile_pci_core_read_4(reg) \ 99244197Sgonzo bus_read_4(sc->mem_res[MEM_CORE], (reg)) 100244197Sgonzo#define versatile_pci_core_write_4(reg, val) \ 101244197Sgonzo bus_write_4(sc->mem_res[MEM_CORE], (reg), (val)) 102244197Sgonzo 103244197Sgonzo#define versatile_pci_read_4(reg) \ 104244197Sgonzo bus_read_4(sc->mem_res[MEM_BASE], (reg)) 105244197Sgonzo#define versatile_pci_write_4(reg, val) \ 106244197Sgonzo bus_write_4(sc->mem_res[MEM_BASE], (reg), (val)) 107244197Sgonzo 108244197Sgonzo#define versatile_pci_conf_read_4(reg) \ 109244197Sgonzo bus_read_4(sc->mem_res[MEM_CONF_BASE], (reg)) 110244197Sgonzo#define versatile_pci_conf_write_4(reg, val) \ 111244197Sgonzo bus_write_4(sc->mem_res[MEM_CONF_BASE], (reg), (val)) 112244197Sgonzo#define versatile_pci_conf_write_2(reg, val) \ 113244197Sgonzo bus_write_2(sc->mem_res[MEM_CONF_BASE], (reg), (val)) 114244197Sgonzo#define versatile_pci_conf_write_1(reg, val) \ 115244197Sgonzo bus_write_1(sc->mem_res[MEM_CONF_BASE], (reg), (val)) 116244197Sgonzo 117244197Sgonzostruct versatile_pci_softc { 118244197Sgonzo struct resource* mem_res[MEM_REGIONS]; 119244197Sgonzo struct resource* irq_res; 120244197Sgonzo void* intr_hl; 121244197Sgonzo 122244197Sgonzo int pcib_slot; 123244197Sgonzo 124244197Sgonzo /* Bus part */ 125244197Sgonzo int busno; 126244197Sgonzo struct rman io_rman; 127244197Sgonzo struct rman irq_rman; 128244197Sgonzo struct rman mem_rman; 129244197Sgonzo 130244197Sgonzo struct mtx mtx; 131244197Sgonzo}; 132244197Sgonzo 133244197Sgonzostatic struct resource_spec versatile_pci_mem_spec[] = { 134244197Sgonzo { SYS_RES_MEMORY, 0, RF_ACTIVE }, 135244197Sgonzo { SYS_RES_MEMORY, 1, RF_ACTIVE }, 136244197Sgonzo { SYS_RES_MEMORY, 2, RF_ACTIVE }, 137244197Sgonzo { SYS_RES_MEMORY, 3, RF_ACTIVE }, 138244197Sgonzo { -1, 0, 0 } 139244197Sgonzo}; 140244197Sgonzo 141244197Sgonzostatic int 142244197Sgonzoversatile_pci_probe(device_t dev) 143244197Sgonzo{ 144244197Sgonzo 145266152Sian if (!ofw_bus_status_okay(dev)) 146266152Sian return (ENXIO); 147266152Sian 148244197Sgonzo if (ofw_bus_is_compatible(dev, "versatile,pci")) { 149244197Sgonzo device_set_desc(dev, "Versatile PCI controller"); 150244197Sgonzo return (BUS_PROBE_DEFAULT); 151244197Sgonzo } 152244197Sgonzo 153244197Sgonzo return (ENXIO); 154244197Sgonzo} 155244197Sgonzo 156244197Sgonzostatic int 157244197Sgonzoversatile_pci_attach(device_t dev) 158244197Sgonzo{ 159244197Sgonzo struct versatile_pci_softc *sc = device_get_softc(dev); 160244197Sgonzo int err; 161244197Sgonzo int slot; 162244197Sgonzo uint32_t vendordev_id, class_id; 163244197Sgonzo uint32_t val; 164244197Sgonzo 165244197Sgonzo /* Request memory resources */ 166244197Sgonzo err = bus_alloc_resources(dev, versatile_pci_mem_spec, 167244197Sgonzo sc->mem_res); 168244197Sgonzo if (err) { 169244197Sgonzo device_printf(dev, "Error: could not allocate memory resources\n"); 170244197Sgonzo return (ENXIO); 171244197Sgonzo } 172244197Sgonzo 173244197Sgonzo /* 174244197Sgonzo * Setup memory windows 175244197Sgonzo */ 176252395Sgonzo versatile_pci_core_write_4(PCI_CORE_IMAP0, (PCI_IO_WINDOW >> 28)); 177252395Sgonzo versatile_pci_core_write_4(PCI_CORE_IMAP1, (PCI_NPREFETCH_WINDOW >> 28)); 178252395Sgonzo versatile_pci_core_write_4(PCI_CORE_IMAP2, (PCI_PREFETCH_WINDOW >> 28)); 179244197Sgonzo 180244197Sgonzo /* 181244197Sgonzo * XXX: this is SDRAM offset >> 28 182252395Sgonzo * Unused as of QEMU 1.5 183244197Sgonzo */ 184252395Sgonzo versatile_pci_core_write_4(PCI_CORE_SMAP0, (PCI_IO_WINDOW >> 28)); 185252395Sgonzo versatile_pci_core_write_4(PCI_CORE_SMAP1, (PCI_NPREFETCH_WINDOW >> 28)); 186252395Sgonzo versatile_pci_core_write_4(PCI_CORE_SMAP2, (PCI_NPREFETCH_WINDOW >> 28)); 187244197Sgonzo 188244197Sgonzo versatile_pci_sys_write_4(SYS_PCICTL, 1); 189244197Sgonzo 190244197Sgonzo for (slot = 0; slot <= PCI_SLOTMAX; slot++) { 191244197Sgonzo vendordev_id = versatile_pci_read_4((slot << 11) + PCIR_DEVVENDOR); 192244197Sgonzo class_id = versatile_pci_read_4((slot << 11) + PCIR_REVID); 193244197Sgonzo if ((vendordev_id == VERSATILE_PCI_DEV) && 194244197Sgonzo (class_id == VERSATILE_PCI_CLASS)) 195244197Sgonzo break; 196244197Sgonzo } 197244197Sgonzo 198244197Sgonzo if (slot == (PCI_SLOTMAX + 1)) { 199244197Sgonzo bus_release_resources(dev, versatile_pci_mem_spec, 200244197Sgonzo sc->mem_res); 201244197Sgonzo device_printf(dev, "Versatile PCI core not found\n"); 202244197Sgonzo return (ENXIO); 203244197Sgonzo } 204244197Sgonzo 205244197Sgonzo sc->pcib_slot = slot; 206244197Sgonzo device_printf(dev, "PCI core at slot #%d\n", slot); 207244197Sgonzo 208244197Sgonzo versatile_pci_core_write_4(PCI_CORE_SELFID, slot); 209244197Sgonzo val = versatile_pci_conf_read_4((slot << 11) + PCIR_COMMAND); 210244197Sgonzo val |= (PCIM_CMD_BUSMASTEREN | PCIM_CMD_MEMEN | PCIM_CMD_MWRICEN); 211244197Sgonzo versatile_pci_conf_write_4((slot << 11) + PCIR_COMMAND, val); 212244197Sgonzo 213244197Sgonzo /* Again SDRAM start >> 28 */ 214244197Sgonzo versatile_pci_write_4((slot << 11) + PCIR_BAR(0), 0); 215244197Sgonzo versatile_pci_write_4((slot << 11) + PCIR_BAR(1), 0); 216244197Sgonzo versatile_pci_write_4((slot << 11) + PCIR_BAR(2), 0); 217244197Sgonzo 218244197Sgonzo /* Prepare resource managers */ 219244197Sgonzo sc->mem_rman.rm_type = RMAN_ARRAY; 220244197Sgonzo sc->mem_rman.rm_descr = "versatile PCI memory window"; 221244197Sgonzo if (rman_init(&sc->mem_rman) != 0 || 222244197Sgonzo rman_manage_region(&sc->mem_rman, PCI_NPREFETCH_WINDOW, 223244197Sgonzo PCI_NPREFETCH_WINDOW + PCI_NPREFETCH_SIZE - 1) != 0) { 224244197Sgonzo panic("versatile_pci_attach: failed to set up memory rman"); 225244197Sgonzo } 226244197Sgonzo 227244197Sgonzo bootverbose = 1; 228244197Sgonzo sc->io_rman.rm_type = RMAN_ARRAY; 229244197Sgonzo sc->io_rman.rm_descr = "versatile PCI IO window"; 230244197Sgonzo if (rman_init(&sc->io_rman) != 0 || 231244197Sgonzo rman_manage_region(&sc->io_rman, PCI_IO_WINDOW, 232244197Sgonzo PCI_IO_WINDOW + PCI_IO_SIZE - 1) != 0) { 233244197Sgonzo panic("versatile_pci_attach: failed to set up I/O rman"); 234244197Sgonzo } 235244197Sgonzo 236244197Sgonzo sc->irq_rman.rm_type = RMAN_ARRAY; 237244197Sgonzo sc->irq_rman.rm_descr = "versatile PCI IRQs"; 238244197Sgonzo if (rman_init(&sc->irq_rman) != 0 || 239244197Sgonzo rman_manage_region(&sc->irq_rman, VERSATILE_PCI_IRQ_START, 240244197Sgonzo VERSATILE_PCI_IRQ_END) != 0) { 241244197Sgonzo panic("versatile_pci_attach: failed to set up IRQ rman"); 242244197Sgonzo } 243244197Sgonzo 244244197Sgonzo mtx_init(&sc->mtx, device_get_nameunit(dev), "versatilepci", 245244197Sgonzo MTX_SPIN); 246244197Sgonzo 247244197Sgonzo val = versatile_pci_conf_read_4((12 << 11) + PCIR_COMMAND); 248244197Sgonzo 249244197Sgonzo for (slot = 0; slot <= PCI_SLOTMAX; slot++) { 250244197Sgonzo vendordev_id = versatile_pci_read_4((slot << 11) + PCIR_DEVVENDOR); 251244197Sgonzo class_id = versatile_pci_read_4((slot << 11) + PCIR_REVID); 252244197Sgonzo 253244197Sgonzo if (slot == sc->pcib_slot) 254244197Sgonzo continue; 255244197Sgonzo 256244197Sgonzo if ((vendordev_id == 0xffffffff) && 257244197Sgonzo (class_id == 0xffffffff)) 258244197Sgonzo continue; 259244197Sgonzo 260244197Sgonzo val = versatile_pci_conf_read_4((slot << 11) + PCIR_COMMAND); 261244197Sgonzo val |= PCIM_CMD_MEMEN | PCIM_CMD_PORTEN; 262244197Sgonzo versatile_pci_conf_write_4((slot << 11) + PCIR_COMMAND, val); 263244197Sgonzo } 264244197Sgonzo 265244197Sgonzo device_add_child(dev, "pci", 0); 266244197Sgonzo return (bus_generic_attach(dev)); 267244197Sgonzo} 268244197Sgonzo 269244197Sgonzostatic int 270244197Sgonzoversatile_pci_read_ivar(device_t dev, device_t child, int which, 271244197Sgonzo uintptr_t *result) 272244197Sgonzo{ 273244197Sgonzo struct versatile_pci_softc *sc = device_get_softc(dev); 274244197Sgonzo 275244197Sgonzo switch (which) { 276244197Sgonzo case PCIB_IVAR_DOMAIN: 277244197Sgonzo *result = 0; 278244197Sgonzo return (0); 279244197Sgonzo case PCIB_IVAR_BUS: 280244197Sgonzo *result = sc->busno; 281244197Sgonzo return (0); 282244197Sgonzo } 283244197Sgonzo 284244197Sgonzo return (ENOENT); 285244197Sgonzo} 286244197Sgonzo 287244197Sgonzostatic int 288244197Sgonzoversatile_pci_write_ivar(device_t dev, device_t child, int which, 289244197Sgonzo uintptr_t result) 290244197Sgonzo{ 291244197Sgonzo struct versatile_pci_softc * sc = device_get_softc(dev); 292244197Sgonzo 293244197Sgonzo switch (which) { 294244197Sgonzo case PCIB_IVAR_BUS: 295244197Sgonzo sc->busno = result; 296244197Sgonzo return (0); 297244197Sgonzo } 298244197Sgonzo 299244197Sgonzo return (ENOENT); 300244197Sgonzo} 301244197Sgonzo 302244197Sgonzostatic struct resource * 303244197Sgonzoversatile_pci_alloc_resource(device_t bus, device_t child, int type, int *rid, 304244197Sgonzo u_long start, u_long end, u_long count, u_int flags) 305244197Sgonzo{ 306244197Sgonzo 307244197Sgonzo struct versatile_pci_softc *sc = device_get_softc(bus); 308244197Sgonzo struct resource *rv; 309244197Sgonzo struct rman *rm; 310244197Sgonzo 311252395Sgonzo dprintf("Alloc resources %d, %08lx..%08lx, %ld\n", type, start, end, count); 312244197Sgonzo 313244197Sgonzo switch (type) { 314244197Sgonzo case SYS_RES_IOPORT: 315244197Sgonzo rm = &sc->io_rman; 316244197Sgonzo break; 317244197Sgonzo case SYS_RES_IRQ: 318244197Sgonzo rm = &sc->irq_rman; 319244197Sgonzo break; 320244197Sgonzo case SYS_RES_MEMORY: 321244197Sgonzo rm = &sc->mem_rman; 322244197Sgonzo break; 323244197Sgonzo default: 324244197Sgonzo return (NULL); 325244197Sgonzo } 326244197Sgonzo 327244197Sgonzo rv = rman_reserve_resource(rm, start, end, count, flags, child); 328244197Sgonzo 329244197Sgonzo if (rv == NULL) 330244197Sgonzo return (NULL); 331244197Sgonzo 332244197Sgonzo rman_set_rid(rv, *rid); 333244197Sgonzo 334244197Sgonzo if (flags & RF_ACTIVE) { 335244197Sgonzo if (bus_activate_resource(child, type, *rid, rv)) { 336244197Sgonzo rman_release_resource(rv); 337244197Sgonzo return (NULL); 338244197Sgonzo } 339244197Sgonzo } 340244197Sgonzo return (rv); 341244197Sgonzo} 342244197Sgonzo 343244197Sgonzostatic int 344244197Sgonzoversatile_pci_activate_resource(device_t bus, device_t child, int type, int rid, 345244197Sgonzo struct resource *r) 346244197Sgonzo{ 347244197Sgonzo vm_offset_t vaddr; 348252395Sgonzo int res; 349244197Sgonzo 350252395Sgonzo switch(type) { 351252395Sgonzo case SYS_RES_MEMORY: 352252395Sgonzo case SYS_RES_IOPORT: 353252395Sgonzo vaddr = (vm_offset_t)pmap_mapdev(rman_get_start(r), 354252395Sgonzo rman_get_size(r)); 355252395Sgonzo rman_set_bushandle(r, vaddr); 356278727Sian rman_set_bustag(r, arm_base_bs_tag); 357252395Sgonzo res = rman_activate_resource(r); 358252395Sgonzo break; 359252395Sgonzo case SYS_RES_IRQ: 360252395Sgonzo res = (BUS_ACTIVATE_RESOURCE(device_get_parent(bus), 361252395Sgonzo child, type, rid, r)); 362252395Sgonzo break; 363256292Sdim default: 364256292Sdim res = ENXIO; 365256292Sdim break; 366244197Sgonzo } 367252395Sgonzo 368244197Sgonzo return (res); 369244197Sgonzo} 370244197Sgonzo 371244197Sgonzostatic int 372244197Sgonzoversatile_pci_setup_intr(device_t bus, device_t child, struct resource *ires, 373244197Sgonzo int flags, driver_filter_t *filt, driver_intr_t *handler, 374244197Sgonzo void *arg, void **cookiep) 375244197Sgonzo{ 376244197Sgonzo 377244197Sgonzo return BUS_SETUP_INTR(device_get_parent(bus), bus, ires, flags, 378244197Sgonzo filt, handler, arg, cookiep); 379244197Sgonzo} 380244197Sgonzo 381244197Sgonzostatic int 382244197Sgonzoversatile_pci_teardown_intr(device_t dev, device_t child, struct resource *ires, 383244197Sgonzo void *cookie) 384244197Sgonzo{ 385244197Sgonzo 386244197Sgonzo return BUS_TEARDOWN_INTR(device_get_parent(dev), dev, ires, cookie); 387244197Sgonzo} 388244197Sgonzo 389244197Sgonzo 390244197Sgonzo 391244197Sgonzostatic int 392244197Sgonzoversatile_pci_maxslots(device_t dev) 393244197Sgonzo{ 394244197Sgonzo 395244197Sgonzo return (PCI_SLOTMAX); 396244197Sgonzo} 397244197Sgonzo 398244197Sgonzostatic int 399244197Sgonzoversatile_pci_route_interrupt(device_t pcib, device_t device, int pin) 400244197Sgonzo{ 401244197Sgonzo 402244197Sgonzo return (27 + ((pci_get_slot(device) + pin - 1) & 3)); 403244197Sgonzo} 404244197Sgonzo 405244197Sgonzostatic uint32_t 406244197Sgonzoversatile_pci_read_config(device_t dev, u_int bus, u_int slot, u_int func, 407244197Sgonzo u_int reg, int bytes) 408244197Sgonzo{ 409244197Sgonzo struct versatile_pci_softc *sc = device_get_softc(dev); 410244197Sgonzo uint32_t data; 411244197Sgonzo uint32_t shift, mask; 412244197Sgonzo uint32_t addr; 413244197Sgonzo 414244197Sgonzo if (sc->pcib_slot == slot) { 415244197Sgonzo switch (bytes) { 416244197Sgonzo case 4: 417244197Sgonzo return (0xffffffff); 418244197Sgonzo break; 419244197Sgonzo case 2: 420244197Sgonzo return (0xffff); 421244197Sgonzo break; 422244197Sgonzo case 1: 423244197Sgonzo return (0xff); 424244197Sgonzo break; 425244197Sgonzo } 426244197Sgonzo } 427244197Sgonzo 428244197Sgonzo addr = (bus << 16) | (slot << 11) | (func << 8) | (reg & ~3); 429244197Sgonzo 430244197Sgonzo /* register access is 32-bit aligned */ 431244197Sgonzo shift = (reg & 3) * 8; 432244197Sgonzo 433244197Sgonzo /* Create a mask based on the width, post-shift */ 434244197Sgonzo if (bytes == 2) 435244197Sgonzo mask = 0xffff; 436244197Sgonzo else if (bytes == 1) 437244197Sgonzo mask = 0xff; 438244197Sgonzo else 439244197Sgonzo mask = 0xffffffff; 440244197Sgonzo 441244197Sgonzo dprintf("%s: tag (%x, %x, %x) reg %d(%d)\n", __func__, bus, slot, 442244197Sgonzo func, reg, bytes); 443244197Sgonzo 444244197Sgonzo mtx_lock_spin(&sc->mtx); 445244197Sgonzo data = versatile_pci_conf_read_4(addr); 446244197Sgonzo mtx_unlock_spin(&sc->mtx); 447244197Sgonzo 448244197Sgonzo /* get request bytes from 32-bit word */ 449244197Sgonzo data = (data >> shift) & mask; 450244197Sgonzo 451244197Sgonzo dprintf("%s: read 0x%x\n", __func__, data); 452244197Sgonzo 453244197Sgonzo return (data); 454244197Sgonzo} 455244197Sgonzo 456244197Sgonzostatic void 457244197Sgonzoversatile_pci_write_config(device_t dev, u_int bus, u_int slot, u_int func, 458244197Sgonzo u_int reg, uint32_t data, int bytes) 459244197Sgonzo{ 460244197Sgonzo 461244197Sgonzo struct versatile_pci_softc *sc = device_get_softc(dev); 462244197Sgonzo uint32_t addr; 463244197Sgonzo 464244197Sgonzo dprintf("%s: tag (%x, %x, %x) reg %d(%d)\n", __func__, bus, slot, 465244197Sgonzo func, reg, bytes); 466244197Sgonzo 467244197Sgonzo if (sc->pcib_slot == slot) 468244197Sgonzo return; 469244197Sgonzo 470244197Sgonzo addr = (bus << 16) | (slot << 11) | (func << 8) | reg; 471244197Sgonzo mtx_lock_spin(&sc->mtx); 472244197Sgonzo switch (bytes) { 473244197Sgonzo case 4: 474244197Sgonzo versatile_pci_conf_write_4(addr, data); 475244197Sgonzo break; 476244197Sgonzo case 2: 477244197Sgonzo versatile_pci_conf_write_2(addr, data); 478244197Sgonzo break; 479244197Sgonzo case 1: 480244197Sgonzo versatile_pci_conf_write_1(addr, data); 481244197Sgonzo break; 482244197Sgonzo } 483244197Sgonzo mtx_unlock_spin(&sc->mtx); 484244197Sgonzo} 485244197Sgonzo 486244197Sgonzostatic device_method_t versatile_pci_methods[] = { 487244197Sgonzo DEVMETHOD(device_probe, versatile_pci_probe), 488244197Sgonzo DEVMETHOD(device_attach, versatile_pci_attach), 489244197Sgonzo 490244197Sgonzo /* Bus interface */ 491244197Sgonzo DEVMETHOD(bus_read_ivar, versatile_pci_read_ivar), 492244197Sgonzo DEVMETHOD(bus_write_ivar, versatile_pci_write_ivar), 493244197Sgonzo DEVMETHOD(bus_alloc_resource, versatile_pci_alloc_resource), 494244197Sgonzo DEVMETHOD(bus_release_resource, bus_generic_release_resource), 495244197Sgonzo DEVMETHOD(bus_activate_resource, versatile_pci_activate_resource), 496244197Sgonzo DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), 497244197Sgonzo DEVMETHOD(bus_setup_intr, versatile_pci_setup_intr), 498244197Sgonzo DEVMETHOD(bus_teardown_intr, versatile_pci_teardown_intr), 499244197Sgonzo 500244197Sgonzo /* pcib interface */ 501244197Sgonzo DEVMETHOD(pcib_maxslots, versatile_pci_maxslots), 502244197Sgonzo DEVMETHOD(pcib_read_config, versatile_pci_read_config), 503244197Sgonzo DEVMETHOD(pcib_write_config, versatile_pci_write_config), 504244197Sgonzo DEVMETHOD(pcib_route_interrupt, versatile_pci_route_interrupt), 505244197Sgonzo 506244197Sgonzo DEVMETHOD_END 507244197Sgonzo}; 508244197Sgonzo 509244197Sgonzostatic driver_t versatile_pci_driver = { 510244197Sgonzo "pcib", 511244197Sgonzo versatile_pci_methods, 512244197Sgonzo sizeof(struct versatile_pci_softc), 513244197Sgonzo}; 514244197Sgonzo 515244197Sgonzostatic devclass_t versatile_pci_devclass; 516244197Sgonzo 517244197SgonzoDRIVER_MODULE(versatile_pci, simplebus, versatile_pci_driver, versatile_pci_devclass, 0, 0); 518