1 /* $NetBSD: bus_space_sparse.c,v 1.16 2009/11/07 07:27:41 cegger 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.16 2009/11/07 07:27:41 cegger Exp $"); 43 44 #include <sys/param.h> 45 #include <sys/systm.h> 46 #include <sys/malloc.h> 47 #include <sys/extent.h> 48 49 #include <uvm/uvm_extern.h> 50 51 #include <mips/cpuregs.h> 52 #include <mips/pte.h> 53 54 #include <machine/bus.h> 55 56 extern paddr_t kvtophys(vaddr_t); /* XXX */ 57 58 static void arc_kseg2_make_cacheable(vaddr_t vaddr, vsize_t size); 59 60 static void 61 arc_kseg2_make_cacheable(vaddr_t vaddr, vsize_t size) 62 { 63 vaddr_t start, end; 64 pt_entry_t *pte; 65 uint32_t entry, mask; 66 67 start = mips_trunc_page(vaddr); 68 end = mips_round_page(vaddr + size); 69 mask = ~(CPUISMIPS3 ? MIPS3_PG_UNCACHED : MIPS1_PG_N); 70 for (; start < end; start += PAGE_SIZE) { 71 pte = kvtopte(start); 72 entry = pte->pt_entry & mask; 73 pte->pt_entry &= entry; 74 MachTLBUpdate(start, entry); 75 } 76 } 77 78 void 79 arc_sparse_bus_space_init(bus_space_tag_t bst, const char *name, paddr_t paddr, 80 bus_addr_t start, bus_size_t size) 81 { 82 83 arc_bus_space_init(bst, name, paddr, ARC_BUS_SPACE_UNMAPPED, 84 start, size); 85 bst->bs_compose_handle = arc_sparse_bus_space_compose_handle; 86 bst->bs_dispose_handle = arc_sparse_bus_space_dispose_handle; 87 bst->bs_paddr = arc_sparse_bus_space_paddr; 88 } 89 90 int 91 arc_sparse_bus_space_compose_handle(bus_space_tag_t bst, bus_addr_t addr, 92 bus_size_t size, int flags, bus_space_handle_t *bshp) 93 { 94 bus_size_t offset = addr - bst->bs_start; 95 /* 96 * Since all buses can be linearly mappable, we don't have to check 97 * BUS_SPACE_MAP_LINEAR and BUS_SPACE_MAP_PREFETCHABLE. 98 */ 99 int cacheable = (flags & BUS_SPACE_MAP_CACHEABLE); 100 101 /* 102 * XXX - `bst->bs_pbase' must be page aligned, 103 * mips_trunc/round_page() cannot treat paddr_t due to overflow. 104 */ 105 paddr_t start = bst->bs_pbase + mips_trunc_page(offset); 106 paddr_t end = bst->bs_pbase + mips_round_page(offset + size); 107 108 if (end <= MIPS_KSEG1_START - MIPS_KSEG0_START) { 109 /* mappable on KSEG0 or KSEG1 */ 110 *bshp = (cacheable ? 111 MIPS_PHYS_TO_KSEG0(start) : 112 MIPS_PHYS_TO_KSEG1(start)); 113 } else { 114 vaddr_t va, 115 vaddr = uvm_km_alloc(kernel_map, (vsize_t)(end - start), 0, 116 UVM_KMF_VAONLY | UVM_KMF_NOWAIT); 117 118 if (vaddr == 0) 119 panic("arc_sparse_bus_space_compose_handle: " 120 "cannot allocate KVA 0x%llx..0x%llx", 121 start, end); 122 for (va = vaddr; start < end; 123 start += PAGE_SIZE, va += PAGE_SIZE) 124 pmap_kenter_pa(va, start, 125 VM_PROT_READ|VM_PROT_WRITE, 0); 126 pmap_update(pmap_kernel()); 127 vaddr += (offset & PGOFSET); 128 if (cacheable) 129 arc_kseg2_make_cacheable(vaddr, size); 130 *bshp = vaddr; 131 } 132 return 0; 133 } 134 135 int 136 arc_sparse_bus_space_dispose_handle(bus_space_tag_t bst, bus_space_handle_t bsh, 137 bus_size_t size) 138 { 139 vaddr_t start = mips_trunc_page(bsh); 140 vaddr_t end = mips_round_page(bsh + size); 141 142 if (start < MIPS_KSEG2_START) /* KSEG0/KSEG1 */ 143 return 0; 144 145 pmap_kremove(start, end - start); 146 pmap_update(pmap_kernel()); 147 uvm_km_free(kernel_map, start, end - start, UVM_KMF_VAONLY); 148 return 0; 149 } 150 151 int 152 arc_sparse_bus_space_paddr(bus_space_tag_t bst, bus_space_handle_t bsh, 153 paddr_t *pap) 154 { 155 156 *pap = kvtophys(bsh); 157 return 0; 158 } 159