pxa_space.c revision 179595
1/* $NetBSD: obio_space.c,v 1.6 2003/07/15 00:25:05 lukem Exp $ */ 2 3/*- 4 * Copyright (c) 2001, 2002, 2003 Wasabi Systems, Inc. 5 * All rights reserved. 6 * 7 * Written by Jason R. Thorpe for Wasabi Systems, Inc. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. All advertising materials mentioning features or use of this software 18 * must display the following acknowledgement: 19 * This product includes software developed for the NetBSD Project by 20 * Wasabi Systems, Inc. 21 * 4. The name of Wasabi Systems, Inc. may not be used to endorse 22 * or promote products derived from this software without specific prior 23 * written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC 29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 35 * POSSIBILITY OF SUCH DAMAGE. 36 */ 37 38/* 39 * bus_space functions for PXA devices 40 */ 41 42#include <sys/cdefs.h> 43__FBSDID("$FreeBSD: head/sys/arm/xscale/pxa/pxa_space.c 179595 2008-06-06 05:08:09Z benno $"); 44 45#include <sys/param.h> 46#include <sys/systm.h> 47#include <sys/bus.h> 48#include <sys/kernel.h> 49#include <sys/malloc.h> 50 51#include <machine/pcb.h> 52 53#include <vm/vm.h> 54#include <vm/pmap.h> 55#include <vm/vm_kern.h> 56#include <vm/vm_extern.h> 57 58#include <machine/bus.h> 59 60#include <arm/xscale/pxa/pxareg.h> 61#include <arm/xscale/pxa/pxavar.h> 62 63MALLOC_DEFINE(M_PXATAG, "PXA bus_space tags", "Bus_space tags for PXA"); 64 65/* Prototypes for all the bus_space structure functions */ 66bs_protos(obio); 67bs_protos(generic); 68bs_protos(generic_armv4); 69bs_protos(pxa); 70 71/* 72 * The obio bus space tag. This is constant for all instances, so 73 * we never have to explicitly "create" it. 74 */ 75struct bus_space _base_tag = { 76 /* cookie */ 77 (void *) 0, 78 79 /* mapping/unmapping */ 80 obio_bs_map, 81 obio_bs_unmap, 82 obio_bs_subregion, 83 84 /* allocation/deallocation */ 85 obio_bs_alloc, 86 obio_bs_free, 87 88 /* barrier */ 89 obio_bs_barrier, 90 91 /* read (single) */ 92 pxa_bs_r_1, 93 pxa_bs_r_2, 94 pxa_bs_r_4, 95 NULL, 96 97 /* read multiple */ 98 pxa_bs_rm_1, 99 pxa_bs_rm_2, 100 NULL, 101 NULL, 102 103 /* read region */ 104 pxa_bs_rr_1, 105 NULL, 106 NULL, 107 NULL, 108 109 /* write (single) */ 110 pxa_bs_w_1, 111 pxa_bs_w_2, 112 pxa_bs_w_4, 113 NULL, 114 115 /* write multiple */ 116 pxa_bs_wm_1, 117 pxa_bs_wm_2, 118 NULL, 119 NULL, 120 121 /* write region */ 122 NULL, 123 NULL, 124 NULL, 125 NULL, 126 127 /* set multiple */ 128 NULL, 129 NULL, 130 NULL, 131 NULL, 132 133 /* set region */ 134 NULL, 135 NULL, 136 NULL, 137 NULL, 138 139 /* copy */ 140 NULL, 141 NULL, 142 NULL, 143 NULL, 144}; 145 146static struct bus_space _obio_tag; 147 148bus_space_tag_t base_tag = &_base_tag; 149bus_space_tag_t obio_tag = NULL; 150 151void 152pxa_obio_tag_init() 153{ 154 155 bcopy(&_base_tag, &_obio_tag, sizeof(struct bus_space)); 156 _obio_tag.bs_cookie = (void *)PXA2X0_PERIPH_OFFSET; 157 obio_tag = &_obio_tag; 158} 159 160bus_space_tag_t 161pxa_bus_tag_alloc(bus_addr_t offset) 162{ 163 struct bus_space *tag; 164 165 tag = (struct bus_space *)malloc(sizeof(struct bus_space), M_PXATAG, 166 M_WAITOK); 167 if (tag == NULL) { 168 return (NULL); 169 } 170 171 bcopy(&_base_tag, tag, sizeof(struct bus_space)); 172 tag->bs_cookie = (void *)offset; 173 174 return ((bus_space_tag_t)tag); 175} 176 177int 178obio_bs_map(void *t, bus_addr_t bpa, bus_size_t size, int flags, 179 bus_space_handle_t *bshp) 180{ 181 const struct pmap_devmap *pd; 182 vm_paddr_t startpa, endpa, pa, offset; 183 vm_offset_t va; 184 pt_entry_t *pte; 185 186 if ((pd = pmap_devmap_find_pa(bpa, size)) != NULL) { 187 /* Device was statically mapped. */ 188 *bshp = pd->pd_va + (bpa - pd->pd_pa); 189 return (0); 190 } 191 192 endpa = round_page(bpa + size); 193 offset = bpa & PAGE_MASK; 194 startpa = trunc_page(bpa); 195 196 va = kmem_alloc(kernel_map, endpa - startpa); 197 if (va == 0) 198 return (ENOMEM); 199 200 *bshp = va + offset; 201 202 for (pa = startpa; pa < endpa; pa += PAGE_SIZE, va += PAGE_SIZE) { 203 pmap_kenter(va, pa); 204 pte = vtopte(va); 205 *pte &= ~L2_S_CACHE_MASK; 206 PTE_SYNC(pte); 207 } 208 209 return (0); 210} 211 212int 213obio_bs_alloc(void *t, bus_addr_t rstart, bus_addr_t rend, bus_size_t size, 214 bus_size_t alignment, bus_size_t boundary, int flags, bus_addr_t *bpap, 215 bus_space_handle_t *bshp) 216{ 217 218 panic("obio_bs_alloc(): not implemented"); 219} 220 221 222void 223obio_bs_unmap(void *t, bus_space_handle_t h, bus_size_t size) 224{ 225 vm_offset_t va, endva; 226 227 if (pmap_devmap_find_va((vm_offset_t)t, size) != NULL) { 228 /* Device was statically mapped; nothing to do. */ 229 return; 230 } 231 232 endva = round_page((vm_offset_t)t + size); 233 va = trunc_page((vm_offset_t)t); 234 235 while (va < endva) { 236 pmap_kremove(va); 237 va += PAGE_SIZE; 238 } 239 kmem_free(kernel_map, va, endva - va); 240} 241 242void 243obio_bs_free(void *t, bus_space_handle_t bsh, bus_size_t size) 244{ 245 246 panic("obio_bs_free(): not implemented"); 247} 248 249int 250obio_bs_subregion(void *t, bus_space_handle_t bsh, bus_size_t offset, 251 bus_size_t size, bus_space_handle_t *nbshp) 252{ 253 254 *nbshp = bsh + offset; 255 return (0); 256} 257 258void 259obio_bs_barrier(void *t, bus_space_handle_t bsh, bus_size_t offset, 260 bus_size_t len, int flags) 261{ 262 263 /* Nothing to do. */ 264} 265 266#define READ_SINGLE(type, proto, base) \ 267 type \ 268 proto(void *cookie, bus_space_handle_t bsh, bus_size_t offset) \ 269 { \ 270 bus_addr_t tag_offset; \ 271 type value; \ 272 tag_offset = (bus_addr_t)cookie; \ 273 value = base(NULL, bsh + tag_offset, offset); \ 274 return (value); \ 275 } 276 277READ_SINGLE(u_int8_t, pxa_bs_r_1, generic_bs_r_1) 278READ_SINGLE(u_int16_t, pxa_bs_r_2, generic_armv4_bs_r_2) 279READ_SINGLE(u_int32_t, pxa_bs_r_4, generic_bs_r_4) 280 281#undef READ_SINGLE 282 283#define WRITE_SINGLE(type, proto, base) \ 284 void \ 285 proto(void *cookie, bus_space_handle_t bsh, bus_size_t offset, \ 286 type value) \ 287 { \ 288 bus_addr_t tag_offset; \ 289 tag_offset = (bus_addr_t)cookie; \ 290 base(NULL, bsh + tag_offset, offset, value); \ 291 } 292 293WRITE_SINGLE(u_int8_t, pxa_bs_w_1, generic_bs_w_1) 294WRITE_SINGLE(u_int16_t, pxa_bs_w_2, generic_armv4_bs_w_2) 295WRITE_SINGLE(u_int32_t, pxa_bs_w_4, generic_bs_w_4) 296 297#undef WRITE_SINGLE 298 299#define READ_MULTI(type, proto, base) \ 300 void \ 301 proto(void *cookie, bus_space_handle_t bsh, bus_size_t offset, \ 302 type *dest, bus_size_t count) \ 303 { \ 304 bus_addr_t tag_offset; \ 305 tag_offset = (bus_addr_t)cookie; \ 306 base(NULL, bsh + tag_offset, offset, dest, count); \ 307 } 308 309READ_MULTI(u_int8_t, pxa_bs_rm_1, generic_bs_rm_1) 310READ_MULTI(u_int16_t, pxa_bs_rm_2, generic_armv4_bs_rm_2) 311 312READ_MULTI(u_int8_t, pxa_bs_rr_1, generic_bs_rr_1) 313 314#undef READ_MULTI 315 316#define WRITE_MULTI(type, proto, base) \ 317 void \ 318 proto(void *cookie, bus_space_handle_t bsh, bus_size_t offset, \ 319 const type *src, bus_size_t count) \ 320 { \ 321 bus_addr_t tag_offset; \ 322 tag_offset = (bus_addr_t)cookie; \ 323 base(NULL, bsh + tag_offset, offset, src, count); \ 324 } 325 326WRITE_MULTI(u_int8_t, pxa_bs_wm_1, generic_bs_wm_1) 327WRITE_MULTI(u_int16_t, pxa_bs_wm_2, generic_armv4_bs_wm_2) 328 329#undef WRITE_MULTI 330