Add support for the SMC91C111 chip, with its internal PHY.

This commit is contained in:
scw 2003-04-29 08:47:29 +00:00
parent 3f3b3242de
commit f95724bd6b
3 changed files with 88 additions and 12 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: smc91cxx.c,v 1.44 2002/10/22 00:01:57 fair Exp $ */
/* $NetBSD: smc91cxx.c,v 1.45 2003/04/29 08:47:29 scw Exp $ */
/*-
* Copyright (c) 1997 The NetBSD Foundation, Inc.
@ -78,7 +78,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: smc91cxx.c,v 1.44 2002/10/22 00:01:57 fair Exp $");
__KERNEL_RCSID(0, "$NetBSD: smc91cxx.c,v 1.45 2003/04/29 08:47:29 scw Exp $");
#include "opt_inet.h"
#include "opt_ccitt.h"
@ -165,7 +165,7 @@ const char *smc91cxx_idstrs[] = {
NULL, /* 6 */
"SMC91C100", /* 7 */
"SMC91C100FD", /* 8 */
NULL, /* 9 */
"SMC91C111", /* 9 */
NULL, /* 10 */
NULL, /* 11 */
NULL, /* 12 */
@ -245,7 +245,7 @@ smc91cxx_attach(sc, myea)
u_int32_t miicapabilities;
u_int16_t tmp;
u_int8_t enaddr[ETHER_ADDR_LEN];
int i, aui, mult, memsize;
int i, aui, mult, scale, memsize;
char pbuf[9];
/* Make sure the chip is stopped. */
@ -268,10 +268,19 @@ smc91cxx_attach(sc, myea)
printf("revision %d, ", RR_REV(tmp));
SMC_SELECT_BANK(sc, 0);
mult = MCR_MEM_MULT(bus_space_read_2(bst, bsh, MEM_CFG_REG_W));
switch (sc->sc_chipid) {
default:
mult = MCR_MEM_MULT(bus_space_read_2(bst, bsh, MEM_CFG_REG_W));
scale = MIR_SCALE_91C9x;
break;
case CHIP_91C111:
mult = MIR_MULT_91C111;
scale = MIR_SCALE_91C111;
}
memsize = bus_space_read_2(bst, bsh, MEM_INFO_REG_W) & MIR_TOTAL_MASK;
if (memsize == 255) memsize++;
memsize *= 256 * mult;
memsize *= scale * mult;
format_bytes(pbuf, sizeof(pbuf), memsize);
printf("buffer size: %s\n", pbuf);
@ -325,8 +334,15 @@ smc91cxx_attach(sc, myea)
*/
miicapabilities &= ~(BMSR_100TXFDX | BMSR_10TFDX);
case CHIP_91100FD:
case CHIP_91C111:
if (tmp & CR_MII_SELECT) {
printf("default media MII\n");
printf("default media MII");
if (sc->sc_chipid == CHIP_91C111) {
printf(" (%s PHY)\n", (tmp & CR_AUI_SELECT) ?
"external" : "internal");
sc->sc_internal_phy = !(tmp & CR_AUI_SELECT);
} else
printf("\n");
mii_attach(&sc->sc_dev, &sc->sc_mii, miicapabilities,
MII_PHY_ANY, MII_OFFSET_ANY, 0);
if (LIST_FIRST(&sc->sc_mii.mii_phys) == NULL) {
@ -340,6 +356,14 @@ smc91cxx_attach(sc, myea)
}
sc->sc_flags |= SMC_FLAGS_HAS_MII;
break;
} else
if (sc->sc_chipid == CHIP_91C111) {
/*
* XXX: Should bring it out of low-power mode
*/
printf("EPH interface in low power mode\n");
sc->sc_internal_phy = 0;
return;
}
/*FALLTHROUGH*/
default:
@ -510,6 +534,19 @@ smc91cxx_init(sc)
*/
bus_space_write_1(bst, bsh, INTR_MASK_REG_B, 0);
/*
* On the 91c111, enable auto-negotiation, and set the LED
* status pins to something sane.
* XXX: Should be some way for MD code to decide the latter.
*/
SMC_SELECT_BANK(sc, 0);
if (sc->sc_chipid == CHIP_91C111) {
bus_space_write_2(bst, bsh, RX_PHY_CONTROL_REG_W,
RPC_ANEG |
(RPC_LS_LINK_DETECT << RPC_LSA_SHIFT) |
(RPC_LS_TXRX << RPC_LSB_SHIFT));
}
/*
* Set current media.
*/
@ -551,8 +588,14 @@ smc91cxx_init(sc)
*/
SMC_SELECT_BANK(sc, 2);
bus_space_write_1(bst, bsh, INTR_MASK_REG_B,
IM_EPH_INT | IM_RX_OVRN_INT | IM_RCV_INT | IM_TX_INT);
if (sc->sc_chipid == CHIP_91C111 && sc->sc_internal_phy) {
bus_space_write_1(bst, bsh, INTR_MASK_REG_B,
IM_EPH_INT | IM_RX_OVRN_INT |
IM_RCV_INT | IM_TX_INT | IM_MD_INT);
} else {
bus_space_write_1(bst, bsh, INTR_MASK_REG_B,
IM_EPH_INT | IM_RX_OVRN_INT | IM_RCV_INT | IM_TX_INT);
}
/* Interface is now running, with no output active. */
ifp->if_flags |= IFF_RUNNING;
@ -996,6 +1039,14 @@ smc91cxx_intr(arg)
ifp->if_timer = 0;
}
if (sc->sc_chipid == CHIP_91C111 && sc->sc_internal_phy &&
(status & IM_MD_INT)) {
/*
* Internal PHY status change
*/
mii_tick(&sc->sc_mii);
}
/*
* Other errors. Reset the interface.
*/

