1/*	$NetBSD: g2bus_bus_mem.c,v 1.15 2009/08/23 14:28:09 tsutsui 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.15 2009/08/23 14:28:09 tsutsui 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
53int	g2bus_bus_mem_map(void *, bus_addr_t, bus_size_t, int,
54	    bus_space_handle_t *);
55void	g2bus_bus_mem_unmap(void *, bus_space_handle_t, bus_size_t);
56paddr_t	g2bus_bus_mem_mmap(void *, bus_addr_t, off_t, int, int);
57
58uint8_t g2bus_bus_mem_read_1(void *, bus_space_handle_t, bus_size_t);
59uint16_t g2bus_bus_mem_read_2(void *, bus_space_handle_t, bus_size_t);
60uint32_t g2bus_bus_mem_read_4(void *, bus_space_handle_t, bus_size_t);
61
62void	g2bus_bus_mem_write_1(void *, bus_space_handle_t, bus_size_t,
63	    uint8_t);
64void	g2bus_bus_mem_write_2(void *, bus_space_handle_t, bus_size_t,
65	    uint16_t);
66void	g2bus_bus_mem_write_4(void *, bus_space_handle_t, bus_size_t,
67	    uint32_t);
68
69void	g2bus_bus_mem_read_region_1(void *, bus_space_handle_t, bus_size_t,
70	    uint8_t *, bus_size_t);
71void	g2bus_bus_mem_read_region_2(void *, bus_space_handle_t, bus_size_t,
72	    uint16_t *, bus_size_t);
73void	g2bus_bus_mem_read_region_4(void *, bus_space_handle_t, bus_size_t,
74	    uint32_t *, bus_size_t);
75
76void	g2bus_bus_mem_write_region_1(void *, bus_space_handle_t, bus_size_t,
77	    const uint8_t *, bus_size_t);
78void	g2bus_bus_mem_write_region_2(void *, bus_space_handle_t, bus_size_t,
79	    const uint16_t *, bus_size_t);
80void	g2bus_bus_mem_write_region_4(void *, bus_space_handle_t, bus_size_t,
81	    const uint32_t *, bus_size_t);
82
83void	g2bus_bus_mem_set_region_4(void *, bus_space_handle_t, bus_size_t,
84	    uint32_t, bus_size_t);
85
86uint8_t g2bus_sparse_bus_mem_read_1(void *, bus_space_handle_t, bus_size_t);
87uint16_t g2bus_sparse_bus_mem_read_2(void *, bus_space_handle_t, bus_size_t);
88uint32_t g2bus_sparse_bus_mem_read_4(void *, bus_space_handle_t, bus_size_t);
89
90void	g2bus_sparse_bus_mem_write_1(void *, bus_space_handle_t, bus_size_t,
91	    uint8_t);
92void	g2bus_sparse_bus_mem_write_2(void *, bus_space_handle_t, bus_size_t,
93	    uint16_t);
94void	g2bus_sparse_bus_mem_write_4(void *, bus_space_handle_t, bus_size_t,
95	    uint32_t);
96
97void	g2bus_sparse_bus_mem_read_region_1(void *, bus_space_handle_t,
98	    bus_size_t, uint8_t *, bus_size_t);
99
100void	g2bus_sparse_bus_mem_write_region_1(void *, bus_space_handle_t,
101	    bus_size_t, const uint8_t *, bus_size_t);
102
103void	g2bus_sparse_bus_mem_read_multi_1(void *, bus_space_handle_t,
104	    bus_size_t, uint8_t *, bus_size_t);
105
106void	g2bus_sparse_bus_mem_write_multi_1(void *, bus_space_handle_t,
107	    bus_size_t, const uint8_t *, bus_size_t);
108
109void
110g2bus_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
139int
140g2bus_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
150void
151g2bus_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
158paddr_t
159g2bus_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
188uint8_t
189g2bus_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
203uint16_t
204g2bus_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
218uint32_t
219g2bus_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
233void
234g2bus_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
246void
247g2bus_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
259void
260g2bus_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
272void
273g2bus_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
287void
288g2bus_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
302void
303g2bus_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
317void
318g2bus_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
332void
333g2bus_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
347void
348g2bus_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
362void
363g2bus_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
377void
378g2bus_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
398uint8_t
399g2bus_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
413uint16_t
414g2bus_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
428uint32_t
429g2bus_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
443void
444g2bus_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
456void
457g2bus_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
469void
470g2bus_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
482void
483g2bus_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
499void
500g2bus_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
516void
517g2bus_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
531void
532g2bus_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