Home | History | Annotate | Line # | Download | only in g2
      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