1/* $NetBSD: g2bus_bus_mem.c,v 1.15 2009/08/23 14:28:09 tsutsui 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.15 2009/08/23 14:28:09 tsutsui 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 53int g2bus_bus_mem_map(void *, bus_addr_t, bus_size_t, int, 54 bus_space_handle_t *); 55void g2bus_bus_mem_unmap(void *, bus_space_handle_t, bus_size_t); 56paddr_t g2bus_bus_mem_mmap(void *, bus_addr_t, off_t, int, int); 57 58uint8_t g2bus_bus_mem_read_1(void *, bus_space_handle_t, bus_size_t); 59uint16_t g2bus_bus_mem_read_2(void *, bus_space_handle_t, bus_size_t); 60uint32_t g2bus_bus_mem_read_4(void *, bus_space_handle_t, bus_size_t); 61 62void g2bus_bus_mem_write_1(void *, bus_space_handle_t, bus_size_t, 63 uint8_t); 64void g2bus_bus_mem_write_2(void *, bus_space_handle_t, bus_size_t, 65 uint16_t); 66void g2bus_bus_mem_write_4(void *, bus_space_handle_t, bus_size_t, 67 uint32_t); 68 69void g2bus_bus_mem_read_region_1(void *, bus_space_handle_t, bus_size_t, 70 uint8_t *, bus_size_t); 71void g2bus_bus_mem_read_region_2(void *, bus_space_handle_t, bus_size_t, 72 uint16_t *, bus_size_t); 73void g2bus_bus_mem_read_region_4(void *, bus_space_handle_t, bus_size_t, 74 uint32_t *, bus_size_t); 75 76void g2bus_bus_mem_write_region_1(void *, bus_space_handle_t, bus_size_t, 77 const uint8_t *, bus_size_t); 78void g2bus_bus_mem_write_region_2(void *, bus_space_handle_t, bus_size_t, 79 const uint16_t *, bus_size_t); 80void g2bus_bus_mem_write_region_4(void *, bus_space_handle_t, bus_size_t, 81 const uint32_t *, bus_size_t); 82 83void g2bus_bus_mem_set_region_4(void *, bus_space_handle_t, bus_size_t, 84 uint32_t, bus_size_t); 85 86uint8_t g2bus_sparse_bus_mem_read_1(void *, bus_space_handle_t, bus_size_t); 87uint16_t g2bus_sparse_bus_mem_read_2(void *, bus_space_handle_t, bus_size_t); 88uint32_t g2bus_sparse_bus_mem_read_4(void *, bus_space_handle_t, bus_size_t); 89 90void g2bus_sparse_bus_mem_write_1(void *, bus_space_handle_t, bus_size_t, 91 uint8_t); 92void g2bus_sparse_bus_mem_write_2(void *, bus_space_handle_t, bus_size_t, 93 uint16_t); 94void g2bus_sparse_bus_mem_write_4(void *, bus_space_handle_t, bus_size_t, 95 uint32_t); 96 97void g2bus_sparse_bus_mem_read_region_1(void *, bus_space_handle_t, 98 bus_size_t, uint8_t *, bus_size_t); 99 100void g2bus_sparse_bus_mem_write_region_1(void *, bus_space_handle_t, 101 bus_size_t, const uint8_t *, bus_size_t); 102 103void g2bus_sparse_bus_mem_read_multi_1(void *, bus_space_handle_t, 104 bus_size_t, uint8_t *, bus_size_t); 105 106void g2bus_sparse_bus_mem_write_multi_1(void *, bus_space_handle_t, 107 bus_size_t, const uint8_t *, bus_size_t); 108 109void 110g2bus_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 139int 140g2bus_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 150void 151g2bus_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 158paddr_t 159g2bus_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 188uint8_t 189g2bus_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 203uint16_t 204g2bus_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 218uint32_t 219g2bus_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 233void 234g2bus_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 246void 247g2bus_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 259void 260g2bus_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 272void 273g2bus_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 287void 288g2bus_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 302void 303g2bus_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 317void 318g2bus_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 332void 333g2bus_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 347void 348g2bus_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 362void 363g2bus_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 377void 378g2bus_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 398uint8_t 399g2bus_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 413uint16_t 414g2bus_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 428uint32_t 429g2bus_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 443void 444g2bus_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 456void 457g2bus_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 469void 470g2bus_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 482void 483g2bus_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 499void 500g2bus_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 516void 517g2bus_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 531void 532g2bus_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