1169689Skan/* $NetBSD: ifpga_io.c,v 1.10 2011/07/01 20:39:34 dyoung Exp $ */ 2169689Skan 3169689Skan/* 4169689Skan * Copyright (c) 1997 Causality Limited 5169689Skan * Copyright (c) 1997 Mark Brinicombe. 6169689Skan * All rights reserved. 7169689Skan * 8169689Skan * Redistribution and use in source and binary forms, with or without 9169689Skan * modification, are permitted provided that the following conditions 10169689Skan * are met: 11169689Skan * 1. Redistributions of source code must retain the above copyright 12169689Skan * notice, this list of conditions and the following disclaimer. 13169689Skan * 2. Redistributions in binary form must reproduce the above copyright 14169689Skan * notice, this list of conditions and the following disclaimer in the 15169689Skan * documentation and/or other materials provided with the distribution. 16169689Skan * 3. All advertising materials mentioning features or use of this software 17169689Skan * must display the following acknowledgement: 18169689Skan * This product includes software developed by Mark Brinicombe 19169689Skan * for the NetBSD Project. 20169689Skan * 4. The name of the company nor the name of the author may be used to 21169689Skan * endorse or promote products derived from this software without specific 22169689Skan * prior written permission. 23169689Skan * 24169689Skan * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 25169689Skan * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 26169689Skan * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 27169689Skan * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 28169689Skan * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 29169689Skan * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 30169689Skan * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31169689Skan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32169689Skan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33169689Skan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34169689Skan * SUCH DAMAGE. 35169689Skan * 36169689Skan * From arm/footbridge/footbridge_io.c 37169689Skan */ 38169689Skan 39169689Skan/* 40169689Skan * bus_space I/O functions for IFPGA 41169689Skan */ 42169689Skan 43169689Skan#include <sys/cdefs.h> 44169689Skan__KERNEL_RCSID(0, "$NetBSD: ifpga_io.c,v 1.10 2011/07/01 20:39:34 dyoung Exp $"); 45169689Skan 46169689Skan#include <sys/param.h> 47169689Skan#include <sys/systm.h> 48169689Skan#include <sys/bus.h> 49169689Skan#include <uvm/uvm_extern.h> 50169689Skan 51169689Skan#include <evbarm/ifpga/ifpgavar.h> 52169689Skan 53169689Skan/* Proto types for all the bus_space structure functions */ 54169689Skan 55169689Skanbs_protos(ifpga); 56169689Skanbs_protos(generic); 57169689Skanbs_protos(generic_armv4); 58169689Skanbs_protos(bs_notimpl); 59169689Skanbs_map_proto(ifpga_mem); 60169689Skanbs_unmap_proto(ifpga_mem); 61169689Skan 62169689Skan/* Declare the ifpga bus space tag */ 63169689Skan 64169689Skanstruct bus_space ifpga_bs_tag = { 65169689Skan /* cookie */ 66169689Skan (void *) 0, /* Physical base address */ 67169689Skan 68169689Skan /* mapping/unmapping */ 69169689Skan ifpga_bs_map, 70169689Skan ifpga_bs_unmap, 71169689Skan ifpga_bs_subregion, 72169689Skan 73169689Skan /* allocation/deallocation */ 74169689Skan ifpga_bs_alloc, 75169689Skan ifpga_bs_free, 76169689Skan 77169689Skan /* get kernel virtual address */ 78169689Skan ifpga_bs_vaddr, 79169689Skan 80169689Skan /* mmap */ 81169689Skan bs_notimpl_bs_mmap, 82169689Skan 83169689Skan /* barrier */ 84169689Skan ifpga_bs_barrier, 85169689Skan 86169689Skan /* read (single) */ 87169689Skan generic_bs_r_1, 88169689Skan generic_armv4_bs_r_2, 89169689Skan generic_bs_r_4, 90169689Skan bs_notimpl_bs_r_8, 91169689Skan 92169689Skan /* read multiple */ 93169689Skan generic_bs_rm_1, 94169689Skan generic_armv4_bs_rm_2, 95169689Skan generic_bs_rm_4, 96169689Skan bs_notimpl_bs_rm_8, 97169689Skan 98169689Skan /* read region */ 99169689Skan bs_notimpl_bs_rr_1, 100169689Skan generic_armv4_bs_rr_2, 101169689Skan generic_bs_rr_4, 102169689Skan bs_notimpl_bs_rr_8, 103169689Skan 104169689Skan /* write (single) */ 105169689Skan generic_bs_w_1, 106169689Skan generic_armv4_bs_w_2, 107169689Skan generic_bs_w_4, 108169689Skan bs_notimpl_bs_w_8, 109169689Skan 110169689Skan /* write multiple */ 111169689Skan generic_bs_wm_1, 112169689Skan generic_armv4_bs_wm_2, 113169689Skan generic_bs_wm_4, 114169689Skan bs_notimpl_bs_wm_8, 115169689Skan 116169689Skan /* write region */ 117169689Skan bs_notimpl_bs_wr_1, 118169689Skan generic_armv4_bs_wr_2, 119169689Skan generic_bs_wr_4, 120169689Skan bs_notimpl_bs_wr_8, 121169689Skan 122169689Skan /* set multiple */ 123169689Skan bs_notimpl_bs_sm_1, 124169689Skan bs_notimpl_bs_sm_2, 125169689Skan bs_notimpl_bs_sm_4, 126169689Skan bs_notimpl_bs_sm_8, 127169689Skan 128169689Skan /* set region */ 129169689Skan bs_notimpl_bs_sr_1, 130169689Skan generic_armv4_bs_sr_2, 131169689Skan bs_notimpl_bs_sr_4, 132169689Skan bs_notimpl_bs_sr_8, 133169689Skan 134169689Skan /* copy */ 135169689Skan bs_notimpl_bs_c_1, 136169689Skan generic_armv4_bs_c_2, 137169689Skan bs_notimpl_bs_c_4, 138169689Skan bs_notimpl_bs_c_8, 139169689Skan}; 140169689Skan 141169689Skanvoid 142169689Skanifpga_create_io_bs_tag(struct bus_space *t, void *cookie) 143169689Skan{ 144169689Skan *t = ifpga_bs_tag; 145169689Skan t->bs_cookie = cookie; 146169689Skan} 147169689Skan 148169689Skanvoid 149169689Skanifpga_create_mem_bs_tag(struct bus_space *t, void *cookie) 150169689Skan{ 151169689Skan *t = ifpga_bs_tag; 152169689Skan t->bs_map = ifpga_mem_bs_map; 153169689Skan t->bs_unmap = ifpga_mem_bs_unmap; 154169689Skan t->bs_cookie = cookie; 155169689Skan} 156169689Skan 157169689Skan/* bus space functions */ 158169689Skan 159169689Skanint 160169689Skanifpga_bs_map(void *t, bus_addr_t bpa, bus_size_t size, int cacheable, bus_space_handle_t *bshp) 161169689Skan{ 162169689Skan /* The cookie is the base address for the I/O area */ 163169689Skan *bshp = bpa + (bus_addr_t)t; 164169689Skan return 0; 165169689Skan} 166169689Skan 167169689Skanint 168169689Skanifpga_mem_bs_map(void *t, bus_addr_t bpa, bus_size_t size, int cacheable, bus_space_handle_t *bshp) 169169689Skan{ 170169689Skan bus_addr_t startpa, endpa; 171169689Skan vaddr_t va; 172169689Skan 173169689Skan /* Round the allocation to page boundries */ 174169689Skan startpa = trunc_page(bpa); 175169689Skan endpa = round_page(bpa + size); 176169689Skan 177169689Skan /* Get some VM. */ 178169689Skan va = uvm_km_alloc(kernel_map, endpa - startpa, 0, 179169689Skan UVM_KMF_VAONLY | UVM_KMF_NOWAIT); 180169689Skan if (va == 0) 181169689Skan return ENOMEM; 182169689Skan 183169689Skan /* Store the bus space handle */ 184169689Skan *bshp = va + (bpa & PGOFSET); 185169689Skan 186169689Skan /* Now map the pages */ 187169689Skan /* The cookie is the physical base address for the I/O area */ 188169689Skan while (startpa < endpa) { 189169689Skan /* XXX pmap_kenter_pa maps pages cacheable -- not what 190169689Skan we want. */ 191169689Skan pmap_enter(pmap_kernel(), va, (bus_addr_t)t + startpa, 192169689Skan VM_PROT_READ | VM_PROT_WRITE, 0); 193169689Skan va += PAGE_SIZE; 194169689Skan startpa += PAGE_SIZE; 195169689Skan } 196169689Skan pmap_update(pmap_kernel()); 197169689Skan 198169689Skan return 0; 199169689Skan} 200169689Skan 201169689Skanint 202169689Skanifpga_bs_alloc(void *t, bus_addr_t rstart, bus_addr_t rend, bus_size_t size, 203169689Skan bus_size_t alignment, bus_size_t boundary, int cacheable, 204169689Skan bus_addr_t *bpap, bus_space_handle_t *bshp) 205169689Skan{ 206169689Skan panic("ifpga_alloc(): Help!"); 207169689Skan} 208169689Skan 209169689Skan 210169689Skanvoid 211169689Skanifpga_bs_unmap(void *t, bus_space_handle_t bsh, bus_size_t size) 212169689Skan{ 213169689Skan /* Nothing to do for an io map. */ 214169689Skan} 215169689Skan 216169689Skanvoid 217169689Skanifpga_mem_bs_unmap(void *t, bus_space_handle_t bsh, bus_size_t size) 218169689Skan{ 219169689Skan vaddr_t startva, endva; 220169689Skan 221169689Skan startva = trunc_page(bsh); 222169689Skan endva = round_page(bsh + size); 223169689Skan 224169689Skan pmap_remove(pmap_kernel(), startva, endva); 225169689Skan pmap_update(pmap_kernel()); 226169689Skan uvm_km_free(kernel_map, startva, endva - startva, UVM_KMF_VAONLY); 227169689Skan} 228169689Skan 229169689Skanvoid 230169689Skanifpga_bs_free(void *t, bus_space_handle_t bsh, bus_size_t size) 231169689Skan{ 232169689Skan 233169689Skan panic("ifpga_free(): Help!"); 234169689Skan /* ifpga_bs_unmap() does all that we need to do. */ 235169689Skan/* ifpga_bs_unmap(t, bsh, size);*/ 236169689Skan} 237169689Skan 238169689Skanint 239169689Skanifpga_bs_subregion(void *t, bus_space_handle_t bsh, bus_size_t offset, bus_size_t size, bus_space_handle_t *nbshp) 240169689Skan{ 241169689Skan 242169689Skan *nbshp = bsh + (offset << ((int)t)); 243169689Skan return (0); 244169689Skan} 245169689Skan 246169689Skanvoid * 247169689Skanifpga_bs_vaddr(void *t, bus_space_handle_t bsh) 248169689Skan{ 249169689Skan 250169689Skan return ((void *)bsh); 251169689Skan} 252169689Skan 253169689Skanvoid 254169689Skanifpga_bs_barrier(void *t, bus_space_handle_t bsh, bus_size_t offset, bus_size_t len, int flags) 255169689Skan{ 256169689Skan} 257169689Skan