Module Name: src Committed By: jmcneill Date: Thu Feb 20 01:35:55 UTC 2020
Modified Files: src/sys/arch/evbarm/conf: files.fdt src/sys/dev/fdt: fdt_subr.c fdtbus.c fdtvar.h Added Files: src/sys/arch/evbarm/fdt: fdt_dma_machdep.c Log Message: Add dma-ranges support. To generate a diff of this commit: cvs rdiff -u -r1.5 -r1.6 src/sys/arch/evbarm/conf/files.fdt cvs rdiff -u -r0 -r1.1 src/sys/arch/evbarm/fdt/fdt_dma_machdep.c cvs rdiff -u -r1.33 -r1.34 src/sys/dev/fdt/fdt_subr.c cvs rdiff -u -r1.32 -r1.33 src/sys/dev/fdt/fdtbus.c cvs rdiff -u -r1.59 -r1.60 src/sys/dev/fdt/fdtvar.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/evbarm/conf/files.fdt diff -u src/sys/arch/evbarm/conf/files.fdt:1.5 src/sys/arch/evbarm/conf/files.fdt:1.6 --- src/sys/arch/evbarm/conf/files.fdt:1.5 Tue Oct 30 22:32:33 2018 +++ src/sys/arch/evbarm/conf/files.fdt Thu Feb 20 01:35:55 2020 @@ -1,8 +1,9 @@ -# $NetBSD: files.fdt,v 1.5 2018/10/30 22:32:33 jmcneill Exp $ +# $NetBSD: files.fdt,v 1.6 2020/02/20 01:35:55 jmcneill Exp $ # # FDT-based kernel configuration info # +file arch/evbarm/fdt/fdt_dma_machdep.c fdt file arch/evbarm/fdt/fdt_machdep.c fdt file arch/evbarm/fdt/fdt_memory.c fdt Index: src/sys/dev/fdt/fdt_subr.c diff -u src/sys/dev/fdt/fdt_subr.c:1.33 src/sys/dev/fdt/fdt_subr.c:1.34 --- src/sys/dev/fdt/fdt_subr.c:1.33 Sun Feb 16 20:28:18 2020 +++ src/sys/dev/fdt/fdt_subr.c Thu Feb 20 01:35:55 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: fdt_subr.c,v 1.33 2020/02/16 20:28:18 thorpej Exp $ */ +/* $NetBSD: fdt_subr.c,v 1.34 2020/02/20 01:35:55 jmcneill Exp $ */ /*- * Copyright (c) 2015 Jared D. McNeill <jmcne...@invisible.ca> @@ -27,7 +27,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: fdt_subr.c,v 1.33 2020/02/16 20:28:18 thorpej Exp $"); +__KERNEL_RCSID(0, "$NetBSD: fdt_subr.c,v 1.34 2020/02/20 01:35:55 jmcneill Exp $"); #include "opt_fdt.h" @@ -95,7 +95,7 @@ fdtbus_set_decoderegprop(bool decode) fdtbus_decoderegprop = decode; } -static int +int fdtbus_get_addr_cells(int phandle) { uint32_t addr_cells; @@ -106,7 +106,7 @@ fdtbus_get_addr_cells(int phandle) return addr_cells; } -static int +int fdtbus_get_size_cells(int phandle) { uint32_t size_cells; @@ -193,7 +193,7 @@ fdtbus_get_path(int phandle, char *buf, return true; } -static uint64_t +uint64_t fdtbus_get_cells(const uint8_t *buf, int cells) { switch (cells) { Index: src/sys/dev/fdt/fdtbus.c diff -u src/sys/dev/fdt/fdtbus.c:1.32 src/sys/dev/fdt/fdtbus.c:1.33 --- src/sys/dev/fdt/fdtbus.c:1.32 Tue Jan 28 08:09:19 2020 +++ src/sys/dev/fdt/fdtbus.c Thu Feb 20 01:35:55 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: fdtbus.c,v 1.32 2020/01/28 08:09:19 martin Exp $ */ +/* $NetBSD: fdtbus.c,v 1.33 2020/02/20 01:35:55 jmcneill Exp $ */ /*- * Copyright (c) 2015 Jared D. McNeill <jmcne...@invisible.ca> @@ -27,7 +27,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: fdtbus.c,v 1.32 2020/01/28 08:09:19 martin Exp $"); +__KERNEL_RCSID(0, "$NetBSD: fdtbus.c,v 1.33 2020/02/20 01:35:55 jmcneill Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -202,6 +202,7 @@ fdt_init_attach_args(const struct fdt_at faa->faa_phandle = node->n_phandle; faa->faa_name = node->n_name; faa->faa_quiet = quiet; + faa->faa_dmat = node->n_faa.faa_dmat; } static bool @@ -230,6 +231,66 @@ fdt_add_bus_match(device_t bus, const in } } +static int +fdt_dma_translate(int phandle, struct fdt_dma_range **ranges, u_int *nranges) +{ + const uint8_t *data; + int len, n; + + const int parent = OF_parent(phandle); + if (parent == -1) + return 1; /* done searching */ + + data = fdtbus_get_prop(phandle, "dma-ranges", &len); + if (data == NULL) + return 1; /* no dma-ranges property, stop searching */ + + if (len == 0) + return 0; /* dma-ranges property is empty, keep going */ + + const int addr_cells = fdtbus_get_addr_cells(phandle); + const int size_cells = fdtbus_get_size_cells(phandle); + const int paddr_cells = fdtbus_get_addr_cells(parent); + if (addr_cells == -1 || size_cells == -1 || paddr_cells == -1) + return 1; + + const int entry_size = (addr_cells + paddr_cells + size_cells) * 4; + + *nranges = len / entry_size; + *ranges = kmem_alloc(sizeof(struct fdt_dma_range) * *nranges, KM_SLEEP); + for (n = 0; len >= entry_size; n++, len -= entry_size) { + const uint64_t cba = fdtbus_get_cells(data, addr_cells); + data += addr_cells * 4; + const uint64_t pba = fdtbus_get_cells(data, paddr_cells); + data += paddr_cells * 4; + const uint64_t cl = fdtbus_get_cells(data, size_cells); + data += size_cells * 4; + + (*ranges)[n].dr_sysbase = pba; + (*ranges)[n].dr_busbase = cba; + (*ranges)[n].dr_len = cl; + } + + return 1; +} + +static bus_dma_tag_t +fdt_get_dma_tag(struct fdt_node *node) +{ + struct fdt_dma_range *ranges = NULL; + u_int nranges = 0; + int parent; + + parent = OF_parent(node->n_phandle); + while (parent != -1) { + if (fdt_dma_translate(parent, &ranges, &nranges) != 0) + break; + parent = OF_parent(parent); + } + + return fdtbus_dma_tag_create(node->n_phandle, ranges, nranges); +} + void fdt_add_child(device_t bus, const int child, struct fdt_attach_args *faa, u_int order) @@ -246,6 +307,7 @@ fdt_add_child(device_t bus, const int ch node->n_faa = *faa; node->n_faa.faa_phandle = child; node->n_faa.faa_name = node->n_name; + node->n_faa.faa_dmat = fdt_get_dma_tag(node); fdt_add_node(node); fdt_need_rescan = true; Index: src/sys/dev/fdt/fdtvar.h diff -u src/sys/dev/fdt/fdtvar.h:1.59 src/sys/dev/fdt/fdtvar.h:1.60 --- src/sys/dev/fdt/fdtvar.h:1.59 Sun Feb 16 20:28:18 2020 +++ src/sys/dev/fdt/fdtvar.h Thu Feb 20 01:35:55 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: fdtvar.h,v 1.59 2020/02/16 20:28:18 thorpej Exp $ */ +/* $NetBSD: fdtvar.h,v 1.60 2020/02/20 01:35:55 jmcneill Exp $ */ /*- * Copyright (c) 2015 Jared D. McNeill <jmcne...@invisible.ca> @@ -270,6 +270,12 @@ _FDT_OPP_REGISTER(_name) TAILQ_HEAD(fdt_conslist, fdt_console_info); +struct fdt_dma_range { + paddr_t dr_sysbase; + bus_addr_t dr_busbase; + bus_size_t dr_len; +}; + int fdtbus_register_interrupt_controller(device_t, int, const struct fdtbus_interrupt_controller_func *); int fdtbus_register_i2c_controller(device_t, int, @@ -306,6 +312,9 @@ int fdtbus_get_reg(int, u_int, bus_addr int fdtbus_get_reg_byname(int, const char *, bus_addr_t *, bus_size_t *); int fdtbus_get_reg64(int, u_int, uint64_t *, uint64_t *); +int fdtbus_get_addr_cells(int); +int fdtbus_get_size_cells(int); +uint64_t fdtbus_get_cells(const uint8_t *, int); int fdtbus_get_phandle(int, const char *); int fdtbus_get_phandle_with_data(int, const char *, const char *, int, struct fdt_phandle_data *); @@ -430,4 +439,7 @@ void fdt_remove_bycompat(const char *[] int fdt_find_with_property(const char *, int *); int fdtbus_print(void *, const char *); +bus_dma_tag_t fdtbus_dma_tag_create(int, const struct fdt_dma_range *, + u_int); + #endif /* _DEV_FDT_FDTVAR_H */ Added files: Index: src/sys/arch/evbarm/fdt/fdt_dma_machdep.c diff -u /dev/null src/sys/arch/evbarm/fdt/fdt_dma_machdep.c:1.1 --- /dev/null Thu Feb 20 01:35:55 2020 +++ src/sys/arch/evbarm/fdt/fdt_dma_machdep.c Thu Feb 20 01:35:55 2020 @@ -0,0 +1,72 @@ +/* $NetBSD: fdt_dma_machdep.c,v 1.1 2020/02/20 01:35:55 jmcneill Exp $ */ + +/*- + * Copyright (c) 2020 Jared McNeill <jmcne...@invisible.ca> + * 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 ``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 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. + */ + +#include <sys/cdefs.h> +__KERNEL_RCSID(0, "$NetBSD: fdt_dma_machdep.c,v 1.1 2020/02/20 01:35:55 jmcneill Exp $"); + +#include <sys/param.h> +#include <sys/bus.h> +#include <sys/kmem.h> + +#include <dev/fdt/fdtvar.h> + +extern struct arm32_bus_dma_tag arm_generic_dma_tag; + +bus_dma_tag_t +fdtbus_dma_tag_create(int phandle, const struct fdt_dma_range *ranges, + u_int nranges) +{ + struct arm32_bus_dma_tag *tagp; + u_int n; + + const int flags = of_hasprop(phandle, "dma-coherent") ? + _BUS_DMAMAP_COHERENT : 0; + + tagp = kmem_alloc(sizeof(*tagp), KM_SLEEP); + *tagp = arm_generic_dma_tag; + if (nranges == 0) { + tagp->_nranges = 1; + tagp->_ranges = kmem_alloc(sizeof(*tagp->_ranges), KM_SLEEP); + tagp->_ranges[0].dr_sysbase = 0; + tagp->_ranges[0].dr_busbase = 0; + tagp->_ranges[0].dr_len = UINTPTR_MAX; + tagp->_ranges[0].dr_flags = flags; + } else { + tagp->_nranges = nranges; + tagp->_ranges = kmem_alloc(sizeof(*tagp->_ranges) * nranges, + KM_SLEEP); + for (n = 0; n < nranges; n++) { + tagp->_ranges[n].dr_sysbase = ranges[n].dr_sysbase; + tagp->_ranges[n].dr_busbase = ranges[n].dr_busbase; + tagp->_ranges[n].dr_len = ranges[n].dr_len; + tagp->_ranges[n].dr_flags = flags; + } + } + + return tagp; +}