xref: /netbsd/sys/arch/arc/arc/bus_space.c (revision bf9ec67e)
1 /*	$NetBSD: bus_space.c,v 1.4 2001/09/04 06:57:26 thorpej Exp $	*/
2 /*	NetBSD: bus_machdep.c,v 1.1 2000/01/26 18:48:00 drochner Exp 	*/
3 
4 /*-
5  * Copyright (c) 1996, 1997, 1998 The NetBSD Foundation, Inc.
6  * All rights reserved.
7  *
8  * This code is derived from software contributed to The NetBSD Foundation
9  * by Charles M. Hannum and by Jason R. Thorpe of the Numerical Aerospace
10  * Simulation Facility, NASA Ames Research Center.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions and the following disclaimer.
17  * 2. Redistributions in binary form must reproduce the above copyright
18  *    notice, this list of conditions and the following disclaimer in the
19  *    documentation and/or other materials provided with the distribution.
20  * 3. All advertising materials mentioning features or use of this software
21  *    must display the following acknowledgement:
22  *	This product includes software developed by the NetBSD
23  *	Foundation, Inc. and its contributors.
24  * 4. Neither the name of The NetBSD Foundation nor the names of its
25  *    contributors may be used to endorse or promote products derived
26  *    from this software without specific prior written permission.
27  *
28  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
29  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
30  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
31  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
32  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
33  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
34  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
35  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
36  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
37  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38  * POSSIBILITY OF SUCH DAMAGE.
39  */
40 
41 #include <sys/param.h>
42 #include <sys/systm.h>
43 #include <sys/malloc.h>
44 #include <sys/extent.h>
45 
46 #include <uvm/uvm_extern.h>
47 
48 #include <machine/bus.h>
49 
50 void
51 arc_bus_space_init(bst, name, paddr, vaddr, start, size)
52 	bus_space_tag_t bst;
53 	const char *name;
54 	paddr_t paddr;
55 	vaddr_t vaddr;
56 	bus_addr_t start;
57 	bus_size_t size;
58 {
59 	bst->bs_name = name;
60 	bst->bs_extent = NULL;
61 	bst->bs_start = start;
62 	bst->bs_size = size;
63 	bst->bs_pbase = paddr;
64 	bst->bs_vbase = vaddr;
65 	bst->bs_compose_handle = arc_bus_space_compose_handle;
66 	bst->bs_dispose_handle = arc_bus_space_dispose_handle;
67 	bst->bs_paddr = arc_bus_space_paddr;
68 	bst->bs_map = arc_bus_space_map;
69 	bst->bs_unmap = arc_bus_space_unmap;
70 	bst->bs_subregion = arc_bus_space_subregion;
71 	bst->bs_mmap = arc_bus_space_mmap;
72 	bst->bs_alloc = arc_bus_space_alloc;
73 	bst->bs_free = arc_bus_space_free;
74 	bst->bs_aux = NULL;
75 	bst->bs_stride_1 = 0;
76 	bst->bs_stride_2 = 0;
77 	bst->bs_stride_4 = 0;
78 	bst->bs_stride_8 = 0;
79 }
80 
81 void
82 arc_bus_space_init_extent(bst, storage, storagesize)
83 	bus_space_tag_t bst;
84 	caddr_t storage;
85 	size_t storagesize;
86 {
87 	bst->bs_extent = extent_create(bst->bs_name,
88 	    bst->bs_start, bst->bs_start + bst->bs_size, M_DEVBUF,
89 	    storage, storagesize, EX_NOWAIT);
90 	if (bst->bs_extent == NULL)
91 		panic("arc_bus_space_init_extent: cannot create extent map %s",
92 		    bst->bs_name);
93 }
94 
95 void
96 arc_bus_space_set_aligned_stride(bst, alignment_shift)
97 	bus_space_tag_t bst;
98 	unsigned int alignment_shift;		/* log2(alignment) */
99 {
100 	bst->bs_stride_1 = alignment_shift;
101 	if (alignment_shift > 0)
102 		--alignment_shift;
103 	bst->bs_stride_2 = alignment_shift;
104 	if (alignment_shift > 0)
105 		--alignment_shift;
106 	bst->bs_stride_4 = alignment_shift;
107 	if (alignment_shift > 0)
108 		--alignment_shift;
109 	bst->bs_stride_8 = alignment_shift;
110 }
111 
112 static int malloc_safe = 0;
113 
114 void
115 arc_bus_space_malloc_set_safe()
116 {
117 	malloc_safe = EX_MALLOCOK;
118 }
119 
120 int
121 arc_bus_space_extent_malloc_flag()
122 {
123 	return (malloc_safe);
124 }
125 
126 int
127 arc_bus_space_compose_handle(bst, addr, size, flags, bshp)
128 	bus_space_tag_t bst;
129 	bus_addr_t addr;
130 	bus_size_t size;
131 	int flags;
132 	bus_space_handle_t *bshp;
133 {
134 	bus_space_handle_t bsh = bst->bs_vbase + (addr - bst->bs_start);
135 
136 	/*
137 	 * Since all buses can be linearly mappable, we don't have to check
138 	 * BUS_SPACE_MAP_LINEAR and BUS_SPACE_MAP_PREFETCHABLE.
139 	 */
140 	if ((flags & BUS_SPACE_MAP_CACHEABLE) == 0) {
141 		*bshp = bsh;
142 		return (0);
143 	}
144 	if (bsh < MIPS_KSEG1_START) /* KUSEG or KSEG0 */
145 		panic("arc_bus_space_compose_handle: bad address 0x%x", bsh);
146 	if (bsh < MIPS_KSEG2_START) { /* KSEG1 */
147 		*bshp = MIPS_PHYS_TO_KSEG0(MIPS_KSEG1_TO_PHYS(bsh));
148 		return (0);
149 	}
150 	/*
151 	 * KSEG2:
152 	 * Do not make the page cacheable in this case, since:
153 	 * - the page which this bus_space belongs might include
154 	 *   other bus_spaces.
155 	 * or
156 	 * - this bus might be mapped by wired TLB, in that case,
157 	 *   we cannot manupulate cacheable attribute with page granularity.
158 	 */
159 #ifdef DIAGNOSTIC
160 	printf("arc_bus_space_compose_handle: ignore cacheable 0x%x\n", bsh);
161 #endif
162 	*bshp = bsh;
163 	return (0);
164 }
165 
166 int
167 arc_bus_space_dispose_handle(bst, bsh, size)
168 	bus_space_tag_t bst;
169 	bus_space_handle_t bsh;
170 	bus_size_t size;
171 {
172 	return (0);
173 }
174 
175 int
176 arc_bus_space_paddr(bst, bsh, pap)
177 	bus_space_tag_t bst;
178 	bus_space_handle_t bsh;
179 	paddr_t *pap;
180 {
181 	if (bsh < MIPS_KSEG0_START) /* KUSEG */
182 		panic("arc_bus_space_paddr(0x%qx): bad address",
183 		    (unsigned long long) bsh);
184 	else if (bsh < MIPS_KSEG1_START) /* KSEG0 */
185 		*pap = MIPS_KSEG0_TO_PHYS(bsh);
186 	else if (bsh < MIPS_KSEG2_START) /* KSEG1 */
187 		*pap = MIPS_KSEG1_TO_PHYS(bsh);
188 	else { /* KSEG2 */
189 		/*
190 		 * Since this region may be mapped by wired TLB,
191 		 * kvtophys() is not always available.
192 		 */
193 		*pap = bst->bs_pbase + (bsh - bst->bs_vbase);
194 	}
195 	return (0);
196 }
197 
198 int
199 arc_bus_space_map(bst, addr, size, flags, bshp)
200 	bus_space_tag_t bst;
201 	bus_addr_t addr;
202 	bus_size_t size;
203 	int flags;
204 	bus_space_handle_t *bshp;
205 {
206 	int err;
207 
208 	if (addr < bst->bs_start || addr + size > bst->bs_start + bst->bs_size)
209 		return (EINVAL);
210 
211 	if (bst->bs_extent != NULL) {
212 		err = extent_alloc_region(bst->bs_extent, addr, size,
213 		    EX_NOWAIT | malloc_safe);
214 		if (err)
215 			return (err);
216 	}
217 
218 	return (bus_space_compose_handle(bst, addr, size, flags, bshp));
219 }
220 
221 void
222 arc_bus_space_unmap(bst, bsh, size)
223 	bus_space_tag_t bst;
224 	bus_space_handle_t bsh;
225 	bus_size_t size;
226 {
227 	if (bst->bs_extent != NULL) {
228 		paddr_t pa;
229 		bus_addr_t addr;
230 		int err;
231 
232 		/* bus_space_paddr() becomes unavailable after unmapping */
233 		err = bus_space_paddr(bst, bsh, &pa);
234 		if (err)
235 			panic("arc_bus_space_unmap: %s va 0x%qx: error %d\n",
236 			    bst->bs_name, (unsigned long long) bsh, err);
237 		addr = (bus_size_t)(pa - bst->bs_pbase) + bst->bs_start;
238 		extent_free(bst->bs_extent, addr, size,
239 		    EX_NOWAIT | malloc_safe);
240 	}
241 	bus_space_dispose_handle(bst, bsh, size);
242 }
243 
244 int
245 arc_bus_space_subregion(bst, bsh, offset, size, nbshp)
246 	bus_space_tag_t bst;
247 	bus_space_handle_t bsh;
248 	bus_size_t offset;
249 	bus_size_t size;
250 	bus_space_handle_t *nbshp;
251 {
252 	*nbshp = bsh + offset;
253 	return (0);
254 }
255 
256 paddr_t
257 arc_bus_space_mmap(bst, addr, off, prot, flags)
258 	bus_space_tag_t bst;
259 	bus_addr_t addr;
260 	off_t off;
261 	int prot;
262 	int flags;
263 {
264 
265 	/*
266 	 * XXX We do not disallow mmap'ing of EISA/PCI I/O space here,
267 	 * XXX which we should be doing.
268 	 */
269 
270 	if (addr < bst->bs_start ||
271 	    (addr + off) >= (bst->bs_start + bst->bs_size))
272 		return (-1);
273 
274 	return (mips_btop(bst->bs_pbase + (addr - bst->bs_start) + off));
275 }
276 
277 int
278 arc_bus_space_alloc(bst, start, end, size, align, boundary, flags, addrp, bshp)
279 	bus_space_tag_t bst;
280 	bus_addr_t start;
281 	bus_addr_t end;
282 	bus_size_t size;
283 	bus_size_t align;
284 	bus_size_t boundary;
285 	int flags;
286 	bus_addr_t *addrp;
287 	bus_space_handle_t *bshp;
288 {
289 	u_long addr;
290 	int err;
291 
292 	if (bst->bs_extent == NULL)
293 		panic("arc_bus_space_alloc: extent map %s not available",
294 		    bst->bs_name);
295 
296 	if (start < bst->bs_start ||
297 	    start + size > bst->bs_start + bst->bs_size)
298 		return (EINVAL);
299 
300 	err = extent_alloc_subregion(bst->bs_extent, start, end, size,
301 	    align, boundary, EX_FAST | EX_NOWAIT | malloc_safe, &addr);
302 	if (err)
303 		return (err);
304 
305 	*addrp = addr;
306 	return (bus_space_compose_handle(bst, addr, size, flags, bshp));
307 }
308