1 /* $NetBSD: bus_space.c,v 1.2 2023/05/07 12:41:48 skrll Exp $ */ 2 3 /*- 4 * Copyright (c) 2022 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Nick Hudson 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 #include "opt_console.h" 33 34 #include <sys/cdefs.h> 35 __KERNEL_RCSID(1, "$NetBSD: bus_space.c,v 1.2 2023/05/07 12:41:48 skrll Exp $"); 36 37 #include <sys/param.h> 38 #include <sys/systm.h> 39 #include <sys/bus.h> 40 41 #include <uvm/uvm_extern.h> 42 43 #include <riscv/bus_funcs.h> 44 45 /* Prototypes for all the bus_space structure functions */ 46 bs_protos(generic); 47 bs_protos(bs_notimpl); 48 49 #ifdef _LP64 50 51 #define GENERIC_BS_R_8 generic_bs_r_8 52 #define GENERIC_BS_RM_8 generic_bs_rm_8 53 #define GENERIC_BS_W_8 generic_bs_w_8 54 #define GENERIC_BS_WM_8 generic_bs_wm_8 55 56 #else 57 58 #define GENERIC_BS_R_8 bs_notimpl_bs_r_8 59 #define GENERIC_BS_RM_8 bs_notimpl_bs_rm_8 60 #define GENERIC_BS_W_8 bs_notimpl_bs_w_8 61 #define GENERIC_BS_WM_8 bs_notimpl_bs_wm_8 62 63 #endif 64 65 struct bus_space riscv_generic_bs_tag = { 66 // .bs_cookie = &riscv_generic_bs_tag, 67 68 .bs_stride = 0, 69 // .bs_flags = 0, 70 71 .bs_map = generic_bs_map, 72 .bs_unmap = generic_bs_unmap, 73 .bs_subregion = generic_bs_subregion, 74 .bs_alloc = generic_bs_alloc, 75 .bs_free = generic_bs_free, 76 .bs_vaddr = generic_bs_vaddr, 77 .bs_mmap = generic_bs_mmap, 78 .bs_barrier = generic_bs_barrier, 79 80 /* read */ 81 .bs_r_1 = generic_bs_r_1, 82 .bs_r_2 = generic_bs_r_2, 83 .bs_r_4 = generic_bs_r_4, 84 .bs_r_8 = GENERIC_BS_R_8, 85 86 /* write */ 87 .bs_w_1 = generic_bs_w_1, 88 .bs_w_2 = generic_bs_w_2, 89 .bs_w_4 = generic_bs_w_4, 90 .bs_w_8 = GENERIC_BS_W_8, 91 92 /* read region */ 93 .bs_rr_1 = generic_bs_rr_1, 94 .bs_rr_2 = bs_notimpl_bs_rr_2 /*generic_bs_rr_2*/, 95 .bs_rr_4 = bs_notimpl_bs_rr_4 /*generic_bs_rr_4*/, 96 .bs_rr_8 = bs_notimpl_bs_rr_8 /*generic_bs_rr_8*/, 97 98 /* write region */ 99 .bs_wr_1 = bs_notimpl_bs_wr_1 /*generic_bs_wr_1*/, 100 .bs_wr_2 = bs_notimpl_bs_wr_2 /*generic_bs_wr_2*/, 101 .bs_wr_4 = bs_notimpl_bs_wr_4 /*generic_bs_wr_4*/, 102 .bs_wr_8 = bs_notimpl_bs_wr_8 /*generic_bs_wr_8*/, 103 104 /* copy region */ 105 .bs_c_1 = bs_notimpl_bs_c_1 /* generic_bs_c_1 */, 106 .bs_c_2 = bs_notimpl_bs_c_2 /* generic_bs_c_2 */, 107 .bs_c_4 = bs_notimpl_bs_c_4 /* generic_bs_c_4 */, 108 .bs_c_8 = bs_notimpl_bs_c_8 /* generic_bs_c_8 */, 109 110 /* set region */ 111 .bs_sr_1 = bs_notimpl_bs_sr_1 /* generic_bs_sr_1 */, 112 .bs_sr_2 = bs_notimpl_bs_sr_2 /* generic_bs_sr_2 */, 113 .bs_sr_4 = bs_notimpl_bs_sr_4 /* generic_bs_sr_4 */, 114 .bs_sr_8 = bs_notimpl_bs_sr_8 /* generic_bs_sr_8 */, 115 116 /* read multi */ 117 .bs_rm_1 = generic_bs_rm_1, 118 .bs_rm_2 = generic_bs_rm_2, 119 .bs_rm_4 = generic_bs_rm_4, 120 .bs_rm_8 = GENERIC_BS_RM_8, 121 122 /* write multi */ 123 .bs_wm_1 = generic_bs_wm_1, 124 .bs_wm_2 = generic_bs_wm_2, 125 .bs_wm_4 = generic_bs_wm_4, 126 .bs_wm_8 = GENERIC_BS_WM_8, 127 128 /* set multi */ 129 .bs_sm_1 = bs_notimpl_bs_sm_1 /* generic_bs_sm_1 */, 130 .bs_sm_2 = bs_notimpl_bs_sm_2 /* generic_bs_sm_2 */, 131 .bs_sm_4 = bs_notimpl_bs_sm_4 /* generic_bs_sm_4 */, 132 .bs_sm_8 = bs_notimpl_bs_sm_8 /* generic_bs_sm_8 */, 133 134 #ifdef __BUS_SPACE_HAS_STREAM_METHODS 135 /* read stream */ 136 .bs_r_1_s = generic_bs_r_1, 137 .bs_r_2_s = generic_bs_r_2, 138 .bs_r_4_s = generic_bs_r_4, 139 .bs_r_8_s = GENERIC_BS_R_8, 140 141 /* write stream */ 142 .bs_w_1_s = generic_bs_w_1, 143 .bs_w_2_s = generic_bs_w_2, 144 .bs_w_4_s = generic_bs_w_4, 145 .bs_w_8_s = GENERIC_BS_W_8, 146 147 /* read region stream */ 148 .bs_rr_1_s = generic_bs_rr_1, 149 .bs_rr_2_s = generic_bs_rr_2, 150 .bs_rr_4_s = bs_notimpl_bs_rr_4 /*generic_bs_rr_4*/, 151 .bs_rr_8_s = bs_notimpl_bs_rr_8 /*generic_bs_rr_8*/, 152 153 /* write region stream */ 154 .bs_wr_1_s = bs_notimpl_bs_wr_1 /*generic_bs_wr_1*/, 155 .bs_wr_2_s = bs_notimpl_bs_wr_2 /*generic_bs_wr_2*/, 156 .bs_wr_4_s = bs_notimpl_bs_wr_4 /*generic_bs_wr_4*/, 157 .bs_wr_8_s = bs_notimpl_bs_wr_8 /*generic_bs_wr_8*/, 158 159 /* read multi stream */ 160 .bs_rm_1_s = generic_bs_rm_1, 161 .bs_rm_2_s = generic_bs_rm_2, 162 .bs_rm_4_s = generic_bs_rm_4, 163 .bs_rm_8_s = GENERIC_BS_RM_8, 164 165 /* write multi stream */ 166 .bs_wm_1_s = generic_bs_wm_1, 167 .bs_wm_2_s = generic_bs_wm_2, 168 .bs_wm_4_s = generic_bs_wm_4, 169 .bs_wm_8_s = GENERIC_BS_WM_8, 170 #endif 171 172 #ifdef __BUS_SPACE_HAS_PROBING_METHODS 173 /* peek */ 174 .bs_pe_1 = generic_bs_pe_1, 175 .bs_pe_2 = generic_bs_pe_2, 176 .bs_pe_4 = generic_bs_pe_4, 177 .bs_pe_8 = generic_bs_pe_8, 178 179 /* poke */ 180 .bs_po_1 = generic_bs_po_1, 181 .bs_po_2 = generic_bs_po_2, 182 .bs_po_4 = generic_bs_po_4, 183 .bs_po_8 = generic_bs_po_8, 184 #endif 185 }; 186 187 struct bus_space riscv_generic_a4x_bs_tag = { 188 // .bs_cookie = &riscv_generic_a4x_bs_tag, 189 190 .bs_stride = 2, 191 // .bs_flags = 0, 192 193 .bs_map = generic_bs_map, 194 .bs_unmap = generic_bs_unmap, 195 .bs_subregion = generic_bs_subregion, 196 .bs_alloc = generic_bs_alloc, 197 .bs_free = generic_bs_free, 198 .bs_vaddr = generic_bs_vaddr, 199 .bs_mmap = generic_bs_mmap, 200 .bs_barrier = generic_bs_barrier, 201 202 /* read */ 203 .bs_r_1 = generic_bs_r_1, 204 .bs_r_2 = generic_bs_r_2, 205 .bs_r_4 = generic_bs_r_4, 206 .bs_r_8 = GENERIC_BS_R_8, 207 208 /* write */ 209 .bs_w_1 = generic_bs_w_1, 210 .bs_w_2 = generic_bs_w_2, 211 .bs_w_4 = generic_bs_w_4, 212 .bs_w_8 = GENERIC_BS_W_8, 213 214 /* read region */ 215 .bs_rr_1 = generic_bs_rr_1, 216 .bs_rr_2 = generic_bs_rr_2, 217 .bs_rr_4 = bs_notimpl_bs_rr_4 /*generic_bs_rr_4*/, 218 .bs_rr_8 = bs_notimpl_bs_rr_8 /*generic_bs_rr_8*/, 219 220 /* write region */ 221 .bs_wr_1 = bs_notimpl_bs_wr_1 /*generic_bs_wr_1*/, 222 .bs_wr_2 = bs_notimpl_bs_wr_2 /*generic_bs_wr_2*/, 223 .bs_wr_4 = bs_notimpl_bs_wr_4 /*generic_bs_wr_4*/, 224 .bs_wr_8 = bs_notimpl_bs_wr_8 /*generic_bs_wr_8*/, 225 226 /* copy region */ 227 .bs_c_1 = bs_notimpl_bs_c_1 /* generic_bs_c_1 */, 228 .bs_c_2 = bs_notimpl_bs_c_2 /* generic_bs_c_2 */, 229 .bs_c_4 = bs_notimpl_bs_c_4 /* generic_bs_c_4 */, 230 .bs_c_8 = bs_notimpl_bs_c_8 /* generic_bs_c_8 */, 231 232 /* set region */ 233 .bs_sr_1 = bs_notimpl_bs_sr_1 /* generic_bs_sr_1 */, 234 .bs_sr_2 = bs_notimpl_bs_sr_2 /* generic_bs_sr_2 */, 235 .bs_sr_4 = bs_notimpl_bs_sr_4 /* generic_bs_sr_4 */, 236 .bs_sr_8 = bs_notimpl_bs_sr_8 /* generic_bs_sr_8 */, 237 238 /* read multi */ 239 .bs_rm_1 = generic_bs_rm_1, 240 .bs_rm_2 = generic_bs_rm_2, 241 .bs_rm_4 = generic_bs_rm_4, 242 .bs_rm_8 = GENERIC_BS_RM_8, 243 244 /* write multi */ 245 .bs_wm_1 = generic_bs_wm_1, 246 .bs_wm_2 = generic_bs_wm_2, 247 .bs_wm_4 = generic_bs_wm_4, 248 .bs_wm_8 = GENERIC_BS_WM_8, 249 250 /* set multi */ 251 .bs_sm_1 = bs_notimpl_bs_sm_1 /* generic_bs_sm_1 */, 252 .bs_sm_2 = bs_notimpl_bs_sm_2 /* generic_bs_sm_2 */, 253 .bs_sm_4 = bs_notimpl_bs_sm_4 /* generic_bs_sm_4 */, 254 .bs_sm_8 = bs_notimpl_bs_sm_8 /* generic_bs_sm_8 */, 255 256 #ifdef __BUS_SPACE_HAS_STREAM_METHODS 257 /* read stream */ 258 .bs_r_1_s = generic_bs_r_1, 259 .bs_r_2_s = generic_bs_r_2, 260 .bs_r_4_s = generic_bs_r_4, 261 .bs_r_8_s = GENERIC_BS_R_8, 262 263 /* write stream */ 264 .bs_w_1_s = generic_bs_w_1, 265 .bs_w_2_s = generic_bs_w_2, 266 .bs_w_4_s = generic_bs_w_4, 267 .bs_w_8_s = GENERIC_BS_W_8, 268 269 /* read region stream */ 270 .bs_rr_1_s = generic_bs_rr_1, 271 .bs_rr_2_s = generic_bs_rr_2, 272 .bs_rr_4_s = bs_notimpl_bs_rr_4 /*generic_bs_rr_4*/, 273 .bs_rr_8_s = bs_notimpl_bs_rr_8 /*generic_bs_rr_8*/, 274 275 /* write region stream */ 276 .bs_wr_1_s = bs_notimpl_bs_wr_1 /*generic_bs_wr_1*/, 277 .bs_wr_2_s = bs_notimpl_bs_wr_2 /*generic_bs_wr_2*/, 278 .bs_wr_4_s = bs_notimpl_bs_wr_4 /*generic_bs_wr_4*/, 279 .bs_wr_8_s = bs_notimpl_bs_wr_8 /*generic_bs_wr_8*/, 280 281 /* read multi stream */ 282 .bs_rm_1_s = generic_bs_rm_1, 283 .bs_rm_2_s = generic_bs_rm_2, 284 .bs_rm_4_s = generic_bs_rm_4, 285 .bs_rm_8_s = GENERIC_BS_RM_8, 286 287 /* write multi stream */ 288 .bs_wm_1_s = generic_bs_wm_1, 289 .bs_wm_2_s = generic_bs_wm_2, 290 .bs_wm_4_s = generic_bs_wm_4, 291 .bs_wm_8_s = GENERIC_BS_WM_8, 292 #endif 293 }; 294 295 int 296 generic_bs_map(void *t, bus_addr_t bpa, bus_size_t size, int flag, 297 bus_space_handle_t *bshp) 298 { 299 const struct pmap_devmap *pd; 300 paddr_t startpa, endpa, pa; 301 vaddr_t va; 302 int pmapflags; 303 304 if ((pd = pmap_devmap_find_pa(bpa, size)) != NULL) { 305 *bshp = pd->pd_va + (bpa - pd->pd_pa); 306 return 0; 307 } 308 309 startpa = trunc_page(bpa); 310 endpa = round_page(bpa + size); 311 312 /* XXX use extent manager to check duplicate mapping */ 313 314 va = uvm_km_alloc(kernel_map, endpa - startpa, 0, 315 UVM_KMF_VAONLY | UVM_KMF_NOWAIT); 316 if (va == 0) 317 return ENOMEM; 318 319 *bshp = (bus_space_handle_t)(va + (bpa - startpa)); 320 321 #if 0 322 if ((flag & BUS_SPACE_MAP_PREFETCHABLE) != 0) 323 pmapflags = PMAP_WRITE_COMBINE; 324 else if ((flag & BUS_SPACE_MAP_CACHEABLE) != 0) 325 pmapflags = PMAP_WRITE_BACK; 326 else if ((flag & _RISCV_BUS_SPACE_MAP_STRONGLY_ORDERED) != 0) 327 pmapflags = PMAP_DEV_NP; 328 else 329 pmapflags = PMAP_DEV; 330 #endif 331 332 pmapflags = 0; 333 334 for (pa = startpa; pa < endpa; pa += PAGE_SIZE, va += PAGE_SIZE) { 335 pmap_kenter_pa(va, pa, VM_PROT_READ | VM_PROT_WRITE, pmapflags); 336 } 337 pmap_update(pmap_kernel()); 338 339 return 0; 340 } 341 342 void 343 generic_bs_unmap(void *t, bus_space_handle_t bsh, bus_size_t size) 344 { 345 vaddr_t va; 346 vsize_t sz; 347 348 if (pmap_devmap_find_va(bsh, size) != NULL) 349 return; 350 va = trunc_page(bsh); 351 sz = round_page(bsh + size) - va; 352 353 pmap_kremove(va, sz); 354 pmap_update(pmap_kernel()); 355 uvm_km_free(kernel_map, va, sz, UVM_KMF_VAONLY); 356 } 357 358 359 int 360 generic_bs_subregion(void *t, bus_space_handle_t bsh, bus_size_t offset, 361 bus_size_t size, bus_space_handle_t *nbshp) 362 { 363 *nbshp = bsh + (offset << ((struct bus_space *)t)->bs_stride); 364 return 0; 365 } 366 367 void 368 generic_bs_barrier(void *t, bus_space_handle_t bsh, bus_size_t offset, 369 bus_size_t len, int flags) 370 { 371 #if 0 372 flags &= BUS_SPACE_BARRIER_READ|BUS_SPACE_BARRIER_WRITE; 373 374 switch (flags) { 375 case BUS_SPACE_BARRIER_READ: 376 dmb(ishld); 377 break; 378 case BUS_SPACE_BARRIER_WRITE: 379 dmb(ishst); 380 break; 381 case BUS_SPACE_BARRIER_READ|BUS_SPACE_BARRIER_WRITE: 382 dmb(ish); 383 break; 384 } 385 #endif 386 } 387 388 void * 389 generic_bs_vaddr(void *t, bus_space_handle_t bsh) 390 { 391 return (void *)bsh; 392 } 393 394 paddr_t 395 generic_bs_mmap(void *t, bus_addr_t bpa, off_t offset, int prot, int flags) 396 { 397 paddr_t bus_flags = 0; 398 399 #if 0 400 if ((flags & BUS_SPACE_MAP_CACHEABLE) != 0) 401 bus_flags |= RISCV_MMAP_WRITEBACK; 402 else if ((flags & BUS_SPACE_MAP_PREFETCHABLE) != 0) 403 bus_flags |= RISCV_MMAP_WRITECOMBINE; 404 else 405 bus_flags |= RISCV_MMAP_DEVICE; 406 407 #endif 408 409 return (atop(bpa + (offset << ((struct bus_space *)t)->bs_stride)) | 410 bus_flags); 411 } 412 413 int 414 generic_bs_alloc(void *t, bus_addr_t rstart, bus_addr_t rend, 415 bus_size_t size, bus_size_t alignment, bus_size_t boundary, int flags, 416 bus_addr_t *bpap, bus_space_handle_t *bshp) 417 { 418 panic("%s(): not implemented\n", __func__); 419 } 420 421 void 422 generic_bs_free(void *t, bus_space_handle_t bsh, bus_size_t size) 423 { 424 panic("%s(): not implemented\n", __func__); 425 } 426 427