1 /* $NetBSD: mvsoc_space.c,v 1.12 2022/05/23 21:46:11 andvar Exp $ */ 2 /* 3 * Copyright (c) 2007 KIYOHARA Takashi 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 19 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 23 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 24 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 * POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 #include <sys/cdefs.h> 29 __KERNEL_RCSID(0, "$NetBSD: mvsoc_space.c,v 1.12 2022/05/23 21:46:11 andvar Exp $"); 30 31 #include "opt_mvsoc.h" 32 #include "mvpex.h" 33 #include "gtpci.h" 34 35 #include <sys/param.h> 36 #include <sys/systm.h> 37 38 #include <uvm/uvm_extern.h> 39 40 #include <sys/bus.h> 41 42 #include <arm/marvell/mvsocreg.h> 43 #include <arm/marvell/mvsocvar.h> 44 45 #ifdef __ARMEB__ 46 #define NSWAP(n) n ## _swap 47 #else 48 #define NSWAP(n) n 49 #endif 50 51 /* Proto types for all the bus_space structure functions */ 52 bs_protos(mvsoc); 53 bs_protos(generic); 54 bs_protos(generic_armv4); 55 bs_protos(bs_notimpl); 56 57 #define MVSOC_BUS_SPACE_NORMAL_FUNCS \ 58 /* read (single) */ \ 59 .bs_r_1 = generic_bs_r_1, \ 60 .bs_r_2 = NSWAP(generic_armv4_bs_r_2), \ 61 .bs_r_4 = NSWAP(generic_bs_r_4), \ 62 .bs_r_8 = bs_notimpl_bs_r_8, \ 63 \ 64 /* read multiple */ \ 65 .bs_rm_1 = generic_bs_rm_1, \ 66 .bs_rm_2 = NSWAP(generic_armv4_bs_rm_2),\ 67 .bs_rm_4 = NSWAP(generic_bs_rm_4), \ 68 .bs_rm_8 = bs_notimpl_bs_rm_8, \ 69 \ 70 /* read region */ \ 71 .bs_rr_1 = generic_bs_rr_1, \ 72 .bs_rr_2 = NSWAP(generic_armv4_bs_rr_2),\ 73 .bs_rr_4 = NSWAP(generic_bs_rr_4), \ 74 .bs_rr_8 = bs_notimpl_bs_rr_8, \ 75 \ 76 /* write (single) */ \ 77 .bs_w_1 = generic_bs_w_1, \ 78 .bs_w_2 = NSWAP(generic_armv4_bs_w_2), \ 79 .bs_w_4 = NSWAP(generic_bs_w_4), \ 80 .bs_w_8 = bs_notimpl_bs_w_8, \ 81 \ 82 /* write multiple */ \ 83 .bs_wm_1 = generic_bs_wm_1, \ 84 .bs_wm_2 = NSWAP(generic_armv4_bs_wm_2),\ 85 .bs_wm_4 = NSWAP(generic_bs_wm_4), \ 86 .bs_wm_8 = bs_notimpl_bs_wm_8, \ 87 \ 88 /* write region */ \ 89 .bs_wr_1 = generic_bs_wr_1, \ 90 .bs_wr_2 = NSWAP(generic_armv4_bs_wr_2),\ 91 .bs_wr_4 = NSWAP(generic_bs_wr_4), \ 92 .bs_wr_8 = bs_notimpl_bs_wr_8 93 94 #define MVSOC_BUS_SPACE_STREAM_FUNCS \ 95 /* read stream (single) */ \ 96 .bs_r_1_s = generic_bs_r_1, \ 97 .bs_r_2_s = NSWAP(generic_armv4_bs_r_2),\ 98 .bs_r_4_s = NSWAP(generic_bs_r_4), \ 99 .bs_r_8_s = bs_notimpl_bs_r_8, \ 100 \ 101 /* read multiple stream */ \ 102 .bs_rm_1_s = generic_bs_rm_1, \ 103 .bs_rm_2_s = NSWAP(generic_armv4_bs_rm_2),\ 104 .bs_rm_4_s = NSWAP(generic_bs_rm_4), \ 105 .bs_rm_8_s = bs_notimpl_bs_rm_8, \ 106 \ 107 /* read region stream */ \ 108 .bs_rr_1_s = generic_bs_rr_1, \ 109 .bs_rr_2_s = NSWAP(generic_armv4_bs_rr_2),\ 110 .bs_rr_4_s = NSWAP(generic_bs_rr_4), \ 111 .bs_rr_8_s = bs_notimpl_bs_rr_8, \ 112 \ 113 /* write stream (single) */ \ 114 .bs_w_1_s = generic_bs_w_1, \ 115 .bs_w_2_s = NSWAP(generic_armv4_bs_w_2),\ 116 .bs_w_4_s = NSWAP(generic_bs_w_4, \ 117 .bs_w_8_s = bs_notimpl_bs_w_8, \ 118 \ 119 /* write multiple stream */ \ 120 .bs_wm_1_s = generic_bs_wm_1, \ 121 .bs_wm_2_s = NSWAP(generic_armv4_bs_wm_2),\ 122 .bs_wm_4_s = NSWAP(generic_bs_wm_4), \ 123 .bs_wm_8_s = bs_notimpl_bs_wm_8, \ 124 \ 125 /* write region stream */ \ 126 .bs_wr_1_s = generic_bs_wr_1, \ 127 .bs_wr_2_s = NSWAP(generic_armv4_bs_wr_2),\ 128 .bs_wr_4_s = NSWAP(generic_bs_wr_4), \ 129 .bs_wr_8_s = bs_notimpl_bs_wr_8 130 131 #define MVSOC_BUS_SPACE_DEFAULT_FUNCS \ 132 /* mapping/unmapping */ \ 133 .bs_map = mvsoc_bs_map, \ 134 .bs_unmap = mvsoc_bs_unmap, \ 135 .bs_subregion = mvsoc_bs_subregion, \ 136 \ 137 /* allocation/deallocation */ \ 138 .bs_alloc = mvsoc_bs_alloc, \ 139 .bs_free = mvsoc_bs_free, \ 140 \ 141 /* get kernel virtual address */ \ 142 .bs_vaddr = mvsoc_bs_vaddr, \ 143 \ 144 /* mmap bus space for userland */ \ 145 .bs_mmap = bs_notimpl_bs_mmap, \ 146 \ 147 /* barrier */ \ 148 .bs_barrier = mvsoc_bs_barrier, \ 149 \ 150 MVSOC_BUS_SPACE_NORMAL_FUNCS, \ 151 \ 152 /* set multiple */ \ 153 .bs_sm_1 = bs_notimpl_bs_sm_1, \ 154 .bs_sm_2 = bs_notimpl_bs_sm_2, \ 155 .bs_sm_4 = bs_notimpl_bs_sm_4, \ 156 .bs_sm_8 = bs_notimpl_bs_sm_8, \ 157 \ 158 /* set region */ \ 159 .bs_sr_1 = bs_notimpl_bs_sr_1, \ 160 .bs_sr_2 = NSWAP(generic_armv4_bs_sr_2),\ 161 .bs_sr_4 = NSWAP(generic_bs_sr_4), \ 162 .bs_sr_8 = bs_notimpl_bs_sr_8, \ 163 \ 164 /* copy */ \ 165 .bs_c_1 = bs_notimpl_bs_c_1, \ 166 .bs_c_2 = generic_armv4_bs_c_2, \ 167 .bs_c_4 = bs_notimpl_bs_c_4, \ 168 .bs_c_8 = bs_notimpl_bs_c_8 169 170 171 struct bus_space mvsoc_bs_tag = { 172 /* cookie */ 173 .bs_cookie = (void *)0, 174 175 MVSOC_BUS_SPACE_DEFAULT_FUNCS, 176 #ifdef __BUS_SPACE_HAS_STREAM_METHODS 177 MVSOC_BUS_SPACE_NORMAL_FUNCS, 178 #endif 179 }; 180 181 #if NMVPEX > 0 182 #if defined(ORION) 183 struct bus_space orion_pex0_mem_bs_tag = { 184 /* cookie */ 185 .bs_cookie = (void *)ORION_TAG_PEX0_MEM, 186 187 MVSOC_BUS_SPACE_DEFAULT_FUNCS, 188 #ifdef __BUS_SPACE_HAS_STREAM_METHODS 189 MVSOC_BUS_SPACE_NORMAL_FUNCS, 190 #endif 191 }; 192 struct bus_space orion_pex0_io_bs_tag = { 193 /* cookie */ 194 .bs_cookie = (void *)ORION_TAG_PEX0_IO, 195 196 MVSOC_BUS_SPACE_DEFAULT_FUNCS, 197 #ifdef __BUS_SPACE_HAS_STREAM_METHODS 198 MVSOC_BUS_SPACE_NORMAL_FUNCS, 199 #endif 200 }; 201 struct bus_space orion_pex1_mem_bs_tag = { 202 /* cookie */ 203 .bs_cookie = (void *)ORION_TAG_PEX1_MEM, 204 205 MVSOC_BUS_SPACE_DEFAULT_FUNCS, 206 #ifdef __BUS_SPACE_HAS_STREAM_METHODS 207 MVSOC_BUS_SPACE_NORMAL_FUNCS, 208 #endif 209 }; 210 struct bus_space orion_pex1_io_bs_tag = { 211 /* cookie */ 212 .bs_cookie = (void *)ORION_TAG_PEX1_IO, 213 214 MVSOC_BUS_SPACE_DEFAULT_FUNCS, 215 #ifdef __BUS_SPACE_HAS_STREAM_METHODS 216 MVSOC_BUS_SPACE_NORMAL_FUNCS, 217 #endif 218 }; 219 #endif 220 221 #if defined(KIRKWOOD) 222 struct bus_space kirkwood_pex_mem_bs_tag = { 223 /* cookie */ 224 .bs_cookie = (void *)KIRKWOOD_TAG_PEX_MEM, 225 226 MVSOC_BUS_SPACE_DEFAULT_FUNCS, 227 #ifdef __BUS_SPACE_HAS_STREAM_METHODS 228 MVSOC_BUS_SPACE_NORMAL_FUNCS, 229 #endif 230 }; 231 struct bus_space kirkwood_pex_io_bs_tag = { 232 /* cookie */ 233 .bs_cookie = (void *)KIRKWOOD_TAG_PEX_IO, 234 235 MVSOC_BUS_SPACE_DEFAULT_FUNCS, 236 #ifdef __BUS_SPACE_HAS_STREAM_METHODS 237 MVSOC_BUS_SPACE_NORMAL_FUNCS, 238 #endif 239 }; 240 struct bus_space kirkwood_pex1_mem_bs_tag = { 241 /* cookie */ 242 .bs_cookie = (void *)KIRKWOOD_TAG_PEX1_MEM, 243 244 MVSOC_BUS_SPACE_DEFAULT_FUNCS, 245 #ifdef __BUS_SPACE_HAS_STREAM_METHODS 246 MVSOC_BUS_SPACE_NORMAL_FUNCS, 247 #endif 248 }; 249 struct bus_space kirkwood_pex1_io_bs_tag = { 250 /* cookie */ 251 .bs_cookie = (void *)KIRKWOOD_TAG_PEX1_IO, 252 253 MVSOC_BUS_SPACE_DEFAULT_FUNCS, 254 #ifdef __BUS_SPACE_HAS_STREAM_METHODS 255 MVSOC_BUS_SPACE_NORMAL_FUNCS, 256 #endif 257 }; 258 #endif 259 260 #if defined(DOVE) 261 struct bus_space dove_pex0_mem_bs_tag = { 262 /* cookie */ 263 .bs_cookie = (void *)DOVE_TAG_PEX0_MEM, 264 265 MVSOC_BUS_SPACE_DEFAULT_FUNCS, 266 #ifdef __BUS_SPACE_HAS_STREAM_METHODS 267 MVSOC_BUS_SPACE_NORMAL_FUNCS, 268 #endif 269 }; 270 struct bus_space dove_pex0_io_bs_tag = { 271 /* cookie */ 272 .bs_cookie = (void *)DOVE_TAG_PEX0_IO, 273 274 MVSOC_BUS_SPACE_DEFAULT_FUNCS, 275 #ifdef __BUS_SPACE_HAS_STREAM_METHODS 276 MVSOC_BUS_SPACE_NORMAL_FUNCS, 277 #endif 278 }; 279 struct bus_space dove_pex1_mem_bs_tag = { 280 /* cookie */ 281 .bs_cookie = (void *)DOVE_TAG_PEX1_MEM, 282 283 MVSOC_BUS_SPACE_DEFAULT_FUNCS, 284 #ifdef __BUS_SPACE_HAS_STREAM_METHODS 285 MVSOC_BUS_SPACE_NORMAL_FUNCS, 286 #endif 287 }; 288 struct bus_space dove_pex1_io_bs_tag = { 289 /* cookie */ 290 .bs_cookie = (void *)DOVE_TAG_PEX1_IO, 291 292 MVSOC_BUS_SPACE_DEFAULT_FUNCS, 293 #ifdef __BUS_SPACE_HAS_STREAM_METHODS 294 MVSOC_BUS_SPACE_NORMAL_FUNCS, 295 #endif 296 }; 297 #endif 298 299 #if defined(ARMADAXP) 300 struct bus_space armadaxp_pex00_mem_bs_tag = { 301 /* cookie */ 302 .bs_cookie = (void *)ARMADAXP_TAG_PEX00_MEM, 303 304 MVSOC_BUS_SPACE_DEFAULT_FUNCS 305 }; 306 struct bus_space armadaxp_pex00_io_bs_tag = { 307 /* cookie */ 308 .bs_cookie = (void *)ARMADAXP_TAG_PEX00_IO, 309 310 MVSOC_BUS_SPACE_DEFAULT_FUNCS 311 }; 312 struct bus_space armadaxp_pex01_mem_bs_tag = { 313 /* cookie */ 314 .bs_cookie = (void *)ARMADAXP_TAG_PEX01_MEM, 315 316 MVSOC_BUS_SPACE_DEFAULT_FUNCS 317 }; 318 struct bus_space armadaxp_pex01_io_bs_tag = { 319 /* cookie */ 320 .bs_cookie = (void *)ARMADAXP_TAG_PEX01_IO, 321 322 MVSOC_BUS_SPACE_DEFAULT_FUNCS 323 }; 324 struct bus_space armadaxp_pex02_mem_bs_tag = { 325 /* cookie */ 326 .bs_cookie = (void *)ARMADAXP_TAG_PEX02_MEM, 327 328 MVSOC_BUS_SPACE_DEFAULT_FUNCS 329 }; 330 struct bus_space armadaxp_pex02_io_bs_tag = { 331 /* cookie */ 332 .bs_cookie = (void *)ARMADAXP_TAG_PEX02_IO, 333 334 MVSOC_BUS_SPACE_DEFAULT_FUNCS 335 }; 336 struct bus_space armadaxp_pex03_mem_bs_tag = { 337 /* cookie */ 338 .bs_cookie = (void *)ARMADAXP_TAG_PEX03_MEM, 339 340 MVSOC_BUS_SPACE_DEFAULT_FUNCS 341 }; 342 struct bus_space armadaxp_pex03_io_bs_tag = { 343 /* cookie */ 344 .bs_cookie = (void *)ARMADAXP_TAG_PEX03_IO, 345 346 MVSOC_BUS_SPACE_DEFAULT_FUNCS 347 }; 348 struct bus_space armadaxp_pex10_mem_bs_tag = { 349 /* cookie */ 350 .bs_cookie = (void *)ARMADAXP_TAG_PEX10_MEM, 351 352 MVSOC_BUS_SPACE_DEFAULT_FUNCS 353 }; 354 struct bus_space armadaxp_pex10_io_bs_tag = { 355 /* cookie */ 356 .bs_cookie = (void *)ARMADAXP_TAG_PEX10_IO, 357 358 MVSOC_BUS_SPACE_DEFAULT_FUNCS 359 }; 360 struct bus_space armadaxp_pex2_mem_bs_tag = { 361 /* cookie */ 362 .bs_cookie = (void *)ARMADAXP_TAG_PEX2_MEM, 363 364 MVSOC_BUS_SPACE_DEFAULT_FUNCS 365 }; 366 struct bus_space armadaxp_pex2_io_bs_tag = { 367 /* cookie */ 368 .bs_cookie = (void *)ARMADAXP_TAG_PEX2_IO, 369 370 MVSOC_BUS_SPACE_DEFAULT_FUNCS 371 }; 372 struct bus_space armadaxp_pex3_mem_bs_tag = { 373 /* cookie */ 374 .bs_cookie = (void *)ARMADAXP_TAG_PEX3_MEM, 375 376 MVSOC_BUS_SPACE_DEFAULT_FUNCS 377 }; 378 struct bus_space armadaxp_pex3_io_bs_tag = { 379 /* cookie */ 380 .bs_cookie = (void *)ARMADAXP_TAG_PEX3_IO, 381 382 MVSOC_BUS_SPACE_DEFAULT_FUNCS 383 }; 384 #endif 385 #endif 386 387 #if NGTPCI > 0 388 #if defined(ORION) 389 struct bus_space orion_pci_mem_bs_tag = { 390 /* cookie */ 391 .bs_cookie = (void *)ORION_TAG_PCI_MEM, 392 393 MVSOC_BUS_SPACE_DEFAULT_FUNCS, 394 #ifdef __BUS_SPACE_HAS_STREAM_METHODS 395 MVSOC_BUS_SPACE_NORMAL_FUNCS, 396 #endif 397 }; 398 struct bus_space orion_pci_io_bs_tag = { 399 /* cookie */ 400 .bs_cookie = (void *)ORION_TAG_PCI_IO, 401 402 MVSOC_BUS_SPACE_DEFAULT_FUNCS, 403 #ifdef __BUS_SPACE_HAS_STREAM_METHODS 404 MVSOC_BUS_SPACE_NORMAL_FUNCS, 405 #endif 406 }; 407 #endif 408 #endif 409 410 411 int 412 mvsoc_bs_map(void *space, bus_addr_t address, bus_size_t size, int flags, 413 bus_space_handle_t *handlep) 414 { 415 const struct pmap_devmap *pd; 416 paddr_t startpa, endpa, offset, pa; 417 vaddr_t va; 418 419 /* 420 * XXX: We are not configuring any decode windows for Armada XP 421 * at the moment. We rely on those that have been set by u-boot. 422 * Hence we don't want to mess around with decode windows, 423 * till we get full control over them. 424 */ 425 426 int tag = (int)space; 427 428 if (tag != 0) { 429 bus_addr_t remap; 430 uint32_t base; 431 int window; 432 433 window = mvsoc_target(tag, NULL, NULL, &base, NULL); 434 if (window == -1) 435 return ENOMEM; 436 if (window < nremap) { 437 remap = read_mlmbreg(MVSOC_MLMB_WRLR(window)) & 438 MVSOC_MLMB_WRLR_REMAP_MASK; 439 remap |= 440 (read_mlmbreg(MVSOC_MLMB_WRHR(window)) << 16) << 16; 441 address = address - remap + base; 442 } 443 } 444 445 if ((pd = pmap_devmap_find_pa(address, size)) != NULL) { 446 /* Device was statically mapped. */ 447 *handlep = pd->pd_va + (address - pd->pd_pa); 448 return 0; 449 } 450 451 startpa = trunc_page(address); 452 endpa = round_page(address + size); 453 offset = address & PAGE_MASK; 454 455 /* XXX use extent manager to check duplicate mapping */ 456 457 va = uvm_km_alloc(kernel_map, endpa - startpa, 0, 458 UVM_KMF_VAONLY | UVM_KMF_NOWAIT); 459 if (va == 0x00000000) 460 return ENOMEM; 461 462 *handlep = va + offset; 463 464 const int pmapflags = 465 (flags & (BUS_SPACE_MAP_CACHEABLE|BUS_SPACE_MAP_PREFETCHABLE)) 466 ? 0 467 : PMAP_NOCACHE; 468 469 /* Now map the pages */ 470 for (pa = startpa; pa < endpa; pa += PAGE_SIZE, va += PAGE_SIZE) { 471 pmap_kenter_pa(va, pa, VM_PROT_READ | VM_PROT_WRITE, pmapflags); 472 } 473 pmap_update(pmap_kernel()); 474 475 return 0; 476 } 477 478 void 479 mvsoc_bs_unmap(void *space, bus_space_handle_t handle, bus_size_t size) 480 { 481 vaddr_t va, sz; 482 483 if (pmap_devmap_find_va(handle, size) != NULL) 484 /* Device was statically mapped; nothing to do. */ 485 return; 486 487 va = trunc_page(handle); 488 sz = round_page(handle + size) - va; 489 490 pmap_kremove(va, sz); 491 pmap_update(pmap_kernel()); 492 uvm_km_free(kernel_map, va, sz, UVM_KMF_VAONLY); 493 } 494 495 /* ARGSUSED */ 496 int 497 mvsoc_bs_subregion(void *space, bus_space_handle_t handle, 498 bus_size_t offset, bus_size_t size, 499 bus_space_handle_t *nhandlep) 500 { 501 502 *nhandlep = handle + offset; 503 return 0; 504 } 505 506 /* ARGSUSED */ 507 int 508 mvsoc_bs_alloc(void *space, bus_addr_t reg_start, bus_addr_t reg_end, 509 bus_size_t size, bus_size_t alignment, bus_size_t boundary, 510 int flags, bus_addr_t *addrp, bus_space_handle_t *handlep) 511 { 512 513 panic("%s(): not implemented\n", __func__); 514 } 515 516 /* ARGSUSED */ 517 void 518 mvsoc_bs_free(void *space, bus_space_handle_t handle, bus_size_t size) 519 { 520 521 panic("%s(): not implemented\n", __func__); 522 } 523 524 /* ARGSUSED */ 525 void 526 mvsoc_bs_barrier(void *space, bus_space_handle_t handle, bus_size_t offset, 527 bus_size_t length, int flags) 528 { 529 530 /* Nothing to do. */ 531 } 532 533 /* ARGSUSED */ 534 void * 535 mvsoc_bs_vaddr(void *space, bus_space_handle_t handle) 536 { 537 538 return (void *)handle; 539 } 540