1 /* $NetBSD: g2bus_bus_mem.c,v 1.16 2011/07/19 15:52:29 dyoung Exp $ */ 2 3 /*- 4 * Copyright (c) 2001 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Jason R. Thorpe. 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 /* 33 * Bus space implementation for the SEGA G2 bus. 34 * 35 * NOTE: We only implement a small subset of what the bus_space(9) 36 * API specifies. Right now, the GAPS PCI bridge is only used for 37 * the Dreamcast Broadband Adatper, so we only provide what the 38 * pci(4) and rtk(4) drivers need. 39 */ 40 41 #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ 42 __KERNEL_RCSID(0, "$NetBSD: g2bus_bus_mem.c,v 1.16 2011/07/19 15:52:29 dyoung Exp $"); 43 44 #include <sys/param.h> 45 #include <sys/systm.h> 46 #include <sys/device.h> 47 #include <sys/bus.h> 48 49 #include <machine/cpu.h> 50 51 #include <dreamcast/dev/g2/g2busvar.h> 52 53 int g2bus_bus_mem_map(void *, bus_addr_t, bus_size_t, int, 54 bus_space_handle_t *); 55 void g2bus_bus_mem_unmap(void *, bus_space_handle_t, bus_size_t); 56 paddr_t g2bus_bus_mem_mmap(void *, bus_addr_t, off_t, int, int); 57 58 uint8_t g2bus_bus_mem_read_1(void *, bus_space_handle_t, bus_size_t); 59 uint16_t g2bus_bus_mem_read_2(void *, bus_space_handle_t, bus_size_t); 60 uint32_t g2bus_bus_mem_read_4(void *, bus_space_handle_t, bus_size_t); 61 62 void g2bus_bus_mem_write_1(void *, bus_space_handle_t, bus_size_t, 63 uint8_t); 64 void g2bus_bus_mem_write_2(void *, bus_space_handle_t, bus_size_t, 65 uint16_t); 66 void g2bus_bus_mem_write_4(void *, bus_space_handle_t, bus_size_t, 67 uint32_t); 68 69 void g2bus_bus_mem_read_region_1(void *, bus_space_handle_t, bus_size_t, 70 uint8_t *, bus_size_t); 71 void g2bus_bus_mem_read_region_2(void *, bus_space_handle_t, bus_size_t, 72 uint16_t *, bus_size_t); 73 void g2bus_bus_mem_read_region_4(void *, bus_space_handle_t, bus_size_t, 74 uint32_t *, bus_size_t); 75 76 void g2bus_bus_mem_write_region_1(void *, bus_space_handle_t, bus_size_t, 77 const uint8_t *, bus_size_t); 78 void g2bus_bus_mem_write_region_2(void *, bus_space_handle_t, bus_size_t, 79 const uint16_t *, bus_size_t); 80 void g2bus_bus_mem_write_region_4(void *, bus_space_handle_t, bus_size_t, 81 const uint32_t *, bus_size_t); 82 83 void g2bus_bus_mem_set_region_4(void *, bus_space_handle_t, bus_size_t, 84 uint32_t, bus_size_t); 85 86 uint8_t g2bus_sparse_bus_mem_read_1(void *, bus_space_handle_t, bus_size_t); 87 uint16_t g2bus_sparse_bus_mem_read_2(void *, bus_space_handle_t, bus_size_t); 88 uint32_t g2bus_sparse_bus_mem_read_4(void *, bus_space_handle_t, bus_size_t); 89 90 void g2bus_sparse_bus_mem_write_1(void *, bus_space_handle_t, bus_size_t, 91 uint8_t); 92 void g2bus_sparse_bus_mem_write_2(void *, bus_space_handle_t, bus_size_t, 93 uint16_t); 94 void g2bus_sparse_bus_mem_write_4(void *, bus_space_handle_t, bus_size_t, 95 uint32_t); 96 97 void g2bus_sparse_bus_mem_read_region_1(void *, bus_space_handle_t, 98 bus_size_t, uint8_t *, bus_size_t); 99 100 void g2bus_sparse_bus_mem_write_region_1(void *, bus_space_handle_t, 101 bus_size_t, const uint8_t *, bus_size_t); 102 103 void g2bus_sparse_bus_mem_read_multi_1(void *, bus_space_handle_t, 104 bus_size_t, uint8_t *, bus_size_t); 105 106 void g2bus_sparse_bus_mem_write_multi_1(void *, bus_space_handle_t, 107 bus_size_t, const uint8_t *, bus_size_t); 108 109 void 110 g2bus_bus_mem_init(struct g2bus_softc *sc) 111 { 112 bus_space_tag_t t = &sc->sc_memt; 113 114 memset(t, 0, sizeof(*t)); 115 116 t->dbs_map = g2bus_bus_mem_map; 117 t->dbs_unmap = g2bus_bus_mem_unmap; 118 t->dbs_mmap = g2bus_bus_mem_mmap; 119 120 t->dbs_r_1 = g2bus_bus_mem_read_1; 121 t->dbs_r_2 = g2bus_bus_mem_read_2; 122 t->dbs_r_4 = g2bus_bus_mem_read_4; 123 124 t->dbs_w_1 = g2bus_bus_mem_write_1; 125 t->dbs_w_2 = g2bus_bus_mem_write_2; 126 t->dbs_w_4 = g2bus_bus_mem_write_4; 127 128 t->dbs_rr_1 = g2bus_bus_mem_read_region_1; 129 t->dbs_rr_2 = g2bus_bus_mem_read_region_2; 130 t->dbs_rr_4 = g2bus_bus_mem_read_region_4; 131 132 t->dbs_wr_1 = g2bus_bus_mem_write_region_1; 133 t->dbs_wr_2 = g2bus_bus_mem_write_region_2; 134 t->dbs_wr_4 = g2bus_bus_mem_write_region_4; 135 136 t->dbs_sr_4 = g2bus_bus_mem_set_region_4; 137 } 138 139 int 140 g2bus_bus_mem_map(void *v, bus_addr_t addr, bus_size_t size, int flags, 141 bus_space_handle_t *shp) 142 { 143 144 KASSERT((addr & SH3_PHYS_MASK) == addr); 145 *shp = SH3_PHYS_TO_P2SEG(addr); 146 147 return 0; 148 } 149 150 void 151 g2bus_bus_mem_unmap(void *v, bus_space_handle_t sh, bus_size_t size) 152 { 153 154 KASSERT(sh >= SH3_P2SEG_BASE && sh <= SH3_P2SEG_END); 155 /* Nothing to do. */ 156 } 157 158 paddr_t 159 g2bus_bus_mem_mmap(void *v, bus_addr_t addr, off_t offset, int prot, int flags) 160 { 161 162 /* XXX not implemented */ 163 return -1; 164 } 165 166 /* 167 * G2 bus cycles must not be interrupted by IRQs or G2 DMA. 168 * The following paired macros will take the necessary precautions. 169 */ 170 171 #define G2LOCK_DECL \ 172 int __s 173 174 #define G2_LOCK() \ 175 do { \ 176 __s = _cpu_intr_suspend(); \ 177 /* suspend any G2 DMA here... */ \ 178 while ((*(volatile uint32_t *)0xa05f688c) & 0x20) \ 179 ; \ 180 } while (/*CONSTCOND*/0) 181 182 #define G2_UNLOCK() \ 183 do { \ 184 /* resume any G2 DMA here... */ \ 185 _cpu_intr_resume(__s); \ 186 } while (/*CONSTCOND*/0) 187 188 uint8_t 189 g2bus_bus_mem_read_1(void *v, bus_space_handle_t sh, bus_size_t off) 190 { 191 G2LOCK_DECL; 192 uint8_t rv; 193 194 G2_LOCK(); 195 196 rv = *(volatile uint8_t *)(sh + off); 197 198 G2_UNLOCK(); 199 200 return rv; 201 } 202 203 uint16_t 204 g2bus_bus_mem_read_2(void *v, bus_space_handle_t sh, bus_size_t off) 205 { 206 G2LOCK_DECL; 207 uint16_t rv; 208 209 G2_LOCK(); 210 211 rv = *(volatile uint16_t *)(sh + off); 212 213 G2_UNLOCK(); 214 215 return rv; 216 } 217 218 uint32_t 219 g2bus_bus_mem_read_4(void *v, bus_space_handle_t sh, bus_size_t off) 220 { 221 G2LOCK_DECL; 222 uint32_t rv; 223 224 G2_LOCK(); 225 226 rv = *(volatile uint32_t *)(sh + off); 227 228 G2_UNLOCK(); 229 230 return rv; 231 } 232 233 void 234 g2bus_bus_mem_write_1(void *v, bus_space_handle_t sh, bus_size_t off, 235 uint8_t val) 236 { 237 G2LOCK_DECL; 238 239 G2_LOCK(); 240 241 *(volatile uint8_t *)(sh + off) = val; 242 243 G2_UNLOCK(); 244 } 245 246 void 247 g2bus_bus_mem_write_2(void *v, bus_space_handle_t sh, bus_size_t off, 248 uint16_t val) 249 { 250 G2LOCK_DECL; 251 252 G2_LOCK(); 253 254 *(volatile uint16_t *)(sh + off) = val; 255 256 G2_UNLOCK(); 257 } 258 259 void 260 g2bus_bus_mem_write_4(void *v, bus_space_handle_t sh, bus_size_t off, 261 uint32_t val) 262 { 263 G2LOCK_DECL; 264 265 G2_LOCK(); 266 267 *(volatile uint32_t *)(sh + off) = val; 268 269 G2_UNLOCK(); 270 } 271 272 void 273 g2bus_bus_mem_read_region_1(void *v, bus_space_handle_t sh, bus_size_t off, 274 uint8_t *addr, bus_size_t len) 275 { 276 G2LOCK_DECL; 277 volatile const uint8_t *baddr = (uint8_t *)(sh + off); 278 279 G2_LOCK(); 280 281 while (len--) 282 *addr++ = *baddr++; 283 284 G2_UNLOCK(); 285 } 286 287 void 288 g2bus_bus_mem_read_region_2(void *v, bus_space_handle_t sh, bus_size_t off, 289 uint16_t *addr, bus_size_t len) 290 { 291 G2LOCK_DECL; 292 volatile const uint16_t *baddr = (uint16_t *)(sh + off); 293 294 G2_LOCK(); 295 296 while (len--) 297 *addr++ = *baddr++; 298 299 G2_UNLOCK(); 300 } 301 302 void 303 g2bus_bus_mem_read_region_4(void *v, bus_space_handle_t sh, bus_size_t off, 304 uint32_t *addr, bus_size_t len) 305 { 306 G2LOCK_DECL; 307 volatile const uint32_t *baddr = (uint32_t *)(sh + off); 308 309 G2_LOCK(); 310 311 while (len--) 312 *addr++ = *baddr++; 313 314 G2_UNLOCK(); 315 } 316 317 void 318 g2bus_bus_mem_write_region_1(void *v, bus_space_handle_t sh, bus_size_t off, 319 const uint8_t *addr, bus_size_t len) 320 { 321 G2LOCK_DECL; 322 volatile uint8_t *baddr = (uint8_t *)(sh + off); 323 324 G2_LOCK(); 325 326 while (len--) 327 *baddr++ = *addr++; 328 329 G2_UNLOCK(); 330 } 331 332 void 333 g2bus_bus_mem_write_region_2(void *v, bus_space_handle_t sh, bus_size_t off, 334 const uint16_t *addr, bus_size_t len) 335 { 336 G2LOCK_DECL; 337 volatile uint16_t *baddr = (uint16_t *)(sh + off); 338 339 G2_LOCK(); 340 341 while (len--) 342 *baddr++ = *addr++; 343 344 G2_UNLOCK(); 345 } 346 347 void 348 g2bus_bus_mem_write_region_4(void *v, bus_space_handle_t sh, bus_size_t off, 349 const uint32_t *addr, bus_size_t len) 350 { 351 G2LOCK_DECL; 352 volatile uint32_t *baddr = (uint32_t *)(sh + off); 353 354 G2_LOCK(); 355 356 while (len--) 357 *baddr++ = *addr++; 358 359 G2_UNLOCK(); 360 } 361 362 void 363 g2bus_bus_mem_set_region_4(void *v, bus_space_handle_t sh, bus_size_t off, 364 uint32_t val, bus_size_t len) 365 { 366 G2LOCK_DECL; 367 volatile uint32_t *baddr = (uint32_t *)(sh + off); 368 369 G2_LOCK(); 370 371 while (len--) 372 *baddr++ = val; 373 374 G2_UNLOCK(); 375 } 376 377 void 378 g2bus_set_bus_mem_sparse(bus_space_tag_t memt) 379 { 380 381 memt->dbs_r_1 = g2bus_sparse_bus_mem_read_1; 382 memt->dbs_r_2 = g2bus_sparse_bus_mem_read_2; 383 memt->dbs_r_4 = g2bus_sparse_bus_mem_read_4; 384 385 memt->dbs_w_1 = g2bus_sparse_bus_mem_write_1; 386 memt->dbs_w_2 = g2bus_sparse_bus_mem_write_2; 387 memt->dbs_w_4 = g2bus_sparse_bus_mem_write_4; 388 389 memt->dbs_rr_1 = g2bus_sparse_bus_mem_read_region_1; 390 391 memt->dbs_wr_1 = g2bus_sparse_bus_mem_write_region_1; 392 393 memt->dbs_rm_1 = g2bus_sparse_bus_mem_read_multi_1; 394 395 memt->dbs_wm_1 = g2bus_sparse_bus_mem_write_multi_1; 396 } 397 398 uint8_t 399 g2bus_sparse_bus_mem_read_1(void *v, bus_space_handle_t sh, bus_size_t off) 400 { 401 G2LOCK_DECL; 402 uint8_t rv; 403 404 G2_LOCK(); 405 406 rv = *(volatile uint8_t *)(sh + (off * 4)); 407 408 G2_UNLOCK(); 409 410 return rv; 411 } 412 413 uint16_t 414 g2bus_sparse_bus_mem_read_2(void *v, bus_space_handle_t sh, bus_size_t off) 415 { 416 G2LOCK_DECL; 417 uint16_t rv; 418 419 G2_LOCK(); 420 421 rv = *(volatile uint16_t *)(sh + (off * 4)); 422 423 G2_UNLOCK(); 424 425 return rv; 426 } 427 428 uint32_t 429 g2bus_sparse_bus_mem_read_4(void *v, bus_space_handle_t sh, bus_size_t off) 430 { 431 G2LOCK_DECL; 432 uint32_t rv; 433 434 G2_LOCK(); 435 436 rv = *(volatile uint32_t *)(sh + (off * 4)); 437 438 G2_UNLOCK(); 439 440 return rv; 441 } 442 443 void 444 g2bus_sparse_bus_mem_write_1(void *v, bus_space_handle_t sh, bus_size_t off, 445 uint8_t val) 446 { 447 G2LOCK_DECL; 448 449 G2_LOCK(); 450 451 *(volatile uint8_t *)(sh + (off * 4)) = val; 452 453 G2_UNLOCK(); 454 } 455 456 void 457 g2bus_sparse_bus_mem_write_2(void *v, bus_space_handle_t sh, bus_size_t off, 458 uint16_t val) 459 { 460 G2LOCK_DECL; 461 462 G2_LOCK(); 463 464 *(volatile uint16_t *)(sh + (off * 4)) = val; 465 466 G2_UNLOCK(); 467 } 468 469 void 470 g2bus_sparse_bus_mem_write_4(void *v, bus_space_handle_t sh, bus_size_t off, 471 uint32_t val) 472 { 473 G2LOCK_DECL; 474 475 G2_LOCK(); 476 477 *(volatile uint32_t *)(sh + (off * 4)) = val; 478 479 G2_UNLOCK(); 480 } 481 482 void 483 g2bus_sparse_bus_mem_read_region_1(void *v, bus_space_handle_t sh, 484 bus_size_t off, uint8_t *addr, bus_size_t len) 485 { 486 G2LOCK_DECL; 487 volatile const uint8_t *baddr = (uint8_t *)(sh + (off * 4)); 488 489 G2_LOCK(); 490 491 while (len--) { 492 *addr++ = *baddr; 493 baddr += 4; 494 } 495 496 G2_UNLOCK(); 497 } 498 499 void 500 g2bus_sparse_bus_mem_write_region_1(void *v, bus_space_handle_t sh, 501 bus_size_t off, const uint8_t *addr, bus_size_t len) 502 { 503 G2LOCK_DECL; 504 volatile uint8_t *baddr = (uint8_t *)(sh + (off * 4)); 505 506 G2_LOCK(); 507 508 while (len--) { 509 *baddr = *addr++; 510 baddr += 4; 511 } 512 513 G2_UNLOCK(); 514 } 515 516 void 517 g2bus_sparse_bus_mem_read_multi_1(void *v, bus_space_handle_t sh, 518 bus_size_t off, uint8_t *addr, bus_size_t len) 519 { 520 G2LOCK_DECL; 521 volatile const uint8_t *baddr = (uint8_t *)(sh + (off * 4)); 522 523 G2_LOCK(); 524 525 while (len--) 526 *addr++ = *baddr; 527 528 G2_UNLOCK(); 529 } 530 531 void 532 g2bus_sparse_bus_mem_write_multi_1(void *v, bus_space_handle_t sh, 533 bus_size_t off, const uint8_t *addr, bus_size_t len) 534 { 535 G2LOCK_DECL; 536 volatile uint8_t *baddr = (uint8_t *)(sh + (off * 4)); 537 538 G2_LOCK(); 539 540 while (len--) 541 *baddr = *addr++; 542 543 G2_UNLOCK(); 544 } 545