Module Name:    src
Committed By:   nisimura
Date:           Tue Dec 21 11:07:51 UTC 2021

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

Log Message:
add interrupt logic stuff


To generate a diff of this commit:
cvs rdiff -u -r1.30 -r1.31 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.30 src/sys/arch/arm/sociox/if_scx.c:1.31
--- src/sys/arch/arm/sociox/if_scx.c:1.30	Mon Dec 20 06:47:24 2021
+++ src/sys/arch/arm/sociox/if_scx.c	Tue Dec 21 11:07:51 2021
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_scx.c,v 1.30 2021/12/20 06:47:24 nisimura Exp $	*/
+/*	$NetBSD: if_scx.c,v 1.31 2021/12/21 11:07:51 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.30 2021/12/20 06:47:24 nisimura Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_scx.c,v 1.31 2021/12/21 11:07:51 nisimura Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -129,28 +129,29 @@ struct rdes {
 #define xINTSR		0x200		/* aggregated interrupt status */
 #define  IRQ_RX		(1U<<1)		/* top level Rx interrupt */
 #define  IRQ_TX		(1U<<0)		/* top level Rx interrupt */
-#define  IRQ_UCODE	(1U<<20)	/* ucode load completed */
+#define  IRQ_UCODE	(1U<<20)	/* ucode load completed; W1C */
 #define xINTAEN		0x204		/* INT_A enable */
 #define xINTAE_SET	0x234		/* bit to set */
 #define xINTAE_CLR	0x238		/* bit to clr */
 #define xINTBEN		0x23c		/* INT_B enable */
 #define xINTBE_SET	0x240		/* bit to set */
 #define xINTBE_CLR	0x244		/* bit to clr */
-#define TXISR		0x400		/* transmit status */
+#define TXISR		0x400		/* transmit status; W1C */
 #define TXIEN		0x404		/* tx interrupt enable */
 #define TXIE_SET	0x428		/* bit to set */
 #define TXIE_CLR	0x42c		/* bit to clr */
-#define  TXI_NTOWNR	(1U<<17)	/* ready desc got empty */
+#define  TXI_NTOWNR	(1U<<17)	/* ??? desc array got empty */
 #define  TXI_TR_ERR	(1U<<16)	/* tx error */
 #define  TXI_TXDONE	(1U<<15)	/* tx completed */
 #define  TXI_TMREXP	(1U<<14)	/* coalesce timer expired */
-#define RXISR		0x440		/* receive status */
+#define RXISR		0x440		/* receive status; W1C */
 #define RXIEN		0x444		/* rx interrupt enable */
 #define RXIE_SET	0x468		/* bit to set */
 #define RXIE_CLR	0x46c		/* bit to clr */
 #define  RXI_RC_ERR	(1U<<16)	/* rx error */
 #define  RXI_PKTCNT	(1U<<15)	/* rx counter has new value */
 #define  RXI_TMREXP	(1U<<14)	/* coalesce timer expired */
+/* 13 sets of special purpose desc interrupt handling register exist */
 #define TDBA_LO		0x408		/* tdes array base addr 31:0 */
 #define TDBA_HI		0x434		/* tdes array base addr 63:32 */
 #define RDBA_LO		0x448		/* rdes array base addr 31:0 */
