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 <jrtc27@jrtc27.com>
Reviewed by:	James Clarke <jrtc27@jrtc27.com>
Sponsored by:	DARPA, AFRL
This commit is contained in:
Ruslan Bukin 2020-02-07 14:36:28 +00:00
parent 79208b1025
commit a8692c16c9
5 changed files with 108 additions and 24 deletions

View File

@ -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.
*/

View File

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

View File

@ -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;

View File

@ -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_ */

View File

@ -64,6 +64,8 @@ __FBSDID("$FreeBSD$");
#include <dev/xilinx/if_xaereg.h>
#include <dev/xilinx/if_xaevar.h>
#include <dev/xilinx/axidma.h>
#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);
}