bcm283x_platform.c revision 1.10 1 /* $NetBSD: bcm283x_platform.c,v 1.10 2018/08/03 15:46:41 skrll Exp $ */
2
3 /*-
4 * Copyright (c) 2017 Jared D. McNeill <jmcneill (at) invisible.ca>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29 #include <sys/cdefs.h>
30 __KERNEL_RCSID(0, "$NetBSD: bcm283x_platform.c,v 1.10 2018/08/03 15:46:41 skrll Exp $");
31
32 #include "opt_arm_debug.h"
33 #include "opt_bcm283x.h"
34 #include "opt_cpuoptions.h"
35 #include "opt_ddb.h"
36 #include "opt_evbarm_boardtype.h"
37 #include "opt_kgdb.h"
38 #include "opt_fdt.h"
39 #include "opt_rpi.h"
40 #include "opt_vcprop.h"
41
42 #include "sdhc.h"
43 #include "bcmsdhost.h"
44 #include "bcmdwctwo.h"
45 #include "bcmspi.h"
46 #include "bsciic.h"
47 #include "plcom.h"
48 #include "com.h"
49 #include "genfb.h"
50 #include "ukbd.h"
51
52 #include <sys/param.h>
53 #include <sys/bus.h>
54 #include <sys/cpu.h>
55 #include <sys/device.h>
56 #include <sys/termios.h>
57
58 #include <net/if_ether.h>
59
60 #include <prop/proplib.h>
61
62 #include <dev/fdt/fdtvar.h>
63
64 #include <uvm/uvm_extern.h>
65
66 #include <machine/bootconfig.h>
67
68 #include <arm/armreg.h>
69 #include <arm/cpufunc.h>
70
71 #include <libfdt.h>
72
73 #include <arm/broadcom/bcm2835reg.h>
74 #include <arm/broadcom/bcm2835var.h>
75 #include <arm/broadcom/bcm283x_platform.h>
76 #include <arm/broadcom/bcm2835_intr.h>
77 #include <arm/broadcom/bcm2835_mbox.h>
78 #include <arm/broadcom/bcm2835_pmwdogvar.h>
79
80 #include <evbarm/dev/plcomreg.h>
81 #include <evbarm/dev/plcomvar.h>
82 #include <evbarm/fdt/machdep.h>
83
84 #include <dev/ic/ns16550reg.h>
85 #include <dev/ic/comreg.h>
86
87 #include <evbarm/rpi/vcio.h>
88 #include <evbarm/rpi/vcpm.h>
89 #include <evbarm/rpi/vcprop.h>
90
91 #include <arm/fdt/arm_fdtvar.h>
92
93 #include <arm/cortex/gtmr_var.h>
94
95 #if NGENFB > 0
96 #include <dev/videomode/videomode.h>
97 #include <dev/videomode/edidvar.h>
98 #include <dev/wscons/wsconsio.h>
99 #endif
100
101 #if NUKBD > 0
102 #include <dev/usb/ukbdvar.h>
103 #endif
104
105 #ifdef DDB
106 #include <machine/db_machdep.h>
107 #include <ddb/db_sym.h>
108 #include <ddb/db_extern.h>
109 #endif
110
111 void bcm283x_platform_early_putchar(vaddr_t, paddr_t, char c);
112 void bcm2835_platform_early_putchar(char c);
113 void bcm2836_platform_early_putchar(char c);
114 void bcm2837_platform_early_putchar(char c);
115
116 extern void bcmgenfb_set_console_dev(device_t dev);
117 void bcmgenfb_set_ioctl(int(*)(void *, void *, u_long, void *, int, struct lwp *));
118 extern void bcmgenfb_ddb_trap_callback(int where);
119 static int rpi_ioctl(void *, void *, u_long, void *, int, lwp_t *);
120
121 extern struct bus_space arm_generic_bs_tag;
122 extern struct bus_space arm_generic_a4x_bs_tag;
123
124 /* Prototypes for all the bus_space structure functions */
125 bs_protos(arm_generic);
126 bs_protos(arm_generic_a4x);
127 bs_protos(bcm2835);
128 bs_protos(bcm2835_a4x);
129 bs_protos(bcm2836);
130 bs_protos(bcm2836_a4x);
131
132 struct bus_space bcm2835_bs_tag;
133 struct bus_space bcm2835_a4x_bs_tag;
134 struct bus_space bcm2836_bs_tag;
135 struct bus_space bcm2836_a4x_bs_tag;
136
137 int bcm283x_bs_map(void *, bus_addr_t, bus_size_t, int, bus_space_handle_t *);
138 paddr_t bcm283x_bs_mmap(void *, bus_addr_t, off_t, int, int);
139 paddr_t bcm283x_a4x_bs_mmap(void *, bus_addr_t, off_t, int, int);
140
141 int
142 bcm283x_bs_map(void *t, bus_addr_t ba, bus_size_t size, int flag,
143 bus_space_handle_t *bshp)
144 {
145 u_long startpa, endpa, pa;
146 vaddr_t va;
147
148 /* Convert BA to PA */
149 pa = ba & ~BCM2835_BUSADDR_CACHE_MASK;
150
151 startpa = trunc_page(pa);
152 endpa = round_page(pa + size);
153
154 /* XXX use extent manager to check duplicate mapping */
155
156 va = uvm_km_alloc(kernel_map, endpa - startpa, 0,
157 UVM_KMF_VAONLY | UVM_KMF_NOWAIT | UVM_KMF_COLORMATCH);
158 if (!va)
159 return ENOMEM;
160
161 *bshp = (bus_space_handle_t)(va + (pa - startpa));
162
163 int pmapflags;
164 if (flag & BUS_SPACE_MAP_PREFETCHABLE)
165 pmapflags = PMAP_WRITE_COMBINE;
166 else if (flag & BUS_SPACE_MAP_CACHEABLE)
167 pmapflags = 0;
168 else
169 pmapflags = PMAP_NOCACHE;
170 for (pa = startpa; pa < endpa; pa += PAGE_SIZE, va += PAGE_SIZE) {
171 pmap_kenter_pa(va, pa, VM_PROT_READ | VM_PROT_WRITE, pmapflags);
172 }
173 pmap_update(pmap_kernel());
174
175 return 0;
176 }
177
178 paddr_t
179 bcm283x_bs_mmap(void *t, bus_addr_t bpa, off_t offset, int prot, int flags)
180 {
181 /* Convert BA to PA */
182 const paddr_t pa = bpa & ~BCM2835_BUSADDR_CACHE_MASK;
183 paddr_t bus_flags = 0;
184
185 if (flags & BUS_SPACE_MAP_PREFETCHABLE)
186 bus_flags |= ARM_MMAP_WRITECOMBINE;
187
188 return arm_btop(pa + offset) | bus_flags;
189 }
190
191 paddr_t
192 bcm283x_a4x_bs_mmap(void *t, bus_addr_t bpa, off_t offset, int prot, int flags)
193 {
194 /* Convert BA to PA */
195 const paddr_t pa = bpa & ~BCM2835_BUSADDR_CACHE_MASK;
196 paddr_t bus_flags = 0;
197
198 if (flags & BUS_SPACE_MAP_PREFETCHABLE)
199 bus_flags |= ARM_MMAP_WRITECOMBINE;
200
201 return arm_btop(pa + 4 * offset) | bus_flags;
202 }
203
204 int
205 bcm2835_bs_map(void *t, bus_addr_t ba, bus_size_t size, int flag,
206 bus_space_handle_t *bshp)
207 {
208 const struct pmap_devmap *pd;
209 bool match = false;
210 u_long pa;
211
212 /* Attempt to find the PA device mapping */
213 if (ba >= BCM2835_PERIPHERALS_BASE_BUS &&
214 ba < BCM2835_PERIPHERALS_BASE_BUS + BCM2835_PERIPHERALS_SIZE) {
215 match = true;
216 pa = BCM2835_PERIPHERALS_BUS_TO_PHYS(ba);
217 }
218
219 if (match && (pd = pmap_devmap_find_pa(pa, size)) != NULL) {
220 /* Device was statically mapped. */
221 *bshp = pd->pd_va + (pa - pd->pd_pa);
222 return 0;
223 }
224
225 return bcm283x_bs_map(t, ba, size, flag, bshp);
226 }
227
228 int
229 bcm2836_bs_map(void *t, bus_addr_t ba, bus_size_t size, int flag,
230 bus_space_handle_t *bshp)
231 {
232 const struct pmap_devmap *pd;
233 bool match = false;
234 u_long pa;
235
236 /* Attempt to find the PA device mapping */
237 if (ba >= BCM2835_PERIPHERALS_BASE_BUS &&
238 ba < BCM2835_PERIPHERALS_BASE_BUS + BCM2835_PERIPHERALS_SIZE) {
239 match = true;
240 pa = BCM2836_PERIPHERALS_BUS_TO_PHYS(ba);
241 }
242
243 if (ba >= BCM2836_ARM_LOCAL_BASE &&
244 ba < BCM2836_ARM_LOCAL_BASE + BCM2836_ARM_LOCAL_SIZE) {
245 match = true;
246 pa = ba;
247 }
248
249 if (match && (pd = pmap_devmap_find_pa(pa, size)) != NULL) {
250 /* Device was statically mapped. */
251 *bshp = pd->pd_va + (pa - pd->pd_pa);
252 return 0;
253 }
254
255 return bcm283x_bs_map(t, ba, size, flag, bshp);
256 }
257
258 struct arm32_dma_range bcm2835_dma_ranges[] = {
259 [0] = {
260 .dr_sysbase = 0,
261 .dr_busbase = BCM2835_BUSADDR_CACHE_COHERENT,
262 }
263 };
264
265 struct arm32_dma_range bcm2836_dma_ranges[] = {
266 [0] = {
267 .dr_sysbase = 0,
268 .dr_busbase = BCM2835_BUSADDR_CACHE_DIRECT,
269 }
270 };
271
272
273 #if defined(SOC_BCM2835)
274 static const struct pmap_devmap *
275 bcm2835_platform_devmap(void)
276 {
277 static const struct pmap_devmap devmap[] = {
278 DEVMAP_ENTRY(BCM2835_PERIPHERALS_VBASE, BCM2835_PERIPHERALS_BASE,
279 BCM2835_PERIPHERALS_SIZE), /* 16Mb */
280
281 DEVMAP_ENTRY_END
282 };
283
284 return devmap;
285 }
286 #endif
287
288 #if defined(SOC_BCM2836)
289 static const struct pmap_devmap *
290 bcm2836_platform_devmap(void)
291 {
292 static const struct pmap_devmap devmap[] = {
293 DEVMAP_ENTRY(BCM2836_PERIPHERALS_VBASE, BCM2836_PERIPHERALS_BASE,
294 BCM2835_PERIPHERALS_SIZE), /* 16Mb */
295
296 DEVMAP_ENTRY(BCM2836_ARM_LOCAL_VBASE, BCM2836_ARM_LOCAL_BASE,
297 BCM2836_ARM_LOCAL_SIZE),
298
299 DEVMAP_ENTRY_END
300 };
301
302 return devmap;
303 }
304 #endif
305 /*
306 * Macros to translate between physical and virtual for a subset of the
307 * kernel address space. *Not* for general use.
308 */
309
310 #ifndef RPI_FB_WIDTH
311 #define RPI_FB_WIDTH 1280
312 #endif
313 #ifndef RPI_FB_HEIGHT
314 #define RPI_FB_HEIGHT 720
315 #endif
316
317 int uart_clk = BCM2835_UART0_CLK;
318 int core_clk;
319
320 static struct {
321 struct vcprop_buffer_hdr vb_hdr;
322 struct vcprop_tag_clockrate vbt_uartclockrate;
323 struct vcprop_tag_clockrate vbt_vpuclockrate;
324 struct vcprop_tag end;
325 } vb_uart __cacheline_aligned = {
326 .vb_hdr = {
327 .vpb_len = sizeof(vb_uart),
328 .vpb_rcode = VCPROP_PROCESS_REQUEST,
329 },
330 .vbt_uartclockrate = {
331 .tag = {
332 .vpt_tag = VCPROPTAG_GET_CLOCKRATE,
333 .vpt_len = VCPROPTAG_LEN(vb_uart.vbt_uartclockrate),
334 .vpt_rcode = VCPROPTAG_REQUEST
335 },
336 .id = VCPROP_CLK_UART
337 },
338 .vbt_vpuclockrate = {
339 .tag = {
340 .vpt_tag = VCPROPTAG_GET_CLOCKRATE,
341 .vpt_len = VCPROPTAG_LEN(vb_uart.vbt_vpuclockrate),
342 .vpt_rcode = VCPROPTAG_REQUEST
343 },
344 .id = VCPROP_CLK_CORE
345 },
346 .end = {
347 .vpt_tag = VCPROPTAG_NULL
348 }
349 };
350
351 static struct {
352 struct vcprop_buffer_hdr vb_hdr;
353 struct vcprop_tag_fwrev vbt_fwrev;
354 struct vcprop_tag_boardmodel vbt_boardmodel;
355 struct vcprop_tag_boardrev vbt_boardrev;
356 struct vcprop_tag_macaddr vbt_macaddr;
357 struct vcprop_tag_memory vbt_memory;
358 struct vcprop_tag_boardserial vbt_serial;
359 struct vcprop_tag_dmachan vbt_dmachan;
360 struct vcprop_tag_cmdline vbt_cmdline;
361 struct vcprop_tag_clockrate vbt_emmcclockrate;
362 struct vcprop_tag_clockrate vbt_armclockrate;
363 struct vcprop_tag_clockrate vbt_vpuclockrate;
364 struct vcprop_tag end;
365 } vb __cacheline_aligned = {
366 .vb_hdr = {
367 .vpb_len = sizeof(vb),
368 .vpb_rcode = VCPROP_PROCESS_REQUEST,
369 },
370 .vbt_fwrev = {
371 .tag = {
372 .vpt_tag = VCPROPTAG_GET_FIRMWAREREV,
373 .vpt_len = VCPROPTAG_LEN(vb.vbt_fwrev),
374 .vpt_rcode = VCPROPTAG_REQUEST
375 },
376 },
377 .vbt_boardmodel = {
378 .tag = {
379 .vpt_tag = VCPROPTAG_GET_BOARDMODEL,
380 .vpt_len = VCPROPTAG_LEN(vb.vbt_boardmodel),
381 .vpt_rcode = VCPROPTAG_REQUEST
382 },
383 },
384 .vbt_boardrev = {
385 .tag = {
386 .vpt_tag = VCPROPTAG_GET_BOARDREVISION,
387 .vpt_len = VCPROPTAG_LEN(vb.vbt_boardrev),
388 .vpt_rcode = VCPROPTAG_REQUEST
389 },
390 },
391 .vbt_macaddr = {
392 .tag = {
393 .vpt_tag = VCPROPTAG_GET_MACADDRESS,
394 .vpt_len = VCPROPTAG_LEN(vb.vbt_macaddr),
395 .vpt_rcode = VCPROPTAG_REQUEST
396 },
397 },
398 .vbt_memory = {
399 .tag = {
400 .vpt_tag = VCPROPTAG_GET_ARMMEMORY,
401 .vpt_len = VCPROPTAG_LEN(vb.vbt_memory),
402 .vpt_rcode = VCPROPTAG_REQUEST
403 },
404 },
405 .vbt_serial = {
406 .tag = {
407 .vpt_tag = VCPROPTAG_GET_BOARDSERIAL,
408 .vpt_len = VCPROPTAG_LEN(vb.vbt_serial),
409 .vpt_rcode = VCPROPTAG_REQUEST
410 },
411 },
412 .vbt_dmachan = {
413 .tag = {
414 .vpt_tag = VCPROPTAG_GET_DMACHAN,
415 .vpt_len = VCPROPTAG_LEN(vb.vbt_dmachan),
416 .vpt_rcode = VCPROPTAG_REQUEST
417 },
418 },
419 .vbt_cmdline = {
420 .tag = {
421 .vpt_tag = VCPROPTAG_GET_CMDLINE,
422 .vpt_len = VCPROPTAG_LEN(vb.vbt_cmdline),
423 .vpt_rcode = VCPROPTAG_REQUEST
424 },
425 },
426 .vbt_emmcclockrate = {
427 .tag = {
428 .vpt_tag = VCPROPTAG_GET_CLOCKRATE,
429 .vpt_len = VCPROPTAG_LEN(vb.vbt_emmcclockrate),
430 .vpt_rcode = VCPROPTAG_REQUEST
431 },
432 .id = VCPROP_CLK_EMMC
433 },
434 .vbt_armclockrate = {
435 .tag = {
436 .vpt_tag = VCPROPTAG_GET_CLOCKRATE,
437 .vpt_len = VCPROPTAG_LEN(vb.vbt_armclockrate),
438 .vpt_rcode = VCPROPTAG_REQUEST
439 },
440 .id = VCPROP_CLK_ARM
441 },
442 .vbt_vpuclockrate = {
443 .tag = {
444 .vpt_tag = VCPROPTAG_GET_CLOCKRATE,
445 .vpt_len = VCPROPTAG_LEN(vb.vbt_vpuclockrate),
446 .vpt_rcode = VCPROPTAG_REQUEST
447 },
448 .id = VCPROP_CLK_CORE
449 },
450 .end = {
451 .vpt_tag = VCPROPTAG_NULL
452 }
453 };
454
455 #if NGENFB > 0
456 static struct {
457 struct vcprop_buffer_hdr vb_hdr;
458 struct vcprop_tag_edidblock vbt_edid;
459 struct vcprop_tag end;
460 } vb_edid __cacheline_aligned = {
461 .vb_hdr = {
462 .vpb_len = sizeof(vb_edid),
463 .vpb_rcode = VCPROP_PROCESS_REQUEST,
464 },
465 .vbt_edid = {
466 .tag = {
467 .vpt_tag = VCPROPTAG_GET_EDID_BLOCK,
468 .vpt_len = VCPROPTAG_LEN(vb_edid.vbt_edid),
469 .vpt_rcode = VCPROPTAG_REQUEST,
470 },
471 .blockno = 0,
472 },
473 .end = {
474 .vpt_tag = VCPROPTAG_NULL
475 }
476 };
477
478 static struct {
479 struct vcprop_buffer_hdr vb_hdr;
480 struct vcprop_tag_fbres vbt_res;
481 struct vcprop_tag_fbres vbt_vres;
482 struct vcprop_tag_fbdepth vbt_depth;
483 struct vcprop_tag_fbalpha vbt_alpha;
484 struct vcprop_tag_allocbuf vbt_allocbuf;
485 struct vcprop_tag_blankscreen vbt_blank;
486 struct vcprop_tag_fbpitch vbt_pitch;
487 struct vcprop_tag end;
488 } vb_setfb __cacheline_aligned = {
489 .vb_hdr = {
490 .vpb_len = sizeof(vb_setfb),
491 .vpb_rcode = VCPROP_PROCESS_REQUEST,
492 },
493 .vbt_res = {
494 .tag = {
495 .vpt_tag = VCPROPTAG_SET_FB_RES,
496 .vpt_len = VCPROPTAG_LEN(vb_setfb.vbt_res),
497 .vpt_rcode = VCPROPTAG_REQUEST,
498 },
499 .width = 0,
500 .height = 0,
501 },
502 .vbt_vres = {
503 .tag = {
504 .vpt_tag = VCPROPTAG_SET_FB_VRES,
505 .vpt_len = VCPROPTAG_LEN(vb_setfb.vbt_vres),
506 .vpt_rcode = VCPROPTAG_REQUEST,
507 },
508 .width = 0,
509 .height = 0,
510 },
511 .vbt_depth = {
512 .tag = {
513 .vpt_tag = VCPROPTAG_SET_FB_DEPTH,
514 .vpt_len = VCPROPTAG_LEN(vb_setfb.vbt_depth),
515 .vpt_rcode = VCPROPTAG_REQUEST,
516 },
517 .bpp = 32,
518 },
519 .vbt_alpha = {
520 .tag = {
521 .vpt_tag = VCPROPTAG_SET_FB_ALPHA_MODE,
522 .vpt_len = VCPROPTAG_LEN(vb_setfb.vbt_alpha),
523 .vpt_rcode = VCPROPTAG_REQUEST,
524 },
525 .state = VCPROP_ALPHA_IGNORED,
526 },
527 .vbt_allocbuf = {
528 .tag = {
529 .vpt_tag = VCPROPTAG_ALLOCATE_BUFFER,
530 .vpt_len = VCPROPTAG_LEN(vb_setfb.vbt_allocbuf),
531 .vpt_rcode = VCPROPTAG_REQUEST,
532 },
533 .address = PAGE_SIZE, /* alignment */
534 },
535 .vbt_blank = {
536 .tag = {
537 .vpt_tag = VCPROPTAG_BLANK_SCREEN,
538 .vpt_len = VCPROPTAG_LEN(vb_setfb.vbt_blank),
539 .vpt_rcode = VCPROPTAG_REQUEST,
540 },
541 .state = VCPROP_BLANK_OFF,
542 },
543 .vbt_pitch = {
544 .tag = {
545 .vpt_tag = VCPROPTAG_GET_FB_PITCH,
546 .vpt_len = VCPROPTAG_LEN(vb_setfb.vbt_pitch),
547 .vpt_rcode = VCPROPTAG_REQUEST,
548 },
549 },
550 .end = {
551 .vpt_tag = VCPROPTAG_NULL,
552 },
553 };
554
555 #endif
556
557 static int rpi_video_on = WSDISPLAYIO_VIDEO_ON;
558
559 #if defined(RPI_HWCURSOR)
560 #define CURSOR_BITMAP_SIZE (64 * 8)
561 #define CURSOR_ARGB_SIZE (64 * 64 * 4)
562 static uint32_t hcursor = 0;
563 static bus_addr_t pcursor = 0;
564 static uint32_t *cmem = NULL;
565 static int cursor_x = 0, cursor_y = 0, hot_x = 0, hot_y = 0, cursor_on = 0;
566 static uint32_t cursor_cmap[4];
567 static uint8_t cursor_mask[8 * 64], cursor_bitmap[8 * 64];
568 #endif
569
570 u_int
571 bcm283x_clk_get_rate_uart(void)
572 {
573
574 if (vcprop_tag_success_p(&vb_uart.vbt_uartclockrate.tag))
575 return vb_uart.vbt_uartclockrate.rate;
576 return 0;
577 }
578
579 u_int
580 bcm283x_clk_get_rate_vpu(void)
581 {
582
583 if (vcprop_tag_success_p(&vb.vbt_vpuclockrate.tag) &&
584 vb.vbt_vpuclockrate.rate > 0) {
585 return vb.vbt_vpuclockrate.rate;
586 }
587 return 0;
588 }
589
590 u_int
591 bcm283x_clk_get_rate_emmc(void)
592 {
593
594 if (vcprop_tag_success_p(&vb.vbt_emmcclockrate.tag) &&
595 vb.vbt_emmcclockrate.rate > 0) {
596 return vb.vbt_emmcclockrate.rate;
597 }
598 return 0;
599 }
600
601
602
603 static void
604 bcm283x_uartinit(bus_space_tag_t iot, bus_space_handle_t ioh)
605 {
606 uint32_t res;
607
608 bcm2835_mbox_write(iot, ioh, BCMMBOX_CHANARM2VC,
609 KERN_VTOPHYS((vaddr_t)&vb_uart));
610
611 bcm2835_mbox_read(iot, ioh, BCMMBOX_CHANARM2VC, &res);
612
613 cpu_dcache_inv_range((vaddr_t)&vb_uart, sizeof(vb_uart));
614
615 if (vcprop_tag_success_p(&vb_uart.vbt_uartclockrate.tag))
616 uart_clk = vb_uart.vbt_uartclockrate.rate;
617 if (vcprop_tag_success_p(&vb_uart.vbt_vpuclockrate.tag))
618 core_clk = vb_uart.vbt_vpuclockrate.rate;
619 }
620
621 #if defined(SOC_BCM2835)
622 static void
623 bcm2835_uartinit(void)
624 {
625 const paddr_t pa = BCM2835_PERIPHERALS_BUS_TO_PHYS(BCM2835_ARMMBOX_BASE);
626 const bus_space_tag_t iot = &bcm2835_bs_tag;
627 const bus_space_handle_t ioh = BCM2835_IOPHYSTOVIRT(pa);
628
629 bcm283x_uartinit(iot, ioh);
630 }
631 #endif
632
633 #if defined(SOC_BCM2836)
634 static void
635 bcm2836_uartinit(void)
636 {
637 const paddr_t pa = BCM2836_PERIPHERALS_BUS_TO_PHYS(BCM2835_ARMMBOX_BASE);
638 const bus_space_tag_t iot = &bcm2836_bs_tag;
639 const bus_space_handle_t ioh = BCM2835_IOPHYSTOVIRT(pa);
640
641 bcm283x_uartinit(iot, ioh);
642 }
643 #endif
644
645 #define BCM283x_MINIMUM_SPLIT (128U * 1024 * 1024)
646
647 static size_t bcm283x_memorysize;
648
649 static void
650 bcm283x_bootparams(bus_space_tag_t iot, bus_space_handle_t ioh)
651 {
652 uint32_t res;
653
654 bcm2835_mbox_write(iot, ioh, BCMMBOX_CHANPM, (
655 #if (NSDHC > 0)
656 (1 << VCPM_POWER_SDCARD) |
657 #endif
658 #if (NPLCOM > 0)
659 (1 << VCPM_POWER_UART0) |
660 #endif
661 #if (NBCMDWCTWO > 0)
662 (1 << VCPM_POWER_USB) |
663 #endif
664 #if (NBSCIIC > 0)
665 (1 << VCPM_POWER_I2C0) | (1 << VCPM_POWER_I2C1) |
666 /* (1 << VCPM_POWER_I2C2) | */
667 #endif
668 #if (NBCMSPI > 0)
669 (1 << VCPM_POWER_SPI) |
670 #endif
671 0) << 4);
672
673 bcm2835_mbox_write(iot, ioh, BCMMBOX_CHANARM2VC,
674 KERN_VTOPHYS((vaddr_t)&vb));
675
676 bcm2835_mbox_read(iot, ioh, BCMMBOX_CHANARM2VC, &res);
677
678 cpu_dcache_inv_range((vaddr_t)&vb, sizeof(vb));
679
680 if (!vcprop_buffer_success_p(&vb.vb_hdr)) {
681 bootconfig.dramblocks = 1;
682 bootconfig.dram[0].address = 0x0;
683 bootconfig.dram[0].pages = atop(BCM283x_MINIMUM_SPLIT);
684 return;
685 }
686
687 struct vcprop_tag_memory *vptp_mem = &vb.vbt_memory;
688 if (vcprop_tag_success_p(&vptp_mem->tag)) {
689 size_t n = vcprop_tag_resplen(&vptp_mem->tag) /
690 sizeof(struct vcprop_memory);
691
692 bcm283x_memorysize = 0;
693 bootconfig.dramblocks = 0;
694
695 for (int i = 0; i < n && i < DRAM_BLOCKS; i++) {
696 bootconfig.dram[i].address = vptp_mem->mem[i].base;
697 bootconfig.dram[i].pages = atop(vptp_mem->mem[i].size);
698 bootconfig.dramblocks++;
699
700 bcm283x_memorysize += vptp_mem->mem[i].size;
701 }
702 }
703
704 if (vcprop_tag_success_p(&vb.vbt_armclockrate.tag))
705 curcpu()->ci_data.cpu_cc_freq = vb.vbt_armclockrate.rate;
706
707 #ifdef VERBOSE_INIT_ARM
708 if (vcprop_tag_success_p(&vb.vbt_memory.tag)) {
709 printf("%s: memory size %d\n", __func__,
710 vb.vbt_armclockrate.rate);
711 }
712 if (vcprop_tag_success_p(&vb.vbt_armclockrate.tag))
713 printf("%s: arm clock %d\n", __func__,
714 vb.vbt_armclockrate.rate);
715 if (vcprop_tag_success_p(&vb.vbt_fwrev.tag))
716 printf("%s: firmware rev %x\n", __func__,
717 vb.vbt_fwrev.rev);
718 if (vcprop_tag_success_p(&vb.vbt_boardmodel.tag))
719 printf("%s: board model %x\n", __func__,
720 vb.vbt_boardmodel.model);
721 if (vcprop_tag_success_p(&vb.vbt_macaddr.tag))
722 printf("%s: mac-address %" PRIx64 "\n", __func__,
723 vb.vbt_macaddr.addr);
724 if (vcprop_tag_success_p(&vb.vbt_boardrev.tag))
725 printf("%s: board rev %x\n", __func__,
726 vb.vbt_boardrev.rev);
727 if (vcprop_tag_success_p(&vb.vbt_serial.tag))
728 printf("%s: board serial %" PRIx64 "\n", __func__,
729 vb.vbt_serial.sn);
730 if (vcprop_tag_success_p(&vb.vbt_dmachan.tag))
731 printf("%s: DMA channel mask 0x%08x\n", __func__,
732 vb.vbt_dmachan.mask);
733
734 if (vcprop_tag_success_p(&vb.vbt_cmdline.tag))
735 printf("%s: cmdline %s\n", __func__,
736 vb.vbt_cmdline.cmdline);
737 #endif
738 }
739
740 #if defined(SOC_BCM2835)
741 static void
742 bcm2835_bootparams(void)
743 {
744 const paddr_t pa = BCM2835_PERIPHERALS_BUS_TO_PHYS(BCM2835_ARMMBOX_BASE);
745 const bus_space_tag_t iot = &bcm2835_bs_tag;
746 const bus_space_handle_t ioh = BCM2835_IOPHYSTOVIRT(pa);
747
748 bcm283x_bootparams(iot, ioh);
749 }
750 #endif
751
752 #if defined(SOC_BCM2836)
753 static void
754 bcm2836_bootparams(void)
755 {
756 const paddr_t pa = BCM2836_PERIPHERALS_BUS_TO_PHYS(BCM2835_ARMMBOX_BASE);
757 const bus_space_tag_t iot = &bcm2836_bs_tag;
758 const bus_space_handle_t ioh = BCM2835_IOPHYSTOVIRT(pa);
759
760 bcm283x_bootparams(iot, ioh);
761 }
762
763 static void
764 bcm2836_bootstrap(void)
765 {
766 #define RPI_CPU_MAX 4
767
768 #ifdef VERBOSE_INIT_ARM
769 #define DPRINTF(...) printf(__VA_ARGS__)
770 #else
771 #define DPRINTF(...)
772 #endif
773
774 #ifdef MULTIPROCESSOR
775 arm_cpu_max = RPI_CPU_MAX;
776 DPRINTF("%s: %d cpus present\n", __func__, arm_cpu_max);
777 #ifdef __arm__
778 extern int cortex_mmuinfo;
779 cortex_mmuinfo = armreg_ttbr_read();
780 DPRINTF("%s: cortex_mmuinfo %x\n", __func__, cortex_mmuinfo);
781 #endif
782 #endif /* MULTIPROCESSOR */
783
784 #ifdef __aarch64__
785 /*
786 * XXX: use psci_fdt_bootstrap()
787 */
788 extern void aarch64_mpstart(void);
789 for (int i = 1; i < RPI_CPU_MAX; i++) {
790 /*
791 * Reference:
792 * armstubs/armstub8.S
793 * in https://github.com/raspberrypi/tools
794 */
795 volatile uint64_t *cpu_release_addr;
796 #define RPI3_ARMSTUB8_SPINADDR_BASE 0x000000d8
797 cpu_release_addr = (void *)
798 AARCH64_PA_TO_KVA(RPI3_ARMSTUB8_SPINADDR_BASE + i * 8);
799 *cpu_release_addr = aarch64_kern_vtophys((vaddr_t)aarch64_mpstart);
800
801 /* need flush cache. secondary processors are cache disabled */
802 cpu_dcache_wb_range((vaddr_t)cpu_release_addr, sizeof(cpu_release_addr));
803 __asm __volatile("sev" ::: "memory");
804
805 #if defined(VERBOSE_INIT_ARM) && defined(EARLYCONS)
806 /* wait secondary processor's debug output */
807 gtmr_delay(100000);
808 #endif
809 }
810 #endif /* __aarch64__ */
811
812 #ifdef __arm__
813 /*
814 * Even if no options MULTIPROCESSOR,
815 * It is need to initialize the secondary CPU,
816 * and go into wfi loop (cortex_mpstart),
817 * otherwise system would be freeze...
818 */
819 extern void cortex_mpstart(void);
820
821 for (size_t i = 1; i < RPI_CPU_MAX; i++) {
822 bus_space_tag_t iot = &bcm2836_bs_tag;
823 bus_space_handle_t ioh = BCM2836_ARM_LOCAL_VBASE;
824
825 bus_space_write_4(iot, ioh,
826 BCM2836_LOCAL_MAILBOX3_SETN(i),
827 (uint32_t)cortex_mpstart);
828 }
829 #endif
830
831 #ifdef MULTIPROCESSOR
832 /* Wake up AP in case firmware has placed it in WFE state */
833 __asm __volatile("sev" ::: "memory");
834
835 for (int loop = 0; loop < 16; loop++) {
836 if (arm_cpu_hatched == __BITS(arm_cpu_max - 1, 1))
837 break;
838 gtmr_delay(10000);
839 }
840
841 for (size_t i = 1; i < arm_cpu_max; i++) {
842 if ((arm_cpu_hatched & (1 << i)) == 0) {
843 printf("%s: warning: cpu%zu failed to hatch\n",
844 __func__, i);
845 }
846 }
847 #if defined(VERBOSE_INIT_ARM) && defined(EARLYCONS)
848 /* for viewability of secondary processor's debug outputs */
849 printf("\n");
850 #endif
851 #endif
852 }
853
854 #endif /* SOC_BCM2836 */
855
856 #if NGENFB > 0
857 static bool
858 rpi_fb_parse_mode(const char *s, uint32_t *pwidth, uint32_t *pheight)
859 {
860 char *x;
861
862 if (strncmp(s, "disable", 7) == 0)
863 return false;
864
865 x = strchr(s, 'x');
866 if (x) {
867 *pwidth = strtoul(s, NULL, 10);
868 *pheight = strtoul(x + 1, NULL, 10);
869 }
870
871 return true;
872 }
873
874 static bool
875 rpi_fb_get_edid_mode(uint32_t *pwidth, uint32_t *pheight)
876 {
877 struct edid_info ei;
878 uint8_t edid_data[1024];
879 uint32_t res;
880 int error;
881
882 error = bcmmbox_request(BCMMBOX_CHANARM2VC, &vb_edid,
883 sizeof(vb_edid), &res);
884 if (error) {
885 printf("%s: mbox request failed (%d)\n", __func__, error);
886 return false;
887 }
888
889 if (!vcprop_buffer_success_p(&vb_edid.vb_hdr) ||
890 !vcprop_tag_success_p(&vb_edid.vbt_edid.tag) ||
891 vb_edid.vbt_edid.status != 0)
892 return false;
893
894 memset(edid_data, 0, sizeof(edid_data));
895 memcpy(edid_data, vb_edid.vbt_edid.data,
896 sizeof(vb_edid.vbt_edid.data));
897 edid_parse(edid_data, &ei);
898 #ifdef VERBOSE_INIT_ARM
899 edid_print(&ei);
900 #endif
901
902 if (ei.edid_preferred_mode) {
903 *pwidth = ei.edid_preferred_mode->hdisplay;
904 *pheight = ei.edid_preferred_mode->vdisplay;
905 }
906
907 return true;
908 }
909
910 /*
911 * Initialize framebuffer console.
912 *
913 * Some notes about boot parameters:
914 * - If "fb=disable" is present, ignore framebuffer completely.
915 * - If "fb=<width>x<height> is present, use the specified mode.
916 * - If "console=fb" is present, attach framebuffer to console.
917 */
918 static bool
919 rpi_fb_init(prop_dictionary_t dict, void *aux)
920 {
921 uint32_t width = 0, height = 0;
922 uint32_t res;
923 char *ptr;
924 int integer;
925 int error;
926 bool is_bgr = true;
927
928 if (get_bootconf_option(boot_args, "fb",
929 BOOTOPT_TYPE_STRING, &ptr)) {
930 if (rpi_fb_parse_mode(ptr, &width, &height) == false)
931 return false;
932 }
933 if (width == 0 || height == 0) {
934 rpi_fb_get_edid_mode(&width, &height);
935 }
936 if (width == 0 || height == 0) {
937 width = RPI_FB_WIDTH;
938 height = RPI_FB_HEIGHT;
939 }
940
941 vb_setfb.vbt_res.width = width;
942 vb_setfb.vbt_res.height = height;
943 vb_setfb.vbt_vres.width = width;
944 vb_setfb.vbt_vres.height = height;
945 error = bcmmbox_request(BCMMBOX_CHANARM2VC, &vb_setfb,
946 sizeof(vb_setfb), &res);
947 if (error) {
948 printf("%s: mbox request failed (%d)\n", __func__, error);
949 return false;
950 }
951
952 if (!vcprop_buffer_success_p(&vb_setfb.vb_hdr) ||
953 !vcprop_tag_success_p(&vb_setfb.vbt_res.tag) ||
954 !vcprop_tag_success_p(&vb_setfb.vbt_vres.tag) ||
955 !vcprop_tag_success_p(&vb_setfb.vbt_depth.tag) ||
956 !vcprop_tag_success_p(&vb_setfb.vbt_allocbuf.tag) ||
957 !vcprop_tag_success_p(&vb_setfb.vbt_blank.tag) ||
958 !vcprop_tag_success_p(&vb_setfb.vbt_pitch.tag)) {
959 printf("%s: prop tag failed\n", __func__);
960 return false;
961 }
962
963 #ifdef VERBOSE_INIT_ARM
964 printf("%s: addr = 0x%x size = %d\n", __func__,
965 vb_setfb.vbt_allocbuf.address,
966 vb_setfb.vbt_allocbuf.size);
967 printf("%s: depth = %d\n", __func__, vb_setfb.vbt_depth.bpp);
968 printf("%s: pitch = %d\n", __func__,
969 vb_setfb.vbt_pitch.linebytes);
970 printf("%s: width = %d height = %d\n", __func__,
971 vb_setfb.vbt_res.width, vb_setfb.vbt_res.height);
972 printf("%s: vwidth = %d vheight = %d\n", __func__,
973 vb_setfb.vbt_vres.width, vb_setfb.vbt_vres.height);
974 #endif
975
976 if (vb_setfb.vbt_allocbuf.address == 0 ||
977 vb_setfb.vbt_allocbuf.size == 0 ||
978 vb_setfb.vbt_res.width == 0 ||
979 vb_setfb.vbt_res.height == 0 ||
980 vb_setfb.vbt_vres.width == 0 ||
981 vb_setfb.vbt_vres.height == 0 ||
982 vb_setfb.vbt_pitch.linebytes == 0) {
983 printf("%s: failed to set mode %ux%u\n", __func__,
984 width, height);
985 return false;
986 }
987
988 prop_dictionary_set_uint32(dict, "width", vb_setfb.vbt_res.width);
989 prop_dictionary_set_uint32(dict, "height", vb_setfb.vbt_res.height);
990 prop_dictionary_set_uint8(dict, "depth", vb_setfb.vbt_depth.bpp);
991 prop_dictionary_set_uint16(dict, "linebytes",
992 vb_setfb.vbt_pitch.linebytes);
993 prop_dictionary_set_uint32(dict, "address",
994 vb_setfb.vbt_allocbuf.address);
995
996 /*
997 * Old firmware uses BGR. New firmware uses RGB. The get and set
998 * pixel order mailbox properties don't seem to work. The firmware
999 * adds a kernel cmdline option bcm2708_fb.fbswap=<0|1>, so use it
1000 * to determine pixel order. 0 means BGR, 1 means RGB.
1001 *
1002 * See https://github.com/raspberrypi/linux/issues/514
1003 */
1004 if (get_bootconf_option(boot_args, "bcm2708_fb.fbswap",
1005 BOOTOPT_TYPE_INT, &integer)) {
1006 is_bgr = integer == 0;
1007 }
1008 prop_dictionary_set_bool(dict, "is_bgr", is_bgr);
1009
1010 /* if "genfb.type=<n>" is passed in cmdline, override wsdisplay type */
1011 if (get_bootconf_option(boot_args, "genfb.type",
1012 BOOTOPT_TYPE_INT, &integer)) {
1013 prop_dictionary_set_uint32(dict, "wsdisplay_type", integer);
1014 }
1015
1016 #if defined(RPI_HWCURSOR)
1017 struct fdt_attach_args *faa = aux;
1018 bus_space_handle_t hc;
1019
1020 hcursor = rpi_alloc_mem(CURSOR_ARGB_SIZE, PAGE_SIZE,
1021 MEM_FLAG_L1_NONALLOCATING | MEM_FLAG_HINT_PERMALOCK);
1022 pcursor = rpi_lock_mem(hcursor);
1023 #ifdef RPI_IOCTL_DEBUG
1024 printf("hcursor: %08x\n", hcursor);
1025 printf("pcursor: %08x\n", (uint32_t)pcursor);
1026 printf("fb: %08x\n", (uint32_t)vb_setfb.vbt_allocbuf.address);
1027 #endif
1028 if (bus_space_map(faa->faa_bst, pcursor, CURSOR_ARGB_SIZE,
1029 BUS_SPACE_MAP_LINEAR|BUS_SPACE_MAP_PREFETCHABLE, &hc) != 0) {
1030 printf("couldn't map cursor memory\n");
1031 } else {
1032 int i, j, k;
1033
1034 cmem = bus_space_vaddr(faa->faa_bst, hc);
1035 k = 0;
1036 for (j = 0; j < 64; j++) {
1037 for (i = 0; i < 64; i++) {
1038 cmem[i + k] =
1039 ((i & 8) ^ (j & 8)) ? 0xa0ff0000 : 0xa000ff00;
1040 }
1041 k += 64;
1042 }
1043 cpu_dcache_wb_range((vaddr_t)cmem, CURSOR_ARGB_SIZE);
1044 rpi_fb_initcursor(pcursor, 0, 0);
1045 #ifdef RPI_IOCTL_DEBUG
1046 rpi_fb_movecursor(600, 400, 1);
1047 #else
1048 rpi_fb_movecursor(cursor_x, cursor_y, cursor_on);
1049 #endif
1050 }
1051 #endif
1052
1053 return true;
1054 }
1055
1056
1057 #if defined(RPI_HWCURSOR)
1058 static int
1059 rpi_fb_do_cursor(struct wsdisplay_cursor *cur)
1060 {
1061 int pos = 0;
1062 int shape = 0;
1063
1064 if (cur->which & WSDISPLAY_CURSOR_DOCUR) {
1065 if (cursor_on != cur->enable) {
1066 cursor_on = cur->enable;
1067 pos = 1;
1068 }
1069 }
1070 if (cur->which & WSDISPLAY_CURSOR_DOHOT) {
1071
1072 hot_x = cur->hot.x;
1073 hot_y = cur->hot.y;
1074 pos = 1;
1075 shape = 1;
1076 }
1077 if (cur->which & WSDISPLAY_CURSOR_DOPOS) {
1078
1079 cursor_x = cur->pos.x;
1080 cursor_y = cur->pos.y;
1081 pos = 1;
1082 }
1083 if (cur->which & WSDISPLAY_CURSOR_DOCMAP) {
1084 int i;
1085 uint32_t val;
1086
1087 for (i = 0; i < min(cur->cmap.count, 3); i++) {
1088 val = (cur->cmap.red[i] << 16 ) |
1089 (cur->cmap.green[i] << 8) |
1090 (cur->cmap.blue[i] ) |
1091 0xff000000;
1092 cursor_cmap[i + cur->cmap.index + 2] = val;
1093 }
1094 shape = 1;
1095 }
1096 if (cur->which & WSDISPLAY_CURSOR_DOSHAPE) {
1097 int err;
1098
1099 err = copyin(cur->mask, cursor_mask, CURSOR_BITMAP_SIZE);
1100 err += copyin(cur->image, cursor_bitmap, CURSOR_BITMAP_SIZE);
1101 if (err != 0)
1102 return EFAULT;
1103 shape = 1;
1104 }
1105 if (shape) {
1106 int i, j, idx;
1107 uint8_t mask;
1108
1109 for (i = 0; i < CURSOR_BITMAP_SIZE; i++) {
1110 mask = 0x01;
1111 for (j = 0; j < 8; j++) {
1112 idx = ((cursor_mask[i] & mask) ? 2 : 0) |
1113 ((cursor_bitmap[i] & mask) ? 1 : 0);
1114 cmem[i * 8 + j] = cursor_cmap[idx];
1115 mask = mask << 1;
1116 }
1117 }
1118 /* just in case */
1119 cpu_dcache_wb_range((vaddr_t)cmem, CURSOR_ARGB_SIZE);
1120 rpi_fb_initcursor(pcursor, hot_x, hot_y);
1121 }
1122 if (pos) {
1123 rpi_fb_movecursor(cursor_x, cursor_y, cursor_on);
1124 }
1125 return 0;
1126 }
1127 #endif
1128
1129 static int
1130 rpi_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, lwp_t *l)
1131 {
1132
1133 switch (cmd) {
1134 case WSDISPLAYIO_SVIDEO:
1135 {
1136 int d = *(int *)data;
1137 if (d == rpi_video_on)
1138 return 0;
1139 rpi_video_on = d;
1140 rpi_fb_set_video(d);
1141 #if defined(RPI_HWCURSOR)
1142 rpi_fb_movecursor(cursor_x, cursor_y,
1143 d ? cursor_on : 0);
1144 #endif
1145 }
1146 return 0;
1147 case WSDISPLAYIO_GVIDEO:
1148 *(int *)data = rpi_video_on;
1149 return 0;
1150 #if defined(RPI_HWCURSOR)
1151 case WSDISPLAYIO_GCURPOS:
1152 {
1153 struct wsdisplay_curpos *cp = (void *)data;
1154
1155 cp->x = cursor_x;
1156 cp->y = cursor_y;
1157 }
1158 return 0;
1159 case WSDISPLAYIO_SCURPOS:
1160 {
1161 struct wsdisplay_curpos *cp = (void *)data;
1162
1163 cursor_x = cp->x;
1164 cursor_y = cp->y;
1165 rpi_fb_movecursor(cursor_x, cursor_y, cursor_on);
1166 }
1167 return 0;
1168 case WSDISPLAYIO_GCURMAX:
1169 {
1170 struct wsdisplay_curpos *cp = (void *)data;
1171
1172 cp->x = 64;
1173 cp->y = 64;
1174 }
1175 return 0;
1176 case WSDISPLAYIO_SCURSOR:
1177 {
1178 struct wsdisplay_cursor *cursor = (void *)data;
1179
1180 return rpi_fb_do_cursor(cursor);
1181 }
1182 #endif
1183 default:
1184 return EPASSTHROUGH;
1185 }
1186 }
1187
1188 #endif
1189
1190 SYSCTL_SETUP(sysctl_machdep_rpi, "sysctl machdep subtree setup (rpi)")
1191 {
1192 sysctl_createv(clog, 0, NULL, NULL,
1193 CTLFLAG_PERMANENT, CTLTYPE_NODE, "machdep", NULL,
1194 NULL, 0, NULL, 0, CTL_MACHDEP, CTL_EOL);
1195
1196 sysctl_createv(clog, 0, NULL, NULL,
1197 CTLFLAG_PERMANENT|CTLFLAG_READONLY,
1198 CTLTYPE_INT, "firmware_revision", NULL, NULL, 0,
1199 &vb.vbt_fwrev.rev, 0, CTL_MACHDEP, CTL_CREATE, CTL_EOL);
1200
1201 sysctl_createv(clog, 0, NULL, NULL,
1202 CTLFLAG_PERMANENT|CTLFLAG_READONLY,
1203 CTLTYPE_INT, "board_model", NULL, NULL, 0,
1204 &vb.vbt_boardmodel.model, 0, CTL_MACHDEP, CTL_CREATE, CTL_EOL);
1205
1206 sysctl_createv(clog, 0, NULL, NULL,
1207 CTLFLAG_PERMANENT|CTLFLAG_READONLY,
1208 CTLTYPE_INT, "board_revision", NULL, NULL, 0,
1209 &vb.vbt_boardrev.rev, 0, CTL_MACHDEP, CTL_CREATE, CTL_EOL);
1210
1211 sysctl_createv(clog, 0, NULL, NULL,
1212 CTLFLAG_PERMANENT|CTLFLAG_READONLY|CTLFLAG_HEX|CTLFLAG_PRIVATE,
1213 CTLTYPE_QUAD, "serial", NULL, NULL, 0,
1214 &vb.vbt_serial.sn, 0, CTL_MACHDEP, CTL_CREATE, CTL_EOL);
1215 }
1216
1217 #if defined(SOC_BCM2835)
1218 static void
1219 bcm2835_platform_bootstrap(void)
1220 {
1221
1222 bcm2835_bs_tag = arm_generic_bs_tag;
1223 bcm2835_a4x_bs_tag = arm_generic_a4x_bs_tag;
1224
1225 bcm2835_bs_tag.bs_map = bcm2835_bs_map;
1226 bcm2835_bs_tag.bs_mmap = bcm283x_bs_mmap;
1227 bcm2835_a4x_bs_tag.bs_map = bcm2835_bs_map;
1228 bcm2835_a4x_bs_tag.bs_mmap = bcm283x_a4x_bs_mmap;
1229
1230 fdtbus_set_decoderegprop(false);
1231
1232 bcm2835_uartinit();
1233
1234 bcm2835_bootparams();
1235 }
1236 #endif
1237
1238 #if defined(SOC_BCM2836)
1239 static void
1240 bcm2836_platform_bootstrap(void)
1241 {
1242
1243 bcm2836_bs_tag = arm_generic_bs_tag;
1244 bcm2836_a4x_bs_tag = arm_generic_a4x_bs_tag;
1245
1246 bcm2836_bs_tag.bs_map = bcm2836_bs_map;
1247 bcm2836_bs_tag.bs_mmap = bcm283x_bs_mmap;
1248 bcm2836_a4x_bs_tag.bs_map = bcm2836_bs_map;
1249 bcm2836_a4x_bs_tag.bs_mmap = bcm283x_a4x_bs_mmap;
1250
1251 fdtbus_set_decoderegprop(false);
1252
1253 bcm2836_uartinit();
1254
1255 bcm2836_bootparams();
1256
1257 bcm2836_bootstrap();
1258 }
1259 #endif
1260
1261 #if defined(SOC_BCM2835)
1262 static void
1263 bcm2835_platform_init_attach_args(struct fdt_attach_args *faa)
1264 {
1265
1266 faa->faa_bst = &bcm2835_bs_tag;
1267 faa->faa_a4x_bst = &bcm2835_a4x_bs_tag;
1268 faa->faa_dmat = &bcm2835_bus_dma_tag;
1269
1270 bcm2835_bus_dma_tag._ranges = bcm2835_dma_ranges;
1271 bcm2835_bus_dma_tag._nranges = __arraycount(bcm2835_dma_ranges);
1272 bcm2835_dma_ranges[0].dr_len = bcm283x_memorysize;
1273 }
1274 #endif
1275
1276 #if defined(SOC_BCM2836)
1277 static void
1278 bcm2836_platform_init_attach_args(struct fdt_attach_args *faa)
1279 {
1280
1281 faa->faa_bst = &bcm2836_bs_tag;
1282 faa->faa_a4x_bst = &bcm2836_a4x_bs_tag;
1283 faa->faa_dmat = &bcm2835_bus_dma_tag;
1284
1285 bcm2835_bus_dma_tag._ranges = bcm2836_dma_ranges;
1286 bcm2835_bus_dma_tag._nranges = __arraycount(bcm2836_dma_ranges);
1287 bcm2836_dma_ranges[0].dr_len = bcm283x_memorysize;
1288 }
1289 #endif
1290
1291
1292 void
1293 bcm283x_platform_early_putchar(vaddr_t va, paddr_t pa, char c)
1294 {
1295 volatile uint32_t *uartaddr =
1296 cpu_earlydevice_va_p() ?
1297 (volatile uint32_t *)va :
1298 (volatile uint32_t *)pa;
1299
1300 while ((uartaddr[PL01XCOM_FR / 4] & PL01X_FR_TXFF) != 0)
1301 continue;
1302
1303 uartaddr[PL01XCOM_DR / 4] = c;
1304
1305 while ((uartaddr[PL01XCOM_FR / 4] & PL01X_FR_TXFE) == 0)
1306 continue;
1307 }
1308
1309 void
1310 bcm2835_platform_early_putchar(char c)
1311 {
1312 paddr_t pa = BCM2835_PERIPHERALS_BUS_TO_PHYS(BCM2835_UART0_BASE);
1313 vaddr_t va = BCM2835_IOPHYSTOVIRT(pa);
1314
1315 bcm283x_platform_early_putchar(va, pa, c);
1316 }
1317
1318 void
1319 bcm2836_platform_early_putchar(char c)
1320 {
1321 paddr_t pa = BCM2836_PERIPHERALS_BUS_TO_PHYS(BCM2835_UART0_BASE);
1322 vaddr_t va = BCM2835_IOPHYSTOVIRT(pa);
1323
1324 bcm283x_platform_early_putchar(va, pa, c);
1325 }
1326
1327 #define BCM283x_REF_FREQ 19200000
1328
1329 void
1330 bcm2837_platform_early_putchar(char c)
1331 {
1332 #define AUCONSADDR_PA BCM2836_PERIPHERALS_BUS_TO_PHYS(BCM2835_AUX_UART_BASE)
1333 #define AUCONSADDR_VA BCM2835_IOPHYSTOVIRT(AUCONSADDR_PA)
1334 volatile uint32_t *uartaddr =
1335 cpu_earlydevice_va_p() ?
1336 (volatile uint32_t *)AUCONSADDR_VA :
1337 (volatile uint32_t *)AUCONSADDR_PA;
1338
1339 while ((uartaddr[com_lsr] & LSR_TXRDY) == 0)
1340 ;
1341
1342 uartaddr[com_data] = c;
1343 }
1344
1345 static void
1346 bcm283x_platform_device_register(device_t dev, void *aux)
1347 {
1348 prop_dictionary_t dict = device_properties(dev);
1349
1350 if (device_is_a(dev, "bcmdmac") &&
1351 vcprop_tag_success_p(&vb.vbt_dmachan.tag)) {
1352 prop_dictionary_set_uint32(dict,
1353 "chanmask", vb.vbt_dmachan.mask);
1354 }
1355 #if NSDHC > 0
1356 if (booted_device == NULL &&
1357 device_is_a(dev, "ld") &&
1358 device_is_a(device_parent(dev), "sdmmc")) {
1359 booted_partition = 0;
1360 booted_device = dev;
1361 }
1362 #endif
1363 if (device_is_a(dev, "usmsc") &&
1364 vcprop_tag_success_p(&vb.vbt_macaddr.tag)) {
1365 const uint8_t enaddr[ETHER_ADDR_LEN] = {
1366 (vb.vbt_macaddr.addr >> 0) & 0xff,
1367 (vb.vbt_macaddr.addr >> 8) & 0xff,
1368 (vb.vbt_macaddr.addr >> 16) & 0xff,
1369 (vb.vbt_macaddr.addr >> 24) & 0xff,
1370 (vb.vbt_macaddr.addr >> 32) & 0xff,
1371 (vb.vbt_macaddr.addr >> 40) & 0xff
1372 };
1373
1374 prop_data_t pd = prop_data_create_data(enaddr, ETHER_ADDR_LEN);
1375 KASSERT(pd != NULL);
1376 if (prop_dictionary_set(device_properties(dev), "mac-address",
1377 pd) == false) {
1378 aprint_error_dev(dev,
1379 "WARNING: Unable to set mac-address property\n");
1380 }
1381 prop_object_release(pd);
1382 }
1383
1384 #if NGENFB > 0
1385 if (device_is_a(dev, "genfb")) {
1386 char *ptr;
1387
1388 bcmgenfb_set_console_dev(dev);
1389 bcmgenfb_set_ioctl(&rpi_ioctl);
1390 #ifdef DDB
1391 db_trap_callback = bcmgenfb_ddb_trap_callback;
1392 #endif
1393 if (rpi_fb_init(dict, aux) == false)
1394 return;
1395 if (get_bootconf_option(boot_args, "console",
1396 BOOTOPT_TYPE_STRING, &ptr) && strncmp(ptr, "fb", 2) == 0) {
1397 prop_dictionary_set_bool(dict, "is_console", true);
1398 #if NUKBD > 0
1399 /* allow ukbd to be the console keyboard */
1400 ukbd_cnattach();
1401 #endif
1402 } else {
1403 prop_dictionary_set_bool(dict, "is_console", false);
1404 }
1405 }
1406 #endif
1407 }
1408
1409 static u_int
1410 bcm283x_platform_uart_freq(void)
1411 {
1412
1413 return uart_clk;
1414 }
1415
1416 #if defined(SOC_BCM2835)
1417 static const struct arm_platform bcm2835_platform = {
1418 .devmap = bcm2835_platform_devmap,
1419 .bootstrap = bcm2835_platform_bootstrap,
1420 .init_attach_args = bcm2835_platform_init_attach_args,
1421 .early_putchar = bcm2835_platform_early_putchar,
1422 .device_register = bcm283x_platform_device_register,
1423 .reset = bcm2835_system_reset,
1424 .delay = bcm2835_tmr_delay,
1425 .uart_freq = bcm283x_platform_uart_freq,
1426 };
1427
1428 ARM_PLATFORM(bcm2835, "brcm,bcm2835", &bcm2835_platform);
1429 #endif
1430
1431 #if defined(SOC_BCM2836)
1432 static u_int
1433 bcm2837_platform_uart_freq(void)
1434 {
1435
1436 return core_clk * 2;
1437 }
1438
1439 static const struct arm_platform bcm2836_platform = {
1440 .devmap = bcm2836_platform_devmap,
1441 .bootstrap = bcm2836_platform_bootstrap,
1442 .init_attach_args = bcm2836_platform_init_attach_args,
1443 .early_putchar = bcm2836_platform_early_putchar,
1444 .device_register = bcm283x_platform_device_register,
1445 .reset = bcm2835_system_reset,
1446 .delay = gtmr_delay,
1447 .uart_freq = bcm283x_platform_uart_freq,
1448 };
1449
1450 static const struct arm_platform bcm2837_platform = {
1451 .devmap = bcm2836_platform_devmap,
1452 .bootstrap = bcm2836_platform_bootstrap,
1453 .init_attach_args = bcm2836_platform_init_attach_args,
1454 .early_putchar = bcm2837_platform_early_putchar,
1455 .device_register = bcm283x_platform_device_register,
1456 .reset = bcm2835_system_reset,
1457 .delay = gtmr_delay,
1458 .uart_freq = bcm2837_platform_uart_freq,
1459 };
1460
1461 ARM_PLATFORM(bcm2836, "brcm,bcm2836", &bcm2836_platform);
1462 ARM_PLATFORM(bcm2837, "brcm,bcm2837", &bcm2837_platform);
1463 #endif
1464