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