mvsoc_space.c revision 1.9.12.1 1 /* $NetBSD: mvsoc_space.c,v 1.9.12.1 2018/03/22 01:44:43 pgoyette 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.9.12.1 2018/03/22 01:44:43 pgoyette 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 <sys/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_NORMAL_FUNCS \
53 /* read (single) */ \
54 .bs_r_1 = generic_bs_r_1, \
55 .bs_r_2 = generic_armv4_bs_r_2, \
56 .bs_r_4 = generic_bs_r_4, \
57 .bs_r_8 = bs_notimpl_bs_r_8, \
58 \
59 /* read multiple */ \
60 .bs_rm_1 = generic_bs_rm_1, \
61 .bs_rm_2 = generic_armv4_bs_rm_2, \
62 .bs_rm_4 = generic_bs_rm_4, \
63 .bs_rm_8 = bs_notimpl_bs_rm_8, \
64 \
65 /* read region */ \
66 .bs_rr_1 = generic_bs_rr_1, \
67 .bs_rr_2 = generic_armv4_bs_rr_2, \
68 .bs_rr_4 = generic_bs_rr_4, \
69 .bs_rr_8 = bs_notimpl_bs_rr_8, \
70 \
71 /* write (single) */ \
72 .bs_w_1 = generic_bs_w_1, \
73 .bs_w_2 = generic_armv4_bs_w_2, \
74 .bs_w_4 = generic_bs_w_4, \
75 .bs_w_8 = bs_notimpl_bs_w_8, \
76 \
77 /* write multiple */ \
78 .bs_wm_1 = generic_bs_wm_1, \
79 .bs_wm_2 = generic_armv4_bs_wm_2, \
80 .bs_wm_4 = generic_bs_wm_4, \
81 .bs_wm_8 = bs_notimpl_bs_wm_8, \
82 \
83 /* write region */ \
84 .bs_wr_1 = generic_bs_wr_1, \
85 .bs_wr_2 = generic_armv4_bs_wr_2, \
86 .bs_wr_4 = generic_bs_wr_4, \
87 .bs_wr_8 = bs_notimpl_bs_wr_8
88
89 #define MVSOC_BUS_SPACE_STREAM_FUNCS \
90 /* read stream (single) */ \
91 .bs_r_1_s = generic_bs_r_1, \
92 .bs_r_2_s = generic_armv4_bs_r_2, \
93 .bs_r_4_s = generic_bs_r_4, \
94 .bs_r_8_s = bs_notimpl_bs_r_8, \
95 \
96 /* read multiple stream */ \
97 .bs_rm_1_s = generic_bs_rm_1, \
98 .bs_rm_2_s = generic_armv4_bs_rm_2, \
99 .bs_rm_4_s = generic_bs_rm_4, \
100 .bs_rm_8_s = bs_notimpl_bs_rm_8, \
101 \
102 /* read region stream */ \
103 .bs_rr_1_s = generic_bs_rr_1, \
104 .bs_rr_2_s = generic_armv4_bs_rr_2, \
105 .bs_rr_4_s = generic_bs_rr_4, \
106 .bs_rr_8_s = bs_notimpl_bs_rr_8, \
107 \
108 /* write stream (single) */ \
109 .bs_w_1_s = generic_bs_w_1, \
110 .bs_w_2_s = generic_armv4_bs_w_2, \
111 .bs_w_4_s = generic_bs_w_4, \
112 .bs_w_8_s = bs_notimpl_bs_w_8, \
113 \
114 /* write multiple stream */ \
115 .bs_wm_1_s = generic_bs_wm_1, \
116 .bs_wm_2_s = generic_armv4_bs_wm_2, \
117 .bs_wm_4_s = generic_bs_wm_4, \
118 .bs_wm_8_s = bs_notimpl_bs_wm_8, \
119 \
120 /* write region stream */ \
121 .bs_wr_1_s = generic_bs_wr_1, \
122 .bs_wr_2_s = generic_armv4_bs_wr_2, \
123 .bs_wr_4_s = generic_bs_wr_4, \
124 .bs_wr_8_s = bs_notimpl_bs_wr_8
125
126 #define MVSOC_BUS_SPACE_DEFAULT_FUNCS \
127 /* mapping/unmapping */ \
128 .bs_map = mvsoc_bs_map, \
129 .bs_unmap = mvsoc_bs_unmap, \
130 .bs_subregion = mvsoc_bs_subregion, \
131 \
132 /* allocation/deallocation */ \
133 .bs_alloc =mvsoc_bs_alloc, \
134 .bs_free = mvsoc_bs_free, \
135 \
136 /* get kernel virtual address */ \
137 .bs_vaddr = mvsoc_bs_vaddr, \
138 \
139 /* mmap bus space for userland */ \
140 .bs_mmap = bs_notimpl_bs_mmap, \
141 \
142 /* barrier */ \
143 .bs_barrier = mvsoc_bs_barrier, \
144 \
145 MVSOC_BUS_SPACE_NORMAL_FUNCS, \
146 \
147 /* set multiple */ \
148 .bs_sm_1 = bs_notimpl_bs_sm_1, \
149 .bs_sm_2 = bs_notimpl_bs_sm_2, \
150 .bs_sm_4 = bs_notimpl_bs_sm_4, \
151 .bs_sm_8 = bs_notimpl_bs_sm_8, \
152 \
153 /* set region */ \
154 .bs_sr_1 = bs_notimpl_bs_sr_1, \
155 .bs_sr_2 = generic_armv4_bs_sr_2, \
156 .bs_sr_4 = generic_bs_sr_4, \
157 .bs_sr_8 = bs_notimpl_bs_sr_8, \
158 \
159 /* copy */ \
160 .bs_c_1 = bs_notimpl_bs_c_1, \
161 .bs_c_2 = generic_armv4_bs_c_2, \
162 .bs_c_4 = bs_notimpl_bs_c_4, \
163 .bs_c_8 = bs_notimpl_bs_c_8
164
165
166 struct bus_space mvsoc_bs_tag = {
167 /* cookie */
168 .bs_cookie = (void *)0,
169
170 MVSOC_BUS_SPACE_DEFAULT_FUNCS,
171 #ifdef __BUS_SPACE_HAS_STREAM_METHODS
172 MVSOC_BUS_SPACE_NORMAL_FUNCS,
173 #endif
174 };
175
176 #if NMVPEX > 0
177 #if defined(ORION)
178 struct bus_space orion_pex0_mem_bs_tag = {
179 /* cookie */
180 .bs_cookie = (void *)ORION_TAG_PEX0_MEM,
181
182 MVSOC_BUS_SPACE_DEFAULT_FUNCS,
183 #ifdef __BUS_SPACE_HAS_STREAM_METHODS
184 MVSOC_BUS_SPACE_NORMAL_FUNCS,
185 #endif
186 };
187 struct bus_space orion_pex0_io_bs_tag = {
188 /* cookie */
189 .bs_cookie = (void *)ORION_TAG_PEX0_IO,
190
191 MVSOC_BUS_SPACE_DEFAULT_FUNCS,
192 #ifdef __BUS_SPACE_HAS_STREAM_METHODS
193 MVSOC_BUS_SPACE_NORMAL_FUNCS,
194 #endif
195 };
196 struct bus_space orion_pex1_mem_bs_tag = {
197 /* cookie */
198 .bs_cookie = (void *)ORION_TAG_PEX1_MEM,
199
200 MVSOC_BUS_SPACE_DEFAULT_FUNCS,
201 #ifdef __BUS_SPACE_HAS_STREAM_METHODS
202 MVSOC_BUS_SPACE_NORMAL_FUNCS,
203 #endif
204 };
205 struct bus_space orion_pex1_io_bs_tag = {
206 /* cookie */
207 .bs_cookie = (void *)ORION_TAG_PEX1_IO,
208
209 MVSOC_BUS_SPACE_DEFAULT_FUNCS,
210 #ifdef __BUS_SPACE_HAS_STREAM_METHODS
211 MVSOC_BUS_SPACE_NORMAL_FUNCS,
212 #endif
213 };
214 #endif
215
216 #if defined(KIRKWOOD)
217 struct bus_space kirkwood_pex_mem_bs_tag = {
218 /* cookie */
219 .bs_cookie = (void *)KIRKWOOD_TAG_PEX_MEM,
220
221 MVSOC_BUS_SPACE_DEFAULT_FUNCS,
222 #ifdef __BUS_SPACE_HAS_STREAM_METHODS
223 MVSOC_BUS_SPACE_NORMAL_FUNCS,
224 #endif
225 };
226 struct bus_space kirkwood_pex_io_bs_tag = {
227 /* cookie */
228 .bs_cookie = (void *)KIRKWOOD_TAG_PEX_IO,
229
230 MVSOC_BUS_SPACE_DEFAULT_FUNCS,
231 #ifdef __BUS_SPACE_HAS_STREAM_METHODS
232 MVSOC_BUS_SPACE_NORMAL_FUNCS,
233 #endif
234 };
235 struct bus_space kirkwood_pex1_mem_bs_tag = {
236 /* cookie */
237 .bs_cookie = (void *)KIRKWOOD_TAG_PEX1_MEM,
238
239 MVSOC_BUS_SPACE_DEFAULT_FUNCS,
240 #ifdef __BUS_SPACE_HAS_STREAM_METHODS
241 MVSOC_BUS_SPACE_NORMAL_FUNCS,
242 #endif
243 };
244 struct bus_space kirkwood_pex1_io_bs_tag = {
245 /* cookie */
246 .bs_cookie = (void *)KIRKWOOD_TAG_PEX1_IO,
247
248 MVSOC_BUS_SPACE_DEFAULT_FUNCS,
249 #ifdef __BUS_SPACE_HAS_STREAM_METHODS
250 MVSOC_BUS_SPACE_NORMAL_FUNCS,
251 #endif
252 };
253 #endif
254
255 #if defined(DOVE)
256 struct bus_space dove_pex0_mem_bs_tag = {
257 /* cookie */
258 .bs_cookie = (void *)DOVE_TAG_PEX0_MEM,
259
260 MVSOC_BUS_SPACE_DEFAULT_FUNCS,
261 #ifdef __BUS_SPACE_HAS_STREAM_METHODS
262 MVSOC_BUS_SPACE_NORMAL_FUNCS,
263 #endif
264 };
265 struct bus_space dove_pex0_io_bs_tag = {
266 /* cookie */
267 .bs_cookie = (void *)DOVE_TAG_PEX0_IO,
268
269 MVSOC_BUS_SPACE_DEFAULT_FUNCS,
270 #ifdef __BUS_SPACE_HAS_STREAM_METHODS
271 MVSOC_BUS_SPACE_NORMAL_FUNCS,
272 #endif
273 };
274 struct bus_space dove_pex1_mem_bs_tag = {
275 /* cookie */
276 .bs_cookie = (void *)DOVE_TAG_PEX1_MEM,
277
278 MVSOC_BUS_SPACE_DEFAULT_FUNCS,
279 #ifdef __BUS_SPACE_HAS_STREAM_METHODS
280 MVSOC_BUS_SPACE_NORMAL_FUNCS,
281 #endif
282 };
283 struct bus_space dove_pex1_io_bs_tag = {
284 /* cookie */
285 .bs_cookie = (void *)DOVE_TAG_PEX1_IO,
286
287 MVSOC_BUS_SPACE_DEFAULT_FUNCS,
288 #ifdef __BUS_SPACE_HAS_STREAM_METHODS
289 MVSOC_BUS_SPACE_NORMAL_FUNCS,
290 #endif
291 };
292 #endif
293
294 #if defined(ARMADAXP)
295 struct bus_space armadaxp_pex00_mem_bs_tag = {
296 /* cookie */
297 .bs_cookie = (void *)ARMADAXP_TAG_PEX00_MEM,
298
299 MVSOC_BUS_SPACE_DEFAULT_FUNCS
300 };
301 struct bus_space armadaxp_pex00_io_bs_tag = {
302 /* cookie */
303 .bs_cookie = (void *)ARMADAXP_TAG_PEX00_IO,
304
305 MVSOC_BUS_SPACE_DEFAULT_FUNCS
306 };
307 struct bus_space armadaxp_pex01_mem_bs_tag = {
308 /* cookie */
309 .bs_cookie = (void *)ARMADAXP_TAG_PEX01_MEM,
310
311 MVSOC_BUS_SPACE_DEFAULT_FUNCS
312 };
313 struct bus_space armadaxp_pex01_io_bs_tag = {
314 /* cookie */
315 .bs_cookie = (void *)ARMADAXP_TAG_PEX01_IO,
316
317 MVSOC_BUS_SPACE_DEFAULT_FUNCS
318 };
319 struct bus_space armadaxp_pex02_mem_bs_tag = {
320 /* cookie */
321 .bs_cookie = (void *)ARMADAXP_TAG_PEX02_MEM,
322
323 MVSOC_BUS_SPACE_DEFAULT_FUNCS
324 };
325 struct bus_space armadaxp_pex02_io_bs_tag = {
326 /* cookie */
327 .bs_cookie = (void *)ARMADAXP_TAG_PEX02_IO,
328
329 MVSOC_BUS_SPACE_DEFAULT_FUNCS
330 };
331 struct bus_space armadaxp_pex03_mem_bs_tag = {
332 /* cookie */
333 .bs_cookie = (void *)ARMADAXP_TAG_PEX03_MEM,
334
335 MVSOC_BUS_SPACE_DEFAULT_FUNCS
336 };
337 struct bus_space armadaxp_pex03_io_bs_tag = {
338 /* cookie */
339 .bs_cookie = (void *)ARMADAXP_TAG_PEX03_IO,
340
341 MVSOC_BUS_SPACE_DEFAULT_FUNCS
342 };
343 struct bus_space armadaxp_pex10_mem_bs_tag = {
344 /* cookie */
345 .bs_cookie = (void *)ARMADAXP_TAG_PEX10_MEM,
346
347 MVSOC_BUS_SPACE_DEFAULT_FUNCS
348 };
349 struct bus_space armadaxp_pex10_io_bs_tag = {
350 /* cookie */
351 .bs_cookie = (void *)ARMADAXP_TAG_PEX10_IO,
352
353 MVSOC_BUS_SPACE_DEFAULT_FUNCS
354 };
355 struct bus_space armadaxp_pex2_mem_bs_tag = {
356 /* cookie */
357 .bs_cookie = (void *)ARMADAXP_TAG_PEX2_MEM,
358
359 MVSOC_BUS_SPACE_DEFAULT_FUNCS
360 };
361 struct bus_space armadaxp_pex2_io_bs_tag = {
362 /* cookie */
363 .bs_cookie = (void *)ARMADAXP_TAG_PEX2_IO,
364
365 MVSOC_BUS_SPACE_DEFAULT_FUNCS
366 };
367 struct bus_space armadaxp_pex3_mem_bs_tag = {
368 /* cookie */
369 .bs_cookie = (void *)ARMADAXP_TAG_PEX3_MEM,
370
371 MVSOC_BUS_SPACE_DEFAULT_FUNCS
372 };
373 struct bus_space armadaxp_pex3_io_bs_tag = {
374 /* cookie */
375 .bs_cookie = (void *)ARMADAXP_TAG_PEX3_IO,
376
377 MVSOC_BUS_SPACE_DEFAULT_FUNCS
378 };
379 #endif
380 #endif
381
382 #if NGTPCI > 0
383 #if defined(ORION)
384 struct bus_space orion_pci_mem_bs_tag = {
385 /* cookie */
386 .bs_cookie = (void *)ORION_TAG_PCI_MEM,
387
388 MVSOC_BUS_SPACE_DEFAULT_FUNCS,
389 #ifdef __BUS_SPACE_HAS_STREAM_METHODS
390 MVSOC_BUS_SPACE_NORMAL_FUNCS,
391 #endif
392 };
393 struct bus_space orion_pci_io_bs_tag = {
394 /* cookie */
395 .bs_cookie = (void *)ORION_TAG_PCI_IO,
396
397 MVSOC_BUS_SPACE_DEFAULT_FUNCS,
398 #ifdef __BUS_SPACE_HAS_STREAM_METHODS
399 MVSOC_BUS_SPACE_NORMAL_FUNCS,
400 #endif
401 };
402 #endif
403 #endif
404
405
406 int
407 mvsoc_bs_map(void *space, bus_addr_t address, bus_size_t size, int flags,
408 bus_space_handle_t *handlep)
409 {
410 const struct pmap_devmap *pd;
411 paddr_t startpa, endpa, offset, pa;
412 vaddr_t va;
413
414 /*
415 * XXX: We are not configuring any decode windows for Armada XP
416 * at the moment. We rely on those that have been set by u-boot.
417 * Hence we don't want to mess around with decode windows,
418 * till we get full controll over them.
419 */
420
421 int tag = (int)space;
422
423 if (tag != 0) {
424 bus_addr_t remap;
425 uint32_t base;
426 int window;
427
428 window = mvsoc_target(tag, NULL, NULL, &base, NULL);
429 if (window == -1)
430 return ENOMEM;
431 if (window < nremap) {
432 remap = read_mlmbreg(MVSOC_MLMB_WRLR(window)) &
433 MVSOC_MLMB_WRLR_REMAP_MASK;
434 remap |=
435 (read_mlmbreg(MVSOC_MLMB_WRHR(window)) << 16) << 16;
436 address = address - remap + base;
437 }
438 }
439
440 if ((pd = pmap_devmap_find_pa(address, size)) != NULL) {
441 /* Device was statically mapped. */
442 *handlep = pd->pd_va + (address - pd->pd_pa);
443 return 0;
444 }
445
446 startpa = trunc_page(address);
447 endpa = round_page(address + size);
448 offset = address & PAGE_MASK;
449
450 /* XXX use extent manager to check duplicate mapping */
451
452 va = uvm_km_alloc(kernel_map, endpa - startpa, 0,
453 UVM_KMF_VAONLY | UVM_KMF_NOWAIT);
454 if (va == 0x00000000)
455 return ENOMEM;
456
457 *handlep = va + offset;
458
459 const int pmapflags =
460 (flags & (BUS_SPACE_MAP_CACHEABLE|BUS_SPACE_MAP_PREFETCHABLE))
461 ? 0
462 : PMAP_NOCACHE;
463
464 /* Now map the pages */
465 for (pa = startpa; pa < endpa; pa += PAGE_SIZE, va += PAGE_SIZE) {
466 pmap_kenter_pa(va, pa, VM_PROT_READ | VM_PROT_WRITE, pmapflags);
467 }
468 pmap_update(pmap_kernel());
469
470 return 0;
471 }
472
473 void
474 mvsoc_bs_unmap(void *space, bus_space_handle_t handle, bus_size_t size)
475 {
476 vaddr_t va, sz;
477
478 if (pmap_devmap_find_va(handle, size) != NULL)
479 /* Device was statically mapped; nothing to do. */
480 return;
481
482 va = trunc_page(handle);
483 sz = round_page(handle + size) - va;
484
485 pmap_kremove(va, sz);
486 pmap_update(pmap_kernel());
487 uvm_km_free(kernel_map, va, sz, UVM_KMF_VAONLY);
488 }
489
490 /* ARGSUSED */
491 int
492 mvsoc_bs_subregion(void *space, bus_space_handle_t handle,
493 bus_size_t offset, bus_size_t size,
494 bus_space_handle_t *nhandlep)
495 {
496
497 *nhandlep = handle + offset;
498 return 0;
499 }
500
501 /* ARGSUSED */
502 int
503 mvsoc_bs_alloc(void *space, bus_addr_t reg_start, bus_addr_t reg_end,
504 bus_size_t size, bus_size_t alignment, bus_size_t boundary,
505 int flags, bus_addr_t *addrp, bus_space_handle_t *handlep)
506 {
507
508 panic("%s(): not implemented\n", __func__);
509 }
510
511 /* ARGSUSED */
512 void
513 mvsoc_bs_free(void *space, bus_space_handle_t handle, bus_size_t size)
514 {
515
516 panic("%s(): not implemented\n", __func__);
517 }
518
519 /* ARGSUSED */
520 void
521 mvsoc_bs_barrier(void *space, bus_space_handle_t handle, bus_size_t offset,
522 bus_size_t length, int flags)
523 {
524
525 /* Nothing to do. */
526 }
527
528 /* ARGSUSED */
529 void *
530 mvsoc_bs_vaddr(void *space, bus_space_handle_t handle)
531 {
532
533 return (void *)handle;
534 }
535