Module Name:    src
Committed By:   nisimura
Date:           Thu Dec 16 11:36:26 UTC 2021

Modified Files:
        src/sys/arch/arm/sociox: if_scx.c

Log Message:
interlim commit to snapshot SC2A11 GbE progress.


To generate a diff of this commit:
cvs rdiff -u -r1.26 -r1.27 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.26 src/sys/arch/arm/sociox/if_scx.c:1.27
--- src/sys/arch/arm/sociox/if_scx.c:1.26	Thu Dec 16 11:32:22 2021
+++ src/sys/arch/arm/sociox/if_scx.c	Thu Dec 16 11:36:25 2021
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_scx.c,v 1.26 2021/12/16 11:32:22 nisimura Exp $	*/
+/*	$NetBSD: if_scx.c,v 1.27 2021/12/16 11:36:25 nisimura Exp $	*/
 
 /*-
  * Copyright (c) 2020 The NetBSD Foundation, Inc.
@@ -46,7 +46,7 @@
 #define NOT_MP_SAFE	0
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_scx.c,v 1.26 2021/12/16 11:32:22 nisimura Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_scx.c,v 1.27 2021/12/16 11:36:25 nisimura Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -408,7 +408,7 @@ struct scx_softc {
 	int sc_phy_id;			/* PHY address */
 	int sc_flowflags;		/* 802.3x PAUSE flow control */
 	uint32_t sc_mdclk;		/* GAR 5:2 clock selection */
-	uint32_t sc_t0coso;		/* T0_CSUM | T0_SGOL to run */
+	uint32_t sc_t0cotso;		/* T0_CSUM | T0_TSO to run */
 	int sc_ucodeloaded;		/* ucode for H2M/M2H/PKT */
 	int sc_100mii;			/* 1 for RMII/MII, 0 for RGMII */
 	int sc_phandle;			/* fdt phandle */
@@ -431,6 +431,9 @@ struct scx_softc {
 	int sc_rxptr;			/* next ready Rx descriptor/descsoft */
 
 	krndsource_t rnd_source;	/* random source */
+#ifdef GMAC_EVENT_COUNTER
+	/* 80 event counter exist */
+#endif
 };
 
 #define SCX_CDTXADDR(sc, x)	((sc)->sc_cddma + SCX_CDTXOFF((x)))
@@ -477,6 +480,16 @@ do {									\
 	if ((x) == MD_NRXDESC - 1) __rxd->r0 |= R0_EOD;			\
 } while (/*CONSTCOND*/0)
 
+/* memory mapped CSR register access */
+#define CSR_READ(sc,off) \
+	    bus_space_read_4((sc)->sc_st, (sc)->sc_sh, (off))
+#define CSR_WRITE(sc,off,val) \
+	    bus_space_write_4((sc)->sc_st, (sc)->sc_sh, (off), (val))
+
+/* flash memory access */
+#define EE_READ(sc,off) \
+	    bus_space_read_4((sc)->sc_st, (sc)->sc_eesh, (off))
+
 static int scx_fdt_match(device_t, cfdata_t, void *);
 static void scx_fdt_attach(device_t, device_t, void *);
 static int scx_acpi_match(device_t, cfdata_t, void *);
@@ -558,6 +571,10 @@ static const struct device_compatible_en
 	{ .compat = "socionext,synquacer-netsec" },
 	DEVICE_COMPAT_EOL
 };
+static const struct device_compatible_entry compatible[] = {
+	{ .compat = "SCX0001" },
+	DEVICE_COMPAT_EOL
+};
 
 static int
 scx_fdt_match(device_t parent, cfdata_t cf, void *aux)
