1 /* $NetBSD: bus_space_sparse.c,v 1.21 2023/12/20 06:36:02 thorpej Exp $ */ 2 /* NetBSD: bus_machdep.c,v 1.1 2000/01/26 18:48:00 drochner Exp */ 3 4 /*- 5 * Copyright (c) 1996, 1997, 1998 The NetBSD Foundation, Inc. 6 * All rights reserved. 7 * 8 * This code is derived from software contributed to The NetBSD Foundation 9 * by Charles M. Hannum and by Jason R. Thorpe of the Numerical Aerospace 10 * Simulation Facility, NASA Ames Research Center. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 23 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 25 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 * POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 /* 35 * For sparse bus space 36 * 37 * This bus_space uses KSEG2 mapping, if the physical address is not 38 * accessible via KSEG0/KSEG1. 39 */ 40 41 #include <sys/cdefs.h> 42 __KERNEL_RCSID(0, "$NetBSD: bus_space_sparse.c,v 1.21 2023/12/20 06:36:02 thorpej Exp $"); 43 44 #include <sys/param.h> 45 #include <sys/bus.h> 46 #include <sys/systm.h> 47 48 #include <uvm/uvm_extern.h> 49 50 #include <mips/locore.h> 51 #include <mips/pte.h> 52 53 extern paddr_t kvtophys(vaddr_t); /* XXX */ 54 55 void 56 arc_sparse_bus_space_init(bus_space_tag_t bst, const char *name, paddr_t paddr, 57 bus_addr_t start, bus_size_t size) 58 { 59 60 arc_bus_space_init(bst, name, paddr, ARC_BUS_SPACE_UNMAPPED, 61 start, size); 62 bst->bs_compose_handle = arc_sparse_bus_space_compose_handle; 63 bst->bs_dispose_handle = arc_sparse_bus_space_dispose_handle; 64 bst->bs_paddr = arc_sparse_bus_space_paddr; 65 } 66 67 int 68 arc_sparse_bus_space_compose_handle(bus_space_tag_t bst, bus_addr_t addr, 69 bus_size_t size, int flags, bus_space_handle_t *bshp) 70 { 71 bus_size_t offset = addr - bst->bs_start; 72 /* 73 * Since all buses can be linearly mappable, we don't have to check 74 * BUS_SPACE_MAP_LINEAR and BUS_SPACE_MAP_PREFETCHABLE. 75 */ 76 const bool cacheable = (flags & BUS_SPACE_MAP_CACHEABLE) != 0; 77 const u_int pmap_flags = cacheable ? PMAP_WRITE_BACK : 0; 78 79 /* 80 * XXX - `bst->bs_pbase' must be page aligned, 81 * mips_trunc/round_page() cannot treat paddr_t due to overflow. 82 */ 83 paddr_t start = bst->bs_pbase + mips_trunc_page(offset); 84 paddr_t end = bst->bs_pbase + mips_round_page(offset + size); 85 86 if (end <= MIPS_KSEG1_START - MIPS_KSEG0_START) { 87 /* mappable on KSEG0 or KSEG1 */ 88 *bshp = (cacheable ? 89 MIPS_PHYS_TO_KSEG0(start) : 90 MIPS_PHYS_TO_KSEG1(start)); 91 } else { 92 vaddr_t vaddr = uvm_km_alloc(kernel_map, (vsize_t)(end - start), 93 0, UVM_KMF_VAONLY | UVM_KMF_NOWAIT); 94 95 if (vaddr == 0) 96 panic("arc_sparse_bus_space_compose_handle: " 97 "cannot allocate KVA 0x%llx..0x%llx", 98 start, end); 99 for (vaddr_t va = vaddr; start < end; 100 start += PAGE_SIZE, va += PAGE_SIZE) { 101 pmap_kenter_pa(va, start, VM_PROT_READ|VM_PROT_WRITE, 102 pmap_flags); 103 } 104 pmap_update(pmap_kernel()); 105 vaddr += (offset & PGOFSET); 106 *bshp = vaddr; 107 } 108 return 0; 109 } 110 111 int 112 arc_sparse_bus_space_dispose_handle(bus_space_tag_t bst, bus_space_handle_t bsh, 113 bus_size_t size) 114 { 115 vaddr_t start = mips_trunc_page(bsh); 116 vaddr_t end = mips_round_page(bsh + size); 117 118 if (start < MIPS_KSEG2_START) /* KSEG0/KSEG1 */ 119 return 0; 120 121 pmap_kremove(start, end - start); 122 pmap_update(pmap_kernel()); 123 uvm_km_free(kernel_map, start, end - start, UVM_KMF_VAONLY); 124 return 0; 125 } 126 127 int 128 arc_sparse_bus_space_paddr(bus_space_tag_t bst, bus_space_handle_t bsh, 129 paddr_t *pap) 130 { 131 132 *pap = kvtophys(bsh); 133 return 0; 134 } 135