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