1 /*
2 * Copyright (c) 2026 Justin Hibbits
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 */
6
7 #include <sys/param.h>
8 #include <sys/systm.h>
9 #include <vm/vm.h>
10 #include <vm/pmap.h>
11
12 #include <dev/fdt/fdt_common.h>
13 #include <dev/ofw/ofw_bus.h>
14 #include <dev/ofw/ofw_bus_subr.h>
15
16 #include "dpaa_common.h"
17
18 #define FDT_REG_CELLS 4
19 int
dpaa_map_private_memory(device_t dev,int idx,const char * compat,vm_paddr_t * addrp,size_t * sizep)20 dpaa_map_private_memory(device_t dev, int idx, const char *compat,
21 vm_paddr_t *addrp, size_t *sizep)
22 {
23 phandle_t node;
24 pcell_t cells[idx + 1];
25 pcell_t *cell_alloc;
26 int addr_cells, size_cells;
27 uint64_t tmp;
28 u_long align, base, size;
29 vm_paddr_t alloc_base;
30 vm_size_t alloc_range_size;
31 ssize_t alloc_size;
32 void *reserved;
33 int rv;
34
35 node = ofw_bus_get_node(dev);
36 if (OF_getencprop(node, "memory-region", cells, sizeof(cells)) <= 0)
37 return (ENXIO);
38
39 node = OF_node_from_xref(cells[idx]);
40 /* If the memory is already reserved, we just need to return it. */
41 if (fdt_regsize(node, &base, &size) == 0)
42 goto success;
43
44 rv = fdt_addrsize_cells(OF_parent(node), &addr_cells, &size_cells);
45 if (rv != 0)
46 return (rv);
47
48 if (OF_getprop(node, "alignment", &tmp, sizeof(tmp)) <= 0)
49 return (ENXIO);
50
51 align = fdt_data_get(&tmp, addr_cells);
52 if (OF_getprop(node, "size", &tmp, sizeof(tmp)) <= 0)
53 return (ENXIO);
54 size = fdt_data_get(&tmp, size_cells);
55
56 alloc_size =
57 OF_getencprop_alloc(node, "alloc-ranges", (void **)&cell_alloc);
58 if (alloc_size < 0)
59 return (ENXIO);
60
61 alloc_size /= sizeof(pcell_t);
62 for (int i = 0; i < alloc_size; i += (addr_cells + size_cells)) {
63 alloc_base = fdt_data_get(&cell_alloc[i], addr_cells);
64 alloc_range_size =
65 fdt_data_get(&cell_alloc[i + addr_cells], size_cells);
66 reserved = contigmalloc(size, M_DEVBUF, M_NOWAIT | M_ZERO,
67 alloc_base, alloc_base + alloc_range_size, align, 0);
68 if (reserved != NULL)
69 break;
70 }
71 if (reserved == NULL)
72 return (ENOMEM);
73 /* Flush the cache (zeroed memory) because it won't be touched later. */
74 cpu_flush_dcache(reserved, size);
75 base = pmap_kextract((vm_offset_t)reserved);
76
77 success:
78 *addrp = base;
79 *sizep = size;
80
81 return (0);
82 }
83