diff options
-rw-r--r-- | sys/dev/mii/brgphy.c | 4 | ||||
-rw-r--r-- | sys/dev/pci/if_bge.c | 200 | ||||
-rw-r--r-- | sys/dev/pci/if_bgereg.h | 69 |
3 files changed, 233 insertions, 40 deletions
diff --git a/sys/dev/mii/brgphy.c b/sys/dev/mii/brgphy.c index f55a269a6b0..8128cc62b92 100644 --- a/sys/dev/mii/brgphy.c +++ b/sys/dev/mii/brgphy.c @@ -1,4 +1,4 @@ -/* $OpenBSD: brgphy.c,v 1.71 2007/01/30 02:35:16 krw Exp $ */ +/* $OpenBSD: brgphy.c,v 1.72 2007/10/13 16:29:52 kettenis Exp $ */ /* * Copyright (c) 2000 @@ -135,6 +135,8 @@ static const struct mii_phydesc brgphys[] = { MII_STR_xxBROADCOM_BCM5706C }, { MII_OUI_xxBROADCOM, MII_MODEL_xxBROADCOM_BCM5708C, MII_STR_xxBROADCOM_BCM5708C }, + { MII_OUI_BROADCOM2, MII_MODEL_BROADCOM2_BCM5906, + MII_STR_BROADCOM2_BCM5906 }, { 0, 0, NULL }, diff --git a/sys/dev/pci/if_bge.c b/sys/dev/pci/if_bge.c index 3dde9f339a1..1be0ffff583 100644 --- a/sys/dev/pci/if_bge.c +++ b/sys/dev/pci/if_bge.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_bge.c,v 1.214 2007/10/09 05:43:37 ray Exp $ */ +/* $OpenBSD: if_bge.c,v 1.215 2007/10/13 16:29:52 kettenis Exp $ */ /* * Copyright (c) 2001 Wind River Systems @@ -154,6 +154,8 @@ void bge_shutdown(void *); int bge_ifmedia_upd(struct ifnet *); void bge_ifmedia_sts(struct ifnet *, struct ifmediareq *); +u_int8_t bge_nvram_getbyte(struct bge_softc *, int, u_int8_t *); +int bge_read_nvram(struct bge_softc *, caddr_t, int, int); u_int8_t bge_eeprom_getbyte(struct bge_softc *, int, u_int8_t *); int bge_read_eeprom(struct bge_softc *, caddr_t, int, int); @@ -177,6 +179,7 @@ int bge_blockinit(struct bge_softc *); u_int32_t bge_readmem_ind(struct bge_softc *, int); void bge_writemem_ind(struct bge_softc *, int, int); void bge_writereg_ind(struct bge_softc *, int, int); +void bge_writembx(struct bge_softc *, int, int); int bge_miibus_readreg(struct device *, int, int); void bge_miibus_writereg(struct device *, int, int, int); @@ -261,10 +264,8 @@ const struct pci_matchid bge_devices[] = { { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5901 }, { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5901A2 }, { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5903M }, -#if 0 { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5906 }, { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5906M }, -#endif { PCI_VENDOR_SCHNEIDERKOCH, PCI_PRODUCT_SCHNEIDERKOCH_SK9D21 }, @@ -359,6 +360,7 @@ static const struct bge_revision { { BGE_CHIPID_BCM5787_A1, "BCM5754/5787 A1" }, { BGE_CHIPID_BCM5787_A2, "BCM5754/5787 A2" }, { BGE_CHIPID_BCM5906_A1, "BCM5906 A1" }, + { BGE_CHIPID_BCM5906_A2, "BCM5906 A2" }, { 0, NULL } }; @@ -414,6 +416,88 @@ bge_writereg_ind(struct bge_softc *sc, int off, int val) pci_conf_write(pa->pa_pc, pa->pa_tag, BGE_PCI_REG_DATA, val); } +void +bge_writembx(struct bge_softc *sc, int off, int val) +{ + if (BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5906) + off += BGE_LPMBX_IRQ0_HI - BGE_MBX_IRQ0_HI; + + CSR_WRITE_4(sc, off, val); +} + +u_int8_t +bge_nvram_getbyte(struct bge_softc *sc, int addr, u_int8_t *dest) +{ + u_int32_t access, byte = 0; + int i; + + /* Lock. */ + CSR_WRITE_4(sc, BGE_NVRAM_SWARB, BGE_NVRAMSWARB_SET1); + for (i = 0; i < 8000; i++) { + if (CSR_READ_4(sc, BGE_NVRAM_SWARB) & BGE_NVRAMSWARB_GNT1) + break; + DELAY(20); + } + if (i == 8000) + return (1); + + /* Enable access. */ + access = CSR_READ_4(sc, BGE_NVRAM_ACCESS); + CSR_WRITE_4(sc, BGE_NVRAM_ACCESS, access | BGE_NVRAMACC_ENABLE); + + CSR_WRITE_4(sc, BGE_NVRAM_ADDR, addr & 0xfffffffc); + CSR_WRITE_4(sc, BGE_NVRAM_CMD, BGE_NVRAM_READCMD); + for (i = 0; i < BGE_TIMEOUT * 10; i++) { + DELAY(10); + if (CSR_READ_4(sc, BGE_NVRAM_CMD) & BGE_NVRAMCMD_DONE) { + DELAY(10); + break; + } + } + + if (i == BGE_TIMEOUT * 10) { + printf("%s: nvram read timed out\n", sc->bge_dev.dv_xname); + return (1); + } + + /* Get result. */ + byte = CSR_READ_4(sc, BGE_NVRAM_RDDATA); + + *dest = (swap32(byte) >> ((addr % 4) * 8)) & 0xFF; + + /* Disable access. */ + CSR_WRITE_4(sc, BGE_NVRAM_ACCESS, access); + + /* Unlock. */ + CSR_WRITE_4(sc, BGE_NVRAM_SWARB, BGE_NVRAMSWARB_CLR1); + CSR_READ_4(sc, BGE_NVRAM_SWARB); + + return (0); +} + +/* + * Read a sequence of bytes from NVRAM. + */ + +int +bge_read_nvram(struct bge_softc *sc, caddr_t dest, int off, int cnt) +{ + int err = 0, i; + u_int8_t byte = 0; + + if (BGE_ASICREV(sc->bge_chipid) != BGE_ASICREV_BCM5906) + return (1); + + for (i = 0; i < cnt; i++) { + err = bge_nvram_getbyte(sc, off + i, &byte); + if (err) + break; + *(dest + i) = byte; + } + + return (err ? 1 : 0); +} + /* * Read a byte of data stored in the EEPROM at address 'addr.' The * BCM570x supports both the traditional bitbang interface and an @@ -906,7 +990,7 @@ bge_init_rx_ring_std(struct bge_softc *sc) } sc->bge_std = i - 1; - CSR_WRITE_4(sc, BGE_MBX_RX_STD_PROD_LO, sc->bge_std); + bge_writembx(sc, BGE_MBX_RX_STD_PROD_LO, sc->bge_std); sc->bge_flags |= BGE_RXRING_VALID; @@ -956,7 +1040,7 @@ bge_init_rx_ring_jumbo(struct bge_softc *sc) rcb->bge_maxlen_flags = BGE_RCB_MAXLEN_FLAGS(0, 0); CSR_WRITE_4(sc, BGE_RX_JUMBO_RCB_MAXLEN_FLAGS, rcb->bge_maxlen_flags); - CSR_WRITE_4(sc, BGE_MBX_RX_JUMBO_PROD_LO, sc->bge_jumbo); + bge_writembx(sc, BGE_MBX_RX_JUMBO_PROD_LO, sc->bge_jumbo); return (0); } @@ -1026,14 +1110,14 @@ bge_init_tx_ring(struct bge_softc *sc) /* Initialize transmit producer index for host-memory send ring. */ sc->bge_tx_prodidx = 0; - CSR_WRITE_4(sc, BGE_MBX_TX_HOST_PROD0_LO, sc->bge_tx_prodidx); + bge_writembx(sc, BGE_MBX_TX_HOST_PROD0_LO, sc->bge_tx_prodidx); if (BGE_CHIPREV(sc->bge_chipid) == BGE_CHIPREV_5700_BX) - CSR_WRITE_4(sc, BGE_MBX_TX_HOST_PROD0_LO, sc->bge_tx_prodidx); + bge_writembx(sc, BGE_MBX_TX_HOST_PROD0_LO, sc->bge_tx_prodidx); /* NIC-memory send ring not used; initialize to zero. */ - CSR_WRITE_4(sc, BGE_MBX_TX_NIC_PROD0_LO, 0); + bge_writembx(sc, BGE_MBX_TX_NIC_PROD0_LO, 0); if (BGE_CHIPREV(sc->bge_chipid) == BGE_CHIPREV_5700_BX) - CSR_WRITE_4(sc, BGE_MBX_TX_NIC_PROD0_LO, 0); + bge_writembx(sc, BGE_MBX_TX_NIC_PROD0_LO, 0); SLIST_INIT(&sc->txdma_list); for (i = 0; i < BGE_TX_RING_CNT; i++) { @@ -1272,6 +1356,10 @@ bge_blockinit(struct bge_softc *sc) CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_READDMA_LOWAT, 0x50); CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_MACRX_LOWAT, 0x20); CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_HIWAT, 0x60); + } else if (BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5906) { + CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_READDMA_LOWAT, 0x0); + CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_MACRX_LOWAT, 0x04); + CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_HIWAT, 0x10); } else { CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_READDMA_LOWAT, 0x0); CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_MACRX_LOWAT, 0x10); @@ -1383,7 +1471,8 @@ bge_blockinit(struct bge_softc *sc) if (BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5750 || BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5752 || BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5755 || - BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5787) + BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5787 || + BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5906) i = 8; CSR_WRITE_4(sc, BGE_RBDI_STD_REPL_THRESH, i); @@ -1422,15 +1511,15 @@ bge_blockinit(struct bge_softc *sc) BGE_RCB_MAXLEN_FLAGS(sc->bge_return_ring_cnt, BGE_RCB_FLAG_RING_DISABLED)); RCB_WRITE_4(sc, rcb_addr, bge_nicaddr, 0); - CSR_WRITE_4(sc, BGE_MBX_RX_CONS0_LO + + bge_writembx(sc, BGE_MBX_RX_CONS0_LO + (i * (sizeof(u_int64_t))), 0); rcb_addr += sizeof(struct bge_rcb); } /* Initialize RX ring indexes */ - CSR_WRITE_4(sc, BGE_MBX_RX_STD_PROD_LO, 0); - CSR_WRITE_4(sc, BGE_MBX_RX_JUMBO_PROD_LO, 0); - CSR_WRITE_4(sc, BGE_MBX_RX_MINI_PROD_LO, 0); + bge_writembx(sc, BGE_MBX_RX_STD_PROD_LO, 0); + bge_writembx(sc, BGE_MBX_RX_JUMBO_PROD_LO, 0); + bge_writembx(sc, BGE_MBX_RX_MINI_PROD_LO, 0); /* * Set up RX return ring 0 @@ -1875,6 +1964,16 @@ bge_attach(struct device *parent, struct device *self, void *aux) gotenaddr = 1; } } + if (!gotenaddr) { + int mac_offset = BGE_EE_MAC_OFFSET; + + if (BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5906) + mac_offset = BGE_EE_MAC_OFFSET_5906; + + if (bge_read_nvram(sc, (caddr_t)&sc->arpcom.ac_enaddr, + mac_offset + 2, ETHER_ADDR_LEN) == 0) + gotenaddr = 1; + } if (!gotenaddr && (!(sc->bge_flags & BGE_NO_EEPROM))) { if (bge_read_eeprom(sc, (caddr_t)&sc->arpcom.ac_enaddr, BGE_EE_MAC_OFFSET + 2, ETHER_ADDR_LEN) == 0) @@ -2136,6 +2235,19 @@ bge_reset(struct bge_softc *sc) /* Issue global reset */ bge_writereg_ind(sc, BGE_MISC_CFG, reset); + if (BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5906) { + u_int32_t status, ctrl; + + status = CSR_READ_4(sc, BGE_VCPU_STATUS); + CSR_WRITE_4(sc, BGE_VCPU_STATUS, + status | BGE_VCPU_STATUS_DRV_RESET); + ctrl = CSR_READ_4(sc, BGE_VCPU_EXT_CTRL); + CSR_WRITE_4(sc, BGE_VCPU_EXT_CTRL, + ctrl & ~BGE_VCPU_EXT_CTRL_HALT_CPU); + + sc->bge_flags |= BGE_NO_EEPROM; + } + DELAY(1000); if (sc->bge_flags & BGE_PCIE) { @@ -2178,22 +2290,34 @@ bge_reset(struct bge_softc *sc) */ bge_writemem_ind(sc, BGE_SOFTWARE_GENCOMM, BGE_MAGIC_NUMBER); - /* - * Poll until we see 1's complement of the magic number. - * This indicates that the firmware initialization - * is complete. We expect this to fail if no SEEPROM - * is fitted. - */ - for (i = 0; i < BGE_TIMEOUT; i++) { - val = bge_readmem_ind(sc, BGE_SOFTWARE_GENCOMM); - if (val == ~BGE_MAGIC_NUMBER) - break; - DELAY(10); - } + if (BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5906) { + for (i = 0; i < BGE_TIMEOUT; i++) { + val = CSR_READ_4(sc, BGE_VCPU_STATUS); + if (val & BGE_VCPU_STATUS_INIT_DONE) + break; + DELAY(100); + } - if (i >= BGE_TIMEOUT && (!(sc->bge_flags & BGE_NO_EEPROM))) - printf("%s: firmware handshake timed out\n", - sc->bge_dev.dv_xname); + if (i >= BGE_TIMEOUT) + printf("%s: reset timed out\n", sc->bge_dev.dv_xname); + } else { + /* + * Poll until we see 1's complement of the magic number. + * This indicates that the firmware initialization + * is complete. We expect this to fail if no SEEPROM + * is fitted. + */ + for (i = 0; i < BGE_TIMEOUT; i++) { + val = bge_readmem_ind(sc, BGE_SOFTWARE_GENCOMM); + if (val == ~BGE_MAGIC_NUMBER) + break; + DELAY(10); + } + + if (i >= BGE_TIMEOUT && (!(sc->bge_flags & BGE_NO_EEPROM))) + printf("%s: firmware handshake timed out\n", + sc->bge_dev.dv_xname); + } /* * XXX Wait for the value of the PCISTATE register to @@ -2397,11 +2521,11 @@ bge_rxeof(struct bge_softc *sc) ether_input_mbuf(ifp, m); } - CSR_WRITE_4(sc, BGE_MBX_RX_CONS0_LO, sc->bge_rx_saved_considx); + bge_writembx(sc, BGE_MBX_RX_CONS0_LO, sc->bge_rx_saved_considx); if (stdcnt) - CSR_WRITE_4(sc, BGE_MBX_RX_STD_PROD_LO, sc->bge_std); + bge_writembx(sc, BGE_MBX_RX_STD_PROD_LO, sc->bge_std); if (jumbocnt) - CSR_WRITE_4(sc, BGE_MBX_RX_JUMBO_PROD_LO, sc->bge_jumbo); + bge_writembx(sc, BGE_MBX_RX_JUMBO_PROD_LO, sc->bge_jumbo); } void @@ -2501,7 +2625,7 @@ bge_intr(void *xsc) (!(CSR_READ_4(sc, BGE_PCI_PCISTATE) & BGE_PCISTATE_INTR_NOT_ACTIVE))) { /* Ack interrupt and stop others from occurring. */ - CSR_WRITE_4(sc, BGE_MBX_IRQ0_LO, 1); + bge_writembx(sc, BGE_MBX_IRQ0_LO, 1); /* clear status word */ sc->bge_rdata->bge_status_block.bge_status = 0; @@ -2521,7 +2645,7 @@ bge_intr(void *xsc) } /* Re-enable interrupts. */ - CSR_WRITE_4(sc, BGE_MBX_IRQ0_LO, 0); + bge_writembx(sc, BGE_MBX_IRQ0_LO, 0); if (ifp->if_flags & IFF_RUNNING && !IFQ_IS_EMPTY(&ifp->if_snd)) bge_start(ifp); @@ -2887,9 +3011,9 @@ bge_start(struct ifnet *ifp) return; /* Transmit */ - CSR_WRITE_4(sc, BGE_MBX_TX_HOST_PROD0_LO, prodidx); + bge_writembx(sc, BGE_MBX_TX_HOST_PROD0_LO, prodidx); if (BGE_CHIPREV(sc->bge_chipid) == BGE_CHIPREV_5700_BX) - CSR_WRITE_4(sc, BGE_MBX_TX_HOST_PROD0_LO, prodidx); + bge_writembx(sc, BGE_MBX_TX_HOST_PROD0_LO, prodidx); sc->bge_tx_prodidx = prodidx; @@ -2992,7 +3116,7 @@ bge_init(void *xsc) /* Enable host interrupts. */ BGE_SETBIT(sc, BGE_PCI_MISC_CTL, BGE_PCIMISCCTL_CLEAR_INTA); BGE_CLRBIT(sc, BGE_PCI_MISC_CTL, BGE_PCIMISCCTL_MASK_PCI_INTR); - CSR_WRITE_4(sc, BGE_MBX_IRQ0_LO, 0); + bge_writembx(sc, BGE_MBX_IRQ0_LO, 0); bge_ifmedia_upd(ifp); @@ -3285,7 +3409,7 @@ bge_stop(struct bge_softc *sc) /* Disable host interrupts. */ BGE_SETBIT(sc, BGE_PCI_MISC_CTL, BGE_PCIMISCCTL_MASK_PCI_INTR); - CSR_WRITE_4(sc, BGE_MBX_IRQ0_LO, 1); + bge_writembx(sc, BGE_MBX_IRQ0_LO, 1); /* * Tell firmware we're shutting down. diff --git a/sys/dev/pci/if_bgereg.h b/sys/dev/pci/if_bgereg.h index a97ca14f45f..cff71f62ea0 100644 --- a/sys/dev/pci/if_bgereg.h +++ b/sys/dev/pci/if_bgereg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: if_bgereg.h,v 1.73 2007/10/11 19:44:39 kettenis Exp $ */ +/* $OpenBSD: if_bgereg.h,v 1.74 2007/10/13 16:29:52 kettenis Exp $ */ /* * Copyright (c) 2001 Wind River Systems @@ -284,6 +284,7 @@ #define BGE_CHIPID_BCM5787_A1 0xb0010000 #define BGE_CHIPID_BCM5787_A2 0xb0020000 #define BGE_CHIPID_BCM5906_A1 0xc0010000 +#define BGE_CHIPID_BCM5906_A2 0xc0020000 /* shorthand one */ #define BGE_ASICREV(x) ((x) >> 28) @@ -1451,6 +1452,19 @@ /* + * V? CPU registers + */ +#define BGE_VCPU_STATUS 0x5100 +#define BGE_VCPU_EXT_CTRL 0x6890 + +#define BGE_VCPU_STATUS_INIT_DONE 0x04000000 +#define BGE_VCPU_STATUS_DRV_RESET 0x08000000 + +#define BGE_VCPU_EXT_CTRL_HALT_CPU 0x00400000 +#define BGE_VCPU_EXT_CTRL_DISABLE_WOL 0x20000000 + + +/* * TX CPU registers */ #define BGE_TXCPU_MODE 0x5400 @@ -1697,6 +1711,58 @@ #define BGE_FASTBOOT_PC 0x6894 /* + * NVRAM Control registers + */ + +#define BGE_NVRAM_CMD 0x7000 +#define BGE_NVRAM_STAT 0x7004 +#define BGE_NVRAM_WRDATA 0x7008 +#define BGE_NVRAM_ADDR 0x700c +#define BGE_NVRAM_RDDATA 0x7010 +#define BGE_NVRAM_CFG1 0x7014 +#define BGE_NVRAM_CFG2 0x7018 +#define BGE_NVRAM_CFG3 0x701c +#define BGE_NVRAM_SWARB 0x7020 +#define BGE_NVRAM_ACCESS 0x7024 +#define BGE_NVRAM_WRITE1 0x7028 + + +#define BGE_NVRAMCMD_RESET 0x00000001 +#define BGE_NVRAMCMD_DONE 0x00000008 +#define BGE_NVRAMCMD_START 0x00000010 +#define BGE_NVRAMCMD_WR 0x00000020 /* 1 = wr, 0 = rd */ +#define BGE_NVRAMCMD_ERASE 0x00000040 +#define BGE_NVRAMCMD_FIRST 0x00000080 +#define BGE_NVRAMCMD_LAST 0x00000100 + +#define BGE_NVRAM_READCMD \ + (BGE_NVRAMCMD_FIRST|BGE_NVRAMCMD_LAST| \ + BGE_NVRAMCMD_START|BGE_NVRAMCMD_DONE) +#define BGE_NVRAM_WRITECMD \ + (BGE_NVRAMCMD_FIRST|BGE_NVRAMCMD_LAST| \ + BGE_NVRAMCMD_START|BGE_NVRAMCMD_DONE|BGE_NVRAMCMD_WR) + +#define BGE_NVRAMSWARB_SET0 0x00000001 +#define BGE_NVRAMSWARB_SET1 0x00000002 +#define BGE_NVRAMSWARB_SET2 0x00000003 +#define BGE_NVRAMSWARB_SET3 0x00000004 +#define BGE_NVRAMSWARB_CLR0 0x00000010 +#define BGE_NVRAMSWARB_CLR1 0x00000020 +#define BGE_NVRAMSWARB_CLR2 0x00000040 +#define BGE_NVRAMSWARB_CLR3 0x00000080 +#define BGE_NVRAMSWARB_GNT0 0x00000100 +#define BGE_NVRAMSWARB_GNT1 0x00000200 +#define BGE_NVRAMSWARB_GNT2 0x00000400 +#define BGE_NVRAMSWARB_GNT3 0x00000800 +#define BGE_NVRAMSWARB_REQ0 0x00001000 +#define BGE_NVRAMSWARB_REQ1 0x00002000 +#define BGE_NVRAMSWARB_REQ2 0x00004000 +#define BGE_NVRAMSWARB_REQ3 0x00008000 + +#define BGE_NVRAMACC_ENABLE 0x00000001 +#define BGE_NVRAMACC_WRENABLE 0x00000002 + +/* * TLP Control Register * Applicable to BCM5721 and BCM5751 only */ @@ -1988,6 +2054,7 @@ struct bge_status_block { * Offset of MAC address inside EEPROM. */ #define BGE_EE_MAC_OFFSET 0x7C +#define BGE_EE_MAC_OFFSET_5906 0x10 #define BGE_EE_HWCFG_OFFSET 0xC8 #define BGE_HWCFG_VOLTAGE 0x00000003 |