xref: /netbsd-src/sys/arch/dreamcast/dev/g2/g2bus_bus_mem.c (revision 274254cdae52594c1aa480a736aef78313d15c9c)
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