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