diff options
-rw-r--r-- | sys/dev/ic/bcw.c | 816 | ||||
-rw-r--r-- | sys/dev/ic/bcwreg.h | 62 | ||||
-rw-r--r-- | sys/dev/ic/bcwvar.h | 10 | ||||
-rw-r--r-- | sys/dev/pci/if_bcw_pci.c | 63 |
4 files changed, 522 insertions, 429 deletions
diff --git a/sys/dev/ic/bcw.c b/sys/dev/ic/bcw.c index 6914ea13563..1a3b64514fe 100644 --- a/sys/dev/ic/bcw.c +++ b/sys/dev/ic/bcw.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bcw.c,v 1.80 2007/03/20 21:14:39 mglocker Exp $ */ +/* $OpenBSD: bcw.c,v 1.81 2007/03/31 09:48:02 mglocker Exp $ */ /* * Copyright (c) 2006 Jon Simola <jsimola@gmail.com> @@ -92,7 +92,6 @@ void bcw_rate_memory_init(struct bcw_softc *); /* * 80211 */ -void bcw_reset(struct bcw_softc *); int bcw_init(struct ifnet *); void bcw_start(struct ifnet *); void bcw_stop(struct ifnet *, int); @@ -102,6 +101,7 @@ void bcw_macfilter_set(struct bcw_softc *, uint16_t, const uint8_t *); void bcw_macfilter_clear(struct bcw_softc *, uint16_t); void bcw_mac_enable(struct bcw_softc *); +void bcw_mac_disable(struct bcw_softc *); uint32_t bcw_intr_enable(struct bcw_softc *, uint32_t); uint32_t bcw_intr_disable(struct bcw_softc *, uint32_t); void bcw_rxintr(struct bcw_softc *); @@ -127,12 +127,14 @@ int bcw_newstate(struct ieee80211com *, int bcw_media_change(struct ifnet *); void bcw_media_status(struct ifnet *, struct ifmediareq *); int bcw_validate_chip_access(struct bcw_softc *); -void bcw_powercontrol_crystal_off(struct bcw_softc *); +void bcw_pc_crystal_on(struct bcw_softc *); +void bcw_pc_crystal_off(struct bcw_softc *); int bcw_change_core(struct bcw_softc *, int); -int bcw_reset_core(struct bcw_softc *, uint32_t); int bcw_core_enable(struct bcw_softc *, uint32_t); int bcw_core_disable(struct bcw_softc *, uint32_t); void bcw_80211_core_reset(struct bcw_softc *, int); +void bcw_80211_core_disable(struct bcw_softc *); +int bcw_iocore_enable(struct bcw_softc *, uint32_t); int bcw_get_firmware(const char *, const uint8_t *, size_t, size_t *, size_t *); int bcw_load_firmware(struct bcw_softc *); @@ -142,6 +144,7 @@ int bcw_load_initvals(struct bcw_softc *); void bcw_leds_switch_all(struct bcw_softc *, int); int bcw_gpio_init(struct bcw_softc *); int bcw_chip_init(struct bcw_softc *); +int bcw_bs_init(struct bcw_softc *); int bcw_80211_core_init(struct bcw_softc *, int); uint8_t bcw_sprom_crc8(uint8_t, uint8_t); uint8_t bcw_sprom_crc(const uint16_t *); @@ -239,9 +242,11 @@ void bcw_ilt_write(struct bcw_softc *, uint16_t, uint16_t); uint16_t bcw_ilt_read(struct bcw_softc *, uint16_t); /* - * Power + * Power Control */ -void bcw_power_saving_ctl_bits(struct bcw_softc *, int, int); +int bcw_pc_init(struct bcw_softc *); +int bcw_pc_set_clock(struct bcw_softc *, uint16_t); +void bcw_pc_saving_ctl_bits(struct bcw_softc *, int, int); /* * XMIT @@ -609,7 +614,6 @@ bcw_shm_read32(struct bcw_softc *sc, uint16_t routing, uint16_t offset) if (routing == BCW_SHM_SHARED) { if (offset & 0x003) { - /* unaligned acccess */ bcw_shm_ctl_word(sc, routing, offset >> 2); r = BCW_READ16(sc, BCW_MMIO_SHM_DATA_UNALIGNED); r <<= 16; @@ -631,7 +635,6 @@ bcw_shm_write32(struct bcw_softc *sc, uint16_t routing, uint16_t offset, { if (routing == BCW_SHM_SHARED) { if (offset & 0x0003) { - /* unaligned access */ bcw_shm_ctl_word(sc, routing, offset >> 2); BCW_WRITE16(sc, BCW_MMIO_SHM_DATA_UNALIGNED, (val >> 16) & 0xffff); @@ -702,7 +705,7 @@ bcw_ram_write(struct bcw_softc *sc, uint16_t offset, uint32_t val) status = BCW_READ(sc, BCW_MMIO_SBF); if (!(status & BCW_SBF_REGISTER_BYTESWAP)) - val = htobe32(val); /* XXX swab32() */ + val = swap32(val); BCW_WRITE(sc, BCW_MMIO_RAM_CONTROL, offset); BCW_WRITE(sc, BCW_MMIO_RAM_DATA, val); @@ -719,6 +722,11 @@ bcw_lv(int number, int min, int max) return (number); } +/* + * Dummy Transmission + * + * http://bcm-specs.sipsolutions.net/DummyTransmission + */ void bcw_dummy_transmission(struct bcw_softc *sc) { @@ -729,7 +737,8 @@ bcw_dummy_transmission(struct bcw_softc *sc) 0x00000400, 0x00000000, 0x00000001, - 0x00000000 }; + 0x00000000 + }; switch (sc->sc_phy_type) { case BCW_PHY_TYPEA: @@ -751,16 +760,16 @@ bcw_dummy_transmission(struct bcw_softc *sc) BCW_READ(sc, BCW_MMIO_SBF); - BCW_WRITE16(sc, 0x0568, 0x0000); - BCW_WRITE16(sc, 0x07c0, 0x0000); - BCW_WRITE16(sc, 0x050c, ((sc->sc_phy_type == BCW_PHY_TYPEA) ? 1 : 0)); + BCW_WRITE16(sc, 0x0568, 0); + BCW_WRITE16(sc, 0x07c0, 0); + BCW_WRITE16(sc, 0x050c, sc->sc_phy_type == BCW_PHY_TYPEA ? 1 : 0); - BCW_WRITE16(sc, 0x0508, 0x0000); - BCW_WRITE16(sc, 0x050a, 0x0000); - BCW_WRITE16(sc, 0x054c, 0x0000); + BCW_WRITE16(sc, 0x0508, 0); + BCW_WRITE16(sc, 0x050a, 0); + BCW_WRITE16(sc, 0x054c, 0); BCW_WRITE16(sc, 0x056a, 0x0014); BCW_WRITE16(sc, 0x0568, 0x0826); - BCW_WRITE16(sc, 0x0500, 0x0000); + BCW_WRITE16(sc, 0x0500, 0); BCW_WRITE16(sc, 0x0502, 0x0030); if (sc->sc_radio_ver == 0x2050 && sc->sc_radio_rev <= 0x5) @@ -909,16 +918,22 @@ bcw_attach(struct bcw_softc *sc) sc->sc_board_vendor, sc->sc_board_type, sc->sc_board_rev)); /* - * Turn crystal on + * Attach chipset to backplane */ - bcw_powercontrol_crystal_on(sc); + bcw_pc_crystal_on(sc); + (sc->sc_conf_write)(sc, PCI_COMMAND_STATUS_REG, + (sc->sc_conf_read)(sc, PCI_COMMAND_STATUS_REG) & + ~PCI_STATUS_TARGET_TARGET_ABORT); /* * Try and change to the ChipCommon Core */ - if (bcw_change_core(sc, 0) == 0) + if (bcw_change_core(sc, 0) == 0) { DPRINTF(("%s: Selected ChipCommon Core\n", sc->sc_dev.dv_xname)); + sc->sc_chip_common_capa = + BCW_READ(sc, BCW_CHIPCOMMON_CAPABILITIES); /* XXX */ + } /* * Core ID REG, this is either the default wireless core (0x812) or @@ -941,10 +956,15 @@ bcw_attach(struct bcw_softc *sc) /* XXX do early init of sc_core[0] here */ + /* powercontrol init is done if a common core exists */ + bcw_pc_init(sc); + + bcw_pc_set_clock(sc, BCW_PCTL_CLK_FAST); + sbval = BCW_READ(sc, BCW_CORE_COMMON_CHIPID); sc->sc_chip_id = (sbval & 0x0000ffff); sc->sc_chip_rev = (sbval & 0x000f0000) >> 16; - sc->sc_chip_package = (sbval & 0x00f00000) >> 20; + sc->sc_chip_pkg = (sbval & 0x00f00000) >> 20; if (core_rev >= 4) sc->sc_numcores = (sbval & 0x0f000000) >> 24; @@ -1022,9 +1042,11 @@ bcw_attach(struct bcw_softc *sc) DPRINTF(("%s: ChipID=0x%x, ChipRev=0x%x, ChipPkg=0x%x, NumCores=%d\n", sc->sc_dev.dv_xname, - sc->sc_chip_id, sc->sc_chip_rev, sc->sc_chip_package, + sc->sc_chip_id, sc->sc_chip_rev, sc->sc_chip_pkg, sc->sc_numcores)); + bcw_iocore_enable(sc, (1 << 1)); + /* Reset and Identify each core */ for (i = 0; i < sc->sc_numcores; i++) { if (bcw_change_core(sc, i) == 0) { @@ -1035,27 +1057,22 @@ bcw_attach(struct bcw_softc *sc) ((sbval & 0x00007000) >> 8 | (sbval & 0x0000000f)); switch (sc->sc_core[i].id) { +#if 0 case BCW_CORE_COMMON: - bcw_reset_core(sc, 0); sc->sc_core_common = &sc->sc_core[i]; break; case BCW_CORE_PCI: -#if 0 - bcw_reset_core(sc,0); (sc->sc_ca == NULL) -#endif sc->sc_core_bus = &sc->sc_core[i]; break; -#if 0 case BCW_CORE_PCMCIA: - bcw_reset_core(sc,0); if (sc->sc_pa == NULL) sc->sc_core_bus = &sc->sc_core[i]; break; #endif case BCW_CORE_80211: - bcw_reset_core(sc, - SBTML_80211FLAG | SBTML_80211PHY); + bcw_80211_core_reset(sc, 1); + bcw_radio_off(sc); sc->sc_core_80211 = &sc->sc_core[i]; break; case BCW_CORE_NONEXIST: @@ -1072,14 +1089,14 @@ bcw_attach(struct bcw_softc *sc) sbval = BCW_READ(sc, BCW_SBTPSFLAG); sc->sc_core[i].backplane_flag = sbval & SBTPS_BACKPLANEFLAGMASK; - sc->sc_core[i].num = i; + sc->sc_core[i].index = i; } else DPRINTF(("%s: Failed change to core %d", sc->sc_dev.dv_xname, i)); - } /* End of For loop */ + } - /* Now that we have cores identified, finish the reset */ - bcw_reset(sc); + /* turn crystal off */ + bcw_pc_crystal_off(sc); /* * XXX Select the 802.11 core, then @@ -1087,7 +1104,7 @@ bcw_attach(struct bcw_softc *sc) * This probably won't work for cards with multiple radio cores, as * the spec suggests that there is one PHY for each core */ - bcw_change_core(sc, sc->sc_core_80211->num); + bcw_change_core(sc, sc->sc_core_80211->index); sbval = BCW_READ16(sc, 0x3E0); sc->sc_phy_ver = (sbval & 0xf000) >> 12; @@ -1229,64 +1246,45 @@ bcw_attach(struct bcw_softc *sc) return; } - bcw_radio_off(sc); - /* * Extract SPROM values and save them where they belong */ bcw_sprom_extract(sc); - /* MAC address */ + /* + * Set MAC address + */ if (!IEEE80211_IS_MULTICAST(sc->sc_sprom.et1macaddr)) memcpy(ic->ic_myaddr, sc->sc_sprom.et1macaddr, ETHER_ADDR_LEN); else memcpy(ic->ic_myaddr, sc->sc_sprom.il0macaddr, ETHER_ADDR_LEN); - printf(", address %s\n", ether_sprintf(ic->ic_myaddr)); - /* Init the Microcode Flags Bitfield */ - /* http://bcm-specs.sipsolutions.net/MicrocodeFlagsBitfield */ + /* + * Init the Microcode Flags Bitfield + * + * http://bcm-specs.sipsolutions.net/MicrocodeFlagsBitfield + */ sbval = 0; - if ((sc->sc_phy_type == BCW_PHY_TYPEA) || - (sc->sc_phy_type == BCW_PHY_TYPEB) || - (sc->sc_phy_type == BCW_PHY_TYPEG)) - sbval |= 2; /* Turned on during init for non N phys */ - if ((sc->sc_phy_type == BCW_PHY_TYPEG) && - (sc->sc_phy_rev == 1)) + if (sc->sc_phy_type == BCW_PHY_TYPEA || + sc->sc_phy_type == BCW_PHY_TYPEB || + sc->sc_phy_type == BCW_PHY_TYPEG) + sbval |= 2; + if (sc->sc_phy_type == BCW_PHY_TYPEG && sc->sc_phy_rev == 1) sbval |= 0x20; - if ((sc->sc_phy_type == BCW_PHY_TYPEG) && - ((sc->sc_sprom.boardflags & BCW_BF_PACTRL) == BCW_BF_PACTRL)) + if (sc->sc_phy_type == BCW_PHY_TYPEG && + sc->sc_sprom.boardflags & BCW_BF_PACTRL) sbval |= 0x40; - if ((sc->sc_phy_type == BCW_PHY_TYPEG) && - (sc->sc_phy_rev < 3)) - sbval |= 0x8; /* MAGIC */ - if ((sc->sc_sprom.boardflags & BCW_BF_XTAL) == BCW_BF_XTAL) + if (sc->sc_phy_type == BCW_PHY_TYPEG && sc->sc_phy_rev < 3) + sbval |= 0x8; + if (sc->sc_sprom.boardflags & BCW_BF_XTAL) sbval |= 0x400; if (sc->sc_phy_type == BCW_PHY_TYPEB) sbval |= 0x4; - if ((sc->sc_radio_ver == 0x2050) && - (sc->sc_radio_rev <= 5)) + if (sc->sc_radio_ver == 0x2050 && sc->sc_radio_rev <= 5) sbval |= 0x40000; - /* - * XXX If the device isn't up and this is a PCI bus with revision - * 10 or less set bit 0x80000 - */ - - /* - * Now, write the value into the regster - * - * The MicrocodeBitFlags is an unaligned 32bit value in SHM, so the - * strategy is to select the aligned word for the lower 16 bits, - * but write to the unaligned address. Then, because the SHM - * pointer is automatically incremented to the next aligned word, - * we can just write the remaining bits as a 16 bit write. - * This explanation could make more sense, but an SHM read/write - * wrapper of some sort would be better. - */ - BCW_WRITE(sc, BCW_MMIO_SHM_CONTROL, - (BCW_SHM_SHARED << 16) + BCW_UCODEFLAGS_OFFSET - 2); - BCW_WRITE16(sc, BCW_MMIO_SHM_DATA_UNALIGNED, sbval & 0x00ff); - BCW_WRITE16(sc, BCW_MMIO_SHM_DATALOW, (sbval & 0xff00) >> 16); + /* XXX device not up and PCI bus with rev =< 10 set 0x80000 */ + bcw_shm_write32(sc, BCW_SHM_SHARED, BCW_UCODEFLAGS_OFFSET, sbval); /* * Initialize the TSSI to DBM table @@ -1296,11 +1294,6 @@ bcw_attach(struct bcw_softc *sc) */ /* - * Turn crystal off - */ - bcw_powercontrol_crystal_off(sc); - - /* * Allocate DMA-safe memory for ring descriptors. * The receive and transmit rings are 4k aligned. */ @@ -1543,7 +1536,31 @@ bcw_mac_enable(struct bcw_softc *sc) BCW_WRITE(sc, BCW_MMIO_GIR, BCW_INTR_READY); BCW_READ(sc, BCW_MMIO_SBF); /* dummy read */ BCW_READ(sc, BCW_MMIO_GIR); /* dummy read */ - bcw_power_saving_ctl_bits(sc, -1, -1); + bcw_pc_saving_ctl_bits(sc, -1, -1); +} + +/* + * Disable MAC on a PHY + * + * http://bcm-specs.sipsolutions.net/SuspendMAC + */ +void +bcw_mac_disable(struct bcw_softc *sc) +{ + int i; + uint32_t tmp; + + bcw_pc_saving_ctl_bits(sc, -1, -1); + BCW_WRITE(sc, BCW_MMIO_SBF, + BCW_READ(sc, BCW_MMIO_SBF) & ~BCW_SBF_MAC_ENABLED); + BCW_READ(sc, BCW_MMIO_GIR); /* dummy read */ + for (i = 10000; i; i--) { + tmp = BCW_READ(sc, BCW_MMIO_GIR); + if (tmp & BCW_INTR_READY) + return; + delay(1); + } + DPRINTF(("%s: MAC disable failed!\n", sc->sc_dev.dv_xname)); } uint32_t @@ -1575,12 +1592,47 @@ bcw_intr_disable(struct bcw_softc *sc, uint32_t mask) int bcw_intr(void *arg) { -#if 0 struct bcw_softc *sc = arg; uint32_t reason; -#endif + uint32_t dma_reason[6]; - return (0); + if (!(sc->sc_flags & BCW_FLAGS_INITIALIZED)) + return (0); + + reason = BCW_READ(sc, BCW_MMIO_GIR); + if (reason == 0xffffffff) + return (0); + + reason &= BCW_READ(sc, BCW_MMIO_GIM); + if (!reason) + return (0); + + dma_reason[0] = BCW_READ(sc, BCW_MMIO_DMA0_REASON) & 0x0001dc00; + dma_reason[1] = BCW_READ(sc, BCW_MMIO_DMA1_REASON) & 0x0000dc00; + dma_reason[2] = BCW_READ(sc, BCW_MMIO_DMA2_REASON) & 0x0000dc00; + dma_reason[3] = BCW_READ(sc, BCW_MMIO_DMA3_REASON) & 0x0001dc00; + dma_reason[4] = BCW_READ(sc, BCW_MMIO_DMA4_REASON) & 0x0000dc00; + dma_reason[5] = BCW_READ(sc, BCW_MMIO_DMA5_REASON) & 0x0000dc00; + + /* ACK interrupt */ + BCW_WRITE(sc, BCW_MMIO_GIR, reason); + BCW_WRITE(sc, BCW_MMIO_GIM, dma_reason[0]); + BCW_WRITE(sc, BCW_MMIO_GIM, dma_reason[1]); + BCW_WRITE(sc, BCW_MMIO_GIM, dma_reason[2]); + BCW_WRITE(sc, BCW_MMIO_GIM, dma_reason[3]); + BCW_WRITE(sc, BCW_MMIO_GIM, dma_reason[4]); + BCW_WRITE(sc, BCW_MMIO_GIM, dma_reason[5]); + + bcw_intr_disable(sc, BCW_INTR_ALL); + + if (reason & BCW_INTR_PS) { + printf("handle PS intr\n"); + bcw_pc_saving_ctl_bits(sc, -1, -1); + } + + bcw_intr_enable(sc, BCW_INTR_INITIAL); + + return (1); } /* @@ -1617,17 +1669,28 @@ bcw_init(struct ifnet *ifp) struct bcw_softc *sc = ifp->if_softc; //struct ieee80211com *ic = &sc->sc_ic; int error; + uint32_t coremask = 0; + + bcw_pc_crystal_on(sc); + + bcw_pc_init(sc); + + bcw_pc_set_clock(sc, BCW_PCTL_CLK_FAST); + + coremask |= (1 << 1); + bcw_iocore_enable(sc, coremask); + + bcw_80211_core_reset(sc, 1); /* initialize 80211 core */ - if ((error = bcw_80211_core_init(sc, 1))) /* XXX */ + if ((error = bcw_80211_core_init(sc, 1))) return (error); -#if 0 - bcw_macfilter_clear(sc, BCW_MACFILTER_ASSOC); - bcw_macfilter_set(sc, BCW_MACFILTER_SELF, ic->ic_myaddr); + bcw_pc_set_clock(sc, BCW_PCTL_CLK_DYNAMIC); + bcw_mac_enable(sc); bcw_intr_enable(sc, BCW_INTR_INITIAL); -#endif + bcw_pc_set_clock(sc, BCW_PCTL_CLK_DYNAMIC); /* start timer */ timeout_add(&sc->sc_timeout, hz); @@ -1636,6 +1699,8 @@ bcw_init(struct ifnet *ifp) ifp->if_flags |= IFF_RUNNING; ifp->if_flags &= ~IFF_OACTIVE; + sc->sc_flags |= BCW_FLAGS_INITIALIZED; + return (0); } @@ -1663,6 +1728,15 @@ bcw_stop(struct ifnet *ifp, int disable) { struct bcw_softc *sc = ifp->if_softc; + /* disable all interrupts */ + bcw_intr_disable(sc, BCW_INTR_ALL); + + /* disable the 80211 core */ + bcw_80211_core_disable(sc); + + /* turn off crystal */ + bcw_pc_crystal_off(sc); + /* Stop the 1 second timer */ timeout_del(&sc->sc_timeout); @@ -1685,53 +1759,6 @@ bcw_stop(struct ifnet *ifp, int disable) bcw_rxdrain(sc); } -/* reset the chip */ -void -bcw_reset(struct bcw_softc *sc) -{ - uint32_t sbval; - uint32_t reject; - - /* - * Figure out what revision the Sonic Backplane is, as the position - * of the Reject bit changes. - */ - sbval = BCW_READ(sc, BCW_CIR_SBID_LO); - sc->sc_sbrev = (sbval & SBREV_MASK) >> SBREV_MASK_SHIFT; - - switch (sc->sc_sbrev) { - case 0: - reject = SBTML_REJ22; - break; - case 1: - reject = SBTML_REJ23; - break; - default: - reject = SBTML_REJ22 | SBTML_REJ23; - } - - sbval = BCW_READ(sc, BCW_SBTMSTATELOW); - - /* - * If the 802.11 core is enabled, only clock of clock,reset,reject - * will be set, and we need to reset all the DMA engines first. - */ - bcw_change_core(sc, sc->sc_core_80211->num); - - sbval = BCW_READ(sc, BCW_SBTMSTATELOW); - - /* Clear Baseband Attenuation, might only work for B/G rev < 0 */ - BCW_WRITE16(sc, BCW_RADIO_BASEBAND, 0); - - /* Set 0x400 in the MMIO StatusBitField reg */ - sbval = BCW_READ(sc, BCW_MMIO_SBF); - sbval |= BCW_SBF_400_MAGIC; - BCW_WRITE(sc, BCW_MMIO_SBF, sbval); - - /* Change back to the Wireless core */ - bcw_change_core(sc, sc->sc_core_80211->num); -} - int bcw_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg) { @@ -1818,7 +1845,7 @@ bcw_validate_chip_access(struct bcw_softc *sc) uint32_t save,val; /* Make sure we're dealing with the wireless core */ - bcw_change_core(sc, sc->sc_core_80211->num); + bcw_change_core(sc, sc->sc_core_80211->index); /* * We use the offset of zero a lot here to reset the SHM pointer to the @@ -2230,12 +2257,12 @@ bcw_free_tx_ring(struct bcw_softc *sc, struct bcw_tx_ring *ring) } void -bcw_powercontrol_crystal_on(struct bcw_softc *sc) +bcw_pc_crystal_on(struct bcw_softc *sc) { uint32_t val; val = (sc->sc_conf_read)(sc->sc_dev_softc, BCW_GPIOI); - if ((val & BCW_PCTL_XTAL_POWERUP) == BCW_PCTL_XTAL_POWERUP) + if (val & BCW_PCTL_XTAL_POWERUP) return; /* crystal is already on */ val = (sc->sc_conf_read)(sc->sc_dev_softc, BCW_GPIOO); @@ -2253,17 +2280,17 @@ bcw_powercontrol_crystal_on(struct bcw_softc *sc) } void -bcw_powercontrol_crystal_off(struct bcw_softc *sc) +bcw_pc_crystal_off(struct bcw_softc *sc) { uint32_t val; /* TODO return if radio is hardware disabled */ if (sc->sc_chip_rev < 5) return; - if ((sc->sc_sprom.boardflags & BCW_BF_XTAL)) + if (sc->sc_sprom.boardflags & BCW_BF_XTAL) return; - /* TODO bcw_powercontrol_clock_slow() */ + bcw_pc_set_clock(sc, BCW_PCTL_CLK_SLOW); val = (sc->sc_conf_read)(sc->sc_dev_softc, BCW_GPIOO); val |= BCW_PCTL_PLL_POWERDOWN; @@ -2278,15 +2305,14 @@ bcw_powercontrol_crystal_off(struct bcw_softc *sc) int bcw_change_core(struct bcw_softc *sc, int changeto) { - uint32_t sbval; int i; + uint32_t sbval; - (sc->sc_conf_write)(sc->sc_dev_softc, BCW_ADDR_SPACE0, - BCW_CORE_SELECT(changeto)); + (sc->sc_conf_write)(sc, BCW_ADDR_SPACE0, BCW_CORE_SELECT(changeto)); /* loop to see if the selected core shows up */ for (i = 0; i < 10; i++) { - sbval = (sc->sc_conf_read)(sc->sc_dev_softc, BCW_ADDR_SPACE0); + sbval = (sc->sc_conf_read)(sc, BCW_ADDR_SPACE0); if (sbval == BCW_CORE_SELECT(changeto)) break; delay(10); @@ -2304,137 +2330,6 @@ bcw_change_core(struct bcw_softc *sc, int changeto) return (0); } -int -bcw_reset_core(struct bcw_softc *sc, uint32_t flags) -{ - uint32_t sbval, reject, val; - int i; - - /* - * Figure out what revision the Sonic Backplane is, as the position - * of the Reject bit changes. - */ - switch (sc->sc_sbrev) { - case 0: - reject = SBTML_REJ22; - break; - case 1: - reject = SBTML_REJ23; - break; - default: - reject = SBTML_REJ22 | SBTML_REJ23; - } - - /* disable core if not in reset */ - if (!(sbval & SBTML_RESET)) { - /* if the core is not enabled, the clock won't be enabled */ - if (!(sbval & SBTML_CLK)) { - BCW_WRITE(sc, BCW_SBTMSTATELOW, - SBTML_RESET | reject | flags); - delay(1); - sbval = BCW_READ(sc, BCW_SBTMSTATELOW); - goto disabled; - - BCW_WRITE(sc, BCW_SBTMSTATELOW, reject); - delay(1); - /* wait until busy is clear */ - for (i = 0; i < 10000; i++) { - val = BCW_READ(sc, BCW_SBTMSTATEHI); - if (!(val & SBTMH_BUSY)) - break; - delay(10); - } - if (i == 10000) - printf("%s: while resetting core, busy did " - "not clear\n", sc->sc_dev.dv_xname); - - val = BCW_READ(sc, BCW_CIR_SBID_LO); - if (val & BCW_CIR_SBID_LO_INITIATOR) { - sbval = BCW_READ(sc, BCW_SBIMSTATE); - BCW_WRITE(sc, BCW_SBIMSTATE, - sbval | SBIM_REJECT); - sbval = BCW_READ(sc, BCW_SBIMSTATE); - delay(1); - - /* wait until busy is clear */ - for (i = 0; i < 10000; i++) { - val = BCW_READ(sc, BCW_SBTMSTATEHI); - if (!(val & SBTMH_BUSY)) - break; - delay(10); - } - if (i == 10000) - printf("%s: while resetting core, busy " - "did not clear\n", - sc->sc_dev.dv_xname); - } /* end initiator check */ - - /* set reset and reject while enabling the clocks */ - /* XXX why isn't reject in here? */ - BCW_WRITE(sc, BCW_SBTMSTATELOW, - SBTML_FGC | SBTML_CLK | SBTML_RESET | flags); - val = BCW_READ(sc, BCW_SBTMSTATELOW); - delay(10); - - val = BCW_READ(sc, BCW_CIR_SBID_LO); - if (val & BCW_CIR_SBID_LO_INITIATOR) { - sbval = BCW_READ(sc, BCW_SBIMSTATE); - BCW_WRITE(sc, BCW_SBIMSTATE, - sbval & ~SBIM_REJECT); - sbval = BCW_READ(sc, BCW_SBIMSTATE); - delay(1); - - /* wait until busy is clear */ - for (i = 0; i < 10000; i++) { - val = BCW_READ(sc, BCW_SBTMSTATEHI); - if (!(val & SBTMH_BUSY)) - break; - delay(10); - } - if (i == 10000) - printf("%s: while resetting core, busy " - "did not clear\n", - sc->sc_dev.dv_xname); - } /* end initiator check */ - - BCW_WRITE(sc, BCW_SBTMSTATELOW, - SBTML_RESET | reject | flags); - delay(1); - } - } - -disabled: - - /* This is enabling/resetting the core */ - /* enable clock */ - BCW_WRITE(sc, BCW_SBTMSTATELOW, - SBTML_FGC | SBTML_CLK | SBTML_RESET | flags); - val = BCW_READ(sc, BCW_SBTMSTATELOW); - delay(1); - - /* clear any error bits that may be on */ - val = BCW_READ(sc, BCW_SBTMSTATEHI); - if (val & SBTMH_SERR) - BCW_WRITE(sc, BCW_SBTMSTATEHI, 0); - val = BCW_READ(sc, BCW_SBIMSTATE); - if (val & (SBIM_INBANDERR | SBIM_TIMEOUT)) - BCW_WRITE(sc, BCW_SBIMSTATE, - val & ~(SBIM_INBANDERR | SBIM_TIMEOUT)); - - /* clear reset and allow it to propagate throughout the core */ - BCW_WRITE(sc, BCW_SBTMSTATELOW, - SBTML_FGC | SBTML_CLK | flags); - val = BCW_READ(sc, BCW_SBTMSTATELOW); - delay(1); - - /* leave clock enabled */ - BCW_WRITE(sc, BCW_SBTMSTATELOW, SBTML_CLK | flags); - val = BCW_READ(sc, BCW_SBTMSTATELOW); - delay(1); - - return 0; -} - /* * Enable current core */ @@ -2569,22 +2464,77 @@ void bcw_80211_core_reset(struct bcw_softc *sc, int connect_phy) { uint32_t flags = 0x00040000; -#if 0 - if (1) { /* XXX */ - BCW_WRITE(sc, BCW_MMIO_SBF, BCW_READ(sc, BCW_MMIO_SBF) & - ~(BCW_SBF_MAC_ENABLED | 0x00000002)); + + if (connect_phy) + flags |= 0x20000000; + bcw_phy_connect(sc, connect_phy); + bcw_core_enable(sc, flags); + BCW_WRITE16(sc, 0x03e6, 0); + BCW_WRITE(sc, BCW_MMIO_SBF, BCW_READ(sc, BCW_MMIO_SBF) | + BCW_SBF_400_MAGIC); +} + +/* + * Disable the 80211 core + * + * http://bcm-specs.sipsolutions.net/80211CoreDisable + */ +void +bcw_80211_core_disable(struct bcw_softc *sc) +{ + bcw_radio_off(sc); + BCW_WRITE16(sc, 0x03e6, 0x00f4); + bcw_core_disable(sc, 0); +} + +int +bcw_iocore_enable(struct bcw_softc *sc, uint32_t coremask) +{ + uint32_t val; + uint32_t bp_flag_nr; + int error; + + val = BCW_READ(sc, BCW_CIR_SBTPSFLAG); + bp_flag_nr = val & SBTPS_BACKPLANEFLAGMASK; + + if ((error = bcw_change_core(sc, 2))) + return (error); + + if (sc->sc_core[sc->sc_currentcore].rev < 6 && + sc->sc_core[sc->sc_currentcore].id == BCW_CORE_PCI) { + val = BCW_READ(sc, BCW_CIR_SBINTVEC); + val |= (1 << bp_flag_nr); + BCW_WRITE(sc, BCW_CIR_SBINTVEC, val); } else { -#endif - if (connect_phy) - flags |= 0x20000000; - bcw_phy_connect(sc, connect_phy); - bcw_core_enable(sc, flags); - BCW_WRITE16(sc, 0x03e6, 0); - BCW_WRITE(sc, BCW_MMIO_SBF, BCW_READ(sc, BCW_MMIO_SBF) | - BCW_SBF_400_MAGIC); -#if 0 + val = (sc->sc_conf_read)(sc, BCW_PCICFG_ICR); + val |= coremask << 8; + (sc->sc_conf_write)(sc, BCW_PCICFG_ICR, val); } -#endif + + if (sc->sc_core[sc->sc_currentcore].id == BCW_CORE_PCI) { + val = BCW_READ(sc, BCW_PCICORE_SBTOPCI2); + val |= BCW_SBTOPCI2_PREFETCH | BCW_SBTOPCI2_BURST; + BCW_WRITE(sc, BCW_PCICORE_SBTOPCI2, val); + + if (sc->sc_core[sc->sc_currentcore].rev < 5) { + val = BCW_READ(sc, BCW_CIR_SBIMCONFIGLOW); + val |= (2 << BCW_SBIMCONFIGLOW_STS) & + BCW_SBIMCONFIGLOW_STM; + val |= (3 << BCW_SBIMCONFIGLOW_STS) & + BCW_SBIMCONFIGLOW_STM; + BCW_WRITE(sc, BCW_CIR_SBIMCONFIGLOW, val); + /* TODO commit PCI settings */ + } else if (sc->sc_core[sc->sc_currentcore].rev >= 11) { + val = BCW_READ(sc, BCW_PCICORE_SBTOPCI2); + val |= BCW_SBTOPCI2_MEMREAD_MULTI; + BCW_WRITE(sc, BCW_PCICORE_SBTOPCI2, val); + } + } + + if ((error = bcw_change_core(sc, sc->sc_lastcore))) + return (error); + + return (0); } int @@ -2928,10 +2878,11 @@ bcw_gpio_init(struct bcw_softc *sc) int bcw_chip_init(struct bcw_softc *sc) { - struct ifnet *ifp = &sc->sc_ic.ic_if; + struct ieee80211com *ic = &sc->sc_ic; + uint8_t limit; uint16_t val16; uint32_t val32; - int error, i, tmp; + int error, i; BCW_WRITE(sc, BCW_MMIO_SBF, BCW_SBF_CORE_READY | BCW_SBF_400_MAGIC); @@ -2988,25 +2939,18 @@ bcw_chip_init(struct bcw_softc *sc) if ((error = bcw_load_initvals(sc))) return (error); - /* turn radio on */ - bcw_radio_on(sc); - - BCW_WRITE16(sc, 0x03e6, 0); - if ((error = bcw_phy_init(sc))) - return (error); + if (sc->sc_core[sc->sc_currentcore].rev > 9) { + BCW_WRITE(sc, 0x540, 0x540); + BCW_WRITE(sc, 0x520, 0x520); + BCW_WRITE(sc, 0x540, 0x540); + BCW_WRITE(sc, 0x418, 0xe0a); + BCW_WRITE(sc, 0x41a, 0x90b); + BCW_WRITE(sc, 0x41c, 0x20e); + BCW_WRITE(sc, 0x41e, 0); + } - /* select initial interference mitigation */ - tmp = sc->sc_radio_interfmode; - sc->sc_radio_interfmode = BCW_RADIO_INTERFMODE_NONE; - bcw_radio_set_interf_mitigation(sc, tmp); + BCW_WRITE(sc, 0x5c, 0xa); - bcw_phy_set_antenna_diversity(sc); - bcw_radio_set_txantenna(sc, BCW_RADIO_TXANTENNA_DEFAULT); - if (sc->sc_phy_type == BCW_PHY_TYPEB) { - val16 = BCW_READ16(sc, 0x005e); - val16 |= 0x0004; - BCW_WRITE16(sc, 0x005e, val16); - } BCW_WRITE(sc, 0x0100, 0x01000000); if (sc->sc_core[sc->sc_currentcore].rev < 5) BCW_WRITE(sc, 0x010c, 0x01000000); @@ -3033,8 +2977,7 @@ bcw_chip_init(struct bcw_softc *sc) /* probe response timeout value */ bcw_shm_write16(sc, BCW_SHM_SHARED, 0x0074, 0); - /* initially set the wireless operation mode */ - bcw_set_opmode(ifp); + BCW_WRITE(sc, 0x400, 0x8); if (sc->sc_core[sc->sc_currentcore].rev < 3) { BCW_WRITE16(sc, 0x060e, 0); @@ -3056,7 +2999,20 @@ bcw_chip_init(struct bcw_softc *sc) val32 = BCW_READ(sc, BCW_CIR_SBTMSTATELOW); val32 |= 0x00100000; BCW_WRITE(sc, BCW_CIR_SBTMSTATELOW, val32); - /* TODO bcw_pctl_powerup_delay(sc) */ + + val16 = sc->sc_core[sc->sc_currentcore].rev; + bcw_shm_write16(sc, BCW_SHM_SHARED, 0x16, val16); + + /* short/long retry limit */ + limit = bcw_lv(BCW_DEFAULT_SHORT_RETRY_LIMIT, 0, 0xf); + bcw_shm_write32(sc, BCW_SHM_80211, 0x0006, limit); + limit = bcw_lv(BCW_DEFAULT_LONG_RETRY_LIMIT, 0, 0xf); + bcw_shm_write32(sc, BCW_SHM_80211, 0x0007, limit); + + bcw_shm_write16(sc, BCW_SHM_SHARED, 0x0044, 3); + bcw_shm_write16(sc, BCW_SHM_SHARED, 0x0046, 2); + + bcw_macfilter_set(sc, BCW_MACFILTER_SELF, ic->ic_myaddr); DPRINTF(("%s: Chip initialized\n", sc->sc_dev.dv_xname)); @@ -3064,6 +3020,57 @@ bcw_chip_init(struct bcw_softc *sc) } /* + * Initialize the BS + * + * http://bcm-specs.sipsolutions.net/BSInit + */ +int +bcw_bs_init(struct bcw_softc *sc) +{ + uint32_t ucodeflags; + + BCW_WRITE16(sc, 0x03e6, 0); + + bcw_radio_on(sc); + + bcw_phy_init(sc); + + /* minimum contention window */ + if (sc->sc_phy_type == BCW_PHY_TYPEB) + bcw_shm_write32(sc, BCW_SHM_80211, 0x0003, 0x0000001f); + else + bcw_shm_write32(sc, BCW_SHM_80211, 0x0003, 0x0000000f); + + /* maximum contention window */ + bcw_shm_write32(sc, BCW_SHM_80211, 0x0004, 0x000003ff); + + bcw_rate_memory_init(sc); + + bcw_shm_write16(sc, BCW_SHM_SHARED, 0x52, sc->sc_phy_type); + bcw_shm_write16(sc, BCW_SHM_SHARED, 0x50, sc->sc_phy_rev); + + ucodeflags = bcw_shm_read32(sc, BCW_SHM_SHARED, BCW_UCODEFLAGS_OFFSET); + ucodeflags |= 0x100000; + bcw_shm_write32(sc, BCW_SHM_SHARED, BCW_UCODEFLAGS_OFFSET, ucodeflags); + + if (sc->sc_phy_type == BCW_PHY_TYPEA && + sc->sc_core[sc->sc_currentcore].rev <= 4) + bcw_shm_write16(sc, BCW_SHM_SHARED, 0x3c, 0x1d); + else + bcw_shm_write16(sc, BCW_SHM_SHARED, 0x3c, 0x1e); + + if (sc->sc_phy_type == BCW_PHY_TYPEA) { + bcw_shm_write16(sc, BCW_SHM_SHARED, 0x612, 0x2); + bcw_shm_write16(sc, BCW_SHM_SHARED, 0x416, 0x2); + + bcw_shm_write16(sc, BCW_SHM_SHARED, 0x612, 0x78); + bcw_shm_write16(sc, BCW_SHM_SHARED, 0x416, 0x78); + } + + return (0); +} + +/* * Initialize the 80211 core * * http://bcm-specs.sipsolutions.net/80211Init @@ -3071,76 +3078,48 @@ bcw_chip_init(struct bcw_softc *sc) int bcw_80211_core_init(struct bcw_softc *sc, int active_80211_core) { - uint8_t limit; uint32_t ucodeflags; - uint32_t sbimconfiglow; + //uint32_t sbimconfiglow; int error; - +#if 0 if (sc->sc_core_bus->rev <= 5 && sc->sc_core_bus->id != BCW_CORE_PCIE) { sbimconfiglow = BCW_READ(sc, BCW_CIR_SBIMCONFIGLOW); sbimconfiglow &= ~BCW_SBIMCONFIGLOW_RTM; sbimconfiglow &= ~BCW_SBIMCONFIGLOW_STM; - if (1) /* XXX find out the bus type (PCI, CARDBUS, PCMCIA */ - sbimconfiglow |= 0x32; - else - sbimconfiglow |= 0x53; + sbimconfiglow |= 0x32; BCW_WRITE(sc, BCW_CIR_SBIMCONFIGLOW, sbimconfiglow); } +#endif bcw_phy_calibrate(sc); + if ((error = bcw_chip_init(sc))) return (error); - bcw_shm_write16(sc, BCW_SHM_SHARED, 0x0016, - sc->sc_core[sc->sc_currentcore].rev); - - ucodeflags = bcw_shm_read32(sc, BCW_SHM_SHARED, BCW_UCODEFLAGS_OFFSET); - - if (0) /* XXX */ - ucodeflags |= 0x00000010; + if ((error = bcw_bs_init(sc))) + return (error); - /* HW decryption needs to be set now */ - ucodeflags |= 0x40000000; + bcw_shm_write16(sc, BCW_SHM_SHARED, 0x0016, 0); - if (sc->sc_phy_type == BCW_PHY_TYPEG) { - ucodeflags |= BCW_UCODEFLAG_UNKBGPHY; - if (sc->sc_phy_rev == 1) - ucodeflags |= BCW_UCODEFLAG_UNKGPHY; - if (sc->sc_sprom.boardflags & BCW_BF_PACTRL) - ucodeflags |= BCW_UCODEFLAG_UNKPACTRL; - } else if (sc->sc_phy_type == BCW_PHY_TYPEB) { + /* + * Set microcode flags if necessery + */ + ucodeflags = bcw_shm_read32(sc, BCW_SHM_SHARED, BCW_UCODEFLAGS_OFFSET); + //ucodeflags |= 0x00000010; /* XXX */ + if (sc->sc_phy_type == BCW_PHY_TYPEB || + sc->sc_phy_type == BCW_PHY_TYPEG) ucodeflags |= BCW_UCODEFLAG_UNKBGPHY; - if (sc->sc_phy_rev >= 2 && sc->sc_radio_ver == 0x2050) - ucodeflags &= ~BCW_UCODEFLAG_UNKGPHY; - } - - if (ucodeflags != bcw_shm_read32(sc, BCW_SHM_SHARED, - BCW_UCODEFLAGS_OFFSET)) { + if (sc->sc_phy_type == BCW_PHY_TYPEG && sc->sc_phy_rev == 1) + ucodeflags |= BCW_UCODEFLAG_UNKGPHY; + if (sc->sc_phy_type == BCW_PHY_TYPEB && sc->sc_phy_rev >= 2 && + sc->sc_radio_ver == 0x2050) + ucodeflags &= ~BCW_UCODEFLAG_UNKGPHY; + if (sc->sc_sprom.boardflags & BCW_BF_PACTRL) + ucodeflags |= BCW_UCODEFLAG_UNKPACTRL; + if (ucodeflags != + bcw_shm_read32(sc, BCW_SHM_SHARED, BCW_UCODEFLAGS_OFFSET)) bcw_shm_write32(sc, BCW_SHM_SHARED, BCW_UCODEFLAGS_OFFSET, ucodeflags); - } - - /* short/long retry limit */ - limit = bcw_lv(BCW_DEFAULT_SHORT_RETRY_LIMIT, 0, 0xf); - bcw_shm_write32(sc, BCW_SHM_80211, 0x0006, limit); - limit = bcw_lv(BCW_DEFAULT_LONG_RETRY_LIMIT, 0, 0xf); - bcw_shm_write32(sc, BCW_SHM_80211, 0x0007, limit); - - bcw_shm_write16(sc, BCW_SHM_SHARED, 0x0044, 3); - bcw_shm_write16(sc, BCW_SHM_SHARED, 0x0046, 2); - - bcw_rate_memory_init(sc); - - /* minimum contention window */ - if (sc->sc_phy_type == BCW_PHY_TYPEB) - bcw_shm_write32(sc, BCW_SHM_80211, 0x0003, 0x0000001f); - else - bcw_shm_write32(sc, BCW_SHM_80211, 0x0003, 0x0000000f); - - /* maximum contention window */ - bcw_shm_write32(sc, BCW_SHM_80211, 0x0004, 0x000003ff); - - /* TODO bcw_gen_bssid(), bcw_write_mac_bssid_templates() */ if (sc->sc_core[sc->sc_currentcore].rev >= 5) BCW_WRITE16(sc, 0x043c, 0x000c); @@ -3152,16 +3131,14 @@ bcw_80211_core_init(struct bcw_softc *sc, int active_80211_core) /* TODO bcw_dma_init() */ } } + BCW_WRITE16(sc, 0x0612, 0x0050); bcw_shm_write16(sc, BCW_SHM_SHARED, 0x0416, 0x0050); bcw_shm_write16(sc, BCW_SHM_SHARED, 0x0414, 0x01f4); - - if (active_80211_core) { - if (1) /* XXX initial channel */ - bcw_radio_select_channel(sc, 0, 0); - } - - /* TODO sc->sc_current_core_initialized = 1; */ +#if 0 + bcw_mac_enable(sc); + bcw_intr_enable(sc, 0xb007a864); +#endif return (0); } @@ -3495,7 +3472,7 @@ bcw_phy_initg(struct bcw_softc *sc) if (sc->sc_radio_rev == 8) bcw_phy_write16(sc, 0x0805, 0x3230); bcw_phy_init_pctl(sc); - if (sc->sc_chip_id == 0x4306 && sc->sc_chip_rev == 2) { + if (sc->sc_chip_id == 0x4306 && sc->sc_chip_pkg == 2) { bcw_phy_write16(sc, 0x0429, bcw_phy_read16(sc, 0x0429) & 0xbfff); bcw_phy_write16(sc, 0x04c3, bcw_phy_read16(sc, 0x04c3) & @@ -5365,7 +5342,7 @@ bcw_phy_connect(struct bcw_softc *sc, int connect) if (!(flags & 0x00010000)) return (ENODEV); flags = BCW_READ(sc, BCW_CIR_SBTMSTATELOW); - flags |= (0x8000 << 18); + flags |= (0x800 << 18); BCW_WRITE(sc, BCW_CIR_SBTMSTATELOW, flags); } else { if (!(flags & 0x00020000)) @@ -6836,14 +6813,98 @@ bcw_ilt_read(struct bcw_softc *sc, uint16_t offset) } /* - * Power + * Power Control */ +int +bcw_pc_init(struct bcw_softc *sc) +{ + //int maxfreq; + int error; + + if ((error = bcw_change_core(sc, 0))) + return (error); + + if (sc->sc_chip_id == 0x4321) { + if (sc->sc_chip_rev == 1) + BCW_WRITE(sc, BCW_CHIPCOMMON_CTL, 0x00a4); + if (sc->sc_chip_rev == 0) + BCW_WRITE(sc, BCW_CHIPCOMMON_CTL, 0x03a4); + } + + if (!(sc->sc_chip_common_capa & BCW_CAPABILITIES_PCTL)) + return (ENODEV); /* no power control */ + + if (sc->sc_core[sc->sc_currentcore].rev >= 10) { + BCW_WRITE(sc, BCW_CHIPCOMMON_SYSCLKCTL, + (BCW_READ(sc, BCW_CHIPCOMMON_SYSCLKCTL) & 0x0000ffff) | + 0x40000); + } else { + /* TODO get maxfreq */ +#if 0 + BCW_WRITE(sc, BCW_CHIPCOMMON_PLLONDELAY, + (maxfreq * 150 + 99999) / 1000000); + BCW_WRITE(sc, BCW_CHIPCOMMON_FREFSELDELAY, + (maxfreq * 15 + 99999) / 100000); +#endif + } + + if ((error = bcw_change_core(sc, sc->sc_lastcore))) + return (error); + + return (0); +} + +int +bcw_pc_set_clock(struct bcw_softc *sc, uint16_t mode) +{ + int error; + uint32_t tmp; + + if ((error = bcw_change_core(sc, 0))) + return (error); + + if (sc->sc_core[sc->sc_currentcore].rev < 6) { + if (mode == BCW_PCTL_CLK_FAST) + bcw_pc_crystal_on(sc); + } else if (sc->sc_chip_common_capa & BCW_CAPABILITIES_PCTL && + sc->sc_core[sc->sc_currentcore].rev < 10) { + switch (mode) { + case BCW_PCTL_CLK_FAST: + tmp = BCW_READ(sc, BCW_CHIPCOMMON_SLOWCLKCTL); + tmp = (tmp & ~BCW_PCTL_FORCE_SLOW) | + BCW_PCTL_FORCE_PLL; + BCW_WRITE(sc, BCW_CHIPCOMMON_SLOWCLKCTL, tmp); + break; + case BCW_PCTL_CLK_SLOW: + tmp = BCW_READ(sc, BCW_CHIPCOMMON_SLOWCLKCTL); + tmp |= BCW_PCTL_FORCE_SLOW; + BCW_WRITE(sc, BCW_CHIPCOMMON_SLOWCLKCTL, tmp); + break; + case BCW_PCTL_CLK_DYNAMIC: + tmp = BCW_READ(sc, BCW_CHIPCOMMON_SLOWCLKCTL); + tmp &= ~BCW_PCTL_FORCE_SLOW; + tmp |= BCW_PCTL_FORCE_PLL; + tmp &= ~BCW_PCTL_DYN_XTAL; + BCW_WRITE(sc, BCW_CHIPCOMMON_SLOWCLKCTL, tmp); + break; + } + } + + if ((error = bcw_change_core(sc, sc->sc_lastcore))) + return (error); + + return (0); +} + void -bcw_power_saving_ctl_bits(struct bcw_softc *sc, int bit25, int bit26) +bcw_pc_saving_ctl_bits(struct bcw_softc *sc, int bit25, int bit26) { int i; uint32_t status; + bit25 = 0; + bit26 = 1; + if (bit25 == -1) { /* TODO */ } @@ -6863,8 +6924,7 @@ bcw_power_saving_ctl_bits(struct bcw_softc *sc, int bit25, int bit26) BCW_WRITE(sc, BCW_MMIO_SBF, status); if (bit26 && sc->sc_core[sc->sc_currentcore].rev >= 5) { for (i = 0; i < 100; i++) { - if (bcw_shm_read32(sc, BCW_SHM_SHARED, 0x0040) - != 4) + if (bcw_shm_read32(sc, BCW_SHM_SHARED, 0x0040) != 4) break; delay(10); } diff --git a/sys/dev/ic/bcwreg.h b/sys/dev/ic/bcwreg.h index e4e097b133a..c5d0e75ea0a 100644 --- a/sys/dev/ic/bcwreg.h +++ b/sys/dev/ic/bcwreg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: bcwreg.h,v 1.24 2007/03/20 21:14:39 mglocker Exp $ */ +/* $OpenBSD: bcwreg.h,v 1.25 2007/03/31 09:48:02 mglocker Exp $ */ /* * Copyright (c) 2006 Jon Simola <jsimola@gmail.com> @@ -29,13 +29,24 @@ #define BCW_SPROM_CONTROL 0x88 /* + * PCI Interrupt Configuration Register + */ +#define BCW_PCICFG_ICR 0x94 + +/* * MMIO offsets */ +#define BCW_MMIO_DMA0_REASON 0x20 #define BCW_MMIO_DMA0_INT_MASK 0x24 +#define BCW_MMIO_DMA1_REASON 0x28 #define BCW_MMIO_DMA1_INT_MASK 0x2c +#define BCW_MMIO_DMA2_REASON 0x30 #define BCW_MMIO_DMA2_INT_MASK 0x34 +#define BCW_MMIO_DMA3_REASON 0x38 #define BCW_MMIO_DMA3_INT_MASK 0x3c +#define BCW_MMIO_DMA4_REASON 0x40 #define BCW_MMIO_DMA4_INT_MASK 0x44 +#define BCW_MMIO_DMA5_REASON 0x48 #define BCW_MMIO_DMA5_INT_MASK 0x4c #define BCW_MMIO_SBF 0x120 /* Status Bit Field */ #define BCW_MMIO_GIR 0x128 /* Generic Interrupt Reason */ @@ -125,6 +136,45 @@ #define BCW_MACFILTER_ASSOC 0x0003 /* + * Chip Common registers + */ +#define BCW_CHIPCOMMON_CAPABILITIES 0x04 +#define BCW_CHIPCOMMON_CTL 0x28 +#define BCW_CHIPCOMMON_PLLONDELAY 0xB0 +#define BCW_CHIPCOMMON_FREFSELDELAY 0xB4 +#define BCW_CHIPCOMMON_SLOWCLKCTL 0xB8 +#define BCW_CHIPCOMMON_SYSCLKCTL 0xC0 + +/* + * PCI core registers + */ +#define BCW_PCICORE_BCAST_ADDR 0x50 +#define BCW_PCICORE_BCAST_DATA 0x54 +#define BCW_PCICORE_SBTOPCI2 0x108 + +/* + * SBTOPCI2 values + */ +#define BCW_SBTOPCI2_PREFETCH 0x4 +#define BCW_SBTOPCI2_BURST 0x8 +#define BCW_SBTOPCI2_MEMREAD_MULTI 0x20 + +/* + * Chip Common capabilities + */ +#define BCW_CAPABILITIES_PCTL 0x00040000 +#define BCW_CAPABILITIES_PLLMASK 0x00030000 +#define BCW_CAPABILITIES_PLLSHIFT 16 +#define BCW_CAPABILITIES_FLASHMASK 0x00000700 +#define BCW_CAPABILITIES_FLASHSHIFT 8 +#define BCW_CAPABILITIES_EXTBUSPRESENT 0x00000040 +#define BCW_CAPABILITIES_UARTGPIO 0x00000020 +#define BCW_CAPABILITIES_UARTCLOCKMASK 0x00000018 +#define BCW_CAPABILITIES_UARTCLOCKSHIFT 3 +#define BCW_CAPABILITIES_MIPSBIGENDIAN 0x00000004 +#define BCW_CAPABILITIES_NRUARTSMASK 0x00000003 + +/* * Power control */ #define BCW_PCTL_IN 0xb0 @@ -134,6 +184,16 @@ #define BCW_PCTL_PLL_POWERDOWN 0x80 /* + * Power control clock modes + */ +#define BCW_PCTL_CLK_FAST 0x00 +#define BCW_PCTL_CLK_SLOW 0x01 +#define BCW_PCTL_CLK_DYNAMIC 0x02 +#define BCW_PCTL_FORCE_SLOW 0x0800 +#define BCW_PCTL_FORCE_PLL 0x1000 +#define BCW_PCTL_DYN_XTAL 0x2000 + +/* * Core IDs */ #define BCW_CORE_COMMON_CHIPID 0x0 diff --git a/sys/dev/ic/bcwvar.h b/sys/dev/ic/bcwvar.h index cad7b218a53..bf2f6a8910a 100644 --- a/sys/dev/ic/bcwvar.h +++ b/sys/dev/ic/bcwvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: bcwvar.h,v 1.31 2007/03/20 11:55:36 mglocker Exp $ */ +/* $OpenBSD: bcwvar.h,v 1.32 2007/03/31 09:48:02 mglocker Exp $ */ /* * Copyright (c) 2006 Jon Simola <jsimola@gmail.com> @@ -25,6 +25,8 @@ #define BCW_ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0])) +#define BCW_FLAGS_INITIALIZED 0x00000001 + #define BCW_DEFAULT_SHORT_RETRY_LIMIT 7 #define BCW_DEFAULT_LONG_RETRY_LIMIT 4 @@ -95,7 +97,7 @@ struct bcw_radio { #define BCW_MAX_CORES 10 struct bcw_core { uint16_t id; - uint8_t num; + uint8_t index; uint8_t rev; uint8_t backplane_flag; }; @@ -254,6 +256,7 @@ struct bcw_softc { bus_space_tag_t sc_iot; bus_space_handle_t sc_ioh; + uint32_t sc_flags; void *bcw_intrhand; const char *bcw_intrstr; /* interrupt description */ void *sc_dev_softc; @@ -274,7 +277,7 @@ struct bcw_softc { uint16_t sc_board_rev; uint16_t sc_chip_id; /* Chip ID */ uint16_t sc_chip_rev; /* Chip Revision */ - uint16_t sc_chip_package; /* Chip Package */ + uint16_t sc_chip_pkg; /* Chip Package */ uint16_t sc_prodid; /* Product ID */ struct bcw_core sc_core[BCW_MAX_CORES]; // struct bcw_radio radio[BCW_RADIO_MAX]; @@ -311,6 +314,7 @@ struct bcw_softc { uint32_t sc_phyinfo; uint16_t sc_numcores; uint16_t sc_havecommon; + uint32_t sc_chip_common_capa; int sc_currentcore; int sc_lastcore; uint16_t sc_radio_pa0b0; diff --git a/sys/dev/pci/if_bcw_pci.c b/sys/dev/pci/if_bcw_pci.c index 39a51eb2a99..694b210a843 100644 --- a/sys/dev/pci/if_bcw_pci.c +++ b/sys/dev/pci/if_bcw_pci.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_bcw_pci.c,v 1.14 2007/03/04 11:04:18 mglocker Exp $ */ +/* $OpenBSD: if_bcw_pci.c,v 1.15 2007/03/31 09:48:02 mglocker Exp $ */ /* * Copyright (c) 2006 Jon Simola <jsimola@gmail.com> @@ -111,17 +111,14 @@ bcw_pci_attach(struct device *parent, struct device *self, void *aux) struct pci_attach_args *pa = (struct pci_attach_args *)aux; struct bcw_softc *sc = &psc->psc_bcw; pci_chipset_tag_t pc = pa->pa_pc; - pcireg_t memtype; - bus_addr_t memaddr; bus_size_t memsize; - int pmreg; - pcireg_t pmode; + int error; sc->sc_dmat = pa->pa_dmat; psc->psc_pc = pa->pa_pc; psc->psc_pcitag = pa->pa_tag; sc->sc_dev_softc = psc; - +#if 0 /* Get it out of power save mode if needed. */ if (pci_get_capability(pc, pa->pa_tag, PCI_CAP_PWRMGMT, &pmreg, 0)) { pmode = pci_conf_read(pc, pa->pa_tag, pmreg + 4) & 0x3; @@ -140,47 +137,36 @@ bcw_pci_attach(struct device *parent, struct device *self, void *aux) pci_conf_write(pc, pa->pa_tag, pmreg + 4, 0); } } - - /* - * Map control/status registers. - */ - /* Copied from pre-abstraction, via if_bce.c */ - memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, BCW_PCI_BAR0); - switch (memtype) { - case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT: - case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_64BIT: - if (pci_mapreg_map(pa, BCW_PCI_BAR0, memtype, 0, &sc->sc_iot, - &sc->sc_ioh, &memaddr, &memsize, 0) == 0) - break; - default: - printf("%s: unable to find mem space\n", - sc->sc_dev.dv_xname); +#endif + /* map control / status registers */ + error = pci_mapreg_map(pa, BCW_PCI_BAR0, + PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT, 0, + &sc->sc_iot, &sc->sc_ioh, NULL, &memsize, 0); + if (error != 0) { + printf(": could not map memory space\n"); return; } - /* Map the PCI interrupt */ - if (pci_intr_map(pa, &psc->psc_ih)) { - printf("%s: couldn't map interrupt\n", - sc->sc_dev.dv_xname); + /* map interrupt */ + if (pci_intr_map(pa, &psc->psc_ih) != 0) { + printf(": couldn't map interrupt\n"); return; } + /* establish interrupt */ sc->bcw_intrstr = pci_intr_string(pc, psc->psc_ih); - psc->psc_intrcookie = pci_intr_establish(pc, psc->psc_ih, IPL_NET, bcw_intr, sc, sc->sc_dev.dv_xname); - if (psc->psc_intrcookie == NULL) { - printf("%s: couldn't establish interrupt", - sc->sc_dev.dv_xname); + printf("%s: couldn't establish interrupt"); if (sc->bcw_intrstr != NULL) printf(" at %s", sc->bcw_intrstr); printf("\n"); return; } - printf(": %s", sc->bcw_intrstr); + /* map function pointers which we need later in the device code */ sc->sc_conf_write = bcw_pci_conf_write; sc->sc_conf_read = bcw_pci_conf_read; @@ -193,23 +179,6 @@ bcw_pci_attach(struct device *parent, struct device *self, void *aux) sc->sc_board_rev = PCI_REVISION(pa->pa_class); /* - * Start the card up while we're in PCI land - */ - - /* Turn the Crystal On */ - bcw_powercontrol_crystal_on(sc); - - /* - * Clear PCI_STATUS_TARGET_TARGET_ABORT, Docs and Linux call it - * PCI_STATUS_SIG_TARGET_ABORT - should use pci_conf_read/write? - */ - pci_conf_write(pa->pa_pc, pa->pa_tag, - PCI_COMMAND_STATUS_REG, - pci_conf_read(pa->pa_pc, pa->pa_tag, - PCI_COMMAND_STATUS_REG) - & ~PCI_STATUS_TARGET_TARGET_ABORT); - - /* * Finish the attach */ bcw_attach(sc); |