xref: /netbsd-src/sys/arch/hpcmips/hpcmips/bus_space.c (revision 5aefcfdc06931dd97e76246d2fe0302f7b3fe094)
1 /*	$NetBSD: bus_space.c,v 1.6 2000/06/29 08:17:59 mrg Exp $	*/
2 
3 /*
4  * Copyright (c) 1999, by UCHIYAMA Yasushi
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. The name of the developer may NOT be used to endorse or promote products
13  *    derived from this software without specific prior written permission.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  *
27  */
28 /*	$NetBSD: bus_space.c,v 1.6 2000/06/29 08:17:59 mrg Exp $	*/
29 
30 /*-
31  * Copyright (c) 1998 The NetBSD Foundation, Inc.
32  * All rights reserved.
33  *
34  * This code is derived from software contributed to The NetBSD Foundation
35  * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
36  * NASA Ames Research Center.
37  *
38  * Redistribution and use in source and binary forms, with or without
39  * modification, are permitted provided that the following conditions
40  * are met:
41  * 1. Redistributions of source code must retain the above copyright
42  *    notice, this list of conditions and the following disclaimer.
43  * 2. Redistributions in binary form must reproduce the above copyright
44  *    notice, this list of conditions and the following disclaimer in the
45  *    documentation and/or other materials provided with the distribution.
46  * 3. All advertising materials mentioning features or use of this software
47  *    must display the following acknowledgement:
48  *	This product includes software developed by the NetBSD
49  *	Foundation, Inc. and its contributors.
50  * 4. Neither the name of The NetBSD Foundation nor the names of its
51  *    contributors may be used to endorse or promote products derived
52  *    from this software without specific prior written permission.
53  *
54  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
55  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
56  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
57  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
58  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
59  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
60  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
61  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
62  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
63  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
64  * POSSIBILITY OF SUCH DAMAGE.
65  */
66 
67 #include <sys/param.h>
68 #include <sys/systm.h>
69 #include <sys/malloc.h>
70 #include <sys/map.h>
71 #include <sys/extent.h>
72 
73 #include <uvm/uvm_extern.h>
74 
75 #include <mips/cpuregs.h>
76 #include <mips/pte.h>
77 #include <machine/bus.h>
78 
79 #ifdef BUS_SPACE_DEBUG
80 #define	DPRINTF(arg) printf arg
81 #else
82 #define	DPRINTF(arg)
83 #endif
84 
85 #define MAX_BUSSPACE_TAG 10
86 
87 static  struct hpcmips_bus_space sys_bus_space[MAX_BUSSPACE_TAG];
88 static int bus_space_index = 0;
89 bus_space_handle_t __hpcmips_cacheable __P((bus_space_tag_t, bus_addr_t, bus_size_t, int));
90 
91 bus_space_tag_t
92 hpcmips_alloc_bus_space_tag()
93 {
94 	bus_space_tag_t	t;
95 
96 	if (bus_space_index >= MAX_BUSSPACE_TAG) {
97 		panic("hpcmips_internal_alloc_bus_space_tag: tag full.");
98 	}
99 	t = &sys_bus_space[bus_space_index++];
100 	return t;
101 }
102 
103 void
104 hpcmips_init_bus_space_extent(t)
105 	bus_space_tag_t t;
106 {
107 	u_int32_t pa, endpa;
108 	vaddr_t va;
109 
110 	/*
111 	 * If request physical address is greater than 512MByte,
112 	 * mapping it to kseg2.
113 	 */
114 	if (t->t_base >= 0x20000000) {
115 		pa = mips_trunc_page(t->t_base);
116 		endpa = mips_round_page(t->t_base + t->t_size);
117 
118 		if (!(va = uvm_km_valloc(kernel_map, endpa - pa))) {
119 			panic("hpcmips_init_bus_space_extent: can't allocate kernel virtual");
120 		}
121 		DPRINTF(("pa:0x%08x -> kv:0x%08x+0x%08x", (unsigned int)t->t_base,
122 		       (unsigned int)va, t->t_size));
123 		t->t_base = va; /* kseg2 addr */
124 
125 		for (; pa < endpa; pa += NBPG, va += NBPG) {
126 			pmap_kenter_pa(va, pa, VM_PROT_READ | VM_PROT_WRITE);
127 		}
128 	}
129 
130 	t->t_extent = (void*)extent_create(t->t_name, t->t_base,
131 					   t->t_base + t->t_size, M_DEVBUF,
132 					   0, 0, EX_NOWAIT);
133 	if (!t->t_extent) {
134 		panic("hpcmips_init_bus_space_extent: unable to allocate %s map", t->t_name);
135 	}
136 }
137 
138 bus_space_handle_t
139 __hpcmips_cacheable(t, bpa, size, cacheable)
140 	bus_space_tag_t t;
141 	bus_addr_t bpa;
142 	bus_size_t size;
143 	int cacheable;
144 {
145 	vaddr_t va, endva;
146 	pt_entry_t *pte;
147 	u_int32_t opte, npte;
148 
149 	MachFlushCache();
150 	if (t->t_base >= MIPS_KSEG2_START) {
151 		va = mips_trunc_page(bpa);
152 		endva = mips_round_page(bpa + size);
153 		npte = CPUISMIPS3 ? MIPS3_PG_UNCACHED : MIPS1_PG_N;
154 
155 		for (; va < endva; va += NBPG) {
156 			pte = kvtopte(va);
157 			opte = pte->pt_entry;
158 			if (cacheable) {
159 				opte &= ~npte;
160 			} else {
161 				opte |= npte;
162 			}
163 			pte->pt_entry = opte;
164 			/*
165 			 * Update the same virtual address entry.
166 			 */
167 			MachTLBUpdate(va, opte);
168 		}
169 		return bpa;
170 	}
171 
172 	return cacheable ? MIPS_PHYS_TO_KSEG0(bpa) : MIPS_PHYS_TO_KSEG1(bpa);
173 }
174 
175 /* ARGSUSED */
176 int
177 bus_space_map(t, bpa, size, flags, bshp)
178 	bus_space_tag_t t;
179 	bus_addr_t bpa;
180 	bus_size_t size;
181 	int flags;
182 	bus_space_handle_t *bshp;
183 {
184 	int err;
185 	int cacheable = flags & BUS_SPACE_MAP_CACHEABLE;
186 
187 	if (!t->t_extent) { /* Before autoconfiguration, can't use extent */
188 		DPRINTF(("bus_space_map: map temprary region:0x%08x-0x%08x\n", bpa, bpa+size));
189 		bpa += t->t_base;
190 	} else {
191 		bpa += t->t_base;
192 		if ((err = extent_alloc_region(t->t_extent, bpa, size,
193 					       EX_NOWAIT|EX_MALLOCOK))) {
194 			return err;
195 		}
196 	}
197 	*bshp = __hpcmips_cacheable(t, bpa, size, cacheable);
198 	DPRINTF(("\tbus_space_map:%#x(%#x)+%#x\n", bpa, bpa - t->t_base, size));
199 
200 	return 0;
201 }
202 
203 /* ARGSUSED */
204 int
205 bus_space_alloc(t, rstart, rend, size, alignment, boundary, flags,
206 		bpap, bshp)
207 	bus_space_tag_t t;
208 	bus_addr_t rstart, rend;
209 	bus_size_t size, alignment, boundary;
210 	int flags;
211 	bus_addr_t *bpap;
212 	bus_space_handle_t *bshp;
213 {
214 	int cacheable = flags & BUS_SPACE_MAP_CACHEABLE;
215 	u_long bpa;
216 	int err;
217 
218 	if (!t->t_extent)
219 		panic("bus_space_alloc: no extent");
220 
221 	rstart += t->t_base;
222 	rend += t->t_base;
223 	if ((err = extent_alloc_subregion(t->t_extent, rstart, rend, size,
224 					  alignment, boundary,
225 					  EX_FAST|EX_NOWAIT|EX_MALLOCOK, &bpa))) {
226 		return err;
227 	}
228 
229 	*bshp = __hpcmips_cacheable(t, bpa, size, cacheable);
230 
231 	if (bpap) {
232 		*bpap = bpa;
233 	}
234 
235 	DPRINTF(("\tbus_space_alloc:%#x(%#x)+%#x\n", (unsigned)bpa, (unsigned)(bpa - t->t_base), size));
236 
237 	return 0;
238 }
239 
240 /* ARGSUSED */
241 void
242 bus_space_free(t, bsh, size)
243 	bus_space_tag_t t;
244 	bus_space_handle_t bsh;
245 	bus_size_t size;
246 {
247 	/* bus_space_unmap() does all that we need to do. */
248 	bus_space_unmap(t, bsh, size);
249 }
250 
251 void
252 bus_space_unmap(t, bsh, size)
253 	bus_space_tag_t t;
254 	bus_space_handle_t bsh;
255 	bus_size_t size;
256 {
257 	int err;
258 	u_int32_t addr;
259 
260 	if (!t->t_extent) {
261 		return; /* Before autoconfiguration, can't use extent */
262 	}
263 
264 	if (t->t_base < MIPS_KSEG2_START) {
265 		addr = MIPS_KSEG1_TO_PHYS(bsh);
266 	} else {
267 		addr = bsh;
268 	}
269 
270 	if ((err = extent_free(t->t_extent, addr, size, EX_NOWAIT))) {
271 		DPRINTF(("warning: %#x-%#x of %s space lost\n",
272 		       bsh, bsh+size, t->t_name));
273 	}
274 }
275 
276 /* ARGSUSED */
277 int
278 bus_space_subregion(t, bsh, offset, size, nbshp)
279 	bus_space_tag_t t;
280 	bus_space_handle_t bsh;
281 	bus_size_t offset, size;
282 	bus_space_handle_t *nbshp;
283 {
284 	*nbshp = bsh + offset;
285 
286 	return 0;
287 }
288