machdep.c revision 1.4 1 /* $NetBSD: machdep.c,v 1.4 2026/06/18 21:23:01 rkujawa Exp $ */
2
3 /*
4 * Copyright (c) 2012, 2014, 2024, 2026 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Radoslaw Kujawa.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 /*
32 * Copyright 2001, 2002 Wasabi Systems, Inc.
33 * All rights reserved.
34 *
35 * Written by Eduardo Horvath and Simon Burge for Wasabi Systems, Inc.
36 *
37 * Redistribution and use in source and binary forms, with or without
38 * modification, are permitted provided that the following conditions
39 * are met:
40 * 1. Redistributions of source code must retain the above copyright
41 * notice, this list of conditions and the following disclaimer.
42 * 2. Redistributions in binary form must reproduce the above copyright
43 * notice, this list of conditions and the following disclaimer in the
44 * documentation and/or other materials provided with the distribution.
45 * 3. All advertising materials mentioning features or use of this software
46 * must display the following acknowledgement:
47 * This product includes software developed for the NetBSD Project by
48 * Wasabi Systems, Inc.
49 * 4. The name of Wasabi Systems, Inc. may not be used to endorse
50 * or promote products derived from this software without specific prior
51 * written permission.
52 *
53 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
54 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
55 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
56 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
57 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
58 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
59 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
60 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
61 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
62 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
63 * POSSIBILITY OF SUCH DAMAGE.
64 */
65 /*
66 * Copyright (C) 1995, 1996 Wolfgang Solfrank.
67 * Copyright (C) 1995, 1996 TooLs GmbH.
68 * All rights reserved.
69 *
70 * Redistribution and use in source and binary forms, with or without
71 * modification, are permitted provided that the following conditions
72 * are met:
73 * 1. Redistributions of source code must retain the above copyright
74 * notice, this list of conditions and the following disclaimer.
75 * 2. Redistributions in binary form must reproduce the above copyright
76 * notice, this list of conditions and the following disclaimer in the
77 * documentation and/or other materials provided with the distribution.
78 * 3. All advertising materials mentioning features or use of this software
79 * must display the following acknowledgement:
80 * This product includes software developed by TooLs GmbH.
81 * 4. The name of TooLs GmbH may not be used to endorse or promote products
82 * derived from this software without specific prior written permission.
83 *
84 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
85 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
86 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
87 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
88 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
89 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
90 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
91 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
92 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
93 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
94 */
95
96 /*
97 * Machine-dependent bootstrap for the ACube Sam460ex (AMCC 460EX).
98 *
99 * Modeled on evbppc/walnut/machdep.c and evbppc/obs405/obs600_machdep.c.
100 */
101
102 #include <sys/cdefs.h>
103 __KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.4 2026/06/18 21:23:01 rkujawa Exp $");
104
105 #include "opt_ddb.h"
106 #include "opt_sam460ex.h"
107
108 #include <sys/param.h>
109 #include <sys/boot_flag.h>
110 #include <sys/bus.h>
111 #include <sys/device.h>
112 #include <sys/kernel.h>
113 #include <sys/reboot.h>
114 #include <sys/sysctl.h>
115 #include <sys/systm.h>
116
117 #include <dev/cons.h>
118
119 #include <prop/proplib.h>
120
121 #include <machine/sam460ex.h>
122
123 #include <powerpc/spr.h>
124 #include <powerpc/ibm4xx/spr.h>
125
126 #include <powerpc/ibm4xx/amcc460ex.h>
127 #include <powerpc/ibm4xx/cpu.h>
128 #include <powerpc/ibm4xx/dcr4xx.h>
129 #include <powerpc/ibm4xx/tlb.h>
130
131 #include <powerpc/ibm4xx/pci_machdep.h>
132 #include <dev/pci/pciconf.h>
133 #include <dev/pci/pcivar.h>
134
135 #include "com.h"
136 #include "ukbd.h"
137 #if NUKBD > 0
138 #include <dev/usb/ukbdvar.h>
139 #endif
140 #if (NCOM > 0)
141 #include <sys/termios.h>
142 #include <powerpc/ibm4xx/dev/comopbvar.h>
143 #include <dev/ic/comreg.h>
144
145 #ifndef CONADDR
146 #define CONADDR AMCC460EX_UART0_BASE
147 #endif
148 #ifndef CONSPEED
149 #define CONSPEED B115200
150 #endif
151 #ifndef CONMODE
152 /* 8N1 */
153 #define CONMODE ((TTYDEF_CFLAG & ~(CSIZE | CSTOPB | PARENB)) | CS8)
154 #endif
155 #endif /* NCOM */
156
157 #ifndef SAM460EX_MEMSIZE
158 #define SAM460EX_MEMSIZE (512 * 1024 * 1024)
159 #endif
160 #ifndef SAM460EX_CPU_FREQ
161 #define SAM460EX_CPU_FREQ (1150 * 1000 * 1000)
162 #endif
163 #ifndef SAM460EX_OPB_FREQ
164 #define SAM460EX_OPB_FREQ (115 * 1000 * 1000)
165 #endif
166
167 #define TLB_PG_SIZE (16 * 1024 * 1024)
168
169 /* Boot loader handoff, for later FDT parsing */
170 paddr_t sam460ex_fdt_pa;
171 uint32_t sam460ex_epapr_magic;
172
173 void initppc(vaddr_t, vaddr_t, paddr_t, uint32_t);
174
175 /*
176 * Polled early console on UART0.
177 * VA 0xef600300 covered by the locore.
178 */
179 static void
180 earlycons_putc(dev_t dev, int c)
181 {
182 volatile uint8_t *uart = (volatile uint8_t *)AMCC460EX_UART0_BASE;
183
184 while ((uart[5] & 0x20) == 0) /* LSR.THRE */
185 ;
186 uart[0] = c;
187 }
188
189 static int
190 earlycons_getc(dev_t dev)
191 {
192 volatile uint8_t *uart = (volatile uint8_t *)AMCC460EX_UART0_BASE;
193
194 while ((uart[5] & 0x01) == 0) /* LSR.DR */
195 ;
196 return uart[0];
197 }
198
199 static struct consdev earlycons = {
200 .cn_putc = earlycons_putc,
201 .cn_getc = earlycons_getc,
202 .cn_pollc = nullcnpollc,
203 .cn_dev = NODEV,
204 .cn_pri = CN_INTERNAL,
205 };
206
207 void
208 initppc(vaddr_t startkernel, vaddr_t endkernel, paddr_t fdt_pa,
209 uint32_t magic)
210 {
211 u_int memsize;
212 vaddr_t va;
213
214 cn_tab = &earlycons;
215
216 sam460ex_fdt_pa = fdt_pa;
217 sam460ex_epapr_magic = magic;
218
219 /* Disable all external interrupts */
220 mtdcr(DCR_UIC0_BASE + DCR_UIC_ER, 0);
221 mtdcr(DCR_UIC1_BASE + DCR_UIC_ER, 0);
222 mtdcr(DCR_UIC2_BASE + DCR_UIC_ER, 0);
223 mtdcr(DCR_UIC3_BASE + DCR_UIC_ER, 0);
224
225 memsize = SAM460EX_MEMSIZE;
226 #ifdef SAM460EX_FDT
227 if (sam460ex_fdt_parse(fdt_pa)) {
228 if (sam460ex_fdt_info.fi_memsize != 0)
229 memsize = sam460ex_fdt_info.fi_memsize;
230 } else
231 printf("sam460ex: no valid FDT at %#lx, using defaults\n",
232 (u_long)fdt_pa);
233 /* Record the value actually used so cpu_startup() agrees. */
234 sam460ex_fdt_info.fi_memsize = memsize;
235 #endif
236
237 /* Slots 0/1 hold the TS=0 identity entries pinned by locore */
238 ppc44x_tlb_boot_reserved(2);
239
240 /*
241 * locore TS=0 RAM identity entry covers the first 256MB
242 */
243 for (paddr_t pa = 0x10000000; pa < memsize; pa += 0x10000000)
244 ppc44x_tlb_reserve_ts0(pa);
245
246 /* Linear map kernel memory (TS=1, KERNEL_PID) */
247 for (va = 0; va < endkernel; va += TLB_PG_SIZE)
248 ppc4xx_tlb_reserve(va, va, TLB_PG_SIZE, TLB_EX);
249
250 /*
251 * Map the on-chip peripherals
252 */
253 ppc44x_tlb_reserve((uint64_t)AMCC460EX_OPB_PA_HIGH << 32 | 0xef000000,
254 0xef000000, TLB_PG_SIZE, TLB_I | TLB_G);
255
256 /*
257 * PCIX host bridge windows
258 */
259 for (va = 0; va < AMCC460EX_PCIX0_MEM_SIZE; va += TLB_PG_SIZE)
260 ppc44x_tlb_reserve(
261 (uint64_t)AMCC460EX_PCIX0_MEM_PLBA_H << 32 |
262 (AMCC460EX_PCIX0_MEM_BASE + va),
263 SAM460EX_PCIMEM_VA + va, TLB_PG_SIZE, TLB_I | TLB_G);
264 /* Prefetchable window (POM1): pin the radeonfb framebuffer aperture */
265 for (va = 0; va < AMCC460EX_PCIX0_PMEM_MAP; va += TLB_PG_SIZE)
266 ppc44x_tlb_reserve(
267 (uint64_t)AMCC460EX_PCIX0_PMEM_PLBA_H << 32 |
268 (AMCC460EX_PCIX0_PMEM_BASE + va),
269 SAM460EX_PCIPREFMEM_VA + va, TLB_PG_SIZE, TLB_I | TLB_G);
270 ppc44x_tlb_reserve((uint64_t)AMCC460EX_PCIX0_IO_PA_HIGH << 32 |
271 AMCC460EX_PCIX0_IO_PLBA,
272 SAM460EX_PCIIO_VA, TLB_PG_SIZE, TLB_I | TLB_G);
273 ppc44x_tlb_reserve((uint64_t)AMCC460EX_PCIX0_CFG_PA_HIGH << 32 |
274 (AMCC460EX_PCIX0_CFG_PLBA & ~(TLB_PG_SIZE - 1)),
275 SAM460EX_PCICFG_VA, TLB_PG_SIZE, TLB_I | TLB_G);
276
277 /*
278 * PCIe root complex windows
279 */
280 ppc44x_tlb_reserve((uint64_t)AMCC460EX_PCIE_CFG_PA_HIGH << 32 |
281 AMCC460EX_PCIE0_CFG_PLBA,
282 SAM460EX_PCIE0CFG_VA, TLB_PG_SIZE, TLB_I | TLB_G);
283 ppc44x_tlb_reserve((uint64_t)AMCC460EX_PCIE_CFG_PA_HIGH << 32 |
284 AMCC460EX_PCIE1_CFG_PLBA,
285 SAM460EX_PCIE1CFG_VA, TLB_PG_SIZE, TLB_I | TLB_G);
286 ppc44x_tlb_reserve((uint64_t)AMCC460EX_PCIE_MEM_PA_HIGH << 32 |
287 AMCC460EX_PCIE0_MEM_PLBA,
288 SAM460EX_PCIE0MEM_VA, TLB_PG_SIZE, TLB_I | TLB_G);
289 ppc44x_tlb_reserve((uint64_t)AMCC460EX_PCIE_MEM_PA_HIGH << 32 |
290 AMCC460EX_PCIE1_MEM_PLBA,
291 SAM460EX_PCIE1MEM_VA, TLB_PG_SIZE, TLB_I | TLB_G);
292
293 /*
294 * AHB peripherals (USB OTG/OHCI/EHCI) behind the PLB-AHB
295 * bridge.
296 */
297 ppc44x_tlb_reserve((uint64_t)AMCC460EX_AHB_PA_HIGH << 32 |
298 AMCC460EX_AHB_BASE,
299 SAM460EX_AHB_VA, TLB_PG_SIZE, TLB_I | TLB_G);
300
301 mtspr(SPR_TCR, 0); /* disable all timers */
302
303 ibm40x_memsize_init(memsize, startkernel);
304 ibm4xx_init(startkernel, endkernel, pic_ext_intr);
305
306 #ifdef DDB
307 if (boothowto & RB_KDB)
308 Debugger();
309 #endif
310 }
311
312 /*
313 * UART input clock for the console and com devices.
314 */
315 uint32_t
316 sam460ex_com_freq(void)
317 {
318
319 #ifdef SAM460EX_FDT
320 if (sam460ex_fdt_info.fi_uart_freq != 0)
321 return sam460ex_fdt_info.fi_uart_freq;
322 #endif
323 return AMCC460EX_COM_FREQ;
324 }
325
326 void
327 consinit(void)
328 {
329
330 #if (NCOM > 0)
331 com_opb_cnattach(sam460ex_com_freq(), CONADDR, CONSPEED, CONMODE);
332 #endif
333 }
334
335 /*
336 * Parse /chosen/bootargs.
337 */
338 static char bootspec_buf[64];
339
340 /* Console target from the "console=" bootarg (see machine/sam460ex.h). */
341 enum sam460ex_console sam460ex_console = SAM460EX_CONS_COM;
342 int sam460ex_console_pci_bdf[3] = { -1, -1, -1 };
343
344 /*
345 * Parse an optional ":bus:dev:func" suffix for "console=pci"
346 */
347 static void
348 parse_pci_bdf(const char *s)
349 {
350 char *ep;
351 int i;
352
353 for (i = 0; i < 3 && *s == ':'; i++) {
354 sam460ex_console_pci_bdf[i] = (int)strtoul(s + 1, &ep, 0);
355 if (ep == s + 1) { /* no digits consumed */
356 sam460ex_console_pci_bdf[i] = -1;
357 return;
358 }
359 s = ep;
360 }
361 }
362
363 static void
364 parse_bootargs(const char *args)
365 {
366 const char *cp = args;
367
368 #define BA_DELIM(c) ((c) == ' ' || (c) == '"')
369 while (*cp != '\0') {
370 if (BA_DELIM(*cp)) {
371 cp++;
372 continue;
373 }
374 if (*cp == '-') {
375 for (cp++; *cp != '\0' && !BA_DELIM(*cp); cp++)
376 BOOT_FLAG(*cp, boothowto);
377 } else if (strncmp(cp, "root=", 5) == 0) {
378 char *bp = bootspec_buf;
379
380 for (cp += 5; *cp != '\0' && !BA_DELIM(*cp) &&
381 bp < &bootspec_buf[sizeof(bootspec_buf) - 1]; )
382 *bp++ = *cp++;
383 *bp = '\0';
384 if (bootspec_buf[0] != '\0') {
385 bootspec = bootspec_buf;
386 booted_method = "bootargs/root";
387 }
388 } else if (strncmp(cp, "console=", 8) == 0) {
389 char cbuf[24];
390 char *bp = cbuf;
391
392 for (cp += 8; *cp != '\0' && !BA_DELIM(*cp) &&
393 bp < &cbuf[sizeof(cbuf) - 1]; )
394 *bp++ = *cp++;
395 *bp = '\0';
396
397 if (strcmp(cbuf, "com0") == 0 ||
398 strcmp(cbuf, "serial") == 0)
399 sam460ex_console = SAM460EX_CONS_COM;
400 else if (strcmp(cbuf, "sm502") == 0 ||
401 strcmp(cbuf, "fb") == 0)
402 sam460ex_console = SAM460EX_CONS_SM502;
403 else if (strncmp(cbuf, "pci", 3) == 0) {
404 sam460ex_console = SAM460EX_CONS_PCI;
405 parse_pci_bdf(&cbuf[3]);
406 }
407 } else {
408 while (*cp != '\0' && !BA_DELIM(*cp))
409 cp++;
410 }
411 }
412 #undef BA_DELIM
413 }
414
415 /*
416 * Sanitize EHCI state before the kernel takes over the USB host controller.
417 */
418 static void
419 sam460ex_usb_host_init(void)
420 {
421 volatile uint32_t *gpio;
422 uint32_t v, srst;
423 const uint32_t pin = 0x00008000; /* GPIO16 = bit 15 in OR/TCR */
424
425 /* AHB-to-PLB bridge config: 460EX errata for concurrent USB/SATA. */
426 v = mfsdr(DCR_SDR0_AHB_CFG);
427 v |= SDR0_AHB_CFG_A2P_INCR4;
428 v &= ~SDR0_AHB_CFG_A2P_PROT2;
429 mtsdr(DCR_SDR0_AHB_CFG, v);
430
431 /* USB 2.0 host wrapper config (Sam460ex value). */
432 v = mfsdr(DCR_SDR0_USB2HOST_CFG);
433 v &= ~0x0000ff00;
434 v |= 0x00004400;
435 mtsdr(DCR_SDR0_USB2HOST_CFG, v);
436
437 gpio = ppc4xx_tlb_mapiodev(AMCC460EX_GPIO0_BASE, 0x40);
438
439 /*
440 * Reset and re-sync the USB 2.0 host and its external ULPI PHY
441 */
442 srst = mfsdr(DCR_SDR0_SRST1);
443 mtsdr(DCR_SDR0_SRST1, srst | SDR0_SRST1_USBHOST);
444
445 if (gpio != NULL) {
446 /* GPIO16 -> GPIO mode, output low */
447 gpio[0x04 / 4] &= ~pin; /* TCR: tristate */
448 gpio[0x0c / 4] &= ~0xc0000000; /* OSRH: select GPIO */
449 gpio[0x00 / 4] &= ~pin; /* OR: drive low */
450 gpio[0x04 / 4] |= pin; /* TCR: drive output */
451 }
452
453 delay(500 * 1000);
454
455 if (gpio != NULL) {
456 /* GPIO16 -> ALT1 (USB2HostStop), output high */
457 gpio[0x04 / 4] &= ~pin;
458 gpio[0x0c / 4] = (gpio[0x0c / 4] & ~0xc0000000) | 0x40000000;
459 gpio[0x00 / 4] |= pin;
460 gpio[0x04 / 4] |= pin;
461 }
462
463 mtsdr(DCR_SDR0_SRST1, srst & ~SDR0_SRST1_USBHOST);
464 delay(200 * 1000);
465 }
466
467 /*
468 * Machine dependent startup code.
469 */
470 void
471 cpu_startup(void)
472 {
473 prop_number_t pn;
474 uint32_t cpu_freq = SAM460EX_CPU_FREQ;
475 uint32_t opb_freq = SAM460EX_OPB_FREQ;
476 uint32_t memsize = SAM460EX_MEMSIZE;
477
478 ibm4xx_cpu_startup("ACube Sam460ex (AMCC 460EX)");
479
480 /* re-init the on-chip USB host so it doesn't depend on firmware state */
481 sam460ex_usb_host_init();
482
483 #ifdef SAM460EX_FDT
484 /*
485 * The timebase runs at the CPU clock; "processor-frequency"
486 * feeds delay() and the DEC reload value.
487 */
488 if (sam460ex_fdt_info.fi_timebase_freq != 0)
489 cpu_freq = sam460ex_fdt_info.fi_timebase_freq;
490 else if (sam460ex_fdt_info.fi_cpu_freq != 0)
491 cpu_freq = sam460ex_fdt_info.fi_cpu_freq;
492 if (sam460ex_fdt_info.fi_opb_freq != 0)
493 opb_freq = sam460ex_fdt_info.fi_opb_freq;
494 if (sam460ex_fdt_info.fi_memsize != 0)
495 memsize = sam460ex_fdt_info.fi_memsize;
496 printf("sam460ex: fdt cpu %u Hz, opb %u Hz, uart %u Hz, mem %u MB\n",
497 cpu_freq, opb_freq, sam460ex_fdt_info.fi_uart_freq,
498 memsize / (1024 * 1024));
499 if (sam460ex_fdt_info.fi_bootargs != NULL) {
500 printf("bootargs: %s\n", sam460ex_fdt_info.fi_bootargs);
501 parse_bootargs(sam460ex_fdt_info.fi_bootargs);
502 }
503 #endif
504
505 #if NUKBD > 0
506 /* Glass consoles (SM502 or a PCI display) take keyboard input via USB. */
507 if (sam460ex_console == SAM460EX_CONS_SM502 ||
508 sam460ex_console == SAM460EX_CONS_PCI) {
509 ukbd_cnattach();
510 }
511 #endif
512
513 /*
514 * Set up the board props
515 */
516 board_info_init();
517
518 pn = prop_number_create_integer(cpu_freq);
519 KASSERT(pn != NULL);
520 if (prop_dictionary_set(board_properties, "processor-frequency",
521 pn) == false)
522 panic("setting processor-frequency");
523 prop_object_release(pn);
524
525 pn = prop_number_create_integer(opb_freq);
526 KASSERT(pn != NULL);
527 if (prop_dictionary_set(board_properties, "opb-frequency", pn) ==
528 false)
529 panic("setting opb-frequency");
530 prop_object_release(pn);
531
532 pn = prop_number_create_integer(memsize);
533 KASSERT(pn != NULL);
534 if (prop_dictionary_set(board_properties, "mem-size", pn) == false)
535 panic("setting mem-size");
536 prop_object_release(pn);
537
538 #ifdef SAM460EX_FDT
539 /*
540 * EMAC MAC addresses from the device tree filled by U-Boot
541 */
542 for (int i = 0; i < SAM460EX_NEMAC; i++) {
543 char propname[16];
544 prop_data_t pd;
545
546 if (!sam460ex_fdt_info.fi_enaddr_valid[i])
547 continue;
548 snprintf(propname, sizeof(propname), "emac%d-mac-addr", i);
549 pd = prop_data_create_data_nocopy(
550 sam460ex_fdt_info.fi_enaddr[i], 6);
551 KASSERT(pd != NULL);
552 if (prop_dictionary_set(board_properties, propname, pd) ==
553 false)
554 panic("setting %s", propname);
555 prop_object_release(pd);
556
557 snprintf(propname, sizeof(propname), "emac%d-mii-phy", i);
558 pn = prop_number_create_integer(i);
559 KASSERT(pn != NULL);
560 if (prop_dictionary_set(board_properties, propname, pn) ==
561 false)
562 panic("setting %s", propname);
563 prop_object_release(pn);
564 }
565 #endif
566
567 calc_delayconst();
568
569 /*
570 * Now that we have VM, malloc is OK
571 */
572 bus_space_mallocok();
573 fake_mapiodev = 0;
574 }
575
576 /*
577 * PCI interrupt routing and slot policy for the on-chip PLB-PCIX
578 * bridge (see powerpc/ibm4xx/pci/pcix.c).
579 *
580 * XXX: On the Sam460ex every PCI intr pin is wired to UIC1 bit 0?
581 */
582 int
583 ibm4xx_pci_bus_maxdevs(void *v, int busno)
584 {
585 return 16;
586 }
587
588 /*
589 * Board interrupt routing for the PCI-X slot. Unlike the AMCC Canyonlands
590 * design (where the SoC's external IRQ2 / UIC1 bit 0 is the PCI INT), the
591 * Sam460ex wire-ORs all PCI INTx through its FPGA onto UIC1 bit 3 = irq 35
592 */
593 #define SAM460EX_PCI_INTR_IRQ 32 /* TEMP, see above; correct value is 35? */
594
595 int
596 ibm4xx_pci_intr_map(const struct pci_attach_args *pa, pci_intr_handle_t *ihp)
597 {
598 *ihp = SAM460EX_PCI_INTR_IRQ;
599 return 0;
600 }
601
602 void
603 ibm4xx_pci_conf_interrupt(void *v, int bus, int dev, int pin, int swiz,
604 int *iline)
605 {
606 *iline = SAM460EX_PCI_INTR_IRQ;
607 }
608
609 #define UIC_DUMP(n, base) \
610 blen += snprintf(buf + blen, sizeof(buf) - blen, \
611 "uic%d SR=%08x MSR=%08x ER=%08x PR=%08x TR=%08x\n", (n), \
612 (unsigned int)mfdcr((base) + DCR_UIC_SR), \
613 (unsigned int)mfdcr((base) + DCR_UIC_MSR), \
614 (unsigned int)mfdcr((base) + DCR_UIC_ER), \
615 (unsigned int)mfdcr((base) + DCR_UIC_PR), \
616 (unsigned int)mfdcr((base) + DCR_UIC_TR))
617
618 static int
619 sysctl_machdep_uicregs(SYSCTLFN_ARGS)
620 {
621 struct sysctlnode node;
622 char buf[400];
623 int blen = 0;
624
625 UIC_DUMP(0, DCR_UIC0_BASE);
626 UIC_DUMP(1, DCR_UIC1_BASE);
627 UIC_DUMP(2, DCR_UIC2_BASE);
628 UIC_DUMP(3, DCR_UIC3_BASE);
629
630 node = *rnode;
631 node.sysctl_data = buf;
632 node.sysctl_size = strlen(buf) + 1;
633 return sysctl_lookup(SYSCTLFN_CALL(&node));
634 }
635 #undef UIC_DUMP
636
637 SYSCTL_SETUP(sysctl_machdep_uicregs_setup, "sam460ex UIC register dump")
638 {
639
640 sysctl_createv(clog, 0, NULL, NULL,
641 CTLFLAG_PERMANENT | CTLFLAG_READONLY,
642 CTLTYPE_STRING, "uicregs",
643 SYSCTL_DESCR("UIC0-3 SR/MSR/ER/PR/TR (interrupt debug)"),
644 sysctl_machdep_uicregs, 0, NULL, 0,
645 CTL_MACHDEP, CTL_CREATE, CTL_EOL);
646 }
647
648