@@ -459,7 +460,6 @@ struct scx_softc {
 	int sc_flowflags;		/* 802.3x PAUSE flow control */
 	uint32_t sc_mdclk;		/* GAR 5:2 clock selection */
 	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 */
 	uint64_t sc_freq;
@@ -603,7 +603,7 @@ static int
 mac_read(struct scx_softc *sc, int reg)
 {
 
-	CSR_WRITE(sc, MACCMD, reg);
+	CSR_WRITE(sc, MACCMD, reg | CMD_BUSY);
 	(void)WAIT_FOR_CLR(sc, MACCMD, CMD_BUSY, 0);
 	return CSR_READ(sc, MACDATA);
 }
@@ -613,10 +613,11 @@ mac_write(struct scx_softc *sc, int reg,
 {
 
 	CSR_WRITE(sc, MACDATA, val);
-	CSR_WRITE(sc, MACCMD, reg | CMD_IOWR);
+	CSR_WRITE(sc, MACCMD, reg | CMD_IOWR | CMD_BUSY);
 	(void)WAIT_FOR_CLR(sc, MACCMD, CMD_BUSY, 0);
 }
 
+/* dig and decode "clock-frequency" value for a given clkname */
 static int
 get_clk_freq(int phandle, const char *clkname)
 {
@@ -671,7 +672,6 @@ scx_fdt_attach(device_t parent, device_t
 	struct scx_softc * const sc = device_private(self);
 	struct fdt_attach_args * const faa = aux;
 	const int phandle = faa->faa_phandle;
-	bus_space_tag_t bst = faa->faa_bst;
 	bus_space_handle_t bsh;
 	bus_space_handle_t eebsh;
 	bus_addr_t addr[2];
@@ -683,7 +683,7 @@ scx_fdt_attach(device_t parent, device_t
 	long ref_clk;
 
 	aprint_naive("\n");
-	aprint_normal(": Gigabit Ethernet Controller\n");
+	aprint_normal(": Socionext Gigabit Ethernet controller\n");
 
 	if (fdtbus_get_reg(phandle, 0, addr+0, size+0) != 0
 	    || bus_space_map(faa->faa_bst, addr[0], size[0], 0, &bsh) != 0) {
@@ -707,7 +707,7 @@ scx_fdt_attach(device_t parent, device_t
 	}
 
 	sc->sc_dev = self;
-	sc->sc_st = bst;
+	sc->sc_st = faa->faa_bst;
 	sc->sc_sh = bsh;
 	sc->sc_sz = size[0];
 	sc->sc_eesh = eebsh;
@@ -754,7 +754,6 @@ scx_acpi_attach(device_t parent, device_
 	struct scx_softc * const sc = device_private(self);
 	struct acpi_attach_args * const aa = aux;
 	ACPI_HANDLE handle = aa->aa_node->ad_handle;
-	bus_space_tag_t bst = aa->aa_memt;
 	bus_space_handle_t bsh, eebsh;
 	struct acpi_resources res;
 	struct acpi_mem *mem;
@@ -763,7 +762,7 @@ scx_acpi_attach(device_t parent, device_
 	ACPI_STATUS rv;
 
 	aprint_naive("\n");
-	aprint_normal(": Gigabit Ethernet Controller\n");
+	aprint_normal(": Socionext Gigabit Ethernet controller\n");
 
 	rv = acpi_resource_parse(self, handle, "_CRS",
 	    &res, &acpi_resource_parse_ops_default);
@@ -777,7 +776,8 @@ scx_acpi_attach(device_t parent, device_
 		aprint_error_dev(self, "incomplete crs resources\n");
 		return;
 	}
-	if (bus_space_map(bst, mem->ar_base, mem->ar_length, 0, &bsh) != 0) {
+	if (bus_space_map(aa->aa_memt, mem->ar_base, mem->ar_length, 0,
+	    &bsh) != 0) {
 		aprint_error_dev(self, "couldn't map registers\n");
 		return;
 	}
@@ -793,7 +793,8 @@ scx_acpi_attach(device_t parent, device_
 		aprint_error_dev(self, "incomplete eeprom resources\n");
 		goto fail;
 	}
-	if (bus_space_map(bst, mem->ar_base, mem->ar_length, 0, &eebsh) != 0) {
+	if (bus_space_map(aa->aa_memt, mem->ar_base, mem->ar_length, 0,
+	    &eebsh)) {
 		aprint_error_dev(self, "couldn't map registers\n");
 		goto fail;
 	}
@@ -813,7 +814,7 @@ scx_acpi_attach(device_t parent, device_
 		ref_freq = 250 * 1000 * 1000;
 
 	sc->sc_dev = self;
-	sc->sc_st = bst;
+	sc->sc_st = aa->aa_memt;
 	sc->sc_sh = bsh;
 	sc->sc_eesh = eebsh;
 	sc->sc_dmat = aa->aa_dmat64;
@@ -874,8 +875,7 @@ scx_attach_i(struct scx_softc *sc)
 
 	sc->sc_mdclk = get_mdioclk(sc->sc_freq) << GAR_CLK; /* 5:2 clk ratio */
 
-	if (sc->sc_ucodeloaded == 0)
-		loaducode(sc);
+	loaducode(sc);
 
 	mii->mii_ifp = ifp;
 	mii->mii_readreg = mii_readreg;
@@ -1026,6 +1026,9 @@ scx_reset(struct scx_softc *sc)
 	CSR_WRITE(sc, COMINIT, INIT_DB | INIT_CLS);
 	WAIT_FOR_CLR(sc, COMINIT, (INIT_DB | INIT_CLS), 0);
 
+	CSR_WRITE(sc, TXISR, ~0);
+	CSR_WRITE(sc, xINTAE_CLR, ~0);
+
 	mac_write(sc, GMACEVCTL, 1);
 }
 
@@ -1076,6 +1079,16 @@ scx_init(struct ifnet *ifp)
 	sc->sc_rxptr = 0;
 	sc->sc_rxptr = 0;
 
+	paddr = SCX_CDTXADDR(sc, 0);		/* tdes array (ring#0) */
+	mac_write(sc, TDBA_HI, BUS_ADDR_HI32(paddr));
+	mac_write(sc, TDBA_LO, BUS_ADDR_LO32(paddr));
+	paddr = SCX_CDRXADDR(sc, 0);		/* rdes array (ring#1) */
+	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 */
+
 	/* set my address in perfect match slot 0. little endian order */
 	csr = (ea[3] << 24) | (ea[2] << 16) | (ea[1] << 8) |  ea[0];
 	mac_write(sc, GMACMAL0, csr);
@@ -1089,30 +1102,30 @@ scx_init(struct ifnet *ifp)
 	if ((error = ether_mediachange(ifp)) != 0)
 		goto out;
 
-	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, GMACRDLA, _RDLA);		/* GMAC rdes store */
+	CSR_WRITE(sc, GMACTDLA, _TDLA);		/* GMAC tdes store */
 
 	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);
+	CSR_WRITE(sc, RXIE_CLR, ~0);	/* clear Rx interrupt enable */
+	CSR_WRITE(sc, TXIE_CLR, ~0);	/* clear Tx interrupt enable */
+
+	CSR_WRITE(sc, RXCOLMAX, 8);	/* Rx coalesce upper bound */
+	CSR_WRITE(sc, TXCOLMAX, 8);	/* Tx coalesce upper bound */
+	CSR_WRITE(sc, RXITIMER, 500);	/* Rx co. timer usec */
+	CSR_WRITE(sc, TXITIMER, 500);	/* Tx co. timer usec */
+
+	CSR_WRITE(sc, RXIE_SET, RXI_RC_ERR | RXI_PKTCNT | RXI_TMREXP);
+	CSR_WRITE(sc, TXIE_SET, TXI_TR_ERR | TXI_TXDONE | TXI_TMREXP);
+	
+	CSR_WRITE(sc, xINTAE_SET, IRQ_RX | IRQ_TX);
 
 	/* kick to start GMAC engine */
 	csr = mac_read(sc, GMACOMR);
@@ -1142,6 +1155,10 @@ scx_stop(struct ifnet *ifp, int disable)
 	ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
 	ifp->if_timer = 0;
 
+	CSR_WRITE(sc, xINTAE_CLR, ~0);
+	CSR_WRITE(sc, TXISR, ~0);
+	CSR_WRITE(sc, RXISR, ~0);
+
 	if (CSR_READ(sc, CORESTAT) != 0) {
 		CSR_WRITE(sc, DMACTL_H2M, DMACTL_STOP);
 		CSR_WRITE(sc, DMACTL_M2H, DMACTL_STOP);
@@ -1447,12 +1464,35 @@ static int
 scx_intr(void *arg)
 {
 	struct scx_softc *sc = arg;
-	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
+	uint32_t enable, status;
 
-	(void)ifp;
-	/* XXX decode interrupt cause to pick isr() XXX */
-	rxintr(sc);
-	txreap(sc);
+	status = CSR_READ(sc, xINTSR); /* not W1C */
+	enable = CSR_READ(sc, xINTAEN);
+	if ((status & enable) == 0)
+		return 0;
+	if (status & (IRQ_TX | IRQ_RX)) {
+		CSR_WRITE(sc, xINTAE_CLR, (IRQ_TX | IRQ_RX));
+
+		status = CSR_READ(sc, RXISR);
+		CSR_WRITE(sc, RXISR, status);
+		if (status & RXI_RC_ERR)
+			aprint_error_dev(sc->sc_dev, "Rx error\n");
+		if (status & (RXI_PKTCNT | RXI_TMREXP)) {
+			rxintr(sc);
+			(void)CSR_READ(sc, RXDONECNT); /* clear RXI_RXDONE */
+		}
+
+		status = CSR_READ(sc, TXISR);
+		CSR_WRITE(sc, TXISR, status);
+		if (status & TXI_TR_ERR)
+			aprint_error_dev(sc->sc_dev, "Tx error\n");
+		if (status & (TXI_TXDONE | TXI_TMREXP)) {
+			txreap(sc);
+			(void)CSR_READ(sc, TXDONECNT); /* clear TXI_TXDONE */
+		}
+
+		CSR_WRITE(sc, xINTAE_SET, (IRQ_TX | IRQ_RX));
+	}
 	return 1;
 }
 
@@ -1473,7 +1513,7 @@ txreap(struct scx_softc *sc)
 		SCX_CDTXSYNC(sc, txs->txs_firstdesc, txs->txs_ndesc,
 		    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
 
-		txstat = sc->sc_txdescs[txs->txs_lastdesc].t0;
+		txstat = le32toh(sc->sc_txdescs[txs->txs_lastdesc].t0);
 		if (txstat & T0_OWN) /* desc is still in use */
 			break;
 
@@ -1734,6 +1774,23 @@ phy_tick(void *arg)
 	callout_schedule(&sc->sc_callout, hz);
 }
 
+static void
+reset_hardware(struct scx_softc *sc)
+{
+
+	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);
+	}
+	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);
+}
+
 /*
  * 3 independent uengines exist to process host2media, media2host and
  * packet data flows.
@@ -1744,7 +1801,8 @@ loaducode(struct scx_softc *sc)
 	uint32_t up, lo, sz;
 	uint64_t addr;
 
-	sc->sc_ucodeloaded = 1;
+	reset_hardware(sc);
+	CSR_WRITE(sc, xINTSR, IRQ_UCODE);
 
 	up = EE_READ(sc, 0x08); /* H->M ucode addr high */
 	lo = EE_READ(sc, 0x0c); /* H->M ucode addr low */
@@ -1767,6 +1825,10 @@ aprint_normal_dev(sc->sc_dev, "0x%x M2H 
 	sz *= 4;
 	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);
+
+	WAIT_FOR_SET(sc, xINTSR, IRQ_UCODE, 0);
+	/* XXX may take long time to end ?! XXX */
+	CSR_WRITE(sc, xINTSR, IRQ_UCODE);
 }
 
 static void

Reply via email to