pxa_space.c revision 179595
1/*	$NetBSD: obio_space.c,v 1.6 2003/07/15 00:25:05 lukem Exp $	*/
2
3/*-
4 * Copyright (c) 2001, 2002, 2003 Wasabi Systems, Inc.
5 * All rights reserved.
6 *
7 * Written by Jason R. Thorpe for Wasabi Systems, Inc.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 *    notice, this list of conditions and the following disclaimer in the
16 *    documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 *    must display the following acknowledgement:
19 *	This product includes software developed for the NetBSD Project by
20 *	Wasabi Systems, Inc.
21 * 4. The name of Wasabi Systems, Inc. may not be used to endorse
22 *    or promote products derived from this software without specific prior
23 *    written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 * POSSIBILITY OF SUCH DAMAGE.
36 */
37
38/*
39 * bus_space functions for PXA devices
40 */
41
42#include <sys/cdefs.h>
43__FBSDID("$FreeBSD: head/sys/arm/xscale/pxa/pxa_space.c 179595 2008-06-06 05:08:09Z benno $");
44
45#include <sys/param.h>
46#include <sys/systm.h>
47#include <sys/bus.h>
48#include <sys/kernel.h>
49#include <sys/malloc.h>
50
51#include <machine/pcb.h>
52
53#include <vm/vm.h>
54#include <vm/pmap.h>
55#include <vm/vm_kern.h>
56#include <vm/vm_extern.h>
57
58#include <machine/bus.h>
59
60#include <arm/xscale/pxa/pxareg.h>
61#include <arm/xscale/pxa/pxavar.h>
62
63MALLOC_DEFINE(M_PXATAG, "PXA bus_space tags", "Bus_space tags for PXA");
64
65/* Prototypes for all the bus_space structure functions */
66bs_protos(obio);
67bs_protos(generic);
68bs_protos(generic_armv4);
69bs_protos(pxa);
70
71/*
72 * The obio bus space tag.  This is constant for all instances, so
73 * we never have to explicitly "create" it.
74 */
75struct bus_space _base_tag = {
76	/* cookie */
77	(void *) 0,
78
79	/* mapping/unmapping */
80	obio_bs_map,
81	obio_bs_unmap,
82	obio_bs_subregion,
83
84	/* allocation/deallocation */
85	obio_bs_alloc,
86	obio_bs_free,
87
88	/* barrier */
89	obio_bs_barrier,
90
91	/* read (single) */
92	pxa_bs_r_1,
93	pxa_bs_r_2,
94	pxa_bs_r_4,
95	NULL,
96
97	/* read multiple */
98	pxa_bs_rm_1,
99	pxa_bs_rm_2,
100	NULL,
101	NULL,
102
103	/* read region */
104	pxa_bs_rr_1,
105	NULL,
106	NULL,
107	NULL,
108
109	/* write (single) */
110	pxa_bs_w_1,
111	pxa_bs_w_2,
112	pxa_bs_w_4,
113	NULL,
114
115	/* write multiple */
116	pxa_bs_wm_1,
117	pxa_bs_wm_2,
118	NULL,
119	NULL,
120
121	/* write region */
122	NULL,
123	NULL,
124	NULL,
125	NULL,
126
127	/* set multiple */
128	NULL,
129	NULL,
130	NULL,
131	NULL,
132
133	/* set region */
134	NULL,
135	NULL,
136	NULL,
137	NULL,
138
139	/* copy */
140	NULL,
141	NULL,
142	NULL,
143	NULL,
144};
145
146static struct bus_space	_obio_tag;
147
148bus_space_tag_t		base_tag = &_base_tag;
149bus_space_tag_t		obio_tag = NULL;
150
151void
152pxa_obio_tag_init()
153{
154
155	bcopy(&_base_tag, &_obio_tag, sizeof(struct bus_space));
156	_obio_tag.bs_cookie = (void *)PXA2X0_PERIPH_OFFSET;
157	obio_tag = &_obio_tag;
158}
159
160bus_space_tag_t
161pxa_bus_tag_alloc(bus_addr_t offset)
162{
163	struct	bus_space *tag;
164
165	tag = (struct bus_space *)malloc(sizeof(struct bus_space), M_PXATAG,
166	    M_WAITOK);
167	if (tag == NULL) {
168		return (NULL);
169	}
170
171	bcopy(&_base_tag, tag, sizeof(struct bus_space));
172	tag->bs_cookie = (void *)offset;
173
174	return ((bus_space_tag_t)tag);
175}
176
177int
178obio_bs_map(void *t, bus_addr_t bpa, bus_size_t size, int flags,
179    bus_space_handle_t *bshp)
180{
181	const struct pmap_devmap *pd;
182	vm_paddr_t startpa, endpa, pa, offset;
183	vm_offset_t va;
184	pt_entry_t *pte;
185
186	if ((pd = pmap_devmap_find_pa(bpa, size)) != NULL) {
187		/* Device was statically mapped. */
188		*bshp = pd->pd_va + (bpa - pd->pd_pa);
189		return (0);
190	}
191
192	endpa = round_page(bpa + size);
193	offset = bpa & PAGE_MASK;
194	startpa = trunc_page(bpa);
195
196	va = kmem_alloc(kernel_map, endpa - startpa);
197	if (va == 0)
198		return (ENOMEM);
199
200	*bshp = va + offset;
201
202	for (pa = startpa; pa < endpa; pa += PAGE_SIZE, va += PAGE_SIZE) {
203		pmap_kenter(va, pa);
204		pte = vtopte(va);
205		*pte &= ~L2_S_CACHE_MASK;
206		PTE_SYNC(pte);
207	}
208
209	return (0);
210}
211
212int
213obio_bs_alloc(void *t, bus_addr_t rstart, bus_addr_t rend, bus_size_t size,
214    bus_size_t alignment, bus_size_t boundary, int flags, bus_addr_t *bpap,
215    bus_space_handle_t *bshp)
216{
217
218	panic("obio_bs_alloc(): not implemented");
219}
220
221
222void
223obio_bs_unmap(void *t, bus_space_handle_t h, bus_size_t size)
224{
225	vm_offset_t va, endva;
226
227	if (pmap_devmap_find_va((vm_offset_t)t, size) != NULL) {
228		/* Device was statically mapped; nothing to do. */
229		return;
230	}
231
232	endva = round_page((vm_offset_t)t + size);
233	va = trunc_page((vm_offset_t)t);
234
235	while (va < endva) {
236		pmap_kremove(va);
237		va += PAGE_SIZE;
238	}
239	kmem_free(kernel_map, va, endva - va);
240}
241
242void
243obio_bs_free(void *t, bus_space_handle_t bsh, bus_size_t size)
244{
245
246	panic("obio_bs_free(): not implemented");
247}
248
249int
250obio_bs_subregion(void *t, bus_space_handle_t bsh, bus_size_t offset,
251    bus_size_t size, bus_space_handle_t *nbshp)
252{
253
254	*nbshp = bsh + offset;
255	return (0);
256}
257
258void
259obio_bs_barrier(void *t, bus_space_handle_t bsh, bus_size_t offset,
260    bus_size_t len, int flags)
261{
262
263	/* Nothing to do. */
264}
265
266#define	READ_SINGLE(type, proto, base)					\
267	type								\
268	proto(void *cookie, bus_space_handle_t bsh, bus_size_t offset)	\
269	{								\
270		bus_addr_t	tag_offset;				\
271		type		value;					\
272		tag_offset = (bus_addr_t)cookie;			\
273		value = base(NULL, bsh + tag_offset, offset);		\
274		return (value);						\
275	}
276
277READ_SINGLE(u_int8_t,  pxa_bs_r_1, generic_bs_r_1)
278READ_SINGLE(u_int16_t, pxa_bs_r_2, generic_armv4_bs_r_2)
279READ_SINGLE(u_int32_t, pxa_bs_r_4, generic_bs_r_4)
280
281#undef READ_SINGLE
282
283#define	WRITE_SINGLE(type, proto, base)					\
284	void								\
285	proto(void *cookie, bus_space_handle_t bsh, bus_size_t offset,	\
286	    type value)							\
287	{								\
288		bus_addr_t	tag_offset;				\
289		tag_offset = (bus_addr_t)cookie;			\
290		base(NULL, bsh + tag_offset, offset, value);		\
291	}
292
293WRITE_SINGLE(u_int8_t,  pxa_bs_w_1, generic_bs_w_1)
294WRITE_SINGLE(u_int16_t, pxa_bs_w_2, generic_armv4_bs_w_2)
295WRITE_SINGLE(u_int32_t, pxa_bs_w_4, generic_bs_w_4)
296
297#undef WRITE_SINGLE
298
299#define	READ_MULTI(type, proto, base)					\
300	void								\
301	proto(void *cookie, bus_space_handle_t bsh, bus_size_t offset,	\
302	    type *dest, bus_size_t count)				\
303	{								\
304		bus_addr_t	tag_offset;				\
305		tag_offset = (bus_addr_t)cookie;			\
306		base(NULL, bsh + tag_offset, offset, dest, count);	\
307	}
308
309READ_MULTI(u_int8_t,  pxa_bs_rm_1, generic_bs_rm_1)
310READ_MULTI(u_int16_t, pxa_bs_rm_2, generic_armv4_bs_rm_2)
311
312READ_MULTI(u_int8_t,  pxa_bs_rr_1, generic_bs_rr_1)
313
314#undef READ_MULTI
315
316#define	WRITE_MULTI(type, proto, base)					\
317	void								\
318	proto(void *cookie, bus_space_handle_t bsh, bus_size_t offset,	\
319	    const type *src, bus_size_t count)				\
320	{								\
321		bus_addr_t	tag_offset;				\
322		tag_offset = (bus_addr_t)cookie;			\
323		base(NULL, bsh + tag_offset, offset, src, count);	\
324	}
325
326WRITE_MULTI(u_int8_t,  pxa_bs_wm_1, generic_bs_wm_1)
327WRITE_MULTI(u_int16_t, pxa_bs_wm_2, generic_armv4_bs_wm_2)
328
329#undef WRITE_MULTI
330