xref: /netbsd-src/sys/arch/evbarm/armadaxp/armadaxp_machdep.c (revision 4d342c046e3288fb5a1edcd33cfec48c41c80664)
1 /*	$NetBSD: armadaxp_machdep.c,v 1.17 2019/07/16 14:41:44 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.17 2019/07/16 14:41:44 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
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 #define	_A(a)	((a) & ~L1_S_OFFSET)
191 #define	_S(s)	(((s) + L1_S_SIZE - 1) & ~(L1_S_SIZE-1))
192 
193 static const struct pmap_devmap devmap[] = {
194 	{
195 		/* Internal registers */
196 		.pd_va = _A(MARVELL_INTERREGS_VBASE),
197 		.pd_pa = _A(MARVELL_INTERREGS_PBASE),
198 		.pd_size = _S(MVSOC_INTERREGS_SIZE),
199 		.pd_prot = VM_PROT_READ|VM_PROT_WRITE,
200 		.pd_cache = PTE_NOCACHE
201 	},
202 	{0, 0, 0, 0, 0}
203 };
204 
205 #undef	_A
206 #undef	_S
207 
208 static inline pd_entry_t *
209 read_ttb(void)
210 {
211 	return (pd_entry_t *)(armreg_ttbr_read() & ~((1<<14)-1));
212 }
213 
214 static int
215 axp_pcie_free_win(void)
216 {
217 	/* Find first disabled window */
218 	for (size_t i = 0; i < ARMADAXP_MLMB_NWINDOW; i++) {
219 		if ((read_mlmbreg(MVSOC_MLMB_WCR(i)) &
220 		    MVSOC_MLMB_WCR_WINEN) == 0) {
221 			return i;
222 		}
223 	}
224 	/* If there is no free window, return erroneous value */
225 	return (-1);
226 }
227 
228 static void
229 reset_axp_pcie_win(void)
230 {
231 	uint32_t target, attr;
232 	int memtag = 0, iotag = 0, window, i;
233 	uint32_t membase;
234 	uint32_t iobase;
235 	uint32_t tags[] = { ARMADAXP_TAG_PEX00_MEM, ARMADAXP_TAG_PEX00_IO,
236 			    ARMADAXP_TAG_PEX01_MEM, ARMADAXP_TAG_PEX01_IO,
237 			    ARMADAXP_TAG_PEX02_MEM, ARMADAXP_TAG_PEX02_IO,
238 			    ARMADAXP_TAG_PEX03_MEM, ARMADAXP_TAG_PEX03_IO,
239 			    ARMADAXP_TAG_PEX10_MEM, ARMADAXP_TAG_PEX10_IO,
240 			    ARMADAXP_TAG_PEX11_MEM, ARMADAXP_TAG_PEX11_IO,
241 			    ARMADAXP_TAG_PEX12_MEM, ARMADAXP_TAG_PEX12_IO,
242 			    ARMADAXP_TAG_PEX13_MEM, ARMADAXP_TAG_PEX13_IO,
243 			    ARMADAXP_TAG_PEX2_MEM, ARMADAXP_TAG_PEX2_IO,
244 			    ARMADAXP_TAG_PEX3_MEM, ARMADAXP_TAG_PEX3_IO
245 			};
246 
247 	nwindow = ARMADAXP_MLMB_NWINDOW;
248 	nremap = ARMADAXP_MLMB_NREMAP;
249 	membase = MARVELL_PEXMEM_PBASE;
250 	iobase = MARVELL_PEXIO_PBASE;
251 	for (i = 0; i < __arraycount(tags) / 2; i++) {
252 		memtag = tags[2 * i];
253 		iotag = tags[(2 * i) + 1];
254 
255 		/* Reset PCI-Express space to window register. */
256 		window = mvsoc_target(memtag, &target, &attr, NULL, NULL);
257 
258 		/* Find free window if we've got spurious one */
259 		if (window >= nwindow) {
260 			window = axp_pcie_free_win();
261 			/* Just break if there is no free windows left */
262 			if (window < 0) {
263 				aprint_error(": no free windows for PEX MEM\n");
264 				break;
265 			}
266 		}
267 		write_mlmbreg(MVSOC_MLMB_WCR(window),
268 		    MVSOC_MLMB_WCR_WINEN |
269 		    MVSOC_MLMB_WCR_TARGET(target) |
270 		    MVSOC_MLMB_WCR_ATTR(attr) |
271 		    MVSOC_MLMB_WCR_SIZE(MARVELL_PEXMEM_SIZE));
272 		write_mlmbreg(MVSOC_MLMB_WBR(window),
273 		    membase & MVSOC_MLMB_WBR_BASE_MASK);
274 #ifdef PCI_NETBSD_CONFIGURE
275 		if (window < nremap) {
276 			write_mlmbreg(MVSOC_MLMB_WRLR(window),
277 			    membase & MVSOC_MLMB_WRLR_REMAP_MASK);
278 			write_mlmbreg(MVSOC_MLMB_WRHR(window), 0);
279 		}
280 #endif
281 		window = mvsoc_target(iotag, &target, &attr, NULL, NULL);
282 
283 		/* Find free window if we've got spurious one */
284 		if (window >= nwindow) {
285 			window = axp_pcie_free_win();
286 			/* Just break if there is no free windows left */
287 			if (window < 0) {
288 				aprint_error(": no free windows for PEX I/O\n");
289 				break;
290 			}
291 		}
292 		write_mlmbreg(MVSOC_MLMB_WCR(window),
293 		    MVSOC_MLMB_WCR_WINEN |
294 		    MVSOC_MLMB_WCR_TARGET(target) |
295 		    MVSOC_MLMB_WCR_ATTR(attr) |
296 		    MVSOC_MLMB_WCR_SIZE(MARVELL_PEXIO_SIZE));
297 		write_mlmbreg(MVSOC_MLMB_WBR(window),
298 		    iobase & MVSOC_MLMB_WBR_BASE_MASK);
299 #ifdef PCI_NETBSD_CONFIGURE
300 		if (window < nremap) {
301 			write_mlmbreg(MVSOC_MLMB_WRLR(window),
302 			    iobase & MVSOC_MLMB_WRLR_REMAP_MASK);
303 			write_mlmbreg(MVSOC_MLMB_WRHR(window), 0);
304 		}
305 #endif
306 		membase += MARVELL_PEXMEM_SIZE;
307 		iobase += MARVELL_PEXIO_SIZE;
308 	}
309 }
310 
311 /*
312  * vaddr_t initarm(...)
313  *
314  * Initial entry point on startup. This gets called before main() is
315  * entered.
316  * It should be responsible for setting up everything that must be
317  * in place when main is called.
318  * This includes
319  *   Taking a copy of the boot configuration structure.
320  *   Initialising the physical console so characters can be printed.
321  *   Setting up page tables for the kernel
322  *   Relocating the kernel to the bottom of physical memory
323  */
324 vaddr_t
325 initarm(void *arg)
326 {
327 	cpu_reset_address = axp_system_reset;
328 
329 	mvsoc_bootstrap(MARVELL_INTERREGS_VBASE);
330 
331 	/* Set CPU functions */
332 	if (set_cpufuncs())
333 		panic("cpu not recognized!");
334 
335 	/*
336 	 * Map devices into the initial page table
337 	 * in order to use early console during initialization process.
338 	 * consinit is going to use this mapping.
339 	 */
340 	pmap_devmap_bootstrap((vaddr_t)read_ttb(), devmap);
341 
342 	/* Initialize system console */
343 	consinit();
344 
345 	/* Reset PCI-Express space to window register. */
346 	reset_axp_pcie_win();
347 
348 	/* Get CPU, system and timebase frequencies */
349 	armadaxp_bootstrap(
350 	    MARVELL_INTERREGS_VBASE,
351 	    MARVELL_INTERREGS_PBASE);
352 
353 #ifdef KGDB
354 	kgdb_port_init();
355 #endif
356 
357 #ifdef VERBOSE_INIT_ARM
358 	/* Talk to the user */
359 #define	BDSTR(s)	_BDSTR(s)
360 #define	_BDSTR(s)	#s
361 	printf("\nNetBSD/evbarm (" BDSTR(EVBARM_BOARDTYPE) ") booting ...\n");
362 #endif
363 
364 #ifdef __HAVE_MM_MD_DIRECT_MAPPED_PHYS
365 	const bool mapallmem_p = true;
366 #else
367 	const bool mapallmem_p = false;
368 #endif
369 
370 #ifdef VERBOSE_INIT_ARM
371 	printf("initarm: Configuring system ...\n");
372 #endif
373 	psize_t memsize = MEMSIZE;
374 	if (mapallmem_p && memsize > KERNEL_VM_BASE - KERNEL_BASE) {
375 		printf("%s: dropping RAM size from %luMB to %uMB\n",
376 		    __func__, (unsigned long) (memsize >> 20),
377 		    (KERNEL_VM_BASE - KERNEL_BASE) >> 20);
378 		memsize = KERNEL_VM_BASE - KERNEL_BASE;
379 	}
380 	/* Fake bootconfig structure for the benefit of pmap.c. */
381 	bootconfig.dramblocks = 1;
382 	bootconfig.dram[0].address = MEMSTART;
383 	bootconfig.dram[0].pages = memsize / PAGE_SIZE;
384 
385         physical_start = bootconfig.dram[0].address;
386         physical_end = physical_start + (bootconfig.dram[0].pages * PAGE_SIZE);
387 
388 	arm32_bootmem_init(0, physical_end, (uintptr_t) KERNEL_BASE_phys);
389 	arm32_kernel_vm_init(KERNEL_VM_BASE, ARM_VECTORS_LOW, 0,
390 	    devmap, mapallmem_p);
391 
392 	/* we've a specific device_register routine */
393 	evbarm_device_register = axp_device_register;
394 
395 	/* copy U-Boot args from U-Boot heap to kernel memory */
396 	uboot_regs_va = (int *)((unsigned int)uboot_regs_pa + KERNEL_BASE);
397 	boot_args = (char *)(uboot_regs_va[3] + KERNEL_BASE);
398 	strlcpy(boot_argbuf, (char *)boot_args, sizeof(boot_argbuf));
399 	boot_args = boot_argbuf;
400 	parse_mi_bootargs(boot_args);
401 
402 	return initarm_common(KERNEL_VM_BASE, KERNEL_VM_SIZE, NULL, 0);
403 }
404 
405 #ifndef CONSADDR
406 #error Specify the address of the UART with the CONSADDR option.
407 #endif
408 #ifndef CONSPEED
409 #define	CONSPEED B115200
410 #endif
411 #ifndef CONMODE
412 #define	CONMODE ((TTYDEF_CFLAG & ~(CSIZE | CSTOPB | PARENB)) | CS8) /* 8N1 */
413 #endif
414 #ifndef CONSFREQ
415 #define	CONSFREQ 0
416 #endif
417 static const int	comcnspeed = CONSPEED;
418 static const int	comcnfreq  = CONSFREQ;
419 static const tcflag_t	comcnmode  = CONMODE;
420 static const bus_addr_t	comcnaddr  = (bus_addr_t)CONSADDR;
421 
422 void
423 consinit(void)
424 {
425 	static bool consinit_called = false;
426 
427 	if (consinit_called)
428 		return;
429 	consinit_called = true;
430 
431 #if NCOM > 0
432 	extern int mvuart_cnattach(bus_space_tag_t, bus_addr_t, int,
433 	    uint32_t, int);
434 
435 	if (mvuart_cnattach(&mvsoc_bs_tag, comcnaddr, comcnspeed,
436 			comcnfreq ? comcnfreq : mvTclk , comcnmode))
437 		panic("Serial console can not be initialized.");
438 #endif
439 }
440 
441 #ifdef KGDB
442 #ifndef KGDB_DEVADDR
443 #error Specify the address of the kgdb UART with the KGDB_DEVADDR option.
444 #endif
445 #ifndef KGDB_DEVRATE
446 #define KGDB_DEVRATE B115200
447 #endif
448 #define MVUART_SIZE 0x20
449 
450 #ifndef KGDB_DEVMODE
451 #define KGDB_DEVMODE ((TTYDEF_CFLAG & ~(CSIZE | CSTOPB | PARENB)) | CS8) /* 8N1 */
452 #endif
453 static const vaddr_t comkgdbaddr = KGDB_DEVADDR;
454 static const int comkgdbspeed = KGDB_DEVRATE;
455 static const int comkgdbmode = KGDB_DEVMODE;
456 
457 void
458 static kgdb_port_init(void)
459 {
460 	static int kgdbsinit_called = 0;
461 
462 	if (kgdbsinit_called != 0)
463 		return;
464 	kgdbsinit_called = 1;
465 
466 	if (com_kgdb_attach(&mvsoc_bs_tag, comkgdbaddr, comkgdbspeed,
467 			MVUART_SIZE, COM_TYPE_16550_NOERS, comkgdbmode))
468 		panic("KGDB uart can not be initialized.");
469 }
470 #endif
471 
472 #if NMVPEX > 0
473 static void
474 marvell_startend_by_tag(int tag, uint64_t *start, uint64_t *end)
475 {
476 
477 	uint32_t base, size;
478 	int win;
479 
480 	win = mvsoc_target(tag, NULL, NULL, &base, &size);
481 	if (size != 0) {
482 		if (win < nremap)
483 			*start = read_mlmbreg(MVSOC_MLMB_WRLR(win)) |
484 			    ((read_mlmbreg(MVSOC_MLMB_WRHR(win)) << 16) << 16);
485 		else
486 			*start = base;
487 		*end = *start + size - 1;
488 	} else
489 		*start = *end = 0;
490 }
491 #endif
492 
493 static void
494 axp_device_register(device_t dev, void *aux)
495 {
496 	prop_dictionary_t dict = device_properties(dev);
497 
498 #if NCOM > 0
499 	if (device_is_a(dev, "com") &&
500 	    device_is_a(device_parent(dev), "mvsoc"))
501 		prop_dictionary_set_uint32(dict, "frequency", mvTclk);
502 #endif
503 
504 #if NMVPEX > 0
505 	extern struct bus_space
506 	    armadaxp_pex00_io_bs_tag, armadaxp_pex00_mem_bs_tag,
507 	    armadaxp_pex01_io_bs_tag, armadaxp_pex01_mem_bs_tag,
508 	    armadaxp_pex02_io_bs_tag, armadaxp_pex02_mem_bs_tag,
509 	    armadaxp_pex03_io_bs_tag, armadaxp_pex03_mem_bs_tag,
510 	    armadaxp_pex10_io_bs_tag, armadaxp_pex10_mem_bs_tag,
511 	    armadaxp_pex2_io_bs_tag, armadaxp_pex2_mem_bs_tag,
512 	    armadaxp_pex3_io_bs_tag, armadaxp_pex3_mem_bs_tag;
513 	extern struct arm32_pci_chipset arm32_mvpex0_chipset,
514 	    arm32_mvpex1_chipset, arm32_mvpex2_chipset,
515 	    arm32_mvpex3_chipset, arm32_mvpex4_chipset,
516 	    arm32_mvpex5_chipset, arm32_mvpex6_chipset;
517 
518 	struct marvell_attach_args *mva = aux;
519 
520 	if (device_is_a(dev, "mvpex")) {
521 		struct bus_space *mvpex_io_bs_tag, *mvpex_mem_bs_tag;
522 		struct arm32_pci_chipset *arm32_mvpex_chipset;
523 		prop_data_t io_bs_tag, mem_bs_tag, pc;
524 		uint64_t start, end;
525 		int iotag, memtag;
526 
527 		if (mva->mva_offset == MVSOC_PEX_BASE) {
528 			mvpex_io_bs_tag = &armadaxp_pex00_io_bs_tag;
529 			mvpex_mem_bs_tag = &armadaxp_pex00_mem_bs_tag;
530 			arm32_mvpex_chipset = &arm32_mvpex0_chipset;
531 			iotag = ARMADAXP_TAG_PEX00_IO;
532 			memtag = ARMADAXP_TAG_PEX00_MEM;
533 		} else if (mva->mva_offset == ARMADAXP_PEX01_BASE) {
534 			mvpex_io_bs_tag = &armadaxp_pex01_io_bs_tag;
535 			mvpex_mem_bs_tag = &armadaxp_pex01_mem_bs_tag;
536 			arm32_mvpex_chipset = &arm32_mvpex1_chipset;
537 			iotag = ARMADAXP_TAG_PEX01_IO;
538 			memtag = ARMADAXP_TAG_PEX01_MEM;
539 		} else if (mva->mva_offset == ARMADAXP_PEX02_BASE) {
540 			mvpex_io_bs_tag = &armadaxp_pex02_io_bs_tag;
541 			mvpex_mem_bs_tag = &armadaxp_pex02_mem_bs_tag;
542 			arm32_mvpex_chipset = &arm32_mvpex2_chipset;
543 			iotag = ARMADAXP_TAG_PEX02_IO;
544 			memtag = ARMADAXP_TAG_PEX02_MEM;
545 		} else if (mva->mva_offset == ARMADAXP_PEX03_BASE) {
546 			mvpex_io_bs_tag = &armadaxp_pex03_io_bs_tag;
547 			mvpex_mem_bs_tag = &armadaxp_pex03_mem_bs_tag;
548 			arm32_mvpex_chipset = &arm32_mvpex3_chipset;
549 			iotag = ARMADAXP_TAG_PEX03_IO;
550 			memtag = ARMADAXP_TAG_PEX03_MEM;
551 		} else if (mva->mva_offset == ARMADAXP_PEX10_BASE) {
552 			mvpex_io_bs_tag = &armadaxp_pex10_io_bs_tag;
553 			mvpex_mem_bs_tag = &armadaxp_pex10_mem_bs_tag;
554 			arm32_mvpex_chipset = &arm32_mvpex4_chipset;
555 			iotag = ARMADAXP_TAG_PEX10_IO;
556 			memtag = ARMADAXP_TAG_PEX10_MEM;
557 		} else if (mva->mva_offset == ARMADAXP_PEX2_BASE) {
558 			mvpex_io_bs_tag = &armadaxp_pex2_io_bs_tag;
559 			mvpex_mem_bs_tag = &armadaxp_pex2_mem_bs_tag;
560 			arm32_mvpex_chipset = &arm32_mvpex5_chipset;
561 			iotag = ARMADAXP_TAG_PEX2_IO;
562 			memtag = ARMADAXP_TAG_PEX2_MEM;
563 		} else {
564 			mvpex_io_bs_tag = &armadaxp_pex3_io_bs_tag;
565 			mvpex_mem_bs_tag = &armadaxp_pex3_mem_bs_tag;
566 			arm32_mvpex_chipset = &arm32_mvpex6_chipset;
567 			iotag = ARMADAXP_TAG_PEX3_IO;
568 			memtag = ARMADAXP_TAG_PEX3_MEM;
569 		}
570 
571 		arm32_mvpex_chipset->pc_conf_v = device_private(dev);
572 		arm32_mvpex_chipset->pc_intr_v = device_private(dev);
573 
574 		io_bs_tag = prop_data_create_data_nocopy(
575 		    mvpex_io_bs_tag, sizeof(struct bus_space));
576 		KASSERT(io_bs_tag != NULL);
577 		prop_dictionary_set(dict, "io-bus-tag", io_bs_tag);
578 		prop_object_release(io_bs_tag);
579 		mem_bs_tag = prop_data_create_data_nocopy(
580 		    mvpex_mem_bs_tag, sizeof(struct bus_space));
581 		KASSERT(mem_bs_tag != NULL);
582 		prop_dictionary_set(dict, "mem-bus-tag", mem_bs_tag);
583 		prop_object_release(mem_bs_tag);
584 
585 		pc = prop_data_create_data_nocopy(arm32_mvpex_chipset,
586 		    sizeof(struct arm32_pci_chipset));
587 		KASSERT(pc != NULL);
588 		prop_dictionary_set(dict, "pci-chipset", pc);
589 		prop_object_release(pc);
590 
591 		marvell_startend_by_tag(iotag, &start, &end);
592 		prop_dictionary_set_uint64(dict, "iostart", start);
593 		prop_dictionary_set_uint64(dict, "ioend", end);
594 		marvell_startend_by_tag(memtag, &start, &end);
595 		prop_dictionary_set_uint64(dict, "memstart", start);
596 		prop_dictionary_set_uint64(dict, "memend", end);
597 		prop_dictionary_set_uint32(dict,
598 		    "cache-line-size", arm_dcache_align);
599 	}
600 	if (device_is_a(dev, "mvgbec")) {
601 		uint8_t enaddr[ETHER_ADDR_LEN];
602 		char optname[9];
603 		int unit = device_unit(dev);
604 
605 		if (unit > 9)
606 			return;
607 		switch (unit) {
608 		case 0:
609 			strlcpy(optname, "ethaddr", sizeof(optname));
610 			break;
611 		default:
612 			/* eth1addr ... eth9addr */
613 			snprintf(optname, sizeof(optname),
614 			    "eth%daddr", unit);
615 			break;
616 		}
617 		if (get_bootconf_option(boot_args, optname,
618 		    BOOTOPT_TYPE_MACADDR, enaddr)) {
619 			prop_data_t pd =
620 			    prop_data_create_data(enaddr, sizeof(enaddr));
621 
622 			prop_dictionary_set(dict, "mac-address", pd);
623 		}
624 	}
625 	if (device_is_a(dev, "mvxpe")) {
626 		uint8_t enaddr[ETHER_ADDR_LEN];
627 		char optname[9];
628 		int unit = device_unit(dev);
629 
630 		if (unit > 9)
631 			return;
632 		switch (unit) {
633 		case 0:
634 			strlcpy(optname, "ethaddr", sizeof(optname));
635 			break;
636 		default:
637 			/* eth1addr ... eth9addr */
638 			snprintf(optname, sizeof(optname),
639 			    "eth%daddr", unit);
640 			break;
641 		}
642 		if (get_bootconf_option(boot_args, optname,
643 		    BOOTOPT_TYPE_MACADDR, enaddr)) {
644 			prop_data_t pd =
645 			    prop_data_create_data(enaddr, sizeof(enaddr));
646 
647 			prop_dictionary_set(dict, "mac-address", pd);
648 		}
649 	}
650 #endif
651 }
652