armadaxp_machdep.c revision 1.12 1 /* $NetBSD: armadaxp_machdep.c,v 1.12 2017/01/07 16:19:29 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.12 2017/01/07 16:19:29 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/marvell/marvellreg.h>
70 #include <dev/pci/pcireg.h>
71 #include <dev/pci/pcivar.h>
72 #include <machine/pci_machdep.h>
73
74 #include <machine/db_machdep.h>
75 #include <ddb/db_sym.h>
76 #include <ddb/db_extern.h>
77 #ifdef KGDB
78 #include <sys/kgdb.h>
79 #endif
80
81 #include <machine/bootconfig.h>
82 #include <machine/autoconf.h>
83 #include <machine/cpu.h>
84 #include <machine/frame.h>
85 #include <arm/armreg.h>
86 #include <arm/undefined.h>
87
88 #include <arm/arm32/machdep.h>
89
90 #include <arm/marvell/mvsocreg.h>
91 #include <arm/marvell/mvsocvar.h>
92 #include <arm/marvell/armadaxpreg.h>
93
94 #include <evbarm/marvell/marvellreg.h>
95 #include <evbarm/marvell/marvellvar.h>
96 #include <dev/marvell/marvellreg.h>
97
98 #include "mvpex.h"
99 #include "com.h"
100 #if NCOM > 0
101 #include <dev/ic/comreg.h>
102 #include <dev/ic/comvar.h>
103 #endif
104
105 #include <net/if_ether.h>
106
107 /*
108 * Address to call from cpu_reset() to reset the machine.
109 * This is machine architecture dependent as it varies depending
110 * on where the ROM appears when you turn the MMU off.
111 */
112
113 BootConfig bootconfig; /* Boot config storage */
114 char *boot_args = NULL;
115 char *boot_file = NULL;
116
117 /*
118 * U-Boot argument buffer
119 */
120 extern unsigned int uboot_regs_pa[]; /* saved r0, r1, r2, r3 */
121 unsigned int *uboot_regs_va;
122 char boot_argbuf[MAX_BOOT_STRING];
123
124 extern int KERNEL_BASE_phys[];
125
126 /*
127 * Put some bogus settings of the MEMSTART and MEMSIZE
128 * if they are not defined in kernel configuration file.
129 */
130 #ifndef MEMSTART
131 #define MEMSTART 0x00000000UL
132 #endif
133 #ifndef MEMSIZE
134 #define MEMSIZE 0x40000000UL
135 #endif
136
137 #ifndef STARTUP_PAGETABLE_ADDR
138 #define STARTUP_PAGETABLE_ADDR 0x00000000UL
139 #endif
140
141 /* Physical offset of the kernel from MEMSTART */
142 #define KERNEL_OFFSET (paddr_t)&KERNEL_BASE_phys
143 /* Kernel base virtual address */
144 #define KERNEL_TEXT_BASE (KERNEL_BASE + KERNEL_OFFSET)
145
146 #define KERNEL_VM_BASE (KERNEL_BASE + 0x40000000)
147 #define KERNEL_VM_SIZE 0x14000000
148
149 void consinit(void);
150 #ifdef KGDB
151 static void kgdb_port_init(void);
152 #endif
153
154 static void axp_device_register(device_t dev, void *aux);
155
156 static void
157 axp_system_reset(void)
158 {
159 extern vaddr_t misc_base;
160
161 #define write_miscreg(r, v) (*(volatile uint32_t *)(misc_base + (r)) = (v))
162
163 cpu_reset_address = 0;
164
165 /* Unmask soft reset */
166 write_miscreg(ARMADAXP_MISC_RSTOUTNMASKR,
167 ARMADAXP_MISC_RSTOUTNMASKR_GLOBALSOFTRSTOUTEN);
168 /* Assert soft reset */
169 write_miscreg(ARMADAXP_MISC_SSRR, ARMADAXP_MISC_SSRR_GLOBALSOFTRST);
170
171 while (1);
172 }
173
174 /*
175 * Static device mappings. These peripheral registers are mapped at
176 * fixed virtual addresses very early in initarm() so that we can use
177 * them while booting the kernel, and stay at the same address
178 * throughout whole kernel's life time.
179 *
180 * We use this table twice; once with bootstrap page table, and once
181 * with kernel's page table which we build up in initarm().
182 *
183 * Since we map these registers into the bootstrap page table using
184 * pmap_devmap_bootstrap() which calls pmap_map_chunk(), we map
185 * registers segment-aligned and segment-rounded in order to avoid
186 * using the 2nd page tables.
187 */
188
189 #define _A(a) ((a) & ~L1_S_OFFSET)
190 #define _S(s) (((s) + L1_S_SIZE - 1) & ~(L1_S_SIZE-1))
191
192 static const struct pmap_devmap devmap[] = {
193 {
194 /* Internal registers */
195 .pd_va = _A(MARVELL_INTERREGS_VBASE),
196 .pd_pa = _A(MARVELL_INTERREGS_PBASE),
197 .pd_size = _S(MVSOC_INTERREGS_SIZE),
198 .pd_prot = VM_PROT_READ|VM_PROT_WRITE,
199 .pd_cache = PTE_NOCACHE
200 },
201 {0, 0, 0, 0, 0}
202 };
203
204 #undef _A
205 #undef _S
206
207 static inline pd_entry_t *
208 read_ttb(void)
209 {
210 return (pd_entry_t *)(armreg_ttbr_read() & ~((1<<14)-1));
211 }
212
213 static int
214 axp_pcie_free_win(void)
215 {
216 /* Find first disabled window */
217 for (size_t i = 0; i < ARMADAXP_MLMB_NWINDOW; i++) {
218 if ((read_mlmbreg(MVSOC_MLMB_WCR(i)) &
219 MVSOC_MLMB_WCR_WINEN) == 0) {
220 return i;
221 }
222 }
223 /* If there is no free window, return erroneous value */
224 return (-1);
225 }
226
227 static void
228 reset_axp_pcie_win(void)
229 {
230 uint32_t target, attr;
231 int memtag = 0, iotag = 0, window, i;
232 uint32_t membase;
233 uint32_t iobase;
234 uint32_t tags[] = { ARMADAXP_TAG_PEX00_MEM, ARMADAXP_TAG_PEX00_IO,
235 ARMADAXP_TAG_PEX01_MEM, ARMADAXP_TAG_PEX01_IO,
236 ARMADAXP_TAG_PEX02_MEM, ARMADAXP_TAG_PEX02_IO,
237 ARMADAXP_TAG_PEX03_MEM, ARMADAXP_TAG_PEX03_IO,
238 ARMADAXP_TAG_PEX2_MEM, ARMADAXP_TAG_PEX2_IO,
239 ARMADAXP_TAG_PEX3_MEM, ARMADAXP_TAG_PEX3_IO};
240
241 nwindow = ARMADAXP_MLMB_NWINDOW;
242 nremap = ARMADAXP_MLMB_NREMAP;
243 membase = MARVELL_PEXMEM_PBASE;
244 iobase = MARVELL_PEXIO_PBASE;
245 for (i = 0; i < __arraycount(tags) / 2; i++) {
246 memtag = tags[2 * i];
247 iotag = tags[(2 * i) + 1];
248
249 /* Reset PCI-Express space to window register. */
250 window = mvsoc_target(memtag, &target, &attr, NULL, NULL);
251
252 /* Find free window if we've got spurious one */
253 if (window >= nwindow) {
254 window = axp_pcie_free_win();
255 /* Just break if there is no free windows left */
256 if (window < 0) {
257 aprint_error(": no free windows for PEX MEM\n");
258 break;
259 }
260 }
261 write_mlmbreg(MVSOC_MLMB_WCR(window),
262 MVSOC_MLMB_WCR_WINEN |
263 MVSOC_MLMB_WCR_TARGET(target) |
264 MVSOC_MLMB_WCR_ATTR(attr) |
265 MVSOC_MLMB_WCR_SIZE(MARVELL_PEXMEM_SIZE));
266 write_mlmbreg(MVSOC_MLMB_WBR(window),
267 membase & MVSOC_MLMB_WBR_BASE_MASK);
268 #ifdef PCI_NETBSD_CONFIGURE
269 if (window < nremap) {
270 write_mlmbreg(MVSOC_MLMB_WRLR(window),
271 membase & MVSOC_MLMB_WRLR_REMAP_MASK);
272 write_mlmbreg(MVSOC_MLMB_WRHR(window), 0);
273 }
274 #endif
275 window = mvsoc_target(iotag, &target, &attr, NULL, NULL);
276
277 /* Find free window if we've got spurious one */
278 if (window >= nwindow) {
279 window = axp_pcie_free_win();
280 /* Just break if there is no free windows left */
281 if (window < 0) {
282 aprint_error(": no free windows for PEX I/O\n");
283 break;
284 }
285 }
286 write_mlmbreg(MVSOC_MLMB_WCR(window),
287 MVSOC_MLMB_WCR_WINEN |
288 MVSOC_MLMB_WCR_TARGET(target) |
289 MVSOC_MLMB_WCR_ATTR(attr) |
290 MVSOC_MLMB_WCR_SIZE(MARVELL_PEXIO_SIZE));
291 write_mlmbreg(MVSOC_MLMB_WBR(window),
292 iobase & MVSOC_MLMB_WBR_BASE_MASK);
293 #ifdef PCI_NETBSD_CONFIGURE
294 if (window < nremap) {
295 write_mlmbreg(MVSOC_MLMB_WRLR(window),
296 iobase & MVSOC_MLMB_WRLR_REMAP_MASK);
297 write_mlmbreg(MVSOC_MLMB_WRHR(window), 0);
298 }
299 #endif
300 membase += MARVELL_PEXMEM_SIZE;
301 iobase += MARVELL_PEXIO_SIZE;
302 }
303 }
304
305 /*
306 * u_int initarm(...)
307 *
308 * Initial entry point on startup. This gets called before main() is
309 * entered.
310 * It should be responsible for setting up everything that must be
311 * in place when main is called.
312 * This includes
313 * Taking a copy of the boot configuration structure.
314 * Initialising the physical console so characters can be printed.
315 * Setting up page tables for the kernel
316 * Relocating the kernel to the bottom of physical memory
317 */
318 u_int
319 initarm(void *arg)
320 {
321 cpu_reset_address = axp_system_reset;
322
323 mvsoc_bootstrap(MARVELL_INTERREGS_VBASE);
324
325 /* Set CPU functions */
326 if (set_cpufuncs())
327 panic("cpu not recognized!");
328
329 /*
330 * Map devices into the initial page table
331 * in order to use early console during initialization process.
332 * consinit is going to use this mapping.
333 */
334 pmap_devmap_bootstrap((vaddr_t)read_ttb(), devmap);
335
336 /* Initialize system console */
337 consinit();
338
339 /* Reset PCI-Express space to window register. */
340 reset_axp_pcie_win();
341
342 /* Get CPU, system and timebase frequencies */
343 armadaxp_bootstrap(
344 MARVELL_INTERREGS_VBASE,
345 MARVELL_INTERREGS_PBASE);
346
347 #ifdef KGDB
348 kgdb_port_init();
349 #endif
350
351 #ifdef VERBOSE_INIT_ARM
352 /* Talk to the user */
353 #define BDSTR(s) _BDSTR(s)
354 #define _BDSTR(s) #s
355 printf("\nNetBSD/evbarm (" BDSTR(EVBARM_BOARDTYPE) ") booting ...\n");
356 #endif
357
358 #ifdef __HAVE_MM_MD_DIRECT_MAPPED_PHYS
359 const bool mapallmem_p = true;
360 #else
361 const bool mapallmem_p = false;
362 #endif
363
364 #ifdef VERBOSE_INIT_ARM
365 printf("initarm: Configuring system ...\n");
366 #endif
367 psize_t memsize = MEMSIZE;
368 if (mapallmem_p && memsize > KERNEL_VM_BASE - KERNEL_BASE) {
369 printf("%s: dropping RAM size from %luMB to %uMB\n",
370 __func__, (unsigned long) (memsize >> 20),
371 (KERNEL_VM_BASE - KERNEL_BASE) >> 20);
372 memsize = KERNEL_VM_BASE - KERNEL_BASE;
373 }
374 /* Fake bootconfig structure for the benefit of pmap.c. */
375 bootconfig.dramblocks = 1;
376 bootconfig.dram[0].address = MEMSTART;
377 bootconfig.dram[0].pages = memsize / PAGE_SIZE;
378
379 physical_start = bootconfig.dram[0].address;
380 physical_end = physical_start + (bootconfig.dram[0].pages * PAGE_SIZE);
381
382 arm32_bootmem_init(0, physical_end, (uintptr_t) KERNEL_BASE_phys);
383 arm32_kernel_vm_init(KERNEL_VM_BASE, ARM_VECTORS_LOW, 0,
384 devmap, mapallmem_p);
385
386 /* we've a specific device_register routine */
387 evbarm_device_register = axp_device_register;
388
389 /* copy U-Boot args from U-Boot heap to kernel memory */
390 uboot_regs_va = (int *)((unsigned int)uboot_regs_pa + KERNEL_BASE);
391 boot_args = (char *)(uboot_regs_va[3] + KERNEL_BASE);
392 strlcpy(boot_argbuf, (char *)boot_args, sizeof(boot_argbuf));
393 boot_args = boot_argbuf;
394 parse_mi_bootargs(boot_args);
395
396 return initarm_common(KERNEL_VM_BASE, KERNEL_VM_SIZE, NULL, 0);
397 }
398
399 #ifndef CONSADDR
400 #error Specify the address of the UART with the CONSADDR option.
401 #endif
402 #ifndef CONSPEED
403 #define CONSPEED B115200
404 #endif
405 #ifndef CONMODE
406 #define CONMODE ((TTYDEF_CFLAG & ~(CSIZE | CSTOPB | PARENB)) | CS8) /* 8N1 */
407 #endif
408 #ifndef CONSFREQ
409 #define CONSFREQ 0
410 #endif
411 static const int comcnspeed = CONSPEED;
412 static const int comcnfreq = CONSFREQ;
413 static const tcflag_t comcnmode = CONMODE;
414 static const bus_addr_t comcnaddr = (bus_addr_t)CONSADDR;
415
416 void
417 consinit(void)
418 {
419 static bool consinit_called = false;
420
421 if (consinit_called)
422 return;
423 consinit_called = true;
424
425 #if NCOM > 0
426 extern int mvuart_cnattach(bus_space_tag_t, bus_addr_t, int,
427 uint32_t, int);
428
429 if (mvuart_cnattach(&mvsoc_bs_tag, comcnaddr, comcnspeed,
430 comcnfreq ? comcnfreq : mvTclk , comcnmode))
431 panic("Serial console can not be initialized.");
432 #endif
433 }
434
435 #ifdef KGDB
436 #ifndef KGDB_DEVADDR
437 #error Specify the address of the kgdb UART with the KGDB_DEVADDR option.
438 #endif
439 #ifndef KGDB_DEVRATE
440 #define KGDB_DEVRATE B115200
441 #endif
442 #define MVUART_SIZE 0x20
443
444 #ifndef KGDB_DEVMODE
445 #define KGDB_DEVMODE ((TTYDEF_CFLAG & ~(CSIZE | CSTOPB | PARENB)) | CS8) /* 8N1 */
446 #endif
447 static const vaddr_t comkgdbaddr = KGDB_DEVADDR;
448 static const int comkgdbspeed = KGDB_DEVRATE;
449 static const int comkgdbmode = KGDB_DEVMODE;
450
451 void
452 static kgdb_port_init(void)
453 {
454 static int kgdbsinit_called = 0;
455
456 if (kgdbsinit_called != 0)
457 return;
458 kgdbsinit_called = 1;
459
460 if (com_kgdb_attach(&mvsoc_bs_tag, comkgdbaddr, comkgdbspeed,
461 MVUART_SIZE, COM_TYPE_16550_NOERS, comkgdbmode))
462 panic("KGDB uart can not be initialized.");
463 }
464 #endif
465
466 #if NMVPEX > 0
467 static void
468 marvell_startend_by_tag(int tag, uint64_t *start, uint64_t *end)
469 {
470
471 uint32_t base, size;
472 int win;
473
474 win = mvsoc_target(tag, NULL, NULL, &base, &size);
475 if (size != 0) {
476 if (win < nremap)
477 *start = read_mlmbreg(MVSOC_MLMB_WRLR(win)) |
478 ((read_mlmbreg(MVSOC_MLMB_WRHR(win)) << 16) << 16);
479 else
480 *start = base;
481 *end = *start + size - 1;
482 } else
483 *start = *end = 0;
484 }
485 #endif
486
487 static void
488 axp_device_register(device_t dev, void *aux)
489 {
490 prop_dictionary_t dict = device_properties(dev);
491
492 #if NCOM > 0
493 if (device_is_a(dev, "com") &&
494 device_is_a(device_parent(dev), "mvsoc"))
495 prop_dictionary_set_uint32(dict, "frequency", mvTclk);
496 #endif
497
498 #if NMVPEX > 0
499 extern struct bus_space
500 armadaxp_pex00_io_bs_tag, armadaxp_pex00_mem_bs_tag,
501 armadaxp_pex01_io_bs_tag, armadaxp_pex01_mem_bs_tag,
502 armadaxp_pex02_io_bs_tag, armadaxp_pex02_mem_bs_tag,
503 armadaxp_pex03_io_bs_tag, armadaxp_pex03_mem_bs_tag,
504 armadaxp_pex2_io_bs_tag, armadaxp_pex2_mem_bs_tag,
505 armadaxp_pex3_io_bs_tag, armadaxp_pex3_mem_bs_tag;
506 extern struct arm32_pci_chipset arm32_mvpex0_chipset,
507 arm32_mvpex1_chipset, arm32_mvpex2_chipset,
508 arm32_mvpex3_chipset, arm32_mvpex4_chipset,
509 arm32_mvpex5_chipset;
510
511 struct marvell_attach_args *mva = aux;
512
513 if (device_is_a(dev, "mvpex")) {
514 struct bus_space *mvpex_io_bs_tag, *mvpex_mem_bs_tag;
515 struct arm32_pci_chipset *arm32_mvpex_chipset;
516 prop_data_t io_bs_tag, mem_bs_tag, pc;
517 uint64_t start, end;
518 int iotag, memtag;
519
520 if (mva->mva_offset == MVSOC_PEX_BASE) {
521 mvpex_io_bs_tag = &armadaxp_pex00_io_bs_tag;
522 mvpex_mem_bs_tag = &armadaxp_pex00_mem_bs_tag;
523 arm32_mvpex_chipset = &arm32_mvpex0_chipset;
524 iotag = ARMADAXP_TAG_PEX00_IO;
525 memtag = ARMADAXP_TAG_PEX00_MEM;
526 } else if (mva->mva_offset == MVSOC_PEX_BASE + 0x4000) {
527 mvpex_io_bs_tag = &armadaxp_pex01_io_bs_tag;
528 mvpex_mem_bs_tag = &armadaxp_pex01_mem_bs_tag;
529 arm32_mvpex_chipset = &arm32_mvpex1_chipset;
530 iotag = ARMADAXP_TAG_PEX01_IO;
531 memtag = ARMADAXP_TAG_PEX01_MEM;
532 } else if (mva->mva_offset == MVSOC_PEX_BASE + 0x8000) {
533 mvpex_io_bs_tag = &armadaxp_pex02_io_bs_tag;
534 mvpex_mem_bs_tag = &armadaxp_pex02_mem_bs_tag;
535 arm32_mvpex_chipset = &arm32_mvpex2_chipset;
536 iotag = ARMADAXP_TAG_PEX02_IO;
537 memtag = ARMADAXP_TAG_PEX02_MEM;
538 } else if (mva->mva_offset == MVSOC_PEX_BASE + 0xc000) {
539 mvpex_io_bs_tag = &armadaxp_pex03_io_bs_tag;
540 mvpex_mem_bs_tag = &armadaxp_pex03_mem_bs_tag;
541 arm32_mvpex_chipset = &arm32_mvpex3_chipset;
542 iotag = ARMADAXP_TAG_PEX03_IO;
543 memtag = ARMADAXP_TAG_PEX03_MEM;
544 } else if (mva->mva_offset == MVSOC_PEX_BASE + 0x2000) {
545 mvpex_io_bs_tag = &armadaxp_pex2_io_bs_tag;
546 mvpex_mem_bs_tag = &armadaxp_pex2_mem_bs_tag;
547 arm32_mvpex_chipset = &arm32_mvpex4_chipset;
548 iotag = ARMADAXP_TAG_PEX2_IO;
549 memtag = ARMADAXP_TAG_PEX2_MEM;
550 } else {
551 mvpex_io_bs_tag = &armadaxp_pex3_io_bs_tag;
552 mvpex_mem_bs_tag = &armadaxp_pex3_mem_bs_tag;
553 arm32_mvpex_chipset = &arm32_mvpex5_chipset;
554 iotag = ARMADAXP_TAG_PEX3_IO;
555 memtag = ARMADAXP_TAG_PEX3_MEM;
556 }
557
558 arm32_mvpex_chipset->pc_conf_v = device_private(dev);
559 arm32_mvpex_chipset->pc_intr_v = device_private(dev);
560
561 io_bs_tag = prop_data_create_data_nocopy(
562 mvpex_io_bs_tag, sizeof(struct bus_space));
563 KASSERT(io_bs_tag != NULL);
564 prop_dictionary_set(dict, "io-bus-tag", io_bs_tag);
565 prop_object_release(io_bs_tag);
566 mem_bs_tag = prop_data_create_data_nocopy(
567 mvpex_mem_bs_tag, sizeof(struct bus_space));
568 KASSERT(mem_bs_tag != NULL);
569 prop_dictionary_set(dict, "mem-bus-tag", mem_bs_tag);
570 prop_object_release(mem_bs_tag);
571
572 pc = prop_data_create_data_nocopy(arm32_mvpex_chipset,
573 sizeof(struct arm32_pci_chipset));
574 KASSERT(pc != NULL);
575 prop_dictionary_set(dict, "pci-chipset", pc);
576 prop_object_release(pc);
577
578 marvell_startend_by_tag(iotag, &start, &end);
579 prop_dictionary_set_uint64(dict, "iostart", start);
580 prop_dictionary_set_uint64(dict, "ioend", end);
581 marvell_startend_by_tag(memtag, &start, &end);
582 prop_dictionary_set_uint64(dict, "memstart", start);
583 prop_dictionary_set_uint64(dict, "memend", end);
584 prop_dictionary_set_uint32(dict,
585 "cache-line-size", arm_dcache_align);
586 }
587 if (device_is_a(dev, "mvgbec")) {
588 uint8_t enaddr[ETHER_ADDR_LEN];
589 char optname[9];
590 int unit = device_unit(dev);
591
592 if (unit > 9)
593 return;
594 switch (unit) {
595 case 0:
596 strlcpy(optname, "ethaddr", sizeof(optname));
597 break;
598 default:
599 /* eth1addr ... eth9addr */
600 snprintf(optname, sizeof(optname),
601 "eth%daddr", unit);
602 break;
603 }
604 if (get_bootconf_option(boot_args, optname,
605 BOOTOPT_TYPE_MACADDR, enaddr)) {
606 prop_data_t pd =
607 prop_data_create_data(enaddr, sizeof(enaddr));
608
609 prop_dictionary_set(dict, "mac-address", pd);
610 }
611 }
612 if (device_is_a(dev, "mvxpe")) {
613 uint8_t enaddr[ETHER_ADDR_LEN];
614 char optname[9];
615 int unit = device_unit(dev);
616
617 if (unit > 9)
618 return;
619 switch (unit) {
620 case 0:
621 strlcpy(optname, "ethaddr", sizeof(optname));
622 break;
623 default:
624 /* eth1addr ... eth9addr */
625 snprintf(optname, sizeof(optname),
626 "eth%daddr", unit);
627 break;
628 }
629 if (get_bootconf_option(boot_args, optname,
630 BOOTOPT_TYPE_MACADDR, enaddr)) {
631 prop_data_t pd =
632 prop_data_create_data(enaddr, sizeof(enaddr));
633
634 prop_dictionary_set(dict, "mac-address", pd);
635 }
636 }
637 #endif
638 }
639