Home | History | Annotate | Line # | Download | only in g2
g2bus_bus_mem.c revision 1.14
      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