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