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