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); }