From a8692c16c962027f141facc357ee28578ccf04b7 Mon Sep 17 00:00:00 2001
From: Ruslan Bukin
Date: Fri, 7 Feb 2020 14:36:28 +0000
Subject: [PATCH] Fix xae(4) driver attachement on the Government Furnished
Equipment (GFE) riscv cores.
GFE cores come with standard DTS file that lacks standard 'dmas ='
property, which means xae(4) could not find a DMA controller to use.
The 'dmas' property could not be added to the DTS file because the
ethernet controller and DMA engine parts in Linux are implemented
in a single driver.
Instead of 'dmas' property the standard Xilinx 'axistream-connected'
property is provided, so fallback to use it instead.
Suggested by: James Clarke
Reviewed by: James Clarke
Sponsored by: DARPA, AFRL
---
sys/dev/xdma/xdma.c | 18 ++++++++++
sys/dev/xdma/xdma.h | 1 +
sys/dev/xilinx/axidma.c | 18 +++++-----
sys/dev/xilinx/axidma.h | 16 ++++-----
sys/dev/xilinx/if_xae.c | 79 +++++++++++++++++++++++++++++++++++++----
5 files changed, 108 insertions(+), 24 deletions(-)
diff --git a/sys/dev/xdma/xdma.c b/sys/dev/xdma/xdma.c
index d88cb1306536..aa6e6497a34c 100644
--- a/sys/dev/xdma/xdma.c
+++ b/sys/dev/xdma/xdma.c
@@ -510,6 +510,24 @@ xdma_ofw_get(device_t dev, const char *prop)
}
#endif
+/*
+ * Allocate xdma controller.
+ */
+xdma_controller_t *
+xdma_get(device_t dev, device_t dma_dev)
+{
+ xdma_controller_t *xdma;
+
+ xdma = malloc(sizeof(struct xdma_controller),
+ M_XDMA, M_WAITOK | M_ZERO);
+ xdma->dev = dev;
+ xdma->dma_dev = dma_dev;
+
+ TAILQ_INIT(&xdma->channels);
+
+ return (xdma);
+}
+
/*
* Free xDMA controller object.
*/
diff --git a/sys/dev/xdma/xdma.h b/sys/dev/xdma/xdma.h
index 48a03c125b3a..b9a8dd2c37c3 100644
--- a/sys/dev/xdma/xdma.h
+++ b/sys/dev/xdma/xdma.h
@@ -231,6 +231,7 @@ static MALLOC_DEFINE(M_XDMA, "xdma", "xDMA framework");
/* xDMA controller ops */
xdma_controller_t *xdma_ofw_get(device_t dev, const char *prop);
+xdma_controller_t *xdma_get(device_t dev, device_t dma_dev);
int xdma_put(xdma_controller_t *xdma);
vmem_t * xdma_get_memory(device_t dev);
void xdma_put_memory(vmem_t *vmem);
diff --git a/sys/dev/xilinx/axidma.c b/sys/dev/xilinx/axidma.c
index 3c9b1b5c6dc7..32683de787d3 100644
--- a/sys/dev/xilinx/axidma.c
+++ b/sys/dev/xilinx/axidma.c
@@ -61,6 +61,15 @@ __FBSDID("$FreeBSD$");
#include "xdma_if.h"
+#define READ4(_sc, _reg) \
+ bus_space_read_4(_sc->bst, _sc->bsh, _reg)
+#define WRITE4(_sc, _reg, _val) \
+ bus_space_write_4(_sc->bst, _sc->bsh, _reg, _val)
+#define READ8(_sc, _reg) \
+ bus_space_read_8(_sc->bst, _sc->bsh, _reg)
+#define WRITE8(_sc, _reg, _val) \
+ bus_space_write_8(_sc->bst, _sc->bsh, _reg, _val)
+
#define AXIDMA_DEBUG
#undef AXIDMA_DEBUG
@@ -70,17 +79,8 @@ __FBSDID("$FreeBSD$");
#define dprintf(fmt, ...)
#endif
-#define AXIDMA_NCHANNELS 2
-#define AXIDMA_DESCS_NUM 512
-#define AXIDMA_TX_CHAN 0
-#define AXIDMA_RX_CHAN 1
-
extern struct bus_space memmap_bus;
-struct axidma_fdt_data {
- int id;
-};
-
struct axidma_channel {
struct axidma_softc *sc;
xdma_channel_t *xchan;
diff --git a/sys/dev/xilinx/axidma.h b/sys/dev/xilinx/axidma.h
index 8e5d83874eee..addacb463d2a 100644
--- a/sys/dev/xilinx/axidma.h
+++ b/sys/dev/xilinx/axidma.h
@@ -60,14 +60,10 @@
#define AXI_TAILDESC_MSB(n) (0x14 + 0x30 * (n)) /* Tail Descriptor Pointer. Upper 32 bits of address. */
#define AXI_SG_CTL 0x2C /* Scatter/Gather User and Cache */
-#define READ4(_sc, _reg) \
- bus_space_read_4(_sc->bst, _sc->bsh, _reg)
-#define WRITE4(_sc, _reg, _val) \
- bus_space_write_4(_sc->bst, _sc->bsh, _reg, _val)
-#define READ8(_sc, _reg) \
- bus_space_read_8(_sc->bst, _sc->bsh, _reg)
-#define WRITE8(_sc, _reg, _val) \
- bus_space_write_8(_sc->bst, _sc->bsh, _reg, _val)
+#define AXIDMA_NCHANNELS 2
+#define AXIDMA_DESCS_NUM 512
+#define AXIDMA_TX_CHAN 0
+#define AXIDMA_RX_CHAN 1
struct axidma_desc {
uint32_t next;
@@ -93,4 +89,8 @@ struct axidma_desc {
uint32_t reserved[3];
};
+struct axidma_fdt_data {
+ int id;
+};
+
#endif /* !_DEV_XILINX_AXIDMA_H_ */
diff --git a/sys/dev/xilinx/if_xae.c b/sys/dev/xilinx/if_xae.c
index bde6470c4376..e6dbb15de75e 100644
--- a/sys/dev/xilinx/if_xae.c
+++ b/sys/dev/xilinx/if_xae.c
@@ -64,6 +64,8 @@ __FBSDID("$FreeBSD$");
#include
#include
+#include
+
#include "miibus_if.h"
#define READ4(_sc, _reg) \
@@ -774,6 +776,68 @@ xae_phy_fixup(struct xae_softc *sc)
} while ((PHY1_RD(sc, MII_BMSR) & BMSR_ACOMP) == 0);
}
+static int
+get_xdma_std(struct xae_softc *sc)
+{
+
+ sc->xdma_tx = xdma_ofw_get(sc->dev, "tx");
+ if (sc->xdma_tx == NULL)
+ return (ENXIO);
+
+ sc->xdma_rx = xdma_ofw_get(sc->dev, "rx");
+ if (sc->xdma_rx == NULL) {
+ xdma_put(sc->xdma_tx);
+ return (ENXIO);
+ }
+
+ return (0);
+}
+
+static int
+get_xdma_axistream(struct xae_softc *sc)
+{
+ struct axidma_fdt_data *data;
+ device_t dma_dev;
+ phandle_t node;
+ pcell_t prop;
+ size_t len;
+
+ node = ofw_bus_get_node(sc->dev);
+ len = OF_getencprop(node, "axistream-connected", &prop, sizeof(prop));
+ if (len != sizeof(prop)) {
+ device_printf(sc->dev,
+ "%s: Couldn't get axistream-connected prop.\n", __func__);
+ return (ENXIO);
+ }
+ dma_dev = OF_device_from_xref(prop);
+ if (dma_dev == NULL) {
+ device_printf(sc->dev, "Could not get DMA device by xref.\n");
+ return (ENXIO);
+ }
+
+ sc->xdma_tx = xdma_get(sc->dev, dma_dev);
+ if (sc->xdma_tx == NULL) {
+ device_printf(sc->dev, "Could not find DMA controller.\n");
+ return (ENXIO);
+ }
+ data = malloc(sizeof(struct axidma_fdt_data),
+ M_DEVBUF, (M_WAITOK | M_ZERO));
+ data->id = AXIDMA_TX_CHAN;
+ sc->xdma_tx->data = data;
+
+ sc->xdma_rx = xdma_get(sc->dev, dma_dev);
+ if (sc->xdma_rx == NULL) {
+ device_printf(sc->dev, "Could not find DMA controller.\n");
+ return (ENXIO);
+ }
+ data = malloc(sizeof(struct axidma_fdt_data),
+ M_DEVBUF, (M_WAITOK | M_ZERO));
+ data->id = AXIDMA_RX_CHAN;
+ sc->xdma_rx->data = data;
+
+ return (0);
+}
+
static int
setup_xdma(struct xae_softc *sc)
{
@@ -784,15 +848,16 @@ setup_xdma(struct xae_softc *sc)
dev = sc->dev;
/* Get xDMA controller */
- sc->xdma_tx = xdma_ofw_get(sc->dev, "tx");
- if (sc->xdma_tx == NULL) {
- device_printf(dev, "Could not find DMA controller.\n");
- return (ENXIO);
+ error = get_xdma_std(sc);
+
+ if (error) {
+ device_printf(sc->dev,
+ "Fallback to axistream-connected property\n");
+ error = get_xdma_axistream(sc);
}
- sc->xdma_rx = xdma_ofw_get(sc->dev, "rx");
- if (sc->xdma_rx == NULL) {
- device_printf(dev, "Could not find DMA controller.\n");
+ if (error) {
+ device_printf(dev, "Could not find xDMA controllers.\n");
return (ENXIO);
}