Skip to content

Commit 9bf4ec1

Browse files
committed
Add dma-ranges support.
1 parent 1afde9e commit 9bf4ec1

File tree

5 files changed

+156
-9
lines changed

5 files changed

+156
-9
lines changed

sys/arch/evbarm/conf/files.fdt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
# $NetBSD: files.fdt,v 1.5 2018/10/30 22:32:33 jmcneill Exp $
1+
# $NetBSD: files.fdt,v 1.6 2020/02/20 01:35:55 jmcneill Exp $
22
#
33
# FDT-based kernel configuration info
44
#
55

6+
file arch/evbarm/fdt/fdt_dma_machdep.c fdt
67
file arch/evbarm/fdt/fdt_machdep.c fdt
78
file arch/evbarm/fdt/fdt_memory.c fdt
89

sys/arch/evbarm/fdt/fdt_dma_machdep.c

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
/* $NetBSD: fdt_dma_machdep.c,v 1.1 2020/02/20 01:35:55 jmcneill Exp $ */
2+
3+
/*-
4+
* Copyright (c) 2020 Jared McNeill <jmcneill@invisible.ca>
5+
* All rights reserved.
6+
*
7+
* Redistribution and use in source and binary forms, with or without
8+
* modification, are permitted provided that the following conditions
9+
* are met:
10+
* 1. Redistributions of source code must retain the above copyright
11+
* notice, this list of conditions and the following disclaimer.
12+
* 2. Redistributions in binary form must reproduce the above copyright
13+
* notice, this list of conditions and the following disclaimer in the
14+
* documentation and/or other materials provided with the distribution.
15+
*
16+
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17+
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18+
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19+
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20+
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21+
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22+
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23+
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24+
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25+
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26+
* SUCH DAMAGE.
27+
*/
28+
29+
#include <sys/cdefs.h>
30+
__KERNEL_RCSID(0, "$NetBSD: fdt_dma_machdep.c,v 1.1 2020/02/20 01:35:55 jmcneill Exp $");
31+
32+
#include <sys/param.h>
33+
#include <sys/bus.h>
34+
#include <sys/kmem.h>
35+
36+
#include <dev/fdt/fdtvar.h>
37+
38+
extern struct arm32_bus_dma_tag arm_generic_dma_tag;
39+
40+
bus_dma_tag_t
41+
fdtbus_dma_tag_create(int phandle, const struct fdt_dma_range *ranges,
42+
u_int nranges)
43+
{
44+
struct arm32_bus_dma_tag *tagp;
45+
u_int n;
46+
47+
const int flags = of_hasprop(phandle, "dma-coherent") ?
48+
_BUS_DMAMAP_COHERENT : 0;
49+
50+
tagp = kmem_alloc(sizeof(*tagp), KM_SLEEP);
51+
*tagp = arm_generic_dma_tag;
52+
if (nranges == 0) {
53+
tagp->_nranges = 1;
54+
tagp->_ranges = kmem_alloc(sizeof(*tagp->_ranges), KM_SLEEP);
55+
tagp->_ranges[0].dr_sysbase = 0;
56+
tagp->_ranges[0].dr_busbase = 0;
57+
tagp->_ranges[0].dr_len = UINTPTR_MAX;
58+
tagp->_ranges[0].dr_flags = flags;
59+
} else {
60+
tagp->_nranges = nranges;
61+
tagp->_ranges = kmem_alloc(sizeof(*tagp->_ranges) * nranges,
62+
KM_SLEEP);
63+
for (n = 0; n < nranges; n++) {
64+
tagp->_ranges[n].dr_sysbase = ranges[n].dr_sysbase;
65+
tagp->_ranges[n].dr_busbase = ranges[n].dr_busbase;
66+
tagp->_ranges[n].dr_len = ranges[n].dr_len;
67+
tagp->_ranges[n].dr_flags = flags;
68+
}
69+
}
70+
71+
return tagp;
72+
}

sys/dev/fdt/fdt_subr.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* $NetBSD: fdt_subr.c,v 1.33 2020/02/16 20:28:18 thorpej Exp $ */
1+
/* $NetBSD: fdt_subr.c,v 1.34 2020/02/20 01:35:55 jmcneill Exp $ */
22

