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