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