summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorloos <loos@FreeBSD.org>2015-09-20 14:13:29 +0000
committerloos <loos@FreeBSD.org>2015-09-20 14:13:29 +0000
commit1387cdb079f40f2a965b68d3b6b13a050b468f90 (patch)
tree0d4caf00a5660189dd641bf82edef118132e1181 /sys
parent231461089380388ab68241e0d48da5b195c597dd (diff)
downloadFreeBSD-src-1387cdb079f40f2a965b68d3b6b13a050b468f90.zip
FreeBSD-src-1387cdb079f40f2a965b68d3b6b13a050b468f90.tar.gz
Add alternate descriptors support for if_dwc.
This also adds a newbus interface that allows a SoC to override the following settings: - if_dwc specific SoC initialization; - if_dwc descriptor type; - if_dwc MII clock. This seems to be an old version of the hardware descriptors but it is still in use in a few SoCs (namely Allwinner A20 and Amlogic at least). Tested on Cubieboard2 and Banana pi. Tested for regressions on Altera Cyclone by br@ (old version). Obtained from: NetBSD
Diffstat (limited to 'sys')
-rw-r--r--sys/arm/altera/socfpga/files.socfpga1
-rw-r--r--sys/arm/amlogic/aml8726/files.aml87262
-rw-r--r--sys/conf/files.arm2
-rw-r--r--sys/dev/dwc/if_dwc.c109
-rw-r--r--sys/dev/dwc/if_dwc_if.m76
-rw-r--r--sys/dev/dwc/if_dwcvar.h99
6 files changed, 219 insertions, 70 deletions
diff --git a/sys/arm/altera/socfpga/files.socfpga b/sys/arm/altera/socfpga/files.socfpga
index 901069b..8c930df 100644
--- a/sys/arm/altera/socfpga/files.socfpga
+++ b/sys/arm/altera/socfpga/files.socfpga
@@ -15,7 +15,6 @@ arm/altera/socfpga/socfpga_rstmgr.c standard
arm/altera/socfpga/socfpga_mp.c optional smp
arm/altera/socfpga/socfpga_gpio.c optional gpio
-dev/dwc/if_dwc.c optional dwc
dev/mii/micphy.c optional micphy
dev/mmc/host/dwmmc.c optional dwmmc
diff --git a/sys/arm/amlogic/aml8726/files.aml8726 b/sys/arm/amlogic/aml8726/files.aml8726
index e4bc31e..0f198aa 100644
--- a/sys/arm/amlogic/aml8726/files.aml8726
+++ b/sys/arm/amlogic/aml8726/files.aml8726
@@ -32,5 +32,3 @@ arm/amlogic/aml8726/aml8726_pinctrl.c optional fdt_pinctrl
arm/amlogic/aml8726/uart_dev_aml8726.c optional uart
arm/amlogic/aml8726/aml8726_usb_phy-m3.c optional dwcotg usb gpio
arm/amlogic/aml8726/aml8726_usb_phy-m6.c optional dwcotg usb gpio
-
-dev/dwc/if_dwc.c optional dwc
diff --git a/sys/conf/files.arm b/sys/conf/files.arm
index 743fd86..8f03809 100644
--- a/sys/conf/files.arm
+++ b/sys/conf/files.arm
@@ -84,6 +84,8 @@ cddl/dev/dtrace/arm/dtrace_subr.c optional dtrace compile-with "${DTRACE_C}"
cddl/dev/fbt/arm/fbt_isa.c optional dtrace_fbt | dtraceall compile-with "${FBT_C}"
crypto/blowfish/bf_enc.c optional crypto | ipsec
crypto/des/des_enc.c optional crypto | ipsec | netsmb
+dev/dwc/if_dwc.c optional dwc
+dev/dwc/if_dwc_if.m optional dwc
dev/fb/fb.c optional sc
dev/fdt/fdt_arm_platform.c optional platform fdt
dev/hwpmc/hwpmc_arm.c optional hwpmc
diff --git a/sys/dev/dwc/if_dwc.c b/sys/dev/dwc/if_dwc.c
index c1cfe2c..e25d7f5 100644
--- a/sys/dev/dwc/if_dwc.c
+++ b/sys/dev/dwc/if_dwc.c
@@ -63,11 +63,13 @@ __FBSDID("$FreeBSD$");
#include <machine/bus.h>
#include <dev/dwc/if_dwc.h>
+#include <dev/dwc/if_dwcvar.h>
#include <dev/mii/mii.h>
#include <dev/mii/miivar.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
+#include "if_dwc_if.h"
#include "miibus_if.h"
#define READ4(_sc, _reg) \
@@ -78,7 +80,6 @@ __FBSDID("$FreeBSD$");
#define MAC_RESET_TIMEOUT 100
#define WATCHDOG_TIMEOUT_SECS 5
#define STATS_HARVEST_INTERVAL 2
-#define MII_CLK_VAL 2
#define DWC_LOCK(sc) mtx_lock(&(sc)->mtx)
#define DWC_UNLOCK(sc) mtx_unlock(&(sc)->mtx)
@@ -98,77 +99,34 @@ __FBSDID("$FreeBSD$");
#define DDESC_RDES0_FL_SHIFT 16 /* Frame Length */
#define DDESC_RDES1_CHAINED (1U << 14)
-struct dwc_bufmap {
- bus_dmamap_t map;
- struct mbuf *mbuf;
-};
+/* Alt descriptor bits. */
+#define DDESC_CNTL_TXINT (1U << 31)
+#define DDESC_CNTL_TXLAST (1U << 30)
+#define DDESC_CNTL_TXFIRST (1U << 29)
+#define DDESC_CNTL_TXCRCDIS (1U << 26)
+#define DDESC_CNTL_TXRINGEND (1U << 25)
+#define DDESC_CNTL_TXCHAIN (1U << 24)
+
+#define DDESC_CNTL_CHAINED (1U << 24)
/*
* A hardware buffer descriptor. Rx and Tx buffers have the same descriptor
- * layout, but the bits in the flags field have different meanings.
+ * layout, but the bits in the fields have different meanings.
*/
struct dwc_hwdesc
{
- uint32_t tdes0;
- uint32_t tdes1;
+ uint32_t tdes0; /* status for alt layout */
+ uint32_t tdes1; /* cntl for alt layout */
uint32_t addr; /* pointer to buffer data */
uint32_t addr_next; /* link to next descriptor */
};
/*
- * Driver data and defines.
- */
-#define RX_DESC_COUNT 1024
-#define RX_DESC_SIZE (sizeof(struct dwc_hwdesc) * RX_DESC_COUNT)
-#define TX_DESC_COUNT 1024
-#define TX_DESC_SIZE (sizeof(struct dwc_hwdesc) * TX_DESC_COUNT)
-
-/*
* The hardware imposes alignment restrictions on various objects involved in
* DMA transfers. These values are expressed in bytes (not bits).
*/
#define DWC_DESC_RING_ALIGN 2048
-struct dwc_softc {
- struct resource *res[2];
- bus_space_tag_t bst;
- bus_space_handle_t bsh;
- device_t dev;
- int mii_clk;
- device_t miibus;
- struct mii_data * mii_softc;
- struct ifnet *ifp;
- int if_flags;
- struct mtx mtx;
- void * intr_cookie;
- struct callout dwc_callout;
- boolean_t link_is_up;
- boolean_t is_attached;
- boolean_t is_detaching;
- int tx_watchdog_count;
- int stats_harvest_count;
-
- /* RX */
- bus_dma_tag_t rxdesc_tag;
- bus_dmamap_t rxdesc_map;
- struct dwc_hwdesc *rxdesc_ring;
- bus_addr_t rxdesc_ring_paddr;
- bus_dma_tag_t rxbuf_tag;
- struct dwc_bufmap rxbuf_map[RX_DESC_COUNT];
- uint32_t rx_idx;
-
- /* TX */
- bus_dma_tag_t txdesc_tag;
- bus_dmamap_t txdesc_map;
- struct dwc_hwdesc *txdesc_ring;
- bus_addr_t txdesc_ring_paddr;
- bus_dma_tag_t txbuf_tag;
- struct dwc_bufmap txbuf_map[RX_DESC_COUNT];
- uint32_t tx_idx_head;
- uint32_t tx_idx_tail;
- int txcount;
-};
-
static struct resource_spec dwc_spec[] = {
{ SYS_RES_MEMORY, 0, RF_ACTIVE },
{ SYS_RES_IRQ, 0, RF_ACTIVE },
@@ -217,14 +175,23 @@ dwc_setup_txdesc(struct dwc_softc *sc, int idx, bus_addr_t paddr,
flags = 0;
--sc->txcount;
} else {
- flags = DDESC_TDES0_TXCHAIN | DDESC_TDES0_TXFIRST
- | DDESC_TDES0_TXLAST | DDESC_TDES0_TXINT;
+ if (sc->mactype == DWC_GMAC_ALT_DESC)
+ flags = DDESC_CNTL_TXCHAIN | DDESC_CNTL_TXFIRST
+ | DDESC_CNTL_TXLAST | DDESC_CNTL_TXINT;
+ else
+ flags = DDESC_TDES0_TXCHAIN | DDESC_TDES0_TXFIRST
+ | DDESC_TDES0_TXLAST | DDESC_TDES0_TXINT;
++sc->txcount;
}
sc->txdesc_ring[idx].addr = (uint32_t)(paddr);
- sc->txdesc_ring[idx].tdes0 = flags;
- sc->txdesc_ring[idx].tdes1 = len;
+ if (sc->mactype == DWC_GMAC_ALT_DESC) {
+ sc->txdesc_ring[idx].tdes0 = 0;
+ sc->txdesc_ring[idx].tdes1 = flags | len;
+ } else {
+ sc->txdesc_ring[idx].tdes0 = flags;
+ sc->txdesc_ring[idx].tdes1 = len;
+ }
if (paddr && len) {
wmb();
@@ -497,7 +464,10 @@ dwc_setup_rxdesc(struct dwc_softc *sc, int idx, bus_addr_t paddr)
nidx = next_rxidx(sc, idx);
sc->rxdesc_ring[idx].addr_next = sc->rxdesc_ring_paddr + \
(nidx * sizeof(struct dwc_hwdesc));
- sc->rxdesc_ring[idx].tdes1 = DDESC_RDES1_CHAINED | MCLBYTES;
+ if (sc->mactype == DWC_GMAC_ALT_DESC)
+ sc->rxdesc_ring[idx].tdes1 = DDESC_CNTL_CHAINED | RX_MAX_PACKET;
+ else
+ sc->rxdesc_ring[idx].tdes1 = DDESC_RDES1_CHAINED | MCLBYTES;
wmb();
sc->rxdesc_ring[idx].tdes0 = DDESC_RDES0_OWN;
@@ -1065,10 +1035,13 @@ dwc_attach(device_t dev)
sc = device_get_softc(dev);
sc->dev = dev;
- sc->mii_clk = MII_CLK_VAL;
sc->rx_idx = 0;
-
sc->txcount = TX_DESC_COUNT;
+ sc->mii_clk = IF_DWC_MII_CLK(dev);
+ sc->mactype = IF_DWC_MAC_TYPE(dev);
+
+ if (IF_DWC_INIT(dev) != 0)
+ return (ENXIO);
if (bus_alloc_resources(dev, dwc_spec, sc->res)) {
device_printf(dev, "could not allocate resources\n");
@@ -1100,8 +1073,11 @@ dwc_attach(device_t dev)
return (ENXIO);
}
- reg = READ4(sc, BUS_MODE);
- reg |= (BUS_MODE_EIGHTXPBL);
+ if (sc->mactype == DWC_GMAC_ALT_DESC) {
+ reg = BUS_MODE_FIXEDBURST;
+ reg |= (BUS_MODE_PRIORXTX_41 << BUS_MODE_PRIORXTX_SHIFT);
+ } else
+ reg = (BUS_MODE_EIGHTXPBL);
reg |= (BUS_MODE_PBL_BEATS_8 << BUS_MODE_PBL_SHIFT);
WRITE4(sc, BUS_MODE, reg);
@@ -1146,7 +1122,6 @@ dwc_attach(device_t dev)
IFQ_SET_MAXLEN(&ifp->if_snd, TX_DESC_COUNT - 1);
ifp->if_snd.ifq_drv_maxlen = TX_DESC_COUNT - 1;
IFQ_SET_READY(&ifp->if_snd);
- ifp->if_hdrlen = sizeof(struct ether_vlan_header);
/* Attach the mii driver. */
error = mii_attach(dev, &sc->miibus, ifp, dwc_media_change,
@@ -1285,7 +1260,7 @@ static device_method_t dwc_methods[] = {
{ 0, 0 }
};
-static driver_t dwc_driver = {
+driver_t dwc_driver = {
"dwc",
dwc_methods,
sizeof(struct dwc_softc),
diff --git a/sys/dev/dwc/if_dwc_if.m b/sys/dev/dwc/if_dwc_if.m
new file mode 100644
index 0000000..feecb4e
--- /dev/null
+++ b/sys/dev/dwc/if_dwc_if.m
@@ -0,0 +1,76 @@
+#-
+# Copyright (c) 2015 Luiz Otavio O Souza <loos@FreeBSD.org>
+# Copyright (c) 2014 Ruslan Bukin <br@bsdpad.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. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# 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$
+#
+
+INTERFACE if_dwc;
+
+#include <dev/dwc/if_dwc.h>
+
+CODE {
+ static int
+ if_dwc_default_init(device_t dev)
+ {
+ return (0);
+ }
+
+ static int
+ if_dwc_default_mac_type(device_t dev)
+ {
+ return (DWC_GMAC);
+ }
+
+ static int
+ if_dwc_default_mii_clk(device_t dev)
+ {
+ return (GMAC_MII_CLK_25_35M_DIV16);
+ }
+};
+
+HEADER {
+};
+
+#
+# Initialize the SoC specific registers.
+#
+METHOD int init {
+ device_t dev;
+} DEFAULT if_dwc_default_init;
+
+#
+# Return the DWC MAC type (descriptor type).
+#
+METHOD int mac_type {
+ device_t dev;
+} DEFAULT if_dwc_default_mac_type;
+
+#
+# Return the DWC MII clock for a specific hardware.
+#
+METHOD int mii_clk {
+ device_t dev;
+} DEFAULT if_dwc_default_mii_clk;
diff --git a/sys/dev/dwc/if_dwcvar.h b/sys/dev/dwc/if_dwcvar.h
new file mode 100644
index 0000000..3dd6a8d
--- /dev/null
+++ b/sys/dev/dwc/if_dwcvar.h
@@ -0,0 +1,99 @@
+/*-
+ * Copyright (c) 2014 Ruslan Bukin <br@bsdpad.com>
+ * All rights reserved.
+ *
+ * This software was developed by SRI International and the University of
+ * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
+ * ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
+ * 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. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 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$
+ */
+
+/*
+ * Ethernet media access controller (EMAC)
+ * Chapter 17, Altera Cyclone V Device Handbook (CV-5V2 2014.07.22)
+ *
+ * EMAC is an instance of the Synopsys DesignWare 3504-0
+ * Universal 10/100/1000 Ethernet MAC (DWC_gmac).
+ */
+
+#ifndef __IF_DWCVAR_H__
+#define __IF_DWCVAR_H__
+
+/*
+ * Driver data and defines.
+ */
+#define RX_MAX_PACKET 0x7ff
+#define RX_DESC_COUNT 1024
+#define RX_DESC_SIZE (sizeof(struct dwc_hwdesc) * RX_DESC_COUNT)
+#define TX_DESC_COUNT 1024
+#define TX_DESC_SIZE (sizeof(struct dwc_hwdesc) * TX_DESC_COUNT)
+
+struct dwc_bufmap {
+ bus_dmamap_t map;
+ struct mbuf *mbuf;
+};
+
+struct dwc_softc {
+ struct resource *res[2];
+ bus_space_tag_t bst;
+ bus_space_handle_t bsh;
+ device_t dev;
+ int mactype;
+ int mii_clk;
+ device_t miibus;
+ struct mii_data * mii_softc;
+ struct ifnet *ifp;
+ int if_flags;
+ struct mtx mtx;
+ void * intr_cookie;
+ struct callout dwc_callout;
+ boolean_t link_is_up;
+ boolean_t is_attached;
+ boolean_t is_detaching;
+ int tx_watchdog_count;
+ int stats_harvest_count;
+
+ /* RX */
+ bus_dma_tag_t rxdesc_tag;
+ bus_dmamap_t rxdesc_map;
+ struct dwc_hwdesc *rxdesc_ring;
+ bus_addr_t rxdesc_ring_paddr;
+ bus_dma_tag_t rxbuf_tag;
+ struct dwc_bufmap rxbuf_map[RX_DESC_COUNT];
+ uint32_t rx_idx;
+
+ /* TX */
+ bus_dma_tag_t txdesc_tag;
+ bus_dmamap_t txdesc_map;
+ struct dwc_hwdesc *txdesc_ring;
+ bus_addr_t txdesc_ring_paddr;
+ bus_dma_tag_t txbuf_tag;
+ struct dwc_bufmap txbuf_map[RX_DESC_COUNT];
+ uint32_t tx_idx_head;
+ uint32_t tx_idx_tail;
+ int txcount;
+};
+
+#endif /* __IF_DWCVAR_H__ */
OpenPOWER on IntegriCloud