svn commit: r306376 - head/sys/arm/ti/cpsw

Luiz Otavio O Souza loos at FreeBSD.org
Tue Sep 27 18:19:31 UTC 2016


Author: loos
Date: Tue Sep 27 18:19:29 2016
New Revision: 306376
URL: https://svnweb.freebsd.org/changeset/base/306376

Log:
  Add a sysctl to control the interrupt pacing on AM335x integrated switch.
  
  The hardware can be set to limit the number of interrupts from 2 to 63
  interrupts per ms.
  
  To keep the compatibility with the TI documentation the sysctl take the
  interval between the interrupts pulses: 16~500 us.
  
  Sponsored by:	Rubicon Communications, LLC (Netgate)

Modified:
  head/sys/arm/ti/cpsw/if_cpsw.c
  head/sys/arm/ti/cpsw/if_cpswreg.h
  head/sys/arm/ti/cpsw/if_cpswvar.h

Modified: head/sys/arm/ti/cpsw/if_cpsw.c
==============================================================================
--- head/sys/arm/ti/cpsw/if_cpsw.c	Tue Sep 27 18:08:38 2016	(r306375)
+++ head/sys/arm/ti/cpsw/if_cpsw.c	Tue Sep 27 18:19:29 2016	(r306376)
@@ -583,6 +583,11 @@ cpsw_init(struct cpsw_softc *sc)
 	struct cpsw_slot *slot;
 	uint32_t reg;
 
+	/* Disable the interrupt pacing. */
+	reg = cpsw_read_4(sc, CPSW_WR_INT_CONTROL);
+	reg &= ~(CPSW_WR_INT_PACE_EN | CPSW_WR_INT_PRESCALE_MASK);
+	cpsw_write_4(sc, CPSW_WR_INT_CONTROL, reg);
+
 	/* Clear ALE */
 	cpsw_write_4(sc, CPSW_ALE_CONTROL, CPSW_ALE_CTL_CLEAR_TBL);
 
@@ -2492,6 +2497,51 @@ cpsw_stat_attached(SYSCTL_HANDLER_ARGS)
 }
 
 static int
+cpsw_intr_coalesce(SYSCTL_HANDLER_ARGS)
+{
+	int error;
+	struct cpsw_softc *sc;
+	uint32_t ctrl, intr_per_ms;
+
+	sc = (struct cpsw_softc *)arg1;
+	error = sysctl_handle_int(oidp, &sc->coal_us, 0, req);
+	if (error != 0 || req->newptr == NULL)
+		return (error);
+
+	ctrl = cpsw_read_4(sc, CPSW_WR_INT_CONTROL);
+	ctrl &= ~(CPSW_WR_INT_PACE_EN | CPSW_WR_INT_PRESCALE_MASK);
+	if (sc->coal_us == 0) {
+		/* Disable the interrupt pace hardware. */
+		cpsw_write_4(sc, CPSW_WR_INT_CONTROL, ctrl);
+		cpsw_write_4(sc, CPSW_WR_C_RX_IMAX(0), 0);
+		cpsw_write_4(sc, CPSW_WR_C_TX_IMAX(0), 0);
+		return (0);
+	}
+
+	if (sc->coal_us > CPSW_WR_C_IMAX_US_MAX)
+		sc->coal_us = CPSW_WR_C_IMAX_US_MAX;
+	if (sc->coal_us < CPSW_WR_C_IMAX_US_MIN)
+		sc->coal_us = CPSW_WR_C_IMAX_US_MIN;
+	intr_per_ms = 1000 / sc->coal_us;
+	/* Just to make sure... */
+	if (intr_per_ms > CPSW_WR_C_IMAX_MAX)
+		intr_per_ms = CPSW_WR_C_IMAX_MAX;
+	if (intr_per_ms < CPSW_WR_C_IMAX_MIN)
+		intr_per_ms = CPSW_WR_C_IMAX_MIN;
+
+	/* Set the prescale to produce 4us pulses from the 125 Mhz clock. */
+	ctrl |= (125 * 4) & CPSW_WR_INT_PRESCALE_MASK;
+
+	/* Enable the interrupt pace hardware. */
+	cpsw_write_4(sc, CPSW_WR_C_RX_IMAX(0), intr_per_ms);
+	cpsw_write_4(sc, CPSW_WR_C_TX_IMAX(0), intr_per_ms);
+	ctrl |= CPSW_WR_INT_C0_RX_PULSE | CPSW_WR_INT_C0_TX_PULSE;
+	cpsw_write_4(sc, CPSW_WR_INT_CONTROL, ctrl);
+
+	return (0);
+}
+
+static int
 cpsw_stat_uptime(SYSCTL_HANDLER_ARGS)
 {
 	struct cpsw_softc *swsc;
@@ -2576,6 +2626,10 @@ cpsw_add_sysctls(struct cpsw_softc *sc)
 	    CTLTYPE_UINT | CTLFLAG_RD, sc, 0, cpsw_stat_attached, "IU",
 	    "Time since driver attach");
 
