Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/pci Add support for the SPI EEPROM found on the newe...
details: https://anonhg.NetBSD.org/src/rev/e50102fed0a8
branches: trunk
changeset: 553889:e50102fed0a8
user: thorpej <thorpej%NetBSD.org@localhost>
date: Wed Oct 22 15:50:39 2003 +0000
description:
Add support for the SPI EEPROM found on the newer i82541 and i82547
chips. Add the i82541 and i82547 product IDs to the table, #if 0'd
out, for now (there are still more changes to come for these new chips
to work properly).
diffstat:
sys/dev/pci/if_wm.c | 123 ++++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 119 insertions(+), 4 deletions(-)
diffs (180 lines):
diff -r 7ea397ca4f48 -r e50102fed0a8 sys/dev/pci/if_wm.c
--- a/sys/dev/pci/if_wm.c Wed Oct 22 15:40:19 2003 +0000
+++ b/sys/dev/pci/if_wm.c Wed Oct 22 15:50:39 2003 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: if_wm.c,v 1.56 2003/10/21 16:52:08 thorpej Exp $ */
+/* $NetBSD: if_wm.c,v 1.57 2003/10/22 15:50:39 thorpej Exp $ */
/*
* Copyright (c) 2001, 2002, 2003 Wasabi Systems, Inc.
@@ -46,7 +46,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.56 2003/10/21 16:52:08 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.57 2003/10/22 15:50:39 thorpej Exp $");
#include "bpfilter.h"
#include "rnd.h"
@@ -322,6 +322,7 @@
/* sc_flags */
#define WM_F_HAS_MII 0x01 /* has MII */
#define WM_F_EEPROM_HANDSHAKE 0x02 /* requires EEPROM handshake */
+#define WM_F_EEPROM_SPI 0x04 /* EEPROM is SPI */
#define WM_F_IOH_VALID 0x10 /* I/O handle is valid */
#define WM_F_BUS64 0x20 /* bus is 64-bit */
#define WM_F_PCIX 0x40 /* bus is PCI-X */
@@ -555,6 +556,31 @@
"Intel i82546GB Gigabit Ethernet (SERDES)",
WM_T_82546_3, WMP_F_SERDES },
#endif
+#if 0 /* not yet... */
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82541EI_MOBILE,
+ "Intel i82541EI Mobile 1000BASE-T Ethernet",
+ WM_T_82541, WMP_F_1000T },
+
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82541ER,
+ "Intel i82541ER 1000BASE-T Ethernet",
+ WM_T_82541_2, WMP_F_1000T },
+
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82541GI,
+ "Intel i82541GI 1000BASE-T Ethernet",
+ WM_T_82541_2, WMP_F_1000T },
+
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82541GI_MOBILE,
+ "Intel i82541GI Mobile 1000BASE-T Ethernet",
+ WM_T_82541_2, WMP_F_1000T },
+
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82547EI,
+ "Intel i82547EI 1000BASE-T Ethernet",
+ WM_T_82547, WMP_F_1000T },
+
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82547GI,
+ "Intel i82547GI 1000BASE-T Ethernet",
+ WM_T_82547_2, WMP_F_1000T },
+#endif /* not yet... */
{ 0, 0,
NULL,
0, 0 },
@@ -926,7 +952,6 @@
/*
* Get some information about the EEPROM.
*/
- eetype = "MicroWire";
if (sc->sc_type >= WM_T_82540)
sc->sc_flags |= WM_F_EEPROM_HANDSHAKE;
if (sc->sc_type <= WM_T_82544)
@@ -937,7 +962,23 @@
sc->sc_ee_addrbits = 8;
else
sc->sc_ee_addrbits = 6;
+ } else if (sc->sc_type <= WM_T_82547_2) {
+ reg = CSR_READ(sc, WMREG_EECD);
+ if (reg & EECD_EE_TYPE) {
+ sc->sc_flags |= WM_F_EEPROM_SPI;
+ sc->sc_ee_addrbits = (reg & EECD_EE_ABITS) ? 16 : 8;
+ } else
+ sc->sc_ee_addrbits = (reg & EECD_EE_ABITS) ? 8 : 6;
+ } else {
+ /* Assume everything else is SPI. */
+ reg = CSR_READ(sc, WMREG_EECD);
+ sc->sc_flags |= WM_F_EEPROM_SPI;
+ sc->sc_ee_addrbits = (reg & EECD_EE_ABITS) ? 16 : 8;
}
+ if (sc->sc_flags & WM_F_EEPROM_SPI)
+ eetype = "SPI";
+ else
+ eetype = "MicroWire";
aprint_verbose("%s: %u word (%d address bits) %s EEPROM\n",
sc->sc_dev.dv_xname, 1U << sc->sc_ee_addrbits,
sc->sc_ee_addrbits, eetype);
@@ -2637,6 +2678,77 @@
}
/*
+ * wm_spi_eeprom_ready:
+ *
+ * Wait for a SPI EEPROM to be ready for commands.
+ */
+static int
+wm_spi_eeprom_ready(struct wm_softc *sc)
+{
+ uint32_t val;
+ int usec;
+
+ for (usec = 0; usec < SPI_MAX_RETRIES; delay(5), usec += 5) {
+ wm_eeprom_sendbits(sc, SPI_OPC_RDSR, 8);
+ wm_eeprom_recvbits(sc, &val, 8);
+ if ((val & SPI_SR_RDY) == 0)
+ break;
+ }
+ if (usec >= SPI_MAX_RETRIES) {
+ aprint_error("%s: EEPROM failed to become ready\n",
+ sc->sc_dev.dv_xname);
+ return (1);
+ }
+ return (0);
+}
+
+/*
+ * wm_read_eeprom_spi:
+ *
+ * Read a work from the EEPROM using the SPI protocol.
+ */
+static int
+wm_read_eeprom_spi(struct wm_softc *sc, int word, int wordcnt, uint16_t *data)
+{
+ uint32_t reg, val;
+ int i;
+ uint8_t opc;
+
+ /* Clear SK and CS. */
+ reg = CSR_READ(sc, WMREG_EECD) & ~(EECD_SK | EECD_CS);
+ CSR_WRITE(sc, WMREG_EECD, reg);
+ delay(2);
+
+ if (wm_spi_eeprom_ready(sc))
+ return (1);
+
+ /* Toggle CS to flush commands. */
+ CSR_WRITE(sc, WMREG_EECD, reg | EECD_CS);
+ delay(2);
+ CSR_WRITE(sc, WMREG_EECD, reg);
+ delay(2);
+
+ opc = SPI_OPC_READ;
+ if (sc->sc_ee_addrbits == 8 && word >= 128)
+ opc |= SPI_OPC_A8;
+
+ wm_eeprom_sendbits(sc, opc, 8);
+ wm_eeprom_sendbits(sc, word << 1, sc->sc_ee_addrbits);
+
+ for (i = 0; i < wordcnt; i++) {
+ wm_eeprom_recvbits(sc, &val, 16);
+ data[i] = ((val >> 8) & 0xff) | ((val & 0xff) << 8);
+ }
+
+ /* Raise CS and clear SK. */
+ reg = (CSR_READ(sc, WMREG_EECD) & ~EECD_SK) | EECD_CS;
+ CSR_WRITE(sc, WMREG_EECD, reg);
+ delay(2);
+
+ return (0);
+}
+
+/*
* wm_read_eeprom:
*
* Read data from the serial EEPROM.
@@ -2649,7 +2761,10 @@
if (wm_acquire_eeprom(sc))
return (1);
- rv = wm_read_eeprom_uwire(sc, word, wordcnt, data);
+ if (sc->sc_flags & WM_F_EEPROM_SPI)
+ rv = wm_read_eeprom_spi(sc, word, wordcnt, data);
+ else
+ rv = wm_read_eeprom_uwire(sc, word, wordcnt, data);
wm_release_eeprom(sc);
return (rv);
Home |
Main Index |
Thread Index |
Old Index