xref: /netbsd-src/sys/arch/dreamcast/dev/g2/g2bus_bus_mem.c (revision 86b5be6e94187e7fa009ab97c775a47c83c11874)
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
g2bus_bus_mem_init(struct g2bus_softc * sc)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
g2bus_bus_mem_map(void * v,bus_addr_t addr,bus_size_t size,int flags,bus_space_handle_t * shp)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
g2bus_bus_mem_unmap(void * v,bus_space_handle_t sh,bus_size_t size)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
g2bus_bus_mem_mmap(void * v,bus_addr_t addr,off_t offset,int prot,int flags)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
g2bus_bus_mem_read_1(void * v,bus_space_handle_t sh,bus_size_t off)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
g2bus_bus_mem_read_2(void * v,bus_space_handle_t sh,bus_size_t off)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
g2bus_bus_mem_read_4(void * v,bus_space_handle_t sh,bus_size_t off)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
g2bus_bus_mem_write_1(void * v,bus_space_handle_t sh,bus_size_t off,uint8_t val)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
g2bus_bus_mem_write_2(void * v,bus_space_handle_t sh,bus_size_t off,uint16_t val)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
g2bus_bus_mem_write_4(void * v,bus_space_handle_t sh,bus_size_t off,uint32_t val)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
g2bus_bus_mem_read_region_1(void * v,bus_space_handle_t sh,bus_size_t off,uint8_t * addr,bus_size_t len)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
g2bus_bus_mem_read_region_2(void * v,bus_space_handle_t sh,bus_size_t off,uint16_t * addr,bus_size_t len)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
g2bus_bus_mem_read_region_4(void * v,bus_space_handle_t sh,bus_size_t off,uint32_t * addr,bus_size_t len)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
g2bus_bus_mem_write_region_1(void * v,bus_space_handle_t sh,bus_size_t off,const uint8_t * addr,bus_size_t len)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
g2bus_bus_mem_write_region_2(void * v,bus_space_handle_t sh,bus_size_t off,const uint16_t * addr,bus_size_t len)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
g2bus_bus_mem_write_region_4(void * v,bus_space_handle_t sh,bus_size_t off,const uint32_t * addr,bus_size_t len)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
g2bus_bus_mem_set_region_4(void * v,bus_space_handle_t sh,bus_size_t off,uint32_t val,bus_size_t len)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
g2bus_set_bus_mem_sparse(bus_space_tag_t memt)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
g2bus_sparse_bus_mem_read_1(void * v,bus_space_handle_t sh,bus_size_t off)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
g2bus_sparse_bus_mem_read_2(void * v,bus_space_handle_t sh,bus_size_t off)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
g2bus_sparse_bus_mem_read_4(void * v,bus_space_handle_t sh,bus_size_t off)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
g2bus_sparse_bus_mem_write_1(void * v,bus_space_handle_t sh,bus_size_t off,uint8_t val)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
g2bus_sparse_bus_mem_write_2(void * v,bus_space_handle_t sh,bus_size_t off,uint16_t val)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
g2bus_sparse_bus_mem_write_4(void * v,bus_space_handle_t sh,bus_size_t off,uint32_t val)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
g2bus_sparse_bus_mem_read_region_1(void * v,bus_space_handle_t sh,bus_size_t off,uint8_t * addr,bus_size_t len)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
g2bus_sparse_bus_mem_write_region_1(void * v,bus_space_handle_t sh,bus_size_t off,const uint8_t * addr,bus_size_t len)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
g2bus_sparse_bus_mem_read_multi_1(void * v,bus_space_handle_t sh,bus_size_t off,uint8_t * addr,bus_size_t len)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
g2bus_sparse_bus_mem_write_multi_1(void * v,bus_space_handle_t sh,bus_size_t off,const uint8_t * addr,bus_size_t len)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