+	SYSCTL_ADD_PROC(ctx, parent, OID_AUTO, "intr_coalesce_us",
+	    CTLTYPE_UINT | CTLFLAG_RW, sc, 0, cpsw_intr_coalesce, "IU",
+	    "minimum time between interrupts");
+
 	node = SYSCTL_ADD_NODE(ctx, parent, OID_AUTO, "ports",
 	    CTLFLAG_RD, NULL, "CPSW Ports Statistics");
 	ports_parent = SYSCTL_CHILDREN(node);

Modified: head/sys/arm/ti/cpsw/if_cpswreg.h
==============================================================================
--- head/sys/arm/ti/cpsw/if_cpswreg.h	Tue Sep 27 18:08:38 2016	(r306375)
+++ head/sys/arm/ti/cpsw/if_cpswreg.h	Tue Sep 27 18:19:29 2016	(r306376)
@@ -138,6 +138,17 @@
 #define	CPSW_WR_SOFT_RESET		(CPSW_WR_OFFSET + 0x04)
 #define	CPSW_WR_CONTROL			(CPSW_WR_OFFSET + 0x08)
 #define	CPSW_WR_INT_CONTROL		(CPSW_WR_OFFSET + 0x0c)
+#define	 CPSW_WR_INT_C0_RX_PULSE	(1 << 16)
+#define	 CPSW_WR_INT_C0_TX_PULSE	(1 << 17)
+#define	 CPSW_WR_INT_C1_RX_PULSE	(1 << 18)
+#define	 CPSW_WR_INT_C1_TX_PULSE	(1 << 19)
+#define	 CPSW_WR_INT_C2_RX_PULSE	(1 << 20)
+#define	 CPSW_WR_INT_C2_TX_PULSE	(1 << 21)
+#define	 CPSW_WR_INT_PACE_EN						\
+	(CPSW_WR_INT_C0_RX_PULSE | CPSW_WR_INT_C0_TX_PULSE |		\
+	 CPSW_WR_INT_C1_RX_PULSE | CPSW_WR_INT_C1_TX_PULSE |		\
+	 CPSW_WR_INT_C2_RX_PULSE | CPSW_WR_INT_C2_TX_PULSE)
+#define	 CPSW_WR_INT_PRESCALE_MASK	0xfff
 #define	CPSW_WR_C_RX_THRESH_EN(p)	(CPSW_WR_OFFSET + (0x10 * (p)) + 0x10)
 #define	CPSW_WR_C_RX_EN(p)		(CPSW_WR_OFFSET + (0x10 * (p)) + 0x14)
 #define	CPSW_WR_C_TX_EN(p)		(CPSW_WR_OFFSET + (0x10 * (p)) + 0x18)
@@ -151,6 +162,13 @@
 #define	 CPSW_WR_C_MISC_HOST_PEND	(1 << 2)
 #define	 CPSW_WR_C_MISC_MDIOLINK	(1 << 1)
 #define	 CPSW_WR_C_MISC_MDIOUSER	(1 << 0)
+#define	CPSW_WR_C_RX_IMAX(p)		(CPSW_WR_OFFSET + (0x08 * (p)) + 0x70)
+#define	CPSW_WR_C_TX_IMAX(p)		(CPSW_WR_OFFSET + (0x08 * (p)) + 0x74)
+#define	 CPSW_WR_C_IMAX_MASK		0x3f
+#define	 CPSW_WR_C_IMAX_MAX		63
+#define	 CPSW_WR_C_IMAX_MIN		2
+#define	 CPSW_WR_C_IMAX_US_MAX		500
+#define	 CPSW_WR_C_IMAX_US_MIN		16
 
 #define	CPSW_CPPI_RAM_OFFSET		0x2000
 #define	CPSW_CPPI_RAM_SIZE		0x2000

Modified: head/sys/arm/ti/cpsw/if_cpswvar.h
==============================================================================
--- head/sys/arm/ti/cpsw/if_cpswvar.h	Tue Sep 27 18:08:38 2016	(r306375)
+++ head/sys/arm/ti/cpsw/if_cpswvar.h	Tue Sep 27 18:19:29 2016	(r306376)
@@ -80,6 +80,7 @@ struct cpsw_softc {
 	phandle_t	node;
 	struct bintime	attach_uptime; /* system uptime when attach happened. */
 	struct cpsw_port port[2];
+	unsigned	coal_us;
 
 	/* RX and TX buffer tracking */
 	struct cpsw_queue rx, tx;


More information about the svn-src-head mailing list