| @@ -1,1189 +1,1194 @@ | | | @@ -1,1189 +1,1194 @@ |
1 | /* $NetBSD: rpi_machdep.c,v 1.59 2015/03/15 22:54:03 joerg Exp $ */ | | 1 | /* $NetBSD: rpi_machdep.c,v 1.60 2015/04/11 15:29:58 skrll Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /*- |
4 | * Copyright (c) 2012 The NetBSD Foundation, Inc. | | 4 | * Copyright (c) 2012 The NetBSD Foundation, Inc. |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * This code is derived from software contributed to The NetBSD Foundation | | 7 | * This code is derived from software contributed to The NetBSD Foundation |
8 | * by Nick Hudson | | 8 | * by Nick Hudson |
9 | * | | 9 | * |
10 | * Redistribution and use in source and binary forms, with or without | | 10 | * Redistribution and use in source and binary forms, with or without |
11 | * modification, are permitted provided that the following conditions | | 11 | * modification, are permitted provided that the following conditions |
12 | * are met: | | 12 | * are met: |
13 | * 1. Redistributions of source code must retain the above copyright | | 13 | * 1. Redistributions of source code must retain the above copyright |
14 | * notice, this list of conditions and the following disclaimer. | | 14 | * notice, this list of conditions and the following disclaimer. |
15 | * 2. Redistributions in binary form must reproduce the above copyright | | 15 | * 2. Redistributions in binary form must reproduce the above copyright |
16 | * notice, this list of conditions and the following disclaimer in the | | 16 | * notice, this list of conditions and the following disclaimer in the |
17 | * documentation and/or other materials provided with the distribution. | | 17 | * documentation and/or other materials provided with the distribution. |
18 | * | | 18 | * |
19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | | 19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS |
20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | | 20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | | 21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | | 22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS |
23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | | 23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | | 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | | 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | | 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | | 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | | 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
29 | * POSSIBILITY OF SUCH DAMAGE. | | 29 | * POSSIBILITY OF SUCH DAMAGE. |
30 | */ | | 30 | */ |
31 | | | 31 | |
32 | #include <sys/cdefs.h> | | 32 | #include <sys/cdefs.h> |
33 | __KERNEL_RCSID(0, "$NetBSD: rpi_machdep.c,v 1.59 2015/03/15 22:54:03 joerg Exp $"); | | 33 | __KERNEL_RCSID(0, "$NetBSD: rpi_machdep.c,v 1.60 2015/04/11 15:29:58 skrll Exp $"); |
34 | | | 34 | |
35 | #include "opt_arm_debug.h" | | 35 | #include "opt_arm_debug.h" |
36 | #include "opt_bcm283x.h" | | 36 | #include "opt_bcm283x.h" |
37 | #include "opt_cpuoptions.h" | | 37 | #include "opt_cpuoptions.h" |
38 | #include "opt_ddb.h" | | 38 | #include "opt_ddb.h" |
39 | #include "opt_evbarm_boardtype.h" | | 39 | #include "opt_evbarm_boardtype.h" |
40 | #include "opt_kgdb.h" | | 40 | #include "opt_kgdb.h" |
41 | #include "opt_rpi.h" | | 41 | #include "opt_rpi.h" |
42 | #include "opt_vcprop.h" | | 42 | #include "opt_vcprop.h" |
43 | | | 43 | |
44 | #include "sdhc.h" | | 44 | #include "sdhc.h" |
45 | #include "bcmdwctwo.h" | | 45 | #include "bcmdwctwo.h" |
46 | #include "bcmspi.h" | | 46 | #include "bcmspi.h" |
47 | #include "bsciic.h" | | 47 | #include "bsciic.h" |
48 | #include "plcom.h" | | 48 | #include "plcom.h" |
49 | #include "genfb.h" | | 49 | #include "genfb.h" |
50 | #include "ukbd.h" | | 50 | #include "ukbd.h" |
51 | | | 51 | |
52 | #include <sys/param.h> | | 52 | #include <sys/param.h> |
53 | #include <sys/device.h> | | 53 | #include <sys/device.h> |
54 | #include <sys/termios.h> | | 54 | #include <sys/termios.h> |
55 | #include <sys/reboot.h> | | 55 | #include <sys/reboot.h> |
56 | #include <sys/sysctl.h> | | 56 | #include <sys/sysctl.h> |
57 | #include <sys/bus.h> | | 57 | #include <sys/bus.h> |
58 | | | 58 | |
59 | #include <net/if_ether.h> | | 59 | #include <net/if_ether.h> |
60 | #include <prop/proplib.h> | | 60 | #include <prop/proplib.h> |
61 | | | 61 | |
62 | #include <dev/cons.h> | | 62 | #include <dev/cons.h> |
63 | | | 63 | |
64 | #include <uvm/uvm_extern.h> | | 64 | #include <uvm/uvm_extern.h> |
65 | | | 65 | |
66 | #include <arm/arm32/machdep.h> | | 66 | #include <arm/arm32/machdep.h> |
67 | | | 67 | |
68 | #include <machine/autoconf.h> | | 68 | #include <machine/autoconf.h> |
69 | #include <machine/vmparam.h> | | 69 | #include <machine/vmparam.h> |
70 | #include <machine/bootconfig.h> | | 70 | #include <machine/bootconfig.h> |
71 | #include <machine/pmap.h> | | 71 | #include <machine/pmap.h> |
72 | | | 72 | |
73 | #include <arm/broadcom/bcm2835reg.h> | | 73 | #include <arm/broadcom/bcm2835reg.h> |
74 | #include <arm/broadcom/bcm2835var.h> | | 74 | #include <arm/broadcom/bcm2835var.h> |
75 | #include <arm/broadcom/bcm2835_pmvar.h> | | 75 | #include <arm/broadcom/bcm2835_pmvar.h> |
76 | #include <arm/broadcom/bcm2835_mbox.h> | | 76 | #include <arm/broadcom/bcm2835_mbox.h> |
77 | #include <arm/broadcom/bcm_amba.h> | | 77 | #include <arm/broadcom/bcm_amba.h> |
78 | | | 78 | |
79 | #include <evbarm/rpi/vcio.h> | | 79 | #include <evbarm/rpi/vcio.h> |
80 | #include <evbarm/rpi/vcpm.h> | | 80 | #include <evbarm/rpi/vcpm.h> |
81 | #include <evbarm/rpi/vcprop.h> | | 81 | #include <evbarm/rpi/vcprop.h> |
82 | | | 82 | |
83 | #include <evbarm/rpi/rpi.h> | | 83 | #include <evbarm/rpi/rpi.h> |
84 | | | 84 | |
85 | #include <arm/cortex/gtmr_var.h> | | 85 | #include <arm/cortex/gtmr_var.h> |
86 | | | 86 | |
87 | #ifdef DDB | | 87 | #ifdef DDB |
88 | #include <machine/db_machdep.h> | | 88 | #include <machine/db_machdep.h> |
89 | #include <ddb/db_sym.h> | | 89 | #include <ddb/db_sym.h> |
90 | #include <ddb/db_extern.h> | | 90 | #include <ddb/db_extern.h> |
91 | #endif | | 91 | #endif |
92 | | | 92 | |
93 | #if NPLCOM > 0 | | 93 | #if NPLCOM > 0 |
94 | #include <evbarm/dev/plcomreg.h> | | 94 | #include <evbarm/dev/plcomreg.h> |
95 | #include <evbarm/dev/plcomvar.h> | | 95 | #include <evbarm/dev/plcomvar.h> |
96 | #endif | | 96 | #endif |
97 | | | 97 | |
98 | #if NGENFB > 0 | | 98 | #if NGENFB > 0 |
99 | #include <dev/videomode/videomode.h> | | 99 | #include <dev/videomode/videomode.h> |
100 | #include <dev/videomode/edidvar.h> | | 100 | #include <dev/videomode/edidvar.h> |
101 | #include <dev/wscons/wsconsio.h> | | 101 | #include <dev/wscons/wsconsio.h> |
102 | #endif | | 102 | #endif |
103 | | | 103 | |
104 | #if NUKBD > 0 | | 104 | #if NUKBD > 0 |
105 | #include <dev/usb/ukbdvar.h> | | 105 | #include <dev/usb/ukbdvar.h> |
106 | #endif | | 106 | #endif |
107 | | | 107 | |
108 | extern int KERNEL_BASE_phys[]; | | 108 | extern int KERNEL_BASE_phys[]; |
109 | extern int KERNEL_BASE_virt[]; | | 109 | extern int KERNEL_BASE_virt[]; |
110 | | | 110 | |
111 | BootConfig bootconfig; /* Boot config storage */ | | 111 | BootConfig bootconfig; /* Boot config storage */ |
112 | static char bootargs[VCPROP_MAXCMDLINE]; | | 112 | static char bootargs[VCPROP_MAXCMDLINE]; |
113 | char *boot_args = NULL; | | 113 | char *boot_args = NULL; |
114 | | | 114 | |
115 | static void rpi_bootparams(void); | | 115 | static void rpi_bootparams(void); |
116 | static void rpi_device_register(device_t, void *); | | 116 | static void rpi_device_register(device_t, void *); |
117 | | | 117 | |
118 | /* | | 118 | /* |
119 | * Macros to translate between physical and virtual for a subset of the | | 119 | * Macros to translate between physical and virtual for a subset of the |
120 | * kernel address space. *Not* for general use. | | 120 | * kernel address space. *Not* for general use. |
121 | */ | | 121 | */ |
122 | | | 122 | |
123 | #define KERN_VTOPDIFF KERNEL_BASE_VOFFSET | | 123 | #define KERN_VTOPDIFF KERNEL_BASE_VOFFSET |
124 | #define KERN_VTOPHYS(va) ((paddr_t)((vaddr_t)va - KERN_VTOPDIFF)) | | 124 | #define KERN_VTOPHYS(va) ((paddr_t)((vaddr_t)va - KERN_VTOPDIFF)) |
125 | #define KERN_PHYSTOV(pa) ((vaddr_t)((paddr_t)pa + KERN_VTOPDIFF)) | | 125 | #define KERN_PHYSTOV(pa) ((vaddr_t)((paddr_t)pa + KERN_VTOPDIFF)) |
126 | | | 126 | |
127 | #ifndef RPI_FB_WIDTH | | 127 | #ifndef RPI_FB_WIDTH |
128 | #define RPI_FB_WIDTH 1280 | | 128 | #define RPI_FB_WIDTH 1280 |
129 | #endif | | 129 | #endif |
130 | #ifndef RPI_FB_HEIGHT | | 130 | #ifndef RPI_FB_HEIGHT |
131 | #define RPI_FB_HEIGHT 720 | | 131 | #define RPI_FB_HEIGHT 720 |
132 | #endif | | 132 | #endif |
133 | | | 133 | |
134 | #if 0 | | 134 | #if 0 |
135 | #define PLCONADDR BCM2835_UART0_BASE | | 135 | #define PLCONADDR BCM2835_UART0_BASE |
136 | #endif | | 136 | #endif |
137 | | | 137 | |
138 | #ifdef BCM2836 | | 138 | #ifdef BCM2836 |
139 | #define PLCONADDR 0x3f201000 | | 139 | #define PLCONADDR 0x3f201000 |
140 | #else | | 140 | #else |
141 | #define PLCONADDR 0x20201000 | | 141 | #define PLCONADDR 0x20201000 |
142 | #endif | | 142 | #endif |
143 | | | 143 | |
144 | #ifndef CONSDEVNAME | | 144 | #ifndef CONSDEVNAME |
145 | #define CONSDEVNAME "plcom" | | 145 | #define CONSDEVNAME "plcom" |
146 | #endif | | 146 | #endif |
147 | | | 147 | |
148 | #ifndef PLCONSPEED | | 148 | #ifndef PLCONSPEED |
149 | #define PLCONSPEED B115200 | | 149 | #define PLCONSPEED B115200 |
150 | #endif | | 150 | #endif |
151 | #ifndef PLCONMODE | | 151 | #ifndef PLCONMODE |
152 | #define PLCONMODE ((TTYDEF_CFLAG & ~(CSIZE | CSTOPB | PARENB)) | CS8) /* 8N1 */ | | 152 | #define PLCONMODE ((TTYDEF_CFLAG & ~(CSIZE | CSTOPB | PARENB)) | CS8) /* 8N1 */ |
153 | #endif | | 153 | #endif |
154 | #ifndef PLCOMCNUNIT | | 154 | #ifndef PLCOMCNUNIT |
155 | #define PLCOMCNUNIT -1 | | 155 | #define PLCOMCNUNIT -1 |
156 | #endif | | 156 | #endif |
157 | | | 157 | |
158 | #if (NPLCOM > 0) | | 158 | #if (NPLCOM > 0) |
159 | static const bus_addr_t consaddr = (bus_addr_t)PLCONADDR; | | 159 | static const bus_addr_t consaddr = (bus_addr_t)PLCONADDR; |
160 | | | 160 | |
161 | int plcomcnspeed = PLCONSPEED; | | 161 | int plcomcnspeed = PLCONSPEED; |
162 | int plcomcnmode = PLCONMODE; | | 162 | int plcomcnmode = PLCONMODE; |
163 | #endif | | 163 | #endif |
164 | | | 164 | |
165 | #include "opt_kgdb.h" | | 165 | #include "opt_kgdb.h" |
166 | #if (NPLCOM == 0) | | 166 | #if (NPLCOM == 0) |
167 | #error Enable plcom for KGDB support | | 167 | #error Enable plcom for KGDB support |
168 | #endif | | 168 | #endif |
169 | #ifdef KGDB | | 169 | #ifdef KGDB |
170 | #include <sys/kgdb.h> | | 170 | #include <sys/kgdb.h> |
171 | static void kgdb_port_init(void); | | 171 | static void kgdb_port_init(void); |
172 | #endif | | 172 | #endif |
173 | | | 173 | |
174 | #if (NPLCOM > 0 && (defined(PLCONSOLE) || defined(KGDB))) | | 174 | #if (NPLCOM > 0 && (defined(PLCONSOLE) || defined(KGDB))) |
175 | static struct plcom_instance rpi_pi = { | | 175 | static struct plcom_instance rpi_pi = { |
176 | .pi_type = PLCOM_TYPE_PL011, | | 176 | .pi_type = PLCOM_TYPE_PL011, |
177 | .pi_flags = PLC_FLAG_32BIT_ACCESS, | | 177 | .pi_flags = PLC_FLAG_32BIT_ACCESS, |
178 | .pi_iot = &bcm2835_bs_tag, | | 178 | .pi_iot = &bcm2835_bs_tag, |
179 | .pi_size = BCM2835_UART0_SIZE | | 179 | .pi_size = BCM2835_UART0_SIZE |
180 | }; | | 180 | }; |
181 | #endif | | 181 | #endif |
182 | | | 182 | |
183 | /* Smallest amount of RAM start.elf could give us. */ | | 183 | /* Smallest amount of RAM start.elf could give us. */ |
184 | #define RPI_MINIMUM_SPLIT (128U * 1024 * 1024) | | 184 | #define RPI_MINIMUM_SPLIT (128U * 1024 * 1024) |
185 | | | 185 | |
186 | static struct __aligned(16) { | | 186 | static struct __aligned(16) { |
187 | struct vcprop_buffer_hdr vb_hdr; | | 187 | struct vcprop_buffer_hdr vb_hdr; |
188 | struct vcprop_tag_fwrev vbt_fwrev; | | 188 | struct vcprop_tag_fwrev vbt_fwrev; |
189 | struct vcprop_tag_boardmodel vbt_boardmodel; | | 189 | struct vcprop_tag_boardmodel vbt_boardmodel; |
190 | struct vcprop_tag_boardrev vbt_boardrev; | | 190 | struct vcprop_tag_boardrev vbt_boardrev; |
191 | struct vcprop_tag_macaddr vbt_macaddr; | | 191 | struct vcprop_tag_macaddr vbt_macaddr; |
192 | struct vcprop_tag_memory vbt_memory; | | 192 | struct vcprop_tag_memory vbt_memory; |
193 | struct vcprop_tag_boardserial vbt_serial; | | 193 | struct vcprop_tag_boardserial vbt_serial; |
194 | struct vcprop_tag_dmachan vbt_dmachan; | | 194 | struct vcprop_tag_dmachan vbt_dmachan; |
195 | struct vcprop_tag_cmdline vbt_cmdline; | | 195 | struct vcprop_tag_cmdline vbt_cmdline; |
196 | struct vcprop_tag_clockrate vbt_emmcclockrate; | | 196 | struct vcprop_tag_clockrate vbt_emmcclockrate; |
197 | struct vcprop_tag_clockrate vbt_armclockrate; | | 197 | struct vcprop_tag_clockrate vbt_armclockrate; |
198 | struct vcprop_tag end; | | 198 | struct vcprop_tag end; |
199 | } vb = | | 199 | } vb = |
200 | { | | 200 | { |
201 | .vb_hdr = { | | 201 | .vb_hdr = { |
202 | .vpb_len = sizeof(vb), | | 202 | .vpb_len = sizeof(vb), |
203 | .vpb_rcode = VCPROP_PROCESS_REQUEST, | | 203 | .vpb_rcode = VCPROP_PROCESS_REQUEST, |
204 | }, | | 204 | }, |
205 | .vbt_fwrev = { | | 205 | .vbt_fwrev = { |
206 | .tag = { | | 206 | .tag = { |
207 | .vpt_tag = VCPROPTAG_GET_FIRMWAREREV, | | 207 | .vpt_tag = VCPROPTAG_GET_FIRMWAREREV, |
208 | .vpt_len = VCPROPTAG_LEN(vb.vbt_fwrev), | | 208 | .vpt_len = VCPROPTAG_LEN(vb.vbt_fwrev), |
209 | .vpt_rcode = VCPROPTAG_REQUEST | | 209 | .vpt_rcode = VCPROPTAG_REQUEST |
210 | }, | | 210 | }, |
211 | }, | | 211 | }, |
212 | .vbt_boardmodel = { | | 212 | .vbt_boardmodel = { |
213 | .tag = { | | 213 | .tag = { |
214 | .vpt_tag = VCPROPTAG_GET_BOARDMODEL, | | 214 | .vpt_tag = VCPROPTAG_GET_BOARDMODEL, |
215 | .vpt_len = VCPROPTAG_LEN(vb.vbt_boardmodel), | | 215 | .vpt_len = VCPROPTAG_LEN(vb.vbt_boardmodel), |
216 | .vpt_rcode = VCPROPTAG_REQUEST | | 216 | .vpt_rcode = VCPROPTAG_REQUEST |
217 | }, | | 217 | }, |
218 | }, | | 218 | }, |
219 | .vbt_boardrev = { | | 219 | .vbt_boardrev = { |
220 | .tag = { | | 220 | .tag = { |
221 | .vpt_tag = VCPROPTAG_GET_BOARDREVISION, | | 221 | .vpt_tag = VCPROPTAG_GET_BOARDREVISION, |
222 | .vpt_len = VCPROPTAG_LEN(vb.vbt_boardrev), | | 222 | .vpt_len = VCPROPTAG_LEN(vb.vbt_boardrev), |
223 | .vpt_rcode = VCPROPTAG_REQUEST | | 223 | .vpt_rcode = VCPROPTAG_REQUEST |
224 | }, | | 224 | }, |
225 | }, | | 225 | }, |
226 | .vbt_macaddr = { | | 226 | .vbt_macaddr = { |
227 | .tag = { | | 227 | .tag = { |
228 | .vpt_tag = VCPROPTAG_GET_MACADDRESS, | | 228 | .vpt_tag = VCPROPTAG_GET_MACADDRESS, |
229 | .vpt_len = VCPROPTAG_LEN(vb.vbt_macaddr), | | 229 | .vpt_len = VCPROPTAG_LEN(vb.vbt_macaddr), |
230 | .vpt_rcode = VCPROPTAG_REQUEST | | 230 | .vpt_rcode = VCPROPTAG_REQUEST |
231 | }, | | 231 | }, |
232 | }, | | 232 | }, |
233 | .vbt_memory = { | | 233 | .vbt_memory = { |
234 | .tag = { | | 234 | .tag = { |
235 | .vpt_tag = VCPROPTAG_GET_ARMMEMORY, | | 235 | .vpt_tag = VCPROPTAG_GET_ARMMEMORY, |
236 | .vpt_len = VCPROPTAG_LEN(vb.vbt_memory), | | 236 | .vpt_len = VCPROPTAG_LEN(vb.vbt_memory), |
237 | .vpt_rcode = VCPROPTAG_REQUEST | | 237 | .vpt_rcode = VCPROPTAG_REQUEST |
238 | }, | | 238 | }, |
239 | }, | | 239 | }, |
240 | .vbt_serial = { | | 240 | .vbt_serial = { |
241 | .tag = { | | 241 | .tag = { |
242 | .vpt_tag = VCPROPTAG_GET_BOARDSERIAL, | | 242 | .vpt_tag = VCPROPTAG_GET_BOARDSERIAL, |
243 | .vpt_len = VCPROPTAG_LEN(vb.vbt_serial), | | 243 | .vpt_len = VCPROPTAG_LEN(vb.vbt_serial), |
244 | .vpt_rcode = VCPROPTAG_REQUEST | | 244 | .vpt_rcode = VCPROPTAG_REQUEST |
245 | }, | | 245 | }, |
246 | }, | | 246 | }, |
247 | .vbt_dmachan = { | | 247 | .vbt_dmachan = { |
248 | .tag = { | | 248 | .tag = { |
249 | .vpt_tag = VCPROPTAG_GET_DMACHAN, | | 249 | .vpt_tag = VCPROPTAG_GET_DMACHAN, |
250 | .vpt_len = VCPROPTAG_LEN(vb.vbt_dmachan), | | 250 | .vpt_len = VCPROPTAG_LEN(vb.vbt_dmachan), |
251 | .vpt_rcode = VCPROPTAG_REQUEST | | 251 | .vpt_rcode = VCPROPTAG_REQUEST |
252 | }, | | 252 | }, |
253 | }, | | 253 | }, |
254 | .vbt_cmdline = { | | 254 | .vbt_cmdline = { |
255 | .tag = { | | 255 | .tag = { |
256 | .vpt_tag = VCPROPTAG_GET_CMDLINE, | | 256 | .vpt_tag = VCPROPTAG_GET_CMDLINE, |
257 | .vpt_len = VCPROPTAG_LEN(vb.vbt_cmdline), | | 257 | .vpt_len = VCPROPTAG_LEN(vb.vbt_cmdline), |
258 | .vpt_rcode = VCPROPTAG_REQUEST | | 258 | .vpt_rcode = VCPROPTAG_REQUEST |
259 | }, | | 259 | }, |
260 | }, | | 260 | }, |
261 | .vbt_emmcclockrate = { | | 261 | .vbt_emmcclockrate = { |
262 | .tag = { | | 262 | .tag = { |
263 | .vpt_tag = VCPROPTAG_GET_CLOCKRATE, | | 263 | .vpt_tag = VCPROPTAG_GET_CLOCKRATE, |
264 | .vpt_len = VCPROPTAG_LEN(vb.vbt_emmcclockrate), | | 264 | .vpt_len = VCPROPTAG_LEN(vb.vbt_emmcclockrate), |
265 | .vpt_rcode = VCPROPTAG_REQUEST | | 265 | .vpt_rcode = VCPROPTAG_REQUEST |
266 | }, | | 266 | }, |
267 | .id = VCPROP_CLK_EMMC | | 267 | .id = VCPROP_CLK_EMMC |
268 | }, | | 268 | }, |
269 | .vbt_armclockrate = { | | 269 | .vbt_armclockrate = { |
270 | .tag = { | | 270 | .tag = { |
271 | .vpt_tag = VCPROPTAG_GET_CLOCKRATE, | | 271 | .vpt_tag = VCPROPTAG_GET_CLOCKRATE, |
272 | .vpt_len = VCPROPTAG_LEN(vb.vbt_armclockrate), | | 272 | .vpt_len = VCPROPTAG_LEN(vb.vbt_armclockrate), |
273 | .vpt_rcode = VCPROPTAG_REQUEST | | 273 | .vpt_rcode = VCPROPTAG_REQUEST |
274 | }, | | 274 | }, |
275 | .id = VCPROP_CLK_ARM | | 275 | .id = VCPROP_CLK_ARM |
276 | }, | | 276 | }, |
277 | .end = { | | 277 | .end = { |
278 | .vpt_tag = VCPROPTAG_NULL | | 278 | .vpt_tag = VCPROPTAG_NULL |
279 | } | | 279 | } |
280 | }; | | 280 | }; |
281 | | | 281 | |
282 | #if NGENFB > 0 | | 282 | #if NGENFB > 0 |
283 | static struct __aligned(16) { | | 283 | static struct __aligned(16) { |
284 | struct vcprop_buffer_hdr vb_hdr; | | 284 | struct vcprop_buffer_hdr vb_hdr; |
285 | struct vcprop_tag_edidblock vbt_edid; | | 285 | struct vcprop_tag_edidblock vbt_edid; |
286 | struct vcprop_tag end; | | 286 | struct vcprop_tag end; |
287 | } vb_edid = | | 287 | } vb_edid = |
288 | { | | 288 | { |
289 | .vb_hdr = { | | 289 | .vb_hdr = { |
290 | .vpb_len = sizeof(vb_edid), | | 290 | .vpb_len = sizeof(vb_edid), |
291 | .vpb_rcode = VCPROP_PROCESS_REQUEST, | | 291 | .vpb_rcode = VCPROP_PROCESS_REQUEST, |
292 | }, | | 292 | }, |
293 | .vbt_edid = { | | 293 | .vbt_edid = { |
294 | .tag = { | | 294 | .tag = { |
295 | .vpt_tag = VCPROPTAG_GET_EDID_BLOCK, | | 295 | .vpt_tag = VCPROPTAG_GET_EDID_BLOCK, |
296 | .vpt_len = VCPROPTAG_LEN(vb_edid.vbt_edid), | | 296 | .vpt_len = VCPROPTAG_LEN(vb_edid.vbt_edid), |
297 | .vpt_rcode = VCPROPTAG_REQUEST, | | 297 | .vpt_rcode = VCPROPTAG_REQUEST, |
298 | }, | | 298 | }, |
299 | .blockno = 0, | | 299 | .blockno = 0, |
300 | }, | | 300 | }, |
301 | .end = { | | 301 | .end = { |
302 | .vpt_tag = VCPROPTAG_NULL | | 302 | .vpt_tag = VCPROPTAG_NULL |
303 | } | | 303 | } |
304 | }; | | 304 | }; |
305 | | | 305 | |
306 | static struct __aligned(16) { | | 306 | static struct __aligned(16) { |
307 | struct vcprop_buffer_hdr vb_hdr; | | 307 | struct vcprop_buffer_hdr vb_hdr; |
308 | struct vcprop_tag_fbres vbt_res; | | 308 | struct vcprop_tag_fbres vbt_res; |
309 | struct vcprop_tag_fbres vbt_vres; | | 309 | struct vcprop_tag_fbres vbt_vres; |
310 | struct vcprop_tag_fbdepth vbt_depth; | | 310 | struct vcprop_tag_fbdepth vbt_depth; |
311 | struct vcprop_tag_fbalpha vbt_alpha; | | 311 | struct vcprop_tag_fbalpha vbt_alpha; |
312 | struct vcprop_tag_allocbuf vbt_allocbuf; | | 312 | struct vcprop_tag_allocbuf vbt_allocbuf; |
313 | struct vcprop_tag_blankscreen vbt_blank; | | 313 | struct vcprop_tag_blankscreen vbt_blank; |
314 | struct vcprop_tag_fbpitch vbt_pitch; | | 314 | struct vcprop_tag_fbpitch vbt_pitch; |
315 | struct vcprop_tag end; | | 315 | struct vcprop_tag end; |
316 | } vb_setfb = | | 316 | } vb_setfb = |
317 | { | | 317 | { |
318 | .vb_hdr = { | | 318 | .vb_hdr = { |
319 | .vpb_len = sizeof(vb_setfb), | | 319 | .vpb_len = sizeof(vb_setfb), |
320 | .vpb_rcode = VCPROP_PROCESS_REQUEST, | | 320 | .vpb_rcode = VCPROP_PROCESS_REQUEST, |
321 | }, | | 321 | }, |
322 | .vbt_res = { | | 322 | .vbt_res = { |
323 | .tag = { | | 323 | .tag = { |
324 | .vpt_tag = VCPROPTAG_SET_FB_RES, | | 324 | .vpt_tag = VCPROPTAG_SET_FB_RES, |
325 | .vpt_len = VCPROPTAG_LEN(vb_setfb.vbt_res), | | 325 | .vpt_len = VCPROPTAG_LEN(vb_setfb.vbt_res), |
326 | .vpt_rcode = VCPROPTAG_REQUEST, | | 326 | .vpt_rcode = VCPROPTAG_REQUEST, |
327 | }, | | 327 | }, |
328 | .width = 0, | | 328 | .width = 0, |
329 | .height = 0, | | 329 | .height = 0, |
330 | }, | | 330 | }, |
331 | .vbt_vres = { | | 331 | .vbt_vres = { |
332 | .tag = { | | 332 | .tag = { |
333 | .vpt_tag = VCPROPTAG_SET_FB_VRES, | | 333 | .vpt_tag = VCPROPTAG_SET_FB_VRES, |
334 | .vpt_len = VCPROPTAG_LEN(vb_setfb.vbt_vres), | | 334 | .vpt_len = VCPROPTAG_LEN(vb_setfb.vbt_vres), |
335 | .vpt_rcode = VCPROPTAG_REQUEST, | | 335 | .vpt_rcode = VCPROPTAG_REQUEST, |
336 | }, | | 336 | }, |
337 | .width = 0, | | 337 | .width = 0, |
338 | .height = 0, | | 338 | .height = 0, |
339 | }, | | 339 | }, |
340 | .vbt_depth = { | | 340 | .vbt_depth = { |
341 | .tag = { | | 341 | .tag = { |
342 | .vpt_tag = VCPROPTAG_SET_FB_DEPTH, | | 342 | .vpt_tag = VCPROPTAG_SET_FB_DEPTH, |
343 | .vpt_len = VCPROPTAG_LEN(vb_setfb.vbt_depth), | | 343 | .vpt_len = VCPROPTAG_LEN(vb_setfb.vbt_depth), |
344 | .vpt_rcode = VCPROPTAG_REQUEST, | | 344 | .vpt_rcode = VCPROPTAG_REQUEST, |
345 | }, | | 345 | }, |
346 | .bpp = 32, | | 346 | .bpp = 32, |
347 | }, | | 347 | }, |
348 | .vbt_alpha = { | | 348 | .vbt_alpha = { |
349 | .tag = { | | 349 | .tag = { |
350 | .vpt_tag = VCPROPTAG_SET_FB_ALPHA_MODE, | | 350 | .vpt_tag = VCPROPTAG_SET_FB_ALPHA_MODE, |
351 | .vpt_len = VCPROPTAG_LEN(vb_setfb.vbt_alpha), | | 351 | .vpt_len = VCPROPTAG_LEN(vb_setfb.vbt_alpha), |
352 | .vpt_rcode = VCPROPTAG_REQUEST, | | 352 | .vpt_rcode = VCPROPTAG_REQUEST, |
353 | }, | | 353 | }, |
354 | .state = VCPROP_ALPHA_IGNORED, | | 354 | .state = VCPROP_ALPHA_IGNORED, |
355 | }, | | 355 | }, |
356 | .vbt_allocbuf = { | | 356 | .vbt_allocbuf = { |
357 | .tag = { | | 357 | .tag = { |
358 | .vpt_tag = VCPROPTAG_ALLOCATE_BUFFER, | | 358 | .vpt_tag = VCPROPTAG_ALLOCATE_BUFFER, |
359 | .vpt_len = VCPROPTAG_LEN(vb_setfb.vbt_allocbuf), | | 359 | .vpt_len = VCPROPTAG_LEN(vb_setfb.vbt_allocbuf), |
360 | .vpt_rcode = VCPROPTAG_REQUEST, | | 360 | .vpt_rcode = VCPROPTAG_REQUEST, |
361 | }, | | 361 | }, |
362 | .address = PAGE_SIZE, /* alignment */ | | 362 | .address = PAGE_SIZE, /* alignment */ |
363 | }, | | 363 | }, |
364 | .vbt_blank = { | | 364 | .vbt_blank = { |
365 | .tag = { | | 365 | .tag = { |
366 | .vpt_tag = VCPROPTAG_BLANK_SCREEN, | | 366 | .vpt_tag = VCPROPTAG_BLANK_SCREEN, |
367 | .vpt_len = VCPROPTAG_LEN(vb_setfb.vbt_blank), | | 367 | .vpt_len = VCPROPTAG_LEN(vb_setfb.vbt_blank), |
368 | .vpt_rcode = VCPROPTAG_REQUEST, | | 368 | .vpt_rcode = VCPROPTAG_REQUEST, |
369 | }, | | 369 | }, |
370 | .state = VCPROP_BLANK_OFF, | | 370 | .state = VCPROP_BLANK_OFF, |
371 | }, | | 371 | }, |
372 | .vbt_pitch = { | | 372 | .vbt_pitch = { |
373 | .tag = { | | 373 | .tag = { |
374 | .vpt_tag = VCPROPTAG_GET_FB_PITCH, | | 374 | .vpt_tag = VCPROPTAG_GET_FB_PITCH, |
375 | .vpt_len = VCPROPTAG_LEN(vb_setfb.vbt_pitch), | | 375 | .vpt_len = VCPROPTAG_LEN(vb_setfb.vbt_pitch), |
376 | .vpt_rcode = VCPROPTAG_REQUEST, | | 376 | .vpt_rcode = VCPROPTAG_REQUEST, |
377 | }, | | 377 | }, |
378 | }, | | 378 | }, |
379 | .end = { | | 379 | .end = { |
380 | .vpt_tag = VCPROPTAG_NULL, | | 380 | .vpt_tag = VCPROPTAG_NULL, |
381 | }, | | 381 | }, |
382 | }; | | 382 | }; |
383 | | | 383 | |
384 | extern void bcmgenfb_set_console_dev(device_t dev); | | 384 | extern void bcmgenfb_set_console_dev(device_t dev); |
385 | void bcmgenfb_set_ioctl(int(*)(void *, void *, u_long, void *, int, struct lwp *)); | | 385 | void bcmgenfb_set_ioctl(int(*)(void *, void *, u_long, void *, int, struct lwp *)); |
386 | extern void bcmgenfb_ddb_trap_callback(int where); | | 386 | extern void bcmgenfb_ddb_trap_callback(int where); |
387 | static int rpi_ioctl(void *, void *, u_long, void *, int, lwp_t *); | | 387 | static int rpi_ioctl(void *, void *, u_long, void *, int, lwp_t *); |
388 | | | 388 | |
389 | static int rpi_video_on = WSDISPLAYIO_VIDEO_ON; | | 389 | static int rpi_video_on = WSDISPLAYIO_VIDEO_ON; |
390 | | | 390 | |
391 | #if defined(RPI_HWCURSOR) | | 391 | #if defined(RPI_HWCURSOR) |
392 | #define CURSOR_BITMAP_SIZE (64 * 8) | | 392 | #define CURSOR_BITMAP_SIZE (64 * 8) |
393 | #define CURSOR_ARGB_SIZE (64 * 64 * 4) | | 393 | #define CURSOR_ARGB_SIZE (64 * 64 * 4) |
394 | static uint32_t hcursor = 0; | | 394 | static uint32_t hcursor = 0; |
395 | static bus_addr_t pcursor = 0; | | 395 | static bus_addr_t pcursor = 0; |
396 | static uint32_t *cmem = NULL; | | 396 | static uint32_t *cmem = NULL; |
397 | static int cursor_x = 0, cursor_y = 0, hot_x = 0, hot_y = 0, cursor_on = 0; | | 397 | static int cursor_x = 0, cursor_y = 0, hot_x = 0, hot_y = 0, cursor_on = 0; |
398 | static uint32_t cursor_cmap[4]; | | 398 | static uint32_t cursor_cmap[4]; |
399 | static uint8_t cursor_mask[8 * 64], cursor_bitmap[8 * 64]; | | 399 | static uint8_t cursor_mask[8 * 64], cursor_bitmap[8 * 64]; |
400 | #endif | | 400 | #endif |
401 | #endif | | 401 | #endif |
402 | | | 402 | |
403 | | | 403 | |
404 | static void | | 404 | static void |
405 | rpi_bootparams(void) | | 405 | rpi_bootparams(void) |
406 | { | | 406 | { |
407 | bus_space_tag_t iot = &bcm2835_bs_tag; | | 407 | bus_space_tag_t iot = &bcm2835_bs_tag; |
408 | bus_space_handle_t ioh = BCM2835_IOPHYSTOVIRT(BCM2835_ARMMBOX_BASE); | | 408 | bus_space_handle_t ioh = BCM2835_IOPHYSTOVIRT(BCM2835_ARMMBOX_BASE); |
409 | uint32_t res; | | 409 | uint32_t res; |
410 | | | 410 | |
411 | bcm2835_mbox_write(iot, ioh, BCMMBOX_CHANPM, ( | | 411 | bcm2835_mbox_write(iot, ioh, BCMMBOX_CHANPM, ( |
412 | #if (NSDHC > 0) | | 412 | #if (NSDHC > 0) |
413 | (1 << VCPM_POWER_SDCARD) | | | 413 | (1 << VCPM_POWER_SDCARD) | |
414 | #endif | | 414 | #endif |
415 | #if (NPLCOM > 0) | | 415 | #if (NPLCOM > 0) |
416 | (1 << VCPM_POWER_UART0) | | | 416 | (1 << VCPM_POWER_UART0) | |
417 | #endif | | 417 | #endif |
418 | #if (NBCMDWCTWO > 0) | | 418 | #if (NBCMDWCTWO > 0) |
419 | (1 << VCPM_POWER_USB) | | | 419 | (1 << VCPM_POWER_USB) | |
420 | #endif | | 420 | #endif |
421 | #if (NBSCIIC > 0) | | 421 | #if (NBSCIIC > 0) |
422 | (1 << VCPM_POWER_I2C0) | (1 << VCPM_POWER_I2C1) | | | 422 | (1 << VCPM_POWER_I2C0) | (1 << VCPM_POWER_I2C1) | |
423 | /* (1 << VCPM_POWER_I2C2) | */ | | 423 | /* (1 << VCPM_POWER_I2C2) | */ |
424 | #endif | | 424 | #endif |
425 | #if (NBCMSPI > 0) | | 425 | #if (NBCMSPI > 0) |
426 | (1 << VCPM_POWER_SPI) | | | 426 | (1 << VCPM_POWER_SPI) | |
427 | #endif | | 427 | #endif |
428 | 0) << 4); | | 428 | 0) << 4); |
429 | | | 429 | |
430 | bcm2835_mbox_write(iot, ioh, BCMMBOX_CHANARM2VC, KERN_VTOPHYS(&vb)); | | 430 | bcm2835_mbox_write(iot, ioh, BCMMBOX_CHANARM2VC, KERN_VTOPHYS(&vb)); |
431 | | | 431 | |
432 | bcm2835_mbox_read(iot, ioh, BCMMBOX_CHANARM2VC, &res); | | 432 | bcm2835_mbox_read(iot, ioh, BCMMBOX_CHANARM2VC, &res); |
433 | | | 433 | |
434 | cpu_dcache_inv_range((vaddr_t)&vb, sizeof(vb)); | | 434 | cpu_dcache_inv_range((vaddr_t)&vb, sizeof(vb)); |
435 | | | 435 | |
436 | if (!vcprop_buffer_success_p(&vb.vb_hdr)) { | | 436 | if (!vcprop_buffer_success_p(&vb.vb_hdr)) { |
437 | bootconfig.dramblocks = 1; | | 437 | bootconfig.dramblocks = 1; |
438 | bootconfig.dram[0].address = 0x0; | | 438 | bootconfig.dram[0].address = 0x0; |
439 | bootconfig.dram[0].pages = atop(RPI_MINIMUM_SPLIT); | | 439 | bootconfig.dram[0].pages = atop(RPI_MINIMUM_SPLIT); |
440 | return; | | 440 | return; |
441 | } | | 441 | } |
442 | | | 442 | |
443 | struct vcprop_tag_memory *vptp_mem = &vb.vbt_memory; | | 443 | struct vcprop_tag_memory *vptp_mem = &vb.vbt_memory; |
444 | | | 444 | |
445 | if (vcprop_tag_success_p(&vptp_mem->tag)) { | | 445 | if (vcprop_tag_success_p(&vptp_mem->tag)) { |
446 | size_t n = vcprop_tag_resplen(&vptp_mem->tag) / | | 446 | size_t n = vcprop_tag_resplen(&vptp_mem->tag) / |
447 | sizeof(struct vcprop_memory); | | 447 | sizeof(struct vcprop_memory); |
448 | | | 448 | |
449 | bootconfig.dramblocks = 0; | | 449 | bootconfig.dramblocks = 0; |
450 | | | 450 | |
451 | for (int i = 0; i < n && i < DRAM_BLOCKS; i++) { | | 451 | for (int i = 0; i < n && i < DRAM_BLOCKS; i++) { |
452 | bootconfig.dram[i].address = vptp_mem->mem[i].base; | | 452 | bootconfig.dram[i].address = vptp_mem->mem[i].base; |
453 | bootconfig.dram[i].pages = atop(vptp_mem->mem[i].size); | | 453 | bootconfig.dram[i].pages = atop(vptp_mem->mem[i].size); |
454 | bootconfig.dramblocks++; | | 454 | bootconfig.dramblocks++; |
455 | } | | 455 | } |
456 | } | | 456 | } |
457 | | | 457 | |
458 | if (vcprop_tag_success_p(&vb.vbt_armclockrate.tag)) | | 458 | if (vcprop_tag_success_p(&vb.vbt_armclockrate.tag)) |
459 | curcpu()->ci_data.cpu_cc_freq = vb.vbt_armclockrate.rate; | | 459 | curcpu()->ci_data.cpu_cc_freq = vb.vbt_armclockrate.rate; |
460 | | | 460 | |
461 | #ifdef VERBOSE_INIT_ARM | | 461 | #ifdef VERBOSE_INIT_ARM |
462 | if (vcprop_tag_success_p(&vb.vbt_fwrev.tag)) | | 462 | if (vcprop_tag_success_p(&vb.vbt_fwrev.tag)) |
463 | printf("%s: firmware rev %x\n", __func__, | | 463 | printf("%s: firmware rev %x\n", __func__, |
464 | vb.vbt_fwrev.rev); | | 464 | vb.vbt_fwrev.rev); |
465 | if (vcprop_tag_success_p(&vb.vbt_macaddr.tag)) | | 465 | if (vcprop_tag_success_p(&vb.vbt_macaddr.tag)) |
466 | printf("%s: mac-address %llx\n", __func__, | | 466 | printf("%s: mac-address %llx\n", __func__, |
467 | vb.vbt_macaddr.addr); | | 467 | vb.vbt_macaddr.addr); |
468 | if (vcprop_tag_success_p(&vb.vbt_boardmodel.tag)) | | 468 | if (vcprop_tag_success_p(&vb.vbt_boardmodel.tag)) |
469 | printf("%s: board model %x\n", __func__, | | 469 | printf("%s: board model %x\n", __func__, |
470 | vb.vbt_boardmodel.model); | | 470 | vb.vbt_boardmodel.model); |
471 | if (vcprop_tag_success_p(&vb.vbt_boardrev.tag)) | | 471 | if (vcprop_tag_success_p(&vb.vbt_boardrev.tag)) |
472 | printf("%s: board rev %x\n", __func__, | | 472 | printf("%s: board rev %x\n", __func__, |
473 | vb.vbt_boardrev.rev); | | 473 | vb.vbt_boardrev.rev); |
474 | if (vcprop_tag_success_p(&vb.vbt_serial.tag)) | | 474 | if (vcprop_tag_success_p(&vb.vbt_serial.tag)) |
475 | printf("%s: board serial %llx\n", __func__, | | 475 | printf("%s: board serial %llx\n", __func__, |
476 | vb.vbt_serial.sn); | | 476 | vb.vbt_serial.sn); |
477 | if (vcprop_tag_success_p(&vb.vbt_dmachan.tag)) | | 477 | if (vcprop_tag_success_p(&vb.vbt_dmachan.tag)) |
478 | printf("%s: DMA channel mask 0x%08x\n", __func__, | | 478 | printf("%s: DMA channel mask 0x%08x\n", __func__, |
479 | vb.vbt_dmachan.mask); | | 479 | vb.vbt_dmachan.mask); |
480 | | | 480 | |
481 | if (vcprop_tag_success_p(&vb.vbt_cmdline.tag)) | | 481 | if (vcprop_tag_success_p(&vb.vbt_cmdline.tag)) |
482 | printf("%s: cmdline %s\n", __func__, | | 482 | printf("%s: cmdline %s\n", __func__, |
483 | vb.vbt_cmdline.cmdline); | | 483 | vb.vbt_cmdline.cmdline); |
484 | #endif | | 484 | #endif |
485 | } | | 485 | } |
486 | | | 486 | |
487 | | | 487 | |
488 | static void | | 488 | static void |
489 | rpi_bootstrap(void) | | 489 | rpi_bootstrap(void) |
490 | { | | 490 | { |
491 | #if defined(BCM2836) | | 491 | #if defined(BCM2836) |
492 | arm_cpu_max = 4; | | 492 | arm_cpu_max = 4; |
493 | extern int cortex_mmuinfo; | | 493 | extern int cortex_mmuinfo; |
494 | bus_space_tag_t iot = &bcm2835_bs_tag; | | | |
495 | bus_space_handle_t ioh = BCM2836_ARM_LOCAL_VBASE; | | | |
496 | | | 494 | |
497 | #ifdef VERBOSE_INIT_ARM | | 495 | #ifdef VERBOSE_INIT_ARM |
498 | printf("%s: %d cpus present\n", __func__, arm_cpu_max); | | 496 | printf("%s: %d cpus present\n", __func__, arm_cpu_max); |
499 | #endif | | 497 | #endif |
500 | | | 498 | |
501 | extern void cortex_mpstart(void); | | | |
502 | cortex_mmuinfo = armreg_ttbr_read(); | | 499 | cortex_mmuinfo = armreg_ttbr_read(); |
| | | 500 | #ifdef VERBOSE_INIT_ARM |
| | | 501 | printf("%s: cortex_mmuinfo %x\n", __func__, cortex_mmuinfo); |
| | | 502 | #endif |
| | | 503 | |
| | | 504 | extern void cortex_mpstart(void); |
503 | | | 505 | |
504 | for (size_t i = 1; i < arm_cpu_max; i++) { | | 506 | for (size_t i = 1; i < arm_cpu_max; i++) { |
| | | 507 | bus_space_tag_t iot = &bcm2835_bs_tag; |
| | | 508 | bus_space_handle_t ioh = BCM2836_ARM_LOCAL_VBASE; |
| | | 509 | |
505 | bus_space_write_4(iot, ioh, | | 510 | bus_space_write_4(iot, ioh, |
506 | BCM2836_LOCAL_MAILBOX3_SETN(i), | | 511 | BCM2836_LOCAL_MAILBOX3_SETN(i), |
507 | (uint32_t)cortex_mpstart); | | 512 | (uint32_t)cortex_mpstart); |
508 | | | 513 | |
509 | int timeout = 20; | | 514 | int timeout = 20; |
510 | while (timeout-- > 0) { | | 515 | while (timeout-- > 0) { |
511 | uint32_t val; | | 516 | uint32_t val; |
512 | | | 517 | |
513 | val = bus_space_read_4(iot, ioh, | | 518 | val = bus_space_read_4(iot, ioh, |
514 | BCM2836_LOCAL_MAILBOX3_CLRN(i)); | | 519 | BCM2836_LOCAL_MAILBOX3_CLRN(i)); |
515 | if (val == 0) | | 520 | if (val == 0) |
516 | break; | | 521 | break; |
517 | } | | 522 | } |
518 | } | | 523 | } |
519 | | | 524 | |
520 | for (int loop = 0; loop < 16; loop++) { | | 525 | for (int loop = 0; loop < 16; loop++) { |
521 | if (arm_cpu_hatched == __BITS(arm_cpu_max - 1, 1)) | | 526 | if (arm_cpu_hatched == __BITS(arm_cpu_max - 1, 1)) |
522 | break; | | 527 | break; |
523 | gtmr_delay(10000); | | 528 | gtmr_delay(10000); |
524 | } | | 529 | } |
525 | | | 530 | |
526 | for (size_t i = 1; i < arm_cpu_max; i++) { | | 531 | for (size_t i = 1; i < arm_cpu_max; i++) { |
527 | if ((arm_cpu_hatched & (1 << i)) == 0) { | | 532 | if ((arm_cpu_hatched & (1 << i)) == 0) { |
528 | printf("%s: warning: cpu%zu failed to hatch\n", | | 533 | printf("%s: warning: cpu%zu failed to hatch\n", |
529 | __func__, i); | | 534 | __func__, i); |
530 | } | | 535 | } |
531 | } | | 536 | } |
532 | | | 537 | |
533 | /* | | 538 | /* |
534 | * XXXNH: Disable non-boot CPUs for now | | 539 | * XXXNH: Disable non-boot CPUs for now |
535 | */ | | 540 | */ |
536 | arm_cpu_hatched = 0; | | 541 | arm_cpu_hatched = 0; |
537 | #endif | | 542 | #endif |
538 | } | | 543 | } |
539 | | | 544 | |
540 | /* | | 545 | /* |
541 | * Static device mappings. These peripheral registers are mapped at | | 546 | * Static device mappings. These peripheral registers are mapped at |
542 | * fixed virtual addresses very early in initarm() so that we can use | | 547 | * fixed virtual addresses very early in initarm() so that we can use |
543 | * them while booting the kernel, and stay at the same address | | 548 | * them while booting the kernel, and stay at the same address |
544 | * throughout whole kernel's life time. | | 549 | * throughout whole kernel's life time. |
545 | * | | 550 | * |
546 | * We use this table twice; once with bootstrap page table, and once | | 551 | * We use this table twice; once with bootstrap page table, and once |
547 | * with kernel's page table which we build up in initarm(). | | 552 | * with kernel's page table which we build up in initarm(). |
548 | * | | 553 | * |
549 | * Since we map these registers into the bootstrap page table using | | 554 | * Since we map these registers into the bootstrap page table using |
550 | * pmap_devmap_bootstrap() which calls pmap_map_chunk(), we map | | 555 | * pmap_devmap_bootstrap() which calls pmap_map_chunk(), we map |
551 | * registers segment-aligned and segment-rounded in order to avoid | | 556 | * registers segment-aligned and segment-rounded in order to avoid |
552 | * using the 2nd page tables. | | 557 | * using the 2nd page tables. |
553 | */ | | 558 | */ |
554 | | | 559 | |
555 | #define _A(a) ((a) & ~L1_S_OFFSET) | | 560 | #define _A(a) ((a) & ~L1_S_OFFSET) |
556 | #define _S(s) (((s) + L1_S_SIZE - 1) & ~(L1_S_SIZE-1)) | | 561 | #define _S(s) (((s) + L1_S_SIZE - 1) & ~(L1_S_SIZE-1)) |
557 | | | 562 | |
558 | static const struct pmap_devmap rpi_devmap[] = { | | 563 | static const struct pmap_devmap rpi_devmap[] = { |
559 | { | | 564 | { |
560 | _A(RPI_KERNEL_IO_VBASE), | | 565 | _A(RPI_KERNEL_IO_VBASE), |
561 | _A(RPI_KERNEL_IO_PBASE), | | 566 | _A(RPI_KERNEL_IO_PBASE), |
562 | _S(RPI_KERNEL_IO_VSIZE), /* 16Mb */ | | 567 | _S(RPI_KERNEL_IO_VSIZE), /* 16Mb */ |
563 | VM_PROT_READ|VM_PROT_WRITE, | | 568 | VM_PROT_READ|VM_PROT_WRITE, |
564 | PTE_NOCACHE, | | 569 | PTE_NOCACHE, |
565 | }, | | 570 | }, |
566 | #if defined(BCM2836) | | 571 | #if defined(BCM2836) |
567 | { | | 572 | { |
568 | _A(RPI_KERNEL_LOCAL_VBASE), | | 573 | _A(RPI_KERNEL_LOCAL_VBASE), |
569 | _A(RPI_KERNEL_LOCAL_PBASE), | | 574 | _A(RPI_KERNEL_LOCAL_PBASE), |
570 | _S(RPI_KERNEL_LOCAL_VSIZE), | | 575 | _S(RPI_KERNEL_LOCAL_VSIZE), |
571 | VM_PROT_READ|VM_PROT_WRITE, | | 576 | VM_PROT_READ|VM_PROT_WRITE, |
572 | PTE_NOCACHE, | | 577 | PTE_NOCACHE, |
573 | }, | | 578 | }, |
574 | #endif | | 579 | #endif |
575 | { 0, 0, 0, 0, 0 } | | 580 | { 0, 0, 0, 0, 0 } |
576 | }; | | 581 | }; |
577 | | | 582 | |
578 | #undef _A | | 583 | #undef _A |
579 | #undef _S | | 584 | #undef _S |
580 | | | 585 | |
581 | /* | | 586 | /* |
582 | * u_int initarm(...) | | 587 | * u_int initarm(...) |
583 | * | | 588 | * |
584 | * Initial entry point on startup. This gets called before main() is | | 589 | * Initial entry point on startup. This gets called before main() is |
585 | * entered. | | 590 | * entered. |
586 | * It should be responsible for setting up everything that must be | | 591 | * It should be responsible for setting up everything that must be |
587 | * in place when main is called. | | 592 | * in place when main is called. |
588 | * This includes | | 593 | * This includes |
589 | * Taking a copy of the boot configuration structure. | | 594 | * Taking a copy of the boot configuration structure. |
590 | * Initialising the physical console so characters can be printed. | | 595 | * Initialising the physical console so characters can be printed. |
591 | * Setting up page tables for the kernel | | 596 | * Setting up page tables for the kernel |
592 | */ | | 597 | */ |
593 | u_int | | 598 | u_int |
594 | initarm(void *arg) | | 599 | initarm(void *arg) |
595 | { | | 600 | { |
596 | | | 601 | |
597 | /* | | 602 | /* |
598 | * Heads up ... Setup the CPU / MMU / TLB functions | | 603 | * Heads up ... Setup the CPU / MMU / TLB functions |
599 | */ | | 604 | */ |
600 | if (set_cpufuncs()) | | 605 | if (set_cpufuncs()) |
601 | panic("cpu not recognized!"); | | 606 | panic("cpu not recognized!"); |
602 | | | 607 | |
603 | /* map some peripheral registers */ | | 608 | /* map some peripheral registers */ |
604 | pmap_devmap_bootstrap((vaddr_t)armreg_ttbr_read() & -L1_TABLE_SIZE, | | 609 | pmap_devmap_bootstrap((vaddr_t)armreg_ttbr_read() & -L1_TABLE_SIZE, |
605 | rpi_devmap); | | 610 | rpi_devmap); |
606 | | | 611 | |
607 | cpu_domains((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT); | | 612 | cpu_domains((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT); |
608 | | | 613 | |
609 | consinit(); | | 614 | consinit(); |
610 | | | 615 | |
611 | /* Talk to the user */ | | 616 | /* Talk to the user */ |
612 | #define BDSTR(s) _BDSTR(s) | | 617 | #define BDSTR(s) _BDSTR(s) |
613 | #define _BDSTR(s) #s | | 618 | #define _BDSTR(s) #s |
614 | printf("\nNetBSD/evbarm (" BDSTR(EVBARM_BOARDTYPE) ") booting ...\n"); | | 619 | printf("\nNetBSD/evbarm (" BDSTR(EVBARM_BOARDTYPE) ") booting ...\n"); |
615 | | | 620 | |
616 | #ifdef CORTEX_PMC | | 621 | #ifdef CORTEX_PMC |
617 | cortex_pmc_ccnt_init(); | | 622 | cortex_pmc_ccnt_init(); |
618 | #endif | | 623 | #endif |
619 | | | 624 | |
620 | rpi_bootparams(); | | 625 | rpi_bootparams(); |
621 | | | 626 | |
622 | rpi_bootstrap(); | | 627 | rpi_bootstrap(); |
623 | | | 628 | |
624 | if (vcprop_tag_success_p(&vb.vbt_armclockrate.tag)) { | | 629 | if (vcprop_tag_success_p(&vb.vbt_armclockrate.tag)) { |
625 | curcpu()->ci_data.cpu_cc_freq = vb.vbt_armclockrate.rate; | | 630 | curcpu()->ci_data.cpu_cc_freq = vb.vbt_armclockrate.rate; |
626 | #ifdef VERBOSE_INIT_ARM | | 631 | #ifdef VERBOSE_INIT_ARM |
627 | printf("%s: arm clock %d\n", __func__, | | 632 | printf("%s: arm clock %d\n", __func__, |
628 | vb.vbt_armclockrate.rate); | | 633 | vb.vbt_armclockrate.rate); |
629 | #endif | | 634 | #endif |
630 | } | | 635 | } |
631 | | | 636 | |
632 | #ifdef VERBOSE_INIT_ARM | | 637 | #ifdef VERBOSE_INIT_ARM |
633 | printf("initarm: Configuring system ...\n"); | | 638 | printf("initarm: Configuring system ...\n"); |
634 | #endif | | 639 | #endif |
635 | | | 640 | |
636 | psize_t ram_size = bootconfig.dram[0].pages * PAGE_SIZE; | | 641 | psize_t ram_size = bootconfig.dram[0].pages * PAGE_SIZE; |
637 | | | 642 | |
638 | #ifdef __HAVE_MM_MD_DIRECT_MAPPED_PHYS | | 643 | #ifdef __HAVE_MM_MD_DIRECT_MAPPED_PHYS |
639 | if (ram_size > KERNEL_VM_BASE - KERNEL_BASE) { | | 644 | if (ram_size > KERNEL_VM_BASE - KERNEL_BASE) { |
640 | printf("%s: dropping RAM size from %luMB to %uMB\n", | | 645 | printf("%s: dropping RAM size from %luMB to %uMB\n", |
641 | __func__, (unsigned long) (ram_size >> 20), | | 646 | __func__, (unsigned long) (ram_size >> 20), |
642 | (KERNEL_VM_BASE - KERNEL_BASE) >> 20); | | 647 | (KERNEL_VM_BASE - KERNEL_BASE) >> 20); |
643 | ram_size = KERNEL_VM_BASE - KERNEL_BASE; | | 648 | ram_size = KERNEL_VM_BASE - KERNEL_BASE; |
644 | } | | 649 | } |
645 | #endif | | 650 | #endif |
646 | | | 651 | |
647 | /* | | 652 | /* |
648 | * If MEMSIZE specified less than what we really have, limit ourselves | | 653 | * If MEMSIZE specified less than what we really have, limit ourselves |
649 | * to that. | | 654 | * to that. |
650 | */ | | 655 | */ |
651 | #ifdef MEMSIZE | | 656 | #ifdef MEMSIZE |
652 | if (ram_size == 0 || ram_size > (unsigned)MEMSIZE * 1024 * 1024) | | 657 | if (ram_size == 0 || ram_size > (unsigned)MEMSIZE * 1024 * 1024) |
653 | ram_size = (unsigned)MEMSIZE * 1024 * 1024; | | 658 | ram_size = (unsigned)MEMSIZE * 1024 * 1024; |
654 | #else | | 659 | #else |
655 | KASSERTMSG(ram_size > 0, "RAM size unknown and MEMSIZE undefined"); | | 660 | KASSERTMSG(ram_size > 0, "RAM size unknown and MEMSIZE undefined"); |
656 | #endif | | 661 | #endif |
657 | | | 662 | |
658 | arm32_bootmem_init(bootconfig.dram[0].address, ram_size, | | 663 | arm32_bootmem_init(bootconfig.dram[0].address, ram_size, |
659 | (uintptr_t)KERNEL_BASE_phys); | | 664 | (uintptr_t)KERNEL_BASE_phys); |
660 | | | 665 | |
661 | #ifdef __HAVE_MM_MD_DIRECT_MAPPED_PHYS | | 666 | #ifdef __HAVE_MM_MD_DIRECT_MAPPED_PHYS |
662 | const bool mapallmem_p = true; | | 667 | const bool mapallmem_p = true; |
663 | KASSERT(ram_size <= KERNEL_VM_BASE - KERNEL_BASE); | | 668 | KASSERT(ram_size <= KERNEL_VM_BASE - KERNEL_BASE); |
664 | #else | | 669 | #else |
665 | const bool mapallmem_p = false; | | 670 | const bool mapallmem_p = false; |
666 | #endif | | 671 | #endif |
667 | | | 672 | |
668 | arm32_kernel_vm_init(KERNEL_VM_BASE, ARM_VECTORS_HIGH, 0, rpi_devmap, | | 673 | arm32_kernel_vm_init(KERNEL_VM_BASE, ARM_VECTORS_HIGH, 0, rpi_devmap, |
669 | mapallmem_p); | | 674 | mapallmem_p); |
670 | | | 675 | |
671 | cpu_reset_address = bcm2835_system_reset; | | 676 | cpu_reset_address = bcm2835_system_reset; |
672 | | | 677 | |
673 | #ifdef VERBOSE_INIT_ARM | | 678 | #ifdef VERBOSE_INIT_ARM |
674 | printf("done.\n"); | | 679 | printf("done.\n"); |
675 | #endif | | 680 | #endif |
676 | | | 681 | |
677 | #ifdef KGDB | | 682 | #ifdef KGDB |
678 | kgdb_port_init(); | | 683 | kgdb_port_init(); |
679 | #endif | | 684 | #endif |
680 | | | 685 | |
681 | #ifdef __HAVE_MEMORY_DISK__ | | 686 | #ifdef __HAVE_MEMORY_DISK__ |
682 | md_root_setconf(memory_disk, sizeof memory_disk); | | 687 | md_root_setconf(memory_disk, sizeof memory_disk); |
683 | #endif | | 688 | #endif |
684 | | | 689 | |
685 | if (vcprop_tag_success_p(&vb.vbt_cmdline.tag)) | | 690 | if (vcprop_tag_success_p(&vb.vbt_cmdline.tag)) |
686 | strlcpy(bootargs, vb.vbt_cmdline.cmdline, sizeof(bootargs)); | | 691 | strlcpy(bootargs, vb.vbt_cmdline.cmdline, sizeof(bootargs)); |
687 | boot_args = bootargs; | | 692 | boot_args = bootargs; |
688 | parse_mi_bootargs(boot_args); | | 693 | parse_mi_bootargs(boot_args); |
689 | | | 694 | |
690 | #ifdef BOOTHOWTO | | 695 | #ifdef BOOTHOWTO |
691 | boothowto |= BOOTHOWTO; | | 696 | boothowto |= BOOTHOWTO; |
692 | #endif | | 697 | #endif |
693 | | | 698 | |
694 | /* we've a specific device_register routine */ | | 699 | /* we've a specific device_register routine */ |
695 | evbarm_device_register = rpi_device_register; | | 700 | evbarm_device_register = rpi_device_register; |
696 | | | 701 | |
697 | return initarm_common(KERNEL_VM_BASE, KERNEL_VM_SIZE, NULL, 0); | | 702 | return initarm_common(KERNEL_VM_BASE, KERNEL_VM_SIZE, NULL, 0); |
698 | } | | 703 | } |
699 | | | 704 | |
700 | void | | 705 | void |
701 | consinit(void) | | 706 | consinit(void) |
702 | { | | 707 | { |
703 | static int consinit_called = 0; | | 708 | static int consinit_called = 0; |
704 | | | 709 | |
705 | if (consinit_called != 0) | | 710 | if (consinit_called != 0) |
706 | return; | | 711 | return; |
707 | | | 712 | |
708 | consinit_called = 1; | | 713 | consinit_called = 1; |
709 | | | 714 | |
710 | #if (NPLCOM > 0 && defined(PLCONSOLE)) | | 715 | #if (NPLCOM > 0 && defined(PLCONSOLE)) |
711 | /* | | 716 | /* |
712 | * Initialise the diagnostic serial console | | 717 | * Initialise the diagnostic serial console |
713 | * This allows a means of generating output during initarm(). | | 718 | * This allows a means of generating output during initarm(). |
714 | */ | | 719 | */ |
715 | rpi_pi.pi_iobase = consaddr; | | 720 | rpi_pi.pi_iobase = consaddr; |
716 | | | 721 | |
717 | plcomcnattach(&rpi_pi, plcomcnspeed, BCM2835_UART0_CLK, | | 722 | plcomcnattach(&rpi_pi, plcomcnspeed, BCM2835_UART0_CLK, |
718 | plcomcnmode, PLCOMCNUNIT); | | 723 | plcomcnmode, PLCOMCNUNIT); |
719 | | | 724 | |
720 | #endif | | 725 | #endif |
721 | } | | 726 | } |
722 | | | 727 | |
723 | #ifdef KGDB | | 728 | #ifdef KGDB |
724 | #if !defined(KGDB_PLCOMUNIT) || !defined(KGDB_DEVRATE) || !defined(KGDB_CONMODE) | | 729 | #if !defined(KGDB_PLCOMUNIT) || !defined(KGDB_DEVRATE) || !defined(KGDB_CONMODE) |
725 | #error Specify KGDB_PLCOMUNIT, KGDB_DEVRATE and KGDB_CONMODE for KGDB. | | 730 | #error Specify KGDB_PLCOMUNIT, KGDB_DEVRATE and KGDB_CONMODE for KGDB. |
726 | #endif | | 731 | #endif |
727 | | | 732 | |
728 | void | | 733 | void |
729 | static kgdb_port_init(void) | | 734 | static kgdb_port_init(void) |
730 | { | | 735 | { |
731 | static int kgdbsinit_called = 0; | | 736 | static int kgdbsinit_called = 0; |
732 | int res; | | 737 | int res; |
733 | | | 738 | |
734 | if (kgdbsinit_called != 0) | | 739 | if (kgdbsinit_called != 0) |
735 | return; | | 740 | return; |
736 | | | 741 | |
737 | kgdbsinit_called = 1; | | 742 | kgdbsinit_called = 1; |
738 | | | 743 | |
739 | rpi_pi.pi_iobase = consaddr; | | 744 | rpi_pi.pi_iobase = consaddr; |
740 | | | 745 | |
741 | res = plcom_kgdb_attach(&rpi_pi, KGDB_DEVRATE, BCM2835_UART0_CLK, | | 746 | res = plcom_kgdb_attach(&rpi_pi, KGDB_DEVRATE, BCM2835_UART0_CLK, |
742 | KGDB_CONMODE, KGDB_PLCOMUNIT); | | 747 | KGDB_CONMODE, KGDB_PLCOMUNIT); |
743 | if (res) | | 748 | if (res) |
744 | panic("KGDB uart can not be initialized, err=%d.", res); | | 749 | panic("KGDB uart can not be initialized, err=%d.", res); |
745 | } | | 750 | } |
746 | #endif | | 751 | #endif |
747 | | | 752 | |
748 | #if NGENFB > 0 | | 753 | #if NGENFB > 0 |
749 | static bool | | 754 | static bool |
750 | rpi_fb_parse_mode(const char *s, uint32_t *pwidth, uint32_t *pheight) | | 755 | rpi_fb_parse_mode(const char *s, uint32_t *pwidth, uint32_t *pheight) |
751 | { | | 756 | { |
752 | char *x; | | 757 | char *x; |
753 | | | 758 | |
754 | if (strncmp(s, "disable", 7) == 0) | | 759 | if (strncmp(s, "disable", 7) == 0) |
755 | return false; | | 760 | return false; |
756 | | | 761 | |
757 | x = strchr(s, 'x'); | | 762 | x = strchr(s, 'x'); |
758 | if (x) { | | 763 | if (x) { |
759 | *pwidth = strtoul(s, NULL, 10); | | 764 | *pwidth = strtoul(s, NULL, 10); |
760 | *pheight = strtoul(x + 1, NULL, 10); | | 765 | *pheight = strtoul(x + 1, NULL, 10); |
761 | } | | 766 | } |
762 | | | 767 | |
763 | return true; | | 768 | return true; |
764 | } | | 769 | } |
765 | | | 770 | |
766 | static bool | | 771 | static bool |
767 | rpi_fb_get_edid_mode(uint32_t *pwidth, uint32_t *pheight) | | 772 | rpi_fb_get_edid_mode(uint32_t *pwidth, uint32_t *pheight) |
768 | { | | 773 | { |
769 | struct edid_info ei; | | 774 | struct edid_info ei; |
770 | uint8_t edid_data[1024]; | | 775 | uint8_t edid_data[1024]; |
771 | uint32_t res; | | 776 | uint32_t res; |
772 | int error; | | 777 | int error; |
773 | | | 778 | |
774 | error = bcmmbox_request(BCMMBOX_CHANARM2VC, &vb_edid, | | 779 | error = bcmmbox_request(BCMMBOX_CHANARM2VC, &vb_edid, |
775 | sizeof(vb_edid), &res); | | 780 | sizeof(vb_edid), &res); |
776 | if (error) { | | 781 | if (error) { |
777 | printf("%s: mbox request failed (%d)\n", __func__, error); | | 782 | printf("%s: mbox request failed (%d)\n", __func__, error); |
778 | return false; | | 783 | return false; |
779 | } | | 784 | } |
780 | | | 785 | |
781 | if (!vcprop_buffer_success_p(&vb_edid.vb_hdr) || | | 786 | if (!vcprop_buffer_success_p(&vb_edid.vb_hdr) || |
782 | !vcprop_tag_success_p(&vb_edid.vbt_edid.tag) || | | 787 | !vcprop_tag_success_p(&vb_edid.vbt_edid.tag) || |
783 | vb_edid.vbt_edid.status != 0) | | 788 | vb_edid.vbt_edid.status != 0) |
784 | return false; | | 789 | return false; |
785 | | | 790 | |
786 | memset(edid_data, 0, sizeof(edid_data)); | | 791 | memset(edid_data, 0, sizeof(edid_data)); |
787 | memcpy(edid_data, vb_edid.vbt_edid.data, | | 792 | memcpy(edid_data, vb_edid.vbt_edid.data, |
788 | sizeof(vb_edid.vbt_edid.data)); | | 793 | sizeof(vb_edid.vbt_edid.data)); |
789 | edid_parse(edid_data, &ei); | | 794 | edid_parse(edid_data, &ei); |
790 | #ifdef VERBOSE_INIT_ARM | | 795 | #ifdef VERBOSE_INIT_ARM |
791 | edid_print(&ei); | | 796 | edid_print(&ei); |
792 | #endif | | 797 | #endif |
793 | | | 798 | |
794 | if (ei.edid_preferred_mode) { | | 799 | if (ei.edid_preferred_mode) { |
795 | *pwidth = ei.edid_preferred_mode->hdisplay; | | 800 | *pwidth = ei.edid_preferred_mode->hdisplay; |
796 | *pheight = ei.edid_preferred_mode->vdisplay; | | 801 | *pheight = ei.edid_preferred_mode->vdisplay; |
797 | } | | 802 | } |
798 | | | 803 | |
799 | return true; | | 804 | return true; |
800 | } | | 805 | } |
801 | | | 806 | |
802 | /* | | 807 | /* |
803 | * Initialize framebuffer console. | | 808 | * Initialize framebuffer console. |
804 | * | | 809 | * |
805 | * Some notes about boot parameters: | | 810 | * Some notes about boot parameters: |
806 | * - If "fb=disable" is present, ignore framebuffer completely. | | 811 | * - If "fb=disable" is present, ignore framebuffer completely. |
807 | * - If "fb=<width>x<height> is present, use the specified mode. | | 812 | * - If "fb=<width>x<height> is present, use the specified mode. |
808 | * - If "console=fb" is present, attach framebuffer to console. | | 813 | * - If "console=fb" is present, attach framebuffer to console. |
809 | */ | | 814 | */ |
810 | static bool | | 815 | static bool |
811 | rpi_fb_init(prop_dictionary_t dict, void *aux) | | 816 | rpi_fb_init(prop_dictionary_t dict, void *aux) |
812 | { | | 817 | { |
813 | uint32_t width = 0, height = 0; | | 818 | uint32_t width = 0, height = 0; |
814 | uint32_t res; | | 819 | uint32_t res; |
815 | char *ptr; | | 820 | char *ptr; |
816 | int integer; | | 821 | int integer; |
817 | int error; | | 822 | int error; |
818 | bool is_bgr = true; | | 823 | bool is_bgr = true; |
819 | | | 824 | |
820 | if (get_bootconf_option(boot_args, "fb", | | 825 | if (get_bootconf_option(boot_args, "fb", |
821 | BOOTOPT_TYPE_STRING, &ptr)) { | | 826 | BOOTOPT_TYPE_STRING, &ptr)) { |
822 | if (rpi_fb_parse_mode(ptr, &width, &height) == false) | | 827 | if (rpi_fb_parse_mode(ptr, &width, &height) == false) |
823 | return false; | | 828 | return false; |
824 | } | | 829 | } |
825 | if (width == 0 || height == 0) { | | 830 | if (width == 0 || height == 0) { |
826 | rpi_fb_get_edid_mode(&width, &height); | | 831 | rpi_fb_get_edid_mode(&width, &height); |
827 | } | | 832 | } |
828 | if (width == 0 || height == 0) { | | 833 | if (width == 0 || height == 0) { |
829 | width = RPI_FB_WIDTH; | | 834 | width = RPI_FB_WIDTH; |
830 | height = RPI_FB_HEIGHT; | | 835 | height = RPI_FB_HEIGHT; |
831 | } | | 836 | } |
832 | | | 837 | |
833 | vb_setfb.vbt_res.width = width; | | 838 | vb_setfb.vbt_res.width = width; |
834 | vb_setfb.vbt_res.height = height; | | 839 | vb_setfb.vbt_res.height = height; |
835 | vb_setfb.vbt_vres.width = width; | | 840 | vb_setfb.vbt_vres.width = width; |
836 | vb_setfb.vbt_vres.height = height; | | 841 | vb_setfb.vbt_vres.height = height; |
837 | error = bcmmbox_request(BCMMBOX_CHANARM2VC, &vb_setfb, | | 842 | error = bcmmbox_request(BCMMBOX_CHANARM2VC, &vb_setfb, |
838 | sizeof(vb_setfb), &res); | | 843 | sizeof(vb_setfb), &res); |
839 | if (error) { | | 844 | if (error) { |
840 | printf("%s: mbox request failed (%d)\n", __func__, error); | | 845 | printf("%s: mbox request failed (%d)\n", __func__, error); |
841 | return false; | | 846 | return false; |
842 | } | | 847 | } |
843 | | | 848 | |
844 | if (!vcprop_buffer_success_p(&vb_setfb.vb_hdr) || | | 849 | if (!vcprop_buffer_success_p(&vb_setfb.vb_hdr) || |
845 | !vcprop_tag_success_p(&vb_setfb.vbt_res.tag) || | | 850 | !vcprop_tag_success_p(&vb_setfb.vbt_res.tag) || |
846 | !vcprop_tag_success_p(&vb_setfb.vbt_vres.tag) || | | 851 | !vcprop_tag_success_p(&vb_setfb.vbt_vres.tag) || |
847 | !vcprop_tag_success_p(&vb_setfb.vbt_depth.tag) || | | 852 | !vcprop_tag_success_p(&vb_setfb.vbt_depth.tag) || |
848 | !vcprop_tag_success_p(&vb_setfb.vbt_allocbuf.tag) || | | 853 | !vcprop_tag_success_p(&vb_setfb.vbt_allocbuf.tag) || |
849 | !vcprop_tag_success_p(&vb_setfb.vbt_blank.tag) || | | 854 | !vcprop_tag_success_p(&vb_setfb.vbt_blank.tag) || |
850 | !vcprop_tag_success_p(&vb_setfb.vbt_pitch.tag)) { | | 855 | !vcprop_tag_success_p(&vb_setfb.vbt_pitch.tag)) { |
851 | printf("%s: prop tag failed\n", __func__); | | 856 | printf("%s: prop tag failed\n", __func__); |
852 | return false; | | 857 | return false; |
853 | } | | 858 | } |
854 | | | 859 | |
855 | #ifdef VERBOSE_INIT_ARM | | 860 | #ifdef VERBOSE_INIT_ARM |
856 | printf("%s: addr = 0x%x size = %d\n", __func__, | | 861 | printf("%s: addr = 0x%x size = %d\n", __func__, |
857 | vb_setfb.vbt_allocbuf.address, | | 862 | vb_setfb.vbt_allocbuf.address, |
858 | vb_setfb.vbt_allocbuf.size); | | 863 | vb_setfb.vbt_allocbuf.size); |
859 | printf("%s: depth = %d\n", __func__, vb_setfb.vbt_depth.bpp); | | 864 | printf("%s: depth = %d\n", __func__, vb_setfb.vbt_depth.bpp); |
860 | printf("%s: pitch = %d\n", __func__, | | 865 | printf("%s: pitch = %d\n", __func__, |
861 | vb_setfb.vbt_pitch.linebytes); | | 866 | vb_setfb.vbt_pitch.linebytes); |
862 | printf("%s: width = %d height = %d\n", __func__, | | 867 | printf("%s: width = %d height = %d\n", __func__, |
863 | vb_setfb.vbt_res.width, vb_setfb.vbt_res.height); | | 868 | vb_setfb.vbt_res.width, vb_setfb.vbt_res.height); |
864 | printf("%s: vwidth = %d vheight = %d\n", __func__, | | 869 | printf("%s: vwidth = %d vheight = %d\n", __func__, |
865 | vb_setfb.vbt_vres.width, vb_setfb.vbt_vres.height); | | 870 | vb_setfb.vbt_vres.width, vb_setfb.vbt_vres.height); |
866 | #endif | | 871 | #endif |
867 | | | 872 | |
868 | if (vb_setfb.vbt_allocbuf.address == 0 || | | 873 | if (vb_setfb.vbt_allocbuf.address == 0 || |
869 | vb_setfb.vbt_allocbuf.size == 0 || | | 874 | vb_setfb.vbt_allocbuf.size == 0 || |
870 | vb_setfb.vbt_res.width == 0 || | | 875 | vb_setfb.vbt_res.width == 0 || |
871 | vb_setfb.vbt_res.height == 0 || | | 876 | vb_setfb.vbt_res.height == 0 || |
872 | vb_setfb.vbt_vres.width == 0 || | | 877 | vb_setfb.vbt_vres.width == 0 || |
873 | vb_setfb.vbt_vres.height == 0 || | | 878 | vb_setfb.vbt_vres.height == 0 || |
874 | vb_setfb.vbt_pitch.linebytes == 0) { | | 879 | vb_setfb.vbt_pitch.linebytes == 0) { |
875 | printf("%s: failed to set mode %ux%u\n", __func__, | | 880 | printf("%s: failed to set mode %ux%u\n", __func__, |
876 | width, height); | | 881 | width, height); |
877 | return false; | | 882 | return false; |
878 | } | | 883 | } |
879 | | | 884 | |
880 | prop_dictionary_set_uint32(dict, "width", vb_setfb.vbt_res.width); | | 885 | prop_dictionary_set_uint32(dict, "width", vb_setfb.vbt_res.width); |
881 | prop_dictionary_set_uint32(dict, "height", vb_setfb.vbt_res.height); | | 886 | prop_dictionary_set_uint32(dict, "height", vb_setfb.vbt_res.height); |
882 | prop_dictionary_set_uint8(dict, "depth", vb_setfb.vbt_depth.bpp); | | 887 | prop_dictionary_set_uint8(dict, "depth", vb_setfb.vbt_depth.bpp); |
883 | prop_dictionary_set_uint16(dict, "linebytes", | | 888 | prop_dictionary_set_uint16(dict, "linebytes", |
884 | vb_setfb.vbt_pitch.linebytes); | | 889 | vb_setfb.vbt_pitch.linebytes); |
885 | prop_dictionary_set_uint32(dict, "address", | | 890 | prop_dictionary_set_uint32(dict, "address", |
886 | vb_setfb.vbt_allocbuf.address); | | 891 | vb_setfb.vbt_allocbuf.address); |
887 | | | 892 | |
888 | /* | | 893 | /* |
889 | * Old firmware uses BGR. New firmware uses RGB. The get and set | | 894 | * Old firmware uses BGR. New firmware uses RGB. The get and set |
890 | * pixel order mailbox properties don't seem to work. The firmware | | 895 | * pixel order mailbox properties don't seem to work. The firmware |
891 | * adds a kernel cmdline option bcm2708_fb.fbswap=<0|1>, so use it | | 896 | * adds a kernel cmdline option bcm2708_fb.fbswap=<0|1>, so use it |
892 | * to determine pixel order. 0 means BGR, 1 means RGB. | | 897 | * to determine pixel order. 0 means BGR, 1 means RGB. |
893 | * | | 898 | * |
894 | * See https://github.com/raspberrypi/linux/issues/514 | | 899 | * See https://github.com/raspberrypi/linux/issues/514 |
895 | */ | | 900 | */ |
896 | if (get_bootconf_option(boot_args, "bcm2708_fb.fbswap", | | 901 | if (get_bootconf_option(boot_args, "bcm2708_fb.fbswap", |
897 | BOOTOPT_TYPE_INT, &integer)) { | | 902 | BOOTOPT_TYPE_INT, &integer)) { |
898 | is_bgr = integer == 0; | | 903 | is_bgr = integer == 0; |
899 | } | | 904 | } |
900 | prop_dictionary_set_bool(dict, "is_bgr", is_bgr); | | 905 | prop_dictionary_set_bool(dict, "is_bgr", is_bgr); |
901 | | | 906 | |
902 | /* if "genfb.type=<n>" is passed in cmdline, override wsdisplay type */ | | 907 | /* if "genfb.type=<n>" is passed in cmdline, override wsdisplay type */ |
903 | if (get_bootconf_option(boot_args, "genfb.type", | | 908 | if (get_bootconf_option(boot_args, "genfb.type", |
904 | BOOTOPT_TYPE_INT, &integer)) { | | 909 | BOOTOPT_TYPE_INT, &integer)) { |
905 | prop_dictionary_set_uint32(dict, "wsdisplay_type", integer); | | 910 | prop_dictionary_set_uint32(dict, "wsdisplay_type", integer); |
906 | } | | 911 | } |
907 | | | 912 | |
908 | #if defined(RPI_HWCURSOR) | | 913 | #if defined(RPI_HWCURSOR) |
909 | struct amba_attach_args *aaa = aux; | | 914 | struct amba_attach_args *aaa = aux; |
910 | bus_space_handle_t hc; | | 915 | bus_space_handle_t hc; |
911 | | | 916 | |
912 | hcursor = rpi_alloc_mem(CURSOR_ARGB_SIZE, PAGE_SIZE, | | 917 | hcursor = rpi_alloc_mem(CURSOR_ARGB_SIZE, PAGE_SIZE, |
913 | MEM_FLAG_L1_NONALLOCATING | MEM_FLAG_HINT_PERMALOCK); | | 918 | MEM_FLAG_L1_NONALLOCATING | MEM_FLAG_HINT_PERMALOCK); |
914 | pcursor = rpi_lock_mem(hcursor); | | 919 | pcursor = rpi_lock_mem(hcursor); |
915 | #ifdef RPI_IOCTL_DEBUG | | 920 | #ifdef RPI_IOCTL_DEBUG |
916 | printf("hcursor: %08x\n", hcursor); | | 921 | printf("hcursor: %08x\n", hcursor); |
917 | printf("pcursor: %08x\n", (uint32_t)pcursor); | | 922 | printf("pcursor: %08x\n", (uint32_t)pcursor); |
918 | printf("fb: %08x\n", (uint32_t)vb_setfb.vbt_allocbuf.address); | | 923 | printf("fb: %08x\n", (uint32_t)vb_setfb.vbt_allocbuf.address); |
919 | #endif | | 924 | #endif |
920 | if (bus_space_map(aaa->aaa_iot, pcursor, CURSOR_ARGB_SIZE, | | 925 | if (bus_space_map(aaa->aaa_iot, pcursor, CURSOR_ARGB_SIZE, |
921 | BUS_SPACE_MAP_LINEAR|BUS_SPACE_MAP_PREFETCHABLE, &hc) != 0) { | | 926 | BUS_SPACE_MAP_LINEAR|BUS_SPACE_MAP_PREFETCHABLE, &hc) != 0) { |
922 | printf("couldn't map cursor memory\n"); | | 927 | printf("couldn't map cursor memory\n"); |
923 | } else { | | 928 | } else { |
924 | int i, j, k; | | 929 | int i, j, k; |
925 | | | 930 | |
926 | cmem = bus_space_vaddr(aaa->aaa_iot, hc); | | 931 | cmem = bus_space_vaddr(aaa->aaa_iot, hc); |
927 | k = 0; | | 932 | k = 0; |
928 | for (j = 0; j < 64; j++) { | | 933 | for (j = 0; j < 64; j++) { |
929 | for (i = 0; i < 64; i++) { | | 934 | for (i = 0; i < 64; i++) { |
930 | cmem[i + k] = | | 935 | cmem[i + k] = |
931 | ((i & 8) ^ (j & 8)) ? 0xa0ff0000 : 0xa000ff00; | | 936 | ((i & 8) ^ (j & 8)) ? 0xa0ff0000 : 0xa000ff00; |
932 | } | | 937 | } |
933 | k += 64; | | 938 | k += 64; |
934 | } | | 939 | } |
935 | cpu_dcache_wb_range((vaddr_t)cmem, CURSOR_ARGB_SIZE); | | 940 | cpu_dcache_wb_range((vaddr_t)cmem, CURSOR_ARGB_SIZE); |
936 | rpi_fb_initcursor(pcursor, 0, 0); | | 941 | rpi_fb_initcursor(pcursor, 0, 0); |
937 | #ifdef RPI_IOCTL_DEBUG | | 942 | #ifdef RPI_IOCTL_DEBUG |
938 | rpi_fb_movecursor(600, 400, 1); | | 943 | rpi_fb_movecursor(600, 400, 1); |
939 | #else | | 944 | #else |
940 | rpi_fb_movecursor(cursor_x, cursor_y, cursor_on); | | 945 | rpi_fb_movecursor(cursor_x, cursor_y, cursor_on); |
941 | #endif | | 946 | #endif |
942 | } | | 947 | } |
943 | #endif | | 948 | #endif |
944 | | | 949 | |
945 | return true; | | 950 | return true; |
946 | } | | 951 | } |
947 | | | 952 | |
948 | | | 953 | |
949 | #if defined(RPI_HWCURSOR) | | 954 | #if defined(RPI_HWCURSOR) |
950 | static int | | 955 | static int |
951 | rpi_fb_do_cursor(struct wsdisplay_cursor *cur) | | 956 | rpi_fb_do_cursor(struct wsdisplay_cursor *cur) |
952 | { | | 957 | { |
953 | int pos = 0; | | 958 | int pos = 0; |
954 | int shape = 0; | | 959 | int shape = 0; |
955 | | | 960 | |
956 | if (cur->which & WSDISPLAY_CURSOR_DOCUR) { | | 961 | if (cur->which & WSDISPLAY_CURSOR_DOCUR) { |
957 | if (cursor_on != cur->enable) { | | 962 | if (cursor_on != cur->enable) { |
958 | cursor_on = cur->enable; | | 963 | cursor_on = cur->enable; |
959 | pos = 1; | | 964 | pos = 1; |
960 | } | | 965 | } |
961 | } | | 966 | } |
962 | if (cur->which & WSDISPLAY_CURSOR_DOHOT) { | | 967 | if (cur->which & WSDISPLAY_CURSOR_DOHOT) { |
963 | | | 968 | |
964 | hot_x = cur->hot.x; | | 969 | hot_x = cur->hot.x; |
965 | hot_y = cur->hot.y; | | 970 | hot_y = cur->hot.y; |
966 | pos = 1; | | 971 | pos = 1; |
967 | shape = 1; | | 972 | shape = 1; |
968 | } | | 973 | } |
969 | if (cur->which & WSDISPLAY_CURSOR_DOPOS) { | | 974 | if (cur->which & WSDISPLAY_CURSOR_DOPOS) { |
970 | | | 975 | |
971 | cursor_x = cur->pos.x; | | 976 | cursor_x = cur->pos.x; |
972 | cursor_y = cur->pos.y; | | 977 | cursor_y = cur->pos.y; |
973 | pos = 1; | | 978 | pos = 1; |
974 | } | | 979 | } |
975 | if (cur->which & WSDISPLAY_CURSOR_DOCMAP) { | | 980 | if (cur->which & WSDISPLAY_CURSOR_DOCMAP) { |
976 | int i; | | 981 | int i; |
977 | uint32_t val; | | 982 | uint32_t val; |
978 | | | 983 | |
979 | for (i = 0; i < min(cur->cmap.count, 3); i++) { | | 984 | for (i = 0; i < min(cur->cmap.count, 3); i++) { |
980 | val = (cur->cmap.red[i] << 16 ) | | | 985 | val = (cur->cmap.red[i] << 16 ) | |
981 | (cur->cmap.green[i] << 8) | | | 986 | (cur->cmap.green[i] << 8) | |
982 | (cur->cmap.blue[i] ) | | | 987 | (cur->cmap.blue[i] ) | |
983 | 0xff000000; | | 988 | 0xff000000; |
984 | cursor_cmap[i + cur->cmap.index + 2] = val; | | 989 | cursor_cmap[i + cur->cmap.index + 2] = val; |
985 | } | | 990 | } |
986 | shape = 1; | | 991 | shape = 1; |
987 | } | | 992 | } |
988 | if (cur->which & WSDISPLAY_CURSOR_DOSHAPE) { | | 993 | if (cur->which & WSDISPLAY_CURSOR_DOSHAPE) { |
989 | int err; | | 994 | int err; |
990 | | | 995 | |
991 | err = copyin(cur->mask, cursor_mask, CURSOR_BITMAP_SIZE); | | 996 | err = copyin(cur->mask, cursor_mask, CURSOR_BITMAP_SIZE); |
992 | err += copyin(cur->image, cursor_bitmap, CURSOR_BITMAP_SIZE); | | 997 | err += copyin(cur->image, cursor_bitmap, CURSOR_BITMAP_SIZE); |
993 | if (err != 0) | | 998 | if (err != 0) |
994 | return EFAULT; | | 999 | return EFAULT; |
995 | shape = 1; | | 1000 | shape = 1; |
996 | } | | 1001 | } |
997 | if (shape) { | | 1002 | if (shape) { |
998 | int i, j, idx; | | 1003 | int i, j, idx; |
999 | uint8_t mask; | | 1004 | uint8_t mask; |
1000 | | | 1005 | |
1001 | for (i = 0; i < CURSOR_BITMAP_SIZE; i++) { | | 1006 | for (i = 0; i < CURSOR_BITMAP_SIZE; i++) { |
1002 | mask = 0x01; | | 1007 | mask = 0x01; |
1003 | for (j = 0; j < 8; j++) { | | 1008 | for (j = 0; j < 8; j++) { |
1004 | idx = ((cursor_mask[i] & mask) ? 2 : 0) | | | 1009 | idx = ((cursor_mask[i] & mask) ? 2 : 0) | |
1005 | ((cursor_bitmap[i] & mask) ? 1 : 0); | | 1010 | ((cursor_bitmap[i] & mask) ? 1 : 0); |
1006 | cmem[i * 8 + j] = cursor_cmap[idx]; | | 1011 | cmem[i * 8 + j] = cursor_cmap[idx]; |
1007 | mask = mask << 1; | | 1012 | mask = mask << 1; |
1008 | } | | 1013 | } |
1009 | } | | 1014 | } |
1010 | /* just in case */ | | 1015 | /* just in case */ |
1011 | cpu_dcache_wb_range((vaddr_t)cmem, CURSOR_ARGB_SIZE); | | 1016 | cpu_dcache_wb_range((vaddr_t)cmem, CURSOR_ARGB_SIZE); |
1012 | rpi_fb_initcursor(pcursor, hot_x, hot_y); | | 1017 | rpi_fb_initcursor(pcursor, hot_x, hot_y); |
1013 | } | | 1018 | } |
1014 | if (pos) { | | 1019 | if (pos) { |
1015 | rpi_fb_movecursor(cursor_x, cursor_y, cursor_on); | | 1020 | rpi_fb_movecursor(cursor_x, cursor_y, cursor_on); |
1016 | } | | 1021 | } |
1017 | return 0; | | 1022 | return 0; |
1018 | } | | 1023 | } |
1019 | #endif | | 1024 | #endif |
1020 | | | 1025 | |
1021 | static int | | 1026 | static int |
1022 | rpi_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, lwp_t *l) | | 1027 | rpi_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, lwp_t *l) |
1023 | { | | 1028 | { |
1024 | | | 1029 | |
1025 | switch (cmd) { | | 1030 | switch (cmd) { |
1026 | case WSDISPLAYIO_SVIDEO: | | 1031 | case WSDISPLAYIO_SVIDEO: |
1027 | { | | 1032 | { |
1028 | int d = *(int *)data; | | 1033 | int d = *(int *)data; |
1029 | if (d == rpi_video_on) | | 1034 | if (d == rpi_video_on) |
1030 | return 0; | | 1035 | return 0; |
1031 | rpi_video_on = d; | | 1036 | rpi_video_on = d; |
1032 | rpi_fb_set_video(d); | | 1037 | rpi_fb_set_video(d); |
1033 | #if defined(RPI_HWCURSOR) | | 1038 | #if defined(RPI_HWCURSOR) |
1034 | rpi_fb_movecursor(cursor_x, cursor_y, | | 1039 | rpi_fb_movecursor(cursor_x, cursor_y, |
1035 | d ? cursor_on : 0); | | 1040 | d ? cursor_on : 0); |
1036 | #endif | | 1041 | #endif |
1037 | } | | 1042 | } |
1038 | return 0; | | 1043 | return 0; |
1039 | case WSDISPLAYIO_GVIDEO: | | 1044 | case WSDISPLAYIO_GVIDEO: |
1040 | *(int *)data = rpi_video_on; | | 1045 | *(int *)data = rpi_video_on; |
1041 | return 0; | | 1046 | return 0; |
1042 | #if defined(RPI_HWCURSOR) | | 1047 | #if defined(RPI_HWCURSOR) |
1043 | case WSDISPLAYIO_GCURPOS: | | 1048 | case WSDISPLAYIO_GCURPOS: |
1044 | { | | 1049 | { |
1045 | struct wsdisplay_curpos *cp = (void *)data; | | 1050 | struct wsdisplay_curpos *cp = (void *)data; |
1046 | | | 1051 | |
1047 | cp->x = cursor_x; | | 1052 | cp->x = cursor_x; |
1048 | cp->y = cursor_y; | | 1053 | cp->y = cursor_y; |
1049 | } | | 1054 | } |
1050 | return 0; | | 1055 | return 0; |
1051 | case WSDISPLAYIO_SCURPOS: | | 1056 | case WSDISPLAYIO_SCURPOS: |
1052 | { | | 1057 | { |
1053 | struct wsdisplay_curpos *cp = (void *)data; | | 1058 | struct wsdisplay_curpos *cp = (void *)data; |
1054 | | | 1059 | |
1055 | cursor_x = cp->x; | | 1060 | cursor_x = cp->x; |
1056 | cursor_y = cp->y; | | 1061 | cursor_y = cp->y; |
1057 | rpi_fb_movecursor(cursor_x, cursor_y, cursor_on); | | 1062 | rpi_fb_movecursor(cursor_x, cursor_y, cursor_on); |
1058 | } | | 1063 | } |
1059 | return 0; | | 1064 | return 0; |
1060 | case WSDISPLAYIO_GCURMAX: | | 1065 | case WSDISPLAYIO_GCURMAX: |
1061 | { | | 1066 | { |
1062 | struct wsdisplay_curpos *cp = (void *)data; | | 1067 | struct wsdisplay_curpos *cp = (void *)data; |
1063 | | | 1068 | |
1064 | cp->x = 64; | | 1069 | cp->x = 64; |
1065 | cp->y = 64; | | 1070 | cp->y = 64; |
1066 | } | | 1071 | } |
1067 | return 0; | | 1072 | return 0; |
1068 | case WSDISPLAYIO_SCURSOR: | | 1073 | case WSDISPLAYIO_SCURSOR: |
1069 | { | | 1074 | { |
1070 | struct wsdisplay_cursor *cursor = (void *)data; | | 1075 | struct wsdisplay_cursor *cursor = (void *)data; |
1071 | | | 1076 | |
1072 | return rpi_fb_do_cursor(cursor); | | 1077 | return rpi_fb_do_cursor(cursor); |
1073 | } | | 1078 | } |
1074 | #endif | | 1079 | #endif |
1075 | default: | | 1080 | default: |
1076 | return EPASSTHROUGH; | | 1081 | return EPASSTHROUGH; |
1077 | } | | 1082 | } |
1078 | } | | 1083 | } |
1079 | | | 1084 | |
1080 | #endif | | 1085 | #endif |
1081 | | | 1086 | |
1082 | static void | | 1087 | static void |
1083 | rpi_device_register(device_t dev, void *aux) | | 1088 | rpi_device_register(device_t dev, void *aux) |
1084 | { | | 1089 | { |
1085 | prop_dictionary_t dict = device_properties(dev); | | 1090 | prop_dictionary_t dict = device_properties(dev); |
1086 | | | 1091 | |
1087 | #if defined(BCM2836) | | 1092 | #if defined(BCM2836) |
1088 | if (device_is_a(dev, "armgtmr")) { | | 1093 | if (device_is_a(dev, "armgtmr")) { |
1089 | /* | | 1094 | /* |
1090 | * The frequency of the generic timer is the reference | | 1095 | * The frequency of the generic timer is the reference |
1091 | * frequency. | | 1096 | * frequency. |
1092 | */ | | 1097 | */ |
1093 | prop_dictionary_set_uint32(dict, "frequency", RPI_REF_FREQ); | | 1098 | prop_dictionary_set_uint32(dict, "frequency", RPI_REF_FREQ); |
1094 | return; | | 1099 | return; |
1095 | } | | 1100 | } |
1096 | #endif | | 1101 | #endif |
1097 | | | 1102 | |
1098 | if (device_is_a(dev, "bcmdmac") && | | 1103 | if (device_is_a(dev, "bcmdmac") && |
1099 | vcprop_tag_success_p(&vb.vbt_dmachan.tag)) { | | 1104 | vcprop_tag_success_p(&vb.vbt_dmachan.tag)) { |
1100 | prop_dictionary_set_uint32(dict, | | 1105 | prop_dictionary_set_uint32(dict, |
1101 | "chanmask", vb.vbt_dmachan.mask); | | 1106 | "chanmask", vb.vbt_dmachan.mask); |
1102 | } | | 1107 | } |
1103 | #if NSDHC > 0 | | 1108 | #if NSDHC > 0 |
1104 | if (device_is_a(dev, "sdhc") && | | 1109 | if (device_is_a(dev, "sdhc") && |
1105 | vcprop_tag_success_p(&vb.vbt_emmcclockrate.tag) && | | 1110 | vcprop_tag_success_p(&vb.vbt_emmcclockrate.tag) && |
1106 | vb.vbt_emmcclockrate.rate > 0) { | | 1111 | vb.vbt_emmcclockrate.rate > 0) { |
1107 | prop_dictionary_set_uint32(dict, | | 1112 | prop_dictionary_set_uint32(dict, |
1108 | "frequency", vb.vbt_emmcclockrate.rate); | | 1113 | "frequency", vb.vbt_emmcclockrate.rate); |
1109 | } | | 1114 | } |
1110 | if (booted_device == NULL && | | 1115 | if (booted_device == NULL && |
1111 | device_is_a(dev, "ld") && | | 1116 | device_is_a(dev, "ld") && |
1112 | device_is_a(device_parent(dev), "sdmmc")) { | | 1117 | device_is_a(device_parent(dev), "sdmmc")) { |
1113 | booted_partition = 0; | | 1118 | booted_partition = 0; |
1114 | booted_device = dev; | | 1119 | booted_device = dev; |
1115 | } | | 1120 | } |
1116 | #endif | | 1121 | #endif |
1117 | if (device_is_a(dev, "usmsc") && | | 1122 | if (device_is_a(dev, "usmsc") && |
1118 | vcprop_tag_success_p(&vb.vbt_macaddr.tag)) { | | 1123 | vcprop_tag_success_p(&vb.vbt_macaddr.tag)) { |
1119 | const uint8_t enaddr[ETHER_ADDR_LEN] = { | | 1124 | const uint8_t enaddr[ETHER_ADDR_LEN] = { |
1120 | (vb.vbt_macaddr.addr >> 0) & 0xff, | | 1125 | (vb.vbt_macaddr.addr >> 0) & 0xff, |
1121 | (vb.vbt_macaddr.addr >> 8) & 0xff, | | 1126 | (vb.vbt_macaddr.addr >> 8) & 0xff, |
1122 | (vb.vbt_macaddr.addr >> 16) & 0xff, | | 1127 | (vb.vbt_macaddr.addr >> 16) & 0xff, |
1123 | (vb.vbt_macaddr.addr >> 24) & 0xff, | | 1128 | (vb.vbt_macaddr.addr >> 24) & 0xff, |
1124 | (vb.vbt_macaddr.addr >> 32) & 0xff, | | 1129 | (vb.vbt_macaddr.addr >> 32) & 0xff, |
1125 | (vb.vbt_macaddr.addr >> 40) & 0xff | | 1130 | (vb.vbt_macaddr.addr >> 40) & 0xff |
1126 | }; | | 1131 | }; |
1127 | | | 1132 | |
1128 | prop_data_t pd = prop_data_create_data(enaddr, ETHER_ADDR_LEN); | | 1133 | prop_data_t pd = prop_data_create_data(enaddr, ETHER_ADDR_LEN); |
1129 | KASSERT(pd != NULL); | | 1134 | KASSERT(pd != NULL); |
1130 | if (prop_dictionary_set(device_properties(dev), "mac-address", | | 1135 | if (prop_dictionary_set(device_properties(dev), "mac-address", |
1131 | pd) == false) { | | 1136 | pd) == false) { |
1132 | aprint_error_dev(dev, | | 1137 | aprint_error_dev(dev, |
1133 | "WARNING: Unable to set mac-address property\n"); | | 1138 | "WARNING: Unable to set mac-address property\n"); |
1134 | } | | 1139 | } |
1135 | prop_object_release(pd); | | 1140 | prop_object_release(pd); |
1136 | } | | 1141 | } |
1137 | | | 1142 | |
1138 | #if NGENFB > 0 | | 1143 | #if NGENFB > 0 |
1139 | if (device_is_a(dev, "genfb")) { | | 1144 | if (device_is_a(dev, "genfb")) { |
1140 | char *ptr; | | 1145 | char *ptr; |
1141 | | | 1146 | |
1142 | bcmgenfb_set_console_dev(dev); | | 1147 | bcmgenfb_set_console_dev(dev); |
1143 | bcmgenfb_set_ioctl(&rpi_ioctl); | | 1148 | bcmgenfb_set_ioctl(&rpi_ioctl); |
1144 | #ifdef DDB | | 1149 | #ifdef DDB |
1145 | db_trap_callback = bcmgenfb_ddb_trap_callback; | | 1150 | db_trap_callback = bcmgenfb_ddb_trap_callback; |
1146 | #endif | | 1151 | #endif |
1147 | | | 1152 | |
1148 | if (rpi_fb_init(dict, aux) == false) | | 1153 | if (rpi_fb_init(dict, aux) == false) |
1149 | return; | | 1154 | return; |
1150 | if (get_bootconf_option(boot_args, "console", | | 1155 | if (get_bootconf_option(boot_args, "console", |
1151 | BOOTOPT_TYPE_STRING, &ptr) && strncmp(ptr, "fb", 2) == 0) { | | 1156 | BOOTOPT_TYPE_STRING, &ptr) && strncmp(ptr, "fb", 2) == 0) { |
1152 | prop_dictionary_set_bool(dict, "is_console", true); | | 1157 | prop_dictionary_set_bool(dict, "is_console", true); |
1153 | #if NUKBD > 0 | | 1158 | #if NUKBD > 0 |
1154 | /* allow ukbd to be the console keyboard */ | | 1159 | /* allow ukbd to be the console keyboard */ |
1155 | ukbd_cnattach(); | | 1160 | ukbd_cnattach(); |
1156 | #endif | | 1161 | #endif |
1157 | } else { | | 1162 | } else { |
1158 | prop_dictionary_set_bool(dict, "is_console", false); | | 1163 | prop_dictionary_set_bool(dict, "is_console", false); |
1159 | } | | 1164 | } |
1160 | } | | 1165 | } |
1161 | #endif | | 1166 | #endif |
1162 | } | | 1167 | } |
1163 | | | 1168 | |
1164 | SYSCTL_SETUP(sysctl_machdep_rpi, "sysctl machdep subtree setup (rpi)") | | 1169 | SYSCTL_SETUP(sysctl_machdep_rpi, "sysctl machdep subtree setup (rpi)") |
1165 | { | | 1170 | { |
1166 | sysctl_createv(clog, 0, NULL, NULL, | | 1171 | sysctl_createv(clog, 0, NULL, NULL, |
1167 | CTLFLAG_PERMANENT, CTLTYPE_NODE, "machdep", NULL, | | 1172 | CTLFLAG_PERMANENT, CTLTYPE_NODE, "machdep", NULL, |
1168 | NULL, 0, NULL, 0, CTL_MACHDEP, CTL_EOL); | | 1173 | NULL, 0, NULL, 0, CTL_MACHDEP, CTL_EOL); |
1169 | | | 1174 | |
1170 | sysctl_createv(clog, 0, NULL, NULL, | | 1175 | sysctl_createv(clog, 0, NULL, NULL, |
1171 | CTLFLAG_PERMANENT|CTLFLAG_READONLY, | | 1176 | CTLFLAG_PERMANENT|CTLFLAG_READONLY, |
1172 | CTLTYPE_INT, "firmware_revision", NULL, NULL, 0, | | 1177 | CTLTYPE_INT, "firmware_revision", NULL, NULL, 0, |
1173 | &vb.vbt_fwrev.rev, 0, CTL_MACHDEP, CTL_CREATE, CTL_EOL); | | 1178 | &vb.vbt_fwrev.rev, 0, CTL_MACHDEP, CTL_CREATE, CTL_EOL); |
1174 | | | 1179 | |
1175 | sysctl_createv(clog, 0, NULL, NULL, | | 1180 | sysctl_createv(clog, 0, NULL, NULL, |
1176 | CTLFLAG_PERMANENT|CTLFLAG_READONLY, | | 1181 | CTLFLAG_PERMANENT|CTLFLAG_READONLY, |
1177 | CTLTYPE_INT, "board_model", NULL, NULL, 0, | | 1182 | CTLTYPE_INT, "board_model", NULL, NULL, 0, |
1178 | &vb.vbt_boardmodel.model, 0, CTL_MACHDEP, CTL_CREATE, CTL_EOL); | | 1183 | &vb.vbt_boardmodel.model, 0, CTL_MACHDEP, CTL_CREATE, CTL_EOL); |
1179 | | | 1184 | |
1180 | sysctl_createv(clog, 0, NULL, NULL, | | 1185 | sysctl_createv(clog, 0, NULL, NULL, |
1181 | CTLFLAG_PERMANENT|CTLFLAG_READONLY, | | 1186 | CTLFLAG_PERMANENT|CTLFLAG_READONLY, |
1182 | CTLTYPE_INT, "board_revision", NULL, NULL, 0, | | 1187 | CTLTYPE_INT, "board_revision", NULL, NULL, 0, |
1183 | &vb.vbt_boardrev.rev, 0, CTL_MACHDEP, CTL_CREATE, CTL_EOL); | | 1188 | &vb.vbt_boardrev.rev, 0, CTL_MACHDEP, CTL_CREATE, CTL_EOL); |
1184 | | | 1189 | |
1185 | sysctl_createv(clog, 0, NULL, NULL, | | 1190 | sysctl_createv(clog, 0, NULL, NULL, |
1186 | CTLFLAG_PERMANENT|CTLFLAG_READONLY|CTLFLAG_HEX|CTLFLAG_PRIVATE, | | 1191 | CTLFLAG_PERMANENT|CTLFLAG_READONLY|CTLFLAG_HEX|CTLFLAG_PRIVATE, |
1187 | CTLTYPE_QUAD, "serial", NULL, NULL, 0, | | 1192 | CTLTYPE_QUAD, "serial", NULL, NULL, 0, |
1188 | &vb.vbt_serial.sn, 0, CTL_MACHDEP, CTL_CREATE, CTL_EOL); | | 1193 | &vb.vbt_serial.sn, 0, CTL_MACHDEP, CTL_CREATE, CTL_EOL); |
1189 | } | | 1194 | } |