diff options
author | imp <imp@FreeBSD.org> | 2008-09-26 03:57:23 +0000 |
---|---|---|
committer | imp <imp@FreeBSD.org> | 2008-09-26 03:57:23 +0000 |
commit | 32d59cec8c293c43734f3c2f6e3b32feaa23b33f (patch) | |
tree | 82b9a0bc4185423e8080ba70132db8ed9623a403 /sys/dev | |
parent | 9488f1b10ef1f66d515bf79a7c25f0900459140b (diff) | |
download | FreeBSD-src-32d59cec8c293c43734f3c2f6e3b32feaa23b33f.zip FreeBSD-src-32d59cec8c293c43734f3c2f6e3b32feaa23b33f.tar.gz |
Support for the siba bus found in many broadcom products.
Submitted by: bms@
Obtained from: p4 mips branch
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/siba/siba.c | 665 | ||||
-rw-r--r-- | sys/dev/siba/siba_ids.h | 71 | ||||
-rw-r--r-- | sys/dev/siba/siba_pcib.c | 432 | ||||
-rw-r--r-- | sys/dev/siba/siba_pcibvar.h | 52 | ||||
-rw-r--r-- | sys/dev/siba/sibareg.h | 73 | ||||
-rw-r--r-- | sys/dev/siba/sibavar.h | 92 |
6 files changed, 1385 insertions, 0 deletions
diff --git a/sys/dev/siba/siba.c b/sys/dev/siba/siba.c new file mode 100644 index 0000000..04a5309 --- /dev/null +++ b/sys/dev/siba/siba.c @@ -0,0 +1,665 @@ +/*- + * Copyright (c) 2007 Bruce M. Simpson. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> +#include <sys/kernel.h> +#include <sys/module.h> +#include <sys/rman.h> +#include <sys/malloc.h> + +#include <machine/bus.h> + +#include <dev/siba/sibavar.h> +#include <dev/siba/sibareg.h> +#include <dev/siba/siba_ids.h> + +/* + * TODO: De-mipsify this code. + * TODO: cpu clock calculation. -> move to siba_cc instance + * TODO: Hardwire IRQs for attached cores on siba at probe time. + * TODO: Support detach. + * TODO: Power management. + * TODO: code cleanup. + * TODO: Support deployments of siba other than as a system bus. + */ + +#ifndef MIPS_MEM_RID +#define MIPS_MEM_RID 0x20 +#endif + +extern int rman_debug; + +static struct rman mem_rman; /* XXX move to softc */ + +static int siba_debug = 1; +static const char descfmt[] = "Sonics SiliconBackplane rev %s"; +#define SIBA_DEVDESCLEN sizeof(descfmt) + 8 + +/* + * Device identifiers and descriptions. + */ +static struct siba_devid siba_devids[] = { + { SIBA_VID_BROADCOM, SIBA_DEVID_CHIPCOMMON, SIBA_REV_ANY, + "ChipCommon" }, + { SIBA_VID_BROADCOM, SIBA_DEVID_SDRAM, SIBA_REV_ANY, + "SDRAM controller" }, + { SIBA_VID_BROADCOM, SIBA_DEVID_PCI, SIBA_REV_ANY, + "PCI host interface" }, + { SIBA_VID_BROADCOM, SIBA_DEVID_MIPS, SIBA_REV_ANY, + "MIPS core" }, + { SIBA_VID_BROADCOM, SIBA_DEVID_ETHERNET, SIBA_REV_ANY, + "Ethernet core" }, + { SIBA_VID_BROADCOM, SIBA_DEVID_USB, SIBA_REV_ANY, + "USB host controller" }, + { SIBA_VID_BROADCOM, SIBA_DEVID_IPSEC, SIBA_REV_ANY, + "IPSEC accelerator" }, + { SIBA_VID_BROADCOM, SIBA_DEVID_SDRAMDDR, SIBA_REV_ANY, + "SDRAM/DDR controller" }, + { SIBA_VID_BROADCOM, SIBA_DEVID_MIPS_3302, SIBA_REV_ANY, + "MIPS 3302 core" }, + { 0, 0, 0, NULL } +}; + +static int siba_activate_resource(device_t, device_t, int, int, + struct resource *); +static device_t siba_add_child(device_t, int, const char *, int); +static struct resource * + siba_alloc_resource(device_t, device_t, int, int *, u_long, + u_long, u_long, u_int); +static int siba_attach(device_t); +#ifdef notyet +static void siba_destroy_devinfo(struct siba_devinfo *); +#endif +static struct siba_devid * + siba_dev_match(uint16_t, uint16_t, uint8_t); +static struct resource_list * + siba_get_reslist(device_t, device_t); +static uint8_t siba_getirq(uint16_t); +static uint8_t siba_getncores(uint16_t); +static int siba_print_all_resources(device_t dev); +static int siba_print_child(device_t, device_t); +static int siba_probe(device_t); +static void siba_probe_nomatch(device_t, device_t); +int siba_read_ivar(device_t, device_t, int, uintptr_t *); +static struct siba_devinfo * + siba_setup_devinfo(device_t, uint8_t); +int siba_write_ivar(device_t, device_t, int, uintptr_t); + +/* + * Earlier ChipCommon revisions have hardcoded number of cores + * present dependent on the ChipCommon ID. + */ +static uint8_t +siba_getncores(uint16_t ccid) +{ + uint8_t ncores; + + switch (ccid) { + case SIBA_CCID_SENTRY5: + ncores = 7; + break; + case SIBA_CCID_BCM4710: + case SIBA_CCID_BCM4704: + ncores = 9; + break; + default: + ncores = 0; + } + + return (ncores); +} + +/* + * On the Sentry5, the system bus IRQs are the same as the + * MIPS IRQs. Particular cores are hardwired to certain IRQ lines. + */ +static uint8_t +siba_getirq(uint16_t devid) +{ + uint8_t irq; + + switch (devid) { + case SIBA_DEVID_CHIPCOMMON: + irq = 0; + break; + case SIBA_DEVID_ETHERNET: + irq = 1; + break; + case SIBA_DEVID_IPSEC: + irq = 2; + break; + case SIBA_DEVID_USB: + irq = 3; + break; + case SIBA_DEVID_PCI: + irq = 4; + break; +#if 0 + /* + * 5 is reserved for the MIPS on-chip timer interrupt; + * it is hard-wired by the tick driver. + */ + case SIBA_DEVID_MIPS: + case SIBA_DEVID_MIPS_3302: + irq = 5; + break; +#endif + default: + irq = 0xFF; /* this core does not need an irq */ + break; + } + + return (irq); +} + +static int +siba_probe(device_t dev) +{ + struct siba_softc *sc = device_get_softc(dev); + uint32_t idlo, idhi; + uint16_t ccid; + int rid; + + sc->sc_dev = dev; + + //rman_debug = 1; /* XXX */ + + /* + * Map the ChipCommon register set using the hints the kernel + * was compiled with. + */ + rid = MIPS_MEM_RID; + sc->sc_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, + RF_ACTIVE); + if (sc->sc_mem == NULL) { + device_printf(dev, "unable to allocate probe aperture\n"); + return (ENXIO); + } + sc->sc_bt = rman_get_bustag(sc->sc_mem); + sc->sc_bh = rman_get_bushandle(sc->sc_mem); + sc->sc_maddr = rman_get_start(sc->sc_mem); + sc->sc_msize = rman_get_size(sc->sc_mem); + + if (siba_debug) { + device_printf(dev, "start %08x len %08x\n", + sc->sc_maddr, sc->sc_msize); + } + + idlo = siba_read_4(sc, 0, SIBA_CORE_IDLO); + idhi = siba_read_4(sc, 0, SIBA_CORE_IDHI); + ccid = ((idhi & 0x8ff0) >> 4); + if (siba_debug) { + device_printf(dev, "idlo = %08x\n", idlo); + device_printf(dev, "idhi = %08x\n", idhi); + device_printf(dev, " chipcore id = %08x\n", ccid); + } + + /* + * For now, check that the first core is the ChipCommon core. + */ + if (ccid != SIBA_DEVID_CHIPCOMMON) { + if (siba_debug) + device_printf(dev, "first core is not ChipCommon\n"); + return (ENXIO); + } + + /* + * Determine backplane revision and set description string. + */ + uint32_t rev; + char *revp; + char descbuf[SIBA_DEVDESCLEN]; + + rev = idlo & 0xF0000000; + revp = "unknown"; + if (rev == 0x00000000) + revp = "2.2"; + else if (rev == 0x10000000) + revp = "2.3"; + + (void)snprintf(descbuf, sizeof(descbuf), descfmt, revp); + device_set_desc_copy(dev, descbuf); + + /* + * Determine how many cores are present on this siba bus, so + * that we may map them all. + */ + uint32_t ccidreg; + uint16_t cc_id; + uint16_t cc_rev; + + ccidreg = siba_read_4(sc, 0, SIBA_CC_CCID); + cc_id = (ccidreg & SIBA_CC_IDMASK); + cc_rev = (ccidreg & SIBA_CC_REVMASK) >> SIBA_CC_REVSHIFT; + if (siba_debug) { + device_printf(dev, "ccid = %08x, cc_id = %04x, cc_rev = %04x\n", + ccidreg, cc_id, cc_rev); + } + + sc->sc_ncores = siba_getncores(cc_id); + if (siba_debug) { + device_printf(dev, "%d cores detected.\n", sc->sc_ncores); + } + + /* + * Now we know how many cores are on this siba, release the + * mapping and allocate a new mapping spanning all cores on the bus. + */ + rid = MIPS_MEM_RID; + int result; + result = bus_release_resource(dev, SYS_RES_MEMORY, rid, sc->sc_mem); + if (result != 0) { + device_printf(dev, "error %d releasing resource\n", result); + return (ENXIO); + } + + uint32_t total; + total = sc->sc_ncores * SIBA_CORE_LEN; + + /* XXX Don't allocate the entire window until we + * enumerate the bus. Once the bus has been enumerated, + * and instance variables/children instantiated + populated, + * release the resource so children may attach. + */ + sc->sc_mem = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, + sc->sc_maddr, sc->sc_maddr + total - 1, total, RF_ACTIVE); + if (sc->sc_mem == NULL) { + device_printf(dev, "unable to allocate entire aperture\n"); + return (ENXIO); + } + sc->sc_bt = rman_get_bustag(sc->sc_mem); + sc->sc_bh = rman_get_bushandle(sc->sc_mem); + sc->sc_maddr = rman_get_start(sc->sc_mem); + sc->sc_msize = rman_get_size(sc->sc_mem); + + if (siba_debug) { + device_printf(dev, "after remapping: start %08x len %08x\n", + sc->sc_maddr, sc->sc_msize); + } + bus_set_resource(dev, SYS_RES_MEMORY, rid, sc->sc_maddr, sc->sc_msize); + + /* + * We need a manager for the space we claim on nexus to + * satisfy requests from children. + * We need to keep the source reservation we took because + * otherwise it may be claimed elsewhere. + * XXX move to softc + */ + mem_rman.rm_start = sc->sc_maddr; + mem_rman.rm_end = sc->sc_maddr + sc->sc_msize - 1; + mem_rman.rm_type = RMAN_ARRAY; + mem_rman.rm_descr = "SiBa I/O memory addresses"; + if (rman_init(&mem_rman) != 0 || + rman_manage_region(&mem_rman, mem_rman.rm_start, mem_rman.rm_end) != 0) { + panic("%s: mem_rman", __func__); + } + + return (0); +} + +static int +siba_attach(device_t dev) +{ + struct siba_softc *sc = device_get_softc(dev); + struct siba_devinfo *sdi; + device_t child; + int idx; + + if (siba_debug) + printf("%s: entry\n", __func__); + + bus_generic_probe(dev); + + /* + * Now that all bus space is mapped and visible to the CPU, + * enumerate its children. + * NB: only one core may be mapped at any time if the siba bus + * is the child of a PCI or PCMCIA bus. + */ + for (idx = 0; idx < sc->sc_ncores; idx++) { + sdi = siba_setup_devinfo(dev, idx); + child = device_add_child(dev, NULL, -1); + if (child == NULL) + panic("%s: device_add_child() failed\n", __func__); + device_set_ivars(child, sdi); + } + + return (bus_generic_attach(dev)); +} + +static struct siba_devid * +siba_dev_match(uint16_t vid, uint16_t devid, uint8_t rev) +{ + size_t i, bound; + struct siba_devid *sd; + + bound = sizeof(siba_devids) / sizeof(struct siba_devid); + sd = &siba_devids[0]; + for (i = 0; i < bound; i++, sd++) { + if (((vid == SIBA_VID_ANY) || (vid == sd->sd_vendor)) && + ((devid == SIBA_DEVID_ANY) || (devid == sd->sd_device)) && + ((rev == SIBA_REV_ANY) || (rev == sd->sd_rev) || + (sd->sd_rev == SIBA_REV_ANY))) + break; + } + if (i == bound) + sd = NULL; + + return (sd); +} + +static int +siba_print_child(device_t bus, device_t child) +{ + int retval = 0; + + retval += bus_print_child_header(bus, child); + retval += siba_print_all_resources(child); + if (device_get_flags(child)) + retval += printf(" flags %#x", device_get_flags(child)); + retval += printf(" on %s\n", device_get_nameunit(bus)); + + return (retval); +} + +static struct resource * +siba_alloc_resource(device_t bus, device_t child, int type, int *rid, + u_long start, u_long end, u_long count, u_int flags) +{ + struct resource *rv; + struct resource_list *rl; + struct resource_list_entry *rle; + int isdefault, needactivate; + +#if 0 + if (siba_debug) + printf("%s: entry\n", __func__); +#endif + + isdefault = (start == 0UL && end == ~0UL && count == 1); + needactivate = flags & RF_ACTIVE; + rl = BUS_GET_RESOURCE_LIST(bus, child); + rle = NULL; + + if (isdefault) { + rle = resource_list_find(rl, type, *rid); + if (rle == NULL) + return (NULL); + if (rle->res != NULL) + panic("%s: resource entry is busy", __func__); + start = rle->start; + end = rle->end; + count = rle->count; + } + + /* + * If the request is for a resource which we manage, + * attempt to satisfy the allocation ourselves. + */ + if (type == SYS_RES_MEMORY && + start >= mem_rman.rm_start && end <= mem_rman.rm_end) { + + rv = rman_reserve_resource(&mem_rman, start, end, count, + flags, child); + if (rv == 0) { + printf("%s: could not reserve resource\n", __func__); + return (0); + } + + rman_set_rid(rv, *rid); + + if (needactivate) { + if (bus_activate_resource(child, type, *rid, rv)) { + printf("%s: could not activate resource\n", + __func__); + rman_release_resource(rv); + return (0); + } + } + + return (rv); + } + + /* + * Pass the request to the parent, usually MIPS nexus. + */ + if (siba_debug) + printf("%s: proxying request to parent\n", __func__); + return (resource_list_alloc(rl, bus, child, type, rid, + start, end, count, flags)); +} + +/* + * The parent bus is responsible for resource activation; in the + * case of MIPS, this boils down to setting the virtual address and + * bus handle by mapping the physical address into KSEG1. + */ +static int +siba_activate_resource(device_t bus, device_t child, int type, int rid, + struct resource *r) +{ + + return (BUS_ACTIVATE_RESOURCE(device_get_parent(bus), child, type, + rid, r)); +} + +static struct siba_devinfo * +siba_setup_devinfo(device_t dev, uint8_t idx) +{ + struct siba_softc *sc = device_get_softc(dev); + struct siba_devinfo *sdi; + uint32_t idlo, idhi, rev; + uint16_t vendorid, devid; + bus_addr_t baseaddr; + + sdi = malloc(sizeof(*sdi), M_DEVBUF, M_WAITOK | M_ZERO); + resource_list_init(&sdi->sdi_rl); + + idlo = siba_read_4(sc, idx, SIBA_CORE_IDLO); + idhi = siba_read_4(sc, idx, SIBA_CORE_IDHI); + + vendorid = (idhi & SIBA_IDHIGH_VC) >> SIBA_IDHIGH_VC_SHIFT; + devid = ((idhi & 0x8ff0) >> 4); + rev = (idhi & SIBA_IDHIGH_RCLO); + rev |= (idhi & SIBA_IDHIGH_RCHI) >> SIBA_IDHIGH_RCHI_SHIFT; + + sdi->sdi_vid = vendorid; + sdi->sdi_devid = devid; + sdi->sdi_rev = rev; + sdi->sdi_idx = idx; + sdi->sdi_irq = siba_getirq(devid); + + /* + * Determine memory window on bus and irq if one is needed. + */ + baseaddr = sc->sc_maddr + (idx * SIBA_CORE_LEN); + resource_list_add(&sdi->sdi_rl, SYS_RES_MEMORY, + MIPS_MEM_RID, /* XXX */ + baseaddr, baseaddr + SIBA_CORE_LEN - 1, SIBA_CORE_LEN); + + if (sdi->sdi_irq != 0xff) { + resource_list_add(&sdi->sdi_rl, SYS_RES_IRQ, + 0, sdi->sdi_irq, sdi->sdi_irq, 1); + } + + return (sdi); +} + +#ifdef notyet +static void +siba_destroy_devinfo(struct siba_devinfo *sdi) +{ + + resource_list_free(&sdi->sdi_rl); + free(sdi, M_DEVBUF); +} +#endif + +/* XXX is this needed? */ +static device_t +siba_add_child(device_t dev, int order, const char *name, int unit) +{ +#if 1 + + device_printf(dev, "%s: entry\n", __func__); + return (NULL); +#else + device_t child; + struct siba_devinfo *sdi; + + child = device_add_child_ordered(dev, order, name, unit); + if (child == NULL) + return (NULL); + + sdi = malloc(sizeof(struct siba_devinfo), M_DEVBUF, M_NOWAIT|M_ZERO); + if (sdi == NULL) + return (NULL); + + device_set_ivars(child, sdi); + return (child); +#endif +} + +int +siba_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) +{ + struct siba_devinfo *sdi; + + sdi = device_get_ivars(child); + + switch (which) { + case SIBA_IVAR_VENDOR: + *result = sdi->sdi_vid; + break; + case SIBA_IVAR_DEVICE: + *result = sdi->sdi_devid; + break; + case SIBA_IVAR_REVID: + *result = sdi->sdi_rev; + break; + case SIBA_IVAR_CORE_INDEX: + *result = sdi->sdi_idx; + break; + default: + return (ENOENT); + } + + return (0); +} + +int +siba_write_ivar(device_t dev, device_t child, int which, uintptr_t value) +{ + + return (EINVAL); +} + +static void +siba_probe_nomatch(device_t dev, device_t child) +{ + + /* + * Announce devices which weren't attached after we probed the bus. + */ + if (siba_debug) { + struct siba_devid *sd; + + sd = siba_dev_match(siba_get_vendor(child), + siba_get_device(child), SIBA_REV_ANY); + if (sd != NULL && sd->sd_desc != NULL) { + device_printf(dev, "<%s> " + "at device %d (no driver attached)\n", + sd->sd_desc, siba_get_core_index(child)); + } else { + device_printf(dev, "<0x%04x, 0x%04x> " + "at device %d (no driver attached)\n", + siba_get_vendor(child), siba_get_device(child), + siba_get_core_index(child)); + } + } +} + +static int +siba_print_all_resources(device_t dev) +{ + struct siba_devinfo *sdi = device_get_ivars(dev); + struct resource_list *rl = &sdi->sdi_rl; + int retval = 0; + + if (STAILQ_FIRST(rl)) + retval += printf(" at"); + + retval += resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#lx"); + retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%ld"); + + return (retval); +} + +static struct resource_list * +siba_get_reslist(device_t dev, device_t child) +{ + struct siba_devinfo *sdi = device_get_ivars(child); + + return (&sdi->sdi_rl); +} + +static device_method_t siba_methods[] = { + /* Device interface */ + DEVMETHOD(device_attach, siba_attach), + DEVMETHOD(device_detach, bus_generic_detach), + DEVMETHOD(device_probe, siba_probe), + DEVMETHOD(device_resume, bus_generic_resume), + DEVMETHOD(device_shutdown, bus_generic_shutdown), + DEVMETHOD(device_suspend, bus_generic_suspend), + + /* Bus interface */ + DEVMETHOD(bus_activate_resource,siba_activate_resource), + DEVMETHOD(bus_add_child, siba_add_child), + DEVMETHOD(bus_alloc_resource, siba_alloc_resource), + DEVMETHOD(bus_get_resource_list,siba_get_reslist), + DEVMETHOD(bus_print_child, siba_print_child), + DEVMETHOD(bus_probe_nomatch, siba_probe_nomatch), + DEVMETHOD(bus_read_ivar, siba_read_ivar), + DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), + DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), + DEVMETHOD(bus_write_ivar, siba_write_ivar), + + {0, 0}, +}; + +static driver_t siba_driver = { + "siba", + siba_methods, + sizeof(struct siba_softc), +}; +static devclass_t siba_devclass; + +DRIVER_MODULE(siba, nexus, siba_driver, siba_devclass, 0, 0); diff --git a/sys/dev/siba/siba_ids.h b/sys/dev/siba/siba_ids.h new file mode 100644 index 0000000..c7acd20 --- /dev/null +++ b/sys/dev/siba/siba_ids.h @@ -0,0 +1,71 @@ +/*- + * Copyright (c) 2007 Bruce M. Simpson. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _SIBA_SIBA_IDS_H_ +#define _SIBA_SIBA_IDS_H_ + +/* + * Constants and structures for SiBa bus enumeration. + */ + +struct siba_devid { + uint16_t sd_vendor; + uint16_t sd_device; + uint8_t sd_rev; + char *sd_desc; +}; + +/* + * Device IDs + */ +#define SIBA_DEVID_ANY 0xffff +#define SIBA_DEVID_CHIPCOMMON 0x0800 +#define SIBA_DEVID_INSIDELINE 0x0801 +#define SIBA_DEVID_SDRAM 0x0803 +#define SIBA_DEVID_PCI 0x0804 +#define SIBA_DEVID_MIPS 0x0805 +#define SIBA_DEVID_ETHERNET 0x0806 +#define SIBA_DEVID_MODEM 0x0807 +#define SIBA_DEVID_USB 0x0808 +#define SIBA_DEVID_IPSEC 0x080b +#define SIBA_DEVID_SDRAMDDR 0x080f +#define SIBA_DEVID_EXTIF 0x0811 +#define SIBA_DEVID_MIPS_3302 0x0816 + +/* + * Vendor IDs + */ +#define SIBA_VID_ANY 0xffff +#define SIBA_VID_BROADCOM 0x4243 + +/* + * Revision IDs + */ +#define SIBA_REV_ANY 0xff + +#endif /*_SIBA_SIBA_IDS_H_ */ diff --git a/sys/dev/siba/siba_pcib.c b/sys/dev/siba/siba_pcib.c new file mode 100644 index 0000000..a872c55 --- /dev/null +++ b/sys/dev/siba/siba_pcib.c @@ -0,0 +1,432 @@ +/*- + * Copyright (c) 2007 Bruce M. Simpson. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Child driver for PCI host bridge core. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> +#include <sys/kernel.h> +#include <sys/module.h> +#include <sys/rman.h> +#include <sys/malloc.h> +#include <sys/endian.h> + +#include <vm/vm.h> +#include <vm/pmap.h> +#include <vm/vm_extern.h> + +#include <machine/bus.h> +#include <machine/cpu.h> +#include <machine/pcb.h> +#include <machine/pmap.h> + +#include <dev/pci/pcireg.h> +#include <dev/pci/pcivar.h> +#include <dev/pci/pcib_private.h> + +#include "pcib_if.h" + +#include <dev/siba/sibavar.h> +#include <dev/siba/sibareg.h> +#include <dev/siba/siba_ids.h> +#include <dev/siba/siba_pcibvar.h> + +#ifndef MIPS_MEM_RID +#define MIPS_MEM_RID 0x20 +#endif + +#define SBPCI_SLOTMAX 15 + +#define SBPCI_READ_4(sc, reg) \ + bus_space_write_4((sc)->sc_bt, (sc)->sc_bh, (reg)) + +#define SBPCI_WRITE_4(sc, reg, val) \ + bus_space_write_4((sc)->sc_bt, (sc)->sc_bh, (reg), (val)) + +/* + * PCI Configuration space window (64MB). + * contained in SBTOPCI1 window. + */ +#define SBPCI_CFGBASE 0x0C000000 +#define SBPCI_CFGSIZE 0x01000000 + +#define SBPCI_SBTOPCI0 0x100 +#define SBPCI_SBTOPCI1 0x104 +#define SBPCI_SBTOPCI2 0x108 + +/* + * TODO: implement type 1 config space access (ie beyond bus 0) + * we may need to tweak the windows to do this + * TODO: interrupt routing. + * TODO: fully implement bus allocation. + * TODO: implement resource managers. + * TODO: code cleanup. + */ + +static int siba_pcib_activate_resource(device_t, device_t, int, + int, struct resource *); +static struct resource * + siba_pcib_alloc_resource(device_t, device_t, int, int *, + u_long , u_long, u_long, u_int); +static int siba_pcib_attach(device_t); +static int siba_pcib_deactivate_resource(device_t, device_t, int, + int, struct resource *); +static int siba_pcib_maxslots(device_t); +static int siba_pcib_probe(device_t); +static u_int32_t + siba_pcib_read_config(device_t, u_int, u_int, u_int, u_int, + int); +static int siba_pcib_read_ivar(device_t, device_t, int, uintptr_t *); +static int siba_pcib_release_resource(device_t, device_t, int, int, + struct resource *); +static int siba_pcib_route_interrupt(device_t, device_t, int); +static int siba_pcib_setup_intr(device_t, device_t, struct resource *, + int, driver_filter_t *, driver_intr_t *, void *, void **); +static int siba_pcib_teardown_intr(device_t, device_t, struct resource *, + void *); +static void siba_pcib_write_config(device_t, u_int, u_int, u_int, u_int, + u_int32_t, int); +static int siba_pcib_write_ivar(device_t, device_t, int, uintptr_t); + +static int +siba_pcib_probe(device_t dev) +{ + + /* TODO: support earlier cores. */ + /* TODO: Check if PCI host mode is enabled in the SPROM. */ + if (siba_get_vendor(dev) == SIBA_VID_BROADCOM && + siba_get_device(dev) == SIBA_DEVID_PCI) { + device_set_desc(dev, "SiBa-to-PCI host bridge"); + return (BUS_PROBE_DEFAULT); + } + + return (ENXIO); +} + +//extern int rman_debug; + +static int +siba_pcib_attach(device_t dev) +{ + struct siba_pcib_softc *sc = device_get_softc(dev); + int rid; + + /* + * Allocate the resources which the parent bus has already + * determined for us. + */ + rid = MIPS_MEM_RID; /* XXX */ + //rman_debug = 1; + sc->sc_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, + RF_ACTIVE); + if (sc->sc_mem == NULL) { + device_printf(dev, "unable to allocate memory\n"); + return (ENXIO); + } + + sc->sc_bt = rman_get_bustag(sc->sc_mem); + sc->sc_bh = rman_get_bushandle(sc->sc_mem); + + device_printf(dev, "bridge registers addr 0x%08x vaddr %p\n", + sc->sc_bh, rman_get_virtual(sc->sc_mem)); + + SBPCI_WRITE_4(sc, 0x0000, 0x05); + SBPCI_WRITE_4(sc, 0x0000, 0x0D); + DELAY(150); + SBPCI_WRITE_4(sc, 0x0000, 0x0F); + SBPCI_WRITE_4(sc, 0x0010, 0x01); + DELAY(1); + + bus_space_handle_t sc_cfg_hand; + int error; + + /* + * XXX this doesn't actually do anything on mips; however... should + * we not be mapping to KSEG1? we need to wire down the range. + */ + error = bus_space_map(sc->sc_bt, SBPCI_CFGBASE, SBPCI_CFGSIZE, + 0, &sc_cfg_hand); + if (error) { + device_printf(dev, "cannot map PCI configuration space\n"); + return (ENXIO); + } + device_printf(dev, "mapped pci config space at 0x%08x\n", sc_cfg_hand); + + /* + * Setup configuration, io, and dma space windows. + * XXX we need to be able to do type 1 too. + * we probably don't need to be able to do i/o cycles. + */ + SBPCI_WRITE_4(sc, SBPCI_SBTOPCI0, 1); /* I/O read/write window */ + SBPCI_WRITE_4(sc, SBPCI_SBTOPCI1, 2); /* type 0 configuration only */ + SBPCI_WRITE_4(sc, SBPCI_SBTOPCI2, 1 << 30); /* memory only */ + DELAY(500); + + /* XXX resource managers */ + + device_add_child(dev, "pci", -1); + return (bus_generic_attach(dev)); +} + +/* bus functions */ + +static int +siba_pcib_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) +{ + struct siba_pcib_softc *sc; + + sc = device_get_softc(dev); + switch (which) { + case PCIB_IVAR_BUS: + *result = sc->sc_bus; + return (0); + } + + return (ENOENT); +} + +static int +siba_pcib_write_ivar(device_t dev, device_t child, int which, uintptr_t value) +{ + struct siba_pcib_softc *sc; + + sc = device_get_softc(dev); + switch (which) { + case PCIB_IVAR_BUS: + sc->sc_bus = value; + return (0); + } + + return (ENOENT); +} + +static int +siba_pcib_setup_intr(device_t dev, device_t child, struct resource *ires, + int flags, driver_filter_t *filt, driver_intr_t *intr, void *arg, + void **cookiep) +{ + + return (BUS_SETUP_INTR(device_get_parent(dev), child, ires, flags, + filt, intr, arg, cookiep)); +} + +static int +siba_pcib_teardown_intr(device_t dev, device_t child, struct resource *vec, + void *cookie) +{ + + return (BUS_TEARDOWN_INTR(device_get_parent(dev), child, vec, cookie)); +} + +static struct resource * +siba_pcib_alloc_resource(device_t bus, device_t child, int type, int *rid, + u_long start, u_long end, u_long count, u_int flags) +{ +#if 1 + + //device_printf(bus, "%s: not yet implemented\n", __func__); + return (NULL); +#else + bus_space_tag_t tag; + struct siba_pcib_softc *sc = device_get_softc(bus); + struct rman *rmanp; + struct resource *rv; + + tag = 0; + rv = NULL; + switch (type) { + case SYS_RES_IRQ: + rmanp = &sc->sc_irq_rman; + break; + + case SYS_RES_MEMORY: + rmanp = &sc->sc_mem_rman; + tag = &sc->sc_pci_memt; + break; + + default: + return (rv); + } + + rv = rman_reserve_resource(rmanp, start, end, count, flags, child); + if (rv != NULL) { + rman_set_rid(rv, *rid); + if (type == SYS_RES_MEMORY) { +#if 0 + rman_set_bustag(rv, tag); + rman_set_bushandle(rv, rman_get_bushandle(sc->sc_mem) + + (rman_get_start(rv) - IXP425_PCI_MEM_HWBASE)); +#endif + } + } + + return (rv); +#endif +} + +static int +siba_pcib_activate_resource(device_t bus, device_t child, int type, int rid, + struct resource *r) +{ + + device_printf(bus, "%s: not yet implemented\n", __func__); + device_printf(bus, "%s called activate_resource\n", + device_get_nameunit(child)); + return (ENXIO); +} + +static int +siba_pcib_deactivate_resource(device_t bus, device_t child, int type, int rid, + struct resource *r) +{ + + device_printf(bus, "%s: not yet implemented\n", __func__); + device_printf(bus, "%s called deactivate_resource\n", + device_get_nameunit(child)); + return (ENXIO); +} + +static int +siba_pcib_release_resource(device_t bus, device_t child, int type, int rid, + struct resource *r) +{ + + device_printf(bus, "%s: not yet implemented\n", __func__); + device_printf(bus, "%s called release_resource\n", + device_get_nameunit(child)); + return (ENXIO); +} + +/* pcib interface functions */ + +static int +siba_pcib_maxslots(device_t dev) +{ + + return (SBPCI_SLOTMAX); +} + +/* + * This needs hacking and fixery. It is currently broke and hangs. + * Debugging it will be tricky; there seems to be no way to enable + * a target abort which would cause a nice target abort. + * Look at linux again? + */ +static u_int32_t +siba_pcib_read_config(device_t dev, u_int bus, u_int slot, u_int func, + u_int reg, int bytes) +{ + struct siba_pcib_softc *sc = device_get_softc(dev); + bus_addr_t cfgaddr; + uint32_t cfgtag; + uint32_t val; + + /* XXX anything higher than slot 2 currently seems to hang the bus. + * not sure why this is; look at linux again + */ + if (bus != 0 || slot > 2) { + printf("%s: bad b/s/f %d/%d/%d\n", __func__, bus, slot, func); + return 0xffffffff; // XXX + } + + device_printf(dev, "requested %d bytes from b/s/f %d/%d/%d reg %d\n", + bytes, bus, slot, func, reg); + + /* + * The configuration tag on the broadcom is weird. + */ + SBPCI_WRITE_4(sc, SBPCI_SBTOPCI1, 2); /* XXX again??? */ + cfgtag = ((1 << slot) << 16) | (func << 8); + cfgaddr = SBPCI_CFGBASE | cfgtag | (reg & ~3); + + /* cfg space i/o is always 32 bits on this bridge */ + printf("reading 4 bytes from %08x\n", cfgaddr); + val = *(volatile uint32_t *)MIPS_PHYS_TO_KSEG1(cfgaddr); /* XXX MIPS */ + + val = bswap32(val); /* XXX seems to be needed for now */ + + /* swizzle and return what was asked for */ + val &= 0xffffffff >> ((4 - bytes) * 8); + + return (val); +} + +static void +siba_pcib_write_config(device_t dev, u_int bus, u_int slot, + u_int func, u_int reg, u_int32_t val, int bytes) +{ + + /* write to pci configuration space */ + //device_printf(dev, "%s: not yet implemented\n", __func__); +} + +static int +siba_pcib_route_interrupt(device_t bridge, device_t device, int pin) +{ + + //device_printf(bridge, "%s: not yet implemented\n", __func__); + return (-1); +} + +static device_method_t siba_pcib_methods[] = { + /* Device interface */ + DEVMETHOD(device_attach, siba_pcib_attach), + DEVMETHOD(device_probe, siba_pcib_probe), + + /* Bus interface */ + DEVMETHOD(bus_print_child, bus_generic_print_child), + DEVMETHOD(bus_read_ivar, siba_pcib_read_ivar), + DEVMETHOD(bus_write_ivar, siba_pcib_write_ivar), + DEVMETHOD(bus_setup_intr, siba_pcib_setup_intr), + DEVMETHOD(bus_teardown_intr, siba_pcib_teardown_intr), + DEVMETHOD(bus_alloc_resource, siba_pcib_alloc_resource), + DEVMETHOD(bus_activate_resource, siba_pcib_activate_resource), + DEVMETHOD(bus_deactivate_resource, siba_pcib_deactivate_resource), + DEVMETHOD(bus_release_resource, siba_pcib_release_resource), + + /* pcib interface */ + DEVMETHOD(pcib_maxslots, siba_pcib_maxslots), + DEVMETHOD(pcib_read_config, siba_pcib_read_config), + DEVMETHOD(pcib_write_config, siba_pcib_write_config), + DEVMETHOD(pcib_route_interrupt, siba_pcib_route_interrupt), + + {0, 0}, +}; + +static driver_t siba_pcib_driver = { + "pcib", + siba_pcib_methods, + sizeof(struct siba_softc), +}; +static devclass_t siba_pcib_devclass; + +DRIVER_MODULE(siba_pcib, siba, siba_pcib_driver, siba_pcib_devclass, 0, 0); diff --git a/sys/dev/siba/siba_pcibvar.h b/sys/dev/siba/siba_pcibvar.h new file mode 100644 index 0000000..6de72ff --- /dev/null +++ b/sys/dev/siba/siba_pcibvar.h @@ -0,0 +1,52 @@ +/*- + * Copyright (c) 2007 Bruce M. Simpson. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _SIBA_PCIBVAR_H_ +#define _SIBA_PCIBVAR_H_ + +#include <sys/rman.h> + +struct siba_pcib_softc { + device_t sc_dev; /* Device ID */ + u_int sc_bus; /* PCI bus number */ + struct resource *sc_mem; /* siba memory window */ + struct resource *sc_csr; /* config space */ + + bus_space_tag_t sc_bt; + bus_space_handle_t sc_bh; +#if 0 + bus_addr_t sc_maddr; + bus_size_t sc_msize; + + struct bus_space sc_pci_memt; + struct bus_space sc_pci_iot; + bus_dma_tag_t sc_dmat; +#endif +}; + +#endif /* _SIBA_PCIBVAR_H_ */ diff --git a/sys/dev/siba/sibareg.h b/sys/dev/siba/sibareg.h new file mode 100644 index 0000000..dc1b7f7 --- /dev/null +++ b/sys/dev/siba/sibareg.h @@ -0,0 +1,73 @@ +/*- + * Copyright (c) 2007 Bruce M. Simpson. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +/* + * TODO: sprom + * TODO: implement dma translation bits (if needed for system bus) + */ + +#ifndef _SIBA_SIBAREG_H_ +#define _SIBA_SIBAREG_H_ + +#define SIBA_CORE_LEN 0x00001000 /* Size of cfg per core */ +#define SIBA_CFG_END 0x00010000 /* Upper bound of cfg space */ +#define SIBA_MAX_CORES (SIBA_CFG_END/SIBA_CORE_LEN) /* #max cores */ + +/* offset of high ID register */ +#define SIBA_CORE_IDLO 0x00000ff8 +#define SIBA_CORE_IDHI 0x00000ffc + +/* + * Offsets of ChipCommon core registers. + * XXX: move to siba_cc + */ +#define SIBA_CC_UART0 0x00000300 /* offset of UART0 */ +#define SIBA_CC_UART1 0x00000400 /* offset of UART1 */ + +#define SIBA_CC_CCID 0x0000 +#define SIBA_CC_IDMASK 0x0000FFFF +#define SIBA_CC_REVMASK 0x000F0000 +#define SIBA_CC_REVSHIFT 16 +#define SIBA_CC_PACKMASK 0x00F00000 +#define SIBA_CC_PACKSHIFT 20 +#define SIBA_CC_NRCORESMASK 0x0F000000 +#define SIBA_CC_NRCORESSHIFT 24 + +#define SIBA_IDHIGH_RCLO 0x0000000F /* Revision Code (low part) */ +#define SIBA_IDHIGH_CC 0x00008FF0 /* Core Code */ +#define SIBA_IDHIGH_CC_SHIFT 4 +#define SIBA_IDHIGH_RCHI 0x00007000 /* Revision Code (high part) */ +#define SIBA_IDHIGH_RCHI_SHIFT 8 +#define SIBA_IDHIGH_VC 0xFFFF0000 /* Vendor Code */ +#define SIBA_IDHIGH_VC_SHIFT 16 + +#define SIBA_CCID_BCM4710 0x4710 +#define SIBA_CCID_BCM4704 0x4704 +#define SIBA_CCID_SENTRY5 0x5365 + +#endif /* _SIBA_SIBAREG_H_ */ diff --git a/sys/dev/siba/sibavar.h b/sys/dev/siba/sibavar.h new file mode 100644 index 0000000..f9c231b --- /dev/null +++ b/sys/dev/siba/sibavar.h @@ -0,0 +1,92 @@ +/*- + * Copyright (c) 2007 Bruce M. Simpson. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _SIBA_SIBAVAR_H_ +#define _SIBA_SIBAVAR_H_ + +#include <sys/rman.h> + +struct siba_softc { + device_t sc_dev; /* Device ID */ + struct resource *sc_mem; /* Memory window on nexus */ + + bus_space_tag_t sc_bt; + bus_space_handle_t sc_bh; + bus_addr_t sc_maddr; + bus_size_t sc_msize; + + uint8_t sc_ncores; +}; + +struct siba_devinfo { + struct resource_list sdi_rl; + /*devhandle_t sdi_devhandle; XXX*/ + /*struct rman sdi_intr_rman;*/ + + /* Accessors are needed for ivars below. */ + uint16_t sdi_vid; + uint16_t sdi_devid; + uint8_t sdi_rev; + uint8_t sdi_idx; /* core index on bus */ + uint8_t sdi_irq; /* TODO */ +}; + +#define siba_read_2(sc, core, reg) \ + bus_space_read_2((sc)->sc_bt, (sc)->sc_bh, \ + (core * SIBA_CORE_LEN) + (reg)) + +#define siba_read_4(sc, core, reg) \ + bus_space_read_4((sc)->sc_bt, (sc)->sc_bh, \ + (core * SIBA_CORE_LEN) + (reg)) + +#define siba_write_2(sc, core, reg, val) \ + bus_space_write_2((sc)->sc_bt, (sc)->sc_bh, \ + (core * SIBA_CORE_LEN) + (reg), (val)) + +#define siba_write_4(sc, core, reg, val) \ + bus_space_write_4((sc)->sc_bt, (sc)->sc_bh, \ + (core * SIBA_CORE_LEN) + (reg), (val)) + +enum siba_device_ivars { + SIBA_IVAR_VENDOR, + SIBA_IVAR_DEVICE, + SIBA_IVAR_REVID, + SIBA_IVAR_CORE_INDEX +}; + +#define SIBA_ACCESSOR(var, ivar, type) \ + __BUS_ACCESSOR(siba, var, SIBA, ivar, type) + +SIBA_ACCESSOR(vendor, VENDOR, uint16_t) +SIBA_ACCESSOR(device, DEVICE, uint16_t) +SIBA_ACCESSOR(revid, REVID, uint8_t) +SIBA_ACCESSOR(core_index, CORE_INDEX, uint8_t) + +#undef SIBA_ACCESSOR + +#endif /* _SIBA_SIBAVAR_H_ */ |