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