summaryrefslogtreecommitdiff
path: root/sys/dev/ic/bcw.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/ic/bcw.c')
-rw-r--r--sys/dev/ic/bcw.c124
1 files changed, 77 insertions, 47 deletions
diff --git a/sys/dev/ic/bcw.c b/sys/dev/ic/bcw.c
index 6721a83e872..7fc3cc176da 100644
--- a/sys/dev/ic/bcw.c
+++ b/sys/dev/ic/bcw.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: bcw.c,v 1.8 2006/11/29 21:34:06 mglocker Exp $ */
+/* $OpenBSD: bcw.c,v 1.9 2006/12/06 19:21:45 mglocker Exp $ */
/*
* Copyright (c) 2006 Jon Simola <jsimola@gmail.com>
@@ -56,6 +56,7 @@
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcidevs.h>
+#include <dev/cardbus/cardbusvar.h>
#include <dev/ic/bcwreg.h>
#include <dev/ic/bcwvar.h>
@@ -90,6 +91,7 @@ int bcw_media_change(struct ifnet *);
void bcw_media_status(struct ifnet *, struct ifmediareq *);
/* fashionably new functions */
int bcw_validatechipaccess(struct bcw_softc *);
+void bcw_powercontrol_crystal_off(struct bcw_softc *);
struct cfdriver bcw_cd = {
NULL, "bcw", DV_IFNET
@@ -137,20 +139,9 @@ bcw_attach(struct bcw_softc *sc)
* below for an example of just figuring out what the chip id is and
* how many cores it has.
*/
-
- /*
- * XXX Can we read BCW_ADDR_SPACE0 and see if it returns a likely
- * Core? On the 4318 that only has an 802.11 core, it always reads as
- * some garbage, so if we do a read first we could set a "singlecore"
- * flag instead of thrashing around trying to select non-existant
- * cores. Testing requires cards that do have multiple cores. This
- * would also simplify identifying cards into 3 classes early:
- * - Multiple Cores without a Chip Common Core
- * - Multiple Cores with a Chip Common Core
- * - Single Core
- */
-
- sbval = bus_space_read_4(sc->sc_iot, sc->sc_ioh, BCW_ADDR_SPACE0);
+#if 0
+ sbval = pci_conf_read(sc->sc_pa.pa_pc, sc->sc_pa.pa_tag,
+ BCW_ADDR_SPACE0);
if ((sbval & 0xffff0000) != 0x18000000) {
DPRINTF(("\n%s: Trial Core read was 0x%x, single core only?\n",
sc->sc_dev.dv_xname, sbval));
@@ -158,18 +149,17 @@ bcw_attach(struct bcw_softc *sc)
} else
DPRINTF(("\n%s: Trial Core read was 0x%x\n",
sc->sc_dev.dv_xname, sbval));
-
+#endif
/*
* Try and change to the ChipCommon Core
*/
for (i = 0; i < 10; i++) {
- bus_space_write_4(sc->sc_iot, sc->sc_ioh, BCW_ADDR_SPACE0,
- BCW_CORE_SELECT(0));
+ (sc->sc_conf_write)(sc, BCW_ADDR_SPACE0, BCW_CORE_SELECT(0));
delay(10);
- sbval = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
- BCW_ADDR_SPACE0);
+ sbval = (sc->sc_conf_read)(sc, BCW_ADDR_SPACE0);
if (sbval == BCW_CORE_SELECT(0)) {
- DPRINTF(("%s: Selected ChipCommon Core\n"));
+ DPRINTF(("%s: Selected ChipCommon Core\n",
+ sc->sc_dev.dv_xname));
break;
}
delay(10);
@@ -259,8 +249,8 @@ bcw_attach(struct bcw_softc *sc)
break;
default:
sc->sc_chipid = sc->sc_prodid;
- /* XXX educated guess */
- sc->sc_numcores = 1;
+ /* Set to max */
+ sc->sc_numcores = BCW_MAX_CORES;
} /* end of switch */
} /* End of if/else */
@@ -270,25 +260,27 @@ bcw_attach(struct bcw_softc *sc)
/* Identify each core */
if (sc->sc_numcores >= 2) { /* Exclude single core chips */
- for (i = 0; i <= sc->sc_numcores; i++) {
- DPRINTF(("%s: Trying core %d -\n",
- sc->sc_dev.dv_xname, i));
- bus_space_write_4(sc->sc_iot, sc->sc_ioh,
- BCW_ADDR_SPACE0, BCW_CORE_SELECT(i));
+ for (i = 0; i < sc->sc_numcores; i++) {
+// DPRINTF(("%s: Trying core %d -\n",
+// sc->sc_dev.dv_xname, i));
+ (sc->sc_conf_write)(sc, BCW_ADDR_SPACE0,
+ BCW_CORE_SELECT(i));
/* loop to see if the selected core shows up */
for (j = 0; j < 10; j++) {
- sbval=bus_space_read_4(sc->sc_iot, sc->sc_ioh,
- BCW_ADDR_SPACE0);
- DPRINTF(("%s: read %d for core %d = 0x%x\n",
- sc->sc_dev.dv_xname, j, i, sbval));
+ sbval = (sc->sc_conf_read)(sc, BCW_ADDR_SPACE0);
+// DPRINTF(("%s: read %d for core %d = 0x%x\n",
+// sc->sc_dev.dv_xname, j, i, sbval));
if (sbval == BCW_CORE_SELECT(i)) break;
delay(10);
}
- if (j < 10)
+ if (j < 10) {
+ sbval = bus_space_read_4(sc->sc_iot,
+ sc->sc_ioh, BCW_CIR_SBID_HI);
DPRINTF(("%s: Found core %d of type 0x%x\n",
sc->sc_dev.dv_xname, i,
(sbval & 0x00008ff0) >> 4));
- //sc->sc_core[i].id = (sbval & 0x00008ff0) >> 4;
+ }
+ sc->sc_core[i].id = (sbval & 0x00008ff0) >> 4;
} /* End of For loop */
}
@@ -296,15 +288,22 @@ bcw_attach(struct bcw_softc *sc)
* XXX Attach cores to the backplane, if we have more than one
*/
// ??? if (!sc->sc_singlecore) {
+#if 0
if (sc->sc_havecommon == 1) {
sbval = bus_space_read_4(sc->sc_iot, sc->sc_ioh, BCW_PCICR);
sbval |= 0x1 << 8; /* XXX hardcoded bitmask of single core */
bus_space_write_4(sc->sc_iot, sc->sc_ioh, BCW_PCICR, sbval);
}
-
+#endif
/*
+ * XXX Select the 802.11 core, then
* Get and display the PHY info from the MIMO
*/
+ for (i=0; i < sc->sc_numcores; i++) {
+ if (sc->sc_core[i].id == BCW_CORE_80211)
+ (sc->sc_conf_write)(sc, BCW_ADDR_SPACE0,
+ BCW_CORE_SELECT(i));
+ }
sbval = bus_space_read_2(sc->sc_iot, sc->sc_ioh, 0x3E0);
sc->sc_phy_version = (sbval&0xf000)>>12;
sc->sc_phy_rev = sbval&0xf;
@@ -512,8 +511,9 @@ bcw_attach(struct bcw_softc *sc)
/* Read antenna gain from SPROM and multiply by 4 */
sbval = bus_space_read_2(sc->sc_iot, sc->sc_ioh, BCW_SPROM_ANTGAIN);
/* If unset, assume 2 */
- if((sbval == 0) || (sbval == 0xffff)) sbval = 0x0202;
- if(sc->sc_phy_type == BCW_PHY_TYPEA)
+ if ((sbval == 0) || (sbval == 0xffff))
+ sbval = 0x0202;
+ if (sc->sc_phy_type == BCW_PHY_TYPEA)
sc->sc_radio_gain = (sbval & 0xff);
else
sc->sc_radio_gain = ((sbval & 0xff00) >> 8);
@@ -600,9 +600,9 @@ bcw_attach(struct bcw_softc *sc)
/*
* XXX TODO still for the card attach:
* - Disable the 80211 Core (and wrapper for on/off)
- * - Powercontrol Crystal Off (and write a wrapper for on/off)
* - Setup LEDs to blink in whatever fashionable manner
*/
+ bcw_powercontrol_crystal_off(sc);
/*
* Allocate DMA-safe memory for ring descriptors.
@@ -916,8 +916,7 @@ bcw_intr(void *xsc)
sc = xsc;
for (wantinit = 0; wantinit == 0;) {
- intstatus = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
- BCW_INT_STS);
+ intstatus = (sc->sc_conf_read)(sc, BCW_INT_STS);
/* ignore if not ours, or unsolicited interrupts */
intstatus &= sc->sc_intmask;
@@ -927,8 +926,7 @@ bcw_intr(void *xsc)
handled = 1;
/* Ack interrupt */
- bus_space_write_4(sc->sc_iot, sc->sc_ioh, BCW_INT_STS,
- intstatus);
+ (sc->sc_conf_write)(sc, BCW_INT_STS, intstatus);
/* Receive interrupts. */
if (intstatus & I_RI)
@@ -1375,12 +1373,22 @@ bcw_reset(struct bcw_softc *sc)
u_int32_t val;
u_int32_t reject;
+ /* Really stupid PCI space dump */
+#if 0
+ for (i=0xe00; i<0x1000; i+=4) {
+ if ((i % 16) == 0)
+ DPRINTF(("%s: 0x%04x - ",sc->sc_dev.dv_xname, i));
+ DPRINTF(("0x%08x ",bus_space_read_4(sc->sc_iot, sc->sc_ioh,i)));
+ if ((i % 16) == 12) DPRINTF(("\n"));
+ }
+#endif
/*
* Figure out what revision the Sonic Backplane is, as the position
* of the Reject bit changed. Save the revision in the softc, and
* use the local variable 'reject' in all the bit banging.
*/
sbval = bus_space_read_4(sc->sc_iot, sc->sc_ioh, BCW_CIR_SBID_LO);
+
sc->sc_sbrev = (sbval & SBREV_MASK) >> SBREV_MASK_SHIFT;
switch (sc->sc_sbrev) {
case 0:
@@ -2129,15 +2137,37 @@ bcw_powercontrol_crystal_on(struct bcw_softc *sc)
{
u_int32_t sbval;
- sbval = bus_space_read_4(sc->sc_iot, sc->sc_ioh, BCW_GPIOI);
+ sbval = (sc->sc_conf_read)(sc, BCW_GPIOI);
if ((sbval & BCW_XTALPOWERUP) != BCW_XTALPOWERUP) {
- sbval = bus_space_read_4(sc->sc_iot, sc->sc_ioh, BCW_GPIOO);
+ sbval = (sc->sc_conf_read)(sc, BCW_GPIOO);
sbval |= (BCW_XTALPOWERUP & BCW_PLLPOWERDOWN);
- bus_space_write_4(sc->sc_iot, sc->sc_ioh, BCW_GPIOO, sbval);
+ (sc->sc_conf_write)(sc, BCW_GPIOO, sbval);
delay(1000);
- sbval = bus_space_read_4(sc->sc_iot, sc->sc_ioh, BCW_GPIOO);
+ sbval = (sc->sc_conf_read)(sc, BCW_GPIOO);
sbval &= ~BCW_PLLPOWERDOWN;
- bus_space_write_4(sc->sc_iot, sc->sc_ioh, BCW_GPIOO, sbval);
+ (sc->sc_conf_write)(sc, BCW_GPIOO, sbval);
delay(5000);
}
}
+
+void
+bcw_powercontrol_crystal_off(struct bcw_softc *sc)
+{
+ u_int32_t sbval;
+
+ /* XXX Return if radio is hardware disabled */
+ if (sc->sc_corerev < 5)
+ return;
+ if ((sc->sc_boardflags & BCW_BF_XTAL) == BCW_BF_XTAL)
+ return;
+
+ /* XXX bcw_powercontrol_clock_slow() */
+
+ sbval = (sc->sc_conf_read)(sc, BCW_GPIOO);
+ sbval |= BCW_PLLPOWERDOWN;
+ sbval &= ~BCW_XTALPOWERUP;
+ (sc->sc_conf_write)(sc, BCW_GPIOO, sbval);
+ sbval = (sc->sc_conf_read)(sc, BCW_GPIOE);
+ sbval |= BCW_PLLPOWERDOWN | BCW_XTALPOWERUP;
+ (sc->sc_conf_write)(sc, BCW_GPIOE, sbval);
+}