2 * Copyright (c) 2007-2019 Apple Inc. All rights reserved.
3 * Copyright (c) 2000-2006 Apple Computer, Inc. All rights reserved.
5 #include <pexpert/pexpert.h>
6 #include <pexpert/boot.h>
7 #include <pexpert/protos.h>
8 #include <pexpert/device_tree.h>
11 #include <pexpert/arm/board_config.h>
12 #elif defined(__arm64__)
13 #include <pexpert/arm64/board_config.h>
16 #include <kern/clock.h>
17 #include <machine/machine_routines.h>
18 #if DEVELOPMENT || DEBUG
19 #include <kern/simple_lock.h>
20 #include <kern/cpu_number.h>
22 /* Local declarations */
23 void pe_identify_machine(boot_args
* bootArgs
);
25 /* External declarations */
26 extern void clean_mmu_dcache(void);
28 static char *gPESoCDeviceType
;
29 static char gPESoCDeviceTypeBuffer
[SOC_DEVICE_TYPE_BUFFER_SIZE
];
30 static vm_offset_t gPESoCBasePhys
;
32 static uint32_t gTCFG0Value
;
34 static uint32_t pe_arm_init_timer(void *args
);
36 #if DEVELOPMENT || DEBUG
37 decl_simple_lock_data(, panic_hook_lock
);
40 * pe_identify_machine:
42 * Sets up platform parameters. Returns: nothing
45 pe_identify_machine(boot_args
* bootArgs
)
47 OpaqueDTEntryIterator iter
;
49 uint32_t mclk
= 0, hclk
= 0, pclk
= 0, tclk
= 0, use_dt
= 0;
56 if (pe_arm_get_soc_base_phys() == 0) {
60 /* Clear the gPEClockFrequencyInfo struct */
61 bzero((void *)&gPEClockFrequencyInfo
, sizeof(clock_frequency_info_t
));
63 if (!strcmp(gPESoCDeviceType
, "s3c2410-io")) {
67 tclk
= (1 << (23 + 2)) / 10;
70 gTCFG0Value
= tclk
- 1;
72 tclk
= pclk
/ (4 * tclk
); /* Calculate the "actual"
73 * Timer0 frequency in fixed
76 mclk
= (mclk
>> 17) * (125 * 125);
77 hclk
= (hclk
>> 17) * (125 * 125);
78 pclk
= (pclk
>> 17) * (125 * 125);
79 tclk
= (((((tclk
* 125) + 2) >> 2) * 125) + (1 << 14)) >> 15;
80 } else if (!strcmp(gPESoCDeviceType
, "integratorcp-io")) {
85 } else if (!strcmp(gPESoCDeviceType
, "olocreek-io")) {
90 } else if (!strcmp(gPESoCDeviceType
, "omap3430sdp-io")) {
95 } else if (!strcmp(gPESoCDeviceType
, "s5i3000-io")) {
99 tclk
= 100000; /* timer is at 100khz */
105 /* Start with default values. */
106 gPEClockFrequencyInfo
.timebase_frequency_hz
= 24000000;
107 gPEClockFrequencyInfo
.bus_clock_rate_hz
= 100000000;
108 gPEClockFrequencyInfo
.cpu_clock_rate_hz
= 400000000;
110 err
= DTLookupEntry(NULL
, "/cpus", &cpus
);
111 assert(err
== kSuccess
);
113 err
= DTInitEntryIterator(cpus
, &iter
);
114 assert(err
== kSuccess
);
116 while (kSuccess
== DTIterateEntries(&iter
, &cpu
)) {
117 if ((kSuccess
!= DTGetProperty(cpu
, "state", (void **)&value
, &size
)) ||
118 (strncmp((char*)value
, "running", size
) != 0)) {
122 /* Find the time base frequency first. */
123 if (DTGetProperty(cpu
, "timebase-frequency", (void **)&value
, &size
) == kSuccess
) {
125 * timebase_frequency_hz is only 32 bits, and
126 * the device tree should never provide 64
127 * bits so this if should never be taken.
130 gPEClockFrequencyInfo
.timebase_frequency_hz
= *(unsigned long long *)value
;
132 gPEClockFrequencyInfo
.timebase_frequency_hz
= *value
;
135 gPEClockFrequencyInfo
.dec_clock_rate_hz
= gPEClockFrequencyInfo
.timebase_frequency_hz
;
137 /* Find the bus frequency next. */
138 if (DTGetProperty(cpu
, "bus-frequency", (void **)&value
, &size
) == kSuccess
) {
140 gPEClockFrequencyInfo
.bus_frequency_hz
= *(unsigned long long *)value
;
142 gPEClockFrequencyInfo
.bus_frequency_hz
= *value
;
145 gPEClockFrequencyInfo
.bus_frequency_min_hz
= gPEClockFrequencyInfo
.bus_frequency_hz
;
146 gPEClockFrequencyInfo
.bus_frequency_max_hz
= gPEClockFrequencyInfo
.bus_frequency_hz
;
148 if (gPEClockFrequencyInfo
.bus_frequency_hz
< 0x100000000ULL
) {
149 gPEClockFrequencyInfo
.bus_clock_rate_hz
= gPEClockFrequencyInfo
.bus_frequency_hz
;
151 gPEClockFrequencyInfo
.bus_clock_rate_hz
= 0xFFFFFFFF;
154 /* Find the memory frequency next. */
155 if (DTGetProperty(cpu
, "memory-frequency", (void **)&value
, &size
) == kSuccess
) {
157 gPEClockFrequencyInfo
.mem_frequency_hz
= *(unsigned long long *)value
;
159 gPEClockFrequencyInfo
.mem_frequency_hz
= *value
;
162 gPEClockFrequencyInfo
.mem_frequency_min_hz
= gPEClockFrequencyInfo
.mem_frequency_hz
;
163 gPEClockFrequencyInfo
.mem_frequency_max_hz
= gPEClockFrequencyInfo
.mem_frequency_hz
;
165 /* Find the peripheral frequency next. */
166 if (DTGetProperty(cpu
, "peripheral-frequency", (void **)&value
, &size
) == kSuccess
) {
168 gPEClockFrequencyInfo
.prf_frequency_hz
= *(unsigned long long *)value
;
170 gPEClockFrequencyInfo
.prf_frequency_hz
= *value
;
173 gPEClockFrequencyInfo
.prf_frequency_min_hz
= gPEClockFrequencyInfo
.prf_frequency_hz
;
174 gPEClockFrequencyInfo
.prf_frequency_max_hz
= gPEClockFrequencyInfo
.prf_frequency_hz
;
176 /* Find the fixed frequency next. */
177 if (DTGetProperty(cpu
, "fixed-frequency", (void **)&value
, &size
) == kSuccess
) {
179 gPEClockFrequencyInfo
.fix_frequency_hz
= *(unsigned long long *)value
;
181 gPEClockFrequencyInfo
.fix_frequency_hz
= *value
;
184 /* Find the cpu frequency last. */
185 if (DTGetProperty(cpu
, "clock-frequency", (void **)&value
, &size
) == kSuccess
) {
187 gPEClockFrequencyInfo
.cpu_frequency_hz
= *(unsigned long long *)value
;
189 gPEClockFrequencyInfo
.cpu_frequency_hz
= *value
;
192 gPEClockFrequencyInfo
.cpu_frequency_min_hz
= gPEClockFrequencyInfo
.cpu_frequency_hz
;
193 gPEClockFrequencyInfo
.cpu_frequency_max_hz
= gPEClockFrequencyInfo
.cpu_frequency_hz
;
195 if (gPEClockFrequencyInfo
.cpu_frequency_hz
< 0x100000000ULL
) {
196 gPEClockFrequencyInfo
.cpu_clock_rate_hz
= gPEClockFrequencyInfo
.cpu_frequency_hz
;
198 gPEClockFrequencyInfo
.cpu_clock_rate_hz
= 0xFFFFFFFF;
202 /* Use the canned values. */
203 gPEClockFrequencyInfo
.timebase_frequency_hz
= tclk
;
204 gPEClockFrequencyInfo
.fix_frequency_hz
= tclk
;
205 gPEClockFrequencyInfo
.bus_frequency_hz
= hclk
;
206 gPEClockFrequencyInfo
.cpu_frequency_hz
= mclk
;
207 gPEClockFrequencyInfo
.prf_frequency_hz
= pclk
;
209 gPEClockFrequencyInfo
.bus_frequency_min_hz
= gPEClockFrequencyInfo
.bus_frequency_hz
;
210 gPEClockFrequencyInfo
.bus_frequency_max_hz
= gPEClockFrequencyInfo
.bus_frequency_hz
;
211 gPEClockFrequencyInfo
.cpu_frequency_min_hz
= gPEClockFrequencyInfo
.cpu_frequency_hz
;
212 gPEClockFrequencyInfo
.cpu_frequency_max_hz
= gPEClockFrequencyInfo
.cpu_frequency_hz
;
213 gPEClockFrequencyInfo
.prf_frequency_min_hz
= gPEClockFrequencyInfo
.prf_frequency_hz
;
214 gPEClockFrequencyInfo
.prf_frequency_max_hz
= gPEClockFrequencyInfo
.prf_frequency_hz
;
216 gPEClockFrequencyInfo
.dec_clock_rate_hz
= gPEClockFrequencyInfo
.timebase_frequency_hz
;
217 gPEClockFrequencyInfo
.bus_clock_rate_hz
= gPEClockFrequencyInfo
.bus_frequency_hz
;
218 gPEClockFrequencyInfo
.cpu_clock_rate_hz
= gPEClockFrequencyInfo
.cpu_frequency_hz
;
221 /* Set the num / den pairs form the hz values. */
222 gPEClockFrequencyInfo
.bus_clock_rate_num
= gPEClockFrequencyInfo
.bus_clock_rate_hz
;
223 gPEClockFrequencyInfo
.bus_clock_rate_den
= 1;
225 gPEClockFrequencyInfo
.bus_to_cpu_rate_num
=
226 (2 * gPEClockFrequencyInfo
.cpu_clock_rate_hz
) / gPEClockFrequencyInfo
.bus_clock_rate_hz
;
227 gPEClockFrequencyInfo
.bus_to_cpu_rate_den
= 2;
229 gPEClockFrequencyInfo
.bus_to_dec_rate_num
= 1;
230 gPEClockFrequencyInfo
.bus_to_dec_rate_den
=
231 gPEClockFrequencyInfo
.bus_clock_rate_hz
/ gPEClockFrequencyInfo
.dec_clock_rate_hz
;
235 pe_arm_get_soc_base_phys(void)
238 uintptr_t *ranges_prop
;
242 if (DTFindEntry("name", "arm-io", &entryP
) == kSuccess
) {
243 if (gPESoCDeviceType
== 0) {
244 DTGetProperty(entryP
, "device_type", (void **)&tmpStr
, &prop_size
);
245 strlcpy(gPESoCDeviceTypeBuffer
, tmpStr
, SOC_DEVICE_TYPE_BUFFER_SIZE
);
246 gPESoCDeviceType
= gPESoCDeviceTypeBuffer
;
248 DTGetProperty(entryP
, "ranges", (void **)&ranges_prop
, &prop_size
);
249 gPESoCBasePhys
= *(ranges_prop
+ 1);
251 return gPESoCBasePhys
;
257 pe_arm_get_soc_revision(void)
263 if ((DTFindEntry("name", "arm-io", &entryP
) == kSuccess
)
264 && (DTGetProperty(entryP
, "chip-revision", (void **)&value
, &size
) == kSuccess
)) {
266 return (uint32_t)*(unsigned long long *)value
;
275 extern void fleh_fiq_generic(void);
278 #if defined(ARM_BOARD_CLASS_T7000)
279 static struct tbd_ops t7000_funcs
= {NULL
, NULL
, NULL
};
280 #endif /* defined(ARM_BOARD_CLASS_T7000) */
282 #if defined(ARM_BOARD_CLASS_S7002)
283 extern void fleh_fiq_s7002(void);
284 extern uint32_t s7002_get_decrementer(void);
285 extern void s7002_set_decrementer(uint32_t);
286 static struct tbd_ops s7002_funcs
= {&fleh_fiq_s7002
, &s7002_get_decrementer
, &s7002_set_decrementer
};
287 #endif /* defined(ARM_BOARD_CLASS_S7002) */
289 #if defined(ARM_BOARD_CLASS_S8000)
290 static struct tbd_ops s8000_funcs
= {NULL
, NULL
, NULL
};
291 #endif /* defined(ARM_BOARD_CLASS_T7000) */
293 #if defined(ARM_BOARD_CLASS_T8002)
294 extern void fleh_fiq_t8002(void);
295 extern uint32_t t8002_get_decrementer(void);
296 extern void t8002_set_decrementer(uint32_t);
297 static struct tbd_ops t8002_funcs
= {&fleh_fiq_t8002
, &t8002_get_decrementer
, &t8002_set_decrementer
};
298 #endif /* defined(ARM_BOARD_CLASS_T8002) */
300 #if defined(ARM_BOARD_CLASS_T8010)
301 static struct tbd_ops t8010_funcs
= {NULL
, NULL
, NULL
};
302 #endif /* defined(ARM_BOARD_CLASS_T8010) */
304 #if defined(ARM_BOARD_CLASS_T8011)
305 static struct tbd_ops t8011_funcs
= {NULL
, NULL
, NULL
};
306 #endif /* defined(ARM_BOARD_CLASS_T8011) */
308 #if defined(ARM_BOARD_CLASS_T8015)
309 static struct tbd_ops t8015_funcs
= {NULL
, NULL
, NULL
};
310 #endif /* defined(ARM_BOARD_CLASS_T8015) */
312 #if defined(ARM_BOARD_CLASS_T8020)
313 static struct tbd_ops t8020_funcs
= {NULL
, NULL
, NULL
};
314 #endif /* defined(ARM_BOARD_CLASS_T8020) */
316 #if defined(ARM_BOARD_CLASS_T8006)
317 static struct tbd_ops t8006_funcs
= {NULL
, NULL
, NULL
};
318 #endif /* defined(ARM_BOARD_CLASS_T8006) */
320 #if defined(ARM_BOARD_CLASS_T8027)
321 static struct tbd_ops t8027_funcs
= {NULL
, NULL
, NULL
};
322 #endif /* defined(ARM_BOARD_CLASS_T8027) */
324 #if defined(ARM_BOARD_CLASS_T8028)
325 static struct tbd_ops t8028_funcs
= {NULL
, NULL
, NULL
};
326 #endif /* defined(ARM_BOARD_CLASS_T8028) */
328 #if defined(ARM_BOARD_CLASS_T8030)
329 static struct tbd_ops t8030_funcs
= {NULL
, NULL
, NULL
};
330 #endif /* defined(ARM_BOARD_CLASS_T8030) */
335 #if defined(ARM_BOARD_CLASS_BCM2837)
336 static struct tbd_ops bcm2837_funcs
= {NULL
, NULL
, NULL
};
337 #endif /* defined(ARM_BOARD_CLASS_BCM2837) */
339 vm_offset_t gPicBase
;
340 vm_offset_t gTimerBase
;
341 vm_offset_t gSocPhys
;
343 #if DEVELOPMENT || DEBUG
344 // This block contains the panic trace implementation
346 // These variables are local to this file, and contain the panic trace configuration information
348 panic_trace_disabled
= 0,
351 panic_trace_alt_enabled
,
353 static panic_trace_t bootarg_panic_trace
;
355 static int bootarg_stop_clocks
;
357 // The command buffer contains the converted commands from the device tree for commanding cpu_halt, enable_trace, etc.
358 #define DEBUG_COMMAND_BUFFER_SIZE 256
359 typedef struct command_buffer_element
{
362 uint16_t destination_cpu_selector
;
365 } command_buffer_element_t
;
366 static command_buffer_element_t debug_command_buffer
[DEBUG_COMMAND_BUFFER_SIZE
]; // statically allocate to prevent needing alloc at runtime
367 static uint32_t next_command_buffer_entry
= 0; // index of next unused slot in debug_command_buffer
369 #define CPU_SELECTOR_SHIFT (16)
370 #define CPU_SELECTOR_MASK (0xFFFF << CPU_SELECTOR_SHIFT)
371 #define REGISTER_OFFSET_MASK ((1 << CPU_SELECTOR_SHIFT) - 1)
372 #define REGISTER_OFFSET(register_prop) (register_prop & REGISTER_OFFSET_MASK)
373 #define CPU_SELECTOR(register_offset) ((register_offset & CPU_SELECTOR_MASK) >> CPU_SELECTOR_SHIFT) // Upper 16bits holds the cpu selector
374 #define MAX_WINDOW_SIZE 0xFFFF
375 #define PE_ISSPACE(c) (c == ' ' || c == '\t' || c == '\n' || c == '\12')
376 #define DELAY_SHIFT (32)
377 #define DELAY_MASK (0xFFFFULL << DELAY_SHIFT)
378 #define DELAY_US(register_offset) ((register_offset & DELAY_MASK) >> DELAY_SHIFT)
379 #define REGISTER_32BIT_MASK (1ULL << 63)
385 * 0x0003 - cpu 0 and 1
386 * since it's 16bits, we can have up to 16 cpus
388 #define ALL_CPUS 0x0000
389 #define IS_CPU_SELECTED(cpu_number, cpu_selector) (cpu_selector == ALL_CPUS || (cpu_selector & (1<<cpu_number) ) != 0 )
391 #define RESET_VIRTUAL_ADDRESS_WINDOW 0xFFFFFFFF
393 // Pointers into debug_command_buffer for each operation. Assumes runtime will init them to zero.
394 static command_buffer_element_t
*cpu_halt
;
395 static command_buffer_element_t
*enable_trace
;
396 static command_buffer_element_t
*enable_alt_trace
;
397 static command_buffer_element_t
*trace_halt
;
398 static command_buffer_element_t
*enable_stop_clocks
;
399 static command_buffer_element_t
*stop_clocks
;
401 // Record which CPU is currently running one of our debug commands, so we can trap panic reentrancy to PE_arm_debug_panic_hook.
402 static int running_debug_command_on_cpu_number
= -1;
405 pe_init_debug_command(DTEntry entryP
, command_buffer_element_t
**command_buffer
, const char* entry_name
)
408 uint32_t prop_size
, reg_window_size
= 0, command_starting_index
;
409 uintptr_t debug_reg_window
= 0;
411 if (command_buffer
== 0) {
415 if (DTGetProperty(entryP
, entry_name
, (void **)®_prop
, &prop_size
) != kSuccess
) {
416 panic("pe_init_debug_command: failed to read property %s\n", entry_name
);
419 // make sure command will fit
420 if (next_command_buffer_entry
+ prop_size
/ sizeof(uintptr_t) > DEBUG_COMMAND_BUFFER_SIZE
- 1) {
421 panic("pe_init_debug_command: property %s is %u bytes, command buffer only has %lu bytes remaining\n",
422 entry_name
, prop_size
, ((DEBUG_COMMAND_BUFFER_SIZE
- 1) - next_command_buffer_entry
) * sizeof(uintptr_t));
425 // Hold the pointer in a temp variable and later assign it to command buffer, in case we panic while half-initialized
426 command_starting_index
= next_command_buffer_entry
;
428 // convert to real virt addresses and stuff commands into debug_command_buffer
429 for (; prop_size
; reg_prop
+= 2, prop_size
-= 2 * sizeof(uintptr_t)) {
430 if (*reg_prop
== RESET_VIRTUAL_ADDRESS_WINDOW
) {
431 debug_reg_window
= 0; // Create a new window
432 } else if (debug_reg_window
== 0) {
433 // create a window from virtual address to the specified physical address
434 reg_window_size
= ((uint32_t)*(reg_prop
+ 1));
435 if (reg_window_size
> MAX_WINDOW_SIZE
) {
436 panic("pe_init_debug_command: Command page size is %0x, exceeds the Maximum allowed page size 0f 0%x\n", reg_window_size
, MAX_WINDOW_SIZE
);
438 debug_reg_window
= ml_io_map(gSocPhys
+ *reg_prop
, reg_window_size
);
439 // for debug -- kprintf("pe_init_debug_command: %s registers @ 0x%08lX for 0x%08lX\n", entry_name, debug_reg_window, *(reg_prop + 1) );
441 if ((REGISTER_OFFSET(*reg_prop
) + sizeof(uintptr_t)) >= reg_window_size
) {
442 panic("pe_init_debug_command: Command Offset is %lx, exceeds allocated size of %x\n", REGISTER_OFFSET(*reg_prop
), reg_window_size
);
444 debug_command_buffer
[next_command_buffer_entry
].address
= debug_reg_window
+ REGISTER_OFFSET(*reg_prop
);
445 debug_command_buffer
[next_command_buffer_entry
].destination_cpu_selector
= CPU_SELECTOR(*reg_prop
);
446 #if defined(__arm64__)
447 debug_command_buffer
[next_command_buffer_entry
].delay_us
= DELAY_US(*reg_prop
);
448 debug_command_buffer
[next_command_buffer_entry
].is_32bit
= ((*reg_prop
& REGISTER_32BIT_MASK
) != 0);
450 debug_command_buffer
[next_command_buffer_entry
].delay_us
= 0;
451 debug_command_buffer
[next_command_buffer_entry
].is_32bit
= false;
453 debug_command_buffer
[next_command_buffer_entry
++].value
= *(reg_prop
+ 1);
457 // null terminate the address field of the command to end it
458 debug_command_buffer
[next_command_buffer_entry
++].address
= 0;
460 // save pointer into table for this command
461 *command_buffer
= &debug_command_buffer
[command_starting_index
];
465 pe_run_debug_command(command_buffer_element_t
*command_buffer
)
467 // When both the CPUs panic, one will get stuck on the lock and the other CPU will be halted when the first executes the debug command
468 simple_lock(&panic_hook_lock
, LCK_GRP_NULL
);
470 running_debug_command_on_cpu_number
= cpu_number();
472 while (command_buffer
&& command_buffer
->address
) {
473 if (IS_CPU_SELECTED(running_debug_command_on_cpu_number
, command_buffer
->destination_cpu_selector
)) {
474 if (command_buffer
->is_32bit
) {
475 *((volatile uint32_t*)(command_buffer
->address
)) = (uint32_t)(command_buffer
->value
);
477 *((volatile uintptr_t*)(command_buffer
->address
)) = command_buffer
->value
; // register = value;
479 if (command_buffer
->delay_us
!= 0) {
481 nanoseconds_to_absolutetime(command_buffer
->delay_us
* NSEC_PER_USEC
, &deadline
);
482 deadline
+= ml_get_timebase();
483 while (ml_get_timebase() < deadline
) {
491 running_debug_command_on_cpu_number
= -1;
492 simple_unlock(&panic_hook_lock
);
497 PE_arm_debug_enable_trace(void)
499 switch (bootarg_panic_trace
) {
500 case panic_trace_enabled
:
501 pe_run_debug_command(enable_trace
);
504 case panic_trace_alt_enabled
:
505 pe_run_debug_command(enable_alt_trace
);
514 PE_arm_panic_hook(const char *str __unused
)
516 (void)str
; // not used
517 if (bootarg_stop_clocks
!= 0) {
518 pe_run_debug_command(stop_clocks
);
520 // if panic trace is enabled
521 if (bootarg_panic_trace
!= 0) {
522 if (running_debug_command_on_cpu_number
== cpu_number()) {
523 // This is going to end badly if we don't trap, since we'd be panic-ing during our own code
524 kprintf("## Panic Trace code caused the panic ##\n");
525 return; // allow the normal panic operation to occur.
528 // Stop tracing to freeze the buffer and return to normal panic processing.
529 pe_run_debug_command(trace_halt
);
533 void (*PE_arm_debug_panic_hook
)(const char *str
) = PE_arm_panic_hook
;
538 if (bootarg_stop_clocks
!= 0) {
539 pe_run_debug_command(enable_stop_clocks
);
545 void(*const PE_arm_debug_panic_hook
)(const char *str
) = NULL
;
552 #endif // DEVELOPMENT || DEBUG
555 PE_panic_hook(const char *str __unused
)
557 if (PE_arm_debug_panic_hook
!= NULL
) {
558 PE_arm_debug_panic_hook(str
);
563 pe_arm_init_debug(void *args
)
570 kprintf("pe_arm_init_debug: failed to initialize gSocPhys == 0\n");
574 if (DTFindEntry("device_type", "cpu-debug-interface", &entryP
) == kSuccess
) {
576 if (DTGetProperty(entryP
, "reg", (void **)®_prop
, &prop_size
) == kSuccess
) {
577 ml_init_arm_debug_interface(args
, ml_io_map(gSocPhys
+ *reg_prop
, *(reg_prop
+ 1)));
579 #if DEVELOPMENT || DEBUG
580 // When args != NULL, this means we're being called from arm_init on the boot CPU.
581 // This controls one-time initialization of the Panic Trace infrastructure
583 simple_lock_init(&panic_hook_lock
, 0); //assuming single threaded mode
585 // Panic_halt is deprecated. Please use panic_trace istead.
586 unsigned int temp_bootarg_panic_trace
;
587 if (PE_parse_boot_argn("panic_trace", &temp_bootarg_panic_trace
, sizeof(temp_bootarg_panic_trace
)) ||
588 PE_parse_boot_argn("panic_halt", &temp_bootarg_panic_trace
, sizeof(temp_bootarg_panic_trace
))) {
589 kprintf("pe_arm_init_debug: panic_trace=%d\n", temp_bootarg_panic_trace
);
591 // Prepare debug command buffers.
592 pe_init_debug_command(entryP
, &cpu_halt
, "cpu_halt");
593 pe_init_debug_command(entryP
, &enable_trace
, "enable_trace");
594 pe_init_debug_command(entryP
, &enable_alt_trace
, "enable_alt_trace");
595 pe_init_debug_command(entryP
, &trace_halt
, "trace_halt");
597 // now that init's are done, enable the panic halt capture (allows pe_init_debug_command to panic normally if necessary)
598 bootarg_panic_trace
= temp_bootarg_panic_trace
;
600 // start tracing now if enabled
601 PE_arm_debug_enable_trace();
603 unsigned int temp_bootarg_stop_clocks
;
604 if (PE_parse_boot_argn("stop_clocks", &temp_bootarg_stop_clocks
, sizeof(temp_bootarg_stop_clocks
))) {
605 pe_init_debug_command(entryP
, &enable_stop_clocks
, "enable_stop_clocks");
606 pe_init_debug_command(entryP
, &stop_clocks
, "stop_clocks");
607 bootarg_stop_clocks
= temp_bootarg_stop_clocks
;
612 kprintf("pe_arm_init_debug: failed to find cpu-debug-interface\n");
617 pe_arm_map_interrupt_controller(void)
622 vm_offset_t soc_phys
= 0;
624 gSocPhys
= pe_arm_get_soc_base_phys();
627 kprintf("pe_arm_map_interrupt_controller: soc_phys: 0x%lx\n", (unsigned long)soc_phys
);
632 if (DTFindEntry("interrupt-controller", "master", &entryP
) == kSuccess
) {
633 kprintf("pe_arm_map_interrupt_controller: found interrupt-controller\n");
634 DTGetProperty(entryP
, "reg", (void **)®_prop
, &prop_size
);
635 gPicBase
= ml_io_map(soc_phys
+ *reg_prop
, *(reg_prop
+ 1));
636 kprintf("pe_arm_map_interrupt_controller: gPicBase: 0x%lx\n", (unsigned long)gPicBase
);
639 kprintf("pe_arm_map_interrupt_controller: failed to find the interrupt-controller.\n");
643 if (DTFindEntry("device_type", "timer", &entryP
) == kSuccess
) {
644 kprintf("pe_arm_map_interrupt_controller: found timer\n");
645 DTGetProperty(entryP
, "reg", (void **)®_prop
, &prop_size
);
646 gTimerBase
= ml_io_map(soc_phys
+ *reg_prop
, *(reg_prop
+ 1));
647 kprintf("pe_arm_map_interrupt_controller: gTimerBase: 0x%lx\n", (unsigned long)gTimerBase
);
649 if (gTimerBase
== 0) {
650 kprintf("pe_arm_map_interrupt_controller: failed to find the timer.\n");
658 pe_arm_init_interrupts(void *args
)
660 kprintf("pe_arm_init_interrupts: args: %p\n", args
);
662 /* Set up mappings for interrupt controller and possibly timers (if they haven't been set up already) */
664 if (!pe_arm_map_interrupt_controller()) {
669 return pe_arm_init_timer(args
);
673 pe_arm_init_timer(void *args
)
675 vm_offset_t pic_base
= 0;
676 vm_offset_t timer_base
= 0;
677 vm_offset_t soc_phys
;
678 vm_offset_t eoi_addr
= 0;
679 uint32_t eoi_value
= 0;
680 struct tbd_ops generic_funcs
= {&fleh_fiq_generic
, NULL
, NULL
};
681 tbd_ops_t tbd_funcs
= &generic_funcs
;
683 /* The SoC headers expect to use pic_base, timer_base, etc... */
685 timer_base
= gTimerBase
;
688 #if defined(ARM_BOARD_CLASS_T7000)
689 if (!strcmp(gPESoCDeviceType
, "t7000-io") ||
690 !strcmp(gPESoCDeviceType
, "t7001-io")) {
691 tbd_funcs
= &t7000_funcs
;
694 #if defined(ARM_BOARD_CLASS_S7002)
695 if (!strcmp(gPESoCDeviceType
, "s7002-io")) {
696 #ifdef ARM_BOARD_WFE_TIMEOUT_NS
697 // Enable the WFE Timer
698 rPMGR_EVENT_TMR_PERIOD
= ((uint64_t)(ARM_BOARD_WFE_TIMEOUT_NS
) *gPEClockFrequencyInfo
.timebase_frequency_hz
) / NSEC_PER_SEC
;
699 rPMGR_EVENT_TMR
= rPMGR_EVENT_TMR_PERIOD
;
700 rPMGR_EVENT_TMR_CTL
= PMGR_EVENT_TMR_CTL_EN
;
701 #endif /* ARM_BOARD_WFE_TIMEOUT_NS */
703 rPMGR_INTERVAL_TMR
= 0x7FFFFFFF;
704 rPMGR_INTERVAL_TMR_CTL
= PMGR_INTERVAL_TMR_CTL_EN
| PMGR_INTERVAL_TMR_CTL_CLR_INT
;
706 eoi_addr
= timer_base
;
707 eoi_value
= PMGR_INTERVAL_TMR_CTL_EN
| PMGR_INTERVAL_TMR_CTL_CLR_INT
;
708 tbd_funcs
= &s7002_funcs
;
711 #if defined(ARM_BOARD_CLASS_S8000)
712 if (!strcmp(gPESoCDeviceType
, "s8000-io") ||
713 !strcmp(gPESoCDeviceType
, "s8001-io")) {
714 tbd_funcs
= &s8000_funcs
;
717 #if defined(ARM_BOARD_CLASS_T8002)
718 if (!strcmp(gPESoCDeviceType
, "t8002-io") ||
719 !strcmp(gPESoCDeviceType
, "t8004-io")) {
720 /* Enable the Decrementer */
721 aic_write32(kAICTmrCnt
, 0x7FFFFFFF);
722 aic_write32(kAICTmrCfg
, kAICTmrCfgEn
);
723 aic_write32(kAICTmrIntStat
, kAICTmrIntStatPct
);
724 #ifdef ARM_BOARD_WFE_TIMEOUT_NS
725 // Enable the WFE Timer
726 rPMGR_EVENT_TMR_PERIOD
= ((uint64_t)(ARM_BOARD_WFE_TIMEOUT_NS
) *gPEClockFrequencyInfo
.timebase_frequency_hz
) / NSEC_PER_SEC
;
727 rPMGR_EVENT_TMR
= rPMGR_EVENT_TMR_PERIOD
;
728 rPMGR_EVENT_TMR_CTL
= PMGR_EVENT_TMR_CTL_EN
;
729 #endif /* ARM_BOARD_WFE_TIMEOUT_NS */
732 eoi_value
= kAICTmrIntStatPct
;
733 tbd_funcs
= &t8002_funcs
;
736 #if defined(ARM_BOARD_CLASS_T8010)
737 if (!strcmp(gPESoCDeviceType
, "t8010-io")) {
738 tbd_funcs
= &t8010_funcs
;
741 #if defined(ARM_BOARD_CLASS_T8011)
742 if (!strcmp(gPESoCDeviceType
, "t8011-io")) {
743 tbd_funcs
= &t8011_funcs
;
746 #if defined(ARM_BOARD_CLASS_T8015)
747 if (!strcmp(gPESoCDeviceType
, "t8015-io")) {
748 tbd_funcs
= &t8015_funcs
;
751 #if defined(ARM_BOARD_CLASS_T8020)
752 if (!strcmp(gPESoCDeviceType
, "t8020-io")) {
753 tbd_funcs
= &t8020_funcs
;
756 #if defined(ARM_BOARD_CLASS_T8006)
757 if (!strcmp(gPESoCDeviceType
, "t8006-io")) {
758 tbd_funcs
= &t8006_funcs
;
761 #if defined(ARM_BOARD_CLASS_T8027)
762 if (!strcmp(gPESoCDeviceType
, "t8027-io")) {
763 tbd_funcs
= &t8027_funcs
;
766 #if defined(ARM_BOARD_CLASS_T8028)
767 if (!strcmp(gPESoCDeviceType
, "t8028-io")) {
768 tbd_funcs
= &t8028_funcs
;
771 #if defined(ARM_BOARD_CLASS_T8030)
772 if (!strcmp(gPESoCDeviceType
, "t8030-io")) {
773 tbd_funcs
= &t8030_funcs
;
776 #if defined(ARM_BOARD_CLASS_BCM2837)
777 if (!strcmp(gPESoCDeviceType
, "bcm2837-io")) {
778 tbd_funcs
= &bcm2837_funcs
;
784 ml_init_timebase(args
, tbd_funcs
, eoi_addr
, eoi_value
);