xref: /netbsd-src/sys/arch/arm/marvell/mvsoc_space.c (revision c2f76ff004a2cb67efe5b12d97bd3ef7fe89e18d)
1 /*	$NetBSD: mvsoc_space.c,v 1.1 2010/10/03 05:49:24 kiyohara Exp $	*/
2 /*
3  * Copyright (c) 2007 KIYOHARA Takashi
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
19  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
23  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
24  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25  * POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 #include <sys/cdefs.h>
29 __KERNEL_RCSID(0, "$NetBSD: mvsoc_space.c,v 1.1 2010/10/03 05:49:24 kiyohara Exp $");
30 
31 #include "opt_mvsoc.h"
32 #include "mvpex.h"
33 #include "gtpci.h"
34 
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 
38 #include <uvm/uvm_extern.h>
39 
40 #include <machine/bus.h>
41 
42 #include <arm/marvell/mvsocreg.h>
43 #include <arm/marvell/mvsocvar.h>
44 
45 
46 /* Proto types for all the bus_space structure functions */
47 bs_protos(mvsoc);
48 bs_protos(generic);
49 bs_protos(generic_armv4);
50 bs_protos(bs_notimpl);
51 
52 #define MVSOC_BUS_SPACE_DEFAULT_FUNCS		\
53 	/* mapping/unmapping */			\
54 	mvsoc_bs_map,				\
55 	mvsoc_bs_unmap,				\
56 	mvsoc_bs_subregion,			\
57 						\
58 	/* allocation/deallocation */		\
59 	mvsoc_bs_alloc,				\
60 	mvsoc_bs_free,				\
61 						\
62 	/* get kernel virtual address */	\
63 	mvsoc_bs_vaddr,				\
64 						\
65 	/* mmap bus space for userland */	\
66 	bs_notimpl_bs_mmap,			\
67 						\
68 	/* barrier */				\
69 	mvsoc_bs_barrier,			\
70 						\
71 	/* read (single) */			\
72 	generic_bs_r_1,				\
73 	generic_armv4_bs_r_2,			\
74 	generic_bs_r_4,				\
75 	bs_notimpl_bs_r_8,			\
76 						\
77 	/* read multiple */			\
78 	generic_bs_rm_1,			\
79 	generic_armv4_bs_rm_2,			\
80 	generic_bs_rm_4,			\
81 	bs_notimpl_bs_rm_8,			\
82 						\
83 	/* read region */			\
84 	generic_bs_rr_1,			\
85 	generic_armv4_bs_rr_2,			\
86 	generic_bs_rr_4,			\
87 	bs_notimpl_bs_rr_8,			\
88 						\
89 	/* write (single) */			\
90 	generic_bs_w_1,				\
91 	generic_armv4_bs_w_2,			\
92 	generic_bs_w_4,				\
93 	bs_notimpl_bs_w_8,			\
94 						\
95 	/* write multiple */			\
96 	generic_bs_wm_1,			\
97 	generic_armv4_bs_wm_2,			\
98 	generic_bs_wm_4,			\
99 	bs_notimpl_bs_wm_8,			\
100 						\
101 	/* write region */			\
102 	generic_bs_wr_1,			\
103 	generic_armv4_bs_wr_2,			\
104 	generic_bs_wr_4,			\
105 	bs_notimpl_bs_wr_8,			\
106 						\
107 	/* set multiple */			\
108 	bs_notimpl_bs_sm_1,			\
109 	bs_notimpl_bs_sm_2,			\
110 	bs_notimpl_bs_sm_4,			\
111 	bs_notimpl_bs_sm_8,			\
112 						\
113 	/* set region */			\
114 	bs_notimpl_bs_sr_1,			\
115 	generic_armv4_bs_sr_2,			\
116 	generic_bs_sr_4,			\
117 	bs_notimpl_bs_sr_8,			\
118 						\
119 	/* copy */				\
120 	bs_notimpl_bs_c_1,			\
121 	generic_armv4_bs_c_2,			\
122 	bs_notimpl_bs_c_4,			\
123 	bs_notimpl_bs_c_8,
124 
125 
126 struct bus_space mvsoc_bs_tag = {
127 	/* cookie */
128 	(void *)0,
129 
130 	MVSOC_BUS_SPACE_DEFAULT_FUNCS
131 };
132 
133 #if NMVPEX > 0
134 #if defined(ORION)
135 struct bus_space orion_pex0_mem_bs_tag = {
136 	/* cookie */
137 	(void *)ORION_TAG_PEX0_MEM,
138 
139 	MVSOC_BUS_SPACE_DEFAULT_FUNCS
140 };
141 struct bus_space orion_pex0_io_bs_tag = {
142 	/* cookie */
143 	(void *)ORION_TAG_PEX0_IO,
144 
145 	MVSOC_BUS_SPACE_DEFAULT_FUNCS
146 };
147 struct bus_space orion_pex1_mem_bs_tag = {
148 	/* cookie */
149 	(void *)ORION_TAG_PEX1_MEM,
150 
151 	MVSOC_BUS_SPACE_DEFAULT_FUNCS
152 };
153 struct bus_space orion_pex1_io_bs_tag = {
154 	/* cookie */
155 	(void *)ORION_TAG_PEX1_IO,
156 
157 	MVSOC_BUS_SPACE_DEFAULT_FUNCS
158 };
159 #endif
160 
161 #if defined(KIRKWOOD)
162 struct bus_space kirkwood_pex_mem_bs_tag = {
163 	/* cookie */
164 	(void *)KIRKWOOD_TAG_PEX_MEM,
165 
166 	MVSOC_BUS_SPACE_DEFAULT_FUNCS
167 };
168 struct bus_space kirkwood_pex_io_bs_tag = {
169 	/* cookie */
170 	(void *)KIRKWOOD_TAG_PEX_IO,
171 
172 	MVSOC_BUS_SPACE_DEFAULT_FUNCS
173 };
174 #endif
175 #endif
176 
177 #if NGTPCI > 0
178 #if defined(ORION)
179 struct bus_space orion_pci_mem_bs_tag = {
180 	/* cookie */
181 	(void *)ORION_TAG_PCI_MEM,
182 
183 	MVSOC_BUS_SPACE_DEFAULT_FUNCS
184 };
185 struct bus_space orion_pci_io_bs_tag = {
186 	/* cookie */
187 	(void *)ORION_TAG_PCI_IO,
188 
189 	MVSOC_BUS_SPACE_DEFAULT_FUNCS
190 };
191 #endif
192 #endif
193 
194 
195 int
196 mvsoc_bs_map(void *space, bus_addr_t address, bus_size_t size, int flags,
197 	     bus_space_handle_t *handlep)
198 {
199 	const struct pmap_devmap *pd;
200 	paddr_t startpa, endpa, offset, pa;
201 	pt_entry_t *pte;
202 	vaddr_t va;
203 	int tag = (int)space;
204 
205 	if (tag != 0) {
206 		bus_addr_t remap;
207 		uint32_t base;
208 		int window;
209 
210 		window = mvsoc_target(tag, NULL, NULL, &base, NULL);
211 		if (window == -1)
212 			return ENOMEM;
213 		if (window < nremap) {
214 			remap = read_mlmbreg(MVSOC_MLMB_WRLR(window)) &
215 			    MVSOC_MLMB_WRLR_REMAP_MASK;
216 			remap |=
217 			    (read_mlmbreg(MVSOC_MLMB_WRHR(window)) << 16) << 16;
218 			address = address - remap + base;
219 		}
220 	}
221 
222 	if ((pd = pmap_devmap_find_pa(address, size)) != NULL) {
223 		/* Device was statically mapped. */
224 		*handlep = pd->pd_va + (address - pd->pd_pa);
225 		return 0;
226 	}
227 
228 	startpa = trunc_page(address);
229 	endpa = round_page(address + size);
230 	offset = address & PAGE_MASK;
231 
232 	/* XXX use extent manager to check duplicate mapping */
233 
234 	va = uvm_km_alloc(kernel_map, endpa - startpa, 0,
235 	    UVM_KMF_VAONLY | UVM_KMF_NOWAIT);
236 	if (va == 0x00000000)
237 		return ENOMEM;
238 
239 	*handlep = va + offset;
240 
241 	/* Now map the pages */
242 	for (pa = startpa; pa < endpa; pa += PAGE_SIZE, va += PAGE_SIZE) {
243 		pmap_kenter_pa(va, pa, VM_PROT_READ | VM_PROT_WRITE, 0);
244 		if ((flags & BUS_SPACE_MAP_CACHEABLE) == 0) {
245 			pte = vtopte(va);
246 			*pte &= ~L2_S_CACHE_MASK;
247 			PTE_SYNC(pte);
248 			/*
249 			 * XXX: pmap_kenter_pa() also does PTE_SYNC(). a bit of
250 			 *      waste.
251 			 */
252 		}
253 	}
254 	pmap_update(pmap_kernel());
255 
256 	return 0;
257 }
258 
259 void
260 mvsoc_bs_unmap(void *space, bus_space_handle_t handle, bus_size_t size)
261 {
262 	vaddr_t va, sz;
263 
264 	if (pmap_devmap_find_va(handle, size) != NULL)
265 		/* Device was statically mapped; nothing to do. */
266 		return;
267 
268 	va = trunc_page(handle);
269         sz = round_page(handle + size) - va;
270 
271 	pmap_kremove(va, sz);
272 	pmap_update(pmap_kernel());
273 	uvm_km_free(kernel_map, va, sz, UVM_KMF_VAONLY);
274 }
275 
276 /* ARGSUSED */
277 int
278 mvsoc_bs_subregion(void *space, bus_space_handle_t handle,
279 		       bus_size_t offset, bus_size_t size,
280 		       bus_space_handle_t *nhandlep)
281 {
282 
283 	*nhandlep = handle + offset;
284 	return 0;
285 }
286 
287 /* ARGSUSED */
288 int
289 mvsoc_bs_alloc(void *space, bus_addr_t reg_start, bus_addr_t reg_end,
290 	       bus_size_t size, bus_size_t alignment, bus_size_t boundary,
291 	       int flags, bus_addr_t *addrp, bus_space_handle_t *handlep)
292 {
293 
294 	panic("%s(): not implemented\n", __func__);
295 }
296 
297 /* ARGSUSED */
298 void
299 mvsoc_bs_free(void *space, bus_space_handle_t handle, bus_size_t size)
300 {
301 
302 	panic("%s(): not implemented\n", __func__);
303 }
304 
305 /* ARGSUSED */
306 void
307 mvsoc_bs_barrier(void *space, bus_space_handle_t handle, bus_size_t offset,
308 		 bus_size_t length, int flags)
309 {
310 
311 	/* Nothing to do. */
312 }
313 
314 /* ARGSUSED */
315 void *
316 mvsoc_bs_vaddr(void *space, bus_space_handle_t handle)
317 {
318 
319 	return (void *)handle;
320 }
321