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;
50 unsigned long const *value
;
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
= SecureDTLookupEntry(NULL
, "/cpus", &cpus
);
111 assert(err
== kSuccess
);
113 err
= SecureDTInitEntryIterator(cpus
, &iter
);
114 assert(err
== kSuccess
);
116 while (kSuccess
== SecureDTIterateEntries(&iter
, &cpu
)) {
117 if ((kSuccess
!= SecureDTGetProperty(cpu
, "state", (void const **)&value
, &size
)) ||
118 (strncmp((char const *)value
, "running", size
) != 0)) {
122 /* Find the time base frequency first. */
123 if (SecureDTGetProperty(cpu
, "timebase-frequency", (void const **)&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 const *)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 (SecureDTGetProperty(cpu
, "bus-frequency", (void const **)&value
, &size
) == kSuccess
) {
140 gPEClockFrequencyInfo
.bus_frequency_hz
= *(unsigned long long const *)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 (SecureDTGetProperty(cpu
, "memory-frequency", (void const **)&value
, &size
) == kSuccess
) {
157 gPEClockFrequencyInfo
.mem_frequency_hz
= *(unsigned long long const *)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 (SecureDTGetProperty(cpu
, "peripheral-frequency", (void const **)&value
, &size
) == kSuccess
) {
168 gPEClockFrequencyInfo
.prf_frequency_hz
= *(unsigned long long const *)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 (SecureDTGetProperty(cpu
, "fixed-frequency", (void const **)&value
, &size
) == kSuccess
) {
179 gPEClockFrequencyInfo
.fix_frequency_hz
= *(unsigned long long const *)value
;
181 gPEClockFrequencyInfo
.fix_frequency_hz
= *value
;
184 /* Find the cpu frequency last. */
185 if (SecureDTGetProperty(cpu
, "clock-frequency", (void const **)&value
, &size
) == kSuccess
) {
187 gPEClockFrequencyInfo
.cpu_frequency_hz
= *(unsigned long long const *)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 const *ranges_prop
;
242 if (SecureDTFindEntry("name", "arm-io", &entryP
) == kSuccess
) {
243 if (gPESoCDeviceType
== 0) {
244 SecureDTGetProperty(entryP
, "device_type", (void const **)&tmpStr
, &prop_size
);
245 strlcpy(gPESoCDeviceTypeBuffer
, tmpStr
, SOC_DEVICE_TYPE_BUFFER_SIZE
);
246 gPESoCDeviceType
= gPESoCDeviceTypeBuffer
;
248 SecureDTGetProperty(entryP
, "ranges", (void const **)&ranges_prop
, &prop_size
);
249 gPESoCBasePhys
= *(ranges_prop
+ 1);
251 return gPESoCBasePhys
;
256 extern void fleh_fiq_generic(void);
258 #if defined(ARM_BOARD_CLASS_T8002)
259 extern void fleh_fiq_t8002(void);
260 extern uint32_t t8002_get_decrementer(void);
261 extern void t8002_set_decrementer(uint32_t);
262 static struct tbd_ops t8002_funcs
= {&fleh_fiq_t8002
, &t8002_get_decrementer
, &t8002_set_decrementer
};
263 #endif /* defined(ARM_BOARD_CLASS_T8002) */
265 vm_offset_t gPicBase
;
266 vm_offset_t gTimerBase
;
267 vm_offset_t gSocPhys
;
269 #if DEVELOPMENT || DEBUG
270 // This block contains the panic trace implementation
272 // These variables are local to this file, and contain the panic trace configuration information
274 panic_trace_disabled
= 0,
277 panic_trace_alt_enabled
,
279 static panic_trace_t bootarg_panic_trace
;
281 static int bootarg_stop_clocks
;
283 // The command buffer contains the converted commands from the device tree for commanding cpu_halt, enable_trace, etc.
284 #define DEBUG_COMMAND_BUFFER_SIZE 256
285 typedef struct command_buffer_element
{
288 uint16_t destination_cpu_selector
;
291 } command_buffer_element_t
;
292 static command_buffer_element_t debug_command_buffer
[DEBUG_COMMAND_BUFFER_SIZE
]; // statically allocate to prevent needing alloc at runtime
293 static uint32_t next_command_buffer_entry
= 0; // index of next unused slot in debug_command_buffer
295 #define CPU_SELECTOR_SHIFT (16)
296 #define CPU_SELECTOR_MASK (0xFFFF << CPU_SELECTOR_SHIFT)
297 #define REGISTER_OFFSET_MASK ((1 << CPU_SELECTOR_SHIFT) - 1)
298 #define REGISTER_OFFSET(register_prop) (register_prop & REGISTER_OFFSET_MASK)
299 #define CPU_SELECTOR(register_offset) ((register_offset & CPU_SELECTOR_MASK) >> CPU_SELECTOR_SHIFT) // Upper 16bits holds the cpu selector
300 #define MAX_WINDOW_SIZE 0xFFFF
301 #define PE_ISSPACE(c) (c == ' ' || c == '\t' || c == '\n' || c == '\12')
302 #define DELAY_SHIFT (32)
303 #define DELAY_MASK (0xFFFFULL << DELAY_SHIFT)
304 #define DELAY_US(register_offset) ((register_offset & DELAY_MASK) >> DELAY_SHIFT)
305 #define REGISTER_32BIT_MASK (1ULL << 63)
311 * 0x0003 - cpu 0 and 1
312 * since it's 16bits, we can have up to 16 cpus
314 #define ALL_CPUS 0x0000
315 #define IS_CPU_SELECTED(cpu_number, cpu_selector) (cpu_selector == ALL_CPUS || (cpu_selector & (1<<cpu_number) ) != 0 )
317 #define RESET_VIRTUAL_ADDRESS_WINDOW 0xFFFFFFFF
319 // Pointers into debug_command_buffer for each operation. Assumes runtime will init them to zero.
320 static command_buffer_element_t
*cpu_halt
;
321 static command_buffer_element_t
*enable_trace
;
322 static command_buffer_element_t
*enable_alt_trace
;
323 static command_buffer_element_t
*trace_halt
;
324 static command_buffer_element_t
*enable_stop_clocks
;
325 static command_buffer_element_t
*stop_clocks
;
327 // Record which CPU is currently running one of our debug commands, so we can trap panic reentrancy to PE_arm_debug_panic_hook.
328 static int running_debug_command_on_cpu_number
= -1;
331 pe_init_debug_command(DTEntry entryP
, command_buffer_element_t
**command_buffer
, const char* entry_name
)
333 uintptr_t const *reg_prop
;
334 uint32_t prop_size
, reg_window_size
= 0, command_starting_index
;
335 uintptr_t debug_reg_window
= 0;
337 if (command_buffer
== 0) {
341 if (SecureDTGetProperty(entryP
, entry_name
, (void const **)®_prop
, &prop_size
) != kSuccess
) {
342 panic("pe_init_debug_command: failed to read property %s\n", entry_name
);
345 // make sure command will fit
346 if (next_command_buffer_entry
+ prop_size
/ sizeof(uintptr_t) > DEBUG_COMMAND_BUFFER_SIZE
- 1) {
347 panic("pe_init_debug_command: property %s is %u bytes, command buffer only has %lu bytes remaining\n",
348 entry_name
, prop_size
, ((DEBUG_COMMAND_BUFFER_SIZE
- 1) - next_command_buffer_entry
) * sizeof(uintptr_t));
351 // Hold the pointer in a temp variable and later assign it to command buffer, in case we panic while half-initialized
352 command_starting_index
= next_command_buffer_entry
;
354 // convert to real virt addresses and stuff commands into debug_command_buffer
355 for (; prop_size
; reg_prop
+= 2, prop_size
-= 2 * sizeof(uintptr_t)) {
356 if (*reg_prop
== RESET_VIRTUAL_ADDRESS_WINDOW
) {
357 debug_reg_window
= 0; // Create a new window
358 } else if (debug_reg_window
== 0) {
359 // create a window from virtual address to the specified physical address
360 reg_window_size
= ((uint32_t)*(reg_prop
+ 1));
361 if (reg_window_size
> MAX_WINDOW_SIZE
) {
362 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
);
364 debug_reg_window
= ml_io_map(gSocPhys
+ *reg_prop
, reg_window_size
);
365 // for debug -- kprintf("pe_init_debug_command: %s registers @ 0x%08lX for 0x%08lX\n", entry_name, debug_reg_window, *(reg_prop + 1) );
367 if ((REGISTER_OFFSET(*reg_prop
) + sizeof(uintptr_t)) >= reg_window_size
) {
368 panic("pe_init_debug_command: Command Offset is %lx, exceeds allocated size of %x\n", REGISTER_OFFSET(*reg_prop
), reg_window_size
);
370 debug_command_buffer
[next_command_buffer_entry
].address
= debug_reg_window
+ REGISTER_OFFSET(*reg_prop
);
371 debug_command_buffer
[next_command_buffer_entry
].destination_cpu_selector
= (uint16_t)CPU_SELECTOR(*reg_prop
);
372 #if defined(__arm64__)
373 debug_command_buffer
[next_command_buffer_entry
].delay_us
= DELAY_US(*reg_prop
);
374 debug_command_buffer
[next_command_buffer_entry
].is_32bit
= ((*reg_prop
& REGISTER_32BIT_MASK
) != 0);
376 debug_command_buffer
[next_command_buffer_entry
].delay_us
= 0;
377 debug_command_buffer
[next_command_buffer_entry
].is_32bit
= false;
379 debug_command_buffer
[next_command_buffer_entry
++].value
= *(reg_prop
+ 1);
383 // null terminate the address field of the command to end it
384 debug_command_buffer
[next_command_buffer_entry
++].address
= 0;
386 // save pointer into table for this command
387 *command_buffer
= &debug_command_buffer
[command_starting_index
];
391 pe_run_debug_command(command_buffer_element_t
*command_buffer
)
393 // 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
394 simple_lock(&panic_hook_lock
, LCK_GRP_NULL
);
396 running_debug_command_on_cpu_number
= cpu_number();
398 while (command_buffer
&& command_buffer
->address
) {
399 if (IS_CPU_SELECTED(running_debug_command_on_cpu_number
, command_buffer
->destination_cpu_selector
)) {
400 if (command_buffer
->is_32bit
) {
401 *((volatile uint32_t*)(command_buffer
->address
)) = (uint32_t)(command_buffer
->value
);
403 *((volatile uintptr_t*)(command_buffer
->address
)) = command_buffer
->value
; // register = value;
405 if (command_buffer
->delay_us
!= 0) {
407 nanoseconds_to_absolutetime(command_buffer
->delay_us
* NSEC_PER_USEC
, &deadline
);
408 deadline
+= ml_get_timebase();
409 while (ml_get_timebase() < deadline
) {
410 os_compiler_barrier();
417 running_debug_command_on_cpu_number
= -1;
418 simple_unlock(&panic_hook_lock
);
423 PE_arm_debug_enable_trace(void)
425 switch (bootarg_panic_trace
) {
426 case panic_trace_enabled
:
427 pe_run_debug_command(enable_trace
);
430 case panic_trace_alt_enabled
:
431 pe_run_debug_command(enable_alt_trace
);
440 PE_arm_panic_hook(const char *str __unused
)
442 (void)str
; // not used
443 if (bootarg_stop_clocks
!= 0) {
444 pe_run_debug_command(stop_clocks
);
446 // if panic trace is enabled
447 if (bootarg_panic_trace
!= 0) {
448 if (running_debug_command_on_cpu_number
== cpu_number()) {
449 // This is going to end badly if we don't trap, since we'd be panic-ing during our own code
450 kprintf("## Panic Trace code caused the panic ##\n");
451 return; // allow the normal panic operation to occur.
454 // Stop tracing to freeze the buffer and return to normal panic processing.
455 pe_run_debug_command(trace_halt
);
459 void (*PE_arm_debug_panic_hook
)(const char *str
) = PE_arm_panic_hook
;
464 if (bootarg_stop_clocks
!= 0) {
465 pe_run_debug_command(enable_stop_clocks
);
471 void(*const PE_arm_debug_panic_hook
)(const char *str
) = NULL
;
478 #endif // DEVELOPMENT || DEBUG
481 PE_panic_hook(const char *str __unused
)
483 if (PE_arm_debug_panic_hook
!= NULL
) {
484 PE_arm_debug_panic_hook(str
);
489 pe_arm_init_debug(void *args
)
492 uintptr_t const *reg_prop
;
496 kprintf("pe_arm_init_debug: failed to initialize gSocPhys == 0\n");
500 if (SecureDTFindEntry("device_type", "cpu-debug-interface", &entryP
) == kSuccess
) {
502 if (SecureDTGetProperty(entryP
, "reg", (void const **)®_prop
, &prop_size
) == kSuccess
) {
503 ml_init_arm_debug_interface(args
, ml_io_map(gSocPhys
+ *reg_prop
, *(reg_prop
+ 1)));
505 #if DEVELOPMENT || DEBUG
506 // When args != NULL, this means we're being called from arm_init on the boot CPU.
507 // This controls one-time initialization of the Panic Trace infrastructure
509 simple_lock_init(&panic_hook_lock
, 0); //assuming single threaded mode
511 // Panic_halt is deprecated. Please use panic_trace istead.
512 unsigned int temp_bootarg_panic_trace
;
513 if (PE_parse_boot_argn("panic_trace", &temp_bootarg_panic_trace
, sizeof(temp_bootarg_panic_trace
)) ||
514 PE_parse_boot_argn("panic_halt", &temp_bootarg_panic_trace
, sizeof(temp_bootarg_panic_trace
))) {
515 kprintf("pe_arm_init_debug: panic_trace=%d\n", temp_bootarg_panic_trace
);
517 // Prepare debug command buffers.
518 pe_init_debug_command(entryP
, &cpu_halt
, "cpu_halt");
519 pe_init_debug_command(entryP
, &enable_trace
, "enable_trace");
520 pe_init_debug_command(entryP
, &enable_alt_trace
, "enable_alt_trace");
521 pe_init_debug_command(entryP
, &trace_halt
, "trace_halt");
523 // now that init's are done, enable the panic halt capture (allows pe_init_debug_command to panic normally if necessary)
524 bootarg_panic_trace
= temp_bootarg_panic_trace
;
526 // start tracing now if enabled
527 PE_arm_debug_enable_trace();
529 unsigned int temp_bootarg_stop_clocks
;
530 if (PE_parse_boot_argn("stop_clocks", &temp_bootarg_stop_clocks
, sizeof(temp_bootarg_stop_clocks
))) {
531 pe_init_debug_command(entryP
, &enable_stop_clocks
, "enable_stop_clocks");
532 pe_init_debug_command(entryP
, &stop_clocks
, "stop_clocks");
533 bootarg_stop_clocks
= temp_bootarg_stop_clocks
;
538 kprintf("pe_arm_init_debug: failed to find cpu-debug-interface\n");
543 pe_arm_map_interrupt_controller(void)
546 uintptr_t const *reg_prop
;
548 vm_offset_t soc_phys
= 0;
550 gSocPhys
= pe_arm_get_soc_base_phys();
553 kprintf("pe_arm_map_interrupt_controller: soc_phys: 0x%lx\n", (unsigned long)soc_phys
);
558 if (SecureDTFindEntry("interrupt-controller", "master", &entryP
) == kSuccess
) {
559 kprintf("pe_arm_map_interrupt_controller: found interrupt-controller\n");
560 SecureDTGetProperty(entryP
, "reg", (void const **)®_prop
, &prop_size
);
561 gPicBase
= ml_io_map(soc_phys
+ *reg_prop
, *(reg_prop
+ 1));
562 kprintf("pe_arm_map_interrupt_controller: gPicBase: 0x%lx\n", (unsigned long)gPicBase
);
565 kprintf("pe_arm_map_interrupt_controller: failed to find the interrupt-controller.\n");
569 if (SecureDTFindEntry("device_type", "timer", &entryP
) == kSuccess
) {
570 kprintf("pe_arm_map_interrupt_controller: found timer\n");
571 SecureDTGetProperty(entryP
, "reg", (void const **)®_prop
, &prop_size
);
572 gTimerBase
= ml_io_map(soc_phys
+ *reg_prop
, *(reg_prop
+ 1));
573 kprintf("pe_arm_map_interrupt_controller: gTimerBase: 0x%lx\n", (unsigned long)gTimerBase
);
575 if (gTimerBase
== 0) {
576 kprintf("pe_arm_map_interrupt_controller: failed to find the timer.\n");
584 pe_arm_init_interrupts(void *args
)
586 kprintf("pe_arm_init_interrupts: args: %p\n", args
);
588 /* Set up mappings for interrupt controller and possibly timers (if they haven't been set up already) */
590 if (!pe_arm_map_interrupt_controller()) {
595 return pe_arm_init_timer(args
);
599 pe_arm_init_timer(void *args
)
601 vm_offset_t pic_base
= 0;
602 vm_offset_t timer_base
= 0;
603 vm_offset_t soc_phys
;
604 vm_offset_t eoi_addr
= 0;
605 uint32_t eoi_value
= 0;
606 struct tbd_ops generic_funcs
= {&fleh_fiq_generic
, NULL
, NULL
};
607 struct tbd_ops empty_funcs __unused
= {NULL
, NULL
, NULL
};
608 tbd_ops_t tbd_funcs
= &generic_funcs
;
610 /* The SoC headers expect to use pic_base, timer_base, etc... */
612 timer_base
= gTimerBase
;
615 #if defined(ARM_BOARD_CLASS_T8002)
616 if (!strcmp(gPESoCDeviceType
, "t8002-io") ||
617 !strcmp(gPESoCDeviceType
, "t8004-io")) {
618 /* Enable the Decrementer */
619 aic_write32(kAICTmrCnt
, 0x7FFFFFFF);
620 aic_write32(kAICTmrCfg
, kAICTmrCfgEn
);
621 aic_write32(kAICTmrIntStat
, kAICTmrIntStatPct
);
622 #ifdef ARM_BOARD_WFE_TIMEOUT_NS
623 // Enable the WFE Timer
624 rPMGR_EVENT_TMR_PERIOD
= ((uint64_t)(ARM_BOARD_WFE_TIMEOUT_NS
) *gPEClockFrequencyInfo
.timebase_frequency_hz
) / NSEC_PER_SEC
;
625 rPMGR_EVENT_TMR
= rPMGR_EVENT_TMR_PERIOD
;
626 rPMGR_EVENT_TMR_CTL
= PMGR_EVENT_TMR_CTL_EN
;
627 #endif /* ARM_BOARD_WFE_TIMEOUT_NS */
630 eoi_value
= kAICTmrIntStatPct
;
631 tbd_funcs
= &t8002_funcs
;
634 #if defined(__arm64__)
635 tbd_funcs
= &empty_funcs
;
641 ml_init_timebase(args
, tbd_funcs
, eoi_addr
, eoi_value
);