@@ -634,15 +651,9 @@ scx_fdt_attach(device_t parent, device_t
 static int
 scx_acpi_match(device_t parent, cfdata_t cf, void *aux)
 {
-	static const char * compatible[] = {
-		"SCX0001",
-		NULL
-	};
 	struct acpi_attach_args *aa = aux;
 
-	if (aa->aa_node->ad_type != ACPI_TYPE_DEVICE)
-		return 0;
-	return acpi_match_hid(aa->aa_node->ad_devinfo, compatible);
+	return acpi_compatible_match(aa, compatible);
 }
 
 static void
@@ -660,6 +671,7 @@ scx_acpi_attach(device_t parent, device_
 	ACPI_INTEGER acpi_phy, acpi_freq;
 	ACPI_STATUS rv;
 
+aprint_normal(": Gigabit Ethernet Controller\n");
 	rv = acpi_resource_parse(self, handle, "_CRS",
 	    &res, &acpi_resource_parse_ops_default);
 	if (ACPI_FAILURE(rv))
@@ -713,7 +725,7 @@ scx_acpi_attach(device_t parent, device_
 	sc->sc_sh = bsh;
 	sc->sc_eesh = eebsh;
 	sc->sc_dmat = aa->aa_dmat64;
-	sc->sc_dmat32 = aa->aa_dmat;	/* descriptor needs dma32 */
+	sc->sc_dmat32 = aa->aa_dmat;
 
 aprint_normal_dev(self,
 "phy mode %s, phy id %d, freq %ld\n", phy_mode, (int)acpi_phy, acpi_freq);
@@ -742,18 +754,19 @@ scx_attach_i(struct scx_softc *sc)
 	struct ifnet * const ifp = &sc->sc_ethercom.ec_if;
 	struct mii_data * const mii = &sc->sc_mii;
 	struct ifmedia * const ifm = &mii->mii_media;
-	uint32_t hwver, dwimp, dwfea;
+	uint32_t which, dwimp, dwfea;
 	uint8_t enaddr[ETHER_ADDR_LEN];
 	bus_dma_segment_t seg;
 	uint32_t csr;
 	int i, nseg, error = 0;
 
-	hwver = CSR_READ(sc, HWVER);	/* Socionext version */
-	dwimp = mac_read(sc, GMACIMPL);	/* DW EMAC XX.YY */
-	dwfea = mac_read(sc, HWFEA);	/* DW feature */
+	which = CSR_READ(sc, HWVER);	/* Socionext version 5.00xx */
+	dwimp = mac_read(sc, GMACIMPL);	/* DWC EMAC XX.YY */
+	dwfea = mac_read(sc, HWFEA);	/* DWC feature */
 	aprint_normal_dev(sc->sc_dev,
-	    "Socionext NetSec GbE %d.%d (impl 0x%x, feature 0x%x)\n",
-	    hwver >> 16, hwver & 0xffff,
+	    "Socionext NetSec GbE %x.%x"
+	    " (impl 0x%x, feature 0x%x)\n",
+	    which >> 16, which & 0xffff,
 	    dwimp, dwfea);
 
 	/* fetch MAC address in flash. stored in big endian order */
@@ -762,14 +775,13 @@ scx_attach_i(struct scx_softc *sc)
 	enaddr[1] = csr >> 16;
 	enaddr[2] = csr >> 8;
 	enaddr[3] = csr;
-	csr = bus_space_read_4(sc->sc_st, sc->sc_eesh, 4);
 	csr = EE_READ(sc, 0x04);
 	enaddr[4] = csr >> 24;
 	enaddr[5] = csr >> 16;
 	aprint_normal_dev(sc->sc_dev,
 	    "Ethernet address %s\n", ether_sprintf(enaddr));
 
-	sc->sc_mdclk = get_mdioclk(sc->sc_freq); /* 5:2 clk control */
+	sc->sc_mdclk = get_mdioclk(sc->sc_freq) << GAR_CLK; /* 5:2 clk ratio */
 
 	if (sc->sc_ucodeloaded == 0)
 		loaducode(sc);
@@ -917,10 +929,11 @@ scx_reset(struct scx_softc *sc)
 	mac_write(sc, GMACBMR, _BMR);
 	mac_write(sc, GMACAFR, 0);
 
-	CSR_WRITE(sc, CLKEN, CLK_ALL);	/* distribute clock sources */
-	CSR_WRITE(sc, SWRESET, 0);	/* reset operation */
-	CSR_WRITE(sc, SWRESET, 1U<<31);	/* manifest run */
-	CSR_WRITE(sc, COMINIT, 3); 	/* DB|CLS */
+	CSR_WRITE(sc, CLKEN, CLK_ALL);		/* distribute clock sources */
+	CSR_WRITE(sc, SWRESET, 0);		/* reset operation */
+	CSR_WRITE(sc, SWRESET, SRST_RUN);	/* manifest run */
+	CSR_WRITE(sc, COMINIT, INIT_DB | INIT_CLS);
+	WAIT_FOR_CLR(sc, COMINIT, (INIT_DB | INIT_CLS), 0);
 
 	mac_write(sc, GMACEVCTL, 1);
 }
@@ -930,6 +943,7 @@ scx_init(struct ifnet *ifp)
 {
 	struct scx_softc *sc = ifp->if_softc;
 	const uint8_t *ea = CLLADDR(ifp->if_sadl);
+	paddr_t paddr;
 	uint32_t csr;
 	int i, error;
 
@@ -984,15 +998,34 @@ scx_init(struct ifnet *ifp)
 	if ((error = ether_mediachange(ifp)) != 0)
 		goto out;
 
-	/* XXX 32 bit paddr XXX hand Tx/Rx rings to HW XXX */
-	mac_write(sc, GMACTDLA, SCX_CDTXADDR(sc, 0));
-	mac_write(sc, GMACRDLA, SCX_CDRXADDR(sc, 0));
+	paddr = SCX_CDTXADDR(sc, 0);
+	mac_write(sc, TDBA_HI, BUS_ADDR_HI32(paddr));
+	mac_write(sc, TDBA_LO, BUS_ADDR_LO32(paddr));
+	paddr = SCX_CDRXADDR(sc, 0);
+	mac_write(sc, RDBA_HI, BUS_ADDR_HI32(paddr));
+	mac_write(sc, RDBA_LO, BUS_ADDR_LO32(paddr));
+
+	CSR_WRITE(sc, TXCONF, DESCNF_LE);	/* little endian */
+	CSR_WRITE(sc, RXCONF, DESCNF_LE);	/* little endian */
+
+	CSR_WRITE(sc, DESC_SRST, 01);
+	WAIT_FOR_CLR(sc, DESC_SRST, 01, 0);
+
+	CSR_WRITE(sc, DESC_INIT, 01);
+	WAIT_FOR_CLR(sc, DESC_INIT, 01, 0);
+
+	CSR_WRITE(sc, GMACRDLA, _RDLA);
+	CSR_WRITE(sc, GMACTDLA, _TDLA);
+
+	CSR_WRITE(sc, FLOWTHR, (48<<16) | 36);	/* pause|resume threshold */
+	mac_write(sc, GMACFCR, 256 << 16);	/* 31:16 pause value */
+
+	CSR_WRITE(sc, RXIE_CLR, ~0);
+	CSR_WRITE(sc, TXIE_CLR, ~0);
 
 	/* kick to start GMAC engine */
-	CSR_WRITE(sc, RXI_CLR, ~0);
-	CSR_WRITE(sc, TXI_CLR, ~0);
 	csr = mac_read(sc, GMACOMR);
-	mac_write(sc, GMACOMR, csr | OMR_RS | OMR_ST);
+	mac_write(sc, GMACOMR, csr | OMR_SR | OMR_ST);
 
 	ifp->if_flags |= IFF_RUNNING;
 	ifp->if_flags &= ~IFF_OACTIVE;
@@ -1017,6 +1050,14 @@ scx_stop(struct ifnet *ifp, int disable)
 	/* Mark the interface down and cancel the watchdog timer. */
 	ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
 	ifp->if_timer = 0;
+
+	if (CSR_READ(sc, CORESTAT) != 0) {
+		CSR_WRITE(sc, DMACTL_H2M, DMACTL_STOP);
+		CSR_WRITE(sc, DMACTL_M2H, DMACTL_STOP);
+
+		WAIT_FOR_CLR(sc, DMACTL_H2M, DMACTL_STOP, 0);
+		WAIT_FOR_CLR(sc, DMACTL_M2H, DMACTL_STOP, 0);
+	}
 }
 
 static int
@@ -1068,6 +1109,16 @@ scx_ioctl(struct ifnet *ifp, u_long cmd,
 	return error;
 }
 
+static uint32_t
+bit_reverse_32(uint32_t x)
+{
+	x = (((x & 0xaaaaaaaa) >> 1) | ((x & 0x55555555) << 1));
+	x = (((x & 0xcccccccc) >> 2) | ((x & 0x33333333) << 2));
+	x = (((x & 0xf0f0f0f0) >> 4) | ((x & 0x0f0f0f0f) << 4));
+	x = (((x & 0xff00ff00) >> 8) | ((x & 0x00ff00ff) << 8));
+	return (x >> 16) | (x << 16);
+}
+
 static void
 scx_set_rcvfilt(struct scx_softc *sc)
 {
@@ -1128,8 +1179,8 @@ printf("[%d] %s\n", i, ether_sprintf(enm
 			mac_write(sc, GMACMAH(i), addr | 1U<<31);
 		} else {
 			/* use hash table when too many */
-			/* bit_reserve_32(~crc) !? */
 			crc = ether_crc32_le(enm->enm_addrlo, ETHER_ADDR_LEN);
+			crc = bit_reverse_32(~crc);
 			/* 1(31) 5(30:26) bit sampling */
 			mchash[crc >> 31] |= 1 << ((crc >> 26) & 0x1f);
 		}
@@ -1152,7 +1203,7 @@ static void
 scx_start(struct ifnet *ifp)
 {
 	struct scx_softc *sc = ifp->if_softc;
-	struct mbuf *m0, *m;
+	struct mbuf *m0;
 	struct scx_txsoft *txs;
 	bus_dmamap_t dmamap;
 	int error, nexttx, lasttx, ofree, seg;
@@ -1236,26 +1287,12 @@ scx_start(struct ifnet *ifp)
 			tdes->t2 = htole32(BUS_ADDR_LO32(paddr));
 			tdes->t1 = htole32(BUS_ADDR_HI32(paddr));
 			tdes->t0 = tdes0 | (tdes->t0 & T0_EOD) |
-					(15 << T0_TRID) | T0_PT |
-					sc->sc_t0coso | T0_TRS;
+					(15 << T0_TDRID) | T0_PT |
+					sc->sc_t0cotso | T0_TRS;
 			tdes0 = T0_OWN; /* 2nd and other segments */
+			/* NB; t0 DRID field contains zero */
 			lasttx = nexttx;
 		}
-		/*
-		 * Outgoing NFS mbuf must be unloaded when Tx completed.
-		 * Without T1_IC NFS mbuf is left unack'ed for excessive
-		 * time and NFS stops to proceed until scx_watchdog()
-		 * calls txreap() to reclaim the unack'ed mbuf.
-		 * It's painful to traverse every mbuf chain to determine
-		 * whether someone is waiting for Tx completion.
-		 */
-		m = m0;
-		do {
-			if ((m->m_flags & M_EXT) && m->m_ext.ext_free) {
-				sc->sc_txdescs[lasttx].t0 |= T0_IOC; /* !!! */
-				break;
-			}
-		} while ((m = m->m_next) != NULL);
 
 		/* Write deferred 1st segment T0_OWN at the final stage */
 		sc->sc_txdescs[lasttx].t0 |= T0_LS;
@@ -1546,11 +1583,7 @@ mii_readreg(device_t self, int phy, int 
 	uint32_t miia;
 	int ntries;
 
-#define CLK_150_250M (1<<2)
-uint32_t clk = CSR_READ(sc, CLKEN);
-CSR_WRITE(sc, CLKEN, clk | CLK_G);
-
-	miia = (phy << GAR_PHY) | (reg << GAR_REG) | CLK_150_250M;
+	miia = (phy << GAR_PHY) | (reg << GAR_REG) | sc->sc_mdclk;
 	mac_write(sc, GMACGAR, miia | GAR_BUSY);
 	for (ntries = 0; ntries < 1000; ntries++) {
 		if ((mac_read(sc, GMACGAR) & GAR_BUSY) == 0)
@@ -1571,9 +1604,6 @@ mii_writereg(device_t self, int phy, int
 	uint16_t dummy;
 	int ntries;
 
-uint32_t clk = CSR_READ(sc, CLKEN);
-CSR_WRITE(sc, CLKEN, clk | CLK_G);
-
 	miia = (phy << GAR_PHY) | (reg << GAR_REG) | sc->sc_mdclk;
 	mac_write(sc, GMACGDR, val);
 	mac_write(sc, GMACGAR, miia | GAR_IOWR | GAR_BUSY);
@@ -1598,7 +1628,7 @@ phy_tick(void *arg)
 	s = splnet();
 	mii_tick(mii);
 	splx(s);
-#ifdef SCX_EVENT_COUNTERS /* if tally counter details are made clear */
+#ifdef GMAC_EVENT_COUNTERS
 #endif
 	callout_schedule(&sc->sc_callout, hz);
 }
@@ -1621,20 +1651,20 @@ loaducode(struct scx_softc *sc)
 	sz *= 4;
 	addr = ((uint64_t)up << 32) | lo;
 aprint_normal_dev(sc->sc_dev, "0x%x H2M ucode %u\n", lo, sz);
-	injectucode(sc, H2MENG, (bus_addr_t)addr, (bus_size_t)sz);
+	injectucode(sc, UCODE_H2M, (bus_addr_t)addr, (bus_size_t)sz);
 
 	up = EE_READ(sc, 0x14); /* M->H ucode addr high */
 	lo = EE_READ(sc, 0x18); /* M->H ucode addr low */
 	sz = EE_READ(sc, 0x1c); /* M->H ucode size */
 	sz *= 4;
 	addr = ((uint64_t)up << 32) | lo;
-	injectucode(sc, M2HENG, (bus_addr_t)addr, (bus_size_t)sz);
+	injectucode(sc, UCODE_M2H, (bus_addr_t)addr, (bus_size_t)sz);
 aprint_normal_dev(sc->sc_dev, "0x%x M2H ucode %u\n", lo, sz);
 
 	lo = EE_READ(sc, 0x20); /* PKT ucode addr */
 	sz = EE_READ(sc, 0x24); /* PKT ucode size */
 	sz *= 4;
-	injectucode(sc, PKTENG, (bus_addr_t)lo, (bus_size_t)sz);
+	injectucode(sc, UCODE_PKT, (bus_addr_t)lo, (bus_size_t)sz);
 aprint_normal_dev(sc->sc_dev, "0x%x PKT ucode %u\n", lo, sz);
 }
 
@@ -1658,31 +1688,23 @@ injectucode(struct scx_softc *sc, int po
 	bus_space_unmap(sc->sc_st, bsh, size);
 }
 
-/* bit selection to determine MDIO speed */
-
+/* GAR 5:2 MDIO frequency selection */
 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;
 
 	freq /= 1000 * 1000;
-	/* 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;
+
+	if (freq < 35)
+		return GAR_MDIO_25_35MHZ;
+	if (freq < 60)
+		return GAR_MDIO_35_60MHZ;
+	if (freq < 100)
+		return GAR_MDIO_60_100MHZ;
+	if (freq < 150)
+		return GAR_MDIO_100_150MHZ;
+	if (freq < 250)
+		return GAR_MDIO_150_250MHZ;
+	return GAR_MDIO_250_300MHZ;
 }

Reply via email to