pxa_space.c revision 179595
1179595Sbenno/*	$NetBSD: obio_space.c,v 1.6 2003/07/15 00:25:05 lukem Exp $	*/
2179595Sbenno
3179595Sbenno/*-
4179595Sbenno * Copyright (c) 2001, 2002, 2003 Wasabi Systems, Inc.
5179595Sbenno * All rights reserved.
6179595Sbenno *
7179595Sbenno * Written by Jason R. Thorpe for Wasabi Systems, Inc.
8179595Sbenno *
9179595Sbenno * Redistribution and use in source and binary forms, with or without
10179595Sbenno * modification, are permitted provided that the following conditions
11179595Sbenno * are met:
12179595Sbenno * 1. Redistributions of source code must retain the above copyright
13179595Sbenno *    notice, this list of conditions and the following disclaimer.
14179595Sbenno * 2. Redistributions in binary form must reproduce the above copyright
15179595Sbenno *    notice, this list of conditions and the following disclaimer in the
16179595Sbenno *    documentation and/or other materials provided with the distribution.
17179595Sbenno * 3. All advertising materials mentioning features or use of this software
18179595Sbenno *    must display the following acknowledgement:
19179595Sbenno *	This product includes software developed for the NetBSD Project by
20179595Sbenno *	Wasabi Systems, Inc.
21179595Sbenno * 4. The name of Wasabi Systems, Inc. may not be used to endorse
22179595Sbenno *    or promote products derived from this software without specific prior
23179595Sbenno *    written permission.
24179595Sbenno *
25179595Sbenno * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
26179595Sbenno * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
27179595Sbenno * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28179595Sbenno * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
29179595Sbenno * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30179595Sbenno * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31179595Sbenno * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32179595Sbenno * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33179595Sbenno * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34179595Sbenno * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35179595Sbenno * POSSIBILITY OF SUCH DAMAGE.
36179595Sbenno */
37179595Sbenno
38179595Sbenno/*
39179595Sbenno * bus_space functions for PXA devices
40179595Sbenno */
41179595Sbenno
42179595Sbenno#include <sys/cdefs.h>
43179595Sbenno__FBSDID("$FreeBSD: head/sys/arm/xscale/pxa/pxa_space.c 179595 2008-06-06 05:08:09Z benno $");
44179595Sbenno
45179595Sbenno#include <sys/param.h>
46179595Sbenno#include <sys/systm.h>
47179595Sbenno#include <sys/bus.h>
48179595Sbenno#include <sys/kernel.h>
49179595Sbenno#include <sys/malloc.h>
50179595Sbenno
51179595Sbenno#include <machine/pcb.h>
52179595Sbenno
53179595Sbenno#include <vm/vm.h>
54179595Sbenno#include <vm/pmap.h>
55179595Sbenno#include <vm/vm_kern.h>
56179595Sbenno#include <vm/vm_extern.h>
57179595Sbenno
58179595Sbenno#include <machine/bus.h>
59179595Sbenno
60179595Sbenno#include <arm/xscale/pxa/pxareg.h>
61179595Sbenno#include <arm/xscale/pxa/pxavar.h>
62179595Sbenno
63179595SbennoMALLOC_DEFINE(M_PXATAG, "PXA bus_space tags", "Bus_space tags for PXA");
64179595Sbenno
65179595Sbenno/* Prototypes for all the bus_space structure functions */
66179595Sbennobs_protos(obio);
67179595Sbennobs_protos(generic);
68179595Sbennobs_protos(generic_armv4);
69179595Sbennobs_protos(pxa);
70179595Sbenno
71179595Sbenno/*
72179595Sbenno * The obio bus space tag.  This is constant for all instances, so
73179595Sbenno * we never have to explicitly "create" it.
74179595Sbenno */
75179595Sbennostruct bus_space _base_tag = {
76179595Sbenno	/* cookie */
77179595Sbenno	(void *) 0,
78179595Sbenno
79179595Sbenno	/* mapping/unmapping */
80179595Sbenno	obio_bs_map,
81179595Sbenno	obio_bs_unmap,
82179595Sbenno	obio_bs_subregion,
83179595Sbenno
84179595Sbenno	/* allocation/deallocation */
85179595Sbenno	obio_bs_alloc,
86179595Sbenno	obio_bs_free,
87179595Sbenno
88179595Sbenno	/* barrier */
89179595Sbenno	obio_bs_barrier,
90179595Sbenno
91179595Sbenno	/* read (single) */
92179595Sbenno	pxa_bs_r_1,
93179595Sbenno	pxa_bs_r_2,
94179595Sbenno	pxa_bs_r_4,
95179595Sbenno	NULL,
96179595Sbenno
97179595Sbenno	/* read multiple */
98179595Sbenno	pxa_bs_rm_1,
99179595Sbenno	pxa_bs_rm_2,
100179595Sbenno	NULL,
101179595Sbenno	NULL,
102179595Sbenno
103179595Sbenno	/* read region */
104179595Sbenno	pxa_bs_rr_1,
105179595Sbenno	NULL,
106179595Sbenno	NULL,
107179595Sbenno	NULL,
108179595Sbenno
109179595Sbenno	/* write (single) */
110179595Sbenno	pxa_bs_w_1,
111179595Sbenno	pxa_bs_w_2,
112179595Sbenno	pxa_bs_w_4,
113179595Sbenno	NULL,
114179595Sbenno
115179595Sbenno	/* write multiple */
116179595Sbenno	pxa_bs_wm_1,
117179595Sbenno	pxa_bs_wm_2,
118179595Sbenno	NULL,
119179595Sbenno	NULL,
120179595Sbenno
121179595Sbenno	/* write region */
122179595Sbenno	NULL,
123179595Sbenno	NULL,
124179595Sbenno	NULL,
125179595Sbenno	NULL,
126179595Sbenno
127179595Sbenno	/* set multiple */
128179595Sbenno	NULL,
129179595Sbenno	NULL,
130179595Sbenno	NULL,
131179595Sbenno	NULL,
132179595Sbenno
133179595Sbenno	/* set region */
134179595Sbenno	NULL,
135179595Sbenno	NULL,
136179595Sbenno	NULL,
137179595Sbenno	NULL,
138179595Sbenno
139179595Sbenno	/* copy */
140179595Sbenno	NULL,
141179595Sbenno	NULL,
142179595Sbenno	NULL,
143179595Sbenno	NULL,
144179595Sbenno};
145179595Sbenno
146179595Sbennostatic struct bus_space	_obio_tag;
147179595Sbenno
148179595Sbennobus_space_tag_t		base_tag = &_base_tag;
149179595Sbennobus_space_tag_t		obio_tag = NULL;
150179595Sbenno
151179595Sbennovoid
152179595Sbennopxa_obio_tag_init()
153179595Sbenno{
154179595Sbenno
155179595Sbenno	bcopy(&_base_tag, &_obio_tag, sizeof(struct bus_space));
156179595Sbenno	_obio_tag.bs_cookie = (void *)PXA2X0_PERIPH_OFFSET;
157179595Sbenno	obio_tag = &_obio_tag;
158179595Sbenno}
159179595Sbenno
160179595Sbennobus_space_tag_t
161179595Sbennopxa_bus_tag_alloc(bus_addr_t offset)
162179595Sbenno{
163179595Sbenno	struct	bus_space *tag;
164179595Sbenno
165179595Sbenno	tag = (struct bus_space *)malloc(sizeof(struct bus_space), M_PXATAG,
166179595Sbenno	    M_WAITOK);
167179595Sbenno	if (tag == NULL) {
168179595Sbenno		return (NULL);
169179595Sbenno	}
170179595Sbenno
171179595Sbenno	bcopy(&_base_tag, tag, sizeof(struct bus_space));
172179595Sbenno	tag->bs_cookie = (void *)offset;
173179595Sbenno
174179595Sbenno	return ((bus_space_tag_t)tag);
175179595Sbenno}
176179595Sbenno
177179595Sbennoint
178179595Sbennoobio_bs_map(void *t, bus_addr_t bpa, bus_size_t size, int flags,
179179595Sbenno    bus_space_handle_t *bshp)
180179595Sbenno{
181179595Sbenno	const struct pmap_devmap *pd;
182179595Sbenno	vm_paddr_t startpa, endpa, pa, offset;
183179595Sbenno	vm_offset_t va;
184179595Sbenno	pt_entry_t *pte;
185179595Sbenno
186179595Sbenno	if ((pd = pmap_devmap_find_pa(bpa, size)) != NULL) {
187179595Sbenno		/* Device was statically mapped. */
188179595Sbenno		*bshp = pd->pd_va + (bpa - pd->pd_pa);
189179595Sbenno		return (0);
190179595Sbenno	}
191179595Sbenno
192179595Sbenno	endpa = round_page(bpa + size);
193179595Sbenno	offset = bpa & PAGE_MASK;
194179595Sbenno	startpa = trunc_page(bpa);
195179595Sbenno
196179595Sbenno	va = kmem_alloc(kernel_map, endpa - startpa);
197179595Sbenno	if (va == 0)
198179595Sbenno		return (ENOMEM);
199179595Sbenno
200179595Sbenno	*bshp = va + offset;
201179595Sbenno
202179595Sbenno	for (pa = startpa; pa < endpa; pa += PAGE_SIZE, va += PAGE_SIZE) {
203179595Sbenno		pmap_kenter(va, pa);
204179595Sbenno		pte = vtopte(va);
205179595Sbenno		*pte &= ~L2_S_CACHE_MASK;
206179595Sbenno		PTE_SYNC(pte);
207179595Sbenno	}
208179595Sbenno
209179595Sbenno	return (0);
210179595Sbenno}
211179595Sbenno
212179595Sbennoint
213179595Sbennoobio_bs_alloc(void *t, bus_addr_t rstart, bus_addr_t rend, bus_size_t size,
214179595Sbenno    bus_size_t alignment, bus_size_t boundary, int flags, bus_addr_t *bpap,
215179595Sbenno    bus_space_handle_t *bshp)
216179595Sbenno{
217179595Sbenno
218179595Sbenno	panic("obio_bs_alloc(): not implemented");
219179595Sbenno}
220179595Sbenno
221179595Sbenno
222179595Sbennovoid
223179595Sbennoobio_bs_unmap(void *t, bus_space_handle_t h, bus_size_t size)
224179595Sbenno{
225179595Sbenno	vm_offset_t va, endva;
226179595Sbenno
227179595Sbenno	if (pmap_devmap_find_va((vm_offset_t)t, size) != NULL) {
228179595Sbenno		/* Device was statically mapped; nothing to do. */
229179595Sbenno		return;
230179595Sbenno	}
231179595Sbenno
232179595Sbenno	endva = round_page((vm_offset_t)t + size);
233179595Sbenno	va = trunc_page((vm_offset_t)t);
234179595Sbenno
235179595Sbenno	while (va < endva) {
236179595Sbenno		pmap_kremove(va);
237179595Sbenno		va += PAGE_SIZE;
238179595Sbenno	}
239179595Sbenno	kmem_free(kernel_map, va, endva - va);
240179595Sbenno}
241179595Sbenno
242179595Sbennovoid
243179595Sbennoobio_bs_free(void *t, bus_space_handle_t bsh, bus_size_t size)
244179595Sbenno{
245179595Sbenno
246179595Sbenno	panic("obio_bs_free(): not implemented");
247179595Sbenno}
248179595Sbenno
249179595Sbennoint
250179595Sbennoobio_bs_subregion(void *t, bus_space_handle_t bsh, bus_size_t offset,
251179595Sbenno    bus_size_t size, bus_space_handle_t *nbshp)
252179595Sbenno{
253179595Sbenno
254179595Sbenno	*nbshp = bsh + offset;
255179595Sbenno	return (0);
256179595Sbenno}
257179595Sbenno
258179595Sbennovoid
259179595Sbennoobio_bs_barrier(void *t, bus_space_handle_t bsh, bus_size_t offset,
260179595Sbenno    bus_size_t len, int flags)
261179595Sbenno{
262179595Sbenno
263179595Sbenno	/* Nothing to do. */
264179595Sbenno}
265179595Sbenno
266179595Sbenno#define	READ_SINGLE(type, proto, base)					\
267179595Sbenno	type								\
268179595Sbenno	proto(void *cookie, bus_space_handle_t bsh, bus_size_t offset)	\
269179595Sbenno	{								\
270179595Sbenno		bus_addr_t	tag_offset;				\
271179595Sbenno		type		value;					\
272179595Sbenno		tag_offset = (bus_addr_t)cookie;			\
273179595Sbenno		value = base(NULL, bsh + tag_offset, offset);		\
274179595Sbenno		return (value);						\
275179595Sbenno	}
276179595Sbenno
277179595SbennoREAD_SINGLE(u_int8_t,  pxa_bs_r_1, generic_bs_r_1)
278179595SbennoREAD_SINGLE(u_int16_t, pxa_bs_r_2, generic_armv4_bs_r_2)
279179595SbennoREAD_SINGLE(u_int32_t, pxa_bs_r_4, generic_bs_r_4)
280179595Sbenno
281179595Sbenno#undef READ_SINGLE
282179595Sbenno
283179595Sbenno#define	WRITE_SINGLE(type, proto, base)					\
284179595Sbenno	void								\
285179595Sbenno	proto(void *cookie, bus_space_handle_t bsh, bus_size_t offset,	\
286179595Sbenno	    type value)							\
287179595Sbenno	{								\
288179595Sbenno		bus_addr_t	tag_offset;				\
289179595Sbenno		tag_offset = (bus_addr_t)cookie;			\
290179595Sbenno		base(NULL, bsh + tag_offset, offset, value);		\
291179595Sbenno	}
292179595Sbenno
293179595SbennoWRITE_SINGLE(u_int8_t,  pxa_bs_w_1, generic_bs_w_1)
294179595SbennoWRITE_SINGLE(u_int16_t, pxa_bs_w_2, generic_armv4_bs_w_2)
295179595SbennoWRITE_SINGLE(u_int32_t, pxa_bs_w_4, generic_bs_w_4)
296179595Sbenno
297179595Sbenno#undef WRITE_SINGLE
298179595Sbenno
299179595Sbenno#define	READ_MULTI(type, proto, base)					\
300179595Sbenno	void								\
301179595Sbenno	proto(void *cookie, bus_space_handle_t bsh, bus_size_t offset,	\
302179595Sbenno	    type *dest, bus_size_t count)				\
303179595Sbenno	{								\
304179595Sbenno		bus_addr_t	tag_offset;				\
305179595Sbenno		tag_offset = (bus_addr_t)cookie;			\
306179595Sbenno		base(NULL, bsh + tag_offset, offset, dest, count);	\
307179595Sbenno	}
308179595Sbenno
309179595SbennoREAD_MULTI(u_int8_t,  pxa_bs_rm_1, generic_bs_rm_1)
310179595SbennoREAD_MULTI(u_int16_t, pxa_bs_rm_2, generic_armv4_bs_rm_2)
311179595Sbenno
312179595SbennoREAD_MULTI(u_int8_t,  pxa_bs_rr_1, generic_bs_rr_1)
313179595Sbenno
314179595Sbenno#undef READ_MULTI
315179595Sbenno
316179595Sbenno#define	WRITE_MULTI(type, proto, base)					\
317179595Sbenno	void								\
318179595Sbenno	proto(void *cookie, bus_space_handle_t bsh, bus_size_t offset,	\
319179595Sbenno	    const type *src, bus_size_t count)				\
320179595Sbenno	{								\
321179595Sbenno		bus_addr_t	tag_offset;				\
322179595Sbenno		tag_offset = (bus_addr_t)cookie;			\
323179595Sbenno		base(NULL, bsh + tag_offset, offset, src, count);	\
324179595Sbenno	}
325179595Sbenno
326179595SbennoWRITE_MULTI(u_int8_t,  pxa_bs_wm_1, generic_bs_wm_1)
327179595SbennoWRITE_MULTI(u_int16_t, pxa_bs_wm_2, generic_armv4_bs_wm_2)
328179595Sbenno
329179595Sbenno#undef WRITE_MULTI
330