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) */
320 #if defined(ARM_BOARD_CLASS_BCM2837)
321 static struct tbd_ops bcm2837_funcs
= {NULL
, NULL
, NULL
};
322 #endif /* defined(ARM_BOARD_CLASS_BCM2837) */
324 vm_offset_t gPicBase
;
325 vm_offset_t gTimerBase
;
326 vm_offset_t gSocPhys
;
328 #if DEVELOPMENT || DEBUG
329 // This block contains the panic trace implementation
331 // These variables are local to this file, and contain the panic trace configuration information
333 panic_trace_disabled
= 0,
336 panic_trace_alt_enabled
,
338 static panic_trace_t bootarg_panic_trace
;
340 static int bootarg_stop_clocks
;
342 // The command buffer contains the converted commands from the device tree for commanding cpu_halt, enable_trace, etc.
343 #define DEBUG_COMMAND_BUFFER_SIZE 256
344 typedef struct command_buffer_element
{
347 uint16_t destination_cpu_selector
;
350 } command_buffer_element_t
;
351 static command_buffer_element_t debug_command_buffer
[DEBUG_COMMAND_BUFFER_SIZE
]; // statically allocate to prevent needing alloc at runtime
352 static uint32_t next_command_buffer_entry
= 0; // index of next unused slot in debug_command_buffer
354 #define CPU_SELECTOR_SHIFT (16)
355 #define CPU_SELECTOR_MASK (0xFFFF << CPU_SELECTOR_SHIFT)
356 #define REGISTER_OFFSET_MASK ((1 << CPU_SELECTOR_SHIFT) - 1)
357 #define REGISTER_OFFSET(register_prop) (register_prop & REGISTER_OFFSET_MASK)
358 #define CPU_SELECTOR(register_offset) ((register_offset & CPU_SELECTOR_MASK) >> CPU_SELECTOR_SHIFT) // Upper 16bits holds the cpu selector
359 #define MAX_WINDOW_SIZE 0xFFFF
360 #define PE_ISSPACE(c) (c == ' ' || c == '\t' || c == '\n' || c == '\12')
361 #define DELAY_SHIFT (32)
362 #define DELAY_MASK (0xFFFFULL << DELAY_SHIFT)
363 #define DELAY_US(register_offset) ((register_offset & DELAY_MASK) >> DELAY_SHIFT)
364 #define REGISTER_32BIT_MASK (1ULL << 63)
370 * 0x0003 - cpu 0 and 1
371 * since it's 16bits, we can have up to 16 cpus
373 #define ALL_CPUS 0x0000
374 #define IS_CPU_SELECTED(cpu_number, cpu_selector) (cpu_selector == ALL_CPUS || (cpu_selector & (1<<cpu_number) ) != 0 )
376 #define RESET_VIRTUAL_ADDRESS_WINDOW 0xFFFFFFFF
378 // Pointers into debug_command_buffer for each operation. Assumes runtime will init them to zero.
379 static command_buffer_element_t
*cpu_halt
;
380 static command_buffer_element_t
*enable_trace
;
381 static command_buffer_element_t
*enable_alt_trace
;
382 static command_buffer_element_t
*trace_halt
;
383 static command_buffer_element_t
*enable_stop_clocks
;
384 static command_buffer_element_t
*stop_clocks
;
386 // Record which CPU is currently running one of our debug commands, so we can trap panic reentrancy to PE_arm_debug_panic_hook.
387 static int running_debug_command_on_cpu_number
= -1;
390 pe_init_debug_command(DTEntry entryP
, command_buffer_element_t
**command_buffer
, const char* entry_name
)
393 uint32_t prop_size
, reg_window_size
= 0, command_starting_index
;
394 uintptr_t debug_reg_window
= 0;
396 if (command_buffer
== 0) {
400 if (DTGetProperty(entryP
, entry_name
, (void **)®_prop
, &prop_size
) != kSuccess
) {
401 panic("pe_init_debug_command: failed to read property %s\n", entry_name
);
404 // make sure command will fit
405 if (next_command_buffer_entry
+ prop_size
/ sizeof(uintptr_t) > DEBUG_COMMAND_BUFFER_SIZE
- 1) {
406 panic("pe_init_debug_command: property %s is %u bytes, command buffer only has %lu bytes remaining\n",
407 entry_name
, prop_size
, ((DEBUG_COMMAND_BUFFER_SIZE
- 1) - next_command_buffer_entry
) * sizeof(uintptr_t));
410 // Hold the pointer in a temp variable and later assign it to command buffer, in case we panic while half-initialized
411 command_starting_index
= next_command_buffer_entry
;
413 // convert to real virt addresses and stuff commands into debug_command_buffer
414 for (; prop_size
; reg_prop
+= 2, prop_size
-= 2 * sizeof(uintptr_t)) {
415 if (*reg_prop
== RESET_VIRTUAL_ADDRESS_WINDOW
) {
416 debug_reg_window
= 0; // Create a new window
417 } else if (debug_reg_window
== 0) {
418 // create a window from virtual address to the specified physical address
419 reg_window_size
= ((uint32_t)*(reg_prop
+ 1));
420 if (reg_window_size
> MAX_WINDOW_SIZE
) {
421 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
);
423 debug_reg_window
= ml_io_map(gSocPhys
+ *reg_prop
, reg_window_size
);
424 // for debug -- kprintf("pe_init_debug_command: %s registers @ 0x%08lX for 0x%08lX\n", entry_name, debug_reg_window, *(reg_prop + 1) );
426 if ((REGISTER_OFFSET(*reg_prop
) + sizeof(uintptr_t)) >= reg_window_size
) {
427 panic("pe_init_debug_command: Command Offset is %lx, exceeds allocated size of %x\n", REGISTER_OFFSET(*reg_prop
), reg_window_size
);
429 debug_command_buffer
[next_command_buffer_entry
].address
= debug_reg_window
+ REGISTER_OFFSET(*reg_prop
);
430 debug_command_buffer
[next_command_buffer_entry
].destination_cpu_selector
= CPU_SELECTOR(*reg_prop
);
431 #if defined(__arm64__)
432 debug_command_buffer
[next_command_buffer_entry
].delay_us
= DELAY_US(*reg_prop
);
433 debug_command_buffer
[next_command_buffer_entry
].is_32bit
= ((*reg_prop
& REGISTER_32BIT_MASK
) != 0);
435 debug_command_buffer
[next_command_buffer_entry
].delay_us
= 0;
436 debug_command_buffer
[next_command_buffer_entry
].is_32bit
= false;
438 debug_command_buffer
[next_command_buffer_entry
++].value
= *(reg_prop
+ 1);
442 // null terminate the address field of the command to end it
443 debug_command_buffer
[next_command_buffer_entry
++].address
= 0;
445 // save pointer into table for this command
446 *command_buffer
= &debug_command_buffer
[command_starting_index
];
450 pe_run_debug_command(command_buffer_element_t
*command_buffer
)
452 // 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
453 simple_lock(&panic_hook_lock
, LCK_GRP_NULL
);
455 running_debug_command_on_cpu_number
= cpu_number();
457 while (command_buffer
&& command_buffer
->address
) {
458 if (IS_CPU_SELECTED(running_debug_command_on_cpu_number
, command_buffer
->destination_cpu_selector
)) {
459 if (command_buffer
->is_32bit
) {
460 *((volatile uint32_t*)(command_buffer
->address
)) = (uint32_t)(command_buffer
->value
);
462 *((volatile uintptr_t*)(command_buffer
->address
)) = command_buffer
->value
; // register = value;
464 if (command_buffer
->delay_us
!= 0) {
466 nanoseconds_to_absolutetime(command_buffer
->delay_us
* NSEC_PER_USEC
, &deadline
);
467 deadline
+= ml_get_timebase();
468 while (ml_get_timebase() < deadline
) {
476 running_debug_command_on_cpu_number
= -1;
477 simple_unlock(&panic_hook_lock
);
482 PE_arm_debug_enable_trace(void)
484 switch (bootarg_panic_trace
) {
485 case panic_trace_enabled
:
486 pe_run_debug_command(enable_trace
);
489 case panic_trace_alt_enabled
:
490 pe_run_debug_command(enable_alt_trace
);
499 PE_arm_panic_hook(const char *str __unused
)
501 (void)str
; // not used
502 if (bootarg_stop_clocks
!= 0) {
503 pe_run_debug_command(stop_clocks
);
505 // if panic trace is enabled
506 if (bootarg_panic_trace
!= 0) {
507 if (running_debug_command_on_cpu_number
== cpu_number()) {
508 // This is going to end badly if we don't trap, since we'd be panic-ing during our own code
509 kprintf("## Panic Trace code caused the panic ##\n");
510 return; // allow the normal panic operation to occur.
513 // Stop tracing to freeze the buffer and return to normal panic processing.
514 pe_run_debug_command(trace_halt
);
518 void (*PE_arm_debug_panic_hook
)(const char *str
) = PE_arm_panic_hook
;
523 if (bootarg_stop_clocks
!= 0) {
524 pe_run_debug_command(enable_stop_clocks
);
530 void(*const PE_arm_debug_panic_hook
)(const char *str
) = NULL
;
537 #endif // DEVELOPMENT || DEBUG
540 PE_panic_hook(const char *str __unused
)
542 if (PE_arm_debug_panic_hook
!= NULL
) {
543 PE_arm_debug_panic_hook(str
);
548 pe_arm_init_debug(void *args
)
555 kprintf("pe_arm_init_debug: failed to initialize gSocPhys == 0\n");
559 if (DTFindEntry("device_type", "cpu-debug-interface", &entryP
) == kSuccess
) {
561 if (DTGetProperty(entryP
, "reg", (void **)®_prop
, &prop_size
) == kSuccess
) {
562 ml_init_arm_debug_interface(args
, ml_io_map(gSocPhys
+ *reg_prop
, *(reg_prop
+ 1)));
564 #if DEVELOPMENT || DEBUG
565 // When args != NULL, this means we're being called from arm_init on the boot CPU.
566 // This controls one-time initialization of the Panic Trace infrastructure
568 simple_lock_init(&panic_hook_lock
, 0); //assuming single threaded mode
570 // Panic_halt is deprecated. Please use panic_trace istead.
571 unsigned int temp_bootarg_panic_trace
;
572 if (PE_parse_boot_argn("panic_trace", &temp_bootarg_panic_trace
, sizeof(temp_bootarg_panic_trace
)) ||
573 PE_parse_boot_argn("panic_halt", &temp_bootarg_panic_trace
, sizeof(temp_bootarg_panic_trace
))) {
574 kprintf("pe_arm_init_debug: panic_trace=%d\n", temp_bootarg_panic_trace
);
576 // Prepare debug command buffers.
577 pe_init_debug_command(entryP
, &cpu_halt
, "cpu_halt");
578 pe_init_debug_command(entryP
, &enable_trace
, "enable_trace");
579 pe_init_debug_command(entryP
, &enable_alt_trace
, "enable_alt_trace");
580 pe_init_debug_command(entryP
, &trace_halt
, "trace_halt");
582 // now that init's are done, enable the panic halt capture (allows pe_init_debug_command to panic normally if necessary)
583 bootarg_panic_trace
= temp_bootarg_panic_trace
;
585 // start tracing now if enabled
586 PE_arm_debug_enable_trace();
588 unsigned int temp_bootarg_stop_clocks
;
589 if (PE_parse_boot_argn("stop_clocks", &temp_bootarg_stop_clocks
, sizeof(temp_bootarg_stop_clocks
))) {
590 pe_init_debug_command(entryP
, &enable_stop_clocks
, "enable_stop_clocks");
591 pe_init_debug_command(entryP
, &stop_clocks
, "stop_clocks");
592 bootarg_stop_clocks
= temp_bootarg_stop_clocks
;
597 kprintf("pe_arm_init_debug: failed to find cpu-debug-interface\n");
602 pe_arm_map_interrupt_controller(void)
607 vm_offset_t soc_phys
= 0;
609 gSocPhys
= pe_arm_get_soc_base_phys();
612 kprintf("pe_arm_map_interrupt_controller: soc_phys: 0x%lx\n", (unsigned long)soc_phys
);
617 if (DTFindEntry("interrupt-controller", "master", &entryP
) == kSuccess
) {
618 kprintf("pe_arm_map_interrupt_controller: found interrupt-controller\n");
619 DTGetProperty(entryP
, "reg", (void **)®_prop
, &prop_size
);
620 gPicBase
= ml_io_map(soc_phys
+ *reg_prop
, *(reg_prop
+ 1));
621 kprintf("pe_arm_map_interrupt_controller: gPicBase: 0x%lx\n", (unsigned long)gPicBase
);
624 kprintf("pe_arm_map_interrupt_controller: failed to find the interrupt-controller.\n");
628 if (DTFindEntry("device_type", "timer", &entryP
) == kSuccess
) {
629 kprintf("pe_arm_map_interrupt_controller: found timer\n");
630 DTGetProperty(entryP
, "reg", (void **)®_prop
, &prop_size
);
631 gTimerBase
= ml_io_map(soc_phys
+ *reg_prop
, *(reg_prop
+ 1));
632 kprintf("pe_arm_map_interrupt_controller: gTimerBase: 0x%lx\n", (unsigned long)gTimerBase
);
634 if (gTimerBase
== 0) {
635 kprintf("pe_arm_map_interrupt_controller: failed to find the timer.\n");
643 pe_arm_init_interrupts(void *args
)
645 kprintf("pe_arm_init_interrupts: args: %p\n", args
);
647 /* Set up mappings for interrupt controller and possibly timers (if they haven't been set up already) */
649 if (!pe_arm_map_interrupt_controller()) {
654 return pe_arm_init_timer(args
);
658 pe_arm_init_timer(void *args
)
660 vm_offset_t pic_base
= 0;
661 vm_offset_t timer_base
= 0;
662 vm_offset_t soc_phys
;
663 vm_offset_t eoi_addr
= 0;
664 uint32_t eoi_value
= 0;
665 struct tbd_ops generic_funcs
= {&fleh_fiq_generic
, NULL
, NULL
};
666 tbd_ops_t tbd_funcs
= &generic_funcs
;
668 /* The SoC headers expect to use pic_base, timer_base, etc... */
670 timer_base
= gTimerBase
;
673 #if defined(ARM_BOARD_CLASS_T7000)
674 if (!strcmp(gPESoCDeviceType
, "t7000-io") ||
675 !strcmp(gPESoCDeviceType
, "t7001-io")) {
676 tbd_funcs
= &t7000_funcs
;
679 #if defined(ARM_BOARD_CLASS_S7002)
680 if (!strcmp(gPESoCDeviceType
, "s7002-io")) {
681 #ifdef ARM_BOARD_WFE_TIMEOUT_NS
682 // Enable the WFE Timer
683 rPMGR_EVENT_TMR_PERIOD
= ((uint64_t)(ARM_BOARD_WFE_TIMEOUT_NS
) *gPEClockFrequencyInfo
.timebase_frequency_hz
) / NSEC_PER_SEC
;
684 rPMGR_EVENT_TMR
= rPMGR_EVENT_TMR_PERIOD
;
685 rPMGR_EVENT_TMR_CTL
= PMGR_EVENT_TMR_CTL_EN
;
686 #endif /* ARM_BOARD_WFE_TIMEOUT_NS */
688 rPMGR_INTERVAL_TMR
= 0x7FFFFFFF;
689 rPMGR_INTERVAL_TMR_CTL
= PMGR_INTERVAL_TMR_CTL_EN
| PMGR_INTERVAL_TMR_CTL_CLR_INT
;
691 eoi_addr
= timer_base
;
692 eoi_value
= PMGR_INTERVAL_TMR_CTL_EN
| PMGR_INTERVAL_TMR_CTL_CLR_INT
;
693 tbd_funcs
= &s7002_funcs
;
696 #if defined(ARM_BOARD_CLASS_S8000)
697 if (!strcmp(gPESoCDeviceType
, "s8000-io") ||
698 !strcmp(gPESoCDeviceType
, "s8001-io")) {
699 tbd_funcs
= &s8000_funcs
;
702 #if defined(ARM_BOARD_CLASS_T8002)
703 if (!strcmp(gPESoCDeviceType
, "t8002-io") ||
704 !strcmp(gPESoCDeviceType
, "t8004-io")) {
705 /* Enable the Decrementer */
706 aic_write32(kAICTmrCnt
, 0x7FFFFFFF);
707 aic_write32(kAICTmrCfg
, kAICTmrCfgEn
);
708 aic_write32(kAICTmrIntStat
, kAICTmrIntStatPct
);
709 #ifdef ARM_BOARD_WFE_TIMEOUT_NS
710 // Enable the WFE Timer
711 rPMGR_EVENT_TMR_PERIOD
= ((uint64_t)(ARM_BOARD_WFE_TIMEOUT_NS
) *gPEClockFrequencyInfo
.timebase_frequency_hz
) / NSEC_PER_SEC
;
712 rPMGR_EVENT_TMR
= rPMGR_EVENT_TMR_PERIOD
;
713 rPMGR_EVENT_TMR_CTL
= PMGR_EVENT_TMR_CTL_EN
;
714 #endif /* ARM_BOARD_WFE_TIMEOUT_NS */
717 eoi_value
= kAICTmrIntStatPct
;
718 tbd_funcs
= &t8002_funcs
;
721 #if defined(ARM_BOARD_CLASS_T8010)
722 if (!strcmp(gPESoCDeviceType
, "t8010-io")) {
723 tbd_funcs
= &t8010_funcs
;
726 #if defined(ARM_BOARD_CLASS_T8011)
727 if (!strcmp(gPESoCDeviceType
, "t8011-io")) {
728 tbd_funcs
= &t8011_funcs
;
731 #if defined(ARM_BOARD_CLASS_T8015)
732 if (!strcmp(gPESoCDeviceType
, "t8015-io")) {
733 tbd_funcs
= &t8015_funcs
;
736 #if defined(ARM_BOARD_CLASS_BCM2837)
737 if (!strcmp(gPESoCDeviceType
, "bcm2837-io")) {
738 tbd_funcs
= &bcm2837_funcs
;
744 ml_init_timebase(args
, tbd_funcs
, eoi_addr
, eoi_value
);