Home | History | Annotate | Line # | Download | only in armadaxp
armadaxp_machdep.c revision 1.3
      1 /*	$NetBSD: armadaxp_machdep.c,v 1.3 2013/09/30 13:29:07 kiyohara 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.3 2013/09/30 13:29:07 kiyohara 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 
     96 #include "mvpex.h"
     97 #include "com.h"
     98 #if NCOM > 0
     99 #include <dev/ic/comreg.h>
    100 #include <dev/ic/comvar.h>
    101 #endif
    102 
    103 /*
    104  * Address to call from cpu_reset() to reset the machine.
    105  * This is machine architecture dependent as it varies depending
    106  * on where the ROM appears when you turn the MMU off.
    107  */
    108 
    109 
    110 /* Define various stack sizes in pages */
    111 #define IRQ_STACK_SIZE	1
    112 #define ABT_STACK_SIZE	1
    113 #ifdef IPKDB
    114 #define UND_STACK_SIZE	2
    115 #else
    116 #define UND_STACK_SIZE	1
    117 #endif
    118 
    119 BootConfig bootconfig;		/* Boot config storage */
    120 char *boot_args = NULL;
    121 char *boot_file = NULL;
    122 
    123 extern int KERNEL_BASE_phys[];
    124 
    125 /*extern char KERNEL_BASE_phys[];*/
    126 extern char etext[], __data_start[], _edata[], __bss_start[], __bss_end__[];
    127 extern char _end[];
    128 
    129 /*
    130  * Put some bogus settings of the MEMSTART and MEMSIZE
    131  * if they are not defined in kernel configuration file.
    132  */
    133 #ifndef MEMSTART
    134 #define MEMSTART 0x00000000UL
    135 #endif
    136 #ifndef MEMSIZE
    137 #define MEMSIZE 0x40000000UL
    138 #endif
    139 
    140 #ifndef STARTUP_PAGETABLE_ADDR
    141 #define	STARTUP_PAGETABLE_ADDR 0x00000000UL
    142 #endif
    143 
    144 /* Physical offset of the kernel from MEMSTART */
    145 #define KERNEL_OFFSET		(paddr_t)&KERNEL_BASE_phys
    146 /* Kernel base virtual address */
    147 #define	KERNEL_TEXT_BASE	(KERNEL_BASE + KERNEL_OFFSET)
    148 
    149 #define	KERNEL_VM_BASE		(KERNEL_BASE + 0x01000000)
    150 #define KERNEL_VM_SIZE		0x10000000
    151 
    152 /* Prototypes */
    153 extern int armadaxp_l2_init(bus_addr_t);
    154 extern void armadaxp_io_coherency_init(void);
    155 
    156 void consinit(void);
    157 #ifdef KGDB
    158 static void kgdb_port_init(void);
    159 #endif
    160 
    161 static void axp_device_register(device_t dev, void *aux);
    162 
    163 static void
    164 axp_system_reset(void)
    165 {
    166 	cpu_reset_address = 0;
    167 
    168 	/* Unmask soft reset */
    169 	write_miscreg(MVSOC_MLMB_RSTOUTNMASKR,
    170 	    MVSOC_MLMB_RSTOUTNMASKR_SOFTRSTOUTEN);
    171 	/* Assert soft reset */
    172 	write_miscreg(MVSOC_MLMB_SSRR, MVSOC_MLMB_SSRR_SYSTEMSOFTRST);
    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
    211 pd_entry_t *
    212 read_ttb(void)
    213 {
    214 	long ttb;
    215 
    216 	__asm volatile("mrc	p15, 0, %0, c2, c0, 0" : "=r" (ttb));
    217 
    218 	return (pd_entry_t *)(ttb & ~((1<<14)-1));
    219 }
    220 
    221 static int
    222 axp_pcie_free_win(void)
    223 {
    224 	int i;
    225 	/* Find first disabled window */
    226 	for (i = 0; i < ARMADAXP_MLMB_NWINDOW; i++) {
    227 		if ((read_mlmbreg(MVSOC_MLMB_WCR(i)) &
    228 		    MVSOC_MLMB_WCR_WINEN) == 0) {
    229 			return i;
    230 		}
    231 	}
    232 	/* If there is no free window, return erroneous value */
    233 	return (-1);
    234 }
    235 
    236 static void
    237 reset_axp_pcie_win(void)
    238 {
    239 	uint32_t target, attr;
    240 	int memtag = 0, iotag = 0, window, i;
    241 	uint32_t membase;
    242 	uint32_t iobase;
    243 	uint32_t tags[] = { ARMADAXP_TAG_PEX00_MEM, ARMADAXP_TAG_PEX00_IO,
    244 			    ARMADAXP_TAG_PEX01_MEM, ARMADAXP_TAG_PEX01_IO,
    245 			    ARMADAXP_TAG_PEX02_MEM, ARMADAXP_TAG_PEX02_IO,
    246 			    ARMADAXP_TAG_PEX03_MEM, ARMADAXP_TAG_PEX03_IO,
    247 			    ARMADAXP_TAG_PEX2_MEM, ARMADAXP_TAG_PEX2_IO,
    248 			    ARMADAXP_TAG_PEX3_MEM, ARMADAXP_TAG_PEX3_IO};
    249 
    250 	nwindow = ARMADAXP_MLMB_NWINDOW;
    251 	nremap = ARMADAXP_MLMB_NREMAP;
    252 	membase = MARVELL_PEXMEM_PBASE;
    253 	iobase = MARVELL_PEXIO_PBASE;
    254 	for (i = 0; i < __arraycount(tags) / 2; i++) {
    255 		memtag = tags[2 * i];
    256 		iotag = tags[(2 * i) + 1];
    257 
    258 		/* Reset PCI-Express space to window register. */
    259 		window = mvsoc_target(memtag, &target, &attr, NULL, NULL);
    260 
    261 		/* Find free window if we've got spurious one */
    262 		if (window >= nwindow) {
    263 			window = axp_pcie_free_win();
    264 			/* Just break if there is no free windows left */
    265 			if (window < 0) {
    266 				aprint_error(": no free windows for PEX MEM\n");
    267 				break;
    268 			}
    269 		}
    270 		write_mlmbreg(MVSOC_MLMB_WCR(window),
    271 		    MVSOC_MLMB_WCR_WINEN |
    272 		    MVSOC_MLMB_WCR_TARGET(target) |
    273 		    MVSOC_MLMB_WCR_ATTR(attr) |
    274 		    MVSOC_MLMB_WCR_SIZE(MARVELL_PEXMEM_SIZE));
    275 		write_mlmbreg(MVSOC_MLMB_WBR(window),
    276 		    membase & MVSOC_MLMB_WBR_BASE_MASK);
    277 #ifdef PCI_NETBSD_CONFIGURE
    278 		if (window < nremap) {
    279 			write_mlmbreg(MVSOC_MLMB_WRLR(window),
    280 			    membase & MVSOC_MLMB_WRLR_REMAP_MASK);
    281 			write_mlmbreg(MVSOC_MLMB_WRHR(window), 0);
    282 		}
    283 #endif
    284 		window = mvsoc_target(iotag, &target, &attr, NULL, NULL);
    285 
    286 		/* Find free window if we've got spurious one */
    287 		if (window >= nwindow) {
    288 			window = axp_pcie_free_win();
    289 			/* Just break if there is no free windows left */
    290 			if (window < 0) {
    291 				aprint_error(": no free windows for PEX I/O\n");
    292 				break;
    293 			}
    294 		}
    295 		write_mlmbreg(MVSOC_MLMB_WCR(window),
    296 		    MVSOC_MLMB_WCR_WINEN |
    297 		    MVSOC_MLMB_WCR_TARGET(target) |
    298 		    MVSOC_MLMB_WCR_ATTR(attr) |
    299 		    MVSOC_MLMB_WCR_SIZE(MARVELL_PEXIO_SIZE));
    300 		write_mlmbreg(MVSOC_MLMB_WBR(window),
    301 		    iobase & MVSOC_MLMB_WBR_BASE_MASK);
    302 #ifdef PCI_NETBSD_CONFIGURE
    303 		if (window < nremap) {
    304 			write_mlmbreg(MVSOC_MLMB_WRLR(window),
    305 			    iobase & MVSOC_MLMB_WRLR_REMAP_MASK);
    306 			write_mlmbreg(MVSOC_MLMB_WRHR(window), 0);
    307 		}
    308 #endif
    309 		membase += MARVELL_PEXMEM_SIZE;
    310 		iobase += MARVELL_PEXIO_SIZE;
    311 	}
    312 }
    313 
    314 /*
    315  * u_int initarm(...)
    316  *
    317  * Initial entry point on startup. This gets called before main() is
    318  * entered.
    319  * It should be responsible for setting up everything that must be
    320  * in place when main is called.
    321  * This includes
    322  *   Taking a copy of the boot configuration structure.
    323  *   Initialising the physical console so characters can be printed.
    324  *   Setting up page tables for the kernel
    325  *   Relocating the kernel to the bottom of physical memory
    326  */
    327 u_int
    328 initarm(void *arg)
    329 {
    330 	cpu_reset_address = axp_system_reset;
    331 
    332 	mvsoc_bootstrap(MARVELL_INTERREGS_VBASE);
    333 
    334 	/* Set CPU functions */
    335 	if (set_cpufuncs())
    336 		panic("cpu not recognized!");
    337 
    338 	/*
    339 	 * Map devices into the initial page table
    340 	 * in order to use early console during initialization process.
    341 	 * consinit is going to use this mapping.
    342 	 */
    343 	pmap_devmap_bootstrap((vaddr_t)read_ttb(), devmap);
    344 
    345 	/* Initialize system console */
    346 	consinit();
    347 
    348 	/* Reset PCI-Express space to window register. */
    349 	reset_axp_pcie_win();
    350 
    351 	/* Get CPU, system and timebase frequencies */
    352 	armadaxp_getclks();
    353 
    354 	/* Preconfigure interrupts */
    355 	armadaxp_intr_bootstrap(MARVELL_INTERREGS_PBASE);
    356 
    357 #ifdef L2CACHE_ENABLE
    358 	/* Initialize L2 Cache */
    359 	(void)armadaxp_l2_init(MARVELL_INTERREGS_PBASE);
    360 #endif
    361 
    362 #ifdef AURORA_IO_CACHE_COHERENCY
    363 	/* Initialize cache coherency */
    364 	armadaxp_io_coherency_init();
    365 #endif
    366 
    367 #ifdef KGDB
    368 	kgdb_port_init();
    369 #endif
    370 
    371 #ifdef VERBOSE_INIT_ARM
    372 	/* Talk to the user */
    373 #define	BDSTR(s)	_BDSTR(s)
    374 #define	_BDSTR(s)	#s
    375 	printf("\nNetBSD/evbarm (" BDSTR(EVBARM_BOARDTYPE) ") booting ...\n");
    376 #endif
    377 
    378 
    379 #ifdef VERBOSE_INIT_ARM
    380 	printf("initarm: Configuring system ...\n");
    381 #endif
    382 	/* Fake bootconfig structure for the benefit of pmap.c. */
    383 	bootconfig.dramblocks = 1;
    384 	bootconfig.dram[0].address = MEMSTART;
    385 	bootconfig.dram[0].pages = MEMSIZE / PAGE_SIZE;
    386 
    387         physical_start = bootconfig.dram[0].address;
    388         physical_end = physical_start + (bootconfig.dram[0].pages * PAGE_SIZE);
    389 
    390 	arm32_bootmem_init(0, physical_end, (uintptr_t) KERNEL_BASE_phys);
    391 	arm32_kernel_vm_init(KERNEL_VM_BASE, ARM_VECTORS_LOW, 0,
    392 	    devmap, false);
    393 
    394 	/* we've a specific device_register routine */
    395 	evbarm_device_register = axp_device_register;
    396 
    397 	return initarm_common(KERNEL_VM_BASE, KERNEL_VM_SIZE, NULL, 0);
    398 }
    399 
    400 #ifndef CONSADDR
    401 #error Specify the address of the UART with the CONSADDR option.
    402 #endif
    403 #ifndef CONSPEED
    404 #define	CONSPEED B115200
    405 #endif
    406 #ifndef CONMODE
    407 #define	CONMODE ((TTYDEF_CFLAG & ~(CSIZE | CSTOPB | PARENB)) | CS8) /* 8N1 */
    408 #endif
    409 #ifndef CONSFREQ
    410 #define	CONSFREQ 250000000
    411 #endif
    412 static const int	comcnspeed = CONSPEED;
    413 static const int	comcnfreq  = CONSFREQ;
    414 static const tcflag_t	comcnmode  = CONMODE;
    415 static const bus_addr_t	comcnaddr  = (bus_addr_t)CONSADDR;
    416 
    417 void
    418 consinit(void)
    419 {
    420 	static bool consinit_called = false;
    421 
    422 	if (consinit_called)
    423 		return;
    424 	consinit_called = true;
    425 
    426 #if NCOM > 0
    427 	extern int mvuart_cnattach(bus_space_tag_t, bus_addr_t, int,
    428 	    uint32_t, int);
    429 
    430 	if (mvuart_cnattach(&mvsoc_bs_tag, comcnaddr, comcnspeed,
    431 			comcnfreq, comcnmode))
    432 		panic("Serial console can not be initialized.");
    433 #endif
    434 }
    435 
    436 #ifdef KGDB
    437 #ifndef KGDB_DEVADDR
    438 #error Specify the address of the kgdb UART with the KGDB_DEVADDR option.
    439 #endif
    440 #ifndef KGDB_DEVRATE
    441 #define KGDB_DEVRATE B115200
    442 #endif
    443 #define MVUART_SIZE 0x20
    444 
    445 #ifndef KGDB_DEVMODE
    446 #define KGDB_DEVMODE ((TTYDEF_CFLAG & ~(CSIZE | CSTOPB | PARENB)) | CS8) /* 8N1 */
    447 #endif
    448 static const vaddr_t comkgdbaddr = KGDB_DEVADDR;
    449 static const int comkgdbspeed = KGDB_DEVRATE;
    450 static const int comkgdbmode = KGDB_DEVMODE;
    451 
    452 void
    453 static kgdb_port_init(void)
    454 {
    455 	static int kgdbsinit_called = 0;
    456 
    457 	if (kgdbsinit_called != 0)
    458 		return;
    459 	kgdbsinit_called = 1;
    460 
    461 	if (com_kgdb_attach(&mvsoc_bs_tag, comkgdbaddr, comkgdbspeed,
    462 			MVUART_SIZE, COM_TYPE_16550_NOERS, comkgdbmode))
    463 		panic("KGDB uart can not be initialized.");
    464 }
    465 #endif
    466 
    467 #if NMVPEX > 0
    468 static void
    469 marvell_startend_by_tag(int tag, uint64_t *start, uint64_t *end)
    470 {
    471 
    472 	uint32_t base, size;
    473 	int win;
    474 
    475 	win = mvsoc_target(tag, NULL, NULL, &base, &size);
    476 	if (size != 0) {
    477 		if (win < nremap)
    478 			*start = read_mlmbreg(MVSOC_MLMB_WRLR(win)) |
    479 			    ((read_mlmbreg(MVSOC_MLMB_WRHR(win)) << 16) << 16);
    480 		else
    481 			*start = base;
    482 		*end = *start + size - 1;
    483 	} else
    484 		*start = *end = 0;
    485 }
    486 #endif
    487 
    488 static void
    489 axp_device_register(device_t dev, void *aux)
    490 {
    491 	prop_dictionary_t dict = device_properties(dev);
    492 
    493 #if NCOM > 0
    494 	if (device_is_a(dev, "com") &&
    495 	    device_is_a(device_parent(dev), "mvsoc"))
    496 		prop_dictionary_set_uint32(dict, "frequency", mvTclk);
    497 #endif
    498 
    499 #if NMVPEX > 0
    500 	extern struct bus_space
    501 	    armadaxp_pex00_io_bs_tag, armadaxp_pex00_mem_bs_tag,
    502 	    armadaxp_pex01_io_bs_tag, armadaxp_pex01_mem_bs_tag,
    503 	    armadaxp_pex02_io_bs_tag, armadaxp_pex02_mem_bs_tag,
    504 	    armadaxp_pex03_io_bs_tag, armadaxp_pex03_mem_bs_tag,
    505 	    armadaxp_pex2_io_bs_tag, armadaxp_pex2_mem_bs_tag,
    506 	    armadaxp_pex3_io_bs_tag, armadaxp_pex3_mem_bs_tag;
    507 	extern struct arm32_pci_chipset arm32_mvpex0_chipset,
    508 	    arm32_mvpex1_chipset, arm32_mvpex2_chipset,
    509 	    arm32_mvpex3_chipset, arm32_mvpex4_chipset,
    510 	    arm32_mvpex5_chipset;
    511 
    512 	struct marvell_attach_args *mva = aux;
    513 
    514 	if (device_is_a(dev, "mvpex")) {
    515 		struct bus_space *mvpex_io_bs_tag, *mvpex_mem_bs_tag;
    516 		struct arm32_pci_chipset *arm32_mvpex_chipset;
    517 		prop_data_t io_bs_tag, mem_bs_tag, pc;
    518 		uint64_t start, end;
    519 		int iotag, memtag;
    520 
    521 		if (mva->mva_offset == MVSOC_PEX_BASE) {
    522 			mvpex_io_bs_tag = &armadaxp_pex00_io_bs_tag;
    523 			mvpex_mem_bs_tag = &armadaxp_pex00_mem_bs_tag;
    524 			arm32_mvpex_chipset = &arm32_mvpex0_chipset;
    525 			iotag = ARMADAXP_TAG_PEX00_IO;
    526 			memtag = ARMADAXP_TAG_PEX00_MEM;
    527 		} else if (mva->mva_offset == MVSOC_PEX_BASE + 0x4000) {
    528 			mvpex_io_bs_tag = &armadaxp_pex01_io_bs_tag;
    529 			mvpex_mem_bs_tag = &armadaxp_pex01_mem_bs_tag;
    530 			arm32_mvpex_chipset = &arm32_mvpex1_chipset;
    531 			iotag = ARMADAXP_TAG_PEX01_IO;
    532 			memtag = ARMADAXP_TAG_PEX01_MEM;
    533 		} else if (mva->mva_offset == MVSOC_PEX_BASE + 0x8000) {
    534 			mvpex_io_bs_tag = &armadaxp_pex02_io_bs_tag;
    535 			mvpex_mem_bs_tag = &armadaxp_pex02_mem_bs_tag;
    536 			arm32_mvpex_chipset = &arm32_mvpex2_chipset;
    537 			iotag = ARMADAXP_TAG_PEX02_IO;
    538 			memtag = ARMADAXP_TAG_PEX02_MEM;
    539 		} else if (mva->mva_offset == MVSOC_PEX_BASE + 0xc000) {
    540 			mvpex_io_bs_tag = &armadaxp_pex03_io_bs_tag;
    541 			mvpex_mem_bs_tag = &armadaxp_pex03_mem_bs_tag;
    542 			arm32_mvpex_chipset = &arm32_mvpex3_chipset;
    543 			iotag = ARMADAXP_TAG_PEX03_IO;
    544 			memtag = ARMADAXP_TAG_PEX03_MEM;
    545 		} else if (mva->mva_offset == MVSOC_PEX_BASE + 0x2000) {
    546 			mvpex_io_bs_tag = &armadaxp_pex2_io_bs_tag;
    547 			mvpex_mem_bs_tag = &armadaxp_pex2_mem_bs_tag;
    548 			arm32_mvpex_chipset = &arm32_mvpex4_chipset;
    549 			iotag = ARMADAXP_TAG_PEX2_IO;
    550 			memtag = ARMADAXP_TAG_PEX2_MEM;
    551 		} else {
    552 			mvpex_io_bs_tag = &armadaxp_pex3_io_bs_tag;
    553 			mvpex_mem_bs_tag = &armadaxp_pex3_mem_bs_tag;
    554 			arm32_mvpex_chipset = &arm32_mvpex5_chipset;
    555 			iotag = ARMADAXP_TAG_PEX3_IO;
    556 			memtag = ARMADAXP_TAG_PEX3_MEM;
    557 		}
    558 
    559 		arm32_mvpex_chipset->pc_conf_v = device_private(dev);
    560 		arm32_mvpex_chipset->pc_intr_v = device_private(dev);
    561 
    562 		io_bs_tag = prop_data_create_data_nocopy(
    563 		    mvpex_io_bs_tag, sizeof(struct bus_space));
    564 		KASSERT(io_bs_tag != NULL);
    565 		prop_dictionary_set(dict, "io-bus-tag", io_bs_tag);
    566 		prop_object_release(io_bs_tag);
    567 		mem_bs_tag = prop_data_create_data_nocopy(
    568 		    mvpex_mem_bs_tag, sizeof(struct bus_space));
    569 		KASSERT(mem_bs_tag != NULL);
    570 		prop_dictionary_set(dict, "mem-bus-tag", mem_bs_tag);
    571 		prop_object_release(mem_bs_tag);
    572 
    573 		pc = prop_data_create_data_nocopy(arm32_mvpex_chipset,
    574 		    sizeof(struct arm32_pci_chipset));
    575 		KASSERT(pc != NULL);
    576 		prop_dictionary_set(dict, "pci-chipset", pc);
    577 		prop_object_release(pc);
    578 
    579 		marvell_startend_by_tag(iotag, &start, &end);
    580 		prop_dictionary_set_uint64(dict, "iostart", start);
    581 		prop_dictionary_set_uint64(dict, "ioend", end);
    582 		marvell_startend_by_tag(memtag, &start, &end);
    583 		prop_dictionary_set_uint64(dict, "memstart", start);
    584 		prop_dictionary_set_uint64(dict, "memend", end);
    585 		prop_dictionary_set_uint32(dict,
    586 		    "cache-line-size", arm_dcache_align);
    587 	}
    588 #endif
    589 }
    590