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