Subject: Broadcom 575x GigE support
To: None <current-users@NetBSD.org>
From: Quentin Garnier <cube@NetBSD.org>
List: current-users
Date: 10/22/2004 17:17:19
This is a multi-part message in MIME format.
--Multipart=_Fri__22_Oct_2004_17_17_19_+0200_anxmFZKyaP/PHT5H
Content-Type: text/plain; charset=US-ASCII
Content-Transfer-Encoding: 7bit
Hi all,
Reading mostly from Linux and a bit from FreeBSD (it all comes from the
Linux driver anyway), I was able to make my Broadcom 5751 chip working.
I tried to reduce the number of magic numbers as much as I could, but
there are still a lot of them.
I'd like people to test the attached patch, since I can't test on 5750
and 5750M chips, and of course I can't test if it introduces a
regression for the rest of the 57xx series.
Unless there is a breakage, I'll commit it sometime next week.
Quentin Garnier.
--Multipart=_Fri__22_Oct_2004_17_17_19_+0200_anxmFZKyaP/PHT5H
Content-Type: text/plain;
name="bge.diff"
Content-Disposition: attachment;
filename="bge.diff"
Content-Transfer-Encoding: 7bit
Index: if_bge.c
===================================================================
RCS file: /cvsroot/src/sys/dev/pci/if_bge.c,v
retrieving revision 1.75
diff -u -r1.75 if_bge.c
--- if_bge.c 29 Sep 2004 11:22:03 -0000 1.75
+++ if_bge.c 22 Oct 2004 15:04:37 -0000
@@ -1288,7 +1288,14 @@
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) {
+ /* From FreeBSD */
+ DPRINTFN(4, ("(%s: PCI-Express DMA setting)\n",
+ sc->bge_dev.dv_xname));
+ 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 */
DPRINTFN(4, ("(%s: PCI 2.2 DMA setting)\n", sc->bge_dev.dv_xname));
@@ -1926,6 +1933,14 @@
BGE_QUIRK_ONLY_PHY_1|BGE_QUIRK_5705_CORE,
"BCM5705 A3" },
+ { BGE_CHIPID_BCM5750_A0,
+ BGE_QUIRK_ONLY_PHY_1|BGE_QUIRK_5705_CORE,
+ "BCM5750 A1" },
+
+ { BGE_CHIPID_BCM5750_A1,
+ BGE_QUIRK_ONLY_PHY_1|BGE_QUIRK_5705_CORE,
+ "BCM5750 A1" },
+
{ 0, 0, NULL }
};
@@ -1954,6 +1969,10 @@
BGE_QUIRK_ONLY_PHY_1|BGE_QUIRK_5705_CORE,
"unknown BCM5705" },
+ { BGE_ASICREV_BCM5750,
+ BGE_QUIRK_ONLY_PHY_1|BGE_QUIRK_5705_CORE,
+ "unknown BCM5750" },
+
{ 0,
0,
NULL }
@@ -2062,6 +2081,21 @@
"Broadcom BCM5705M Gigabit Ethernet",
},
+ { PCI_VENDOR_BROADCOM,
+ PCI_PRODUCT_BROADCOM_BCM5750,
+ "Broadcom BCM5750 Gigabit Ethernet",
+ },
+
+ { PCI_VENDOR_BROADCOM,
+ PCI_PRODUCT_BROADCOM_BCM5750M,
+ "Broadcom BCM5750M Gigabit Ethernet",
+ },
+
+ { PCI_VENDOR_BROADCOM,
+ PCI_PRODUCT_BROADCOM_BCM5751,
+ "Broadcom BCM5751 Gigabit Ethernet",
+ },
+
{ PCI_VENDOR_BROADCOM,
PCI_PRODUCT_BROADCOM_BCM5782,
"Broadcom BCM5782 Gigabit Ethernet",
@@ -2280,6 +2314,25 @@
pci_conf_write(pc, pa->pa_tag, BGE_PCI_PWRMGMT_CMD, pm_ctl);
DELAY(1000); /* 27 usec is allegedly sufficent */
+ /*
+ * Save ASIC rev. Look up any quirks associated with this
+ * ASIC.
+ */
+ sc->bge_chipid =
+ pci_conf_read(pa->pa_pc, pa->pa_tag, BGE_PCI_MISC_CTL) &
+ BGE_PCIMISCCTL_ASICREV;
+
+ /*
+ * Detect PCI-Express devices
+ * XXX: guessed from Linux/FreeBSD; no documentation
+ */
+ if (BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5750 &&
+ pci_get_capability(pa->pa_pc, pa->pa_tag, PCI_CAP_PCIEXPRESS,
+ NULL, NULL) != 0)
+ sc->bge_pcie = 1;
+ else
+ sc->bge_pcie = 0;
+
/* Try to reset the chip. */
DPRINTFN(5, ("bge_reset\n"));
bge_reset(sc);
@@ -2311,15 +2364,7 @@
return;
}
- /*
- * Save ASIC rev. Look up any quirks associated with this
- * ASIC.
- */
- sc->bge_chipid =
- pci_conf_read(pa->pa_pc, pa->pa_tag, BGE_PCI_MISC_CTL) &
- BGE_PCIMISCCTL_ASICREV;
br = bge_lookup_rev(sc->bge_chipid);
-
aprint_normal("%s: ", sc->bge_dev.dv_xname);
if (br == NULL) {
@@ -2544,7 +2589,7 @@
{
struct pci_attach_args *pa = &sc->bge_pa;
u_int32_t cachesize, command, pcistate, new_pcistate;
- int i, val = 0;
+ int i, val;
/* Save some important PCI state. */
cachesize = pci_conf_read(pa->pa_pc, pa->pa_tag, BGE_PCI_CACHESZ);
@@ -2555,12 +2600,42 @@
BGE_PCIMISCCTL_INDIRECT_ACCESS|BGE_PCIMISCCTL_MASK_PCI_INTR|
BGE_HIF_SWAP_OPTIONS|BGE_PCIMISCCTL_PCISTATE_RW);
+ val = BGE_MISCCFG_RESET_CORE_CLOCKS | (65<<1);
+ /*
+ * XXX: from FreeBSD/Linux; no documentation
+ */
+ if (sc->bge_pcie) {
+ if (CSR_READ_4(sc, BGE_PCIE_CTL1) == 0x60)
+ CSR_WRITE_4(sc, BGE_PCIE_CTL1, 0x20);
+ if (sc->bge_chipid != BGE_CHIPID_BCM5750_A0) {
+ /* No idea what that actually means */
+ CSR_WRITE_4(sc, BGE_MISC_CFG, 1 << 29);
+ val |= (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, val);
DELAY(1000);
+ /*
+ * XXX: from FreeBSD/Linux; no documentation
+ */
+ if (sc->bge_pcie) {
+ if (sc->bge_chipid == BGE_CHIPID_BCM5750_A0) {
+ pcireg_t reg;
+
+ DELAY(500000);
+ /* XXX: Magic Numbers */
+ reg = pci_conf_read(pa->pa_pc, pa->pa_tag, BGE_PCI_UNKNOWN0);
+ pci_conf_write(pa->pa_pc, pa->pa_tag, BGE_PCI_UNKNOWN0,
+ reg | (1 << 15));
+ }
+ /* XXX: Magic Numbers */
+ pci_conf_write(pa->pa_pc, pa->pa_tag, BGE_PCI_UNKNOWN1, 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|
@@ -2621,6 +2696,10 @@
sc->bge_dev.dv_xname);
}
+ /* XXX: from FreeBSD/Linux; no documentation */
+ if (sc->bge_pcie && sc->bge_chipid != BGE_CHIPID_BCM5750_A0)
+ CSR_WRITE_4(sc, BGE_PCIE_CTL0, CSR_READ_4(sc, BGE_PCIE_CTL0) | (1<<25));
+
/* Enable memory arbiter. */
if ((sc->bge_quirks & BGE_QUIRK_5705_CORE) == 0) {
CSR_WRITE_4(sc, BGE_MARB_MODE, BGE_MARBMODE_ENABLE);
Index: if_bgereg.h
===================================================================
RCS file: /cvsroot/src/sys/dev/pci/if_bgereg.h,v
retrieving revision 1.21
diff -u -r1.21 if_bgereg.h
--- if_bgereg.h 15 May 2004 22:19:27 -0000 1.21
+++ if_bgereg.h 22 Oct 2004 15:04:37 -0000
@@ -192,6 +192,9 @@
#define BGE_PCI_UNDI_TX_BD_PRODIDX_LO 0xAC
#define BGE_PCI_ISR_MBX_HI 0xB0
#define BGE_PCI_ISR_MBX_LO 0xB4
+/* XXX: used in PCI-Express code for 575x chips */
+#define BGE_PCI_UNKNOWN0 0xC4
+#define BGE_PCI_UNKNOWN1 0xD8
/* PCI Misc. Host control register */
#define BGE_PCIMISCCTL_CLEAR_INTA 0x00000001
@@ -244,6 +247,8 @@
#define BGE_CHIPID_BCM5705_A1 0x30010000
#define BGE_CHIPID_BCM5705_A2 0x30020000
#define BGE_CHIPID_BCM5705_A3 0x30030000
+#define BGE_CHIPID_BCM5750_A0 0x40000000
+#define BGE_CHIPID_BCM5750_A1 0x40010000
/* shorthand one */
#define BGE_ASICREV(x) ((x) >> 28)
@@ -252,6 +257,7 @@
#define BGE_ASICREV_BCM5703 0x01
#define BGE_ASICREV_BCM5704 0x02
#define BGE_ASICREV_BCM5705 0x03
+#define BGE_ASICREV_BCM5750 0x04
/* chip revisions */
#define BGE_CHIPREV(x) ((x) >> 24)
@@ -1608,6 +1614,12 @@
#define BGE_EE_CTL 0x6840
#define BGE_MDI_CTL 0x6844
#define BGE_EE_DELAY 0x6848
+/*
+ * XXX: Those names are made up as I have no documentation about it;
+ * I only know it is only used in the PCI-Express case.
+ */
+#define BGE_PCIE_CTL0 0x7c00
+#define BGE_PCIE_CTL1 0x7e2c
/* Mode control register */
#define BGE_MODECTL_INT_SNDCOAL_ONLY 0x00000001
@@ -2313,6 +2325,7 @@
u_int8_t bge_extram; /* has external SSRAM */
u_int8_t bge_tbi;
u_int8_t bge_rx_alignment_bug;
+ u_int8_t bge_pcie; /* on a PCI Express port */
u_int32_t bge_return_ring_cnt;
bus_dma_tag_t bge_dmatag;
u_int32_t bge_chipid;
--Multipart=_Fri__22_Oct_2004_17_17_19_+0200_anxmFZKyaP/PHT5H--