Page MenuHomeFreeBSD

D24304.id75253.diff
No OneTemporary

D24304.id75253.diff

Index: share/man/man4/Makefile
===================================================================
--- share/man/man4/Makefile
+++ share/man/man4/Makefile
@@ -106,6 +106,7 @@
cdceem.4 \
cfi.4 \
cfumass.4 \
+ ${_cgem.4} \
ch.4 \
chromebook_platform.4 \
${_chvgpio.4} \
@@ -880,6 +881,12 @@
_virtio_random.4= virtio_random.4
_virtio_scsi.4= virtio_scsi.4
_vtnet.4= vtnet.4
+.endif
+
+.if ${MACHINE_ARCH} == "armv7" || ${MACHINE_ARCH} == "aarch64" || \
+ ${MACHINE_ARCH} == "riscv64"
+_cgem.4= cgem.4
+MLINKS+=cgem.4 if_cgem.4
.endif
.if empty(MAN_ARCH)
Index: share/man/man4/cgem.4
===================================================================
--- share/man/man4/cgem.4
+++ share/man/man4/cgem.4
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD: head/share/man/man4/man4.arm/cgem.4 301591 2016-06-08 09:36:07Z trasz $
.\"
-.Dd August 26, 2014
+.Dd March 27, 2020
.Dt CGEM 4
.Os
.Sh NAME
@@ -44,7 +44,8 @@
.Nm
driver provides support for the Cadence GEM (Gigabit Ethernet MAC).
The Cadence GEM is used in some SoC (System on a Chip) devices such as
-the Xilinx Zynq-7000 and the Atmel SAMA5D3.
+the Xilinx Zynq-7000, the Xilinx Zynq UltraScale+, and the SiFive
+HiFive Unleashed.
.Pp
The
.Nm
@@ -284,7 +285,7 @@
variables that count
packets discarded by the hardware (see below).
.Pp
-The GEM used in the Zynq-7000 has a bug such that the receiver can
+The GEM used in the Zynq-7000 has a bug such that the receiver can
potentially freeze up under a high load.
The issue is described in sec. 16.7
"Known Issues" of the Zynq-7000 SoC Technical Reference Manual (Xilinx
@@ -292,7 +293,10 @@
The
.Nm
driver implements the work-around suggested in the manual.
-If the bug does not exist in other versions of this device, the
-work-around can be disabled by setting the dev.cgem.%d.rxhangwar
+It is believed that the bug does not exist in the Zynq UltraScale+ and
+SiFive SoCs so the work-around is disabled in those instances and enabled
+in all others.
+The work-around can be disabled by setting the
+.Va dev.cgem.%d.rxhangwar
.Xr sysctl 8
variable to 0.
Index: share/man/man4/man4.arm/Makefile
===================================================================
--- share/man/man4/man4.arm/Makefile
+++ share/man/man4/man4.arm/Makefile
@@ -8,7 +8,6 @@
aw_spi.4 \
aw_syscon.4 \
bcm283x_pwm.4 \
- cgem.4 \
devcfg.4 \
imx6_ahci.4 \
imx6_snvs.4 \
@@ -16,8 +15,7 @@
mge.4 \
ti_adc.4
-MLINKS= cgem.4 if_cgem.4
-MLINKS+= imx_wdog.4 imxwdt.4
+MLINKS= imx_wdog.4 imxwdt.4
MLINKS+= mge.4 if_mge.4
MANSUBDIR=/arm
Index: share/man/man4/man4.arm/cgem.4
===================================================================
--- share/man/man4/man4.arm/cgem.4
+++ share/man/man4/man4.arm/cgem.4
@@ -1,298 +0,0 @@
-.\"
-.\" Copyright (c) 2014 Thomas Skibo <thomasskibo@yahoo.com>
-.\" All rights reserved.
-.\"
-.\" Redistribution and use in source and binary forms, with or without
-.\" modification, are permitted provided that the following conditions
-.\" are met:
-.\" 1. Redistributions of source code must retain the above copyright
-.\" notice, this list of conditions and the following disclaimer.
-.\" 2. The name of the author may not be used to endorse or promote products
-.\" derived from this software without specific prior written permission.
-.\"
-.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-.\" SUCH DAMAGE.
-.\"
-.\" $FreeBSD$
-.\"
-.Dd August 26, 2014
-.Dt CGEM 4
-.Os
-.Sh NAME
-.Nm cgem
-.Nd "Cadence GEM Gigabit Ethernet driver"
-.Sh SYNOPSIS
-To compile this driver into the kernel,
-place the following lines in your
-kernel configuration file:
-.Bd -ragged -offset indent
-.Cd "device ether"
-.Cd "device miibus"
-.Cd "device cgem"
-.Ed
-.Sh DESCRIPTION
-The
-.Nm
-driver provides support for the Cadence GEM (Gigabit Ethernet MAC).
-The Cadence GEM is used in some SoC (System on a Chip) devices such as
-the Xilinx Zynq-7000 and the Atmel SAMA5D3.
-.Pp
-The
-.Nm
-driver supports the following media types:
-.Bl -tag -width ".Cm 10baseT/UTP"
-.It Cm autoselect
-Enable autoselection of the media type and options.
-The user can manually override
-the autoselected mode using
-.Xr ifconfig 8
-or by adding media options to
-.Xr rc.conf 5 .
-.It Cm 10baseT/UTP
-Set 10Mbps operation.
-The
-.Xr ifconfig 8
-.Cm mediaopt
-option can also be used to select either
-.Cm full-duplex
-or
-.Cm half-duplex
-modes.
-.It Cm 100baseTX
-Set 100Mbps (Fast Ethernet) operation.
-The
-.Xr ifconfig 8
-.Cm mediaopt
-option can also be used to select either
-.Cm full-duplex
-or
-.Cm half-duplex
-modes.
-.It Cm 1000baseT
-Set 1000Mbps (Gigabit Ethernet) operation over twisted pair.
-The GEM supports 1000Mbps in
-.Cm full-duplex
-mode only.
-.El
-.Pp
-The
-.Nm
-driver supports the following media options:
-.Bl -tag -width ".Cm full-duplex"
-.It Cm full-duplex
-Force full-duplex operation.
-.It Cm half-duplex
-Force half-duplex operation.
-.El
-.Pp
-The driver provides support for TCP/UDP/IP checksum offloading (although
-disabled by default).
-The device and driver also support 1536-byte frames for VLANs (vlanmtu).
-.Sh SYSCTL VARIABLES
-The following variables are available as both
-.Xr sysctl 8
-variables and
-.Xr loader 8
-tunables:
-.Bl -tag -width "xxxxxxxx"
-.It Va dev.cgem.%d.rxbufs
-The number of receive buffers allocated to the hardware.
-The default value is 256.
-The maximum value is 511.
-If this number is increased while the interface is UP, it will not
-take effect until the next packet is received.
-If this number is decreased while the interface is UP, buffers will
-not be immediately removed from the receive buffer ring but the
-number of buffers will decrease as packets are received until it
-reaches the new value.
-.It Va dev.cgem.%d.rxhangwar
-This tunable enables a work-around to recover from receive hangs.
-The default value is 1.
-Set to 0 to disable the work-around.
-.El
-.Pp
-The following read-only variables are available as
-.Xr sysctl 8
-variables:
-.Bl -tag -width "xxxxxxxx"
-.It Va dev.cgem.%d._rxoverruns
-This variable counts the number of receive packet buffer overrun interrupts.
-.It Va dev.cgem.%d._rxnobufs
-This variable counts the number of interrupts due to the GEM buffer ring
-going empty.
-.It Va dev.cgem.%d._rxdmamapfails
-This variable is the number of times bus_dmamap_load_mbuf_sg(9) failed in
-the receive path.
-.It Va dev.cgem.%d._txfull
-The number of times the GEM's transmit ring was full.
-.It Va dev.cgem.%d._txdmamapfails
-This variable is the number of times bus_dmamap_load_mbuf_sg(9) failed in
-the transmit path.
-.It Va dev.cgem.%d._txdefrags
-This variable is the number of times the driver needed to call m_defrag(9)
-because a packet queued for transmit had too many DMA segments.
-.It Va dev.cgem.%d._txdefragfails
-This variable is the number of times
-.Xr m_defrag 9
-failed.
-.It Va dev.cgem.%d.stats.*
-The following variables are useful MAC counters supplied by the hardware:
-.It Va dev.cgem.%d.stats.tx_bytes
-A 64-bit counter of the number of bytes transmitted in frames without error.
-.It Va dev.cgem.%d.stats.tx_frames
-Counter of frames transmitted without error excluding pause frames.
-.It Va dev.cgem.%d.stats.tx_frames_bcast
-Counter of broadcast frames transmitted without error excluding
-pause frames.
-.It Va dev.cgem.%d.stats.tx_frames_multi
-Counter of multicast frames transmitted without error excluding
-pause frames.
-.It Va dev.cgem.%d.stats.tx_frames_pause
-Counter of pause frames transmitted without error.
-.It Va dev.cgem.%d.stats.tx_frames_64b
-Counter of 64 byte frames transmitted without error.
-.It Va dev.cgem.%d.stats.tx_frames_65to127b
-Counter of 65 to 127 byte frames transmitted without error.
-.It Va dev.cgem.%d.stats.tx_frames_128to255b
-Counter of 128 to 255 byte frames transmitted without error.
-.It Va dev.cgem.%d.stats.tx_frames_256to511b
-Counter of 256 to 511 byte frames transmitted without error.
-.It Va dev.cgem.%d.stats.tx_frames_512to1023b
-Counter of 512 to 1023 byte frames transmitted without error.
-.It Va dev.cgem.%d.stats.tx_frames_1024to1536b
-Counter of 1024 to 1536 byte frames transmitted without error.
-.It Va dev.cgem.%d.stats.tx_under_runs
-Counter of frames not transmitted due to a transmit underrun.
-.It Va dev.cgem.%d.stats.tx_single_collisn
-Counter of frames experiencing a single collision before being successfully
-transmitted.
-.It Va dev.cgem.%d.stats.tx_multi_collisn
-Counter of frames experiencing between 2 and 15 collisions before
-being successfully transmitted.
-.It Va dev.cgem.%d.stats.tx_excsv_collisn
-Counter of frames that failed to transmit because they experienced 16
-collisions.
-.It Va dev.cgem.%d.stats.tx_late_collisn
-Counter of frames that experienced a late collision.
-.It Va dev.cgem.%d.stats.tx_deferred_frames
-Counter of frames experiencing deferral due to carrier sense being
-active on their first attempt at transmission.
-.It Va dev.cgem.%d.stats.tx_carrier_sense_errs
-Counter of frames transmitted where carrier sense was not seen during
-transmission or where carrier sense was deasserted after being asserted
-in a transmit frame without collision.
-.It Va dev.cgem.%d.stats.rx_bytes
-A 64-bit counter of bytes received without error excluding pause
-frames.
-.It Va dev.cgem.%d.stats.rx_frames
-Counter of frames received without error excluding pause frames.
-.It Va dev.cgem.%d.stats.rx_frames_bcast
-Counter of broadcast frames receive without error excluding pause frames.
-.It Va dev.cgem.%d.stats.rx_frames_multi
-Counter of multicast frames receive without error excluding pause frames.
-.It Va dev.cgem.%d.stats.rx_frames_pause
-Counter of pause frames recevied without error.
-.It Va dev.cgem.%d.stats.rx_frames_64b
-Counter of 64-byte frames received without error.
-.It Va dev.cgem.%d.stats.rx_frames_65to127b
-Counter of 65 to 127 byte frames received without error.
-.It Va dev.cgem.%d.stats.rx_frames_128to255b
-Counter of 128 to 255 byte frames received without error.
-.It Va dev.cgem.%d.stats.rx_frames_256to511b
-Counter of 256 to 511 byte frames received without error.
-.It Va dev.cgem.%d.stats.rx_frames_512to1023b
-Counter of 512 to 1023 byte frames received without error.
-.It Va dev.cgem.%d.stats.rx_frames_1024to1536b
-Counter of 1024 to 1536 byte frames received without error.
-.It Va dev.cgem.%d.stats.rx_frames_undersize
-Counter of frames received less than 64 bytes in length that
-do not also have either a CRC error or an alignment error.
-.It Va dev.cgem.%d.stats.rx_frames_oversize
-Counter of frames received exceeding 1536 bytes and do not also have either
-a CRC error or an alignment error.
-.It Va dev.cgem.%d.stats.rx_frames_jabber
-Counter of frames received exceeding 1536 bytes and also have either a CRC
-error, an alignment error, or a receive symbol error.
-.It Va dev.cgem.%d.stats.rx_frames_fcs_errs
-Counter of frames received with a bad CRC and are between 64
-and 1536 bytes.
-.It Va dev.cgem.%d.stats.rx_frames_length_errs
-Counter of frames received that are shorter than that extracted
-from the length field.
-.It Va dev.cgem.%d.stats.rx_symbol_errs
-Counter of receive symbol errors.
-.It Va dev.cgem.%d.stats.rx_align_errs
-Counter of received frames that are not an integral number of bytes.
-.It Va dev.cgem.%d.stats.rx_resource_errs
-Counter of frames successfully receive by the MAC but could not be
-copied to memory because no receive buffer was available.
-.It Va dev.cgem.%d.stats.rx_overrun_errs
-Counter of frames that are address recognized but were not copied
-to memory due to a receive overrun.
-.It Va dev.cgem.%d.stats.rx_frames_ip_hdr_csum_errs
-Counter of frames discarded due to an incorrect IP header checksum when
-checksum offloading is enabled.
-.It Va dev.cgem.%d.stats.rx_frames_tcp_csum_errs
-Counter of frames discarded due to an incorrect TCP checksum when
-checksum offloading is enabled.
-.It Va dev.cgem.%d.stats.rx_frames_udp_csum_errs
-Counter of frames discarded due to an incorrect UDP checksum when
-checksum offloading is enabled.
-.El
-.Sh SEE ALSO
-.Xr miibus 4 ,
-.Xr ifconfig 8
-.Rs
-.%T "Zynq-7000 SoC Technical Reference Manual (Xilinx doc UG585)"
-.%U http://www.xilinx.com/support/documentation/user_guides/\:ug585-Zynq-7000-TRM.pdf
-.Re
-.Sh HISTORY
-The
-.Nm
-device driver first appeared in
-.Fx 10.0 .
-.Sh AUTHORS
-The
-.Nm
-driver and this manual page was written by
-.An Thomas Skibo Aq Mt thomasskibo@yahoo.com .
-.Sh BUGS
-The GEM can perform TCP/UDP/IP checksum offloading.
-However, when transmit checksum offloading is enabled, the GEM generates and
-replaces checksums for all packets it transmits.
-In a system that is forwarding packets, the device could potentially correct
-the checksum of packet that was corrupted in transit.
-For this reason, checksum offloading is disabled by default but can be
-enabled using ifconfig(8).
-.Pp
-When receive checksum offloading is enabled, the device will discard packets
-with bad TCP/UDP/IP checksums.
-The bad packets will not be counted in any
-.Xr netstat 1
-statistics.
-There are
-.Xr sysctl 8
-variables that count
-packets discarded by the hardware (see below).
-.Pp
-The GEM used in the Zynq-7000 has a bug such that the receiver can
-potentially freeze up under a high load.
-The issue is described in sec. 16.7
-"Known Issues" of the Zynq-7000 SoC Technical Reference Manual (Xilinx
-UG585 v1.7).
-The
-.Nm
-driver implements the work-around suggested in the manual.
-If the bug does not exist in other versions of this device, the
-work-around can be disabled by setting the dev.cgem.%d.rxhangwar
-.Xr sysctl 8
-variable to 0.
Index: sys/arm/conf/GENERIC
===================================================================
--- sys/arm/conf/GENERIC
+++ sys/arm/conf/GENERIC
@@ -226,8 +226,8 @@
device miibus
device awg # 10/100/1000 integrated EMAC controller
+device cgem # Cadence GEM Gigabit Ethernet device
device cpsw # TI Common Platform Ethernet Switch (CPSW)
-device cgem # Zynq-7000 gig ethernet device
device dwc # 10/100/1000 integrated GMAC controller
device emac # 10/100 integrated EMAC controller
device ffec # Freescale Fast Ethernet Controller
Index: sys/arm/conf/ZEDBOARD
===================================================================
--- sys/arm/conf/ZEDBOARD
+++ sys/arm/conf/ZEDBOARD
@@ -49,7 +49,7 @@
device loop
device ether
-device cgem # Zynq-7000 gig ethernet device
+device cgem # Cadence GEM Gigabit Ethernet device
device mii
device e1000phy
device rgephy # Zybo uses Realtek RTL8211E
Index: sys/arm64/conf/GENERIC
===================================================================
--- sys/arm64/conf/GENERIC
+++ sys/arm64/conf/GENERIC
@@ -166,6 +166,7 @@
device miibus # MII bus support
device awg # Allwinner EMAC Gigabit Ethernet
device axgbe # AMD Opteron A1100 integrated NIC
+device cgem # Cadence GEM Gigabit Ethernet device
device msk # Marvell/SysKonnect Yukon II Gigabit Ethernet
device neta # Marvell Armada 370/38x/XP/3700 NIC
device smc # SMSC LAN91C111
Index: sys/dev/cadence/if_cgem.c
===================================================================
--- sys/dev/cadence/if_cgem.c
+++ sys/dev/cadence/if_cgem.c
@@ -77,6 +77,14 @@
#include <dev/mii/mii.h>
#include <dev/mii/miivar.h>
+#ifdef EXT_RESOURCES
+#include <dev/extres/clk/clk.h>
+#endif
+
+#if INTPTR_MAX == INT64_MAX
+#define CGEM64
+#endif
+
#include <dev/cadence/if_cgem_hw.h>
#include "miibus_if.h"
@@ -86,10 +94,6 @@
#define CGEM_NUM_RX_DESCS 512 /* size of receive descriptor ring */
#define CGEM_NUM_TX_DESCS 512 /* size of transmit descriptor ring */
-#define MAX_DESC_RING_SIZE (MAX(CGEM_NUM_RX_DESCS*sizeof(struct cgem_rx_desc),\
- CGEM_NUM_TX_DESCS*sizeof(struct cgem_tx_desc)))
-
-
/* Default for sysctl rxbufs. Must be < CGEM_NUM_RX_DESCS of course. */
#define DEFAULT_NUM_RX_BUFS 256 /* number of receive bufs to queue. */
@@ -98,11 +102,18 @@
#define CGEM_CKSUM_ASSIST (CSUM_IP | CSUM_TCP | CSUM_UDP | \
CSUM_TCP_IPV6 | CSUM_UDP_IPV6)
+#define HWTYPE_GENERIC_GEM 1
+#define HWTYPE_ZYNQ 2
+#define HWTYPE_ZYNQMP 3
+#define HWTYPE_SIFIVE_FU540 4
+
static struct ofw_compat_data compat_data[] = {
- { "cadence,gem", 1 },
- { "cdns,macb", 1 },
- { "sifive,fu540-c000-gem", 1 },
- { NULL, 0 },
+ { "cdns,zynq-gem", HWTYPE_ZYNQ },
+ { "cdns,zynqmp-gem", HWTYPE_ZYNQMP },
+ { "sifive,fu540-c000-gem", HWTYPE_SIFIVE_FU540 },
+ { "cdns,gem", HWTYPE_GENERIC_GEM },
+ { "cadence,gem", HWTYPE_GENERIC_GEM },
+ { NULL, 0 }
};
struct cgem_softc {
@@ -117,8 +128,13 @@
void *intrhand;
struct callout tick_ch;
uint32_t net_ctl_shadow;
+ uint32_t net_cfg_shadow;
+#ifdef EXT_RESOURCES
+ clk_t ref_clk;
+#else
int ref_clk_num;
- u_char eaddr[6];
+#endif
+ int neednullqs;
bus_dma_tag_t desc_dma_tag;
bus_dma_tag_t mbuf_dma_tag;
@@ -147,12 +163,15 @@
int txring_hd_ptr; /* where to put next xmits */
int txring_tl_ptr; /* next xmit mbuf to free */
int txring_queued; /* num xmits segs queued */
- bus_dmamap_t txring_dma_map;
u_int txfull; /* tx ring full events */
u_int txdefrags; /* tx calls to m_defrag() */
u_int txdefragfails; /* tx m_defrag() failures */
u_int txdmamapfails; /* tx dmamap failures */
+ /* null descriptor rings */
+ void *null_qs;
+ bus_addr_t null_qs_physaddr;
+
/* hardware provided statistics */
struct cgem_hw_stats {
uint64_t tx_bytes;
@@ -275,9 +294,9 @@
/*
* cgem_mac_hash(): map 48-bit address to a 6-bit hash. The 6-bit hash
- * corresponds to a bit in a 64-bit hash register. Setting that bit in the hash
- * register enables reception of all frames with a destination address that
- * hashes to that 6-bit value.
+ * corresponds to a bit in a 64-bit hash register. Setting that bit in the
+ * hash register enables reception of all frames with a destination address
+ * that hashes to that 6-bit value.
*
* The hash function is described in sec. 16.2.3 in the Zynq-7000 Tech
* Reference Manual. Bits 0-5 in the hash are the exclusive-or of
@@ -322,18 +341,15 @@
{
if_t ifp = sc->ifp;
uint32_t hashes[2] = { 0, 0 };
- uint32_t net_cfg;
- net_cfg = RD4(sc, CGEM_NET_CFG);
-
- net_cfg &= ~(CGEM_NET_CFG_MULTI_HASH_EN |
+ sc->net_cfg_shadow &= ~(CGEM_NET_CFG_MULTI_HASH_EN |
CGEM_NET_CFG_NO_BCAST | CGEM_NET_CFG_COPY_ALL);
if ((if_getflags(ifp) & IFF_PROMISC) != 0)
- net_cfg |= CGEM_NET_CFG_COPY_ALL;
+ sc->net_cfg_shadow |= CGEM_NET_CFG_COPY_ALL;
else {
if ((if_getflags(ifp) & IFF_BROADCAST) == 0)
- net_cfg |= CGEM_NET_CFG_NO_BCAST;
+ sc->net_cfg_shadow |= CGEM_NET_CFG_NO_BCAST;
if ((if_getflags(ifp) & IFF_ALLMULTI) != 0) {
hashes[0] = 0xffffffff;
hashes[1] = 0xffffffff;
@@ -341,12 +357,12 @@
if_foreach_llmaddr(ifp, cgem_hash_maddr, hashes);
if (hashes[0] != 0 || hashes[1] != 0)
- net_cfg |= CGEM_NET_CFG_MULTI_HASH_EN;
+ sc->net_cfg_shadow |= CGEM_NET_CFG_MULTI_HASH_EN;
}
WR4(sc, CGEM_HASH_TOP, hashes[0]);
WR4(sc, CGEM_HASH_BOT, hashes[1]);
- WR4(sc, CGEM_NET_CFG, net_cfg);
+ WR4(sc, CGEM_NET_CFG, sc->net_cfg_shadow);
}
/* For bus_dmamap_load() callback. */
@@ -359,40 +375,92 @@
*(bus_addr_t *)arg = segs[0].ds_addr;
}
+/* Set up null queues for priority queues we actually can't disable. */
+static void
+cgem_null_qs(struct cgem_softc *sc)
+{
+ struct cgem_rx_desc *rx_desc;
+ struct cgem_tx_desc *tx_desc;
+ uint32_t queue_mask;
+ int n;
+
+ /* Read design config register 6 to determine number of queues. */
+ queue_mask = (RD4(sc, CGEM_DESIGN_CFG6) &
+ CGEM_DESIGN_CFG6_DMA_PRIO_Q_MASK) >> 1;
+ if (queue_mask == 0)
+ return;
+
+ /* Create empty RX queue and empty TX buf queues. */
+ memset(sc->null_qs, 0, sizeof(struct cgem_rx_desc) +
+ sizeof(struct cgem_tx_desc));
+ rx_desc = sc->null_qs;
+ rx_desc->addr = CGEM_RXDESC_OWN | CGEM_RXDESC_WRAP;
+ tx_desc = (struct cgem_tx_desc *)(rx_desc + 1);
+ tx_desc->ctl = CGEM_TXDESC_USED | CGEM_TXDESC_WRAP;
+
+ /* Point all valid ring base pointers to the null queues. */
+ for (n = 1; (queue_mask & 1) != 0; n++, queue_mask >>= 1) {
+ WR4(sc, CGEM_RX_QN_BAR(n), sc->null_qs_physaddr);
+ WR4(sc, CGEM_TX_QN_BAR(n), sc->null_qs_physaddr +
+ sizeof(struct cgem_rx_desc));
+ }
+}
+
/* Create DMA'able descriptor rings. */
static int
cgem_setup_descs(struct cgem_softc *sc)
{
int i, err;
+ int desc_rings_size = CGEM_NUM_RX_DESCS * sizeof(struct cgem_rx_desc) +
+ CGEM_NUM_TX_DESCS * sizeof(struct cgem_tx_desc);
+ if (sc->neednullqs)
+ desc_rings_size += sizeof(struct cgem_rx_desc) +
+ sizeof(struct cgem_tx_desc);
+
sc->txring = NULL;
sc->rxring = NULL;
/* Allocate non-cached DMA space for RX and TX descriptors. */
- err = bus_dma_tag_create(bus_get_dma_tag(sc->dev), 1, 0,
- BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
- MAX_DESC_RING_SIZE, 1, MAX_DESC_RING_SIZE, 0,
+ err = bus_dma_tag_create(bus_get_dma_tag(sc->dev), 1,
+#ifdef CGEM64
+ 1ULL << 32, /* Do not cross a 4G boundary. */
+#else
+ 0,
+#endif
+ BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL,
+ desc_rings_size, 1, desc_rings_size, 0,
busdma_lock_mutex, &sc->sc_mtx, &sc->desc_dma_tag);
if (err)
return (err);
/* Set up a bus_dma_tag for mbufs. */
err = bus_dma_tag_create(bus_get_dma_tag(sc->dev), 1, 0,
- BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
- MCLBYTES, TX_MAX_DMA_SEGS, MCLBYTES, 0,
- busdma_lock_mutex, &sc->sc_mtx, &sc->mbuf_dma_tag);
+ BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, MCLBYTES,
+ TX_MAX_DMA_SEGS, MCLBYTES, 0, busdma_lock_mutex, &sc->sc_mtx,
+ &sc->mbuf_dma_tag);
if (err)
return (err);
- /* Allocate DMA memory in non-cacheable space. */
+ /*
+ * Allocate DMA memory in non-cacheable space. We allocate transmit,
+ * receive and null descriptor queues all at once because the
+ * hardware only provides one register for the upper 32 bits of
+ * rx and tx descriptor queues hardware addresses.
+ */
err = bus_dmamem_alloc(sc->desc_dma_tag, (void **)&sc->rxring,
- BUS_DMA_NOWAIT | BUS_DMA_COHERENT, &sc->rxring_dma_map);
+#ifdef __arm__
+ BUS_DMA_NOWAIT | BUS_DMA_COHERENT | BUS_DMA_ZERO,
+#else
+ BUS_DMA_NOWAIT | BUS_DMA_NOCACHE | BUS_DMA_ZERO,
+#endif
+ &sc->rxring_dma_map);
if (err)
return (err);
/* Load descriptor DMA memory. */
err = bus_dmamap_load(sc->desc_dma_tag, sc->rxring_dma_map,
- (void *)sc->rxring, CGEM_NUM_RX_DESCS*sizeof(struct cgem_rx_desc),
+ (void *)sc->rxring, desc_rings_size,
cgem_getaddr, &sc->rxring_physaddr, BUS_DMA_NOWAIT);
if (err)
return (err);
@@ -410,19 +478,10 @@
sc->rxring_tl_ptr = 0;
sc->rxring_queued = 0;
- /* Allocate DMA memory for TX descriptors in non-cacheable space. */
- err = bus_dmamem_alloc(sc->desc_dma_tag, (void **)&sc->txring,
- BUS_DMA_NOWAIT | BUS_DMA_COHERENT, &sc->txring_dma_map);
- if (err)
- return (err);
+ sc->txring = (struct cgem_tx_desc *)(sc->rxring + CGEM_NUM_RX_DESCS);
+ sc->txring_physaddr = sc->rxring_physaddr + CGEM_NUM_RX_DESCS *
+ sizeof(struct cgem_rx_desc);
- /* Load TX descriptor DMA memory. */
- err = bus_dmamap_load(sc->desc_dma_tag, sc->txring_dma_map,
- (void *)sc->txring, CGEM_NUM_TX_DESCS*sizeof(struct cgem_tx_desc),
- cgem_getaddr, &sc->txring_physaddr, BUS_DMA_NOWAIT);
- if (err)
- return (err);
-
/* Initialize TX descriptor ring. */
for (i = 0; i < CGEM_NUM_TX_DESCS; i++) {
sc->txring[i].addr = 0;
@@ -436,6 +495,14 @@
sc->txring_tl_ptr = 0;
sc->txring_queued = 0;
+ if (sc->neednullqs) {
+ sc->null_qs = (void *)(sc->txring + CGEM_NUM_TX_DESCS);
+ sc->null_qs_physaddr = sc->txring_physaddr +
+ CGEM_NUM_TX_DESCS * sizeof(struct cgem_tx_desc);
+
+ cgem_null_qs(sc);
+ }
+
return (0);
}
@@ -485,6 +552,9 @@
/* Write rx descriptor and increment head pointer. */
sc->rxring[sc->rxring_hd_ptr].ctl = 0;
+#ifdef CGEM64
+ sc->rxring[sc->rxring_hd_ptr].addrhi = segs[0].ds_addr >> 32;
+#endif
if (sc->rxring_hd_ptr == CGEM_NUM_RX_DESCS - 1) {
sc->rxring[sc->rxring_hd_ptr].addr = segs[0].ds_addr |
CGEM_RXDESC_WRAP;
@@ -510,7 +580,7 @@
m_hd = NULL;
m_tl = &m_hd;
while (sc->rxring_queued > 0 &&
- (sc->rxring[sc->rxring_tl_ptr].addr & CGEM_RXDESC_OWN) != 0) {
+ (sc->rxring[sc->rxring_tl_ptr].addr & CGEM_RXDESC_OWN) != 0) {
ctl = sc->rxring[sc->rxring_tl_ptr].ctl;
@@ -632,9 +702,16 @@
/* Check the status. */
if ((ctl & CGEM_TXDESC_AHB_ERR) != 0) {
/* Serious bus error. log to console. */
+#ifdef CGEM64
device_printf(sc->dev,
+ "cgem_clean_tx: AHB error, addr=0x%x%08x\n",
+ sc->txring[sc->txring_tl_ptr].addrhi,
+ sc->txring[sc->txring_tl_ptr].addr);
+#else
+ device_printf(sc->dev,
"cgem_clean_tx: AHB error, addr=0x%x\n",
sc->txring[sc->txring_tl_ptr].addr);
+#endif
} else if ((ctl & (CGEM_TXDESC_RETRY_ERR |
CGEM_TXDESC_LATE_COLL)) != 0) {
if_inc_counter(sc->ifp, IFCOUNTER_OERRORS, 1);
@@ -643,8 +720,8 @@
/*
* If the packet spanned more than one tx descriptor, skip
- * descriptors until we find the end so that only start-of-frame
- * descriptors are processed.
+ * descriptors until we find the end so that only
+ * start-of-frame descriptors are processed.
*/
while ((ctl & CGEM_TXDESC_LAST_BUF) == 0) {
if ((ctl & CGEM_TXDESC_WRAP) != 0)
@@ -763,7 +840,10 @@
/* Descriptor address. */
sc->txring[sc->txring_hd_ptr + i].addr =
segs[i].ds_addr;
-
+#ifdef CGEM64
+ sc->txring[sc->txring_hd_ptr + i].addrhi =
+ segs[i].ds_addr >> 32;
+#endif
/* Descriptor control word. */
ctl = segs[i].ds_len;
if (i == nsegs - 1) {
@@ -965,8 +1045,21 @@
CGEM_ASSERT_LOCKED(sc);
+ /* Determine data bus width from design configuration register. */
+ switch (RD4(sc, CGEM_DESIGN_CFG1) &
+ CGEM_DESIGN_CFG1_DMA_BUS_WIDTH_MASK) {
+ case CGEM_DESIGN_CFG1_DMA_BUS_WIDTH_64:
+ sc->net_cfg_shadow = CGEM_NET_CFG_DBUS_WIDTH_64;
+ break;
+ case CGEM_DESIGN_CFG1_DMA_BUS_WIDTH_128:
+ sc->net_cfg_shadow = CGEM_NET_CFG_DBUS_WIDTH_128;
+ break;
+ default:
+ sc->net_cfg_shadow = CGEM_NET_CFG_DBUS_WIDTH_32;
+ }
+
WR4(sc, CGEM_NET_CTRL, 0);
- WR4(sc, CGEM_NET_CFG, 0);
+ WR4(sc, CGEM_NET_CFG, sc->net_cfg_shadow);
WR4(sc, CGEM_NET_CTRL, CGEM_NET_CTRL_CLR_STAT_REGS);
WR4(sc, CGEM_TX_STAT, CGEM_TX_STAT_ALL);
WR4(sc, CGEM_RX_STAT, CGEM_RX_STAT_ALL);
@@ -977,8 +1070,8 @@
WR4(sc, CGEM_RX_QBAR, 0);
/* Get management port running even if interface is down. */
- WR4(sc, CGEM_NET_CFG, CGEM_NET_CFG_DBUS_WIDTH_32 |
- CGEM_NET_CFG_MDC_CLK_DIV_64);
+ sc->net_cfg_shadow |= CGEM_NET_CFG_MDC_CLK_DIV_48;
+ WR4(sc, CGEM_NET_CFG, sc->net_cfg_shadow);
sc->net_ctl_shadow = CGEM_NET_CTRL_MGMT_PORT_EN;
WR4(sc, CGEM_NET_CTRL, sc->net_ctl_shadow);
@@ -989,33 +1082,33 @@
cgem_config(struct cgem_softc *sc)
{
if_t ifp = sc->ifp;
- uint32_t net_cfg;
uint32_t dma_cfg;
u_char *eaddr = if_getlladdr(ifp);
CGEM_ASSERT_LOCKED(sc);
/* Program Net Config Register. */
- net_cfg = CGEM_NET_CFG_DBUS_WIDTH_32 |
- CGEM_NET_CFG_MDC_CLK_DIV_64 |
- CGEM_NET_CFG_FCS_REMOVE |
+ sc->net_cfg_shadow &= (CGEM_NET_CFG_MDC_CLK_DIV_MASK |
+ CGEM_NET_CFG_DBUS_WIDTH_MASK);
+ sc->net_cfg_shadow |= (CGEM_NET_CFG_FCS_REMOVE |
CGEM_NET_CFG_RX_BUF_OFFSET(ETHER_ALIGN) |
- CGEM_NET_CFG_GIGE_EN |
- CGEM_NET_CFG_1536RXEN |
- CGEM_NET_CFG_FULL_DUPLEX |
- CGEM_NET_CFG_SPEED100;
+ CGEM_NET_CFG_GIGE_EN | CGEM_NET_CFG_1536RXEN |
+ CGEM_NET_CFG_FULL_DUPLEX | CGEM_NET_CFG_SPEED100);
/* Enable receive checksum offloading? */
if ((if_getcapenable(ifp) & IFCAP_RXCSUM) != 0)
- net_cfg |= CGEM_NET_CFG_RX_CHKSUM_OFFLD_EN;
+ sc->net_cfg_shadow |= CGEM_NET_CFG_RX_CHKSUM_OFFLD_EN;
- WR4(sc, CGEM_NET_CFG, net_cfg);
+ WR4(sc, CGEM_NET_CFG, sc->net_cfg_shadow);
/* Program DMA Config Register. */
dma_cfg = CGEM_DMA_CFG_RX_BUF_SIZE(MCLBYTES) |
CGEM_DMA_CFG_RX_PKTBUF_MEMSZ_SEL_8K |
CGEM_DMA_CFG_TX_PKTBUF_MEMSZ_SEL |
CGEM_DMA_CFG_AHB_FIXED_BURST_LEN_16 |
+#ifdef CGEM64
+ CGEM_DMA_CFG_ADDR_BUS_64 |
+#endif
CGEM_DMA_CFG_DISC_WHEN_NO_AHB;
/* Enable transmit checksum offloading? */
@@ -1025,8 +1118,12 @@
WR4(sc, CGEM_DMA_CFG, dma_cfg);
/* Write the rx and tx descriptor ring addresses to the QBAR regs. */
- WR4(sc, CGEM_RX_QBAR, (uint32_t) sc->rxring_physaddr);
- WR4(sc, CGEM_TX_QBAR, (uint32_t) sc->txring_physaddr);
+ WR4(sc, CGEM_RX_QBAR, (uint32_t)sc->rxring_physaddr);
+ WR4(sc, CGEM_TX_QBAR, (uint32_t)sc->txring_physaddr);
+#ifdef CGEM64
+ WR4(sc, CGEM_RX_QBAR_HI, (uint32_t)(sc->rxring_physaddr >> 32));
+ WR4(sc, CGEM_TX_QBAR_HI, (uint32_t)(sc->txring_physaddr >> 32));
+#endif
/* Enable rx and tx. */
sc->net_ctl_shadow |= (CGEM_NET_CTRL_TX_EN | CGEM_NET_CTRL_RX_EN);
@@ -1059,8 +1156,10 @@
if_setdrvflagbits(sc->ifp, IFF_DRV_RUNNING, IFF_DRV_OACTIVE);
- mii = device_get_softc(sc->miibus);
- mii_mediachg(mii);
+ if (sc->miibus != NULL) {
+ mii = device_get_softc(sc->miibus);
+ mii_mediachg(mii);
+ }
callout_reset(&sc->tick_ch, hz, cgem_tick, sc);
}
@@ -1089,9 +1188,9 @@
cgem_reset(sc);
/* Clear out transmit queue. */
+ memset(sc->txring, 0, CGEM_NUM_TX_DESCS * sizeof(struct cgem_tx_desc));
for (i = 0; i < CGEM_NUM_TX_DESCS; i++) {
sc->txring[i].ctl = CGEM_TXDESC_USED;
- sc->txring[i].addr = 0;
if (sc->txring_m[i]) {
/* Unload and destroy dmamap. */
bus_dmamap_unload(sc->mbuf_dma_tag,
@@ -1110,9 +1209,9 @@
sc->txring_queued = 0;
/* Clear out receive queue. */
+ memset(sc->rxring, 0, CGEM_NUM_RX_DESCS * sizeof(struct cgem_rx_desc));
for (i = 0; i < CGEM_NUM_RX_DESCS; i++) {
sc->rxring[i].addr = CGEM_RXDESC_OWN;
- sc->rxring[i].ctl = 0;
if (sc->rxring_m[i]) {
/* Unload and destroy dmamap. */
bus_dmamap_unload(sc->mbuf_dma_tag,
@@ -1176,6 +1275,8 @@
case SIOCSIFMEDIA:
case SIOCGIFMEDIA:
+ if (sc->miibus == NULL)
+ return (ENXIO);
mii = device_get_softc(sc->miibus);
error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, cmd);
break;
@@ -1210,16 +1311,16 @@
/* Turn on RX checksumming. */
if_setcapenablebit(ifp, IFCAP_RXCSUM |
IFCAP_RXCSUM_IPV6, 0);
- WR4(sc, CGEM_NET_CFG,
- RD4(sc, CGEM_NET_CFG) |
- CGEM_NET_CFG_RX_CHKSUM_OFFLD_EN);
+ sc->net_cfg_shadow |=
+ CGEM_NET_CFG_RX_CHKSUM_OFFLD_EN;
+ WR4(sc, CGEM_NET_CFG, sc->net_cfg_shadow);
} else {
/* Turn off RX checksumming. */
if_setcapenablebit(ifp, 0, IFCAP_RXCSUM |
IFCAP_RXCSUM_IPV6);
- WR4(sc, CGEM_NET_CFG,
- RD4(sc, CGEM_NET_CFG) &
- ~CGEM_NET_CFG_RX_CHKSUM_OFFLD_EN);
+ sc->net_cfg_shadow &=
+ ~CGEM_NET_CFG_RX_CHKSUM_OFFLD_EN;
+ WR4(sc, CGEM_NET_CFG, sc->net_cfg_shadow);
}
}
if ((if_getcapenable(ifp) & (IFCAP_RXCSUM | IFCAP_TXCSUM)) ==
@@ -1240,15 +1341,6 @@
/* MII bus support routines.
*/
-static void
-cgem_child_detached(device_t dev, device_t child)
-{
- struct cgem_softc *sc = device_get_softc(dev);
-
- if (child == sc->miibus)
- sc->miibus = NULL;
-}
-
static int
cgem_ifmedia_upd(if_t ifp)
{
@@ -1385,24 +1477,22 @@
static void
cgem_mediachange(struct cgem_softc *sc, struct mii_data *mii)
{
- uint32_t net_cfg;
int ref_clk_freq;
CGEM_ASSERT_LOCKED(sc);
/* Update hardware to reflect media. */
- net_cfg = RD4(sc, CGEM_NET_CFG);
- net_cfg &= ~(CGEM_NET_CFG_SPEED100 | CGEM_NET_CFG_GIGE_EN |
+ sc->net_cfg_shadow &= ~(CGEM_NET_CFG_SPEED100 | CGEM_NET_CFG_GIGE_EN |
CGEM_NET_CFG_FULL_DUPLEX);
switch (IFM_SUBTYPE(mii->mii_media_active)) {
case IFM_1000_T:
- net_cfg |= (CGEM_NET_CFG_SPEED100 |
+ sc->net_cfg_shadow |= (CGEM_NET_CFG_SPEED100 |
CGEM_NET_CFG_GIGE_EN);
ref_clk_freq = 125000000;
break;
case IFM_100_TX:
- net_cfg |= CGEM_NET_CFG_SPEED100;
+ sc->net_cfg_shadow |= CGEM_NET_CFG_SPEED100;
ref_clk_freq = 25000000;
break;
default:
@@ -1410,15 +1500,25 @@
}
if ((mii->mii_media_active & IFM_FDX) != 0)
- net_cfg |= CGEM_NET_CFG_FULL_DUPLEX;
+ sc->net_cfg_shadow |= CGEM_NET_CFG_FULL_DUPLEX;
- WR4(sc, CGEM_NET_CFG, net_cfg);
+ WR4(sc, CGEM_NET_CFG, sc->net_cfg_shadow);
+#ifdef EXT_RESOURCES
+ if (sc->ref_clk != NULL) {
+ CGEM_UNLOCK(sc);
+ if (clk_set_freq(sc->ref_clk, ref_clk_freq, 0))
+ device_printf(sc->dev, "could not set ref clk to %d\n",
+ ref_clk_freq);
+ CGEM_LOCK(sc);
+ }
+#else
/* Set the reference clock if necessary. */
if (cgem_set_ref_clk(sc->ref_clk_num, ref_clk_freq))
device_printf(sc->dev,
"cgem_mediachange: could not set ref clk%d to %d.\n",
sc->ref_clk_num, ref_clk_freq);
+#endif
sc->mii_media_active = mii->mii_media_active;
}
@@ -1646,19 +1746,46 @@
{
struct cgem_softc *sc = device_get_softc(dev);
if_t ifp = NULL;
- phandle_t node;
- pcell_t cell;
int rid, err;
u_char eaddr[ETHER_ADDR_LEN];
+ int hwtype;
+#ifndef EXT_RESOURCES
+ phandle_t node;
+ pcell_t cell;
+#endif
sc->dev = dev;
CGEM_LOCK_INIT(sc);
+ /* Key off of compatible string and set hardware-specific options. */
+ hwtype = ofw_bus_search_compatible(dev, compat_data)->ocd_data;
+ if (hwtype == HWTYPE_ZYNQMP)
+ sc->neednullqs = 1;
+ if (hwtype == HWTYPE_ZYNQ)
+ sc->rxhangwar = 1;
+
+#ifdef EXT_RESOURCES
+ if (hwtype == HWTYPE_ZYNQ || hwtype == HWTYPE_ZYNQMP) {
+ if (clk_get_by_ofw_name(dev, 0, "tx_clk", &sc->ref_clk) != 0)
+ device_printf(dev,
+ "could not retrieve reference clock.\n");
+ else if (clk_enable(sc->ref_clk) != 0)
+ device_printf(dev, "could not enable clock.\n");
+ }
+ else if (hwtype == HWTYPE_SIFIVE_FU540) {
+ if (clk_get_by_ofw_name(dev, 0, "pclk", &sc->ref_clk) != 0)
+ device_printf(dev,
+ "could not retrieve reference clock.\n");
+ else if (clk_enable(sc->ref_clk) != 0)
+ device_printf(dev, "could not enable clock.\n");
+ }
+#else
/* Get reference clock number and base divider from fdt. */
node = ofw_bus_get_node(dev);
sc->ref_clk_num = 0;
if (OF_getprop(node, "ref-clock-num", &cell, sizeof(cell)) > 0)
sc->ref_clk_num = fdt32_to_cpu(cell);
+#endif
/* Get memory resource. */
rid = 0;
@@ -1671,7 +1798,8 @@
/* Get IRQ resource. */
rid = 0;
- sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE);
+ sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
+ RF_ACTIVE);
if (sc->irq_res == NULL) {
device_printf(dev, "could not allocate interrupt resource.\n");
cgem_detach(dev);
@@ -1703,7 +1831,6 @@
sc->if_old_flags = if_getflags(ifp);
sc->rxbufs = DEFAULT_NUM_RX_BUFS;
- sc->rxhangwar = 1;
/* Reset hardware. */
CGEM_LOCK(sc);
@@ -1714,11 +1841,8 @@
err = mii_attach(dev, &sc->miibus, ifp,
cgem_ifmedia_upd, cgem_ifmedia_sts, BMSR_DEFCAPMASK,
MII_PHY_ANY, MII_OFFSET_ANY, 0);
- if (err) {
- device_printf(dev, "attaching PHYs failed\n");
- cgem_detach(dev);
- return (err);
- }
+ if (err)
+ device_printf(dev, "warning: attaching PHYs failed\n");
/* Set up TX and RX descriptor area. */
err = cgem_setup_descs(sc);
@@ -1793,26 +1917,21 @@
bus_dmamap_unload(sc->desc_dma_tag,
sc->rxring_dma_map);
sc->rxring_physaddr = 0;
+ sc->txring_physaddr = 0;
+ sc->null_qs_physaddr = 0;
}
bus_dmamem_free(sc->desc_dma_tag, sc->rxring,
sc->rxring_dma_map);
sc->rxring = NULL;
+ sc->txring = NULL;
+ sc->null_qs = NULL;
+
for (i = 0; i < CGEM_NUM_RX_DESCS; i++)
if (sc->rxring_m_dmamap[i] != NULL) {
bus_dmamap_destroy(sc->mbuf_dma_tag,
sc->rxring_m_dmamap[i]);
sc->rxring_m_dmamap[i] = NULL;
}
- }
- if (sc->txring != NULL) {
- if (sc->txring_physaddr != 0) {
- bus_dmamap_unload(sc->desc_dma_tag,
- sc->txring_dma_map);
- sc->txring_physaddr = 0;
- }
- bus_dmamem_free(sc->desc_dma_tag, sc->txring,
- sc->txring_dma_map);
- sc->txring = NULL;
for (i = 0; i < CGEM_NUM_TX_DESCS; i++)
if (sc->txring_m_dmamap[i] != NULL) {
bus_dmamap_destroy(sc->mbuf_dma_tag,
@@ -1829,6 +1948,13 @@
sc->mbuf_dma_tag = NULL;
}
+#ifdef EXT_RESOURCES
+ if (sc->ref_clk != NULL) {
+ clk_release(sc->ref_clk);
+ sc->ref_clk = NULL;
+ }
+#endif
+
bus_generic_detach(dev);
CGEM_LOCK_DESTROY(sc);
@@ -1842,9 +1968,6 @@
DEVMETHOD(device_attach, cgem_attach),
DEVMETHOD(device_detach, cgem_detach),
- /* Bus interface */
- DEVMETHOD(bus_child_detached, cgem_child_detached),
-
/* MII interface */
DEVMETHOD(miibus_readreg, cgem_miibus_readreg),
DEVMETHOD(miibus_writereg, cgem_miibus_writereg),
@@ -1864,3 +1987,4 @@
DRIVER_MODULE(miibus, cgem, miibus_driver, miibus_devclass, NULL, NULL);
MODULE_DEPEND(cgem, miibus, 1, 1, 1);
MODULE_DEPEND(cgem, ether, 1, 1, 1);
+SIMPLEBUS_PNP_INFO(compat_data);
Index: sys/dev/cadence/if_cgem_hw.h
===================================================================
--- sys/dev/cadence/if_cgem_hw.h
+++ sys/dev/cadence/if_cgem_hw.h
@@ -35,6 +35,10 @@
* Reference: Zynq-7000 All Programmable SoC Technical Reference Manual.
* (v1.4) November 16, 2012. Xilinx doc UG585. GEM is covered in Ch. 16
* and register definitions are in appendix B.18.
+ *
+ * Additional Reference: Zynq UltraScale+ Device Register Reference
+ * (UG1087 v1.7 Feb 8,2019):
+ * https://www.xilinx.com/html_docs/registers/ug1087/ug1087-zynq-ultrascale-registers.html
*/
#ifndef _IF_CGEM_HW_H_
@@ -113,6 +117,7 @@
#define CGEM_USER_IO 0x00C /* User I/O */
#define CGEM_DMA_CFG 0x010 /* DMA Config */
+#define CGEM_DMA_CFG_ADDR_BUS_64 (1 << 30)
#define CGEM_DMA_CFG_DISC_WHEN_NO_AHB (1 << 24)
#define CGEM_DMA_CFG_RX_BUF_SIZE_SHIFT 16
#define CGEM_DMA_CFG_RX_BUF_SIZE_MASK (0xff << 16)
@@ -290,6 +295,29 @@
#define CGEM_PTP_PEER_RX_S 0x1F8 /* PTP Peer Event rcv'd s */
#define CGEM_PTP_PEER_RX_NS 0x1FC /* PTP Peer Event rcv'd ns */
+#define CGEM_DESIGN_CFG1 0x280 /* Design Configuration 1 */
+#define CGEM_DESIGN_CFG1_AXI_CACHE_WIDTH_MASK (0xfU << 28)
+#define CGEM_DESIGN_CFG1_DMA_BUS_WIDTH_MASK (7 << 25)
+#define CGEM_DESIGN_CFG1_DMA_BUS_WIDTH_32 (1 << 25)
+#define CGEM_DESIGN_CFG1_DMA_BUS_WIDTH_64 (2 << 25)
+#define CGEM_DESIGN_CFG1_DMA_BUS_WIDTH_128 (4 << 25)
+#define CGEM_DESIGN_CFG1_IRQ_READ_CLR (1 << 23)
+#define CGEM_DESIGN_CFG1_NO_SNAPSHOT (1 << 22)
+#define CGEM_DESIGN_CFG1_NO_STATS (1 << 21)
+#define CGEM_DESIGN_CFG1_NO_SCAN_PINS (1 << 20)
+#define CGEM_DESIGN_CFG1_USER_IN_WIDTH_MASK (0x1f << 15)
+#define CGEM_DESIGN_CFG1_USER_OUT_WIDTH_MASK (0x1f << 10)
+#define CGEM_DESIGN_CFG1_USER_IO (1 << 9)
+#define CGEM_DESIGN_CFG1_APB_REV2 (1 << 8)
+#define CGEM_DESIGN_CFG1_APB_REV1 (1 << 7)
+#define CGEM_DESIGN_CFG1_EXT_FIFO_INTERFACE (1 << 6)
+#define CGEM_DESIGN_CFG1_NO_INT_LOOPBACK (1 << 5)
+#define CGEM_DESIGN_CFG1_INT_LOOPBACK (1 << 4)
+#define CGEM_DESIGN_CFG1_TDC_50 (1 << 3)
+#define CGEM_DESIGN_CFG1_RDC_50 (1 << 2)
+#define CGEM_DESIGN_CFG1_SERDES (1 << 1)
+#define CGEM_DESIGN_CFG1_NO_PCS (1 << 0)
+
#define CGEM_DESIGN_CFG2 0x284 /* Design Configuration 2 */
#define CGEM_DESIGN_CFG2_TX_PBUF_ADDR_SHIFT 26
#define CGEM_DESIGN_CFG2_TX_PBUF_ADDR_MASK (0xf << 26)
@@ -330,7 +358,25 @@
#define CGEM_DESIGN_CFG5_TX_FIFO_CNT_WIDTH_MASK (0xf << 4)
#define CGEM_DESIGN_CFG5_RX_FIFO_CNT_WIDTH_MASK 0xf
-/* Transmit Descriptors */
+#define CGEM_DESIGN_CFG6 0x294 /* Design Configuration 6 */
+#define CGEM_DESIGN_CFG6_ADDR_64B (1 << 23) /* 64-bit addr cap */
+#define CGEM_DESIGN_CFG6_DMA_PRIO_Q_MASK 0xfffe
+#define CGEM_DESIGN_CFG6_DMA_PRIO_Q(n) (1 << (n))
+
+#define CGEM_TX_QN_BAR(n) (0x440 + ((n) - 1) * 4)
+#define CGEM_RX_QN_BAR(n) (0x480 + ((n) - 1) * 4)
+
+#define CGEM_TX_QBAR_HI 0x4C8
+#define CGEM_RX_QBAR_HI 0x4D4
+
+/*
+ * Transmit Descriptors: two or four 32-bit words:
+ * word0: address
+ * word1: length and control
+ * word2: address upper 32-bits (64-bit mode)
+ * word3: unused (64-bit mode)
+ */
+
struct cgem_tx_desc {
uint32_t addr;
uint32_t ctl;
@@ -350,8 +396,20 @@
#define CGEM_TXDESC_NO_CRC_APPENDED (1 << 16)
#define CGEM_TXDESC_LAST_BUF (1 << 15) /* last in frame */
#define CGEM_TXDESC_LENGTH_MASK 0x3fff
+#ifdef CGEM64
+ uint32_t addrhi;
+ uint32_t unused;
+#endif
};
+/*
+ * Receive Descriptors: two or four 32-bit words:
+ * word0: address | WRAP and OWN flags
+ * word1: length and control
+ * word2: address upper 32 bits (64-bit mode)
+ * word3: unused
+ */
+
struct cgem_rx_desc {
uint32_t addr;
#define CGEM_RXDESC_WRAP (1 << 1) /* goes in addr! */
@@ -379,6 +437,10 @@
#define CGEM_RXDESC_SOF (1 << 14) /* start of frame */
#define CGEM_RXDESC_BAD_FCS (1 << 13)
#define CGEM_RXDESC_LENGTH_MASK 0x1fff
+#ifdef CGEM64
+ uint32_t addrhi;
+ uint32_t unused;
+#endif
};
#endif /* _IF_CGEM_HW_H_ */
Index: sys/dts/arm/zynq-7000.dtsi
===================================================================
--- sys/dts/arm/zynq-7000.dtsi
+++ sys/dts/arm/zynq-7000.dtsi
@@ -177,7 +177,7 @@
// Gigabit Ethernet controllers
eth0: eth@b000 {
device_type = "network";
- compatible = "cadence,gem";
+ compatible = "cdns,zynq-gem", "cadence,gem";
status = "disabled";
reg = <0xb000 0x1000>;
interrupts = <0 22 4>;
@@ -187,7 +187,7 @@
eth1: eth@c000 {
device_type = "network";
- compatible = "cadence,gem";
+ compatible = "cdns,zynq-gem", "cadence,gem";
status = "disabled";
reg = <0xc000 0x1000>;
interrupts = <0 45 4>;

File Metadata

Mime Type
text/plain
Expires
Thu, May 1, 11:37 AM (10 h, 18 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
17880408
Default Alt Text
D24304.id75253.diff (41 KB)

Event Timeline