xref: /netbsd-src/sys/arch/evbarm/armadaxp/armadaxp_machdep.c (revision c38e7cc395b1472a774ff828e46123de44c628e9)
1 /*	$NetBSD: armadaxp_machdep.c,v 1.13 2017/03/10 15:44:24 skrll Exp $	*/
2 /*******************************************************************************
3 Copyright (C) Marvell International Ltd. and its affiliates
4 
5 Developed by Semihalf
6 
7 ********************************************************************************
8 Marvell BSD License
9 
10 If you received this File from Marvell, you may opt to use, redistribute and/or
11 modify this File under the following licensing terms.
12 Redistribution and use in source and binary forms, with or without modification,
13 are permitted provided that the following conditions are met:
14 
15     *   Redistributions of source code must retain the above copyright notice,
16             this list of conditions and the following disclaimer.
17 
18     *   Redistributions in binary form must reproduce the above copyright
19         notice, this list of conditions and the following disclaimer in the
20         documentation and/or other materials provided with the distribution.
21 
22     *   Neither the name of Marvell nor the names of its contributors may be
23         used to endorse or promote products derived from this software without
24         specific prior written permission.
25 
26 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
27 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
28 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
29 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
30 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
31 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
32 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
33 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 
37 *******************************************************************************/
38 
39 #include <sys/cdefs.h>
40 __KERNEL_RCSID(0, "$NetBSD: armadaxp_machdep.c,v 1.13 2017/03/10 15:44:24 skrll Exp $");
41 
42 #include "opt_machdep.h"
43 #include "opt_mvsoc.h"
44 #include "opt_evbarm_boardtype.h"
45 #include "opt_com.h"
46 #include "opt_ddb.h"
47 #include "opt_kgdb.h"
48 #include "opt_pci.h"
49 #include "opt_ipkdb.h"
50 
51 #include <sys/bus.h>
52 #include <sys/param.h>
53 #include <sys/device.h>
54 #include <sys/systm.h>
55 #include <sys/kernel.h>
56 #include <sys/exec.h>
57 #include <sys/proc.h>
58 #include <sys/msgbuf.h>
59 #include <sys/reboot.h>
60 #include <sys/termios.h>
61 #include <sys/ksyms.h>
62 
63 #include <uvm/uvm_extern.h>
64 
65 #include <sys/conf.h>
66 #include <dev/cons.h>
67 #include <dev/md.h>
68 
69 #include <dev/marvell/marvellreg.h>
70 #include <dev/pci/pcireg.h>
71 #include <dev/pci/pcivar.h>
72 #include <machine/pci_machdep.h>
73 
74 #include <machine/db_machdep.h>
75 #include <ddb/db_sym.h>
76 #include <ddb/db_extern.h>
77 #ifdef KGDB
78 #include <sys/kgdb.h>
79 #endif
80 
81 #include <machine/bootconfig.h>
82 #include <machine/autoconf.h>
83 #include <machine/cpu.h>
84 #include <machine/frame.h>
85 #include <arm/armreg.h>
86 #include <arm/undefined.h>
87 
88 #include <arm/arm32/machdep.h>
89 
90 #include <arm/marvell/mvsocreg.h>
91 #include <arm/marvell/mvsocvar.h>
92 #include <arm/marvell/armadaxpreg.h>
93 
94 #include <evbarm/marvell/marvellreg.h>
95 #include <evbarm/marvell/marvellvar.h>
96 #include <dev/marvell/marvellreg.h>
97 
98 #include "mvpex.h"
99 #include "com.h"
100 #if NCOM > 0
101 #include <dev/ic/comreg.h>
102 #include <dev/ic/comvar.h>
103 #endif
104 
105 #include <net/if_ether.h>
106 
107 /*
108  * Address to call from cpu_reset() to reset the machine.
109  * This is machine architecture dependent as it varies depending
110  * on where the ROM appears when you turn the MMU off.
111  */
112 
113 BootConfig bootconfig;		/* Boot config storage */
114 char *boot_args = NULL;
115 char *boot_file = NULL;
116 
117 /*
118  * U-Boot argument buffer
119  */
120 extern unsigned int uboot_regs_pa[]; /* saved r0, r1, r2, r3 */
121 unsigned int *uboot_regs_va;
122 char boot_argbuf[MAX_BOOT_STRING];
123 
124 extern int KERNEL_BASE_phys[];
125 
126 /*
127  * Put some bogus settings of the MEMSTART and MEMSIZE
128  * if they are not defined in kernel configuration file.
129  */
130 #ifndef MEMSTART
131 #define MEMSTART 0x00000000UL
132 #endif
133 #ifndef MEMSIZE
134 #define MEMSIZE 0x40000000UL
135 #endif
136 
137 #ifndef STARTUP_PAGETABLE_ADDR
138 #define	STARTUP_PAGETABLE_ADDR 0x00000000UL
139 #endif
140 
141 /* Physical offset of the kernel from MEMSTART */
142 #define KERNEL_OFFSET		(paddr_t)&KERNEL_BASE_phys
143 /* Kernel base virtual address */
144 #define	KERNEL_TEXT_BASE	(KERNEL_BASE + KERNEL_OFFSET)
145 
146 #define	KERNEL_VM_BASE		(KERNEL_BASE + 0x40000000)
147 #define KERNEL_VM_SIZE		0x14000000
148 
149 void consinit(void);
150 #ifdef KGDB
151 static void kgdb_port_init(void);
152 #endif
153 
154 static void axp_device_register(device_t dev, void *aux);
155 
156 static void
157 axp_system_reset(void)
158 {
159 	extern vaddr_t misc_base;
160 
161 #define write_miscreg(r, v)	(*(volatile uint32_t *)(misc_base + (r)) = (v))
162 
163 	cpu_reset_address = 0;
164 
165 	/* Unmask soft reset */
166 	write_miscreg(ARMADAXP_MISC_RSTOUTNMASKR,
167 	    ARMADAXP_MISC_RSTOUTNMASKR_GLOBALSOFTRSTOUTEN);
168 	/* Assert soft reset */
169 	write_miscreg(ARMADAXP_MISC_SSRR, ARMADAXP_MISC_SSRR_GLOBALSOFTRST);
170 
171 	while (1);
172 }
173 
174 /*
175  * Static device mappings. These peripheral registers are mapped at
176  * fixed virtual addresses very early in initarm() so that we can use
177  * them while booting the kernel, and stay at the same address
178  * throughout whole kernel's life time.
179  *
180  * We use this table twice; once with bootstrap page table, and once
181  * with kernel's page table which we build up in initarm().
182  *
183  * Since we map these registers into the bootstrap page table using
184  * pmap_devmap_bootstrap() which calls pmap_map_chunk(), we map
185  * registers segment-aligned and segment-rounded in order to avoid
186  * using the 2nd page tables.
187  */
188 
189 #define	_A(a)	((a) & ~L1_S_OFFSET)
190 #define	_S(s)	(((s) + L1_S_SIZE - 1) & ~(L1_S_SIZE-1))
191 
192 static const struct pmap_devmap devmap[] = {
193 	{
194 		/* Internal registers */
195 		.pd_va = _A(MARVELL_INTERREGS_VBASE),
196 		.pd_pa = _A(MARVELL_INTERREGS_PBASE),
197 		.pd_size = _S(MVSOC_INTERREGS_SIZE),
198 		.pd_prot = VM_PROT_READ|VM_PROT_WRITE,
199 		.pd_cache = PTE_NOCACHE
200 	},
201 	{0, 0, 0, 0, 0}
202 };
203 
204 #undef	_A
205 #undef	_S
206 
207 static inline pd_entry_t *
208 read_ttb(void)
209 {
210 	return (pd_entry_t *)(armreg_ttbr_read() & ~((1<<14)-1));
211 }
212 
213 static int
214 axp_pcie_free_win(void)
215 {
216 	/* Find first disabled window */
217 	for (size_t i = 0; i < ARMADAXP_MLMB_NWINDOW; i++) {
218 		if ((read_mlmbreg(MVSOC_MLMB_WCR(i)) &
219 		    MVSOC_MLMB_WCR_WINEN) == 0) {
220 			return i;
221 		}
222 	}
223 	/* If there is no free window, return erroneous value */
224 	return (-1);
225 }
226 
227 static void
228 reset_axp_pcie_win(void)
229 {
230 	uint32_t target, attr;
231 	int memtag = 0, iotag = 0, window, i;
232 	uint32_t membase;
233 	uint32_t iobase;
234 	uint32_t tags[] = { ARMADAXP_TAG_PEX00_MEM, ARMADAXP_TAG_PEX00_IO,
235 			    ARMADAXP_TAG_PEX01_MEM, ARMADAXP_TAG_PEX01_IO,
236 			    ARMADAXP_TAG_PEX02_MEM, ARMADAXP_TAG_PEX02_IO,
237 			    ARMADAXP_TAG_PEX03_MEM, ARMADAXP_TAG_PEX03_IO,
238 			    ARMADAXP_TAG_PEX10_MEM, ARMADAXP_TAG_PEX10_IO,
239 			    ARMADAXP_TAG_PEX11_MEM, ARMADAXP_TAG_PEX11_IO,
240 			    ARMADAXP_TAG_PEX12_MEM, ARMADAXP_TAG_PEX12_IO,
241 			    ARMADAXP_TAG_PEX13_MEM, ARMADAXP_TAG_PEX13_IO,
242 			    ARMADAXP_TAG_PEX2_MEM, ARMADAXP_TAG_PEX2_IO,
243 			    ARMADAXP_TAG_PEX3_MEM, ARMADAXP_TAG_PEX3_IO
244 			};
245 
246 	nwindow = ARMADAXP_MLMB_NWINDOW;
247 	nremap = ARMADAXP_MLMB_NREMAP;
248 	membase = MARVELL_PEXMEM_PBASE;
249 	iobase = MARVELL_PEXIO_PBASE;
250 	for (i = 0; i < __arraycount(tags) / 2; i++) {
251 		memtag = tags[2 * i];
252 		iotag = tags[(2 * i) + 1];
253 
254 		/* Reset PCI-Express space to window register. */
255 		window = mvsoc_target(memtag, &target, &attr, NULL, NULL);
256 
257 		/* Find free window if we've got spurious one */
258 		if (window >= nwindow) {
259 			window = axp_pcie_free_win();
260 			/* Just break if there is no free windows left */
261 			if (window < 0) {
262 				aprint_error(": no free windows for PEX MEM\n");
263 				break;
264 			}
265 		}
266 		write_mlmbreg(MVSOC_MLMB_WCR(window),
267 		    MVSOC_MLMB_WCR_WINEN |
268 		    MVSOC_MLMB_WCR_TARGET(target) |
269 		    MVSOC_MLMB_WCR_ATTR(attr) |
270 		    MVSOC_MLMB_WCR_SIZE(MARVELL_PEXMEM_SIZE));
271 		write_mlmbreg(MVSOC_MLMB_WBR(window),
272 		    membase & MVSOC_MLMB_WBR_BASE_MASK);
273 #ifdef PCI_NETBSD_CONFIGURE
274 		if (window < nremap) {
275 			write_mlmbreg(MVSOC_MLMB_WRLR(window),
276 			    membase & MVSOC_MLMB_WRLR_REMAP_MASK);
277 			write_mlmbreg(MVSOC_MLMB_WRHR(window), 0);
278 		}
279 #endif
280 		window = mvsoc_target(iotag, &target, &attr, NULL, NULL);
281 
282 		/* Find free window if we've got spurious one */
283 		if (window >= nwindow) {
284 			window = axp_pcie_free_win();
285 			/* Just break if there is no free windows left */
286 			if (window < 0) {
287 				aprint_error(": no free windows for PEX I/O\n");
288 				break;
289 			}
290 		}
291 		write_mlmbreg(MVSOC_MLMB_WCR(window),
292 		    MVSOC_MLMB_WCR_WINEN |
293 		    MVSOC_MLMB_WCR_TARGET(target) |
294 		    MVSOC_MLMB_WCR_ATTR(attr) |
295 		    MVSOC_MLMB_WCR_SIZE(MARVELL_PEXIO_SIZE));
296 		write_mlmbreg(MVSOC_MLMB_WBR(window),
297 		    iobase & MVSOC_MLMB_WBR_BASE_MASK);
298 #ifdef PCI_NETBSD_CONFIGURE
299 		if (window < nremap) {
300 			write_mlmbreg(MVSOC_MLMB_WRLR(window),
301 			    iobase & MVSOC_MLMB_WRLR_REMAP_MASK);
302 			write_mlmbreg(MVSOC_MLMB_WRHR(window), 0);
303 		}
304 #endif
305 		membase += MARVELL_PEXMEM_SIZE;
306 		iobase += MARVELL_PEXIO_SIZE;
307 	}
308 }
309 
310 /*
311  * u_int initarm(...)
312  *
313  * Initial entry point on startup. This gets called before main() is
314  * entered.
315  * It should be responsible for setting up everything that must be
316  * in place when main is called.
317  * This includes
318  *   Taking a copy of the boot configuration structure.
319  *   Initialising the physical console so characters can be printed.
320  *   Setting up page tables for the kernel
321  *   Relocating the kernel to the bottom of physical memory
322  */
323 u_int
324 initarm(void *arg)
325 {
326 	cpu_reset_address = axp_system_reset;
327 
328 	mvsoc_bootstrap(MARVELL_INTERREGS_VBASE);
329 
330 	/* Set CPU functions */
331 	if (set_cpufuncs())
332 		panic("cpu not recognized!");
333 
334 	/*
335 	 * Map devices into the initial page table
336 	 * in order to use early console during initialization process.
337 	 * consinit is going to use this mapping.
338 	 */
339 	pmap_devmap_bootstrap((vaddr_t)read_ttb(), devmap);
340 
341 	/* Initialize system console */
342 	consinit();
343 
344 	/* Reset PCI-Express space to window register. */
345 	reset_axp_pcie_win();
346 
347 	/* Get CPU, system and timebase frequencies */
348 	armadaxp_bootstrap(
349 	    MARVELL_INTERREGS_VBASE,
350 	    MARVELL_INTERREGS_PBASE);
351 
352 #ifdef KGDB
353 	kgdb_port_init();
354 #endif
355 
356 #ifdef VERBOSE_INIT_ARM
357 	/* Talk to the user */
358 #define	BDSTR(s)	_BDSTR(s)
359 #define	_BDSTR(s)	#s
360 	printf("\nNetBSD/evbarm (" BDSTR(EVBARM_BOARDTYPE) ") booting ...\n");
361 #endif
362 
363 #ifdef __HAVE_MM_MD_DIRECT_MAPPED_PHYS
364 	const bool mapallmem_p = true;
365 #else
366 	const bool mapallmem_p = false;
367 #endif
368 
369 #ifdef VERBOSE_INIT_ARM
370 	printf("initarm: Configuring system ...\n");
371 #endif
372 	psize_t memsize = MEMSIZE;
373 	if (mapallmem_p && memsize > KERNEL_VM_BASE - KERNEL_BASE) {
374 		printf("%s: dropping RAM size from %luMB to %uMB\n",
375 		    __func__, (unsigned long) (memsize >> 20),
376 		    (KERNEL_VM_BASE - KERNEL_BASE) >> 20);
377 		memsize = KERNEL_VM_BASE - KERNEL_BASE;
378 	}
379 	/* Fake bootconfig structure for the benefit of pmap.c. */
380 	bootconfig.dramblocks = 1;
381 	bootconfig.dram[0].address = MEMSTART;
382 	bootconfig.dram[0].pages = memsize / PAGE_SIZE;
383 
384         physical_start = bootconfig.dram[0].address;
385         physical_end = physical_start + (bootconfig.dram[0].pages * PAGE_SIZE);
386 
387 	arm32_bootmem_init(0, physical_end, (uintptr_t) KERNEL_BASE_phys);
388 	arm32_kernel_vm_init(KERNEL_VM_BASE, ARM_VECTORS_LOW, 0,
389 	    devmap, mapallmem_p);
390 
391 	/* we've a specific device_register routine */
392 	evbarm_device_register = axp_device_register;
393 
394 	/* copy U-Boot args from U-Boot heap to kernel memory */
395 	uboot_regs_va = (int *)((unsigned int)uboot_regs_pa + KERNEL_BASE);
396 	boot_args = (char *)(uboot_regs_va[3] + KERNEL_BASE);
397 	strlcpy(boot_argbuf, (char *)boot_args, sizeof(boot_argbuf));
398 	boot_args = boot_argbuf;
399 	parse_mi_bootargs(boot_args);
400 
401 	return initarm_common(KERNEL_VM_BASE, KERNEL_VM_SIZE, NULL, 0);
402 }
403 
404 #ifndef CONSADDR
405 #error Specify the address of the UART with the CONSADDR option.
406 #endif
407 #ifndef CONSPEED
408 #define	CONSPEED B115200
409 #endif
410 #ifndef CONMODE
411 #define	CONMODE ((TTYDEF_CFLAG & ~(CSIZE | CSTOPB | PARENB)) | CS8) /* 8N1 */
412 #endif
413 #ifndef CONSFREQ
414 #define	CONSFREQ 0
415 #endif
416 static const int	comcnspeed = CONSPEED;
417 static const int	comcnfreq  = CONSFREQ;
418 static const tcflag_t	comcnmode  = CONMODE;
419 static const bus_addr_t	comcnaddr  = (bus_addr_t)CONSADDR;
420 
421 void
422 consinit(void)
423 {
424 	static bool consinit_called = false;
425 
426 	if (consinit_called)
427 		return;
428 	consinit_called = true;
429 
430 #if NCOM > 0
431 	extern int mvuart_cnattach(bus_space_tag_t, bus_addr_t, int,
432 	    uint32_t, int);
433 
434 	if (mvuart_cnattach(&mvsoc_bs_tag, comcnaddr, comcnspeed,
435 			comcnfreq ? comcnfreq : mvTclk , comcnmode))
436 		panic("Serial console can not be initialized.");
437 #endif
438 }
439 
440 #ifdef KGDB
441 #ifndef KGDB_DEVADDR
442 #error Specify the address of the kgdb UART with the KGDB_DEVADDR option.
443 #endif
444 #ifndef KGDB_DEVRATE
445 #define KGDB_DEVRATE B115200
446 #endif
447 #define MVUART_SIZE 0x20
448 
449 #ifndef KGDB_DEVMODE
450 #define KGDB_DEVMODE ((TTYDEF_CFLAG & ~(CSIZE | CSTOPB | PARENB)) | CS8) /* 8N1 */
451 #endif
452 static const vaddr_t comkgdbaddr = KGDB_DEVADDR;
453 static const int comkgdbspeed = KGDB_DEVRATE;
454 static const int comkgdbmode = KGDB_DEVMODE;
455 
456 void
457 static kgdb_port_init(void)
458 {
459 	static int kgdbsinit_called = 0;
460 
461 	if (kgdbsinit_called != 0)
462 		return;
463 	kgdbsinit_called = 1;
464 
465 	if (com_kgdb_attach(&mvsoc_bs_tag, comkgdbaddr, comkgdbspeed,
466 			MVUART_SIZE, COM_TYPE_16550_NOERS, comkgdbmode))
467 		panic("KGDB uart can not be initialized.");
468 }
469 #endif
470 
471 #if NMVPEX > 0
472 static void
473 marvell_startend_by_tag(int tag, uint64_t *start, uint64_t *end)
474 {
475 
476 	uint32_t base, size;
477 	int win;
478 
479 	win = mvsoc_target(tag, NULL, NULL, &base, &size);
480 	if (size != 0) {
481 		if (win < nremap)
482 			*start = read_mlmbreg(MVSOC_MLMB_WRLR(win)) |
483 			    ((read_mlmbreg(MVSOC_MLMB_WRHR(win)) << 16) << 16);
484 		else
485 			*start = base;
486 		*end = *start + size - 1;
487 	} else
488 		*start = *end = 0;
489 }
490 #endif
491 
492 static void
493 axp_device_register(device_t dev, void *aux)
494 {
495 	prop_dictionary_t dict = device_properties(dev);
496 
497 #if NCOM > 0
498 	if (device_is_a(dev, "com") &&
499 	    device_is_a(device_parent(dev), "mvsoc"))
500 		prop_dictionary_set_uint32(dict, "frequency", mvTclk);
501 #endif
502 
503 #if NMVPEX > 0
504 	extern struct bus_space
505 	    armadaxp_pex00_io_bs_tag, armadaxp_pex00_mem_bs_tag,
506 	    armadaxp_pex01_io_bs_tag, armadaxp_pex01_mem_bs_tag,
507 	    armadaxp_pex02_io_bs_tag, armadaxp_pex02_mem_bs_tag,
508 	    armadaxp_pex03_io_bs_tag, armadaxp_pex03_mem_bs_tag,
509 	    armadaxp_pex10_io_bs_tag, armadaxp_pex10_mem_bs_tag,
510 	    armadaxp_pex2_io_bs_tag, armadaxp_pex2_mem_bs_tag,
511 	    armadaxp_pex3_io_bs_tag, armadaxp_pex3_mem_bs_tag;
512 	extern struct arm32_pci_chipset arm32_mvpex0_chipset,
513 	    arm32_mvpex1_chipset, arm32_mvpex2_chipset,
514 	    arm32_mvpex3_chipset, arm32_mvpex4_chipset,
515 	    arm32_mvpex5_chipset, arm32_mvpex6_chipset;
516 
517 	struct marvell_attach_args *mva = aux;
518 
519 	if (device_is_a(dev, "mvpex")) {
520 		struct bus_space *mvpex_io_bs_tag, *mvpex_mem_bs_tag;
521 		struct arm32_pci_chipset *arm32_mvpex_chipset;
522 		prop_data_t io_bs_tag, mem_bs_tag, pc;
523 		uint64_t start, end;
524 		int iotag, memtag;
525 
526 		if (mva->mva_offset == MVSOC_PEX_BASE) {
527 			mvpex_io_bs_tag = &armadaxp_pex00_io_bs_tag;
528 			mvpex_mem_bs_tag = &armadaxp_pex00_mem_bs_tag;
529 			arm32_mvpex_chipset = &arm32_mvpex0_chipset;
530 			iotag = ARMADAXP_TAG_PEX00_IO;
531 			memtag = ARMADAXP_TAG_PEX00_MEM;
532 		} else if (mva->mva_offset == ARMADAXP_PEX01_BASE) {
533 			mvpex_io_bs_tag = &armadaxp_pex01_io_bs_tag;
534 			mvpex_mem_bs_tag = &armadaxp_pex01_mem_bs_tag;
535 			arm32_mvpex_chipset = &arm32_mvpex1_chipset;
536 			iotag = ARMADAXP_TAG_PEX01_IO;
537 			memtag = ARMADAXP_TAG_PEX01_MEM;
538 		} else if (mva->mva_offset == ARMADAXP_PEX02_BASE) {
539 			mvpex_io_bs_tag = &armadaxp_pex02_io_bs_tag;
540 			mvpex_mem_bs_tag = &armadaxp_pex02_mem_bs_tag;
541 			arm32_mvpex_chipset = &arm32_mvpex2_chipset;
542 			iotag = ARMADAXP_TAG_PEX02_IO;
543 			memtag = ARMADAXP_TAG_PEX02_MEM;
544 		} else if (mva->mva_offset == ARMADAXP_PEX03_BASE) {
545 			mvpex_io_bs_tag = &armadaxp_pex03_io_bs_tag;
546 			mvpex_mem_bs_tag = &armadaxp_pex03_mem_bs_tag;
547 			arm32_mvpex_chipset = &arm32_mvpex3_chipset;
548 			iotag = ARMADAXP_TAG_PEX03_IO;
549 			memtag = ARMADAXP_TAG_PEX03_MEM;
550 		} else if (mva->mva_offset == ARMADAXP_PEX10_BASE) {
551 			mvpex_io_bs_tag = &armadaxp_pex10_io_bs_tag;
552 			mvpex_mem_bs_tag = &armadaxp_pex10_mem_bs_tag;
553 			arm32_mvpex_chipset = &arm32_mvpex4_chipset;
554 			iotag = ARMADAXP_TAG_PEX10_IO;
555 			memtag = ARMADAXP_TAG_PEX10_MEM;
556 		} else if (mva->mva_offset == ARMADAXP_PEX2_BASE) {
557 			mvpex_io_bs_tag = &armadaxp_pex2_io_bs_tag;
558 			mvpex_mem_bs_tag = &armadaxp_pex2_mem_bs_tag;
559 			arm32_mvpex_chipset = &arm32_mvpex5_chipset;
560 			iotag = ARMADAXP_TAG_PEX2_IO;
561 			memtag = ARMADAXP_TAG_PEX2_MEM;
562 		} else {
563 			mvpex_io_bs_tag = &armadaxp_pex3_io_bs_tag;
564 			mvpex_mem_bs_tag = &armadaxp_pex3_mem_bs_tag;
565 			arm32_mvpex_chipset = &arm32_mvpex6_chipset;
566 			iotag = ARMADAXP_TAG_PEX3_IO;
567 			memtag = ARMADAXP_TAG_PEX3_MEM;
568 		}
569 
570 		arm32_mvpex_chipset->pc_conf_v = device_private(dev);
571 		arm32_mvpex_chipset->pc_intr_v = device_private(dev);
572 
573 		io_bs_tag = prop_data_create_data_nocopy(
574 		    mvpex_io_bs_tag, sizeof(struct bus_space));
575 		KASSERT(io_bs_tag != NULL);
576 		prop_dictionary_set(dict, "io-bus-tag", io_bs_tag);
577 		prop_object_release(io_bs_tag);
578 		mem_bs_tag = prop_data_create_data_nocopy(
579 		    mvpex_mem_bs_tag, sizeof(struct bus_space));
580 		KASSERT(mem_bs_tag != NULL);
581 		prop_dictionary_set(dict, "mem-bus-tag", mem_bs_tag);
582 		prop_object_release(mem_bs_tag);
583 
584 		pc = prop_data_create_data_nocopy(arm32_mvpex_chipset,
585 		    sizeof(struct arm32_pci_chipset));
586 		KASSERT(pc != NULL);
587 		prop_dictionary_set(dict, "pci-chipset", pc);
588 		prop_object_release(pc);
589 
590 		marvell_startend_by_tag(iotag, &start, &end);
591 		prop_dictionary_set_uint64(dict, "iostart", start);
592 		prop_dictionary_set_uint64(dict, "ioend", end);
593 		marvell_startend_by_tag(memtag, &start, &end);
594 		prop_dictionary_set_uint64(dict, "memstart", start);
595 		prop_dictionary_set_uint64(dict, "memend", end);
596 		prop_dictionary_set_uint32(dict,
597 		    "cache-line-size", arm_dcache_align);
598 	}
599 	if (device_is_a(dev, "mvgbec")) {
600 		uint8_t enaddr[ETHER_ADDR_LEN];
601 		char optname[9];
602 		int unit = device_unit(dev);
603 
604 		if (unit > 9)
605 			return;
606 		switch (unit) {
607 		case 0:
608 			strlcpy(optname, "ethaddr", sizeof(optname));
609 			break;
610 		default:
611 			/* eth1addr ... eth9addr */
612 			snprintf(optname, sizeof(optname),
613 			    "eth%daddr", unit);
614 			break;
615 		}
616 		if (get_bootconf_option(boot_args, optname,
617 		    BOOTOPT_TYPE_MACADDR, enaddr)) {
618 			prop_data_t pd =
619 			    prop_data_create_data(enaddr, sizeof(enaddr));
620 
621 			prop_dictionary_set(dict, "mac-address", pd);
622 		}
623 	}
624 	if (device_is_a(dev, "mvxpe")) {
625 		uint8_t enaddr[ETHER_ADDR_LEN];
626 		char optname[9];
627 		int unit = device_unit(dev);
628 
629 		if (unit > 9)
630 			return;
631 		switch (unit) {
632 		case 0:
633 			strlcpy(optname, "ethaddr", sizeof(optname));
634 			break;
635 		default:
636 			/* eth1addr ... eth9addr */
637 			snprintf(optname, sizeof(optname),
638 			    "eth%daddr", unit);
639 			break;
640 		}
641 		if (get_bootconf_option(boot_args, optname,
642 		    BOOTOPT_TYPE_MACADDR, enaddr)) {
643 			prop_data_t pd =
644 			    prop_data_create_data(enaddr, sizeof(enaddr));
645 
646 			prop_dictionary_set(dict, "mac-address", pd);
647 		}
648 	}
649 #endif
650 }
651