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