Home | History | Annotate | Line # | Download | only in armadaxp
      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
    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 *
    198 read_ttb(void)
    199 {
    200 	return (pd_entry_t *)(armreg_ttbr_read() & ~((1<<14)-1));
    201 }
    202 
    203 static int
    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
    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
    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
    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
    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
    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
    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