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