33
/*-
44
* Copyright (c) 2015 Jared D. McNeill <jmcneill@invisible.ca>
@@ -27,7 +27,7 @@
2727
*/
2828

2929
#include <sys/cdefs.h>
30-
__KERNEL_RCSID(0, "$NetBSD: fdt_subr.c,v 1.33 2020/02/16 20:28:18 thorpej Exp $");
30+
__KERNEL_RCSID(0, "$NetBSD: fdt_subr.c,v 1.34 2020/02/20 01:35:55 jmcneill Exp $");
3131

3232
#include "opt_fdt.h"
3333

@@ -95,7 +95,7 @@ fdtbus_set_decoderegprop(bool decode)
9595
fdtbus_decoderegprop = decode;
9696
}
9797

98-
static int
98+
int
9999
fdtbus_get_addr_cells(int phandle)
100100
{
101101
uint32_t addr_cells;
@@ -106,7 +106,7 @@ fdtbus_get_addr_cells(int phandle)
106106
return addr_cells;
107107
}
108108

109-
static int
109+
int
110110
fdtbus_get_size_cells(int phandle)
111111
{
112112
uint32_t size_cells;
@@ -193,7 +193,7 @@ fdtbus_get_path(int phandle, char *buf, size_t buflen)
193193
return true;
194194
}
195195

