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

Reply via email to