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