View File

@ -1,4 +1,4 @@
/* $NetBSD: smc91cxxreg.h,v 1.4 2001/06/12 15:17:23 wiz Exp $ */
/* $NetBSD: smc91cxxreg.h,v 1.5 2003/04/29 08:47:30 scw Exp $ */
/*
* Copyright (c) 1996 Gardner Buchanan <gbuchanan@shl.com>
@ -172,16 +172,38 @@
#define MIR_FREE_MASK 0xff00 /* Free memory pages available */
#define MIR_TOTAL_MASK 0x00ff /* Total memory pages available */
#define MIR_MULT_91C111 1
#define MIR_SCALE_91C9x 256
#define MIR_SCALE_91C111 2048
/*
* Memory Configuration
*/
#define MEM_CFG_REG_W 0x0a
#define MEM_CFG_REG_W 0x0a
#define MCR_MEM_MULT(x) (((x)>>9)&7) /* Memory size multiplier */
#define MCR_TXRSV_MASK 0x001f /* Count of pages reserved for transmit */
/*
* Receive/PHY Control Register (SM91C111 only)
*/
#define RX_PHY_CONTROL_REG_W 0x0a /* 91C111 only */
#define RPC_LSB_SHIFT 2 /* Shift for LED-B select bits */
#define RPC_LSA_SHIFT 5 /* Shift for LED-A select bits */
#define RPC_LS_MASK 0x7 /* LED Select mask */
#define RPC_LS_LINK_DETECT 0x0 /* 10/100 link detected */
#define RPC_LS_LINK_10MBPS 0x2 /* 10 MBPS link detected */
#define RPC_LS_FULL_DUPLEX 0x3 /* Full duplex operation */
#define RPC_LS_TXRX 0x4 /* Tx/Rx packet */
#define RPC_LS_LINK_100MBPS 0x5 /* 100 MBPS link detected */
#define RPC_LS_RX 0x6 /* Rx packet */
#define RPC_LS_TX 0x7 /* Tx packet */
#define RPC_ANEG 0x0800 /* Autonegotiate enable */
#define RPC_DPLX 0x1000 /* Duplex select (set = Full) */
#define RPC_SPEED 0x2000 /* Speed (set = 100mbps) */
/*
* Bank 0, Register 0x0c is unused in the SMC91C92
@ -346,6 +368,7 @@
#define IM_RX_OVRN_INT 0x10 /* Receiver was overrun */
#define IM_EPH_INT 0x20 /* Misc. EPH conditions (see CONTROL_REG_W) */
#define IM_ERCV_INT 0x40 /* not on SMC9192 */
#define IM_MD_INT 0x80 /* SMC91C111 Internal PHY status change */
/*
@ -396,6 +419,7 @@
#define CHIP_9195 5
#define CHIP_91100 7
#define CHIP_91100FD 8
#define CHIP_91C111 9
/*

View File

@ -1,4 +1,4 @@
/* $NetBSD: smc91cxxvar.h,v 1.10 2002/09/04 14:54:37 scw Exp $ */
/* $NetBSD: smc91cxxvar.h,v 1.11 2003/04/29 08:47:30 scw Exp $ */
/*-
* Copyright (c) 1997 The NetBSD Foundation, Inc.
@ -63,6 +63,7 @@ struct smc91cxx_softc {
#define SMC_FLAGS_32BIT_READ 0x0008 /* reads are always 32-bits */
u_int8_t sc_chipid;
u_int8_t sc_internal_phy; /* 91C111 only */
#if NRND > 0
rndsource_element_t rnd_source;