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