Home | History | Annotate | Line # | Download | only in armadaxp
armadaxp_machdep.c revision 1.13.12.1
      1 /*	$NetBSD: armadaxp_machdep.c,v 1.13.12.1 2018/07/28 04:37:30 pgoyette 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.13.12.1 2018/07/28 04:37:30 pgoyette 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 
     50 #include <sys/bus.h>
     51 #include <sys/param.h>
     52 #include <sys/device.h>
     53 #include <sys/systm.h>
     54 #include <sys/kernel.h>
     55 #include <sys/exec.h>
     56 #include <sys/proc.h>
     57 #include <sys/msgbuf.h>
     58 #include <sys/reboot.h>
     59 #include <sys/termios.h>
     60 #include <sys/ksyms.h>
     61 
     62 #include <uvm/uvm_extern.h>
     63 
     64 #include <sys/conf.h>
     65 #include <dev/cons.h>
     66 #include <dev/md.h>
     67 
     68 #include <dev/marvell/marvellreg.h>
     69 #include <dev/pci/pcireg.h>
     70 #include <dev/pci/pcivar.h>
     71 #include <machine/pci_machdep.h>
     72 
     73 #include <machine/db_machdep.h>
     74 #include <ddb/db_sym.h>
     75 #include <ddb/db_extern.h>
     76 #ifdef KGDB
     77 #include <sys/kgdb.h>
     78 #endif
     79 
     80 #include <machine/bootconfig.h>
     81 #include <machine/autoconf.h>
     82 #include <machine/cpu.h>
     83 #include <machine/frame.h>
     84 #include <arm/armreg.h>
     85 #include <arm/undefined.h>
     86 
     87 #include <arm/arm32/machdep.h>
     88 
     89 #include <arm/marvell/mvsocreg.h>
     90 #include <arm/marvell/mvsocvar.h>
     91 #include <arm/marvell/armadaxpreg.h>
     92 
     93 #include <evbarm/marvell/marvellreg.h>
     94 #include <evbarm/marvell/marvellvar.h>
     95 #include <dev/marvell/marvellreg.h>
     96 
     97 #include "mvpex.h"
     98 #include "com.h"
     99 #if NCOM > 0
    100 #include <dev/ic/comreg.h>
    101 #include <dev/ic/comvar.h>
    102 #endif
    103 
    104 #include <net/if_ether.h>
    105 
    106 /*
    107  * Address to call from cpu_reset() to reset the machine.
    108  * This is machine architecture dependent as it varies depending
    109  * on where the ROM appears when you turn the MMU off.
    110  */
    111 
    112 BootConfig bootconfig;		/* Boot config storage */
    113 char *boot_args = NULL;
    114 char *boot_file = NULL;
    115 
    116 /*
    117  * U-Boot argument buffer
    118  */
    119 extern unsigned int uboot_regs_pa[]; /* saved r0, r1, r2, r3 */
    120 unsigned int *uboot_regs_va;
    121 char boot_argbuf[MAX_BOOT_STRING];
    122 
    123 extern int KERNEL_BASE_phys[];
    124 
    125 /*
    126  * Put some bogus settings of the MEMSTART and MEMSIZE
    127  * if they are not defined in kernel configuration file.
    128  */
    129 #ifndef MEMSTART
    130 #define MEMSTART 0x00000000UL
    131 #endif
    132 #ifndef MEMSIZE
    133 #define MEMSIZE 0x40000000UL
    134 #endif
    135 
    136 #ifndef STARTUP_PAGETABLE_ADDR
    137 #define	STARTUP_PAGETABLE_ADDR 0x00000000UL
    138 #endif
    139 
    140 /* Physical offset of the kernel from MEMSTART */
    141 #define KERNEL_OFFSET		(paddr_t)&KERNEL_BASE_phys
    142 /* Kernel base virtual address */
    143 #define	KERNEL_TEXT_BASE	(KERNEL_BASE + KERNEL_OFFSET)
    144 
    145 #define	KERNEL_VM_BASE		(KERNEL_BASE + 0x40000000)
    146 #define KERNEL_VM_SIZE		0x14000000
    147 
    148 void consinit(void);
    149 #ifdef KGDB
    150 static void kgdb_port_init(void);
    151 #endif
    152 
    153 static void axp_device_register(device_t dev, void *aux);
    154 
    155 static void
    156 axp_system_reset(void)
    157 {
    158 	extern vaddr_t misc_base;
    159 
    160 #define write_miscreg(r, v)	(*(volatile uint32_t *)(misc_base + (r)) = (v))
    161 
    162 	cpu_reset_address = 0;
    163 
    164 	/* Unmask soft reset */
    165 	write_miscreg(ARMADAXP_MISC_RSTOUTNMASKR,
    166 	    ARMADAXP_MISC_RSTOUTNMASKR_GLOBALSOFTRSTOUTEN);
    167 	/* Assert soft reset */
    168 	write_miscreg(ARMADAXP_MISC_SSRR, ARMADAXP_MISC_SSRR_GLOBALSOFTRST);
    169 
    170 	while (1);
    171 }
    172 
    173 /*
    174  * Static device mappings. These peripheral registers are mapped at
    175  * fixed virtual addresses very early in initarm() so that we can use
    176  * them while booting the kernel, and stay at the same address
    177  * throughout whole kernel's life time.
    178  *
    179  * We use this table twice; once with bootstrap page table, and once
    180  * with kernel's page table which we build up in initarm().
    181  *
    182  * Since we map these registers into the bootstrap page table using
    183  * pmap_devmap_bootstrap() which calls pmap_map_chunk(), we map
    184  * registers segment-aligned and segment-rounded in order to avoid
    185  * using the 2nd page tables.
    186  */
    187 
    188 #define	_A(a)	((a) & ~L1_S_OFFSET)
    189 #define	_S(s)	(((s) + L1_S_SIZE - 1) & ~(L1_S_SIZE-1))
    190 
    191 static const struct pmap_devmap devmap[] = {
    192 	{
    193 		/* Internal registers */
    194 		.pd_va = _A(MARVELL_INTERREGS_VBASE),
    195 		.pd_pa = _A(MARVELL_INTERREGS_PBASE),
    196 		.pd_size = _S(MVSOC_INTERREGS_SIZE),
    197 		.pd_prot = VM_PROT_READ|VM_PROT_WRITE,
    198 		.pd_cache = PTE_NOCACHE
    199 	},
    200 	{0, 0, 0, 0, 0}
    201 };
    202 
    203 #undef	_A
    204 #undef	_S
    205 
    206 static inline pd_entry_t *
    207 read_ttb(void)
    208 {
    209 	return (pd_entry_t *)(armreg_ttbr_read() & ~((1<<14)-1));
    210 }
    211 
    212 static int
    213 axp_pcie_free_win(void)
    214 {
    215 	/* Find first disabled window */
    216 	for (size_t i = 0; i < ARMADAXP_MLMB_NWINDOW; i++) {
    217 		if ((read_mlmbreg(MVSOC_MLMB_WCR(i)) &
    218 		    MVSOC_MLMB_WCR_WINEN) == 0) {
    219 			return i;
    220 		}
    221 	}
    222 	/* If there is no free window, return erroneous value */
    223 	return (-1);
    224 }
    225 
    226 static void
    227 reset_axp_pcie_win(void)
    228 {
    229 	uint32_t target, attr;
    230 	int memtag = 0, iotag = 0, window, i;
    231 	uint32_t membase;
    232 	uint32_t iobase;
    233 	uint32_t tags[] = { ARMADAXP_TAG_PEX00_MEM, ARMADAXP_TAG_PEX00_IO,
    234 			    ARMADAXP_TAG_PEX01_MEM, ARMADAXP_TAG_PEX01_IO,
    235 			    ARMADAXP_TAG_PEX02_MEM, ARMADAXP_TAG_PEX02_IO,
    236 			    ARMADAXP_TAG_PEX03_MEM, ARMADAXP_TAG_PEX03_IO,
    237 			    ARMADAXP_TAG_PEX10_MEM, ARMADAXP_TAG_PEX10_IO,
    238 			    ARMADAXP_TAG_PEX11_MEM, ARMADAXP_TAG_PEX11_IO,
    239 			    ARMADAXP_TAG_PEX12_MEM, ARMADAXP_TAG_PEX12_IO,
    240 			    ARMADAXP_TAG_PEX13_MEM, ARMADAXP_TAG_PEX13_IO,
    241 			    ARMADAXP_TAG_PEX2_MEM, ARMADAXP_TAG_PEX2_IO,
    242 			    ARMADAXP_TAG_PEX3_MEM, ARMADAXP_TAG_PEX3_IO
    243 			};
    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 	armadaxp_bootstrap(
    348 	    MARVELL_INTERREGS_VBASE,
    349 	    MARVELL_INTERREGS_PBASE);
    350 
    351 #ifdef KGDB
    352 	kgdb_port_init();
    353 #endif
    354 
    355 #ifdef VERBOSE_INIT_ARM
    356 	/* Talk to the user */
    357 #define	BDSTR(s)	_BDSTR(s)
    358 #define	_BDSTR(s)	#s
    359 	printf("\nNetBSD/evbarm (" BDSTR(EVBARM_BOARDTYPE) ") booting ...\n");
    360 #endif
    361 
    362 #ifdef __HAVE_MM_MD_DIRECT_MAPPED_PHYS
    363 	const bool mapallmem_p = true;
    364 #else
    365 	const bool mapallmem_p = false;
    366 #endif
    367 
    368 #ifdef VERBOSE_INIT_ARM
    369 	printf("initarm: Configuring system ...\n");
    370 #endif
    371 	psize_t memsize = MEMSIZE;
    372 	if (mapallmem_p && memsize > KERNEL_VM_BASE - KERNEL_BASE) {
    373 		printf("%s: dropping RAM size from %luMB to %uMB\n",
    374 		    __func__, (unsigned long) (memsize >> 20),
    375 		    (KERNEL_VM_BASE - KERNEL_BASE) >> 20);
    376 		memsize = KERNEL_VM_BASE - KERNEL_BASE;
    377 	}
    378 	/* Fake bootconfig structure for the benefit of pmap.c. */
    379 	bootconfig.dramblocks = 1;
    380 	bootconfig.dram[0].address = MEMSTART;
    381 	bootconfig.dram[0].pages = memsize / PAGE_SIZE;
    382 
    383         physical_start = bootconfig.dram[0].address;
    384         physical_end = physical_start + (bootconfig.dram[0].pages * PAGE_SIZE);
    385 
    386 	arm32_bootmem_init(0, physical_end, (uintptr_t) KERNEL_BASE_phys);
    387 	arm32_kernel_vm_init(KERNEL_VM_BASE, ARM_VECTORS_LOW, 0,
    388 	    devmap, mapallmem_p);
    389 
    390 	/* we've a specific device_register routine */
    391 	evbarm_device_register = axp_device_register;
    392 
    393 	/* copy U-Boot args from U-Boot heap to kernel memory */
    394 	uboot_regs_va = (int *)((unsigned int)uboot_regs_pa + KERNEL_BASE);
    395 	boot_args = (char *)(uboot_regs_va[3] + KERNEL_BASE);
    396 	strlcpy(boot_argbuf, (char *)boot_args, sizeof(boot_argbuf));
    397 	boot_args = boot_argbuf;
    398 	parse_mi_bootargs(boot_args);
    399 
    400 	return initarm_common(KERNEL_VM_BASE, KERNEL_VM_SIZE, NULL, 0);
    401 }
    402 
    403 #ifndef CONSADDR
    404 #error Specify the address of the UART with the CONSADDR option.
    405 #endif
    406 #ifndef CONSPEED
    407 #define	CONSPEED B115200
    408 #endif
    409 #ifndef CONMODE
    410 #define	CONMODE ((TTYDEF_CFLAG & ~(CSIZE | CSTOPB | PARENB)) | CS8) /* 8N1 */
    411 #endif
    412 #ifndef CONSFREQ
    413 #define	CONSFREQ 0
    414 #endif
    415 static const int	comcnspeed = CONSPEED;
    416 static const int	comcnfreq  = CONSFREQ;
    417 static const tcflag_t	comcnmode  = CONMODE;
    418 static const bus_addr_t	comcnaddr  = (bus_addr_t)CONSADDR;
    419 
    420 void
    421 consinit(void)
    422 {
    423 	static bool consinit_called = false;
    424 
    425 	if (consinit_called)
    426 		return;
    427 	consinit_called = true;
    428 
    429 #if NCOM > 0
    430 	extern int mvuart_cnattach(bus_space_tag_t, bus_addr_t, int,
    431 	    uint32_t, int);
    432 
    433 	if (mvuart_cnattach(&mvsoc_bs_tag, comcnaddr, comcnspeed,
    434 			comcnfreq ? comcnfreq : mvTclk , comcnmode))
    435 		panic("Serial console can not be initialized.");
    436 #endif
    437 }
    438 
    439 #ifdef KGDB
    440 #ifndef KGDB_DEVADDR
    441 #error Specify the address of the kgdb UART with the KGDB_DEVADDR option.
    442 #endif
    443 #ifndef KGDB_DEVRATE
    444 #define KGDB_DEVRATE B115200
    445 #endif
    446 #define MVUART_SIZE 0x20
    447 
    448 #ifndef KGDB_DEVMODE
    449 #define KGDB_DEVMODE ((TTYDEF_CFLAG & ~(CSIZE | CSTOPB | PARENB)) | CS8) /* 8N1 */
    450 #endif
    451 static const vaddr_t comkgdbaddr = KGDB_DEVADDR;
    452 static const int comkgdbspeed = KGDB_DEVRATE;
    453 static const int comkgdbmode = KGDB_DEVMODE;
    454 
    455 void
    456 static kgdb_port_init(void)
    457 {
    458 	static int kgdbsinit_called = 0;
    459 
    460 	if (kgdbsinit_called != 0)
    461 		return;
    462 	kgdbsinit_called = 1;
    463 
    464 	if (com_kgdb_attach(&mvsoc_bs_tag, comkgdbaddr, comkgdbspeed,
    465 			MVUART_SIZE, COM_TYPE_16550_NOERS, comkgdbmode))
    466 		panic("KGDB uart can not be initialized.");
    467 }
    468 #endif
    469 
    470 #if NMVPEX > 0
    471 static void
    472 marvell_startend_by_tag(int tag, uint64_t *start, uint64_t *end)
    473 {
    474 
    475 	uint32_t base, size;
    476 	int win;
    477 
    478 	win = mvsoc_target(tag, NULL, NULL, &base, &size);
    479 	if (size != 0) {
    480 		if (win < nremap)
    481 			*start = read_mlmbreg(MVSOC_MLMB_WRLR(win)) |
    482 			    ((read_mlmbreg(MVSOC_MLMB_WRHR(win)) << 16) << 16);
    483 		else
    484 			*start = base;
    485 		*end = *start + size - 1;
    486 	} else
    487 		*start = *end = 0;
    488 }
    489 #endif
    490 
    491 static void
    492 axp_device_register(device_t dev, void *aux)
    493 {
    494 	prop_dictionary_t dict = device_properties(dev);
    495 
    496 #if NCOM > 0
    497 	if (device_is_a(dev, "com") &&
    498 	    device_is_a(device_parent(dev), "mvsoc"))
    499 		prop_dictionary_set_uint32(dict, "frequency", mvTclk);
    500 #endif
    501 
    502 #if NMVPEX > 0
    503 	extern struct bus_space
    504 	    armadaxp_pex00_io_bs_tag, armadaxp_pex00_mem_bs_tag,
    505 	    armadaxp_pex01_io_bs_tag, armadaxp_pex01_mem_bs_tag,
    506 	    armadaxp_pex02_io_bs_tag, armadaxp_pex02_mem_bs_tag,
    507 	    armadaxp_pex03_io_bs_tag, armadaxp_pex03_mem_bs_tag,
    508 	    armadaxp_pex10_io_bs_tag, armadaxp_pex10_mem_bs_tag,
    509 	    armadaxp_pex2_io_bs_tag, armadaxp_pex2_mem_bs_tag,
    510 	    armadaxp_pex3_io_bs_tag, armadaxp_pex3_mem_bs_tag;
    511 	extern struct arm32_pci_chipset arm32_mvpex0_chipset,
    512 	    arm32_mvpex1_chipset, arm32_mvpex2_chipset,
    513 	    arm32_mvpex3_chipset, arm32_mvpex4_chipset,
    514 	    arm32_mvpex5_chipset, arm32_mvpex6_chipset;
    515 
    516 	struct marvell_attach_args *mva = aux;
    517 
    518 	if (device_is_a(dev, "mvpex")) {
    519 		struct bus_space *mvpex_io_bs_tag, *mvpex_mem_bs_tag;
    520 		struct arm32_pci_chipset *arm32_mvpex_chipset;
    521 		prop_data_t io_bs_tag, mem_bs_tag, pc;
    522 		uint64_t start, end;
    523 		int iotag, memtag;
    524 
    525 		if (mva->mva_offset == MVSOC_PEX_BASE) {
    526 			mvpex_io_bs_tag = &armadaxp_pex00_io_bs_tag;
    527 			mvpex_mem_bs_tag = &armadaxp_pex00_mem_bs_tag;
    528 			arm32_mvpex_chipset = &arm32_mvpex0_chipset;
    529 			iotag = ARMADAXP_TAG_PEX00_IO;
    530 			memtag = ARMADAXP_TAG_PEX00_MEM;
    531 		} else if (mva->mva_offset == ARMADAXP_PEX01_BASE) {
    532 			mvpex_io_bs_tag = &armadaxp_pex01_io_bs_tag;
    533 			mvpex_mem_bs_tag = &armadaxp_pex01_mem_bs_tag;
    534 			arm32_mvpex_chipset = &arm32_mvpex1_chipset;
    535 			iotag = ARMADAXP_TAG_PEX01_IO;
    536 			memtag = ARMADAXP_TAG_PEX01_MEM;
    537 		} else if (mva->mva_offset == ARMADAXP_PEX02_BASE) {
    538 			mvpex_io_bs_tag = &armadaxp_pex02_io_bs_tag;
    539 			mvpex_mem_bs_tag = &armadaxp_pex02_mem_bs_tag;
    540 			arm32_mvpex_chipset = &arm32_mvpex2_chipset;
    541 			iotag = ARMADAXP_TAG_PEX02_IO;
    542 			memtag = ARMADAXP_TAG_PEX02_MEM;
    543 		} else if (mva->mva_offset == ARMADAXP_PEX03_BASE) {
    544 			mvpex_io_bs_tag = &armadaxp_pex03_io_bs_tag;
    545 			mvpex_mem_bs_tag = &armadaxp_pex03_mem_bs_tag;
    546 			arm32_mvpex_chipset = &arm32_mvpex3_chipset;
    547 			iotag = ARMADAXP_TAG_PEX03_IO;
    548 			memtag = ARMADAXP_TAG_PEX03_MEM;
    549 		} else if (mva->mva_offset == ARMADAXP_PEX10_BASE) {
    550 			mvpex_io_bs_tag = &armadaxp_pex10_io_bs_tag;
    551 			mvpex_mem_bs_tag = &armadaxp_pex10_mem_bs_tag;
    552 			arm32_mvpex_chipset = &arm32_mvpex4_chipset;
    553 			iotag = ARMADAXP_TAG_PEX10_IO;
    554 			memtag = ARMADAXP_TAG_PEX10_MEM;
    555 		} else if (mva->mva_offset == ARMADAXP_PEX2_BASE) {
    556 			mvpex_io_bs_tag = &armadaxp_pex2_io_bs_tag;
    557 			mvpex_mem_bs_tag = &armadaxp_pex2_mem_bs_tag;
    558 			arm32_mvpex_chipset = &arm32_mvpex5_chipset;
    559 			iotag = ARMADAXP_TAG_PEX2_IO;
    560 			memtag = ARMADAXP_TAG_PEX2_MEM;
    561 		} else {
    562 			mvpex_io_bs_tag = &armadaxp_pex3_io_bs_tag;
    563 			mvpex_mem_bs_tag = &armadaxp_pex3_mem_bs_tag;
    564 			arm32_mvpex_chipset = &arm32_mvpex6_chipset;
    565 			iotag = ARMADAXP_TAG_PEX3_IO;
    566 			memtag = ARMADAXP_TAG_PEX3_MEM;
    567 		}
    568 
    569 		arm32_mvpex_chipset->pc_conf_v = device_private(dev);
    570 		arm32_mvpex_chipset->pc_intr_v = device_private(dev);
    571 
    572 		io_bs_tag = prop_data_create_data_nocopy(
    573 		    mvpex_io_bs_tag, sizeof(struct bus_space));
    574 		KASSERT(io_bs_tag != NULL);
    575 		prop_dictionary_set(dict, "io-bus-tag", io_bs_tag);
    576 		prop_object_release(io_bs_tag);
    577 		mem_bs_tag = prop_data_create_data_nocopy(
    578 		    mvpex_mem_bs_tag, sizeof(struct bus_space));
    579 		KASSERT(mem_bs_tag != NULL);
    580 		prop_dictionary_set(dict, "mem-bus-tag", mem_bs_tag);
    581 		prop_object_release(mem_bs_tag);
    582 
    583 		pc = prop_data_create_data_nocopy(arm32_mvpex_chipset,
    584 		    sizeof(struct arm32_pci_chipset));
    585 		KASSERT(pc != NULL);
    586 		prop_dictionary_set(dict, "pci-chipset", pc);
    587 		prop_object_release(pc);
    588 
    589 		marvell_startend_by_tag(iotag, &start, &end);
    590 		prop_dictionary_set_uint64(dict, "iostart", start);
    591 		prop_dictionary_set_uint64(dict, "ioend", end);
    592 		marvell_startend_by_tag(memtag, &start, &end);
    593 		prop_dictionary_set_uint64(dict, "memstart", start);
    594 		prop_dictionary_set_uint64(dict, "memend", end);
    595 		prop_dictionary_set_uint32(dict,
    596 		    "cache-line-size", arm_dcache_align);
    597 	}
    598 	if (device_is_a(dev, "mvgbec")) {
    599 		uint8_t enaddr[ETHER_ADDR_LEN];
    600 		char optname[9];
    601 		int unit = device_unit(dev);
    602 
    603 		if (unit > 9)
    604 			return;
    605 		switch (unit) {
    606 		case 0:
    607 			strlcpy(optname, "ethaddr", sizeof(optname));
    608 			break;
    609 		default:
    610 			/* eth1addr ... eth9addr */
    611 			snprintf(optname, sizeof(optname),
    612 			    "eth%daddr", unit);
    613 			break;
    614 		}
    615 		if (get_bootconf_option(boot_args, optname,
    616 		    BOOTOPT_TYPE_MACADDR, enaddr)) {
    617 			prop_data_t pd =
    618 			    prop_data_create_data(enaddr, sizeof(enaddr));
    619 
    620 			prop_dictionary_set(dict, "mac-address", pd);
    621 		}
    622 	}
    623 	if (device_is_a(dev, "mvxpe")) {
    624 		uint8_t enaddr[ETHER_ADDR_LEN];
    625 		char optname[9];
    626 		int unit = device_unit(dev);
    627 
    628 		if (unit > 9)
    629 			return;
    630 		switch (unit) {
    631 		case 0:
    632 			strlcpy(optname, "ethaddr", sizeof(optname));
    633 			break;
    634 		default:
    635 			/* eth1addr ... eth9addr */
    636 			snprintf(optname, sizeof(optname),
    637 			    "eth%daddr", unit);
    638 			break;
    639 		}
    640 		if (get_bootconf_option(boot_args, optname,
    641 		    BOOTOPT_TYPE_MACADDR, enaddr)) {
    642 			prop_data_t pd =
    643 			    prop_data_create_data(enaddr, sizeof(enaddr));
    644 
    645 			prop_dictionary_set(dict, "mac-address", pd);
    646 		}
    647 	}
    648 #endif
    649 }
    650