196-
static uint64_t
196+
uint64_t
197197
fdtbus_get_cells(const uint8_t *buf, int cells)
198198
{
199199
switch (cells) {

sys/dev/fdt/fdtbus.c

Lines changed: 64 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* $NetBSD: fdtbus.c,v 1.32 2020/01/28 08:09:19 martin Exp $ */
1+
/* $NetBSD: fdtbus.c,v 1.33 2020/02/20 01:35:55 jmcneill Exp $ */
22

33
/*-
44
* Copyright (c) 2015 Jared D. McNeill <jmcneill@invisible.ca>
@@ -27,7 +27,7 @@
2727
*/
2828

2929
#include <sys/cdefs.h>
30-
__KERNEL_RCSID(0, "$NetBSD: fdtbus.c,v 1.32 2020/01/28 08:09:19 martin Exp $");
30+
__KERNEL_RCSID(0, "$NetBSD: fdtbus.c,v 1.33 2020/02/20 01:35:55 jmcneill Exp $");
3131

3232
#include <sys/param.h>
3333
#include <sys/systm.h>
@@ -202,6 +202,7 @@ fdt_init_attach_args(const struct fdt_attach_args *faa_tmpl, struct fdt_node *no
202202
faa->faa_phandle = node->n_phandle;
203203
faa->faa_name = node->n_name;
204204
faa->faa_quiet = quiet;
205+
faa->faa_dmat = node->n_faa.faa_dmat;
205206
}
206207

207208
static bool
@@ -230,6 +231,66 @@ fdt_add_bus_match(device_t bus, const int phandle, struct fdt_attach_args *faa,
230231
}
231232
}
232233

234+
static int
235+
fdt_dma_translate(int phandle, struct fdt_dma_range **ranges, u_int *nranges)
236+
{
237+
const uint8_t *data;
238+
int len, n;
239+
240+
const int parent = OF_parent(phandle);
241+
if (parent == -1)
242+
return 1; /* done searching */
243+
244+
data = fdtbus_get_prop(phandle, "dma-ranges", &len);
245+
if (data == NULL)
246+
return 1; /* no dma-ranges property, stop searching */
247+
248+
if (len == 0)
249+
return 0; /* dma-ranges property is empty, keep going */
250+
251+
const int addr_cells = fdtbus_get_addr_cells(phandle);
252+
const int size_cells = fdtbus_get_size_cells(phandle);
253+
const int paddr_cells = fdtbus_get_addr_cells(parent);
254+
if (addr_cells == -1 || size_cells == -1 || paddr_cells == -1)
255+
return 1;
256+
257+
const int entry_size = (addr_cells + paddr_cells + size_cells) * 4;
258+
259+
*nranges = len / entry_size;
260+
*ranges = kmem_alloc(sizeof(struct fdt_dma_range) * *nranges, KM_SLEEP);
261+
for (n = 0; len >= entry_size; n++, len -= entry_size) {
262+
const uint64_t cba = fdtbus_get_cells(data, addr_cells);
263+
data += addr_cells * 4;
264+
const uint64_t pba = fdtbus_get_cells(data, paddr_cells);
265+
data += paddr_cells * 4;
266+
const uint64_t cl = fdtbus_get_cells(data, size_cells);
267+
data += size_cells * 4;
268+
269+
(*ranges)[n].dr_sysbase = pba;
270+
(*ranges)[n].dr_busbase = cba;
271+
(*ranges)[n].dr_len = cl;
272+
}
273+
274+
return 1;
275+
}
276+
277+
static bus_dma_tag_t
278+
fdt_get_dma_tag(struct fdt_node *node)
279+
{
280+
struct fdt_dma_range *ranges = NULL;
281+
u_int nranges = 0;
282+
int parent;
283+
284+
parent = OF_parent(node->n_phandle);
285+
while (parent != -1) {
286+
if (fdt_dma_translate(parent, &ranges, &nranges) != 0)
287+
break;
288+
parent = OF_parent(parent);
289+
}
290+
291+
return fdtbus_dma_tag_create(node->n_phandle, ranges, nranges);
292+
}
293+
233294
void
234295
fdt_add_child(device_t bus, const int child, struct fdt_attach_args *faa,
235296
u_int order)
@@ -246,6 +307,7 @@ fdt_add_child(device_t bus, const int child, struct fdt_attach_args *faa,
246307
node->n_faa = *faa;
247308
node->n_faa.faa_phandle = child;
248309
node->n_faa.faa_name = node->n_name;
310+
node->n_faa.faa_dmat = fdt_get_dma_tag(node);
249311

250312
fdt_add_node(node);
251313
fdt_need_rescan = true;

sys/dev/fdt/fdtvar.h

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* $NetBSD: fdtvar.h,v 1.59 2020/02/16 20:28:18 thorpej Exp $ */
1+
/* $NetBSD: fdtvar.h,v 1.60 2020/02/20 01:35:55 jmcneill Exp $ */
22

33
/*-
44
* Copyright (c) 2015 Jared D. McNeill <jmcneill@invisible.ca>
@@ -270,6 +270,12 @@ _FDT_OPP_REGISTER(_name)
270270

271271
TAILQ_HEAD(fdt_conslist, fdt_console_info);
272272

273+
struct fdt_dma_range {
274+
paddr_t dr_sysbase;
275+
bus_addr_t dr_busbase;
276+
bus_size_t dr_len;
277+
};
278+
273279
int fdtbus_register_interrupt_controller(device_t, int,
274280
const struct fdtbus_interrupt_controller_func *);
275281
int fdtbus_register_i2c_controller(device_t, int,
@@ -306,6 +312,9 @@ int fdtbus_get_reg(int, u_int, bus_addr_t *, bus_size_t *);
306312
int fdtbus_get_reg_byname(int, const char *, bus_addr_t *,
307313
bus_size_t *);
308314
int fdtbus_get_reg64(int, u_int, uint64_t *, uint64_t *);
315+
int fdtbus_get_addr_cells(int);
316+
int fdtbus_get_size_cells(int);
317+
uint64_t fdtbus_get_cells(const uint8_t *, int);
309318
int fdtbus_get_phandle(int, const char *);
310319
int fdtbus_get_phandle_with_data(int, const char *, const char *,
311320
int, struct fdt_phandle_data *);
@@ -430,4 +439,7 @@ void fdt_remove_bycompat(const char *[]);
430439
int fdt_find_with_property(const char *, int *);
431440
int fdtbus_print(void *, const char *);
432441

442+
bus_dma_tag_t fdtbus_dma_tag_create(int, const struct fdt_dma_range *,
443+
u_int);
444+
433445
#endif /* _DEV_FDT_FDTVAR_H */

0 commit comments

Comments
 (0)