xref: /netbsd-src/sys/arch/dreamcast/dev/g2/g2bus_bus_mem.c (revision 23c8222edbfb0f0932d88a8351d3a0cf817dfb9e)
1 /*	$NetBSD: g2bus_bus_mem.c,v 1.9 2003/08/24 17:33:29 marcus 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  * 3. All advertising materials mentioning features or use of this software
19  *    must display the following acknowledgement:
20  *	This product includes software developed by the NetBSD
21  *	Foundation, Inc. and its contributors.
22  * 4. Neither the name of The NetBSD Foundation nor the names of its
23  *    contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36  * POSSIBILITY OF SUCH DAMAGE.
37  */
38 
39 /*
40  * Bus space implementation for the SEGA G2 bus.
41  *
42  * NOTE: We only implement a small subset of what the bus_space(9)
43  * API specifies.  Right now, the GAPS PCI bridge is only used for
44  * the Dreamcast Broadband Adatper, so we only provide what the
45  * pci(4) and rtk(4) drivers need.
46  */
47 
48 #include <sys/cdefs.h>			/* RCS ID & Copyright macro defns */
49 __KERNEL_RCSID(0, "$NetBSD: g2bus_bus_mem.c,v 1.9 2003/08/24 17:33:29 marcus Exp $");
50 
51 #include <sys/param.h>
52 #include <sys/systm.h>
53 #include <sys/device.h>
54 
55 #include <machine/cpu.h>
56 #include <machine/bus.h>
57 
58 #include <dreamcast/dev/g2/g2busvar.h>
59 
60 int	g2bus_bus_mem_map(void *, bus_addr_t, bus_size_t, int,
61 	    bus_space_handle_t *);
62 void	g2bus_bus_mem_unmap(void *, bus_space_handle_t, bus_size_t);
63 
64 u_int8_t g2bus_bus_mem_read_1(void *, bus_space_handle_t, bus_size_t);
65 u_int16_t g2bus_bus_mem_read_2(void *, bus_space_handle_t, bus_size_t);
66 u_int32_t g2bus_bus_mem_read_4(void *, bus_space_handle_t, bus_size_t);
67 
68 void	g2bus_bus_mem_write_1(void *, bus_space_handle_t, bus_size_t,
69 	    u_int8_t);
70 void	g2bus_bus_mem_write_2(void *, bus_space_handle_t, bus_size_t,
71 	    u_int16_t);
72 void	g2bus_bus_mem_write_4(void *, bus_space_handle_t, bus_size_t,
73 	    u_int32_t);
74 
75 void	g2bus_bus_mem_read_region_1(void *, bus_space_handle_t, bus_size_t,
76 	    u_int8_t *, bus_size_t);
77 void	g2bus_bus_mem_read_region_2(void *, bus_space_handle_t, bus_size_t,
78 	    u_int16_t *, bus_size_t);
79 void	g2bus_bus_mem_read_region_4(void *, bus_space_handle_t, bus_size_t,
80 	    u_int32_t *, bus_size_t);
81 
82 void	g2bus_bus_mem_write_region_1(void *, bus_space_handle_t, bus_size_t,
83 	    const u_int8_t *, bus_size_t);
84 void	g2bus_bus_mem_write_region_2(void *, bus_space_handle_t, bus_size_t,
85 	    const u_int16_t *, bus_size_t);
86 void	g2bus_bus_mem_write_region_4(void *, bus_space_handle_t, bus_size_t,
87 	    const u_int32_t *, bus_size_t);
88 
89 void	g2bus_bus_mem_set_region_4(void *, bus_space_handle_t, bus_size_t,
90 	    u_int32_t, bus_size_t);
91 
92 u_int8_t g2bus_sparse_bus_mem_read_1(void *, bus_space_handle_t, bus_size_t);
93 u_int16_t g2bus_sparse_bus_mem_read_2(void *, bus_space_handle_t, bus_size_t);
94 u_int32_t g2bus_sparse_bus_mem_read_4(void *, bus_space_handle_t, bus_size_t);
95 
96 void	g2bus_sparse_bus_mem_write_1(void *, bus_space_handle_t, bus_size_t,
97 	    u_int8_t);
98 void	g2bus_sparse_bus_mem_write_2(void *, bus_space_handle_t, bus_size_t,
99 	    u_int16_t);
100 void	g2bus_sparse_bus_mem_write_4(void *, bus_space_handle_t, bus_size_t,
101 	    u_int32_t);
102 
103 void	g2bus_sparse_bus_mem_read_region_1(void *, bus_space_handle_t,
104 	    bus_size_t, u_int8_t *, bus_size_t);
105 
106 void	g2bus_sparse_bus_mem_write_region_1(void *, bus_space_handle_t,
107 	    bus_size_t, const u_int8_t *, bus_size_t);
108 
109 void	g2bus_sparse_bus_mem_read_multi_1(void *, bus_space_handle_t,
110 	    bus_size_t, u_int8_t *, bus_size_t);
111 
112 void	g2bus_sparse_bus_mem_write_multi_1(void *, bus_space_handle_t,
113 	    bus_size_t, const u_int8_t *, bus_size_t);
114 
115 void
116 g2bus_bus_mem_init(struct g2bus_softc *sc)
117 {
118 	bus_space_tag_t t = &sc->sc_memt;
119 
120 	memset(t, 0, sizeof(*t));
121 
122 	t->dbs_map = g2bus_bus_mem_map;
123 	t->dbs_unmap = g2bus_bus_mem_unmap;
124 
125 	t->dbs_r_1 = g2bus_bus_mem_read_1;
126 	t->dbs_r_2 = g2bus_bus_mem_read_2;
127 	t->dbs_r_4 = g2bus_bus_mem_read_4;
128 
129 	t->dbs_w_1 = g2bus_bus_mem_write_1;
130 	t->dbs_w_2 = g2bus_bus_mem_write_2;
131 	t->dbs_w_4 = g2bus_bus_mem_write_4;
132 
133 	t->dbs_rr_1 = g2bus_bus_mem_read_region_1;
134 	t->dbs_rr_2 = g2bus_bus_mem_read_region_2;
135 	t->dbs_rr_4 = g2bus_bus_mem_read_region_4;
136 
137 	t->dbs_wr_1 = g2bus_bus_mem_write_region_1;
138 	t->dbs_wr_2 = g2bus_bus_mem_write_region_2;
139 	t->dbs_wr_4 = g2bus_bus_mem_write_region_4;
140 
141 	t->dbs_sr_4 = g2bus_bus_mem_set_region_4;
142 }
143 
144 int
145 g2bus_bus_mem_map(void *v, bus_addr_t addr, bus_size_t size, int flags,
146     bus_space_handle_t *shp)
147 {
148 
149 	KASSERT((addr & SH3_PHYS_MASK) == addr);
150 	*shp = SH3_PHYS_TO_P2SEG(addr);
151 
152 	return (0);
153 }
154 
155 void
156 g2bus_bus_mem_unmap(void *v, bus_space_handle_t sh, bus_size_t size)
157 {
158 
159 	KASSERT(sh >= SH3_P2SEG_BASE && sh <= SH3_P2SEG_END);
160 	/* Nothing to do. */
161 }
162 
163 /*
164  * G2 bus cycles must not be interrupted by IRQs or G2 DMA.
165  * The following paired macros will take the necessary precautions.
166  */
167 
168 #define G2LOCK_DECL							\
169 	int __s
170 
171 #define G2_LOCK()							\
172 	do {								\
173 		__s = _cpu_intr_suspend();				\
174 		/* suspend any G2 DMA here... */			\
175 		while ((*(__volatile u_int32_t *)0xa05f688c) & 0x20)	\
176 			;						\
177 	} while (/*CONSTCOND*/0)
178 
179 #define G2_UNLOCK()							\
180 	do {								\
181 		/* resume any G2 DMA here... */				\
182 		_cpu_intr_resume(__s);					\
183 	} while (/*CONSTCOND*/0)
184 
185 u_int8_t
186 g2bus_bus_mem_read_1(void *v, bus_space_handle_t sh, bus_size_t off)
187 {
188 	G2LOCK_DECL;
189 	u_int8_t rv;
190 
191 	G2_LOCK();
192 
193 	rv = *(__volatile u_int8_t *)(sh + off);
194 
195 	G2_UNLOCK();
196 
197 	return (rv);
198 }
199 
200 u_int16_t
201 g2bus_bus_mem_read_2(void *v, bus_space_handle_t sh, bus_size_t off)
202 {
203 	G2LOCK_DECL;
204 	u_int16_t rv;
205 
206 	G2_LOCK();
207 
208 	rv = *(__volatile u_int16_t *)(sh + off);
209 
210 	G2_UNLOCK();
211 
212 	return (rv);
213 }
214 
215 u_int32_t
216 g2bus_bus_mem_read_4(void *v, bus_space_handle_t sh, bus_size_t off)
217 {
218 	G2LOCK_DECL;
219 	u_int32_t rv;
220 
221 	G2_LOCK();
222 
223 	rv = *(__volatile u_int32_t *)(sh + off);
224 
225 	G2_UNLOCK();
226 
227 	return (rv);
228 }
229 
230 void
231 g2bus_bus_mem_write_1(void *v, bus_space_handle_t sh, bus_size_t off,
232     u_int8_t val)
233 {
234 	G2LOCK_DECL;
235 
236 	G2_LOCK();
237 
238 	*(__volatile u_int8_t *)(sh + off) = val;
239 
240 	G2_UNLOCK();
241 }
242 
243 void
244 g2bus_bus_mem_write_2(void *v, bus_space_handle_t sh, bus_size_t off,
245     u_int16_t val)
246 {
247 	G2LOCK_DECL;
248 
249 	G2_LOCK();
250 
251 	*(__volatile u_int16_t *)(sh + off) = val;
252 
253 	G2_UNLOCK();
254 }
255 
256 void
257 g2bus_bus_mem_write_4(void *v, bus_space_handle_t sh, bus_size_t off,
258     u_int32_t val)
259 {
260 	G2LOCK_DECL;
261 
262 	G2_LOCK();
263 
264 	*(__volatile u_int32_t *)(sh + off) = val;
265 
266 	G2_UNLOCK();
267 }
268 
269 void
270 g2bus_bus_mem_read_region_1(void *v, bus_space_handle_t sh, bus_size_t off,
271     u_int8_t *addr, bus_size_t len)
272 {
273 	G2LOCK_DECL;
274 	__volatile const u_int8_t *baddr = (u_int8_t *)(sh + off);
275 
276 	G2_LOCK();
277 
278 	while (len--)
279 		*addr++ = *baddr++;
280 
281 	G2_UNLOCK();
282 }
283 
284 void
285 g2bus_bus_mem_read_region_2(void *v, bus_space_handle_t sh, bus_size_t off,
286     u_int16_t *addr, bus_size_t len)
287 {
288 	G2LOCK_DECL;
289 	__volatile const u_int16_t *baddr = (u_int16_t *)(sh + off);
290 
291 	G2_LOCK();
292 
293 	while (len--)
294 		*addr++ = *baddr++;
295 
296 	G2_UNLOCK();
297 }
298 
299 void
300 g2bus_bus_mem_read_region_4(void *v, bus_space_handle_t sh, bus_size_t off,
301     u_int32_t *addr, bus_size_t len)
302 {
303 	G2LOCK_DECL;
304 	__volatile const u_int32_t *baddr = (u_int32_t *)(sh + off);
305 
306 	G2_LOCK();
307 
308 	while (len--)
309 		*addr++ = *baddr++;
310 
311 	G2_UNLOCK();
312 }
313 
314 void
315 g2bus_bus_mem_write_region_1(void *v, bus_space_handle_t sh, bus_size_t off,
316     const u_int8_t *addr, bus_size_t len)
317 {
318 	G2LOCK_DECL;
319 	__volatile u_int8_t *baddr = (u_int8_t *)(sh + off);
320 
321 	G2_LOCK();
322 
323 	while (len--)
324 		*baddr++ = *addr++;
325 
326 	G2_UNLOCK();
327 }
328 
329 void
330 g2bus_bus_mem_write_region_2(void *v, bus_space_handle_t sh, bus_size_t off,
331     const u_int16_t *addr, bus_size_t len)
332 {
333 	G2LOCK_DECL;
334 	__volatile u_int16_t *baddr = (u_int16_t *)(sh + off);
335 
336 	G2_LOCK();
337 
338 	while (len--)
339 		*baddr++ = *addr++;
340 
341 	G2_UNLOCK();
342 }
343 
344 void
345 g2bus_bus_mem_write_region_4(void *v, bus_space_handle_t sh, bus_size_t off,
346     const u_int32_t *addr, bus_size_t len)
347 {
348 	G2LOCK_DECL;
349 	__volatile u_int32_t *baddr = (u_int32_t *)(sh + off);
350 
351 	G2_LOCK();
352 
353 	while (len--)
354 		*baddr++ = *addr++;
355 
356 	G2_UNLOCK();
357 }
358 
359 void
360 g2bus_bus_mem_set_region_4(void *v, bus_space_handle_t sh, bus_size_t off,
361     u_int32_t val, bus_size_t len)
362 {
363 	G2LOCK_DECL;
364 	__volatile u_int32_t *baddr = (u_int32_t *)(sh + off);
365 
366 	G2_LOCK();
367 
368 	while (len--)
369 		*baddr++ = val;
370 
371 	G2_UNLOCK();
372 }
373 
374 void
375 g2bus_set_bus_mem_sparse(bus_space_tag_t memt)
376 {
377 
378 	memt->dbs_r_1 = g2bus_sparse_bus_mem_read_1;
379 	memt->dbs_r_2 = g2bus_sparse_bus_mem_read_2;
380 	memt->dbs_r_4 = g2bus_sparse_bus_mem_read_4;
381 
382 	memt->dbs_w_1 = g2bus_sparse_bus_mem_write_1;
383 	memt->dbs_w_2 = g2bus_sparse_bus_mem_write_2;
384 	memt->dbs_w_4 = g2bus_sparse_bus_mem_write_4;
385 
386 	memt->dbs_rr_1 = g2bus_sparse_bus_mem_read_region_1;
387 
388 	memt->dbs_wr_1 = g2bus_sparse_bus_mem_write_region_1;
389 
390 	memt->dbs_rm_1 = g2bus_sparse_bus_mem_read_multi_1;
391 
392 	memt->dbs_wm_1 = g2bus_sparse_bus_mem_write_multi_1;
393 }
394 
395 u_int8_t
396 g2bus_sparse_bus_mem_read_1(void *v, bus_space_handle_t sh, bus_size_t off)
397 {
398 	G2LOCK_DECL;
399 	u_int8_t rv;
400 
401 	G2_LOCK();
402 
403 	rv = *(__volatile u_int8_t *)(sh + (off * 4));
404 
405 	G2_UNLOCK();
406 
407 	return (rv);
408 }
409 
410 u_int16_t
411 g2bus_sparse_bus_mem_read_2(void *v, bus_space_handle_t sh, bus_size_t off)
412 {
413 	G2LOCK_DECL;
414 	u_int16_t rv;
415 
416 	G2_LOCK();
417 
418 	rv = *(__volatile u_int16_t *)(sh + (off * 4));
419 
420 	G2_UNLOCK();
421 
422 	return (rv);
423 }
424 
425 u_int32_t
426 g2bus_sparse_bus_mem_read_4(void *v, bus_space_handle_t sh, bus_size_t off)
427 {
428 	G2LOCK_DECL;
429 	u_int32_t rv;
430 
431 	G2_LOCK();
432 
433 	rv = *(__volatile u_int32_t *)(sh + (off * 4));
434 
435 	G2_UNLOCK();
436 
437 	return (rv);
438 }
439 
440 void
441 g2bus_sparse_bus_mem_write_1(void *v, bus_space_handle_t sh, bus_size_t off,
442     u_int8_t val)
443 {
444 	G2LOCK_DECL;
445 
446 	G2_LOCK();
447 
448 	*(__volatile u_int8_t *)(sh + (off * 4)) = val;
449 
450 	G2_UNLOCK();
451 }
452 
453 void
454 g2bus_sparse_bus_mem_write_2(void *v, bus_space_handle_t sh, bus_size_t off,
455     u_int16_t val)
456 {
457 	G2LOCK_DECL;
458 
459 	G2_LOCK();
460 
461 	*(__volatile u_int16_t *)(sh + (off * 4)) = val;
462 
463 	G2_UNLOCK();
464 }
465 
466 void
467 g2bus_sparse_bus_mem_write_4(void *v, bus_space_handle_t sh, bus_size_t off,
468     u_int32_t val)
469 {
470 	G2LOCK_DECL;
471 
472 	G2_LOCK();
473 
474 	*(__volatile u_int32_t *)(sh + (off * 4)) = val;
475 
476 	G2_UNLOCK();
477 }
478 
479 void
480 g2bus_sparse_bus_mem_read_region_1(void *v, bus_space_handle_t sh,
481     bus_size_t off, u_int8_t *addr, bus_size_t len)
482 {
483 	G2LOCK_DECL;
484 	__volatile const u_int8_t *baddr = (u_int8_t *)(sh + (off * 4));
485 
486 	G2_LOCK();
487 
488 	while (len--) {
489 		*addr++ = *baddr;
490 		baddr += 4;
491 	}
492 
493 	G2_UNLOCK();
494 }
495 
496 void
497 g2bus_sparse_bus_mem_write_region_1(void *v, bus_space_handle_t sh,
498     bus_size_t off, const u_int8_t *addr, bus_size_t len)
499 {
500 	G2LOCK_DECL;
501 	__volatile u_int8_t *baddr = (u_int8_t *)(sh + (off * 4));
502 
503 	G2_LOCK();
504 
505 	while (len--) {
506 		*baddr = *addr++;
507 		baddr += 4;
508 	}
509 
510 	G2_UNLOCK();
511 }
512 
513 void
514 g2bus_sparse_bus_mem_read_multi_1(void *v, bus_space_handle_t sh,
515     bus_size_t off, u_int8_t *addr, bus_size_t len)
516 {
517 	G2LOCK_DECL;
518 	__volatile const u_int8_t *baddr = (u_int8_t *)(sh + (off * 4));
519 
520 	G2_LOCK();
521 
522 	while (len--)
523 		*addr++ = *baddr;
524 
525 	G2_UNLOCK();
526 }
527 
528 void
529 g2bus_sparse_bus_mem_write_multi_1(void *v, bus_space_handle_t sh,
530     bus_size_t off, const u_int8_t *addr, bus_size_t len)
531 {
532 	G2LOCK_DECL;
533 	__volatile u_int8_t *baddr = (u_int8_t *)(sh + (off * 4));
534 
535 	G2_LOCK();
536 
537 	while (len--)
538 		*baddr = *addr++;
539 
540 	G2_UNLOCK();
541 }
542