1169689Skan/*	$NetBSD: ifpga_io.c,v 1.10 2011/07/01 20:39:34 dyoung Exp $ */
2169689Skan
3169689Skan/*
4169689Skan * Copyright (c) 1997 Causality Limited
5169689Skan * Copyright (c) 1997 Mark Brinicombe.
6169689Skan * All rights reserved.
7169689Skan *
8169689Skan * Redistribution and use in source and binary forms, with or without
9169689Skan * modification, are permitted provided that the following conditions
10169689Skan * are met:
11169689Skan * 1. Redistributions of source code must retain the above copyright
12169689Skan *    notice, this list of conditions and the following disclaimer.
13169689Skan * 2. Redistributions in binary form must reproduce the above copyright
14169689Skan *    notice, this list of conditions and the following disclaimer in the
15169689Skan *    documentation and/or other materials provided with the distribution.
16169689Skan * 3. All advertising materials mentioning features or use of this software
17169689Skan *    must display the following acknowledgement:
18169689Skan *	This product includes software developed by Mark Brinicombe
19169689Skan *	for the NetBSD Project.
20169689Skan * 4. The name of the company nor the name of the author may be used to
21169689Skan *    endorse or promote products derived from this software without specific
22169689Skan *    prior written permission.
23169689Skan *
24169689Skan * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
25169689Skan * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
26169689Skan * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27169689Skan * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
28169689Skan * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29169689Skan * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30169689Skan * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31169689Skan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32169689Skan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33169689Skan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34169689Skan * SUCH DAMAGE.
35169689Skan *
36169689Skan * From arm/footbridge/footbridge_io.c
37169689Skan */
38169689Skan
39169689Skan/*
40169689Skan * bus_space I/O functions for IFPGA
41169689Skan */
42169689Skan
43169689Skan#include <sys/cdefs.h>
44169689Skan__KERNEL_RCSID(0, "$NetBSD: ifpga_io.c,v 1.10 2011/07/01 20:39:34 dyoung Exp $");
45169689Skan
46169689Skan#include <sys/param.h>
47169689Skan#include <sys/systm.h>
48169689Skan#include <sys/bus.h>
49169689Skan#include <uvm/uvm_extern.h>
50169689Skan
51169689Skan#include <evbarm/ifpga/ifpgavar.h>
52169689Skan
53169689Skan/* Proto types for all the bus_space structure functions */
54169689Skan
55169689Skanbs_protos(ifpga);
56169689Skanbs_protos(generic);
57169689Skanbs_protos(generic_armv4);
58169689Skanbs_protos(bs_notimpl);
59169689Skanbs_map_proto(ifpga_mem);
60169689Skanbs_unmap_proto(ifpga_mem);
61169689Skan
62169689Skan/* Declare the ifpga bus space tag */
63169689Skan
64169689Skanstruct bus_space ifpga_bs_tag = {
65169689Skan	/* cookie */
66169689Skan	(void *) 0,			/* Physical base address */
67169689Skan
68169689Skan	/* mapping/unmapping */
69169689Skan	ifpga_bs_map,
70169689Skan	ifpga_bs_unmap,
71169689Skan	ifpga_bs_subregion,
72169689Skan
73169689Skan	/* allocation/deallocation */
74169689Skan	ifpga_bs_alloc,
75169689Skan	ifpga_bs_free,
76169689Skan
77169689Skan	/* get kernel virtual address */
78169689Skan	ifpga_bs_vaddr,
79169689Skan
80169689Skan	/* mmap */
81169689Skan	bs_notimpl_bs_mmap,
82169689Skan
83169689Skan	/* barrier */
84169689Skan	ifpga_bs_barrier,
85169689Skan
86169689Skan	/* read (single) */
87169689Skan	generic_bs_r_1,
88169689Skan	generic_armv4_bs_r_2,
89169689Skan	generic_bs_r_4,
90169689Skan	bs_notimpl_bs_r_8,
91169689Skan
92169689Skan	/* read multiple */
93169689Skan	generic_bs_rm_1,
94169689Skan	generic_armv4_bs_rm_2,
95169689Skan	generic_bs_rm_4,
96169689Skan	bs_notimpl_bs_rm_8,
97169689Skan
98169689Skan	/* read region */
99169689Skan	bs_notimpl_bs_rr_1,
100169689Skan	generic_armv4_bs_rr_2,
101169689Skan	generic_bs_rr_4,
102169689Skan	bs_notimpl_bs_rr_8,
103169689Skan
104169689Skan	/* write (single) */
105169689Skan	generic_bs_w_1,
106169689Skan	generic_armv4_bs_w_2,
107169689Skan	generic_bs_w_4,
108169689Skan	bs_notimpl_bs_w_8,
109169689Skan
110169689Skan	/* write multiple */
111169689Skan	generic_bs_wm_1,
112169689Skan	generic_armv4_bs_wm_2,
113169689Skan	generic_bs_wm_4,
114169689Skan	bs_notimpl_bs_wm_8,
115169689Skan
116169689Skan	/* write region */
117169689Skan	bs_notimpl_bs_wr_1,
118169689Skan	generic_armv4_bs_wr_2,
119169689Skan	generic_bs_wr_4,
120169689Skan	bs_notimpl_bs_wr_8,
121169689Skan
122169689Skan	/* set multiple */
123169689Skan	bs_notimpl_bs_sm_1,
124169689Skan	bs_notimpl_bs_sm_2,
125169689Skan	bs_notimpl_bs_sm_4,
126169689Skan	bs_notimpl_bs_sm_8,
127169689Skan
128169689Skan	/* set region */
129169689Skan	bs_notimpl_bs_sr_1,
130169689Skan	generic_armv4_bs_sr_2,
131169689Skan	bs_notimpl_bs_sr_4,
132169689Skan	bs_notimpl_bs_sr_8,
133169689Skan
134169689Skan	/* copy */
135169689Skan	bs_notimpl_bs_c_1,
136169689Skan	generic_armv4_bs_c_2,
137169689Skan	bs_notimpl_bs_c_4,
138169689Skan	bs_notimpl_bs_c_8,
139169689Skan};
140169689Skan
141169689Skanvoid
142169689Skanifpga_create_io_bs_tag(struct bus_space *t, void *cookie)
143169689Skan{
144169689Skan	*t = ifpga_bs_tag;
145169689Skan	t->bs_cookie = cookie;
146169689Skan}
147169689Skan
148169689Skanvoid
149169689Skanifpga_create_mem_bs_tag(struct bus_space *t, void *cookie)
150169689Skan{
151169689Skan	*t = ifpga_bs_tag;
152169689Skan	t->bs_map = ifpga_mem_bs_map;
153169689Skan	t->bs_unmap = ifpga_mem_bs_unmap;
154169689Skan	t->bs_cookie = cookie;
155169689Skan}
156169689Skan
157169689Skan/* bus space functions */
158169689Skan
159169689Skanint
160169689Skanifpga_bs_map(void *t, bus_addr_t bpa, bus_size_t size, int cacheable, bus_space_handle_t *bshp)
161169689Skan{
162169689Skan        /* The cookie is the base address for the I/O area */
163169689Skan        *bshp = bpa + (bus_addr_t)t;
164169689Skan	return 0;
165169689Skan}
166169689Skan
167169689Skanint
168169689Skanifpga_mem_bs_map(void *t, bus_addr_t bpa, bus_size_t size, int cacheable, bus_space_handle_t *bshp)
169169689Skan{
170169689Skan	bus_addr_t startpa, endpa;
171169689Skan	vaddr_t va;
172169689Skan
173169689Skan	/* Round the allocation to page boundries */
174169689Skan	startpa = trunc_page(bpa);
175169689Skan	endpa = round_page(bpa + size);
176169689Skan
177169689Skan	/* Get some VM.  */
178169689Skan	va = uvm_km_alloc(kernel_map, endpa - startpa, 0,
179169689Skan	    UVM_KMF_VAONLY | UVM_KMF_NOWAIT);
180169689Skan	if (va == 0)
181169689Skan		return ENOMEM;
182169689Skan
183169689Skan	/* Store the bus space handle */
184169689Skan	*bshp = va + (bpa & PGOFSET);
185169689Skan
186169689Skan	/* Now map the pages */
187169689Skan	/* The cookie is the physical base address for the I/O area */
188169689Skan	while (startpa < endpa) {
189169689Skan		/* XXX pmap_kenter_pa maps pages cacheable -- not what
190169689Skan		   we want.  */
191169689Skan		pmap_enter(pmap_kernel(), va, (bus_addr_t)t + startpa,
192169689Skan			   VM_PROT_READ | VM_PROT_WRITE, 0);
193169689Skan		va += PAGE_SIZE;
194169689Skan		startpa += PAGE_SIZE;
195169689Skan	}
196169689Skan	pmap_update(pmap_kernel());
197169689Skan
198169689Skan	return 0;
199169689Skan}
200169689Skan
201169689Skanint
202169689Skanifpga_bs_alloc(void *t, bus_addr_t rstart, bus_addr_t rend, bus_size_t size,
203169689Skan	bus_size_t alignment, bus_size_t boundary, int cacheable,
204169689Skan	bus_addr_t *bpap, bus_space_handle_t *bshp)
205169689Skan{
206169689Skan	panic("ifpga_alloc(): Help!");
207169689Skan}
208169689Skan
209169689Skan
210169689Skanvoid
211169689Skanifpga_bs_unmap(void *t, bus_space_handle_t bsh, bus_size_t size)
212169689Skan{
213169689Skan	/* Nothing to do for an io map.  */
214169689Skan}
215169689Skan
216169689Skanvoid
217169689Skanifpga_mem_bs_unmap(void *t, bus_space_handle_t bsh, bus_size_t size)
218169689Skan{
219169689Skan	vaddr_t startva, endva;
220169689Skan
221169689Skan	startva = trunc_page(bsh);
222169689Skan	endva = round_page(bsh + size);
223169689Skan
224169689Skan	pmap_remove(pmap_kernel(), startva, endva);
225169689Skan	pmap_update(pmap_kernel());
226169689Skan	uvm_km_free(kernel_map, startva, endva - startva, UVM_KMF_VAONLY);
227169689Skan}
228169689Skan
229169689Skanvoid
230169689Skanifpga_bs_free(void *t, bus_space_handle_t bsh, bus_size_t size)
231169689Skan{
232169689Skan
233169689Skan	panic("ifpga_free(): Help!");
234169689Skan	/* ifpga_bs_unmap() does all that we need to do. */
235169689Skan/*	ifpga_bs_unmap(t, bsh, size);*/
236169689Skan}
237169689Skan
238169689Skanint
239169689Skanifpga_bs_subregion(void *t, bus_space_handle_t bsh, bus_size_t offset, bus_size_t size, bus_space_handle_t *nbshp)
240169689Skan{
241169689Skan
242169689Skan	*nbshp = bsh + (offset << ((int)t));
243169689Skan	return (0);
244169689Skan}
245169689Skan
246169689Skanvoid *
247169689Skanifpga_bs_vaddr(void *t, bus_space_handle_t bsh)
248169689Skan{
249169689Skan
250169689Skan	return ((void *)bsh);
251169689Skan}
252169689Skan
253169689Skanvoid
254169689Skanifpga_bs_barrier(void *t, bus_space_handle_t bsh, bus_size_t offset, bus_size_t len, int flags)
255169689Skan{
256169689Skan}
257169689Skan