Module Name: src Committed By: nisimura Date: Wed Mar 25 01:39:50 UTC 2020
Modified Files: src/sys/arch/arm/sociox: if_scx.c Log Message: make sure to use mac_write() for GMACxxx registers. try to decode xMII link status report To generate a diff of this commit: cvs rdiff -u -r1.12 -r1.13 src/sys/arch/arm/sociox/if_scx.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/arm/sociox/if_scx.c diff -u src/sys/arch/arm/sociox/if_scx.c:1.12 src/sys/arch/arm/sociox/if_scx.c:1.13 --- src/sys/arch/arm/sociox/if_scx.c:1.12 Tue Mar 24 13:44:21 2020 +++ src/sys/arch/arm/sociox/if_scx.c Wed Mar 25 01:39:49 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: if_scx.c,v 1.12 2020/03/24 13:44:21 nisimura Exp $ */ +/* $NetBSD: if_scx.c,v 1.13 2020/03/25 01:39:49 nisimura Exp $ */ /*- * Copyright (c) 2020 The NetBSD Foundation, Inc. @@ -56,7 +56,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_scx.c,v 1.12 2020/03/24 13:44:21 nisimura Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_scx.c,v 1.13 2020/03/25 01:39:49 nisimura Exp $"); #include <sys/param.h> #include <sys/bus.h> @@ -83,6 +83,7 @@ __KERNEL_RCSID(0, "$NetBSD: if_scx.c,v 1 #include <dev/acpi/acpivar.h> #include <dev/acpi/acpi_intr.h> +/* SC2A11 register block */ #define SWRESET 0x104 #define COMINIT 0x120 #define INTRST 0x200 @@ -124,6 +125,7 @@ __KERNEL_RCSID(0, "$NetBSD: if_scx.c,v 1 #define DESCENG_INIT 0x11fc #define DESCENG_SRST 0x1204 +/* GMAC register block. use mac_write()/mac_read() to handle */ #define GMACMCR 0x0000 /* MAC configuration */ #define MCR_IBN (1U<<30) /* */ #define MCR_CST (1U<<25) /* strip CRC */ @@ -169,13 +171,21 @@ __KERNEL_RCSID(0, "$NetBSD: if_scx.c,v 1 #define GMACMAL0 0x0044 /* MAC address 0 31:0 */ #define GMACMAH(i) ((i)*8+0x40) /* supplimental MAC addr 1 - 15 */ #define GMACMAL(i) ((i)*8+0x44) -#define GMACMDSR 0x00d8 /* GMII/RGMII/MII command/status */ +#define GMACMIISR 0x00d8 /* resolved xMII link status */ + /* 3 link up detected + * 2:1 resovled speed + * 0 2.5Mhz (10Mbps) + * 1 25Mhz (100bps) + * 2 125Mhz (1000Mbps) + * 1 full duplex detected */ + #define GMACMHT0 0x0500 /* multicast hash table 0 - 7 */ #define GMACMHT(i) ((i)*4+0x500) #define GMACVHT 0x0588 /* VLAN tag hash */ #define GMACAMAH(i) ((i)*8+0x800) /* supplimental MAC addr 16-127 */ #define GMACAMAL(i) ((i)*8+0x804) #define GMACEVCNT(i) ((i)*4+0x114) /* event counter 0x114~284 */ +#define GMACEVCTL 0x0100 /* clear event counter registers */ #define GMACBMR 0x1000 /* DMA bus mode control * 24 4PBL @@ -202,8 +212,6 @@ __KERNEL_RCSID(0, "$NetBSD: if_scx.c,v 1 #define OMR_TXE (1U<<13) /* start Tx DMA engine, 0 to stop */ #define OMR_RXE (1U<<1) /* start Rx DMA engine, 0 to stop */ -static int get_mdioclk(uint32_t); - /* descriptor format definition */ struct tdes { uint32_t t0, t1, t2, t3; @@ -390,6 +398,8 @@ static int scx_intr(void *); static void txreap(struct scx_softc *); static void rxintr(struct scx_softc *); static int add_rxbuf(struct scx_softc *, int); + +static int get_mdioclk(uint32_t); static int spin_waitfor(struct scx_softc *, int, int); static int mac_read(struct scx_softc *, int); static void mac_write(struct scx_softc *, int, int); @@ -585,7 +595,7 @@ scx_attach_i(struct scx_softc *sc) csr = bus_space_read_4(sc->sc_st, sc->sc_eesh, 4); enaddr[4] = csr >> 24; enaddr[5] = csr >> 16; - csr = CSR_READ(sc, GMACIMPL); + csr = mac_read(sc, GMACIMPL); aprint_normal_dev(sc->sc_dev, "NetSec GbE (%d.%d) impl (%x.%x)\n", hwver >> 16, hwver & 0xffff, csr >> 16, csr & 0xffff); @@ -747,6 +757,7 @@ scx_reset(struct scx_softc *sc) mac_write(sc, GMACRDLAR, _RDLAR); mac_write(sc, GMACTDLAR, _TDLAR); mac_write(sc, GMACAFR, _AFR); + mac_write(sc, GMACEVCTL, 1); } static int @@ -763,28 +774,43 @@ scx_init(struct ifnet *ifp) /* Reset the chip to a known state. */ scx_reset(sc); - /* build sane Tx and load Rx descriptors with mbuf */ - for (i = 0; i < MD_NTXDESC; i++) - sc->sc_txdescs[i].t0 = T0_OWN; - sc->sc_txdescs[MD_NTXDESC - 1].t0 |= T0_EOD; /* tie off the ring */ - for (i = 0; i < MD_NRXDESC; i++) - (void)add_rxbuf(sc, i); - /* set my address in perfect match slot 0 */ csr = (ea[3] << 24) | (ea[2] << 16) | (ea[1] << 8) | ea[0]; - CSR_WRITE(sc, GMACMAL0, csr); + mac_write(sc, GMACMAL0, csr); csr = (ea[5] << 8) | ea[4]; - CSR_WRITE(sc, GMACMAH0, csr | 1U<<31); /* always valid? */ + mac_write(sc, GMACMAH0, csr | 1U<<31); /* always valid? */ /* accept multicast frame or run promisc mode */ scx_set_rcvfilt(sc); (void)scx_ifmedia_upd(ifp); + /* build sane Tx */ + memset(sc->sc_txdescs, 0, sizeof(struct tdes) * MD_NTXDESC); + sc->sc_txdescs[MD_NTXDESC - 1].t0 |= T0_EOD; /* tie off the ring */ + SCX_CDTXSYNC(sc, 0, MD_NTXDESC, + BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); + sc->sc_txfree = MD_NTXDESC; + sc->sc_txnext = 0; + for (i = 0; i < MD_TXQUEUELEN; i++) + sc->sc_txsoft[i].txs_mbuf = NULL; + sc->sc_txsfree = MD_TXQUEUELEN; + sc->sc_txsnext = 0; + sc->sc_txsdirty = 0; + + /* load Rx descriptors with fresh mbuf */ + for (i = 0; i < MD_NRXDESC; i++) + (void)add_rxbuf(sc, i); + sc->sc_rxptr = 0; + + /* XXX 32 bit paddr XXX hand Tx/Rx rings to HW XXX */ + mac_write(sc, GMACTDLAR, SCX_CDTXADDR(sc, 0)); + mac_write(sc, GMACRDLAR, SCX_CDRXADDR(sc, 0)); + /* kick to start GMAC engine */ - csr = mac_read(sc, GMACOMR); CSR_WRITE(sc, RXINT_CLR, ~0); CSR_WRITE(sc, TXINT_CLR, ~0); + csr = mac_read(sc, GMACOMR); mac_write(sc, GMACOMR, csr | OMR_RXE | OMR_TXE); ifp->if_flags |= IFF_RUNNING; @@ -898,9 +924,9 @@ scx_set_rcvfilt(struct scx_softc *sc) uint32_t csr, crc; int i; - csr = CSR_READ(sc, GMACAFR); + csr = mac_read(sc, GMACAFR); csr &= ~(AFR_PM | AFR_AM | AFR_MHTE); - CSR_WRITE(sc, GMACAFR, csr); + mac_write(sc, GMACAFR, csr); ETHER_LOCK(ec); if (ifp->if_flags & IFF_PROMISC) { @@ -912,7 +938,7 @@ scx_set_rcvfilt(struct scx_softc *sc) /* clear 15 entry supplimental perfect match filter */ for (i = 1; i < 16; i++) - CSR_WRITE(sc, GMACMAH(i), 0); + mac_write(sc, GMACMAH(i), 0); /* build 256 bit multicast hash filter */ memset(mchash, 0, sizeof(mchash)); crc = 0; @@ -940,9 +966,9 @@ printf("[%d] %s\n", i, ether_sprintf(enm uint8_t *ep = enm->enm_addrlo; addr = (ep[3] << 24) | (ep[2] << 16) | (ep[1] << 8) | ep[0]; - CSR_WRITE(sc, GMACMAL(i), addr); + mac_write(sc, GMACMAL(i), addr); addr = (ep[5] << 8) | ep[4]; - CSR_WRITE(sc, GMACMAH(i), addr | 1U<<31); + mac_write(sc, GMACMAH(i), addr | 1U<<31); } else { /* use hash table when too many */ /* bit_reserve_32(~crc) !? */ @@ -958,8 +984,8 @@ printf("[%d] %s\n", i, ether_sprintf(enm if (crc) csr |= AFR_MHTE; for (i = 0; i < __arraycount(mchash); i++) - CSR_WRITE(sc, GMACMHT(i), mchash[i]); - CSR_WRITE(sc, GMACAFR, csr); + mac_write(sc, GMACMHT(i), mchash[i]); + mac_write(sc, GMACAFR, csr); return; update: @@ -968,7 +994,7 @@ printf("[%d] %s\n", i, ether_sprintf(enm csr |= AFR_PM; /* run promisc. mode */ else csr |= AFR_AM; /* accept all multicast */ - CSR_WRITE(sc, GMACAFR, csr); + mac_write(sc, GMACAFR, csr); return; } @@ -1023,7 +1049,16 @@ mii_statchg(struct ifnet *ifp) struct scx_softc *sc = ifp->if_softc; struct mii_data *mii = &sc->sc_mii; uint32_t fcr; - +#if 1 + /* decode MIISR register value */ + uint32_t miisr = mac_read(sc, GMACMIISR); + int spd = (miisr >> 1) & 03; + printf("xMII link status (0x%x) spd%d", miisr, + (spd == 2) ? 1000 : (spd == 1) ? 100 : 10); + if (miisr & 1) + printf(",full-duplex"); + printf("\n"); +#endif /* Get flow control negotiation result. */ if (IFM_SUBTYPE(mii->mii_media.ifm_cur->ifm_media) == IFM_AUTO && (mii->mii_media_active & IFM_ETH_FMASK) != sc->sc_flowflags) @@ -1207,7 +1242,7 @@ scx_start(struct ifnet *ifp) BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); /* Tell DMA start transmit */ - /* CSR_WRITE(sc, GMACTDS, 1); */ + mac_write(sc, GMACTDS, 1); txs->txs_mbuf = m0; txs->txs_firstdesc = sc->sc_txnext; @@ -1241,6 +1276,7 @@ scx_intr(void *arg) struct ifnet *ifp = &sc->sc_ethercom.ec_if; (void)ifp; + /* XXX decode interrupt cause to pick isr() XXX */ rxintr(sc); txreap(sc); return 1; @@ -1388,6 +1424,8 @@ spin_waitfor(struct scx_softc *sc, int r return (loop > 0) ? 0 : ETIMEDOUT; } +/* GMAC register needs to use indirect rd/wr via memory mapped registers. */ + static int mac_read(struct scx_softc *sc, int reg) { @@ -1406,32 +1444,10 @@ mac_write(struct scx_softc *sc, int reg, (void)spin_waitfor(sc, MACCMD, CMD_BUSY); } -static int -get_mdioclk(uint32_t freq) -{ - - const struct { - uint16_t freq, bit; /* GAR 5:2 MDIO frequency selection */ - } mdioclk[] = { - { 35, 2 }, /* 25-35 MHz */ - { 60, 3 }, /* 35-60 MHz */ - { 100, 0 }, /* 60-100 MHz */ - { 150, 1 }, /* 100-150 MHz */ - { 250, 4 }, /* 150-250 MHz */ - { 300, 5 }, /* 250-300 MHz */ - }; - int i; - - /* convert MDIO clk to a divisor value */ - if (freq < mdioclk[0].freq) - return mdioclk[0].bit; - for (i = 1; i < __arraycount(mdioclk); i++) { - if (freq < mdioclk[i].freq) - return mdioclk[i-1].bit; - } - return mdioclk[__arraycount(mdioclk) - 1].bit << GAR_CTL; -} - +/* + * 3 independent uengines exist * to process host2media, media2host and + * packet data flows. + */ static void loaducode(struct scx_softc *sc) { @@ -1482,3 +1498,31 @@ injectucode(struct scx_softc *sc, int po } bus_space_unmap(sc->sc_st, bsh, size); } + +/* bit selection to determine MDIO speed */ + +static int +get_mdioclk(uint32_t freq) +{ + + const struct { + uint16_t freq, bit; /* GAR 5:2 MDIO frequency selection */ + } mdioclk[] = { + { 35, 2 }, /* 25-35 MHz */ + { 60, 3 }, /* 35-60 MHz */ + { 100, 0 }, /* 60-100 MHz */ + { 150, 1 }, /* 100-150 MHz */ + { 250, 4 }, /* 150-250 MHz */ + { 300, 5 }, /* 250-300 MHz */ + }; + int i; + + /* convert MDIO clk to a divisor value */ + if (freq < mdioclk[0].freq) + return mdioclk[0].bit; + for (i = 1; i < __arraycount(mdioclk); i++) { + if (freq < mdioclk[i].freq) + return mdioclk[i-1].bit; + } + return mdioclk[__arraycount(mdioclk) - 1].bit << GAR_CTL; +}