From owner-svn-src-head@FreeBSD.ORG Mon May 3 20:57:16 2010 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id D77FB106566C; Mon, 3 May 2010 20:57:16 +0000 (UTC) (envelope-from marius@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [69.147.83.44]) by mx1.freebsd.org (Postfix) with ESMTP id C5B518FC12; Mon, 3 May 2010 20:57:16 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id o43KvGYg091476; Mon, 3 May 2010 20:57:16 GMT (envelope-from marius@svn.freebsd.org) Received: (from marius@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o43KvGaF091473; Mon, 3 May 2010 20:57:16 GMT (envelope-from marius@svn.freebsd.org) Message-Id: <201005032057.o43KvGaF091473@svn.freebsd.org> From: Marius Strobl Date: Mon, 3 May 2010 20:57:16 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r207585 - head/sys/dev/cas X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 03 May 2010 20:57:17 -0000 Author: marius Date: Mon May 3 20:57:16 2010 New Revision: 207585 URL: http://svn.freebsd.org/changeset/base/207585 Log: - Don't set CAS_PCS_DATAPATH to anything except CAS_PCS_DATAPATH_SERDES on Cassini using the external PCS SERDES otherwise unaligned access traps and other strange effects happen with some machines. Don't touch the MIF which is unused in that case either. These changes require the PHY type to use to be determined via the OFW device tree or from the VPD in machines without the former. - Disable the SERDES pins of Saturn when not used in order to save power and ensure they are enabled otherwise. - In cas_attach() use the correct register offset for CAS_PCS_CONF_EN. - Add some bus space barriers missing in the PCS code path. These changes make the Sun GigaSwift Ethernet 1.0 MMF cards as well as the on-board interfaces found in Sun Fire B100s Blade Server work. PR: 144867 Modified: head/sys/dev/cas/if_cas.c head/sys/dev/cas/if_casreg.h Modified: head/sys/dev/cas/if_cas.c ============================================================================== --- head/sys/dev/cas/if_cas.c Mon May 3 20:31:13 2010 (r207584) +++ head/sys/dev/cas/if_cas.c Mon May 3 20:57:16 2010 (r207585) @@ -76,6 +76,7 @@ __FBSDID("$FreeBSD$"); #include #if defined(__powerpc__) || defined(__sparc64__) +#include #include #include #endif @@ -321,55 +322,82 @@ cas_attach(struct cas_softc *sc) } } - CAS_WRITE_4(sc, CAS_PCS_DATAPATH, CAS_PCS_DATAPATH_MII); - - cas_mifinit(sc); - - /* - * Look for an external PHY. - */ - error = ENXIO; - v = CAS_READ_4(sc, CAS_MIF_CONF); - if ((v & CAS_MIF_CONF_MDI1) != 0) { - v |= CAS_MIF_CONF_PHY_SELECT; - CAS_WRITE_4(sc, CAS_MIF_CONF, v); - switch (sc->sc_variant) { - default: - sc->sc_phyad = -1; - break; + if ((sc->sc_flags & CAS_SERDES) == 0) { + CAS_WRITE_4(sc, CAS_PCS_DATAPATH, CAS_PCS_DATAPATH_MII); + CAS_BARRIER(sc, CAS_PCS_DATAPATH, 4, + BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); + cas_mifinit(sc); + /* + * Look for an external PHY. + */ + error = ENXIO; + v = CAS_READ_4(sc, CAS_MIF_CONF); + if ((v & CAS_MIF_CONF_MDI1) != 0) { + v |= CAS_MIF_CONF_PHY_SELECT; + CAS_WRITE_4(sc, CAS_MIF_CONF, v); + CAS_BARRIER(sc, CAS_MIF_CONF, 4, + BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); + /* Enable/unfreeze the GMII pins of Saturn. */ + if (sc->sc_variant == CAS_SATURN) { + CAS_WRITE_4(sc, CAS_SATURN_PCFG, 0); + CAS_BARRIER(sc, CAS_SATURN_PCFG, 4, + BUS_SPACE_BARRIER_READ | + BUS_SPACE_BARRIER_WRITE); + } + switch (sc->sc_variant) { + default: + sc->sc_phyad = -1; + break; + } + error = mii_phy_probe(sc->sc_dev, &sc->sc_miibus, + cas_mediachange, cas_mediastatus); } - error = mii_phy_probe(sc->sc_dev, &sc->sc_miibus, - cas_mediachange, cas_mediastatus); - } - - /* - * Fall back on an internal PHY if no external PHY was found. - */ - if (error != 0 && (v & CAS_MIF_CONF_MDI0) != 0) { - v &= ~CAS_MIF_CONF_PHY_SELECT; - CAS_WRITE_4(sc, CAS_MIF_CONF, v); - switch (sc->sc_variant) { - default: - sc->sc_phyad = -1; - break; + /* + * Fall back on an internal PHY if no external PHY was found. + */ + if (error != 0 && (v & CAS_MIF_CONF_MDI0) != 0) { + v &= ~CAS_MIF_CONF_PHY_SELECT; + CAS_WRITE_4(sc, CAS_MIF_CONF, v); + CAS_BARRIER(sc, CAS_MIF_CONF, 4, + BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); + /* Freeze the GMII pins of Saturn for saving power. */ + if (sc->sc_variant == CAS_SATURN) { + CAS_WRITE_4(sc, CAS_SATURN_PCFG, + CAS_SATURN_PCFG_FSI); + CAS_BARRIER(sc, CAS_SATURN_PCFG, 4, + BUS_SPACE_BARRIER_READ | + BUS_SPACE_BARRIER_WRITE); + } + switch (sc->sc_variant) { + default: + sc->sc_phyad = -1; + break; + } + error = mii_phy_probe(sc->sc_dev, &sc->sc_miibus, + cas_mediachange, cas_mediastatus); } - error = mii_phy_probe(sc->sc_dev, &sc->sc_miibus, - cas_mediachange, cas_mediastatus); - } - - /* - * Try the external PCS SERDES if we didn't find any PHYs. - */ - if (error != 0) { + } else { + /* + * Use the external PCS SERDES. + */ CAS_WRITE_4(sc, CAS_PCS_DATAPATH, CAS_PCS_DATAPATH_SERDES); + CAS_BARRIER(sc, CAS_PCS_DATAPATH, 4, BUS_SPACE_BARRIER_WRITE); + /* Enable/unfreeze the SERDES pins of Saturn. */ + if (sc->sc_variant == CAS_SATURN) { + CAS_WRITE_4(sc, CAS_SATURN_PCFG, 0); + CAS_BARRIER(sc, CAS_SATURN_PCFG, 4, + BUS_SPACE_BARRIER_WRITE); + } CAS_WRITE_4(sc, CAS_PCS_SERDES_CTRL, CAS_PCS_SERDES_CTRL_ESD); - CAS_WRITE_4(sc, CAS_PCS_CONF_EN, CAS_PCS_CONF_EN); - sc->sc_flags |= CAS_SERDES; + CAS_BARRIER(sc, CAS_PCS_SERDES_CTRL, 4, + BUS_SPACE_BARRIER_WRITE); + CAS_WRITE_4(sc, CAS_PCS_CONF, CAS_PCS_CONF_EN); + CAS_BARRIER(sc, CAS_PCS_CONF, 4, + BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); sc->sc_phyad = CAS_PHYAD_EXTERNAL; error = mii_phy_probe(sc->sc_dev, &sc->sc_miibus, cas_mediachange, cas_mediastatus); } - if (error != 0) { device_printf(sc->sc_dev, "PHY probe failed: %d\n", error); goto fail_rxmap; @@ -956,8 +984,9 @@ cas_init_locked(struct cas_softc *sc) __func__); #endif - /* Re-initialize the MIF. */ - cas_mifinit(sc); + if ((sc->sc_flags & CAS_SERDES) == 0) + /* Re-initialize the MIF. */ + cas_mifinit(sc); /* step 3. Setup data structures in host memory. */ cas_meminit(sc); @@ -2105,6 +2134,8 @@ cas_mifinit(struct cas_softc *sc) /* Configure the MIF in frame mode. */ CAS_WRITE_4(sc, CAS_MIF_CONF, CAS_READ_4(sc, CAS_MIF_CONF) & ~CAS_MIF_CONF_BB_MODE); + CAS_BARRIER(sc, CAS_MIF_CONF, 4, + BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); } /* @@ -2219,10 +2250,16 @@ cas_mii_writereg(device_t dev, int phy, CAS_BARRIER(sc, CAS_PCS_CONF, 4, BUS_SPACE_BARRIER_WRITE); CAS_WRITE_4(sc, CAS_PCS_ANAR, val); + CAS_BARRIER(sc, CAS_PCS_ANAR, 4, + BUS_SPACE_BARRIER_WRITE); CAS_WRITE_4(sc, CAS_PCS_SERDES_CTRL, CAS_PCS_SERDES_CTRL_ESD); + CAS_BARRIER(sc, CAS_PCS_CONF, 4, + BUS_SPACE_BARRIER_WRITE); CAS_WRITE_4(sc, CAS_PCS_CONF, CAS_PCS_CONF_EN); + CAS_BARRIER(sc, CAS_PCS_CONF, 4, + BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); return (0); case MII_ANLPAR: reg = CAS_PCS_ANLPAR; @@ -2233,6 +2270,8 @@ cas_mii_writereg(device_t dev, int phy, return (0); } CAS_WRITE_4(sc, reg, val); + CAS_BARRIER(sc, reg, 4, + BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); return (0); } @@ -2630,15 +2669,20 @@ static struct resource_spec cas_pci_res_ { -1, 0 } }; +#define CAS_LOCAL_MAC_ADDRESS "local-mac-address" +#define CAS_PHY_INTERFACE "phy-interface" +#define CAS_PHY_TYPE "phy-type" +#define CAS_PHY_TYPE_PCS "pcs" + static int cas_pci_attach(device_t dev) { + char buf[sizeof(CAS_LOCAL_MAC_ADDRESS)]; struct cas_softc *sc; int i; #if !(defined(__powerpc__) || defined(__sparc64__)) u_char enaddr[4][ETHER_ADDR_LEN]; - char lma[sizeof("local-mac-address")]; - int found, j; + u_int j, k, lma, pcs[4], phy; #endif sc = device_get_softc(dev); @@ -2679,13 +2723,20 @@ cas_pci_attach(device_t dev) #if defined(__powerpc__) || defined(__sparc64__) OF_getetheraddr(dev, sc->sc_enaddr); + if (OF_getprop(ofw_bus_get_node(dev), CAS_PHY_INTERFACE, buf, + sizeof(buf)) > 0 || OF_getprop(ofw_bus_get_node(dev), + CAS_PHY_TYPE, buf, sizeof(buf)) > 0) { + buf[sizeof(buf) - 1] = '\0'; + if (strcmp(buf, CAS_PHY_TYPE_PCS) == 0) + sc->sc_flags |= CAS_SERDES; + } #else /* - * Dig out VPD (vital product data) and read the MAX address. - * The VPD resides in the PCI Expansion ROM (PCI FCode) and - * can't be accessed via the PCI capability pointer. - * SUNW,pci-ce and SUNW,pci-qge use the Enhanced VPD format - * described in US Patent 7149820. + * Dig out VPD (vital product data) and read the MAC address as well + * as the PHY type. The VPD resides in the PCI Expansion ROM (PCI + * FCode) and can't be accessed via the PCI capability pointer. + * SUNW,pci-ce and SUNW,pci-qge use the Enhanced VPD format described + * in the free US Patent 7149820. */ #define PCI_ROMHDR_SIZE 0x1c @@ -2719,7 +2770,10 @@ cas_pci_attach(device_t dev) #define CAS_ROM_READ_4(sc, offs) \ CAS_READ_4((sc), CAS_PCI_ROM_OFFSET + (offs)) - found = 0; + lma = phy = 0; + memset(enaddr, 0, sizeof(enaddr)); + memset(pcs, 0, sizeof(pcs)); + /* Enable PCI Expansion ROM access. */ CAS_WRITE_4(sc, CAS_BIM_LDEV_OEN, CAS_BIM_LDEV_OEN_PAD | CAS_BIM_LDEV_OEN_PROM); @@ -2768,23 +2822,51 @@ cas_pci_attach(device_t dev) if (CAS_ROM_READ_1(sc, j + PCI_VPD_SIZE) != 'I') /* no instance property */ continue; - if (CAS_ROM_READ_1(sc, j + PCI_VPD_SIZE + 3) != 'B') - /* no byte array */ - continue; - if (CAS_ROM_READ_1(sc, j + PCI_VPD_SIZE + 4) != - ETHER_ADDR_LEN) - continue; - bus_read_region_1(sc->sc_res[CAS_RES_MEM], - CAS_PCI_ROM_OFFSET + j + PCI_VPD_SIZE + 5, - lma, sizeof(lma)); - if (strcmp(lma, "local-mac-address") != 0) - continue; - bus_read_region_1(sc->sc_res[CAS_RES_MEM], - CAS_PCI_ROM_OFFSET + j + PCI_VPD_SIZE + 5 + - sizeof(lma), enaddr[found], - sizeof(enaddr[found])); - if (found++ == 4) - break; + if (CAS_ROM_READ_1(sc, j + PCI_VPD_SIZE + 3) == 'B') { + /* byte array */ + if (CAS_ROM_READ_1(sc, + j + PCI_VPD_SIZE + 4) != ETHER_ADDR_LEN) + continue; + bus_read_region_1(sc->sc_res[CAS_RES_MEM], + CAS_PCI_ROM_OFFSET + j + PCI_VPD_SIZE + 5, + buf, sizeof(buf)); + buf[sizeof(buf) - 1] = '\0'; + if (strcmp(buf, CAS_LOCAL_MAC_ADDRESS) != 0) + continue; + bus_read_region_1(sc->sc_res[CAS_RES_MEM], + CAS_PCI_ROM_OFFSET + j + PCI_VPD_SIZE + + 5 + sizeof(CAS_LOCAL_MAC_ADDRESS), + enaddr[lma], sizeof(enaddr[lma])); + lma++; + if (lma == 4 && phy == 4) + break; + } else if (CAS_ROM_READ_1(sc, j + PCI_VPD_SIZE + 3) == + 'S') { + /* string */ + if (CAS_ROM_READ_1(sc, + j + PCI_VPD_SIZE + 4) != + sizeof(CAS_PHY_TYPE_PCS)) + continue; + bus_read_region_1(sc->sc_res[CAS_RES_MEM], + CAS_PCI_ROM_OFFSET + j + PCI_VPD_SIZE + 5, + buf, sizeof(buf)); + buf[sizeof(buf) - 1] = '\0'; + if (strcmp(buf, CAS_PHY_INTERFACE) == 0) + k = sizeof(CAS_PHY_INTERFACE); + else if (strcmp(buf, CAS_PHY_TYPE) == 0) + k = sizeof(CAS_PHY_TYPE); + else + continue; + bus_read_region_1(sc->sc_res[CAS_RES_MEM], + CAS_PCI_ROM_OFFSET + j + PCI_VPD_SIZE + + 5 + k, buf, sizeof(buf)); + buf[sizeof(buf) - 1] = '\0'; + if (strcmp(buf, CAS_PHY_TYPE_PCS) == 0) + pcs[phy] = 1; + phy++; + if (lma == 4 && phy == 4) + break; + } } break; default: @@ -2795,14 +2877,24 @@ cas_pci_attach(device_t dev) fail_prom: CAS_WRITE_4(sc, CAS_BIM_LDEV_OEN, 0); - if (found == 0) { + if (lma == 0) { device_printf(dev, "could not determine Ethernet address\n"); goto fail; } i = 0; - if (found > 1 && pci_get_slot(dev) < sizeof(enaddr) / sizeof(*enaddr)) + if (lma > 1 && pci_get_slot(dev) < sizeof(enaddr) / sizeof(*enaddr)) i = pci_get_slot(dev); memcpy(sc->sc_enaddr, enaddr[i], ETHER_ADDR_LEN); + + if (phy == 0) { + device_printf(dev, "could not determine PHY type\n"); + goto fail; + } + i = 0; + if (phy > 1 && pci_get_slot(dev) < sizeof(pcs) / sizeof(*pcs)) + i = pci_get_slot(dev); + if (pcs[i] != 0) + sc->sc_flags |= CAS_SERDES; #endif if (cas_attach(sc) != 0) { Modified: head/sys/dev/cas/if_casreg.h ============================================================================== --- head/sys/dev/cas/if_casreg.h Mon May 3 20:31:13 2010 (r207584) +++ head/sys/dev/cas/if_casreg.h Mon May 3 20:57:16 2010 (r207585) @@ -68,6 +68,7 @@ #define CAS_STATUS4 0x105c /* interrupt status 4 for INTD */ #define CAS_CLEAR_ALIAS4 0x1060 /* clear mask alias 4 for INTD */ #define CAS_STATUS_ALIAS4 0x1064 /* interrupt status alias 4 for INTD */ +#define CAS_SATURN_PCFG 0x106c /* internal MACPHY pin configuration */ #define CAS_CAW_RX_WGHT_MASK 0x00000003 /* RX DMA factor for... */ #define CAS_CAW_RX_WGHT_SHFT 0 /* ...weighted round robin */ @@ -171,6 +172,17 @@ /* INTn enable bit for CAS_INTMASK[2-4] */ #define CAS_INTMASKN_EN 0x00000080 /* INT[B-D] enable */ +#define CAS_SATURN_PCFG_TLA 0x00000001 /* PHY activity LED */ +#define CAS_SATURN_PCFG_FLA 0x00000002 /* PHY 10MBit/sec LED */ +#define CAS_SATURN_PCFG_CLA 0x00000004 /* PHY 100MBit/sec LED */ +#define CAS_SATURN_PCFG_LLA 0x00000008 /* PHY 1000MBit/sec LED */ +#define CAS_SATURN_PCFG_RLA 0x00000010 /* PHY full-duplex LED */ +#define CAS_SATURN_PCFG_PDS 0x00000020 /* PHY debug mode */ +#define CAS_SATURN_PCFG_MTP 0x00000080 /* test point select */ +#define CAS_SATURN_PCFG_GMO 0x00000100 /* GMII observe */ +#define CAS_SATURN_PCFG_FSI 0x00000200 /* freeze GMII/SERDES */ +#define CAS_SATURN_PCFG_LAD 0x00000800 /* MAC LED control active low */ + /* TX DMA registers */ #define CAS_TX_CONF 0x2004 /* TX configuration */ #define CAS_TX_FIFO_WR 0x2014 /* FIFO write pointer */