diff options
author | Brad Smith <brad@cvs.openbsd.org> | 2004-10-31 06:59:26 +0000 |
---|---|---|
committer | Brad Smith <brad@cvs.openbsd.org> | 2004-10-31 06:59:26 +0000 |
commit | dada15611a8ea178c2b52e9a6d8bd3bcf06579c1 (patch) | |
tree | d9363582c3f8db4dfdc8b4357ede0f07727ee13a /sys/dev/pci/if_bge.c | |
parent | f2649a5953c2bd47680e1cb7ecdc8689d3795e7a (diff) |
rev 1.68
Add support for BCM5705K
rev 1.74
Add support for the BCM5750/5751. Unfortunately the documentation
I have from Broadcom does not give much information on these devices,
so the Broadcom Linux driver was used for clues to what these chips
support. It turns out they are similar to the 5705 with the 5751
being the PCI-Express version and needing special work-arounds and
settings.
From FreeBSD
Diffstat (limited to 'sys/dev/pci/if_bge.c')
-rw-r--r-- | sys/dev/pci/if_bge.c | 146 |
1 files changed, 111 insertions, 35 deletions
diff --git a/sys/dev/pci/if_bge.c b/sys/dev/pci/if_bge.c index 3694b333115..11d06ca2f53 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.33 2004/09/28 04:37:32 brad Exp $ */ +/* $OpenBSD: if_bge.c,v 1.34 2004/10/31 06:59:25 brad Exp $ */ /* * Copyright (c) 2001 Wind River Systems * Copyright (c) 1997, 1998, 1999, 2001 @@ -212,8 +212,12 @@ const struct pci_matchid bge_devices[] = { { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5704C }, { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5704S }, { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5705 }, + { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5705K }, { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5705M }, { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5705M_ALT }, + { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5750 }, + { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5750M }, + { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5751 }, { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5782 }, { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5788 }, { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5901 }, @@ -1016,7 +1020,11 @@ bge_chipinit(sc) BGE_MEMWIN_WRITE(pa->pa_pc, pa->pa_tag, i, 0); /* Set up the PCI DMA control register. */ - if (pci_conf_read(pa->pa_pc, pa->pa_tag, BGE_PCI_PCISTATE) & + if (sc->bge_pcie) { + dma_rw_ctl = BGE_PCI_READ_CMD | BGE_PCI_WRITE_CMD | + (0xf << BGE_PCIDMARWCTL_RD_WAT_SHIFT) | + (0x2 << BGE_PCIDMARWCTL_WR_WAT_SHIFT); + } else if (pci_conf_read(pa->pa_pc, pa->pa_tag, BGE_PCI_PCISTATE) & BGE_PCISTATE_PCI_BUSMODE) { /* Conventional PCI bus */ dma_rw_ctl = BGE_PCI_READ_CMD | BGE_PCI_WRITE_CMD | @@ -1055,7 +1063,8 @@ bge_chipinit(sc) if (sc->bge_asicrev == BGE_ASICREV_BCM5703 || sc->bge_asicrev == BGE_ASICREV_BCM5704 || - sc->bge_asicrev == BGE_ASICREV_BCM5705) + sc->bge_asicrev == BGE_ASICREV_BCM5705 || + sc->bge_asicrev == BGE_ASICREV_BCM5750) dma_rw_ctl &= ~BGE_PCIDMARWCTL_MINDMA; pci_conf_write(pa->pa_pc, pa->pa_tag, BGE_PCI_DMA_RW_CTL, dma_rw_ctl); @@ -1116,7 +1125,8 @@ bge_blockinit(sc) /* Note: the BCM5704 has a smaller bmuf space than the other chips */ - if (sc->bge_asicrev != BGE_ASICREV_BCM5705) { + if (sc->bge_asicrev != BGE_ASICREV_BCM5705 && + sc->bge_asicrev != BGE_ASICREV_BCM5750) { /* Configure mbuf memory pool */ CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_BASEADDR, (sc->bge_extram) ? BGE_EXT_SSRAM : BGE_BUFFPOOL_1); @@ -1130,7 +1140,8 @@ bge_blockinit(sc) } /* Configure mbuf pool watermarks */ - if (sc->bge_asicrev == BGE_ASICREV_BCM5705) { + if (sc->bge_asicrev == BGE_ASICREV_BCM5705 || + sc->bge_asicrev == BGE_ASICREV_BCM5750) { CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_READDMA_LOWAT, 0x0); CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_MACRX_LOWAT, 0x10); } else { @@ -1144,7 +1155,8 @@ bge_blockinit(sc) CSR_WRITE_4(sc, BGE_BMAN_DMA_DESCPOOL_HIWAT, 10); /* Enable buffer manager */ - if (sc->bge_asicrev != BGE_ASICREV_BCM5705) { + if (sc->bge_asicrev != BGE_ASICREV_BCM5705 && + sc->bge_asicrev != BGE_ASICREV_BCM5750) { CSR_WRITE_4(sc, BGE_BMAN_MODE, BGE_BMANMODE_ENABLE|BGE_BMANMODE_LOMBUF_ATTN); @@ -1182,7 +1194,8 @@ bge_blockinit(sc) /* Initialize the standard RX ring control block */ rcb = &sc->bge_rdata->bge_info.bge_std_rx_rcb; BGE_HOSTADDR(rcb->bge_hostaddr, BGE_RING_DMA_ADDR(sc, bge_rx_std_ring)); - if (sc->bge_asicrev == BGE_ASICREV_BCM5705) + if (sc->bge_asicrev == BGE_ASICREV_BCM5705 || + sc->bge_asicrev == BGE_ASICREV_BCM5750) rcb->bge_maxlen_flags = BGE_RCB_MAXLEN_FLAGS(512, 0); else rcb->bge_maxlen_flags = @@ -1203,7 +1216,8 @@ bge_blockinit(sc) * using this ring (i.e. once we set the MTU * high enough to require it). */ - if (sc->bge_asicrev != BGE_ASICREV_BCM5705) { + if (sc->bge_asicrev != BGE_ASICREV_BCM5705 && + sc->bge_asicrev != BGE_ASICREV_BCM5750) { rcb = &sc->bge_rdata->bge_info.bge_jumbo_rx_rcb; BGE_HOSTADDR(rcb->bge_hostaddr, BGE_RING_DMA_ADDR(sc, bge_rx_jumbo_ring)); @@ -1260,7 +1274,8 @@ bge_blockinit(sc) BGE_RING_DMA_ADDR(sc, bge_tx_ring)); RCB_WRITE_4(sc, rcb_addr, bge_nicaddr, BGE_NIC_TXRING_ADDR(0, BGE_TX_RING_CNT)); - if (sc->bge_asicrev != BGE_ASICREV_BCM5705) + if (sc->bge_asicrev != BGE_ASICREV_BCM5705 && + sc->bge_asicrev != BGE_ASICREV_BCM5750) RCB_WRITE_4(sc, rcb_addr, bge_maxlen_flags, BGE_RCB_MAXLEN_FLAGS(BGE_TX_RING_CNT, 0)); @@ -1344,7 +1359,8 @@ bge_blockinit(sc) CSR_WRITE_4(sc, BGE_HCC_TX_COAL_TICKS, sc->bge_tx_coal_ticks); CSR_WRITE_4(sc, BGE_HCC_RX_MAX_COAL_BDS, sc->bge_rx_max_coal_bds); CSR_WRITE_4(sc, BGE_HCC_TX_MAX_COAL_BDS, sc->bge_tx_max_coal_bds); - if (sc->bge_asicrev != BGE_ASICREV_BCM5705) { + if (sc->bge_asicrev != BGE_ASICREV_BCM5705 && + sc->bge_asicrev != BGE_ASICREV_BCM5750) { CSR_WRITE_4(sc, BGE_HCC_RX_COAL_TICKS_INT, 0); CSR_WRITE_4(sc, BGE_HCC_TX_COAL_TICKS_INT, 0); } @@ -1352,7 +1368,8 @@ bge_blockinit(sc) CSR_WRITE_4(sc, BGE_HCC_TX_MAX_COAL_BDS_INT, 0); /* Set up address of statistics block */ - if (sc->bge_asicrev != BGE_ASICREV_BCM5705) { + if (sc->bge_asicrev != BGE_ASICREV_BCM5705 && + sc->bge_asicrev != BGE_ASICREV_BCM5750) { CSR_WRITE_4(sc, BGE_HCC_STATS_ADDR_HI, 0); CSR_WRITE_4(sc, BGE_HCC_STATS_ADDR_LO, BGE_RING_DMA_ADDR(sc, bge_info.bge_stats)); @@ -1381,7 +1398,8 @@ bge_blockinit(sc) CSR_WRITE_4(sc, BGE_RXLP_MODE, BGE_RXLPMODE_ENABLE); /* Turn on RX list selector state machine. */ - if (sc->bge_asicrev != BGE_ASICREV_BCM5705) + if (sc->bge_asicrev != BGE_ASICREV_BCM5705 && + sc->bge_asicrev != BGE_ASICREV_BCM5750) CSR_WRITE_4(sc, BGE_RXLS_MODE, BGE_RXLSMODE_ENABLE); /* Turn on DMA, clear stats */ @@ -1403,7 +1421,8 @@ bge_blockinit(sc) #endif /* Turn on DMA completion state machine */ - if (sc->bge_asicrev != BGE_ASICREV_BCM5705) + if (sc->bge_asicrev != BGE_ASICREV_BCM5705 && + sc->bge_asicrev != BGE_ASICREV_BCM5750) CSR_WRITE_4(sc, BGE_DMAC_MODE, BGE_DMACMODE_ENABLE); /* Turn on write DMA state machine */ @@ -1424,7 +1443,8 @@ bge_blockinit(sc) CSR_WRITE_4(sc, BGE_RDBDI_MODE, BGE_RDBDIMODE_ENABLE); /* Turn on Mbuf cluster free state machine */ - if (sc->bge_asicrev != BGE_ASICREV_BCM5705) + if (sc->bge_asicrev != BGE_ASICREV_BCM5705 && + sc->bge_asicrev != BGE_ASICREV_BCM5750) CSR_WRITE_4(sc, BGE_MBCF_MODE, BGE_MBCFMODE_ENABLE); /* Turn on send BD completion state machine */ @@ -1563,6 +1583,29 @@ bge_attach(parent, self, aux) } printf(": %s", intrstr); + /* Save ASIC rev. */ + + sc->bge_chipid = + pci_conf_read(pc, pa->pa_tag, BGE_PCI_MISC_CTL) & + BGE_PCIMISCCTL_ASICREV; + sc->bge_asicrev = BGE_ASICREV(sc->bge_chipid); + sc->bge_chiprev = BGE_CHIPREV(sc->bge_chipid); + + /* + * XXX: Broadcom Linux driver. Not in specs or eratta. + * PCI-Express? + */ + if (sc->bge_asicrev == BGE_ASICREV_BCM5750) { + u_int32_t v; + + v = pci_conf_read(pc, pa->pa_tag, BGE_PCI_MSI_CAPID); + if (((v >> 8) & 0xff) == BGE_PCIE_CAPID_REG) { + v = pci_conf_read(pc, pa->pa_tag, BGE_PCIE_CAPID_REG); + if ((v & 0xff) == BGE_PCIE_CAPID) + sc->bge_pcie = 1; + } + } + /* Try to reset the chip. */ DPRINTFN(5, ("bge_reset\n")); bge_reset(sc); @@ -1644,19 +1687,12 @@ bge_attach(parent, self, aux) bzero(sc->bge_rdata, sizeof(struct bge_ring_data)); - /* Save ASIC rev. */ - - sc->bge_chipid = - pci_conf_read(pc, pa->pa_tag, BGE_PCI_MISC_CTL) & - BGE_PCIMISCCTL_ASICREV; - sc->bge_asicrev = BGE_ASICREV(sc->bge_chipid); - sc->bge_chiprev = BGE_CHIPREV(sc->bge_chipid); - /* * Try to allocate memory for jumbo buffers. * The 5705 does not appear to support jumbo frames. */ - if (sc->bge_asicrev != BGE_ASICREV_BCM5705) { + if (sc->bge_asicrev != BGE_ASICREV_BCM5705 && + sc->bge_asicrev != BGE_ASICREV_BCM5750) { if (bge_alloc_jumbo_mem(sc)) { printf("%s: jumbo buffer allocation failed\n", sc->bge_dev.dv_xname); @@ -1673,7 +1709,8 @@ bge_attach(parent, self, aux) sc->bge_tx_max_coal_bds = 128; /* 5705 limits RX return ring to 512 entries. */ - if (sc->bge_asicrev == BGE_ASICREV_BCM5705) + if (sc->bge_asicrev == BGE_ASICREV_BCM5705 || + sc->bge_asicrev == BGE_ASICREV_BCM5750) sc->bge_return_ring_cnt = BGE_RETURN_RING_CNT_5705; else sc->bge_return_ring_cnt = BGE_RETURN_RING_CNT; @@ -1818,7 +1855,7 @@ bge_reset(sc) struct bge_softc *sc; { struct pci_attach_args *pa = &sc->bge_pa; - u_int32_t cachesize, command, pcistate; + u_int32_t cachesize, command, pcistate, reset; int i, val = 0; /* Save some important PCI state. */ @@ -1830,12 +1867,37 @@ bge_reset(sc) BGE_PCIMISCCTL_INDIRECT_ACCESS|BGE_PCIMISCCTL_MASK_PCI_INTR| BGE_PCIMISCCTL_ENDIAN_WORDSWAP|BGE_PCIMISCCTL_PCISTATE_RW); + reset = BGE_MISCCFG_RESET_CORE_CLOCKS|(65<<1); + + /* XXX: Broadcom Linux driver. */ + if (sc->bge_pcie) { + if (CSR_READ_4(sc, 0x7e2c) == 0x60) /* PCIE 1.0 */ + CSR_WRITE_4(sc, 0x7e2c, 0x20); + if (sc->bge_chipid != BGE_CHIPID_BCM5750_A0) { + /* Prevent PCIE link training during global reset */ + CSR_WRITE_4(sc, BGE_MISC_CFG, (1<<29)); + reset |= (1<<29); + } + } + /* Issue global reset */ - bge_writereg_ind(sc, BGE_MISC_CFG, - BGE_MISCCFG_RESET_CORE_CLOCKS|(65<<1)); + bge_writereg_ind(sc, BGE_MISC_CFG, reset); DELAY(1000); + /* XXX: Broadcom Linux driver. */ + if (sc->bge_pcie) { + if (sc->bge_chipid == BGE_CHIPID_BCM5750_A0) { + uint32_t v; + + DELAY(500000); /* wait for link training to complete */ + v = pci_conf_read(pa->pa_pc, pa->pa_tag, 0xc4); + pci_conf_write(pa->pa_pc, pa->pa_tag, 0xc4, v | (1<<15)); + } + /* Set PCIE max payload size and clear error status. */ + pci_conf_write(pa->pa_pc, pa->pa_tag, 0xd8, 0xf5000); + } + /* Reset some of the PCI state that got zapped by reset */ pci_conf_write(pa->pa_pc, pa->pa_tag, BGE_PCI_MISC_CTL, BGE_PCIMISCCTL_INDIRECT_ACCESS|BGE_PCIMISCCTL_MASK_PCI_INTR| @@ -1845,7 +1907,8 @@ bge_reset(sc) bge_writereg_ind(sc, BGE_MISC_CFG, (65 << 1)); /* Enable memory arbiter. */ - if (sc->bge_asicrev != BGE_ASICREV_BCM5705) + if (sc->bge_asicrev != BGE_ASICREV_BCM5705 && + sc->bge_asicrev != BGE_ASICREV_BCM5750) CSR_WRITE_4(sc, BGE_MARB_MODE, BGE_MARBMODE_ENABLE); /* @@ -1893,6 +1956,12 @@ bge_reset(sc) CSR_WRITE_4(sc, BGE_MAC_MODE, 0); + /* XXX: Broadcom Linux driver. */ + if (sc->bge_pcie && sc->bge_chipid != BGE_CHIPID_BCM5750_A0) { + uint32_t v; + v = CSR_READ_4(sc, 0x7c00); + CSR_WRITE_4(sc, 0x7c00, v | (1<<25)); + } DELAY(10000); } @@ -2193,7 +2262,8 @@ bge_tick(xsc) s = splimp(); - if (sc->bge_asicrev == BGE_ASICREV_BCM5705) + if (sc->bge_asicrev == BGE_ASICREV_BCM5705 || + sc->bge_asicrev == BGE_ASICREV_BCM5750) bge_stats_update_regs(sc); else bge_stats_update(sc); @@ -2679,7 +2749,8 @@ bge_ioctl(ifp, command, data) break; case SIOCSIFMTU: /* Disallow jumbo frames on 5705. */ - if ((sc->bge_asicrev == BGE_ASICREV_BCM5705 && + if (((sc->bge_asicrev == BGE_ASICREV_BCM5705 || + sc->bge_asicrev == BGE_ASICREV_BCM5750) && ifr->ifr_mtu > ETHERMTU) || ifr->ifr_mtu > ETHERMTU_JUMBO) error = EINVAL; else @@ -2786,7 +2857,8 @@ bge_stop(sc) BGE_CLRBIT(sc, BGE_RX_MODE, BGE_RXMODE_ENABLE); BGE_CLRBIT(sc, BGE_RBDI_MODE, BGE_RBDIMODE_ENABLE); BGE_CLRBIT(sc, BGE_RXLP_MODE, BGE_RXLPMODE_ENABLE); - if (sc->bge_asicrev != BGE_ASICREV_BCM5705) + if (sc->bge_asicrev != BGE_ASICREV_BCM5705 && + sc->bge_asicrev != BGE_ASICREV_BCM5750) BGE_CLRBIT(sc, BGE_RXLS_MODE, BGE_RXLSMODE_ENABLE); BGE_CLRBIT(sc, BGE_RDBDI_MODE, BGE_RBDIMODE_ENABLE); BGE_CLRBIT(sc, BGE_RDC_MODE, BGE_RDCMODE_ENABLE); @@ -2800,7 +2872,8 @@ bge_stop(sc) BGE_CLRBIT(sc, BGE_SDI_MODE, BGE_SDIMODE_ENABLE); BGE_CLRBIT(sc, BGE_RDMA_MODE, BGE_RDMAMODE_ENABLE); BGE_CLRBIT(sc, BGE_SDC_MODE, BGE_SDCMODE_ENABLE); - if (sc->bge_asicrev != BGE_ASICREV_BCM5705) + if (sc->bge_asicrev != BGE_ASICREV_BCM5705 && + sc->bge_asicrev != BGE_ASICREV_BCM5750) BGE_CLRBIT(sc, BGE_DMAC_MODE, BGE_DMACMODE_ENABLE); BGE_CLRBIT(sc, BGE_SBDC_MODE, BGE_SBDCMODE_ENABLE); @@ -2810,11 +2883,13 @@ bge_stop(sc) */ BGE_CLRBIT(sc, BGE_HCC_MODE, BGE_HCCMODE_ENABLE); BGE_CLRBIT(sc, BGE_WDMA_MODE, BGE_WDMAMODE_ENABLE); - if (sc->bge_asicrev != BGE_ASICREV_BCM5705) + if (sc->bge_asicrev != BGE_ASICREV_BCM5705 && + sc->bge_asicrev != BGE_ASICREV_BCM5750) BGE_CLRBIT(sc, BGE_MBCF_MODE, BGE_MBCFMODE_ENABLE); CSR_WRITE_4(sc, BGE_FTQ_RESET, 0xFFFFFFFF); CSR_WRITE_4(sc, BGE_FTQ_RESET, 0); - if (sc->bge_asicrev != BGE_ASICREV_BCM5705) { + if (sc->bge_asicrev != BGE_ASICREV_BCM5705 && + sc->bge_asicrev != BGE_ASICREV_BCM5750) { BGE_CLRBIT(sc, BGE_BMAN_MODE, BGE_BMANMODE_ENABLE); BGE_CLRBIT(sc, BGE_MARB_MODE, BGE_MARBMODE_ENABLE); } @@ -2832,7 +2907,8 @@ bge_stop(sc) bge_free_rx_ring_std(sc); /* Free jumbo RX list. */ - if (sc->bge_asicrev != BGE_ASICREV_BCM5705) + if (sc->bge_asicrev != BGE_ASICREV_BCM5705 && + sc->bge_asicrev != BGE_ASICREV_BCM5750) bge_free_rx_ring_jumbo(sc); /* Free TX buffers. */ |