summaryrefslogtreecommitdiffstats
path: root/sys/dev/siba
diff options
context:
space:
mode:
authorweongyo <weongyo@FreeBSD.org>2010-01-31 21:18:22 +0000
committerweongyo <weongyo@FreeBSD.org>2010-01-31 21:18:22 +0000
commit9d4753ed16c144e682520b2681c7a13d70018387 (patch)
tree74efb352cc6cb4d089c66a66ce1354aeab587939 /sys/dev/siba
parentc841cfa60246ddcfedc9a424428a5a824da147d9 (diff)
downloadFreeBSD-src-9d4753ed16c144e682520b2681c7a13d70018387.zip
FreeBSD-src-9d4753ed16c144e682520b2681c7a13d70018387.tar.gz
Adds siba_bwn module which is used with bwn(4). Main purpose of this
module is to distinguish parts of Silicon Backplane and of Broadcom Wireless.
Diffstat (limited to 'sys/dev/siba')
-rw-r--r--sys/dev/siba/siba.c106
-rw-r--r--sys/dev/siba/siba_bwn.c366
-rw-r--r--sys/dev/siba/siba_cc.c4
-rw-r--r--sys/dev/siba/siba_core.c2007
-rw-r--r--sys/dev/siba/siba_ids.h48
-rw-r--r--sys/dev/siba/siba_pcib.c19
-rw-r--r--sys/dev/siba/sibareg.h403
-rw-r--r--sys/dev/siba/sibavar.h357
8 files changed, 3153 insertions, 157 deletions
diff --git a/sys/dev/siba/siba.c b/sys/dev/siba/siba.c
index 04a5309..541585b 100644
--- a/sys/dev/siba/siba.c
+++ b/sys/dev/siba/siba.c
@@ -37,9 +37,9 @@ __FBSDID("$FreeBSD$");
#include <machine/bus.h>
-#include <dev/siba/sibavar.h>
-#include <dev/siba/sibareg.h>
#include <dev/siba/siba_ids.h>
+#include <dev/siba/sibareg.h>
+#include <dev/siba/sibavar.h>
/*
* TODO: De-mipsify this code.
@@ -77,7 +77,7 @@ static struct siba_devid siba_devids[] = {
"MIPS core" },
{ SIBA_VID_BROADCOM, SIBA_DEVID_ETHERNET, SIBA_REV_ANY,
"Ethernet core" },
- { SIBA_VID_BROADCOM, SIBA_DEVID_USB, SIBA_REV_ANY,
+ { SIBA_VID_BROADCOM, SIBA_DEVID_USB11_HOSTDEV, SIBA_REV_ANY,
"USB host controller" },
{ SIBA_VID_BROADCOM, SIBA_DEVID_IPSEC, SIBA_REV_ANY,
"IPSEC accelerator" },
@@ -103,7 +103,6 @@ static struct siba_devid *
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);
@@ -112,30 +111,7 @@ 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);
-}
+uint8_t siba_getncores(device_t, uint16_t);
/*
* On the Sentry5, the system bus IRQs are the same as the
@@ -156,7 +132,7 @@ siba_getirq(uint16_t devid)
case SIBA_DEVID_IPSEC:
irq = 2;
break;
- case SIBA_DEVID_USB:
+ case SIBA_DEVID_USB11_HOSTDEV:
irq = 3;
break;
case SIBA_DEVID_PCI:
@@ -188,7 +164,7 @@ siba_probe(device_t dev)
uint16_t ccid;
int rid;
- sc->sc_dev = dev;
+ sc->siba_dev = dev;
//rman_debug = 1; /* XXX */
@@ -197,24 +173,24 @@ siba_probe(device_t dev)
* was compiled with.
*/
rid = MIPS_MEM_RID;
- sc->sc_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ sc->siba_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
RF_ACTIVE);
- if (sc->sc_mem == NULL) {
+ if (sc->siba_mem_res == 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);
+ sc->siba_mem_bt = rman_get_bustag(sc->siba_mem_res);
+ sc->siba_mem_bh = rman_get_bushandle(sc->siba_mem_res);
+ sc->siba_maddr = rman_get_start(sc->siba_mem_res);
+ sc->siba_msize = rman_get_size(sc->siba_mem_res);
if (siba_debug) {
device_printf(dev, "start %08x len %08x\n",
- sc->sc_maddr, sc->sc_msize);
+ sc->siba_maddr, sc->siba_msize);
}
- idlo = siba_read_4(sc, 0, SIBA_CORE_IDLO);
- idhi = siba_read_4(sc, 0, SIBA_CORE_IDHI);
+ idlo = siba_mips_read_4(sc, 0, SIBA_IDLOW);
+ idhi = siba_mips_read_4(sc, 0, SIBA_IDHIGH);
ccid = ((idhi & 0x8ff0) >> 4);
if (siba_debug) {
device_printf(dev, "idlo = %08x\n", idlo);
@@ -256,7 +232,7 @@ siba_probe(device_t dev)
uint16_t cc_id;
uint16_t cc_rev;
- ccidreg = siba_read_4(sc, 0, SIBA_CC_CCID);
+ ccidreg = siba_mips_read_4(sc, 0, SIBA_CC_CHIPID);
cc_id = (ccidreg & SIBA_CC_IDMASK);
cc_rev = (ccidreg & SIBA_CC_REVMASK) >> SIBA_CC_REVSHIFT;
if (siba_debug) {
@@ -264,9 +240,9 @@ siba_probe(device_t dev)
ccidreg, cc_id, cc_rev);
}
- sc->sc_ncores = siba_getncores(cc_id);
+ sc->siba_ncores = siba_getncores(dev, cc_id);
if (siba_debug) {
- device_printf(dev, "%d cores detected.\n", sc->sc_ncores);
+ device_printf(dev, "%d cores detected.\n", sc->siba_ncores);
}
/*
@@ -275,36 +251,38 @@ siba_probe(device_t dev)
*/
rid = MIPS_MEM_RID;
int result;
- result = bus_release_resource(dev, SYS_RES_MEMORY, rid, sc->sc_mem);
+ result = bus_release_resource(dev, SYS_RES_MEMORY, rid,
+ sc->siba_mem_res);
if (result != 0) {
device_printf(dev, "error %d releasing resource\n", result);
return (ENXIO);
}
uint32_t total;
- total = sc->sc_ncores * SIBA_CORE_LEN;
+ total = sc->siba_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) {
+ sc->siba_mem_res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid,
+ sc->siba_maddr, sc->siba_maddr + total - 1, total, RF_ACTIVE);
+ if (sc->siba_mem_res == 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);
+ sc->siba_mem_bt = rman_get_bustag(sc->siba_mem_res);
+ sc->siba_mem_bh = rman_get_bushandle(sc->siba_mem_res);
+ sc->siba_maddr = rman_get_start(sc->siba_mem_res);
+ sc->siba_msize = rman_get_size(sc->siba_mem_res);
if (siba_debug) {
device_printf(dev, "after remapping: start %08x len %08x\n",
- sc->sc_maddr, sc->sc_msize);
+ sc->siba_maddr, sc->siba_msize);
}
- bus_set_resource(dev, SYS_RES_MEMORY, rid, sc->sc_maddr, sc->sc_msize);
+ bus_set_resource(dev, SYS_RES_MEMORY, rid, sc->siba_maddr,
+ sc->siba_msize);
/*
* We need a manager for the space we claim on nexus to
@@ -313,12 +291,13 @@ siba_probe(device_t dev)
* 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_start = sc->siba_maddr;
+ mem_rman.rm_end = sc->siba_maddr + sc->siba_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) {
+ rman_manage_region(&mem_rman, mem_rman.rm_start,
+ mem_rman.rm_end) != 0) {
panic("%s: mem_rman", __func__);
}
@@ -344,7 +323,7 @@ siba_attach(device_t dev)
* 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++) {
+ for (idx = 0; idx < sc->siba_ncores; idx++) {
sdi = siba_setup_devinfo(dev, idx);
child = device_add_child(dev, NULL, -1);
if (child == NULL)
@@ -483,13 +462,14 @@ siba_setup_devinfo(device_t dev, uint8_t idx)
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);
+ idlo = siba_mips_read_4(sc, idx, SIBA_IDLOW);
+ idhi = siba_mips_read_4(sc, idx, SIBA_IDHIGH);
- vendorid = (idhi & SIBA_IDHIGH_VC) >> SIBA_IDHIGH_VC_SHIFT;
+ vendorid = (idhi & SIBA_IDHIGH_VENDORMASK) >>
+ SIBA_IDHIGH_VENDOR_SHIFT;
devid = ((idhi & 0x8ff0) >> 4);
- rev = (idhi & SIBA_IDHIGH_RCLO);
- rev |= (idhi & SIBA_IDHIGH_RCHI) >> SIBA_IDHIGH_RCHI_SHIFT;
+ rev = (idhi & SIBA_IDHIGH_REVLO);
+ rev |= (idhi & SIBA_IDHIGH_REVHI) >> SIBA_IDHIGH_REVHI_SHIFT;
sdi->sdi_vid = vendorid;
sdi->sdi_devid = devid;
@@ -500,7 +480,7 @@ siba_setup_devinfo(device_t dev, uint8_t idx)
/*
* Determine memory window on bus and irq if one is needed.
*/
- baseaddr = sc->sc_maddr + (idx * SIBA_CORE_LEN);
+ baseaddr = sc->siba_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);
diff --git a/sys/dev/siba/siba_bwn.c b/sys/dev/siba/siba_bwn.c
new file mode 100644
index 0000000..a5513bd
--- /dev/null
+++ b/sys/dev/siba/siba_bwn.c
@@ -0,0 +1,366 @@
+/*-
+ * Copyright (c) 2009-2010 Weongyo Jeong <weongyo@freebsd.org>
+ * 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,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
+ * redistribution must be conditioned upon including a substantially
+ * similar Disclaimer requirement for further binary redistribution.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * Sonics Silicon Backplane front-end for bwn(4).
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/module.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/errno.h>
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <sys/bus.h>
+#include <sys/rman.h>
+#include <sys/socket.h>
+
+#include <net/if.h>
+#include <net/if_media.h>
+#include <net/if_arp.h>
+
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcireg.h>
+
+#include <dev/siba/siba_ids.h>
+#include <dev/siba/sibareg.h>
+#include <dev/siba/sibavar.h>
+
+/*
+ * PCI glue.
+ */
+
+struct siba_bwn_softc {
+ /* Child driver using MSI. */
+ device_t ssc_msi_child;
+ struct siba_softc ssc_siba;
+};
+
+#define BS_BAR 0x10
+#define PCI_VENDOR_BROADCOM 0x14e4
+#define N(a) (sizeof(a) / sizeof(a[0]))
+
+static const struct siba_dev {
+ uint16_t vid;
+ uint16_t did;
+ const char *desc;
+} siba_devices[] = {
+ { PCI_VENDOR_BROADCOM, 0x4301, "Broadcom BCM4301 802.11b Wireless" },
+ { PCI_VENDOR_BROADCOM, 0x4306, "Unknown" },
+ { PCI_VENDOR_BROADCOM, 0x4307, "Broadcom BCM4307 802.11b Wireless" },
+ { PCI_VENDOR_BROADCOM, 0x4311, "Broadcom BCM4311 802.11b/g Wireless" },
+ { PCI_VENDOR_BROADCOM, 0x4312,
+ "Broadcom BCM4312 802.11a/b/g Wireless" },
+ { PCI_VENDOR_BROADCOM, 0x4315, "Broadcom BCM4312 802.11b/g Wireless" },
+ { PCI_VENDOR_BROADCOM, 0x4318, "Broadcom BCM4318 802.11b/g Wireless" },
+ { PCI_VENDOR_BROADCOM, 0x4319,
+ "Broadcom BCM4318 802.11a/b/g Wireless" },
+ { PCI_VENDOR_BROADCOM, 0x4320, "Broadcom BCM4306 802.11b/g Wireless" },
+ { PCI_VENDOR_BROADCOM, 0x4321, "Broadcom BCM4306 802.11a Wireless" },
+ { PCI_VENDOR_BROADCOM, 0x4324,
+ "Broadcom BCM4309 802.11a/b/g Wireless" },
+ { PCI_VENDOR_BROADCOM, 0x4325, "Broadcom BCM4306 802.11b/g Wireless" },
+ { PCI_VENDOR_BROADCOM, 0x4328, "Unknown" },
+ { PCI_VENDOR_BROADCOM, 0x4329, "Unknown" },
+ { PCI_VENDOR_BROADCOM, 0x432b, "Unknown" }
+};
+
+device_t siba_add_child(device_t, struct siba_softc *, int, const char *,
+ int);
+int siba_core_attach(struct siba_softc *);
+int siba_core_detach(struct siba_softc *);
+int siba_core_suspend(struct siba_softc *);
+int siba_core_resume(struct siba_softc *);
+
+static int
+siba_bwn_probe(device_t dev)
+{
+ int i;
+ uint16_t did, vid;
+
+ did = pci_get_device(dev);
+ vid = pci_get_vendor(dev);
+
+ for (i = 0; i < N(siba_devices); i++) {
+ if (siba_devices[i].did == did && siba_devices[i].vid == vid) {
+ device_set_desc(dev, siba_devices[i].desc);
+ return (BUS_PROBE_DEFAULT);
+ }
+ }
+ return (ENXIO);
+}
+
+static int
+siba_bwn_attach(device_t dev)
+{
+ struct siba_bwn_softc *ssc = device_get_softc(dev);
+ struct siba_softc *siba = &ssc->ssc_siba;
+
+ siba->siba_dev = dev;
+ siba->siba_type = SIBA_TYPE_PCI;
+
+ /*
+ * Enable bus mastering.
+ */
+ pci_enable_busmaster(dev);
+
+ /*
+ * Setup memory-mapping of PCI registers.
+ */
+ siba->siba_mem_rid = SIBA_PCIR_BAR;
+ siba->siba_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
+ &siba->siba_mem_rid, RF_ACTIVE);
+ if (siba->siba_mem_res == NULL) {
+ device_printf(dev, "cannot map register space\n");
+ return (ENXIO);
+ }
+ siba->siba_mem_bt = rman_get_bustag(siba->siba_mem_res);
+ siba->siba_mem_bh = rman_get_bushandle(siba->siba_mem_res);
+
+ /* Get more PCI information */
+ siba->siba_pci_did = pci_get_device(dev);
+ siba->siba_pci_vid = pci_get_vendor(dev);
+ siba->siba_pci_subvid = pci_get_subvendor(dev);
+ siba->siba_pci_subdid = pci_get_subdevice(dev);
+
+ return (siba_core_attach(siba));
+}
+
+static int
+siba_bwn_detach(device_t dev)
+{
+ struct siba_bwn_softc *ssc = device_get_softc(dev);
+ struct siba_softc *siba = &ssc->ssc_siba;
+
+ /* check if device was removed */
+ siba->siba_invalid = !bus_child_present(dev);
+
+ pci_disable_busmaster(dev);
+ bus_generic_detach(dev);
+ siba_core_detach(siba);
+
+ bus_release_resource(dev, SYS_RES_MEMORY, BS_BAR, siba->siba_mem_res);
+
+ return (0);
+}
+
+static int
+siba_bwn_shutdown(device_t dev)
+{
+ device_t *devlistp;
+ int devcnt, error = 0, i;
+
+ error = device_get_children(dev, &devlistp, &devcnt);
+ if (error != 0)
+ return (error);
+
+ for (i = 0 ; i < devcnt ; i++)
+ device_shutdown(devlistp[i]);
+ free(devlistp, M_TEMP);
+ return (0);
+}
+
+static int
+siba_bwn_suspend(device_t dev)
+{
+ struct siba_bwn_softc *ssc = device_get_softc(dev);
+ struct siba_softc *siba = &ssc->ssc_siba;
+ device_t *devlistp;
+ int devcnt, error = 0, i, j;
+
+ error = device_get_children(dev, &devlistp, &devcnt);
+ if (error != 0)
+ return (error);
+
+ for (i = 0 ; i < devcnt ; i++) {
+ error = DEVICE_SUSPEND(devlistp[i]);
+ if (error) {
+ for (j = 0; j < i; i++)
+ DEVICE_RESUME(devlistp[j]);
+ return (error);
+ }
+ }
+ free(devlistp, M_TEMP);
+ return (siba_core_suspend(siba));
+}
+
+static int
+siba_bwn_resume(device_t dev)
+{
+ struct siba_bwn_softc *ssc = device_get_softc(dev);
+ struct siba_softc *siba = &ssc->ssc_siba;
+ device_t *devlistp;
+ int devcnt, error = 0, i;
+
+ error = siba_core_resume(siba);
+ if (error != 0)
+ return (error);
+
+ error = device_get_children(dev, &devlistp, &devcnt);
+ if (error != 0)
+ return (error);
+
+ for (i = 0 ; i < devcnt ; i++)
+ DEVICE_RESUME(devlistp[i]);
+ free(devlistp, M_TEMP);
+ return (0);
+}
+
+static device_t
+siba_bwn_add_child(device_t dev, int order, const char *name, int unit)
+{
+ struct siba_bwn_softc *ssc = device_get_softc(dev);
+ struct siba_softc *siba = &ssc->ssc_siba;
+
+ return (siba_add_child(dev, siba, order, name, unit));
+}
+
+/* proxying to the parent */
+static struct resource *
+siba_bwn_alloc_resource(device_t dev, device_t child, int type, int *rid,
+ u_long start, u_long end, u_long count, u_int flags)
+{
+
+ return (BUS_ALLOC_RESOURCE(device_get_parent(dev), dev,
+ type, rid, start, end, count, flags));
+}
+
+/* proxying to the parent */
+static int
+siba_bwn_release_resource(device_t dev, device_t child, int type,
+ int rid, struct resource *r)
+{
+
+ return (BUS_RELEASE_RESOURCE(device_get_parent(dev), dev, type,
+ rid, r));
+}
+
+/* proxying to the parent */
+static int
+siba_bwn_setup_intr(device_t dev, device_t child, struct resource *irq,
+ int flags, driver_filter_t *filter, driver_intr_t *intr, void *arg,
+ void **cookiep)
+{
+
+ return (BUS_SETUP_INTR(device_get_parent(dev), dev, irq, flags,
+ filter, intr, arg, cookiep));
+}
+
+/* proxying to the parent */
+static int
+siba_bwn_teardown_intr(device_t dev, device_t child, struct resource *irq,
+ void *cookie)
+{
+
+ return (BUS_TEARDOWN_INTR(device_get_parent(dev), dev, irq, cookie));
+}
+
+static int
+siba_bwn_find_extcap(device_t dev, device_t child, int capability,
+ int *capreg)
+{
+
+ return (pci_find_extcap(dev, capability, capreg));
+}
+
+static int
+siba_bwn_alloc_msi(device_t dev, device_t child, int *count)
+{
+ struct siba_bwn_softc *ssc;
+ int error;
+
+ ssc = device_get_softc(dev);
+ if (ssc->ssc_msi_child != NULL)
+ return (EBUSY);
+ error = pci_alloc_msi(dev, count);
+ if (error == 0)
+ ssc->ssc_msi_child = child;
+ return (error);
+}
+
+static int
+siba_bwn_release_msi(device_t dev, device_t child)
+{
+ struct siba_bwn_softc *ssc;
+ int error;
+
+ ssc = device_get_softc(dev);
+ if (ssc->ssc_msi_child != child)
+ return (ENXIO);
+ error = pci_release_msi(dev);
+ if (error == 0)
+ ssc->ssc_msi_child = NULL;
+ return (error);
+}
+
+static int
+siba_bwn_msi_count(device_t dev, device_t child)
+{
+
+ return (pci_msi_count(dev));
+}
+
+static device_method_t siba_bwn_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, siba_bwn_probe),
+ DEVMETHOD(device_attach, siba_bwn_attach),
+ DEVMETHOD(device_detach, siba_bwn_detach),
+ DEVMETHOD(device_shutdown, siba_bwn_shutdown),
+ DEVMETHOD(device_suspend, siba_bwn_suspend),
+ DEVMETHOD(device_resume, siba_bwn_resume),
+
+ /* Bus interface */
+ DEVMETHOD(bus_add_child, siba_bwn_add_child),
+ DEVMETHOD(bus_alloc_resource, siba_bwn_alloc_resource),
+ DEVMETHOD(bus_release_resource, siba_bwn_release_resource),
+ DEVMETHOD(bus_setup_intr, siba_bwn_setup_intr),
+ DEVMETHOD(bus_teardown_intr, siba_bwn_teardown_intr),
+
+ /* PCI interface */
+ DEVMETHOD(pci_find_extcap, siba_bwn_find_extcap),
+ DEVMETHOD(pci_alloc_msi, siba_bwn_alloc_msi),
+ DEVMETHOD(pci_release_msi, siba_bwn_release_msi),
+ DEVMETHOD(pci_msi_count, siba_bwn_msi_count),
+
+ { 0,0 }
+};
+static driver_t siba_bwn_driver = {
+ "siba_bwn",
+ siba_bwn_methods,
+ sizeof(struct siba_bwn_softc)
+};
+static devclass_t siba_bwn_devclass;
+DRIVER_MODULE(siba_bwn, pci, siba_bwn_driver, siba_bwn_devclass, 0, 0);
+MODULE_VERSION(siba_bwn, 1);
diff --git a/sys/dev/siba/siba_cc.c b/sys/dev/siba/siba_cc.c
index cd78f0b..db0aac5 100644
--- a/sys/dev/siba/siba_cc.c
+++ b/sys/dev/siba/siba_cc.c
@@ -55,9 +55,9 @@ __FBSDID("$FreeBSD$");
#include <machine/bus.h>
-#include <dev/siba/sibavar.h>
-#include <dev/siba/sibareg.h>
#include <dev/siba/siba_ids.h>
+#include <dev/siba/sibareg.h>
+#include <dev/siba/sibavar.h>
static int siba_cc_attach(device_t);
static int siba_cc_probe(device_t);
diff --git a/sys/dev/siba/siba_core.c b/sys/dev/siba/siba_core.c
new file mode 100644
index 0000000..b2168f5
--- /dev/null
+++ b/sys/dev/siba/siba_core.c
@@ -0,0 +1,2007 @@
+/*-
+ * Copyright (c) 2009-2010 Weongyo Jeong <weongyo@freebsd.org>
+ * 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,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
+ * redistribution must be conditioned upon including a substantially
+ * similar Disclaimer requirement for further binary redistribution.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * the Sonics Silicon Backplane driver.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/module.h>
+#include <sys/kernel.h>
+#include <sys/endian.h>
+#include <sys/errno.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <sys/bus.h>
+#include <sys/rman.h>
+#include <sys/socket.h>
+
+#include <net/if.h>
+#include <net/if_media.h>
+#include <net/if_arp.h>
+
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcireg.h>
+
+#include <dev/siba/siba_ids.h>
+#include <dev/siba/sibareg.h>
+#include <dev/siba/sibavar.h>
+
+#ifdef SIBA_DEBUG
+enum {
+ SIBA_DEBUG_SCAN = 0x00000001, /* scan */
+ SIBA_DEBUG_PMU = 0x00000002, /* PMU */
+ SIBA_DEBUG_PLL = 0x00000004, /* PLL */
+ SIBA_DEBUG_SWITCHCORE = 0x00000008, /* switching core */
+ SIBA_DEBUG_SPROM = 0x00000010, /* SPROM */
+ SIBA_DEBUG_CORE = 0x00000020, /* handling cores */
+ SIBA_DEBUG_ANY = 0xffffffff
+};
+#define DPRINTF(siba, m, fmt, ...) do { \
+ if (siba->siba_debug & (m)) \
+ printf(fmt, __VA_ARGS__); \
+} while (0)
+#else
+#define DPRINTF(siba, m, fmt, ...) do { (void) siba; } while (0)
+#endif
+#define N(a) (sizeof(a) / sizeof(a[0]))
+
+static void siba_pci_gpio(struct siba_softc *, uint32_t, int);
+static void siba_scan(struct siba_softc *);
+static int siba_switchcore(struct siba_softc *, uint8_t);
+static int siba_pci_switchcore_sub(struct siba_softc *, uint8_t);
+static uint32_t siba_scan_read_4(struct siba_softc *, uint8_t, uint16_t);
+static uint16_t siba_dev2chipid(struct siba_softc *);
+static uint16_t siba_pci_read_2(struct siba_dev_softc *, uint16_t);
+static uint32_t siba_pci_read_4(struct siba_dev_softc *, uint16_t);
+static void siba_pci_write_2(struct siba_dev_softc *, uint16_t, uint16_t);
+static void siba_pci_write_4(struct siba_dev_softc *, uint16_t, uint32_t);
+static void siba_cc_clock(struct siba_cc *,
+ enum siba_clock);
+static void siba_cc_pmu_init(struct siba_cc *);
+static void siba_cc_power_init(struct siba_cc *);
+static void siba_cc_powerup_delay(struct siba_cc *);
+static int siba_cc_clockfreq(struct siba_cc *, int);
+static void siba_cc_pmu1_pll0_init(struct siba_cc *, uint32_t);
+static void siba_cc_pmu0_pll0_init(struct siba_cc *, uint32_t);
+static enum siba_clksrc siba_cc_clksrc(struct siba_cc *);
+static const struct siba_cc_pmu1_plltab *siba_cc_pmu1_plltab_find(uint32_t);
+static uint32_t siba_cc_pll_read(struct siba_cc *, uint32_t);
+static void siba_cc_pll_write(struct siba_cc *, uint32_t,
+ uint32_t);
+static const struct siba_cc_pmu0_plltab *
+ siba_cc_pmu0_plltab_findentry(uint32_t);
+static int siba_pci_sprom(struct siba_softc *, struct siba_sprom *);
+static int siba_sprom_read(struct siba_softc *, uint16_t *, uint16_t);
+static int sprom_check_crc(const uint16_t *, size_t);
+static uint8_t siba_crc8(uint8_t, uint8_t);
+static void siba_sprom_r123(struct siba_sprom *, const uint16_t *);
+static void siba_sprom_r45(struct siba_sprom *, const uint16_t *);
+static void siba_sprom_r8(struct siba_sprom *, const uint16_t *);
+static int8_t siba_sprom_r123_antgain(uint8_t, const uint16_t *, uint16_t,
+ uint16_t);
+static uint32_t siba_tmslow_reject_bitmask(struct siba_dev_softc *);
+static uint32_t siba_pcicore_read_4(struct siba_pci *, uint16_t);
+static void siba_pcicore_write_4(struct siba_pci *, uint16_t, uint32_t);
+static uint32_t siba_pcie_read(struct siba_pci *, uint32_t);
+static void siba_pcie_write(struct siba_pci *, uint32_t, uint32_t);
+static void siba_pcie_mdio_write(struct siba_pci *, uint8_t, uint8_t,
+ uint16_t);
+static void siba_pci_read_multi_1(struct siba_dev_softc *, void *, size_t,
+ uint16_t);
+static void siba_pci_read_multi_2(struct siba_dev_softc *, void *, size_t,
+ uint16_t);
+static void siba_pci_read_multi_4(struct siba_dev_softc *, void *, size_t,
+ uint16_t);
+static void siba_pci_write_multi_1(struct siba_dev_softc *, const void *,
+ size_t, uint16_t);
+static void siba_pci_write_multi_2(struct siba_dev_softc *, const void *,
+ size_t, uint16_t);
+static void siba_pci_write_multi_4(struct siba_dev_softc *, const void *,
+ size_t, uint16_t);
+static const char *siba_core_name(uint16_t);
+static void siba_pcicore_init(struct siba_pci *);
+device_t siba_add_child(device_t, struct siba_softc *, int, const char *,
+ int);
+int siba_core_attach(struct siba_softc *);
+int siba_core_detach(struct siba_softc *);
+int siba_core_suspend(struct siba_softc *);
+int siba_core_resume(struct siba_softc *);
+uint8_t siba_getncores(device_t, uint16_t);
+
+static const struct siba_bus_ops siba_pci_ops = {
+ .read_2 = siba_pci_read_2,
+ .read_4 = siba_pci_read_4,
+ .write_2 = siba_pci_write_2,
+ .write_4 = siba_pci_write_4,
+ .read_multi_1 = siba_pci_read_multi_1,
+ .read_multi_2 = siba_pci_read_multi_2,
+ .read_multi_4 = siba_pci_read_multi_4,
+ .write_multi_1 = siba_pci_write_multi_1,
+ .write_multi_2 = siba_pci_write_multi_2,
+ .write_multi_4 = siba_pci_write_multi_4,
+};
+
+static const struct siba_cc_pmu_res_updown siba_cc_pmu_4325_updown[] =
+ SIBA_CC_PMU_4325_RES_UPDOWN;
+static const struct siba_cc_pmu_res_depend siba_cc_pmu_4325_depend[] =
+ SIBA_CC_PMU_4325_RES_DEPEND;
+static const struct siba_cc_pmu_res_updown siba_cc_pmu_4328_updown[] =
+ SIBA_CC_PMU_4328_RES_UPDOWN;
+static const struct siba_cc_pmu_res_depend siba_cc_pmu_4328_depend[] =
+ SIBA_CC_PMU_4328_RES_DEPEND;
+static const struct siba_cc_pmu0_plltab siba_cc_pmu0_plltab[] =
+ SIBA_CC_PMU0_PLLTAB_ENTRY;
+static const struct siba_cc_pmu1_plltab siba_cc_pmu1_plltab[] =
+ SIBA_CC_PMU1_PLLTAB_ENTRY;
+
+int
+siba_core_attach(struct siba_softc *siba)
+{
+ struct siba_cc *scc;
+ int error;
+
+ KASSERT(siba->siba_type == SIBA_TYPE_PCI,
+ ("unsupported BUS type (%#x)", siba->siba_type));
+
+ siba->siba_ops = &siba_pci_ops;
+
+ siba_pci_gpio(siba, SIBA_GPIO_CRYSTAL | SIBA_GPIO_PLL, 1);
+ siba_scan(siba);
+
+ /* XXX init PCI or PCMCIA host devices */
+
+ siba_powerup(siba, 0);
+
+ /* init ChipCommon */
+ scc = &siba->siba_cc;
+ if (scc->scc_dev != NULL) {
+ siba_cc_pmu_init(scc);
+ siba_cc_power_init(scc);
+ siba_cc_clock(scc, SIBA_CLOCK_FAST);
+ siba_cc_powerup_delay(scc);
+ }
+
+ /* fetch various internal informations for PCI */
+ siba->siba_board_vendor = pci_read_config(siba->siba_dev,
+ PCIR_SUBVEND_0, 2);
+ siba->siba_board_type = pci_read_config(siba->siba_dev, PCIR_SUBDEV_0,
+ 2);
+ siba->siba_board_rev = pci_read_config(siba->siba_dev, PCIR_REVID, 2);
+ error = siba_pci_sprom(siba, &siba->siba_sprom);
+ if (error) {
+ siba_powerdown(siba);
+ return (error);
+ }
+
+ siba_powerdown(siba);
+ return (0);
+}
+
+int
+siba_core_detach(struct siba_softc *siba)
+{
+ device_t *devlistp;
+ int devcnt, error = 0, i;
+
+ error = device_get_children(siba->siba_dev, &devlistp, &devcnt);
+ if (error != 0)
+ return (0);
+
+ for ( i = 0 ; i < devcnt ; i++)
+ device_delete_child(siba->siba_dev, devlistp[i]);
+ free(devlistp, M_TEMP);
+ return (0);
+}
+
+static void
+siba_pci_gpio(struct siba_softc *siba, uint32_t what, int on)
+{
+ uint32_t in, out;
+ uint16_t status;
+
+ if (siba->siba_type != SIBA_TYPE_PCI)
+ return;
+
+ out = pci_read_config(siba->siba_dev, SIBA_GPIO_OUT, 4);
+ if (on == 0) {
+ if (what & SIBA_GPIO_PLL)
+ out |= SIBA_GPIO_PLL;
+ if (what & SIBA_GPIO_CRYSTAL)
+ out &= ~SIBA_GPIO_CRYSTAL;
+ pci_write_config(siba->siba_dev, SIBA_GPIO_OUT, out, 4);
+ pci_write_config(siba->siba_dev, SIBA_GPIO_OUT_EN,
+ pci_read_config(siba->siba_dev,
+ SIBA_GPIO_OUT_EN, 4) | what, 4);
+ return;
+ }
+
+ in = pci_read_config(siba->siba_dev, SIBA_GPIO_IN, 4);
+ if ((in & SIBA_GPIO_CRYSTAL) != SIBA_GPIO_CRYSTAL) {
+ if (what & SIBA_GPIO_CRYSTAL) {
+ out |= SIBA_GPIO_CRYSTAL;
+ if (what & SIBA_GPIO_PLL)
+ out |= SIBA_GPIO_PLL;
+ pci_write_config(siba->siba_dev, SIBA_GPIO_OUT, out, 4);
+ pci_write_config(siba->siba_dev,
+ SIBA_GPIO_OUT_EN, pci_read_config(siba->siba_dev,
+ SIBA_GPIO_OUT_EN, 4) | what, 4);
+ DELAY(1000);
+ }
+ if (what & SIBA_GPIO_PLL) {
+ out &= ~SIBA_GPIO_PLL;
+ pci_write_config(siba->siba_dev, SIBA_GPIO_OUT, out, 4);
+ DELAY(5000);
+ }
+ }
+
+ status = pci_read_config(siba->siba_dev, PCIR_STATUS, 2);
+ status &= ~PCIM_STATUS_STABORT;
+ pci_write_config(siba->siba_dev, PCIR_STATUS, status, 2);
+}
+
+static void
+siba_scan(struct siba_softc *siba)
+{
+ struct siba_dev_softc *sd;
+ uint32_t idhi, tmp;
+ int base, dev_i = 0, error, i, is_pcie, n_80211 = 0, n_cc = 0,
+ n_pci = 0;
+
+ KASSERT(siba->siba_type == SIBA_TYPE_PCI,
+ ("unsupported BUS type (%#x)", siba->siba_type));
+
+ siba->siba_ndevs = 0;
+ error = siba_switchcore(siba, 0); /* need the first core */
+ if (error)
+ return;
+
+ idhi = siba_scan_read_4(siba, 0, SIBA_IDHIGH);
+ if (SIBA_IDHIGH_CORECODE(idhi) == SIBA_DEVID_CHIPCOMMON) {
+ tmp = siba_scan_read_4(siba, 0, SIBA_CC_CHIPID);
+ siba->siba_chipid = SIBA_CC_ID(tmp);
+ siba->siba_chiprev = SIBA_CC_REV(tmp);
+ siba->siba_chippkg = SIBA_CC_PKG(tmp);
+ if (SIBA_IDHIGH_REV(idhi) >= 4)
+ siba->siba_ndevs = SIBA_CC_NCORES(tmp);
+ siba->siba_cc.scc_caps = siba_scan_read_4(siba, 0,
+ SIBA_CC_CAPS);
+ } else {
+ if (siba->siba_type == SIBA_TYPE_PCI) {
+ siba->siba_chipid = siba_dev2chipid(siba);
+ siba->siba_chiprev = pci_read_config(siba->siba_dev,
+ PCIR_REVID, 2);
+ siba->siba_chippkg = 0;
+ } else {
+ siba->siba_chipid = 0x4710;
+ siba->siba_chiprev = 0;
+ siba->siba_chippkg = 0;
+ }
+ }
+ if (siba->siba_ndevs == 0)
+ siba->siba_ndevs = siba_getncores(siba->siba_dev,
+ siba->siba_chipid);
+ if (siba->siba_ndevs > SIBA_MAX_CORES) {
+ device_printf(siba->siba_dev,
+ "too many siba cores (max %d %d)\n",
+ SIBA_MAX_CORES, siba->siba_ndevs);
+ return;
+ }
+
+ /* looking basic information about each cores/devices */
+ for (i = 0; i < siba->siba_ndevs; i++) {
+ error = siba_switchcore(siba, i);
+ if (error)
+ return;
+ sd = &(siba->siba_devs[dev_i]);
+ idhi = siba_scan_read_4(siba, i, SIBA_IDHIGH);
+ sd->sd_bus = siba;
+ sd->sd_id.sd_device = SIBA_IDHIGH_CORECODE(idhi);
+ sd->sd_id.sd_rev = SIBA_IDHIGH_REV(idhi);
+ sd->sd_id.sd_vendor = SIBA_IDHIGH_VENDOR(idhi);
+ sd->sd_ops = siba->siba_ops;
+ sd->sd_coreidx = i;
+
+ DPRINTF(siba, SIBA_DEBUG_SCAN,
+ "core %d (%s) found (cc %#xrev %#x vendor %#x)\n",
+ i, siba_core_name(sd->sd_id.sd_device),
+ sd->sd_id.sd_device, sd->sd_id.sd_rev, sd->sd_id.vendor);
+
+ switch (sd->sd_id.sd_device) {
+ case SIBA_DEVID_CHIPCOMMON:
+ n_cc++;
+ if (n_cc > 1) {
+ device_printf(siba->siba_dev,
+ "warn: multiple ChipCommon\n");
+ break;
+ }
+ siba->siba_cc.scc_dev = sd;
+ break;
+ case SIBA_DEVID_80211:
+ n_80211++;
+ if (n_80211 > 1) {
+ device_printf(siba->siba_dev,
+ "warn: multiple 802.11 core\n");
+ continue;
+ }
+ break;
+ case SIBA_DEVID_PCI:
+ case SIBA_DEVID_PCIE:
+ n_pci++;
+ error = pci_find_extcap(siba->siba_dev, PCIY_EXPRESS,
+ &base);
+ is_pcie = (error == 0) ? 1 : 0;
+
+ if (n_pci > 1) {
+ device_printf(siba->siba_dev,
+ "warn: multiple PCI(E) cores\n");
+ break;
+ }
+ if (sd->sd_id.sd_device == SIBA_DEVID_PCI &&
+ is_pcie == 1)
+ continue;
+ if (sd->sd_id.sd_device == SIBA_DEVID_PCIE &&
+ is_pcie == 0)
+ continue;
+ siba->siba_pci.spc_dev = sd;
+ break;
+ case SIBA_DEVID_MODEM:
+ case SIBA_DEVID_PCMCIA:
+ break;
+ default:
+ device_printf(siba->siba_dev,
+ "unsupported coreid (%s)\n",
+ siba_core_name(sd->sd_id.sd_device));
+ break;
+ }
+ dev_i++;
+ }
+ siba->siba_ndevs = dev_i;
+}
+
+static int
+siba_switchcore(struct siba_softc *siba, uint8_t idx)
+{
+
+ switch (siba->siba_type) {
+ case SIBA_TYPE_PCI:
+ return (siba_pci_switchcore_sub(siba, idx));
+ default:
+ KASSERT(0 == 1,
+ ("%s: unsupported bustype %#x", __func__,
+ siba->siba_type));
+ }
+ return (0);
+}
+
+static int
+siba_pci_switchcore_sub(struct siba_softc *siba, uint8_t idx)
+{
+#define RETRY_MAX 50
+ int i;
+ uint32_t dir;
+
+ dir = SIBA_REGWIN(idx);
+
+ for (i = 0; i < RETRY_MAX; i++) {
+ pci_write_config(siba->siba_dev, SIBA_BAR0, dir, 4);
+ if (pci_read_config(siba->siba_dev, SIBA_BAR0, 4) == dir)
+ return (0);
+ DELAY(10);
+ }
+ return (ENODEV);
+#undef RETRY_MAX
+}
+
+static int
+siba_pci_switchcore(struct siba_softc *siba, struct siba_dev_softc *sd)
+{
+ int error;
+
+ DPRINTF(siba, SIBA_DEBUG_SWITCHCORE, "Switching to %s core, index %d\n",
+ siba_core_name(sd->sd_id.sd_device), sd->sd_coreidx);
+
+ error = siba_pci_switchcore_sub(siba, sd->sd_coreidx);
+ if (error == 0)
+ siba->siba_curdev = sd;
+
+ return (error);
+}
+
+static uint32_t
+siba_scan_read_4(struct siba_softc *siba, uint8_t coreidx,
+ uint16_t offset)
+{
+
+ (void)coreidx;
+ KASSERT(siba->siba_type == SIBA_TYPE_PCI,
+ ("unsupported BUS type (%#x)", siba->siba_type));
+
+ return (SIBA_READ_4(siba, offset));
+}
+
+static uint16_t
+siba_dev2chipid(struct siba_softc *siba)
+{
+ uint16_t chipid = 0;
+
+ switch (siba->siba_pci_did) {
+ case 0x4301:
+ chipid = 0x4301;
+ break;
+ case 0x4305:
+ case 0x4306:
+ case 0x4307:
+ chipid = 0x4307;
+ break;
+ case 0x4403:
+ chipid = 0x4402;
+ break;
+ case 0x4610:
+ case 0x4611:
+ case 0x4612:
+ case 0x4613:
+ case 0x4614:
+ case 0x4615:
+ chipid = 0x4610;
+ break;
+ case 0x4710:
+ case 0x4711:
+ case 0x4712:
+ case 0x4713:
+ case 0x4714:
+ case 0x4715:
+ chipid = 0x4710;
+ break;
+ case 0x4320:
+ case 0x4321:
+ case 0x4322:
+ case 0x4323:
+ case 0x4324:
+ case 0x4325:
+ chipid = 0x4309;
+ break;
+ case PCI_DEVICE_ID_BCM4401:
+ case PCI_DEVICE_ID_BCM4401B0:
+ case PCI_DEVICE_ID_BCM4401B1:
+ chipid = 0x4401;
+ break;
+ default:
+ device_printf(siba->siba_dev, "unknown PCI did (%d)\n",
+ siba->siba_pci_did);
+ }
+
+ return (chipid);
+}
+
+/*
+ * Earlier ChipCommon revisions have hardcoded number of cores
+ * present dependent on the ChipCommon ID.
+ */
+uint8_t
+siba_getncores(device_t dev, uint16_t chipid)
+{
+ switch (chipid) {
+ case 0x4401:
+ case 0x4402:
+ return (3);
+ case 0x4301:
+ case 0x4307:
+ return (5);
+ case 0x4306:
+ return (6);
+ case SIBA_CCID_SENTRY5:
+ return (7);
+ case 0x4310:
+ return (8);
+ case SIBA_CCID_BCM4710:
+ case 0x4610:
+ case SIBA_CCID_BCM4704:
+ return (9);
+ default:
+ device_printf(dev, "unknown the chipset ID %#x\n", chipid);
+ }
+
+ return (1);
+}
+
+static const char *
+siba_core_name(uint16_t coreid)
+{
+
+ switch (coreid) {
+ case SIBA_DEVID_CHIPCOMMON:
+ return ("ChipCommon");
+ case SIBA_DEVID_ILINE20:
+ return ("ILine 20");
+ case SIBA_DEVID_SDRAM:
+ return ("SDRAM");
+ case SIBA_DEVID_PCI:
+ return ("PCI");
+ case SIBA_DEVID_MIPS:
+ return ("MIPS");
+ case SIBA_DEVID_ETHERNET:
+ return ("Fast Ethernet");
+ case SIBA_DEVID_MODEM:
+ return ("Modem");
+ case SIBA_DEVID_USB11_HOSTDEV:
+ return ("USB 1.1 Hostdev");
+ case SIBA_DEVID_ADSL:
+ return ("ADSL");
+ case SIBA_DEVID_ILINE100:
+ return ("ILine 100");
+ case SIBA_DEVID_IPSEC:
+ return ("IPSEC");
+ case SIBA_DEVID_PCMCIA:
+ return ("PCMCIA");
+ case SIBA_DEVID_INTERNAL_MEM:
+ return ("Internal Memory");
+ case SIBA_DEVID_SDRAMDDR:
+ return ("MEMC SDRAM");
+ case SIBA_DEVID_EXTIF:
+ return ("EXTIF");
+ case SIBA_DEVID_80211:
+ return ("IEEE 802.11");
+ case SIBA_DEVID_MIPS_3302:
+ return ("MIPS 3302");
+ case SIBA_DEVID_USB11_HOST:
+ return ("USB 1.1 Host");
+ case SIBA_DEVID_USB11_DEV:
+ return ("USB 1.1 Device");
+ case SIBA_DEVID_USB20_HOST:
+ return ("USB 2.0 Host");
+ case SIBA_DEVID_USB20_DEV:
+ return ("USB 2.0 Device");
+ case SIBA_DEVID_SDIO_HOST:
+ return ("SDIO Host");
+ case SIBA_DEVID_ROBOSWITCH:
+ return ("Roboswitch");
+ case SIBA_DEVID_PARA_ATA:
+ return ("PATA");
+ case SIBA_DEVID_SATA_XORDMA:
+ return ("SATA XOR-DMA");
+ case SIBA_DEVID_ETHERNET_GBIT:
+ return ("GBit Ethernet");
+ case SIBA_DEVID_PCIE:
+ return ("PCI-Express");
+ case SIBA_DEVID_MIMO_PHY:
+ return ("MIMO PHY");
+ case SIBA_DEVID_SRAM_CTRLR:
+ return ("SRAM Controller");
+ case SIBA_DEVID_MINI_MACPHY:
+ return ("Mini MACPHY");
+ case SIBA_DEVID_ARM_1176:
+ return ("ARM 1176");
+ case SIBA_DEVID_ARM_7TDMI:
+ return ("ARM 7TDMI");
+ }
+ return ("unknown");
+}
+
+static uint16_t
+siba_pci_read_2(struct siba_dev_softc *sd, uint16_t offset)
+{
+ struct siba_softc *siba = sd->sd_bus;
+
+ if (siba->siba_curdev != sd && siba_pci_switchcore(siba, sd) != 0)
+ return (0xffff);
+
+ return (SIBA_READ_2(siba, offset));
+}
+
+static uint32_t
+siba_pci_read_4(struct siba_dev_softc *sd, uint16_t offset)
+{
+ struct siba_softc *siba = sd->sd_bus;
+
+ if (siba->siba_curdev != sd && siba_pci_switchcore(siba, sd) != 0)
+ return (0xffff);
+
+ return (SIBA_READ_4(siba, offset));
+}
+
+static void
+siba_pci_write_2(struct siba_dev_softc *sd, uint16_t offset, uint16_t value)
+{
+ struct siba_softc *siba = sd->sd_bus;
+
+ if (siba->siba_curdev != sd && siba_pci_switchcore(siba, sd) != 0)
+ return;
+
+ SIBA_WRITE_2(siba, offset, value);
+}
+
+static void
+siba_pci_write_4(struct siba_dev_softc *sd, uint16_t offset, uint32_t value)
+{
+ struct siba_softc *siba = sd->sd_bus;
+
+ if (siba->siba_curdev != sd && siba_pci_switchcore(siba, sd) != 0)
+ return;
+
+ SIBA_WRITE_4(siba, offset, value);
+}
+
+static void
+siba_pci_read_multi_1(struct siba_dev_softc *sd, void *buffer, size_t count,
+ uint16_t offset)
+{
+ struct siba_softc *siba = sd->sd_bus;
+
+ if (siba->siba_curdev != sd && siba_pci_switchcore(siba, sd) != 0) {
+ memset(buffer, 0xff, count);
+ return;
+ }
+
+ SIBA_READ_MULTI_1(siba, offset, buffer, count);
+}
+
+static void
+siba_pci_read_multi_2(struct siba_dev_softc *sd, void *buffer, size_t count,
+ uint16_t offset)
+{
+ struct siba_softc *siba = sd->sd_bus;
+
+ if (siba->siba_curdev != sd && siba_pci_switchcore(siba, sd) != 0) {
+ memset(buffer, 0xff, count);
+ return;
+ }
+
+ KASSERT(!(count & 1), ("%s:%d: fail", __func__, __LINE__));
+ SIBA_READ_MULTI_2(siba, offset, buffer, count >> 1);
+}
+
+static void
+siba_pci_read_multi_4(struct siba_dev_softc *sd, void *buffer, size_t count,
+ uint16_t offset)
+{
+ struct siba_softc *siba = sd->sd_bus;
+
+ if (siba->siba_curdev != sd && siba_pci_switchcore(siba, sd) != 0) {
+ memset(buffer, 0xff, count);
+ return;
+ }
+
+ KASSERT(!(count & 3), ("%s:%d: fail", __func__, __LINE__));
+ SIBA_READ_MULTI_4(siba, offset, buffer, count >> 2);
+}
+
+static void
+siba_pci_write_multi_1(struct siba_dev_softc *sd, const void *buffer,
+ size_t count, uint16_t offset)
+{
+ struct siba_softc *siba = sd->sd_bus;
+
+ if (siba->siba_curdev != sd && siba_pci_switchcore(siba, sd) != 0)
+ return;
+
+ SIBA_WRITE_MULTI_1(siba, offset, buffer, count);
+}
+
+static void
+siba_pci_write_multi_2(struct siba_dev_softc *sd, const void *buffer,
+ size_t count, uint16_t offset)
+{
+ struct siba_softc *siba = sd->sd_bus;
+
+ if (siba->siba_curdev != sd && siba_pci_switchcore(siba, sd) != 0)
+ return;
+
+ KASSERT(!(count & 1), ("%s:%d: fail", __func__, __LINE__));
+ SIBA_WRITE_MULTI_2(siba, offset, buffer, count >> 1);
+}
+
+static void
+siba_pci_write_multi_4(struct siba_dev_softc *sd, const void *buffer,
+ size_t count, uint16_t offset)
+{
+ struct siba_softc *siba = sd->sd_bus;
+
+ if (siba->siba_curdev != sd && siba_pci_switchcore(siba, sd) != 0)
+ return;
+
+ KASSERT(!(count & 3), ("%s:%d: fail", __func__, __LINE__));
+ SIBA_WRITE_MULTI_4(siba, offset, buffer, count >> 2);
+}
+
+void
+siba_powerup(struct siba_softc *siba, int dynamic)
+{
+
+ siba_pci_gpio(siba, SIBA_GPIO_CRYSTAL | SIBA_GPIO_PLL, 1);
+ siba_cc_clock(&siba->siba_cc,
+ (dynamic != 0) ? SIBA_CLOCK_DYNAMIC : SIBA_CLOCK_FAST);
+}
+
+static void
+siba_cc_clock(struct siba_cc *scc, enum siba_clock clock)
+{
+ struct siba_dev_softc *sd = scc->scc_dev;
+ struct siba_softc *siba;
+ uint32_t tmp;
+
+ if (sd == NULL)
+ return;
+ siba = sd->sd_bus;
+ /*
+ * chipcommon < r6 (no dynamic clock control)
+ * chipcommon >= r10 (unknown)
+ */
+ if (sd->sd_id.sd_rev < 6 || sd->sd_id.sd_rev >= 10 ||
+ (scc->scc_caps & SIBA_CC_CAPS_PWCTL) == 0)
+ return;
+
+ switch (clock) {
+ case SIBA_CLOCK_DYNAMIC:
+ tmp = SIBA_CC_READ32(scc, SIBA_CC_CLKSLOW) &
+ ~(SIBA_CC_CLKSLOW_ENXTAL | SIBA_CC_CLKSLOW_FSLOW |
+ SIBA_CC_CLKSLOW_IPLL);
+ if ((tmp & SIBA_CC_CLKSLOW_SRC) != SIBA_CC_CLKSLOW_SRC_CRYSTAL)
+ tmp |= SIBA_CC_CLKSLOW_ENXTAL;
+ SIBA_CC_WRITE32(scc, SIBA_CC_CLKSLOW, tmp);
+ if (tmp & SIBA_CC_CLKSLOW_ENXTAL)
+ siba_pci_gpio(siba, SIBA_GPIO_CRYSTAL, 0);
+ break;
+ case SIBA_CLOCK_SLOW:
+ SIBA_CC_WRITE32(scc, SIBA_CC_CLKSLOW,
+ SIBA_CC_READ32(scc, SIBA_CC_CLKSLOW) |
+ SIBA_CC_CLKSLOW_FSLOW);
+ break;
+ case SIBA_CLOCK_FAST:
+ /* crystal on */
+ siba_pci_gpio(siba, SIBA_GPIO_CRYSTAL, 1);
+ SIBA_CC_WRITE32(scc, SIBA_CC_CLKSLOW,
+ (SIBA_CC_READ32(scc, SIBA_CC_CLKSLOW) |
+ SIBA_CC_CLKSLOW_IPLL) & ~SIBA_CC_CLKSLOW_FSLOW);
+ break;
+ default:
+ KASSERT(0 == 1,
+ ("%s: unsupported clock %#x", __func__, clock));
+ }
+}
+
+uint16_t
+siba_read_2(struct siba_dev_softc *sd, uint16_t offset)
+{
+
+ return (sd->sd_ops->read_2(sd, offset));
+}
+
+uint32_t
+siba_read_4(struct siba_dev_softc *sd, uint16_t offset)
+{
+
+ return (sd->sd_ops->read_4(sd, offset));
+}
+
+void
+siba_write_2(struct siba_dev_softc *sd, uint16_t offset, uint16_t value)
+{
+
+ sd->sd_ops->write_2(sd, offset, value);
+}
+
+void
+siba_write_4(struct siba_dev_softc *sd, uint16_t offset, uint32_t value)
+{
+
+ sd->sd_ops->write_4(sd, offset, value);
+}
+
+void
+siba_read_multi_1(struct siba_dev_softc *sd, void *buffer, size_t count,
+ uint16_t offset)
+{
+
+ sd->sd_ops->read_multi_1(sd, buffer, count, offset);
+}
+
+void
+siba_read_multi_2(struct siba_dev_softc *sd, void *buffer, size_t count,
+ uint16_t offset)
+{
+
+ sd->sd_ops->read_multi_2(sd, buffer, count, offset);
+}
+
+void
+siba_read_multi_4(struct siba_dev_softc *sd, void *buffer, size_t count,
+ uint16_t offset)
+{
+
+ sd->sd_ops->read_multi_4(sd, buffer, count, offset);
+}
+
+void
+siba_write_multi_1(struct siba_dev_softc *sd, const void *buffer,
+ size_t count, uint16_t offset)
+{
+
+ sd->sd_ops->write_multi_1(sd, buffer, count, offset);
+}
+
+void
+siba_write_multi_2(struct siba_dev_softc *sd, const void *buffer,
+ size_t count, uint16_t offset)
+{
+
+ sd->sd_ops->write_multi_2(sd, buffer, count, offset);
+}
+
+void
+siba_write_multi_4(struct siba_dev_softc *sd, const void *buffer,
+ size_t count, uint16_t offset)
+{
+
+ sd->sd_ops->write_multi_4(sd, buffer, count, offset);
+}
+
+static void
+siba_cc_pmu_init(struct siba_cc *scc)
+{
+ const struct siba_cc_pmu_res_updown *updown = NULL;
+ const struct siba_cc_pmu_res_depend *depend = NULL;
+ struct siba_dev_softc *sd = scc->scc_dev;
+ struct siba_softc *siba = sd->sd_bus;
+ uint32_t min = 0, max = 0, pmucap;
+ unsigned int i, updown_size, depend_size;
+
+ if ((scc->scc_caps & SIBA_CC_CAPS_PMU) == 0)
+ return;
+
+ pmucap = SIBA_CC_READ32(scc, SIBA_CC_PMUCAPS);
+ scc->scc_pmu.rev = (pmucap & SIBA_CC_PMUCAPS_REV);
+
+ DPRINTF(siba, SIBA_DEBUG_PMU, "PMU(r%u) found (caps %#x)\n",
+ scc->scc_pmu.rev, pmucap);
+
+ if (scc->scc_pmu.rev >= 1) {
+ if (siba->siba_chiprev < 2 && siba->siba_chipid == 0x4325)
+ SIBA_CC_MASK32(scc, SIBA_CC_PMUCTL,
+ ~SIBA_CC_PMUCTL_NOILP);
+ else
+ SIBA_CC_SET32(scc, SIBA_CC_PMUCTL,
+ SIBA_CC_PMUCTL_NOILP);
+ }
+
+ /* initialize PLL & PMU resources */
+ switch (siba->siba_chipid) {
+ case 0x4312:
+ siba_cc_pmu1_pll0_init(scc, 0 /* use default */);
+ /* use the default: min = 0xcbb max = 0x7ffff */
+ break;
+ case 0x4325:
+ siba_cc_pmu1_pll0_init(scc, 0 /* use default */);
+
+ updown = siba_cc_pmu_4325_updown;
+ updown_size = N(siba_cc_pmu_4325_updown);
+ depend = siba_cc_pmu_4325_depend;
+ depend_size = N(siba_cc_pmu_4325_depend);
+
+ min = (1 << SIBA_CC_PMU_4325_BURST) |
+ (1 << SIBA_CC_PMU_4325_LN);
+ if (SIBA_CC_READ32(scc, SIBA_CC_CHIPSTAT) &
+ SIBA_CC_CHST_4325_PMUTOP_2B)
+ min |= (1 << SIBA_CC_PMU_4325_CLBURST);
+ max = 0xfffff;
+ break;
+ case 0x4328:
+ siba_cc_pmu0_pll0_init(scc, 0 /* use default */);
+
+ updown = siba_cc_pmu_4328_updown;
+ updown_size = N(siba_cc_pmu_4328_updown);
+ depend = siba_cc_pmu_4328_depend;
+ depend_size = N(siba_cc_pmu_4328_depend);
+
+ min = (1 << SIBA_CC_PMU_4328_EXT_SWITCH_PWM) |
+ (1 << SIBA_CC_PMU_4328_BB_SWITCH_PWM) |
+ (1 << SIBA_CC_PMU_4328_CRYSTAL_EN);
+
+ max = 0xfffff;
+ break;
+ case 0x5354:
+ siba_cc_pmu0_pll0_init(scc, 0 /* use default */);
+
+ max = 0xfffff;
+ break;
+ default:
+ device_printf(siba->siba_dev,
+ "unknown chipid %#x for PLL & PMU init\n",
+ siba->siba_chipid);
+ }
+
+ if (updown) {
+ for (i = 0; i < updown_size; i++) {
+ SIBA_CC_WRITE32(scc, SIBA_CC_PMU_TABSEL,
+ updown[i].res);
+ SIBA_CC_WRITE32(scc, SIBA_CC_PMU_UPDNTM,
+ updown[i].updown);
+ }
+ }
+ if (depend) {
+ for (i = 0; i < depend_size; i++) {
+ SIBA_CC_WRITE32(scc, SIBA_CC_PMU_TABSEL,
+ depend[i].res);
+ switch (depend[i].task) {
+ case SIBA_CC_PMU_DEP_SET:
+ SIBA_CC_WRITE32(scc, SIBA_CC_PMU_DEPMSK,
+ depend[i].depend);
+ break;
+ case SIBA_CC_PMU_DEP_ADD:
+ SIBA_CC_SET32(scc, SIBA_CC_PMU_DEPMSK,
+ depend[i].depend);
+ break;
+ case SIBA_CC_PMU_DEP_REMOVE:
+ SIBA_CC_MASK32(scc, SIBA_CC_PMU_DEPMSK,
+ ~(depend[i].depend));
+ break;
+ default:
+ KASSERT(0 == 1,
+ ("%s:%d: assertion failed",
+ __func__, __LINE__));
+ }
+ }
+ }
+
+ if (min)
+ SIBA_CC_WRITE32(scc, SIBA_CC_PMU_MINRES, min);
+ if (max)
+ SIBA_CC_WRITE32(scc, SIBA_CC_PMU_MAXRES, max);
+}
+
+static void
+siba_cc_power_init(struct siba_cc *scc)
+{
+ struct siba_softc *siba = scc->scc_dev->sd_bus;
+ int maxfreq;
+
+ if (siba->siba_chipid == 0x4321) {
+ if (siba->siba_chiprev == 0)
+ SIBA_CC_WRITE32(scc, SIBA_CC_CHIPCTL, 0x3a4);
+ else if (siba->siba_chiprev == 1)
+ SIBA_CC_WRITE32(scc, SIBA_CC_CHIPCTL, 0xa4);
+ }
+
+ if ((scc->scc_caps & SIBA_CC_CAPS_PWCTL) == 0)
+ return;
+
+ if (scc->scc_dev->sd_id.sd_rev >= 10)
+ SIBA_CC_WRITE32(scc, SIBA_CC_CLKSYSCTL,
+ (SIBA_CC_READ32(scc, SIBA_CC_CLKSYSCTL) &
+ 0xffff) | 0x40000);
+ else {
+ maxfreq = siba_cc_clockfreq(scc, 1);
+ SIBA_CC_WRITE32(scc, SIBA_CC_PLLONDELAY,
+ (maxfreq * 150 + 999999) / 1000000);
+ SIBA_CC_WRITE32(scc, SIBA_CC_FREFSELDELAY,
+ (maxfreq * 15 + 999999) / 1000000);
+ }
+}
+
+static void
+siba_cc_powerup_delay(struct siba_cc *scc)
+{
+ struct siba_softc *siba = scc->scc_dev->sd_bus;
+ int min;
+
+ if (siba->siba_type != SIBA_TYPE_PCI ||
+ !(scc->scc_caps & SIBA_CC_CAPS_PWCTL))
+ return;
+
+ min = siba_cc_clockfreq(scc, 0);
+ scc->scc_powerup_delay =
+ (((SIBA_CC_READ32(scc, SIBA_CC_PLLONDELAY) + 2) * 1000000) +
+ (min - 1)) / min;
+}
+
+static int
+siba_cc_clockfreq(struct siba_cc *scc, int max)
+{
+ enum siba_clksrc src;
+ int div = 1, limit = 0;
+
+ src = siba_cc_clksrc(scc);
+ if (scc->scc_dev->sd_id.sd_rev < 6) {
+ div = (src == SIBA_CC_CLKSRC_PCI) ? 64 :
+ (src == SIBA_CC_CLKSRC_CRYSTAL) ? 32 : 1;
+ KASSERT(div != 1,
+ ("%s: unknown clock %d", __func__, src));
+ } else if (scc->scc_dev->sd_id.sd_rev < 10) {
+ switch (src) {
+ case SIBA_CC_CLKSRC_CRYSTAL:
+ case SIBA_CC_CLKSRC_PCI:
+ div = ((SIBA_CC_READ32(scc, SIBA_CC_CLKSLOW) >> 16) +
+ 1) * 4;
+ break;
+ case SIBA_CC_CLKSRC_LOWPW:
+ break;
+ }
+ } else
+ div = ((SIBA_CC_READ32(scc, SIBA_CC_CLKSYSCTL) >> 16) + 1) * 4;
+
+ switch (src) {
+ case SIBA_CC_CLKSRC_CRYSTAL:
+ limit = (max) ? 20200000 : 19800000;
+ break;
+ case SIBA_CC_CLKSRC_LOWPW:
+ limit = (max) ? 43000 : 25000;
+ break;
+ case SIBA_CC_CLKSRC_PCI:
+ limit = (max) ? 34000000 : 25000000;
+ break;
+ }
+
+ return (limit / div);
+}
+
+static void
+siba_cc_pmu1_pll0_init(struct siba_cc *scc, uint32_t freq)
+{
+ struct siba_dev_softc *sd = scc->scc_dev;
+ struct siba_softc *siba = sd->sd_bus;
+ const struct siba_cc_pmu1_plltab *e = NULL;
+ uint32_t bufsth = 0, pll, pmu;
+ unsigned int i;
+
+ KASSERT(freq == 0, ("%s:%d: assertion vail", __func__, __LINE__));
+ if (siba->siba_chipid == 0x4312) {
+ scc->scc_pmu.freq = 20000;
+ return;
+ }
+
+ e = siba_cc_pmu1_plltab_find(SIBA_CC_PMU1_DEFAULT_FREQ);
+ KASSERT(e != NULL, ("%s:%d: assertion vail", __func__, __LINE__));
+ scc->scc_pmu.freq = e->freq;
+
+ pmu = SIBA_CC_READ32(scc, SIBA_CC_PMUCTL);
+ if (SIBA_CC_PMUCTL_XF_VAL(pmu) == e->xf)
+ return;
+
+ DPRINTF(siba, SIBA_DEBUG_PLL, "change PLL value to %u.%03u MHz\n",
+ (e->freq / 1000), (e->freq % 1000));
+
+ /* turn PLL off */
+ switch (siba->siba_chipid) {
+ case 0x4325:
+ bufsth = 0x222222;
+ SIBA_CC_MASK32(scc, SIBA_CC_PMU_MINRES,
+ ~((1 << SIBA_CC_PMU_4325_BBPLL_PWR) |
+ (1 << SIBA_CC_PMU_4325_HT)));
+ SIBA_CC_MASK32(scc, SIBA_CC_PMU_MAXRES,
+ ~((1 << SIBA_CC_PMU_4325_BBPLL_PWR) |
+ (1 << SIBA_CC_PMU_4325_HT)));
+ break;
+ default:
+ KASSERT(0 == 1,
+ ("%s:%d: assertion failed", __func__, __LINE__));
+ }
+ for (i = 0; i < 1500; i++) {
+ if (!(SIBA_CC_READ32(scc, SIBA_CC_CLKCTLSTATUS) &
+ SIBA_CC_CLKCTLSTATUS_HT))
+ break;
+ DELAY(10);
+ }
+ if (SIBA_CC_READ32(scc, SIBA_CC_CLKCTLSTATUS) & SIBA_CC_CLKCTLSTATUS_HT)
+ device_printf(siba->siba_dev, "failed to turn PLL off!\n");
+
+ pll = siba_cc_pll_read(scc, SIBA_CC_PMU1_PLL0);
+ pll &= ~(SIBA_CC_PMU1_PLL0_P1DIV | SIBA_CC_PMU1_PLL0_P2DIV);
+ pll |= ((uint32_t)e->p1div << 20) & SIBA_CC_PMU1_PLL0_P1DIV;
+ pll |= ((uint32_t)e->p2div << 24) & SIBA_CC_PMU1_PLL0_P2DIV;
+ siba_cc_pll_write(scc, SIBA_CC_PMU1_PLL0, pll);
+
+ pll = siba_cc_pll_read(scc, SIBA_CC_PMU1_PLL2);
+ pll &= ~(SIBA_CC_PMU1_PLL2_NDIVINT | SIBA_CC_PMU1_PLL2_NDIVMODE);
+ pll |= ((uint32_t)e->ndiv_int << 20) & SIBA_CC_PMU1_PLL2_NDIVINT;
+ pll |= (1 << 17) & SIBA_CC_PMU1_PLL2_NDIVMODE;
+ siba_cc_pll_write(scc, SIBA_CC_PMU1_PLL2, pll);
+
+ pll = siba_cc_pll_read(scc, SIBA_CC_PMU1_PLL3);
+ pll &= ~SIBA_CC_PMU1_PLL3_NDIVFRAC;
+ pll |= ((uint32_t)e->ndiv_frac << 0) & SIBA_CC_PMU1_PLL3_NDIVFRAC;
+ siba_cc_pll_write(scc, SIBA_CC_PMU1_PLL3, pll);
+
+ if (bufsth) {
+ pll = siba_cc_pll_read(scc, SIBA_CC_PMU1_PLL5);
+ pll &= ~SIBA_CC_PMU1_PLL5_CLKDRV;
+ pll |= (bufsth << 8) & SIBA_CC_PMU1_PLL5_CLKDRV;
+ siba_cc_pll_write(scc, SIBA_CC_PMU1_PLL5, pll);
+ }
+
+ pmu = SIBA_CC_READ32(scc, SIBA_CC_PMUCTL);
+ pmu &= ~(SIBA_CC_PMUCTL_ILP | SIBA_CC_PMUCTL_XF);
+ pmu |= ((((uint32_t)e->freq + 127) / 128 - 1) << 16) &
+ SIBA_CC_PMUCTL_ILP;
+ pmu |= ((uint32_t)e->xf << 2) & SIBA_CC_PMUCTL_XF;
+ SIBA_CC_WRITE32(scc, SIBA_CC_PMUCTL, pmu);
+}
+
+static void
+siba_cc_pmu0_pll0_init(struct siba_cc *scc, uint32_t xtalfreq)
+{
+ struct siba_dev_softc *sd = scc->scc_dev;
+ struct siba_softc *siba = sd->sd_bus;
+ const struct siba_cc_pmu0_plltab *e = NULL;
+ uint32_t pmu, tmp, pll;
+ unsigned int i;
+
+ if ((siba->siba_chipid == 0x5354) && !xtalfreq)
+ xtalfreq = 25000;
+ if (xtalfreq)
+ e = siba_cc_pmu0_plltab_findentry(xtalfreq);
+ if (!e)
+ e = siba_cc_pmu0_plltab_findentry(
+ SIBA_CC_PMU0_DEFAULT_XTALFREQ);
+ KASSERT(e != NULL, ("%s:%d: fail", __func__, __LINE__));
+ xtalfreq = e->freq;
+ scc->scc_pmu.freq = e->freq;
+
+ pmu = SIBA_CC_READ32(scc, SIBA_CC_PMUCTL);
+ if (((pmu & SIBA_CC_PMUCTL_XF) >> 2) == e->xf)
+ return;
+
+ DPRINTF(siba, SIBA_DEBUG_PLL, "change PLL value to %u.%03u mhz\n",
+ (xtalfreq / 1000), (xtalfreq % 1000));
+
+ KASSERT(siba->siba_chipid == 0x4328 || siba->siba_chipid == 0x5354,
+ ("%s:%d: fail", __func__, __LINE__));
+
+ switch (siba->siba_chipid) {
+ case 0x4328:
+ SIBA_CC_MASK32(scc, SIBA_CC_PMU_MINRES,
+ ~(1 << SIBA_CC_PMU_4328_BB_PLL_PU));
+ SIBA_CC_MASK32(scc, SIBA_CC_PMU_MAXRES,
+ ~(1 << SIBA_CC_PMU_4328_BB_PLL_PU));
+ break;
+ case 0x5354:
+ SIBA_CC_MASK32(scc, SIBA_CC_PMU_MINRES,
+ ~(1 << SIBA_CC_PMU_5354_BB_PLL_PU));
+ SIBA_CC_MASK32(scc, SIBA_CC_PMU_MAXRES,
+ ~(1 << SIBA_CC_PMU_5354_BB_PLL_PU));
+ break;
+ }
+ for (i = 1500; i; i--) {
+ tmp = SIBA_CC_READ32(scc, SIBA_CC_CLKCTLSTATUS);
+ if (!(tmp & SIBA_CC_CLKCTLSTATUS_HT))
+ break;
+ DELAY(10);
+ }
+ tmp = SIBA_CC_READ32(scc, SIBA_CC_CLKCTLSTATUS);
+ if (tmp & SIBA_CC_CLKCTLSTATUS_HT)
+ device_printf(siba->siba_dev, "failed to turn PLL off!\n");
+
+ /* set PDIV */
+ pll = siba_cc_pll_read(scc, SIBA_CC_PMU0_PLL0);
+ if (xtalfreq >= SIBA_CC_PMU0_PLL0_PDIV_FREQ)
+ pll |= SIBA_CC_PMU0_PLL0_PDIV_MSK;
+ else
+ pll &= ~SIBA_CC_PMU0_PLL0_PDIV_MSK;
+ siba_cc_pll_write(scc, SIBA_CC_PMU0_PLL0, pll);
+
+ /* set WILD */
+ pll = siba_cc_pll_read(scc, SIBA_CC_PMU0_PLL1);
+ pll &= ~(SIBA_CC_PMU0_PLL1_STOPMOD | SIBA_CC_PMU0_PLL1_IMSK |
+ SIBA_CC_PMU0_PLL1_FMSK);
+ pll |= ((uint32_t)e->wb_int << 28) & SIBA_CC_PMU0_PLL1_IMSK;
+ pll |= ((uint32_t)e->wb_frac << 8) & SIBA_CC_PMU0_PLL1_FMSK;
+ if (e->wb_frac == 0)
+ pll |= SIBA_CC_PMU0_PLL1_STOPMOD;
+ siba_cc_pll_write(scc, SIBA_CC_PMU0_PLL1, pll);
+
+ /* set WILD */
+ pll = siba_cc_pll_read(scc, SIBA_CC_PMU0_PLL2);
+ pll &= ~SIBA_CC_PMU0_PLL2_IMSKHI;
+ pll |= (((uint32_t)e->wb_int >> 4) << 0) & SIBA_CC_PMU0_PLL2_IMSKHI;
+ siba_cc_pll_write(scc, SIBA_CC_PMU0_PLL2, pll);
+
+ /* set freq and divisor. */
+ pmu = SIBA_CC_READ32(scc, SIBA_CC_PMUCTL);
+ pmu &= ~SIBA_CC_PMUCTL_ILP;
+ pmu |= (((xtalfreq + 127) / 128 - 1) << 16) & SIBA_CC_PMUCTL_ILP;
+ pmu &= ~SIBA_CC_PMUCTL_XF;
+ pmu |= ((uint32_t)e->xf << 2) & SIBA_CC_PMUCTL_XF;
+ SIBA_CC_WRITE32(scc, SIBA_CC_PMUCTL, pmu);
+}
+
+static enum siba_clksrc
+siba_cc_clksrc(struct siba_cc *scc)
+{
+ struct siba_dev_softc *sd = scc->scc_dev;
+ struct siba_softc *siba = sd->sd_bus;
+
+ if (sd->sd_id.sd_rev < 6) {
+ if (siba->siba_type == SIBA_TYPE_PCI) {
+ if (pci_read_config(siba->siba_dev, SIBA_GPIO_OUT, 4) &
+ 0x10)
+ return (SIBA_CC_CLKSRC_PCI);
+ return (SIBA_CC_CLKSRC_CRYSTAL);
+ }
+ if (siba->siba_type == SIBA_TYPE_SSB ||
+ siba->siba_type == SIBA_TYPE_PCMCIA)
+ return (SIBA_CC_CLKSRC_CRYSTAL);
+ }
+ if (sd->sd_id.sd_rev < 10) {
+ switch (SIBA_CC_READ32(scc, SIBA_CC_CLKSLOW) & 0x7) {
+ case 0:
+ return (SIBA_CC_CLKSRC_LOWPW);
+ case 1:
+ return (SIBA_CC_CLKSRC_CRYSTAL);
+ case 2:
+ return (SIBA_CC_CLKSRC_PCI);
+ default:
+ break;
+ }
+ }
+
+ return (SIBA_CC_CLKSRC_CRYSTAL);
+}
+
+static const struct siba_cc_pmu1_plltab *
+siba_cc_pmu1_plltab_find(uint32_t crystalfreq)
+{
+ const struct siba_cc_pmu1_plltab *e;
+ unsigned int i;
+
+ for (i = 0; i < N(siba_cc_pmu1_plltab); i++) {
+ e = &siba_cc_pmu1_plltab[i];
+ if (crystalfreq == e->freq)
+ return (e);
+ }
+
+ return (NULL);
+}
+
+static uint32_t
+siba_cc_pll_read(struct siba_cc *scc, uint32_t offset)
+{
+
+ SIBA_CC_WRITE32(scc, SIBA_CC_PLLCTL_ADDR, offset);
+ return (SIBA_CC_READ32(scc, SIBA_CC_PLLCTL_DATA));
+}
+
+static void
+siba_cc_pll_write(struct siba_cc *scc, uint32_t offset, uint32_t value)
+{
+
+ SIBA_CC_WRITE32(scc, SIBA_CC_PLLCTL_ADDR, offset);
+ SIBA_CC_WRITE32(scc, SIBA_CC_PLLCTL_DATA, value);
+}
+
+static const struct siba_cc_pmu0_plltab *
+siba_cc_pmu0_plltab_findentry(uint32_t crystalfreq)
+{
+ const struct siba_cc_pmu0_plltab *e;
+ unsigned int i;
+
+ for (i = 0; i < N(siba_cc_pmu0_plltab); i++) {
+ e = &siba_cc_pmu0_plltab[i];
+ if (e->freq == crystalfreq)
+ return (e);
+ }
+
+ return (NULL);
+}
+
+static int
+siba_pci_sprom(struct siba_softc *siba, struct siba_sprom *sprom)
+{
+ int error = ENOMEM;
+ uint16_t *buf;
+
+ buf = malloc(SIBA_SPROMSIZE_R123 * sizeof(uint16_t),
+ M_DEVBUF, M_NOWAIT | M_ZERO);
+ if (buf == NULL)
+ return (ENOMEM);
+ siba_sprom_read(siba, buf, SIBA_SPROMSIZE_R123);
+ error = sprom_check_crc(buf, siba->siba_spromsize);
+ if (error) {
+ free(buf, M_DEVBUF);
+ buf = malloc(SIBA_SPROMSIZE_R4 * sizeof(uint16_t),
+ M_DEVBUF, M_NOWAIT | M_ZERO);
+ if (buf == NULL)
+ return (ENOMEM);
+ siba_sprom_read(siba, buf, SIBA_SPROMSIZE_R4);
+ error = sprom_check_crc(buf, siba->siba_spromsize);
+ if (error)
+ device_printf(siba->siba_dev, "warn: bad SPROM CRC\n");
+ }
+
+ bzero(sprom, sizeof(*sprom));
+
+ sprom->rev = buf[siba->siba_spromsize - 1] & 0x00FF;
+ DPRINTF(siba, SIBA_DEBUG_SPROM, "SPROM rev %d\n",
+ sprom->rev);
+ memset(sprom->mac_eth, 0xff, 6);
+ memset(sprom->mac_80211a, 0xff, 6);
+ if ((siba->siba_chipid & 0xff00) == 0x4400) {
+ sprom->rev = 1;
+ siba_sprom_r123(sprom, buf);
+ } else if (siba->siba_chipid == 0x4321) {
+ sprom->rev = 4;
+ siba_sprom_r45(sprom, buf);
+ } else {
+ switch (sprom->rev) {
+ case 1:
+ case 2:
+ case 3:
+ siba_sprom_r123(sprom, buf);
+ break;
+ case 4:
+ case 5:
+ siba_sprom_r45(sprom, buf);
+ break;
+ case 8:
+ siba_sprom_r8(sprom, buf);
+ break;
+ default:
+ device_printf(siba->siba_dev,
+ "unknown SPROM revision %d.\n", sprom->rev);
+ siba_sprom_r123(sprom, buf);
+ }
+ }
+
+ if (sprom->bf_lo == 0xffff)
+ sprom->bf_lo = 0;
+ if (sprom->bf_hi == 0xffff)
+ sprom->bf_hi = 0;
+
+ free(buf, M_DEVBUF);
+ return (error);
+}
+
+static int
+siba_sprom_read(struct siba_softc *siba, uint16_t *sprom, uint16_t len)
+{
+ int i;
+
+ for (i = 0; i < len; i++)
+ sprom[i] = SIBA_READ_2(siba, SIBA_SPROM_BASE + (i * 2));
+
+ siba->siba_spromsize = len;
+ return (0);
+}
+
+static int
+sprom_check_crc(const uint16_t *sprom, size_t size)
+{
+ int word;
+ uint8_t crc0, crc1 = 0xff;
+
+ crc0 = (sprom[size - 1] & SIBA_SPROM_REV_CRC) >> 8;
+ for (word = 0; word < size - 1; word++) {
+ crc1 = siba_crc8(crc1, sprom[word] & 0x00ff);
+ crc1 = siba_crc8(crc1, (sprom[word] & 0xff00) >> 8);
+ }
+ crc1 = siba_crc8(crc1, sprom[size - 1] & 0x00ff);
+ crc1 ^= 0xff;
+
+ return ((crc0 != crc1) ? EPROTO : 0);
+}
+
+static uint8_t
+siba_crc8(uint8_t crc, uint8_t data)
+{
+ static const uint8_t ct[] = {
+ 0x00, 0xf7, 0xb9, 0x4e, 0x25, 0xd2, 0x9c, 0x6b,
+ 0x4a, 0xbd, 0xf3, 0x04, 0x6f, 0x98, 0xd6, 0x21,
+ 0x94, 0x63, 0x2d, 0xda, 0xb1, 0x46, 0x08, 0xff,
+ 0xde, 0x29, 0x67, 0x90, 0xfb, 0x0c, 0x42, 0xb5,
+ 0x7f, 0x88, 0xc6, 0x31, 0x5a, 0xad, 0xe3, 0x14,
+ 0x35, 0xc2, 0x8c, 0x7b, 0x10, 0xe7, 0xa9, 0x5e,
+ 0xeb, 0x1c, 0x52, 0xa5, 0xce, 0x39, 0x77, 0x80,
+ 0xa1, 0x56, 0x18, 0xef, 0x84, 0x73, 0x3d, 0xca,
+ 0xfe, 0x09, 0x47, 0xb0, 0xdb, 0x2c, 0x62, 0x95,
+ 0xb4, 0x43, 0x0d, 0xfa, 0x91, 0x66, 0x28, 0xdf,
+ 0x6a, 0x9d, 0xd3, 0x24, 0x4f, 0xb8, 0xf6, 0x01,
+ 0x20, 0xd7, 0x99, 0x6e, 0x05, 0xf2, 0xbc, 0x4b,
+ 0x81, 0x76, 0x38, 0xcf, 0xa4, 0x53, 0x1d, 0xea,
+ 0xcb, 0x3c, 0x72, 0x85, 0xee, 0x19, 0x57, 0xa0,
+ 0x15, 0xe2, 0xac, 0x5b, 0x30, 0xc7, 0x89, 0x7e,
+ 0x5f, 0xa8, 0xe6, 0x11, 0x7a, 0x8d, 0xc3, 0x34,
+ 0xab, 0x5c, 0x12, 0xe5, 0x8e, 0x79, 0x37, 0xc0,
+ 0xe1, 0x16, 0x58, 0xaf, 0xc4, 0x33, 0x7d, 0x8a,
+ 0x3f, 0xc8, 0x86, 0x71, 0x1a, 0xed, 0xa3, 0x54,
+ 0x75, 0x82, 0xcc, 0x3b, 0x50, 0xa7, 0xe9, 0x1e,
+ 0xd4, 0x23, 0x6d, 0x9a, 0xf1, 0x06, 0x48, 0xbf,
+ 0x9e, 0x69, 0x27, 0xd0, 0xbb, 0x4c, 0x02, 0xf5,
+ 0x40, 0xb7, 0xf9, 0x0e, 0x65, 0x92, 0xdc, 0x2b,
+ 0x0a, 0xfd, 0xb3, 0x44, 0x2f, 0xd8, 0x96, 0x61,
+ 0x55, 0xa2, 0xec, 0x1b, 0x70, 0x87, 0xc9, 0x3e,
+ 0x1f, 0xe8, 0xa6, 0x51, 0x3a, 0xcd, 0x83, 0x74,
+ 0xc1, 0x36, 0x78, 0x8f, 0xe4, 0x13, 0x5d, 0xaa,
+ 0x8b, 0x7c, 0x32, 0xc5, 0xae, 0x59, 0x17, 0xe0,
+ 0x2a, 0xdd, 0x93, 0x64, 0x0f, 0xf8, 0xb6, 0x41,
+ 0x60, 0x97, 0xd9, 0x2e, 0x45, 0xb2, 0xfc, 0x0b,
+ 0xbe, 0x49, 0x07, 0xf0, 0x9b, 0x6c, 0x22, 0xd5,
+ 0xf4, 0x03, 0x4d, 0xba, 0xd1, 0x26, 0x68, 0x9f,
+ };
+ return (ct[crc ^ data]);
+}
+
+#define SIBA_LOWEST_SET_BIT(__mask) ((((__mask) - 1) & (__mask)) ^ (__mask))
+#define SIBA_OFFSET(offset) \
+ (((offset) - SIBA_SPROM_BASE) / sizeof(uint16_t))
+#define SIBA_SHIFTOUT_SUB(__x, __mask) \
+ (((__x) & (__mask)) / SIBA_LOWEST_SET_BIT(__mask))
+#define SIBA_SHIFTOUT(_var, _offset, _mask) \
+ out->_var = SIBA_SHIFTOUT_SUB(in[SIBA_OFFSET(_offset)], (_mask))
+
+static void
+siba_sprom_r123(struct siba_sprom *out, const uint16_t *in)
+{
+ int i;
+ uint16_t v;
+ int8_t gain;
+ uint16_t loc[3];
+
+ if (out->rev == 3)
+ loc[0] = SIBA_SPROM3_MAC_80211BG;
+ else {
+ loc[0] = SIBA_SPROM1_MAC_80211BG;
+ loc[1] = SIBA_SPROM1_MAC_ETH;
+ loc[2] = SIBA_SPROM1_MAC_80211A;
+ }
+ for (i = 0; i < 3; i++) {
+ v = in[SIBA_OFFSET(loc[0]) + i];
+ *(((uint16_t *)out->mac_80211bg) + i) = htobe16(v);
+ }
+ if (out->rev < 3) {
+ for (i = 0; i < 3; i++) {
+ v = in[SIBA_OFFSET(loc[1]) + i];
+ *(((uint16_t *)out->mac_eth) + i) = htobe16(v);
+ }
+ for (i = 0; i < 3; i++) {
+ v = in[SIBA_OFFSET(loc[2]) + i];
+ *(((uint16_t *)out->mac_80211a) + i) = htobe16(v);
+ }
+ }
+ SIBA_SHIFTOUT(mii_eth0, SIBA_SPROM1_ETHPHY,
+ SIBA_SPROM1_ETHPHY_MII_ETH0);
+ SIBA_SHIFTOUT(mii_eth1, SIBA_SPROM1_ETHPHY,
+ SIBA_SPROM1_ETHPHY_MII_ETH1);
+ SIBA_SHIFTOUT(mdio_eth0, SIBA_SPROM1_ETHPHY,
+ SIBA_SPROM1_ETHPHY_MDIO_ETH0);
+ SIBA_SHIFTOUT(mdio_eth1, SIBA_SPROM1_ETHPHY,
+ SIBA_SPROM1_ETHPHY_MDIO_ETH1);
+ SIBA_SHIFTOUT(brev, SIBA_SPROM1_BOARDINFO, SIBA_SPROM1_BOARDINFO_BREV);
+ SIBA_SHIFTOUT(ccode, SIBA_SPROM1_BOARDINFO,
+ SIBA_SPROM1_BOARDINFO_CCODE);
+ SIBA_SHIFTOUT(ant_a, SIBA_SPROM1_BOARDINFO, SIBA_SPROM1_BOARDINFO_ANTA);
+ SIBA_SHIFTOUT(ant_bg, SIBA_SPROM1_BOARDINFO,
+ SIBA_SPROM1_BOARDINFO_ANTBG);
+ SIBA_SHIFTOUT(pa0b0, SIBA_SPROM1_PA0B0, 0xffff);
+ SIBA_SHIFTOUT(pa0b1, SIBA_SPROM1_PA0B1, 0xffff);
+ SIBA_SHIFTOUT(pa0b2, SIBA_SPROM1_PA0B2, 0xffff);
+ SIBA_SHIFTOUT(pa1b0, SIBA_SPROM1_PA1B0, 0xffff);
+ SIBA_SHIFTOUT(pa1b1, SIBA_SPROM1_PA1B1, 0xffff);
+ SIBA_SHIFTOUT(pa1b2, SIBA_SPROM1_PA1B2, 0xffff);
+ SIBA_SHIFTOUT(gpio0, SIBA_SPROM1_GPIOA, SIBA_SPROM1_GPIOA_P0);
+ SIBA_SHIFTOUT(gpio1, SIBA_SPROM1_GPIOA, SIBA_SPROM1_GPIOA_P1);
+ SIBA_SHIFTOUT(gpio2, SIBA_SPROM1_GPIOB, SIBA_SPROM1_GPIOB_P2);
+ SIBA_SHIFTOUT(gpio3, SIBA_SPROM1_GPIOB, SIBA_SPROM1_GPIOB_P3);
+ SIBA_SHIFTOUT(maxpwr_a, SIBA_SPROM1_MAXPWR, SIBA_SPROM1_MAXPWR_A);
+ SIBA_SHIFTOUT(maxpwr_bg, SIBA_SPROM1_MAXPWR, SIBA_SPROM1_MAXPWR_BG);
+ SIBA_SHIFTOUT(tssi_a, SIBA_SPROM1_TSSI, SIBA_SPROM1_TSSI_A);
+ SIBA_SHIFTOUT(tssi_bg, SIBA_SPROM1_TSSI, SIBA_SPROM1_TSSI_BG);
+ SIBA_SHIFTOUT(bf_lo, SIBA_SPROM1_BFLOW, 0xffff);
+ if (out->rev >= 2)
+ SIBA_SHIFTOUT(bf_hi, SIBA_SPROM2_BFHIGH, 0xffff);
+
+ /* antenna gain */
+ gain = siba_sprom_r123_antgain(out->rev, in, SIBA_SPROM1_AGAIN_BG, 0);
+ out->again.ghz24.a0 = out->again.ghz24.a1 = gain;
+ out->again.ghz24.a2 = out->again.ghz24.a3 = gain;
+ gain = siba_sprom_r123_antgain(out->rev, in, SIBA_SPROM1_AGAIN_A, 8);
+ out->again.ghz5.a0 = out->again.ghz5.a1 = gain;
+ out->again.ghz5.a2 = out->again.ghz5.a3 = gain;
+}
+
+static void
+siba_sprom_r45(struct siba_sprom *out, const uint16_t *in)
+{
+ int i;
+ uint16_t v;
+ uint16_t mac_80211bg_offset;
+
+ if (out->rev == 4)
+ mac_80211bg_offset = SIBA_SPROM4_MAC_80211BG;
+ else
+ mac_80211bg_offset = SIBA_SPROM5_MAC_80211BG;
+ for (i = 0; i < 3; i++) {
+ v = in[SIBA_OFFSET(mac_80211bg_offset) + i];
+ *(((uint16_t *)out->mac_80211bg) + i) = htobe16(v);
+ }
+ SIBA_SHIFTOUT(mii_eth0, SIBA_SPROM4_ETHPHY, SIBA_SPROM4_ETHPHY_ET0A);
+ SIBA_SHIFTOUT(mii_eth1, SIBA_SPROM4_ETHPHY, SIBA_SPROM4_ETHPHY_ET1A);
+ if (out->rev == 4) {
+ SIBA_SHIFTOUT(ccode, SIBA_SPROM4_CCODE, 0xffff);
+ SIBA_SHIFTOUT(bf_lo, SIBA_SPROM4_BFLOW, 0xffff);
+ SIBA_SHIFTOUT(bf_hi, SIBA_SPROM4_BFHIGH, 0xffff);
+ } else {
+ SIBA_SHIFTOUT(ccode, SIBA_SPROM5_CCODE, 0xffff);
+ SIBA_SHIFTOUT(bf_lo, SIBA_SPROM5_BFLOW, 0xffff);
+ SIBA_SHIFTOUT(bf_hi, SIBA_SPROM5_BFHIGH, 0xffff);
+ }
+ SIBA_SHIFTOUT(ant_a, SIBA_SPROM4_ANTAVAIL, SIBA_SPROM4_ANTAVAIL_A);
+ SIBA_SHIFTOUT(ant_bg, SIBA_SPROM4_ANTAVAIL, SIBA_SPROM4_ANTAVAIL_BG);
+ SIBA_SHIFTOUT(maxpwr_bg, SIBA_SPROM4_MAXP_BG, SIBA_SPROM4_MAXP_BG_MASK);
+ SIBA_SHIFTOUT(tssi_bg, SIBA_SPROM4_MAXP_BG, SIBA_SPROM4_TSSI_BG);
+ SIBA_SHIFTOUT(maxpwr_a, SIBA_SPROM4_MAXP_A, SIBA_SPROM4_MAXP_A_MASK);
+ SIBA_SHIFTOUT(tssi_a, SIBA_SPROM4_MAXP_A, SIBA_SPROM4_TSSI_A);
+ if (out->rev == 4) {
+ SIBA_SHIFTOUT(gpio0, SIBA_SPROM4_GPIOA, SIBA_SPROM4_GPIOA_P0);
+ SIBA_SHIFTOUT(gpio1, SIBA_SPROM4_GPIOA, SIBA_SPROM4_GPIOA_P1);
+ SIBA_SHIFTOUT(gpio2, SIBA_SPROM4_GPIOB, SIBA_SPROM4_GPIOB_P2);
+ SIBA_SHIFTOUT(gpio3, SIBA_SPROM4_GPIOB, SIBA_SPROM4_GPIOB_P3);
+ } else {
+ SIBA_SHIFTOUT(gpio0, SIBA_SPROM5_GPIOA, SIBA_SPROM5_GPIOA_P0);
+ SIBA_SHIFTOUT(gpio1, SIBA_SPROM5_GPIOA, SIBA_SPROM5_GPIOA_P1);
+ SIBA_SHIFTOUT(gpio2, SIBA_SPROM5_GPIOB, SIBA_SPROM5_GPIOB_P2);
+ SIBA_SHIFTOUT(gpio3, SIBA_SPROM5_GPIOB, SIBA_SPROM5_GPIOB_P3);
+ }
+
+ /* antenna gain */
+ SIBA_SHIFTOUT(again.ghz24.a0, SIBA_SPROM4_AGAIN01, SIBA_SPROM4_AGAIN0);
+ SIBA_SHIFTOUT(again.ghz24.a1, SIBA_SPROM4_AGAIN01, SIBA_SPROM4_AGAIN1);
+ SIBA_SHIFTOUT(again.ghz24.a2, SIBA_SPROM4_AGAIN23, SIBA_SPROM4_AGAIN2);
+ SIBA_SHIFTOUT(again.ghz24.a3, SIBA_SPROM4_AGAIN23, SIBA_SPROM4_AGAIN3);
+ bcopy(&out->again.ghz24, &out->again.ghz5, sizeof(out->again.ghz5));
+}
+
+static void
+siba_sprom_r8(struct siba_sprom *out, const uint16_t *in)
+{
+ int i;
+ uint16_t v;
+
+ for (i = 0; i < 3; i++) {
+ v = in[SIBA_OFFSET(SIBA_SPROM1_MAC_80211BG) + i];
+ *(((uint16_t *)out->mac_80211bg) + i) = htobe16(v);
+ }
+ SIBA_SHIFTOUT(ccode, SIBA_SPROM8_CCODE, 0xffff);
+ SIBA_SHIFTOUT(bf_lo, SIBA_SPROM8_BFLOW, 0xffff);
+ SIBA_SHIFTOUT(bf_hi, SIBA_SPROM8_BFHIGH, 0xffff);
+ SIBA_SHIFTOUT(ant_a, SIBA_SPROM8_ANTAVAIL, SIBA_SPROM8_ANTAVAIL_A);
+ SIBA_SHIFTOUT(ant_bg, SIBA_SPROM8_ANTAVAIL, SIBA_SPROM8_ANTAVAIL_BG);
+ SIBA_SHIFTOUT(maxpwr_bg, SIBA_SPROM8_MAXP_BG, SIBA_SPROM8_MAXP_BG_MASK);
+ SIBA_SHIFTOUT(tssi_bg, SIBA_SPROM8_MAXP_BG, SIBA_SPROM8_TSSI_BG);
+ SIBA_SHIFTOUT(maxpwr_a, SIBA_SPROM8_MAXP_A, SIBA_SPROM8_MAXP_A_MASK);
+ SIBA_SHIFTOUT(tssi_a, SIBA_SPROM8_MAXP_A, SIBA_SPROM8_TSSI_A);
+ SIBA_SHIFTOUT(gpio0, SIBA_SPROM8_GPIOA, SIBA_SPROM8_GPIOA_P0);
+ SIBA_SHIFTOUT(gpio1, SIBA_SPROM8_GPIOA, SIBA_SPROM8_GPIOA_P1);
+ SIBA_SHIFTOUT(gpio2, SIBA_SPROM8_GPIOB, SIBA_SPROM8_GPIOB_P2);
+ SIBA_SHIFTOUT(gpio3, SIBA_SPROM8_GPIOB, SIBA_SPROM8_GPIOB_P3);
+
+ /* antenna gain */
+ SIBA_SHIFTOUT(again.ghz24.a0, SIBA_SPROM8_AGAIN01, SIBA_SPROM8_AGAIN0);
+ SIBA_SHIFTOUT(again.ghz24.a1, SIBA_SPROM8_AGAIN01, SIBA_SPROM8_AGAIN1);
+ SIBA_SHIFTOUT(again.ghz24.a2, SIBA_SPROM8_AGAIN23, SIBA_SPROM8_AGAIN2);
+ SIBA_SHIFTOUT(again.ghz24.a3, SIBA_SPROM8_AGAIN23, SIBA_SPROM8_AGAIN3);
+ bcopy(&out->again.ghz24, &out->again.ghz5, sizeof(out->again.ghz5));
+}
+
+static int8_t
+siba_sprom_r123_antgain(uint8_t sprom_revision, const uint16_t *in,
+ uint16_t mask, uint16_t shift)
+{
+ uint16_t v;
+ uint8_t gain;
+
+ v = in[SIBA_OFFSET(SIBA_SPROM1_AGAIN)];
+ gain = (v & mask) >> shift;
+ gain = (gain == 0xff) ? 2 : (sprom_revision == 1) ? gain << 2 :
+ ((gain & 0xc0) >> 6) | ((gain & 0x3f) << 2);
+
+ return ((int8_t)gain);
+}
+
+#undef SIBA_LOWEST_SET_BIT
+#undef SIBA_OFFSET
+#undef SIBA_SHIFTOUT_SUB
+#undef SIBA_SHIFTOUT
+
+int
+siba_powerdown(struct siba_softc *siba)
+{
+ struct siba_cc *scc;
+
+ if (siba->siba_type == SIBA_TYPE_SSB)
+ return (0);
+
+ scc = &siba->siba_cc;
+ if (!scc->scc_dev || scc->scc_dev->sd_id.sd_rev < 5)
+ return (0);
+ siba_cc_clock(scc, SIBA_CLOCK_SLOW);
+ siba_pci_gpio(siba, SIBA_GPIO_CRYSTAL | SIBA_GPIO_PLL, 0);
+ return (0);
+}
+
+static void
+siba_pcicore_init(struct siba_pci *spc)
+{
+ struct siba_dev_softc *sd = spc->spc_dev;
+ struct siba_softc *siba;
+
+ if (sd == NULL)
+ return;
+
+ siba = sd->sd_bus;
+ if (!siba_dev_isup(sd))
+ siba_dev_up(sd, 0);
+
+ KASSERT(spc->spc_hostmode == 0,
+ ("%s:%d: hostmode", __func__, __LINE__));
+ /* disable PCI interrupt */
+ siba_write_4(spc->spc_dev, SIBA_INTR_MASK, 0);
+}
+
+int
+siba_dev_isup(struct siba_dev_softc *sd)
+{
+ uint32_t reject, val;
+
+ reject = siba_tmslow_reject_bitmask(sd);
+ val = siba_read_4(sd, SIBA_TGSLOW);
+ val &= SIBA_TGSLOW_CLOCK | SIBA_TGSLOW_RESET | reject;
+
+ return (val == SIBA_TGSLOW_CLOCK);
+}
+
+void
+siba_dev_up(struct siba_dev_softc *sd, uint32_t flags)
+{
+ uint32_t val;
+
+ siba_dev_down(sd, flags);
+ siba_write_4(sd, SIBA_TGSLOW, SIBA_TGSLOW_RESET | SIBA_TGSLOW_CLOCK |
+ SIBA_TGSLOW_FGC | flags);
+ siba_read_4(sd, SIBA_TGSLOW);
+ DELAY(1);
+
+ if (siba_read_4(sd, SIBA_TGSHIGH) & SIBA_TGSHIGH_SERR)
+ siba_write_4(sd, SIBA_TGSHIGH, 0);
+
+ val = siba_read_4(sd, SIBA_IAS);
+ if (val & (SIBA_IAS_INBAND_ERR | SIBA_IAS_TIMEOUT)) {
+ val &= ~(SIBA_IAS_INBAND_ERR | SIBA_IAS_TIMEOUT);
+ siba_write_4(sd, SIBA_IAS, val);
+ }
+
+ siba_write_4(sd, SIBA_TGSLOW,
+ SIBA_TGSLOW_CLOCK | SIBA_TGSLOW_FGC | flags);
+ siba_read_4(sd, SIBA_TGSLOW);
+ DELAY(1);
+
+ siba_write_4(sd, SIBA_TGSLOW, SIBA_TGSLOW_CLOCK | flags);
+ siba_read_4(sd, SIBA_TGSLOW);
+ DELAY(1);
+}
+
+static uint32_t
+siba_tmslow_reject_bitmask(struct siba_dev_softc *sd)
+{
+ uint32_t rev = siba_read_4(sd, SIBA_IDLOW) & SIBA_IDLOW_SSBREV;
+
+ switch (rev) {
+ case SIBA_IDLOW_SSBREV_22:
+ return (SIBA_TGSLOW_REJECT_22);
+ case SIBA_IDLOW_SSBREV_23:
+ return (SIBA_TGSLOW_REJECT_23);
+ case SIBA_IDLOW_SSBREV_24:
+ case SIBA_IDLOW_SSBREV_25:
+ case SIBA_IDLOW_SSBREV_26:
+ case SIBA_IDLOW_SSBREV_27:
+ return (SIBA_TGSLOW_REJECT_23);
+ default:
+ KASSERT(0 == 1,
+ ("%s:%d: unknown backplane rev %#x\n",
+ __func__, __LINE__, rev));
+ }
+ return (SIBA_TGSLOW_REJECT_22 | SIBA_TGSLOW_REJECT_23);
+}
+
+void
+siba_dev_down(struct siba_dev_softc *sd, uint32_t flags)
+{
+ struct siba_softc *siba = sd->sd_bus;
+ uint32_t reject, val;
+ int i;
+
+ if (siba_read_4(sd, SIBA_TGSLOW) & SIBA_TGSLOW_RESET)
+ return;
+
+ reject = siba_tmslow_reject_bitmask(sd);
+ siba_write_4(sd, SIBA_TGSLOW, reject | SIBA_TGSLOW_CLOCK);
+
+ for (i = 0; i < 1000; i++) {
+ val = siba_read_4(sd, SIBA_TGSLOW);
+ if (val & reject)
+ break;
+ DELAY(10);
+ }
+ if ((val & reject) == 0) {
+ device_printf(siba->siba_dev, "timeout (bit %#x reg %#x)\n",
+ reject, SIBA_TGSLOW);
+ }
+ for (i = 0; i < 1000; i++) {
+ val = siba_read_4(sd, SIBA_TGSHIGH);
+ if (!(val & SIBA_TGSHIGH_BUSY))
+ break;
+ DELAY(10);
+ }
+ if ((val & SIBA_TGSHIGH_BUSY) != 0) {
+ device_printf(siba->siba_dev, "timeout (bit %#x reg %#x)\n",
+ SIBA_TGSHIGH_BUSY, SIBA_TGSHIGH);
+ }
+
+ siba_write_4(sd, SIBA_TGSLOW, SIBA_TGSLOW_FGC | SIBA_TGSLOW_CLOCK |
+ reject | SIBA_TGSLOW_RESET | flags);
+ siba_read_4(sd, SIBA_TGSLOW);
+ DELAY(1);
+ siba_write_4(sd, SIBA_TGSLOW, reject | SIBA_TGSLOW_RESET | flags);
+ siba_read_4(sd, SIBA_TGSLOW);
+ DELAY(1);
+}
+
+static void
+siba_pcicore_setup(struct siba_pci *spc, struct siba_dev_softc *sd)
+{
+ struct siba_dev_softc *psd = spc->spc_dev;
+ struct siba_softc *siba = psd->sd_bus;
+ uint32_t tmp;
+
+ if (psd->sd_id.sd_device == SIBA_DEVID_PCI) {
+ siba_pcicore_write_4(spc, SIBA_PCICORE_SBTOPCI2,
+ siba_pcicore_read_4(spc, SIBA_PCICORE_SBTOPCI2) |
+ SIBA_PCICORE_SBTOPCI_PREF | SIBA_PCICORE_SBTOPCI_BURST);
+
+ if (psd->sd_id.sd_rev < 5) {
+ tmp = siba_read_4(psd, SIBA_IMCFGLO);
+ tmp &= ~SIBA_IMCFGLO_SERTO;
+ tmp = (tmp | 2) & ~SIBA_IMCFGLO_REQTO;
+ tmp |= 3 << 4 /* SIBA_IMCFGLO_REQTO_SHIFT */;
+ siba_write_4(psd, SIBA_IMCFGLO, tmp);
+
+ /* broadcast value */
+ sd = (siba->siba_cc.scc_dev != NULL) ?
+ siba->siba_cc.scc_dev : siba->siba_pci.spc_dev;
+ if (sd != NULL) {
+ siba_write_4(sd, SIBA_PCICORE_BCAST_ADDR,
+ 0xfd8);
+ siba_read_4(sd, SIBA_PCICORE_BCAST_ADDR);
+ siba_write_4(sd, SIBA_PCICORE_BCAST_DATA, 0);
+ siba_read_4(sd, SIBA_PCICORE_BCAST_DATA);
+ }
+ } else if (psd->sd_id.sd_rev >= 11) {
+ tmp = siba_pcicore_read_4(spc, SIBA_PCICORE_SBTOPCI2);
+ tmp |= SIBA_PCICORE_SBTOPCI_MRM;
+ siba_pcicore_write_4(spc, SIBA_PCICORE_SBTOPCI2, tmp);
+ }
+ } else {
+ KASSERT(psd->sd_id.sd_device == SIBA_DEVID_PCIE, ("only PCIE"));
+ if ((psd->sd_id.sd_rev == 0) || (psd->sd_id.sd_rev == 1))
+ siba_pcie_write(spc, 0x4,
+ siba_pcie_read(spc, 0x4) | 0x8);
+ if (psd->sd_id.sd_rev == 0) {
+ siba_pcie_mdio_write(spc, 0x1f, 2, 0x8128); /* Timer */
+ siba_pcie_mdio_write(spc, 0x1f, 6, 0x0100); /* CDR */
+ siba_pcie_mdio_write(spc, 0x1f, 7, 0x1466); /* CDR BW */
+ } else if (psd->sd_id.sd_rev == 1)
+ siba_pcie_write(spc, 0x100,
+ siba_pcie_read(spc, 0x100) | 0x40);
+ }
+ spc->spc_inited = 1;
+}
+
+void
+siba_pcicore_intr(struct siba_pci *spc, struct siba_dev_softc *sd)
+{
+ struct siba_dev_softc *psd = spc->spc_dev;
+ struct siba_softc *siba;
+ uint32_t tmp;
+
+ if (sd->sd_bus->siba_type != SIBA_TYPE_PCI || !psd)
+ return;
+
+ siba = psd->sd_bus;
+ /* enable interrupts */
+ if (siba->siba_dev != NULL &&
+ (psd->sd_id.sd_rev >= 6 || psd->sd_id.sd_device == SIBA_DEVID_PCIE)) {
+ tmp = pci_read_config(siba->siba_dev, SIBA_IRQMASK, 4);
+ tmp |= (1 << sd->sd_coreidx) << 8;
+ pci_write_config(siba->siba_dev, SIBA_IRQMASK, tmp, 4);
+ } else {
+ tmp = siba_read_4(sd, SIBA_TPS);
+ tmp &= SIBA_TPS_BPFLAG;
+ siba_write_4(psd, SIBA_INTR_MASK,
+ siba_read_4(psd, SIBA_INTR_MASK) | (1 << tmp));
+ }
+
+ /* setup PCIcore */
+ if (spc->spc_inited == 0)
+ siba_pcicore_setup(spc, sd);
+}
+
+static uint32_t
+siba_pcicore_read_4(struct siba_pci *spc, uint16_t offset)
+{
+
+ return (siba_read_4(spc->spc_dev, offset));
+}
+
+static void
+siba_pcicore_write_4(struct siba_pci *spc, uint16_t offset, uint32_t value)
+{
+
+ siba_write_4(spc->spc_dev, offset, value);
+}
+
+static uint32_t
+siba_pcie_read(struct siba_pci *spc, uint32_t address)
+{
+
+ siba_pcicore_write_4(spc, 0x130, address);
+ return (siba_pcicore_read_4(spc, 0x134));
+}
+
+static void
+siba_pcie_write(struct siba_pci *spc, uint32_t address, uint32_t data)
+{
+
+ siba_pcicore_write_4(spc, 0x130, address);
+ siba_pcicore_write_4(spc, 0x134, data);
+}
+
+static void
+siba_pcie_mdio_write(struct siba_pci *spc, uint8_t device, uint8_t address,
+ uint16_t data)
+{
+ int i;
+
+ siba_pcicore_write_4(spc, SIBA_PCICORE_MDIO_CTL, 0x80 | 0x2);
+ siba_pcicore_write_4(spc, SIBA_PCICORE_MDIO_DATA,
+ (1 << 30) | (1 << 28) |
+ ((uint32_t)device << 22) | ((uint32_t)address << 18) |
+ (1 << 17) | data);
+ DELAY(10);
+ for (i = 0; i < 10; i++) {
+ if (siba_pcicore_read_4(spc, SIBA_PCICORE_MDIO_CTL) & 0x100)
+ break;
+ DELAY(1000);
+ }
+ siba_pcicore_write_4(spc, SIBA_PCICORE_MDIO_CTL, 0);
+}
+
+uint32_t
+siba_dma_translation(struct siba_dev_softc *sd)
+{
+
+ KASSERT(sd->sd_bus->siba_type == SIBA_TYPE_PCI,
+ ("unsupported bustype %d\n", sd->sd_bus->siba_type));
+ return (SIBA_PCI_DMA);
+}
+
+void
+siba_barrier(struct siba_dev_softc *sd, int flags)
+{
+ struct siba_softc *siba = sd->sd_bus;
+
+ SIBA_BARRIER(siba, flags);
+}
+
+/*
+ * Attach it as child.
+ */
+device_t
+siba_add_child(device_t dev, struct siba_softc *siba, int order,
+ const char *name, int unit)
+{
+ struct siba_dev_softc *sd;
+ device_t child;
+ int idx = 0, i;
+
+ child = device_add_child(dev, name, unit);
+ if (child == NULL)
+ return (NULL);
+
+ siba_powerup(siba, 0);
+ siba_pcicore_init(&siba->siba_pci);
+ siba_powerdown(siba);
+
+ for (i = 0; i < siba->siba_ndevs; i++) {
+ sd = &(siba->siba_devs[i]);
+
+ if (sd->sd_id.sd_device != SIBA_DEVID_80211) {
+ DPRINTF(siba, SIBA_DEBUG_CORE,
+ "skip to register coreid %#x (%s)\n",
+ sd->sd_id.sd_device,
+ siba_core_name(sd->sd_id.sd_device));
+ continue;
+ }
+
+ DPRINTF(siba, SIBA_DEBUG_CORE,
+ "siba: attaching coreid %#x (%s) idx %d\n",
+ sd->sd_id.sd_device,
+ siba_core_name(sd->sd_id.sd_device), idx);
+
+ KASSERT(sd->sd_id.sd_device == SIBA_DEVID_80211,
+ ("%s:%d: SIBA_DEVID_80211 is only supportted currently.",
+ __func__, __LINE__));
+
+ device_set_ivars(child, sd);
+ device_probe_and_attach(child);
+ idx++;
+ }
+ return (child);
+}
+
+static void
+siba_cc_suspend(struct siba_cc *scc)
+{
+
+ siba_cc_clock(scc, SIBA_CLOCK_SLOW);
+}
+
+static void
+siba_cc_resume(struct siba_cc *scc)
+{
+
+ siba_cc_power_init(scc);
+ siba_cc_clock(scc, SIBA_CLOCK_FAST);
+}
+
+int
+siba_core_suspend(struct siba_softc *siba)
+{
+
+ siba_cc_suspend(&siba->siba_cc);
+ siba_pci_gpio(siba, SIBA_GPIO_CRYSTAL | SIBA_GPIO_PLL, 0);
+ return (0);
+}
+
+int
+siba_core_resume(struct siba_softc *siba)
+{
+
+ siba->siba_pci.spc_inited = 0;
+ siba->siba_curdev = NULL;
+
+ siba_powerup(siba, 0);
+ /* XXX setup H/W for PCMCIA??? */
+ siba_cc_resume(&siba->siba_cc);
+ siba_powerdown(siba);
+
+ return (0);
+}
diff --git a/sys/dev/siba/siba_ids.h b/sys/dev/siba/siba_ids.h
index c7acd20..b5aaf34 100644
--- a/sys/dev/siba/siba_ids.h
+++ b/sys/dev/siba/siba_ids.h
@@ -39,23 +39,45 @@ struct siba_devid {
uint8_t sd_rev;
char *sd_desc;
};
+#define SIBA_DEV(_vendor, _cid, _rev, _msg) \
+ { SIBA_VID_##_vendor, SIBA_DEVID_##_cid, _rev, _msg }
/*
* 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
+#define SIBA_DEVID_ANY 0xffff
+#define SIBA_DEVID_CHIPCOMMON 0x800
+#define SIBA_DEVID_ILINE20 0x801
+#define SIBA_DEVID_SDRAM 0x803
+#define SIBA_DEVID_PCI 0x804
+#define SIBA_DEVID_MIPS 0x805
+#define SIBA_DEVID_ETHERNET 0x806
+#define SIBA_DEVID_MODEM 0x807
+#define SIBA_DEVID_USB11_HOSTDEV 0x808
+#define SIBA_DEVID_ADSL 0x809
+#define SIBA_DEVID_ILINE100 0x80a
+#define SIBA_DEVID_IPSEC 0x80b
+#define SIBA_DEVID_PCMCIA 0x80d
+#define SIBA_DEVID_INTERNAL_MEM 0x80e
+#define SIBA_DEVID_SDRAMDDR 0x80f
+#define SIBA_DEVID_EXTIF 0x811
+#define SIBA_DEVID_80211 0x812
+#define SIBA_DEVID_MIPS_3302 0x816
+#define SIBA_DEVID_USB11_HOST 0x817
+#define SIBA_DEVID_USB11_DEV 0x818
+#define SIBA_DEVID_USB20_HOST 0x819
+#define SIBA_DEVID_USB20_DEV 0x81a
+#define SIBA_DEVID_SDIO_HOST 0x81b
+#define SIBA_DEVID_ROBOSWITCH 0x81c
+#define SIBA_DEVID_PARA_ATA 0x81d
+#define SIBA_DEVID_SATA_XORDMA 0x81e
+#define SIBA_DEVID_ETHERNET_GBIT 0x81f
+#define SIBA_DEVID_PCIE 0x820
+#define SIBA_DEVID_MIMO_PHY 0x821
+#define SIBA_DEVID_SRAM_CTRLR 0x822
+#define SIBA_DEVID_MINI_MACPHY 0x823
+#define SIBA_DEVID_ARM_1176 0x824
+#define SIBA_DEVID_ARM_7TDMI 0x825
/*
* Vendor IDs
diff --git a/sys/dev/siba/siba_pcib.c b/sys/dev/siba/siba_pcib.c
index d43f54c..5175aa7 100644
--- a/sys/dev/siba/siba_pcib.c
+++ b/sys/dev/siba/siba_pcib.c
@@ -55,9 +55,9 @@ __FBSDID("$FreeBSD$");
#include "pcib_if.h"
-#include <dev/siba/sibavar.h>
-#include <dev/siba/sibareg.h>
#include <dev/siba/siba_ids.h>
+#include <dev/siba/sibareg.h>
+#include <dev/siba/sibavar.h>
#include <dev/siba/siba_pcibvar.h>
#ifndef MIPS_MEM_RID
@@ -79,10 +79,6 @@ __FBSDID("$FreeBSD$");
#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
@@ -187,9 +183,12 @@ siba_pcib_attach(device_t dev)
* 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 */
+
+ /* I/O read/write window */
+ SBPCI_WRITE_4(sc, SIBA_PCICORE_SBTOPCI0, 1);
+ /* type 0 configuration only */
+ SBPCI_WRITE_4(sc, SIBA_PCICORE_SBTOPCI1, 2);
+ SBPCI_WRITE_4(sc, SIBA_PCICORE_SBTOPCI2, 1 << 30); /* memory only */
DELAY(500);
/* XXX resource managers */
@@ -365,7 +364,7 @@ siba_pcib_read_config(device_t dev, u_int bus, u_int slot, u_int func,
/*
* The configuration tag on the broadcom is weird.
*/
- SBPCI_WRITE_4(sc, SBPCI_SBTOPCI1, 2); /* XXX again??? */
+ SBPCI_WRITE_4(sc, SIBA_PCICORE_SBTOPCI1, 2); /* XXX again??? */
cfgtag = ((1 << slot) << 16) | (func << 8);
cfgaddr = SBPCI_CFGBASE | cfgtag | (reg & ~3);
diff --git a/sys/dev/siba/sibareg.h b/sys/dev/siba/sibareg.h
index dc1b7f7..9aa9e7c 100644
--- a/sys/dev/siba/sibareg.h
+++ b/sys/dev/siba/sibareg.h
@@ -34,40 +34,383 @@
#ifndef _SIBA_SIBAREG_H_
#define _SIBA_SIBAREG_H_
+#define PCI_DEVICE_ID_BCM4401 0x4401
+#define PCI_DEVICE_ID_BCM4401B0 0x4402
+#define PCI_DEVICE_ID_BCM4401B1 0x170c
+#define SIBA_PCIR_BAR PCIR_BAR(0)
+#define SIBA_CCID_BCM4710 0x4710
+#define SIBA_CCID_BCM4704 0x4704
+#define SIBA_CCID_SENTRY5 0x5365
+
+/*
+ * ChipCommon registers.
+ */
+#define SIBA_CC_CHIPID 0x0000
+#define SIBA_CC_IDMASK 0x0000ffff
+#define SIBA_CC_ID(id) (id & SIBA_CC_IDMASK)
+#define SIBA_CC_REVMASK 0x000f0000
+#define SIBA_CC_REVSHIFT 16
+#define SIBA_CC_REV(id) \
+ ((id & SIBA_CC_REVMASK) >> SIBA_CC_REVSHIFT)
+#define SIBA_CC_PKGMASK 0x00F00000
+#define SIBA_CC_PKGSHIFT 20
+#define SIBA_CC_PKG(id) \
+ ((id & SIBA_CC_PKGMASK) >> SIBA_CC_PKGSHIFT)
+#define SIBA_CC_NCORESMASK 0x0F000000
+#define SIBA_CC_NCORESSHIFT 24
+#define SIBA_CC_NCORES(id) \
+ ((id & SIBA_CC_NCORESMASK) >> SIBA_CC_NCORESSHIFT)
+#define SIBA_CC_CAPS 0x0004
+#define SIBA_CC_CAPS_PWCTL 0x00040000
+#define SIBA_CC_CAPS_PMU 0x10000000 /* PMU (rev >= 20) */
+#define SIBA_CC_CHIPCTL 0x0028 /* rev >= 11 */
+#define SIBA_CC_CHIPSTAT 0x002C /* rev >= 11 */
+#define SIBA_CC_BCAST_ADDR 0x0050 /* Broadcast Address */
+#define SIBA_CC_BCAST_DATA 0x0054 /* Broadcast Data */
+#define SIBA_CC_PLLONDELAY 0x00B0 /* Rev >= 4 only */
+#define SIBA_CC_FREFSELDELAY 0x00B4 /* Rev >= 4 only */
+#define SIBA_CC_CLKSLOW 0x00b8 /* 6 <= Rev <= 9 only */
+#define SIBA_CC_CLKSLOW_SRC 0x00000007
+#define SIBA_CC_CLKSLOW_SRC_CRYSTAL 0x00000001
+#define SIBA_CC_CLKSLOW_FSLOW 0x00000800
+#define SIBA_CC_CLKSLOW_IPLL 0x00001000
+#define SIBA_CC_CLKSLOW_ENXTAL 0x00002000
+#define SIBA_CC_CLKSYSCTL 0x00C0 /* Rev >= 3 only */
+#define SIBA_CC_CLKCTLSTATUS 0x01e0
+#define SIBA_CC_CLKCTLSTATUS_HT 0x00010000
+#define SIBA_CC_UART0 0x0300 /* offset of UART0 */
+#define SIBA_CC_UART1 0x0400 /* offset of UART1 */
+#define SIBA_CC_PMUCTL 0x0600 /* PMU control */
+#define SIBA_CC_PMUCTL_ILP 0xffff0000 /* mask */
+#define SIBA_CC_PMUCTL_NOILP 0x00000200
+#define SIBA_CC_PMUCTL_XF 0x0000007c /* crystal freq */
+#define SIBA_CC_PMUCTL_XF_VAL(id) ((id & 0x0000007c) >> 2)
+#define SIBA_CC_PMUCAPS 0x0604
+#define SIBA_CC_PMUCAPS_REV 0x000000ff
+#define SIBA_CC_PMU_MINRES 0x0618
+#define SIBA_CC_PMU_MAXRES 0x061c
+#define SIBA_CC_PMU_TABSEL 0x0620
+#define SIBA_CC_PMU_DEPMSK 0x0624
+#define SIBA_CC_PMU_UPDNTM 0x0628
+#define SIBA_CC_PLLCTL_ADDR 0x0660
+#define SIBA_CC_PLLCTL_DATA 0x0664
+
+#define SIBA_CC_PMU0_PLL0 0
+#define SIBA_CC_PMU0_PLL0_PDIV_MSK 0x00000001
+#define SIBA_CC_PMU0_PLL0_PDIV_FREQ 25000
+#define SIBA_CC_PMU0_PLL1 1
+#define SIBA_CC_PMU0_PLL1_IMSK 0xf0000000
+#define SIBA_CC_PMU0_PLL1_FMSK 0x0fffff00
+#define SIBA_CC_PMU0_PLL1_STOPMOD 0x00000040
+#define SIBA_CC_PMU0_PLL2 2
+#define SIBA_CC_PMU0_PLL2_IMSKHI 0x0000000f
+#define SIBA_CC_PMU1_PLL0 0
+#define SIBA_CC_PMU1_PLL0_P1DIV 0x00f00000
+#define SIBA_CC_PMU1_PLL0_P2DIV 0x0f000000
+#define SIBA_CC_PMU1_PLL2 2
+#define SIBA_CC_PMU1_PLL2_NDIVMODE 0x000e0000
+#define SIBA_CC_PMU1_PLL2_NDIVINT 0x1ff00000
+#define SIBA_CC_PMU1_PLL3 3
+#define SIBA_CC_PMU1_PLL3_NDIVFRAC 0x00ffffff
+#define SIBA_CC_PMU1_PLL5 5
+#define SIBA_CC_PMU1_PLL5_CLKDRV 0xffffff00
+
+#define SIBA_CC_PMU0_DEFAULT_XTALFREQ 20000
+#define SIBA_CC_PMU1_DEFAULT_FREQ 15360
+
+#define SIBA_CC_PMU1_PLLTAB_ENTRY \
+{ \
+ { 12000, 1, 3, 22, 0x9, 0xffffef }, \
+ { 13000, 2, 1, 6, 0xb, 0x483483 }, \
+ { 14400, 3, 1, 10, 0xa, 0x1c71c7 }, \
+ { 15360, 4, 1, 5, 0xb, 0x755555 }, \
+ { 16200, 5, 1, 10, 0x5, 0x6e9e06 }, \
+ { 16800, 6, 1, 10, 0x5, 0x3cf3cf }, \
+ { 19200, 7, 1, 9, 0x5, 0x17b425 }, \
+ { 19800, 8, 1, 11, 0x4, 0xa57eb }, \
+ { 20000, 9, 1, 11, 0x4, 0 }, \
+ { 24000, 10, 3, 11, 0xa, 0 }, \
+ { 25000, 11, 5, 16, 0xb, 0 }, \
+ { 26000, 12, 1, 2, 0x10, 0xec4ec4 }, \
+ { 30000, 13, 3, 8, 0xb, 0 }, \
+ { 38400, 14, 1, 5, 0x4, 0x955555 }, \
+ { 40000, 15, 1, 2, 0xb, 0 } \
+}
+
+#define SIBA_CC_PMU0_PLLTAB_ENTRY \
+{ \
+ { 12000, 1, 73, 349525, }, { 13000, 2, 67, 725937, }, \
+ { 14400, 3, 61, 116508, }, { 15360, 4, 57, 305834, }, \
+ { 16200, 5, 54, 336579, }, { 16800, 6, 52, 399457, }, \
+ { 19200, 7, 45, 873813, }, { 19800, 8, 44, 466033, }, \
+ { 20000, 9, 44, 0, }, { 25000, 10, 70, 419430, }, \
+ { 26000, 11, 67, 725937, }, { 30000, 12, 58, 699050, }, \
+ { 38400, 13, 45, 873813, }, { 40000, 14, 45, 0, }, \
+}
+
+#define SIBA_CC_PMU_4325_BURST 1
+#define SIBA_CC_PMU_4325_CLBURST 3
+#define SIBA_CC_PMU_4325_LN 10
+#define SIBA_CC_PMU_4325_CRYSTAL 13
+#define SIBA_CC_PMU_4325_RX_PWR 15
+#define SIBA_CC_PMU_4325_TX_PWR 16
+#define SIBA_CC_PMU_4325_LOGEN_PWR 18
+#define SIBA_CC_PMU_4325_AFE_PWR 19
+#define SIBA_CC_PMU_4325_BBPLL_PWR 20
+#define SIBA_CC_PMU_4325_HT 21
+#define SIBA_CC_PMU_4328_EXT_SWITCH_PWM 0
+#define SIBA_CC_PMU_4328_BB_SWITCH_PWM 1
+#define SIBA_CC_PMU_4328_BB_SWITCH_BURST 2
+#define SIBA_CC_PMU_4328_BB_EXT_SWITCH_BURST 3
+#define SIBA_CC_PMU_4328_ILP_REQUEST 4
+#define SIBA_CC_PMU_4328_RADSWITCH_PWM 5 /* radio switch */
+#define SIBA_CC_PMU_4328_RADSWITCH_BURST 6
+#define SIBA_CC_PMU_4328_ROM_SWITCH 7
+#define SIBA_CC_PMU_4328_PA_REF 8
+#define SIBA_CC_PMU_4328_RADIO 9
+#define SIBA_CC_PMU_4328_AFE 10
+#define SIBA_CC_PMU_4328_PLL 11
+#define SIBA_CC_PMU_4328_BG_FILTBYP 12
+#define SIBA_CC_PMU_4328_TX_FILTBYP 13
+#define SIBA_CC_PMU_4328_RX_FILTBYP 14
+#define SIBA_CC_PMU_4328_CRYSTAL_PU 15
+#define SIBA_CC_PMU_4328_CRYSTAL_EN 16
+#define SIBA_CC_PMU_4328_BB_PLL_FILTBYP 17
+#define SIBA_CC_PMU_4328_RF_PLL_FILTBYP 18
+#define SIBA_CC_PMU_4328_BB_PLL_PU 19
+#define SIBA_CC_PMU_5354_BB_PLL_PU 19
+
+#define SIBA_CC_PMU_4325_RES_UPDOWN \
+{ \
+ { SIBA_CC_PMU_4325_CRYSTAL, 0x1501 } \
+}
+
+#define SIBA_CC_PMU_4325_RES_DEPEND \
+{ \
+ { SIBA_CC_PMU_4325_HT, SIBA_CC_PMU_DEP_ADD, \
+ ((1 << SIBA_CC_PMU_4325_RX_PWR) | \
+ (1 << SIBA_CC_PMU_4325_TX_PWR) | \
+ (1 << SIBA_CC_PMU_4325_LOGEN_PWR) | \
+ (1 << SIBA_CC_PMU_4325_AFE_PWR)) } \
+}
+
+#define SIBA_CC_PMU_4328_RES_UPDOWN \
+{ \
+ { SIBA_CC_PMU_4328_EXT_SWITCH_PWM, 0x0101 }, \
+ { SIBA_CC_PMU_4328_BB_SWITCH_PWM, 0x1f01 }, \
+ { SIBA_CC_PMU_4328_BB_SWITCH_BURST, 0x010f }, \
+ { SIBA_CC_PMU_4328_BB_EXT_SWITCH_BURST, 0x0101 }, \
+ { SIBA_CC_PMU_4328_ILP_REQUEST, 0x0202 }, \
+ { SIBA_CC_PMU_4328_RADSWITCH_PWM, 0x0f01 }, \
+ { SIBA_CC_PMU_4328_RADSWITCH_BURST, 0x0f01 }, \
+ { SIBA_CC_PMU_4328_ROM_SWITCH, 0x0101 }, \
+ { SIBA_CC_PMU_4328_PA_REF, 0x0f01 }, \
+ { SIBA_CC_PMU_4328_RADIO, 0x0f01 }, \
+ { SIBA_CC_PMU_4328_AFE, 0x0f01 }, \
+ { SIBA_CC_PMU_4328_PLL, 0x0f01 }, \
+ { SIBA_CC_PMU_4328_BG_FILTBYP, 0x0101 }, \
+ { SIBA_CC_PMU_4328_TX_FILTBYP, 0x0101 }, \
+ { SIBA_CC_PMU_4328_RX_FILTBYP, 0x0101 }, \
+ { SIBA_CC_PMU_4328_CRYSTAL_PU, 0x0101 }, \
+ { SIBA_CC_PMU_4328_CRYSTAL_EN, 0xa001 }, \
+ { SIBA_CC_PMU_4328_BB_PLL_FILTBYP, 0x0101 }, \
+ { SIBA_CC_PMU_4328_RF_PLL_FILTBYP, 0x0101 }, \
+ { SIBA_CC_PMU_4328_BB_PLL_PU, 0x0701 }, \
+}
+
+#define SIBA_CC_PMU_4328_RES_DEPEND \
+{ \
+ { SIBA_CC_PMU_4328_ILP_REQUEST, SIBA_CC_PMU_DEP_SET, \
+ ((1 << SIBA_CC_PMU_4328_EXT_SWITCH_PWM) | \
+ (1 << SIBA_CC_PMU_4328_BB_SWITCH_PWM)) }, \
+}
+
+#define SIBA_CC_CHST_4325_PMUTOP_2B 0x00000200
+
+#define SIBA_BAR0 0x80
+#define SIBA_IRQMASK 0x94
+#define SIBA_GPIO_IN 0xb0
+#define SIBA_GPIO_OUT 0xb4
+#define SIBA_GPIO_OUT_EN 0xb8
+#define SIBA_GPIO_CRYSTAL 0x40
+#define SIBA_GPIO_PLL 0x80
+
+#define SIBA_REGWIN(x) \
+ (SIBA_ENUM_START + ((x) * SIBA_CORE_LEN))
#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 */
+#define SIBA_ENUM_START 0x18000000U
+#define SIBA_ENUM_END 0x18010000U
-/* offset of high ID register */
-#define SIBA_CORE_IDLO 0x00000ff8
-#define SIBA_CORE_IDHI 0x00000ffc
+#define SIBA_DMA_TRANSLATION_MASK 0xc0000000
-/*
- * 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
+#define SIBA_PCI_DMA 0x40000000U
+#define SIBA_TPS 0x0f18
+#define SIBA_TPS_BPFLAG 0x0000003f
+#define SIBA_IAS 0x0f90 /* Initiator Agent State */
+#define SIBA_IAS_INBAND_ERR 0x00020000
+#define SIBA_IAS_TIMEOUT 0x00040000
+#define SIBA_INTR_MASK 0x0f94
+#define SIBA_TGSLOW 0x0f98
+#define SIBA_TGSLOW_RESET 0x00000001 /* target state low */
+#define SIBA_TGSLOW_REJECT_22 0x00000002
+#define SIBA_TGSLOW_REJECT_23 0x00000004
+#define SIBA_TGSLOW_CLOCK 0x00010000
+#define SIBA_TGSLOW_FGC 0x00020000
+#define SIBA_TGSHIGH 0x0f9c
+#define SIBA_TGSHIGH_SERR 0x00000001
+#define SIBA_TGSHIGH_BUSY 0x00000004
+#define SIBA_TGSHIGH_DMA64 0x10000000
+#define SIBA_IMCFGLO 0x0fa8
+#define SIBA_IMCFGLO_SERTO 0x00000007
+#define SIBA_IMCFGLO_REQTO 0x00000070
+#define SIBA_IDLOW 0x0ff8
+#define SIBA_IDLOW_SSBREV 0xf0000000
+#define SIBA_IDLOW_SSBREV_22 0x00000000
+#define SIBA_IDLOW_SSBREV_23 0x10000000
+#define SIBA_IDLOW_SSBREV_24 0x40000000
+#define SIBA_IDLOW_SSBREV_25 0x50000000
+#define SIBA_IDLOW_SSBREV_26 0x60000000
+#define SIBA_IDLOW_SSBREV_27 0x70000000
+#define SIBA_IDHIGH 0x0ffc
+#define SIBA_IDHIGH_CORECODEMASK 0x00008FF0 /* Core Code */
+#define SIBA_IDHIGH_CORECODE_SHIFT 4
+#define SIBA_IDHIGH_CORECODE(id) \
+ ((id & SIBA_IDHIGH_CORECODEMASK) >> SIBA_IDHIGH_CORECODE_SHIFT)
+/* Revision Code (low part) */
+#define SIBA_IDHIGH_REVLO 0x0000000f
+/* Revision Code (high part) */
+#define SIBA_IDHIGH_REVHI 0x00007000
+#define SIBA_IDHIGH_REVHI_SHIFT 8
+#define SIBA_IDHIGH_REV(id) \
+ ((id & SIBA_IDHIGH_REVLO) | ((id & SIBA_IDHIGH_REVHI) >> \
+ SIBA_IDHIGH_REVHI_SHIFT))
+#define SIBA_IDHIGH_VENDORMASK 0xFFFF0000 /* Vendor Code */
+#define SIBA_IDHIGH_VENDOR_SHIFT 16
+#define SIBA_IDHIGH_VENDOR(id) \
+ ((id & SIBA_IDHIGH_VENDORMASK) >> SIBA_IDHIGH_VENDOR_SHIFT)
+
+#define SIBA_SPROMSIZE_R123 64
+#define SIBA_SPROMSIZE_R4 220
+#define SIBA_SPROM_BASE 0x1000
+#define SIBA_SPROM_REV_CRC 0xff00
+#define SIBA_SPROM1_MAC_80211BG 0x1048
+#define SIBA_SPROM1_MAC_ETH 0x104e
+#define SIBA_SPROM1_MAC_80211A 0x1054
+#define SIBA_SPROM1_ETHPHY 0x105a
+#define SIBA_SPROM1_ETHPHY_MII_ETH0 0x001f
+#define SIBA_SPROM1_ETHPHY_MII_ETH1 0x03e0
+#define SIBA_SPROM1_ETHPHY_MDIO_ETH0 (1 << 14)
+#define SIBA_SPROM1_ETHPHY_MDIO_ETH1 (1 << 15)
+#define SIBA_SPROM1_BOARDINFO 0x105c
+#define SIBA_SPROM1_BOARDINFO_BREV 0x00ff
+#define SIBA_SPROM1_BOARDINFO_CCODE 0x0f00
+#define SIBA_SPROM1_BOARDINFO_ANTBG 0x3000
+#define SIBA_SPROM1_BOARDINFO_ANTA 0xc000
+#define SIBA_SPROM1_PA0B0 0x105e
+#define SIBA_SPROM1_PA0B1 0x1060
+#define SIBA_SPROM1_PA0B2 0x1062
+#define SIBA_SPROM1_GPIOA 0x1064
+#define SIBA_SPROM1_GPIOA_P0 0x00ff
+#define SIBA_SPROM1_GPIOA_P1 0xff00
+#define SIBA_SPROM1_GPIOB 0x1066
+#define SIBA_SPROM1_GPIOB_P2 0x00ff
+#define SIBA_SPROM1_GPIOB_P3 0xff00
+#define SIBA_SPROM1_MAXPWR 0x1068
+#define SIBA_SPROM1_MAXPWR_BG 0x00ff
+#define SIBA_SPROM1_MAXPWR_A 0xff00
+#define SIBA_SPROM1_PA1B0 0x106a
+#define SIBA_SPROM1_PA1B1 0x106c
+#define SIBA_SPROM1_PA1B2 0x106e
+#define SIBA_SPROM1_TSSI 0x1070
+#define SIBA_SPROM1_TSSI_BG 0x00ff
+#define SIBA_SPROM1_TSSI_A 0xff00
+#define SIBA_SPROM1_BFLOW 0x1072
+#define SIBA_SPROM1_AGAIN 0x1074
+#define SIBA_SPROM1_AGAIN_BG 0x00ff
+#define SIBA_SPROM1_AGAIN_A 0xff00
+#define SIBA_SPROM2_BFHIGH 0x1038
+#define SIBA_SPROM3_MAC_80211BG 0x104a
+#define SIBA_SPROM4_MAC_80211BG 0x104c
+#define SIBA_SPROM4_ETHPHY 0x105a
+#define SIBA_SPROM4_ETHPHY_ET0A 0x001f
+#define SIBA_SPROM4_ETHPHY_ET1A 0x03e0
+#define SIBA_SPROM4_CCODE 0x1052
+#define SIBA_SPROM4_ANTAVAIL 0x105d
+#define SIBA_SPROM4_ANTAVAIL_A 0x00ff
+#define SIBA_SPROM4_ANTAVAIL_BG 0xff00
+#define SIBA_SPROM4_BFLOW 0x1044
+#define SIBA_SPROM4_AGAIN01 0x105e
+#define SIBA_SPROM4_AGAIN0 0x00ff
+#define SIBA_SPROM4_AGAIN1 0xff00
+#define SIBA_SPROM4_AGAIN23 0x1060
+#define SIBA_SPROM4_AGAIN2 0x00ff
+#define SIBA_SPROM4_AGAIN3 0xff00
+#define SIBA_SPROM4_BFHIGH 0x1046
+#define SIBA_SPROM4_MAXP_BG 0x1080
+#define SIBA_SPROM4_MAXP_BG_MASK 0x00ff
+#define SIBA_SPROM4_TSSI_BG 0xff00
+#define SIBA_SPROM4_MAXP_A 0x108a
+#define SIBA_SPROM4_MAXP_A_MASK 0x00ff
+#define SIBA_SPROM4_TSSI_A 0xff00
+#define SIBA_SPROM4_GPIOA 0x1056
+#define SIBA_SPROM4_GPIOA_P0 0x00ff
+#define SIBA_SPROM4_GPIOA_P1 0xff00
+#define SIBA_SPROM4_GPIOB 0x1058
+#define SIBA_SPROM4_GPIOB_P2 0x00ff
+#define SIBA_SPROM4_GPIOB_P3 0xff00
+#define SIBA_SPROM5_BFLOW 0x104a
+#define SIBA_SPROM5_BFHIGH 0x104c
+#define SIBA_SPROM5_MAC_80211BG 0x1052
+#define SIBA_SPROM5_CCODE 0x1044
+#define SIBA_SPROM5_GPIOA 0x1076
+#define SIBA_SPROM5_GPIOA_P0 0x00ff
+#define SIBA_SPROM5_GPIOA_P1 0xff00
+#define SIBA_SPROM5_GPIOB 0x1078
+#define SIBA_SPROM5_GPIOB_P2 0x00ff
+#define SIBA_SPROM5_GPIOB_P3 0xff00
+#define SIBA_SPROM8_BFLOW 0x1084
+#define SIBA_SPROM8_BFHIGH 0x1086
+#define SIBA_SPROM8_CCODE 0x1092
+#define SIBA_SPROM8_ANTAVAIL 0x109c
+#define SIBA_SPROM8_ANTAVAIL_A 0xff00
+#define SIBA_SPROM8_ANTAVAIL_BG 0x00ff
+#define SIBA_SPROM8_AGAIN01 0x109e
+#define SIBA_SPROM8_AGAIN0 0x00ff
+#define SIBA_SPROM8_AGAIN1 0xff00
+#define SIBA_SPROM8_AGAIN23 0x10a0
+#define SIBA_SPROM8_AGAIN2 0x00ff
+#define SIBA_SPROM8_AGAIN3 0xff00
+#define SIBA_SPROM8_GPIOA 0x1096
+#define SIBA_SPROM8_GPIOA_P0 0x00ff
+#define SIBA_SPROM8_GPIOA_P1 0xff00
+#define SIBA_SPROM8_GPIOB 0x1098
+#define SIBA_SPROM8_GPIOB_P2 0x00ff
+#define SIBA_SPROM8_GPIOB_P3 0xff00
+#define SIBA_SPROM8_MAXP_BG 0x10c0
+#define SIBA_SPROM8_MAXP_BG_MASK 0x00ff
+#define SIBA_SPROM8_TSSI_BG 0xff00
+#define SIBA_SPROM8_MAXP_A 0x10c8
+#define SIBA_SPROM8_MAXP_A_MASK 0x00ff
+#define SIBA_SPROM8_TSSI_A 0xff00
+
+#define SIBA_BOARDVENDOR_DELL 0x1028
+#define SIBA_BOARDVENDOR_BCM 0x14e4
+#define SIBA_BOARD_BCM4309G 0x0421
+#define SIBA_BOARD_MP4318 0x044a
+#define SIBA_BOARD_BU4306 0x0416
+#define SIBA_BOARD_BU4309 0x040a
+
+#define SIBA_PCICORE_BCAST_ADDR SIBA_CC_BCAST_ADDR
+#define SIBA_PCICORE_BCAST_DATA SIBA_CC_BCAST_DATA
+#define SIBA_PCICORE_SBTOPCI0 0x0100
+#define SIBA_PCICORE_SBTOPCI1 0x0104
+#define SIBA_PCICORE_SBTOPCI2 0x0108
+#define SIBA_PCICORE_MDIO_CTL 0x0128
+#define SIBA_PCICORE_MDIO_DATA 0x012c
+#define SIBA_PCICORE_SBTOPCI_PREF 0x00000004
+#define SIBA_PCICORE_SBTOPCI_BURST 0x00000008
+#define SIBA_PCICORE_SBTOPCI_MRM 0x00000020
#endif /* _SIBA_SIBAREG_H_ */
diff --git a/sys/dev/siba/sibavar.h b/sys/dev/siba/sibavar.h
index f9c231b..93d4ff7 100644
--- a/sys/dev/siba/sibavar.h
+++ b/sys/dev/siba/sibavar.h
@@ -31,62 +31,341 @@
#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;
+struct siba_softc;
+struct siba_dev_softc;
- uint8_t sc_ncores;
+enum siba_device_ivars {
+ SIBA_IVAR_VENDOR,
+ SIBA_IVAR_DEVICE,
+ SIBA_IVAR_REVID,
+ SIBA_IVAR_CORE_INDEX
};
-struct siba_devinfo {
- struct resource_list sdi_rl;
- /*devhandle_t sdi_devhandle; XXX*/
- /*struct rman sdi_intr_rman;*/
+#define SIBA_ACCESSOR(var, ivar, type) \
+ __BUS_ACCESSOR(siba, var, SIBA, ivar, type)
- /* 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 */
+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
+
+/* XXX just for SPROM1? */
+enum {
+ SIBA_CCODE_WORLD,
+ SIBA_CCODE_THAILAND,
+ SIBA_CCODE_ISRAEL,
+ SIBA_CCODE_JORDAN,
+ SIBA_CCODE_CHINA,
+ SIBA_CCODE_JAPAN,
+ SIBA_CCODE_USA_CANADA_ANZ,
+ SIBA_CCODE_EUROPE,
+ SIBA_CCODE_USA_LOW,
+ SIBA_CCODE_JAPAN_HIGH,
+ SIBA_CCODE_ALL,
+ SIBA_CCODE_NONE,
};
-#define siba_read_2(sc, core, reg) \
- bus_space_read_2((sc)->sc_bt, (sc)->sc_bh, \
+#define siba_mips_read_2(sc, core, reg) \
+ bus_space_read_2((sc)->siba_mem_bt, (sc)->siba_mem_bh, \
(core * SIBA_CORE_LEN) + (reg))
-#define siba_read_4(sc, core, reg) \
- bus_space_read_4((sc)->sc_bt, (sc)->sc_bh, \
+#define siba_mips_read_4(sc, core, reg) \
+ bus_space_read_4((sc)->siba_mem_bt, (sc)->siba_mem_bh, \
(core * SIBA_CORE_LEN) + (reg))
-#define siba_write_2(sc, core, reg, val) \
- bus_space_write_2((sc)->sc_bt, (sc)->sc_bh, \
+#define siba_mips_write_2(sc, core, reg, val) \
+ bus_space_write_2((sc)->siba_mem_bt, (sc)->siba_mem_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, \
+#define siba_mips_write_4(sc, core, reg, val) \
+ bus_space_write_4((sc)->siba_mem_bt, (sc)->siba_mem_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_READ_4(siba, reg) \
+ bus_space_read_4((siba)->siba_mem_bt, (siba)->siba_mem_bh, (reg))
+#define SIBA_READ_2(siba, reg) \
+ bus_space_read_2((siba)->siba_mem_bt, (siba)->siba_mem_bh, (reg))
+#define SIBA_READ_MULTI_1(siba, reg, addr, count) \
+ bus_space_read_multi_1((siba)->siba_mem_bt, (siba)->siba_mem_bh,\
+ (reg), (addr), (count))
+#define SIBA_READ_MULTI_2(siba, reg, addr, count) \
+ bus_space_read_multi_2((siba)->siba_mem_bt, (siba)->siba_mem_bh,\
+ (reg), (addr), (count))
+#define SIBA_READ_MULTI_4(siba, reg, addr, count) \
+ bus_space_read_multi_4((siba)->siba_mem_bt, (siba)->siba_mem_bh,\
+ (reg), (addr), (count))
+
+#define SIBA_WRITE_4(siba, reg, val) \
+ bus_space_write_4((siba)->siba_mem_bt, (siba)->siba_mem_bh, \
+ (reg), (val))
+#define SIBA_WRITE_2(siba, reg, val) \
+ bus_space_write_2((siba)->siba_mem_bt, (siba)->siba_mem_bh, \
+ (reg), (val))
+#define SIBA_WRITE_MULTI_1(siba, reg, addr, count) \
+ bus_space_write_multi_1((siba)->siba_mem_bt, (siba)->siba_mem_bh,\
+ (reg), (addr), (count))
+#define SIBA_WRITE_MULTI_2(siba, reg, addr, count) \
+ bus_space_write_multi_2((siba)->siba_mem_bt, (siba)->siba_mem_bh,\
+ (reg), (addr), (count))
+#define SIBA_WRITE_MULTI_4(siba, reg, addr, count) \
+ bus_space_write_multi_4((siba)->siba_mem_bt, (siba)->siba_mem_bh,\
+ (reg), (addr), (count))
+
+#define SIBA_BARRIER(siba, flags) \
+ bus_space_barrier((siba)->siba_mem_bt, (siba)->siba_mem_bh, (0),\
+ (0), (flags))
+
+#define SIBA_SETBITS_4(siba, reg, bits) \
+ SIBA_WRITE_4((siba), (reg), SIBA_READ_4((siba), (reg)) | (bits))
+#define SIBA_SETBITS_2(siba, reg, bits) \
+ SIBA_WRITE_2((siba), (reg), SIBA_READ_2((siba), (reg)) | (bits))
+
+#define SIBA_FILT_SETBITS_4(siba, reg, filt, bits) \
+ SIBA_WRITE_4((siba), (reg), (SIBA_READ_4((siba), \
+ (reg)) & (filt)) | (bits))
+#define SIBA_FILT_SETBITS_2(siba, reg, filt, bits) \
+ SIBA_WRITE_2((siba), (reg), (SIBA_READ_2((siba), \
+ (reg)) & (filt)) | (bits))
+
+#define SIBA_CLRBITS_4(siba, reg, bits) \
+ SIBA_WRITE_4((siba), (reg), SIBA_READ_4((siba), (reg)) & ~(bits))
+#define SIBA_CLRBITS_2(siba, reg, bits) \
+ SIBA_WRITE_2((siba), (reg), SIBA_READ_2((siba), (reg)) & ~(bits))
+
+#define SIBA_CC_READ32(scc, offset) \
+ siba_read_4((scc)->scc_dev, offset)
+#define SIBA_CC_WRITE32(scc, offset, val) \
+ siba_write_4((scc)->scc_dev, offset, val)
+#define SIBA_CC_MASK32(scc, offset, mask) \
+ SIBA_CC_WRITE32(scc, offset, SIBA_CC_READ32(scc, offset) & (mask))
+#define SIBA_CC_SET32(scc, offset, set) \
+ SIBA_CC_WRITE32(scc, offset, SIBA_CC_READ32(scc, offset) | (set))
+#define SIBA_CC_MASKSET32(scc, offset, mask, set) \
+ SIBA_CC_WRITE32(scc, offset, \
+ (SIBA_CC_READ32(scc, offset) & (mask)) | (set))
+
+enum siba_type {
+ SIBA_TYPE_SSB,
+ SIBA_TYPE_PCI,
+ SIBA_TYPE_PCMCIA,
};
-#define SIBA_ACCESSOR(var, ivar, type) \
- __BUS_ACCESSOR(siba, var, SIBA, ivar, type)
+enum siba_clock {
+ SIBA_CLOCK_DYNAMIC,
+ SIBA_CLOCK_SLOW,
+ SIBA_CLOCK_FAST,
+};
-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)
+enum siba_clksrc {
+ SIBA_CC_CLKSRC_PCI,
+ SIBA_CC_CLKSRC_CRYSTAL,
+ SIBA_CC_CLKSRC_LOWPW,
+};
-#undef SIBA_ACCESSOR
+struct siba_cc_pmu0_plltab {
+ uint16_t freq; /* in kHz.*/
+ uint8_t xf; /* crystal frequency */
+ uint8_t wb_int;
+ uint32_t wb_frac;
+};
+
+struct siba_cc_pmu1_plltab {
+ uint16_t freq;
+ uint8_t xf;
+ uint8_t p1div;
+ uint8_t p2div;
+ uint8_t ndiv_int;
+ uint32_t ndiv_frac;
+};
+
+struct siba_cc_pmu_res_updown {
+ uint8_t res;
+ uint16_t updown;
+};
+
+#define SIBA_CC_PMU_DEP_SET 1
+#define SIBA_CC_PMU_DEP_ADD 2
+#define SIBA_CC_PMU_DEP_REMOVE 3
+
+struct siba_cc_pmu_res_depend {
+ uint8_t res;
+ uint8_t task;
+ uint32_t depend;
+};
+
+struct siba_sprom {
+ uint8_t rev; /* revision */
+ uint8_t mac_80211bg[6]; /* address for 802.11b/g */
+ uint8_t mac_eth[6]; /* address for Ethernet */
+ uint8_t mac_80211a[6]; /* address for 802.11a */
+ uint8_t mii_eth0; /* MII address for eth0 */
+ uint8_t mii_eth1; /* MII address for eth1 */
+ uint8_t mdio_eth0; /* MDIO for eth0 */
+ uint8_t mdio_eth1; /* MDIO for eth1 */
+ uint8_t brev; /* board revision */
+ uint8_t ccode; /* Country Code */
+ uint8_t ant_a; /* A-PHY antenna */
+ uint8_t ant_bg; /* B/G-PHY antenna */
+ uint16_t pa0b0;
+ uint16_t pa0b1;
+ uint16_t pa0b2;
+ uint16_t pa1b0;
+ uint16_t pa1b1;
+ uint16_t pa1b2;
+ uint8_t gpio0;
+ uint8_t gpio1;
+ uint8_t gpio2;
+ uint8_t gpio3;
+ uint16_t maxpwr_a; /* A-PHY Max Power */
+ uint16_t maxpwr_bg; /* BG-PHY Max Power */
+ uint8_t tssi_a; /* Idle TSSI */
+ uint8_t tssi_bg; /* Idle TSSI */
+ uint16_t bf_lo; /* boardflags */
+ uint16_t bf_hi; /* boardflags */
+ struct {
+ struct {
+ int8_t a0, a1, a2, a3;
+ } ghz24;
+ struct {
+ int8_t a0, a1, a2, a3;
+ } ghz5;
+ } again; /* antenna gain */
+};
+
+struct siba_cc_pmu {
+ uint8_t rev; /* PMU rev */
+ uint32_t freq; /* crystal freq in kHz */
+};
+
+struct siba_cc {
+ struct siba_dev_softc *scc_dev;
+ uint32_t scc_caps;
+ struct siba_cc_pmu scc_pmu;
+ uint16_t scc_powerup_delay;
+};
+
+struct siba_pci {
+ struct siba_dev_softc *spc_dev;
+ uint8_t spc_inited;
+ uint8_t spc_hostmode;
+};
+
+struct siba_bus_ops {
+ uint16_t (*read_2)(struct siba_dev_softc *,
+ uint16_t);
+ uint32_t (*read_4)(struct siba_dev_softc *,
+ uint16_t);
+ void (*write_2)(struct siba_dev_softc *,
+ uint16_t, uint16_t);
+ void (*write_4)(struct siba_dev_softc *,
+ uint16_t, uint32_t);
+ void (*read_multi_1)(struct siba_dev_softc *,
+ void *, size_t, uint16_t);
+ void (*read_multi_2)(struct siba_dev_softc *,
+ void *, size_t, uint16_t);
+ void (*read_multi_4)(struct siba_dev_softc *,
+ void *, size_t, uint16_t);
+ void (*write_multi_1)(struct siba_dev_softc *,
+ const void *, size_t, uint16_t);
+ void (*write_multi_2)(struct siba_dev_softc *,
+ const void *, size_t, uint16_t);
+ void (*write_multi_4)(struct siba_dev_softc *,
+ const void *, size_t, uint16_t);
+};
+
+struct siba_dev_softc {
+ struct siba_softc *sd_bus;
+ struct siba_devid sd_id;
+ const struct siba_bus_ops *sd_ops;
+
+ uint8_t sd_coreidx;
+};
+
+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 */
+};
+
+struct siba_softc {
+ /*
+ * common variables which used for siba(4) bus and siba_bwn bridge.
+ */
+ device_t siba_dev; /* Device ID */
+ struct resource *siba_mem_res;
+ bus_space_tag_t siba_mem_bt;
+ bus_space_handle_t siba_mem_bh;
+ bus_addr_t siba_maddr;
+ bus_size_t siba_msize;
+ uint8_t siba_ncores;
+
+ /*
+ * the following variables are only used for siba_bwn bridge.
+ */
+
+ enum siba_type siba_type;
+ int siba_invalid;
+
+ struct siba_dev_softc *siba_curdev; /* only for PCI */
+ struct siba_dev_softc siba_devs[SIBA_MAX_CORES];
+ int siba_ndevs;
+
+ uint16_t siba_pci_vid;
+ uint16_t siba_pci_did;
+ uint16_t siba_pci_subvid;
+ uint16_t siba_pci_subdid;
+ int siba_mem_rid;
+
+ uint16_t siba_chipid; /* for CORE 0 */
+ uint16_t siba_chiprev;
+ uint8_t siba_chippkg;
+
+ struct siba_cc siba_cc; /* ChipCommon */
+ struct siba_pci siba_pci; /* PCI-core */
+ const struct siba_bus_ops *siba_ops;
+
+ /* board informations */
+ uint16_t siba_board_vendor;
+ uint16_t siba_board_type;
+ uint16_t siba_board_rev;
+ struct siba_sprom siba_sprom; /* SPROM */
+ uint16_t siba_spromsize; /* in word size */
+};
+
+void siba_powerup(struct siba_softc *, int);
+uint16_t siba_read_2(struct siba_dev_softc *, uint16_t);
+void siba_write_2(struct siba_dev_softc *, uint16_t, uint16_t);
+uint32_t siba_read_4(struct siba_dev_softc *, uint16_t);
+void siba_write_4(struct siba_dev_softc *, uint16_t, uint32_t);
+void siba_dev_up(struct siba_dev_softc *, uint32_t);
+void siba_dev_down(struct siba_dev_softc *, uint32_t);
+int siba_powerdown(struct siba_softc *);
+int siba_dev_isup(struct siba_dev_softc *);
+void siba_pcicore_intr(struct siba_pci *, struct siba_dev_softc *);
+uint32_t siba_dma_translation(struct siba_dev_softc *);
+void *siba_dma_alloc_consistent(struct siba_dev_softc *, size_t,
+ bus_addr_t *);
+void siba_read_multi_1(struct siba_dev_softc *, void *, size_t,
+ uint16_t);
+void siba_read_multi_2(struct siba_dev_softc *, void *, size_t,
+ uint16_t);
+void siba_read_multi_4(struct siba_dev_softc *, void *, size_t,
+ uint16_t);
+void siba_write_multi_1(struct siba_dev_softc *, const void *,
+ size_t, uint16_t);
+void siba_write_multi_2(struct siba_dev_softc *, const void *,
+ size_t, uint16_t);
+void siba_write_multi_4(struct siba_dev_softc *, const void *,
+ size_t, uint16_t);
+void siba_barrier(struct siba_dev_softc *, int);
#endif /* _SIBA_SIBAVAR_H_ */
OpenPOWER on IntegriCloud