2 * Copyright (c) 2007-2017 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 <machine/machine_routines.h>
17 #if DEVELOPMENT || DEBUG
18 #include <kern/simple_lock.h>
19 #include <kern/cpu_number.h>
21 /* Local declarations */
22 void pe_identify_machine(boot_args
* bootArgs
);
24 /* External declarations */
25 extern void clean_mmu_dcache(void);
27 static char *gPESoCDeviceType
;
28 static char gPESoCDeviceTypeBuffer
[SOC_DEVICE_TYPE_BUFFER_SIZE
];
29 static vm_offset_t gPESoCBasePhys
;
31 static uint32_t gTCFG0Value
;
33 static uint32_t pe_arm_init_timer(void *args
);
35 #if DEVELOPMENT || DEBUG
36 decl_simple_lock_data(, panic_trace_lock
;)
39 * pe_identify_machine:
41 * Sets up platform parameters. Returns: nothing
44 pe_identify_machine(boot_args
* bootArgs
)
46 OpaqueDTEntryIterator iter
;
48 uint32_t mclk
= 0, hclk
= 0, pclk
= 0, tclk
= 0, use_dt
= 0;
55 if (pe_arm_get_soc_base_phys() == 0)
58 /* Clear the gPEClockFrequencyInfo struct */
59 bzero((void *)&gPEClockFrequencyInfo
, sizeof(clock_frequency_info_t
));
61 if (!strcmp(gPESoCDeviceType
, "s3c2410-io")) {
65 tclk
= (1 << (23 + 2)) / 10;
68 gTCFG0Value
= tclk
- 1;
70 tclk
= pclk
/ (4 * tclk
); /* Calculate the "actual"
71 * Timer0 frequency in fixed
74 mclk
= (mclk
>> 17) * (125 * 125);
75 hclk
= (hclk
>> 17) * (125 * 125);
76 pclk
= (pclk
>> 17) * (125 * 125);
77 tclk
= (((((tclk
* 125) + 2) >> 2) * 125) + (1 << 14)) >> 15;
79 } else if (!strcmp(gPESoCDeviceType
, "integratorcp-io")) {
84 } else if (!strcmp(gPESoCDeviceType
, "olocreek-io")) {
89 } else if (!strcmp(gPESoCDeviceType
, "omap3430sdp-io")) {
94 } else if (!strcmp(gPESoCDeviceType
, "s5i3000-io")) {
98 tclk
= 100000; /* timer is at 100khz */
104 /* Start with default values. */
105 gPEClockFrequencyInfo
.timebase_frequency_hz
= 24000000;
106 gPEClockFrequencyInfo
.bus_clock_rate_hz
= 100000000;
107 gPEClockFrequencyInfo
.cpu_clock_rate_hz
= 400000000;
109 err
= DTLookupEntry(NULL
, "/cpus", &cpus
);
110 assert(err
== kSuccess
);
112 err
= DTInitEntryIterator(cpus
, &iter
);
113 assert(err
== kSuccess
);
115 while (kSuccess
== DTIterateEntries(&iter
, &cpu
)) {
116 if ((kSuccess
!= DTGetProperty(cpu
, "state", (void **)&value
, &size
)) ||
117 (strncmp((char*)value
, "running", size
) != 0))
120 /* Find the time base frequency first. */
121 if (DTGetProperty(cpu
, "timebase-frequency", (void **)&value
, &size
) == kSuccess
) {
123 * timebase_frequency_hz is only 32 bits, and
124 * the device tree should never provide 64
125 * bits so this if should never be taken.
128 gPEClockFrequencyInfo
.timebase_frequency_hz
= *(unsigned long long *)value
;
130 gPEClockFrequencyInfo
.timebase_frequency_hz
= *value
;
132 gPEClockFrequencyInfo
.dec_clock_rate_hz
= gPEClockFrequencyInfo
.timebase_frequency_hz
;
134 /* Find the bus frequency next. */
135 if (DTGetProperty(cpu
, "bus-frequency", (void **)&value
, &size
) == kSuccess
) {
137 gPEClockFrequencyInfo
.bus_frequency_hz
= *(unsigned long long *)value
;
139 gPEClockFrequencyInfo
.bus_frequency_hz
= *value
;
141 gPEClockFrequencyInfo
.bus_frequency_min_hz
= gPEClockFrequencyInfo
.bus_frequency_hz
;
142 gPEClockFrequencyInfo
.bus_frequency_max_hz
= gPEClockFrequencyInfo
.bus_frequency_hz
;
144 if (gPEClockFrequencyInfo
.bus_frequency_hz
< 0x100000000ULL
)
145 gPEClockFrequencyInfo
.bus_clock_rate_hz
= gPEClockFrequencyInfo
.bus_frequency_hz
;
147 gPEClockFrequencyInfo
.bus_clock_rate_hz
= 0xFFFFFFFF;
149 /* Find the memory frequency next. */
150 if (DTGetProperty(cpu
, "memory-frequency", (void **)&value
, &size
) == kSuccess
) {
152 gPEClockFrequencyInfo
.mem_frequency_hz
= *(unsigned long long *)value
;
154 gPEClockFrequencyInfo
.mem_frequency_hz
= *value
;
156 gPEClockFrequencyInfo
.mem_frequency_min_hz
= gPEClockFrequencyInfo
.mem_frequency_hz
;
157 gPEClockFrequencyInfo
.mem_frequency_max_hz
= gPEClockFrequencyInfo
.mem_frequency_hz
;
159 /* Find the peripheral frequency next. */
160 if (DTGetProperty(cpu
, "peripheral-frequency", (void **)&value
, &size
) == kSuccess
) {
162 gPEClockFrequencyInfo
.prf_frequency_hz
= *(unsigned long long *)value
;
164 gPEClockFrequencyInfo
.prf_frequency_hz
= *value
;
166 gPEClockFrequencyInfo
.prf_frequency_min_hz
= gPEClockFrequencyInfo
.prf_frequency_hz
;
167 gPEClockFrequencyInfo
.prf_frequency_max_hz
= gPEClockFrequencyInfo
.prf_frequency_hz
;
169 /* Find the fixed frequency next. */
170 if (DTGetProperty(cpu
, "fixed-frequency", (void **)&value
, &size
) == kSuccess
) {
172 gPEClockFrequencyInfo
.fix_frequency_hz
= *(unsigned long long *)value
;
174 gPEClockFrequencyInfo
.fix_frequency_hz
= *value
;
176 /* Find the cpu frequency last. */
177 if (DTGetProperty(cpu
, "clock-frequency", (void **)&value
, &size
) == kSuccess
) {
179 gPEClockFrequencyInfo
.cpu_frequency_hz
= *(unsigned long long *)value
;
181 gPEClockFrequencyInfo
.cpu_frequency_hz
= *value
;
183 gPEClockFrequencyInfo
.cpu_frequency_min_hz
= gPEClockFrequencyInfo
.cpu_frequency_hz
;
184 gPEClockFrequencyInfo
.cpu_frequency_max_hz
= gPEClockFrequencyInfo
.cpu_frequency_hz
;
186 if (gPEClockFrequencyInfo
.cpu_frequency_hz
< 0x100000000ULL
)
187 gPEClockFrequencyInfo
.cpu_clock_rate_hz
= gPEClockFrequencyInfo
.cpu_frequency_hz
;
189 gPEClockFrequencyInfo
.cpu_clock_rate_hz
= 0xFFFFFFFF;
192 /* Use the canned values. */
193 gPEClockFrequencyInfo
.timebase_frequency_hz
= tclk
;
194 gPEClockFrequencyInfo
.fix_frequency_hz
= tclk
;
195 gPEClockFrequencyInfo
.bus_frequency_hz
= hclk
;
196 gPEClockFrequencyInfo
.cpu_frequency_hz
= mclk
;
197 gPEClockFrequencyInfo
.prf_frequency_hz
= pclk
;
199 gPEClockFrequencyInfo
.bus_frequency_min_hz
= gPEClockFrequencyInfo
.bus_frequency_hz
;
200 gPEClockFrequencyInfo
.bus_frequency_max_hz
= gPEClockFrequencyInfo
.bus_frequency_hz
;
201 gPEClockFrequencyInfo
.cpu_frequency_min_hz
= gPEClockFrequencyInfo
.cpu_frequency_hz
;
202 gPEClockFrequencyInfo
.cpu_frequency_max_hz
= gPEClockFrequencyInfo
.cpu_frequency_hz
;
203 gPEClockFrequencyInfo
.prf_frequency_min_hz
= gPEClockFrequencyInfo
.prf_frequency_hz
;
204 gPEClockFrequencyInfo
.prf_frequency_max_hz
= gPEClockFrequencyInfo
.prf_frequency_hz
;
206 gPEClockFrequencyInfo
.dec_clock_rate_hz
= gPEClockFrequencyInfo
.timebase_frequency_hz
;
207 gPEClockFrequencyInfo
.bus_clock_rate_hz
= gPEClockFrequencyInfo
.bus_frequency_hz
;
208 gPEClockFrequencyInfo
.cpu_clock_rate_hz
= gPEClockFrequencyInfo
.cpu_frequency_hz
;
211 /* Set the num / den pairs form the hz values. */
212 gPEClockFrequencyInfo
.bus_clock_rate_num
= gPEClockFrequencyInfo
.bus_clock_rate_hz
;
213 gPEClockFrequencyInfo
.bus_clock_rate_den
= 1;
215 gPEClockFrequencyInfo
.bus_to_cpu_rate_num
=
216 (2 * gPEClockFrequencyInfo
.cpu_clock_rate_hz
) / gPEClockFrequencyInfo
.bus_clock_rate_hz
;
217 gPEClockFrequencyInfo
.bus_to_cpu_rate_den
= 2;
219 gPEClockFrequencyInfo
.bus_to_dec_rate_num
= 1;
220 gPEClockFrequencyInfo
.bus_to_dec_rate_den
=
221 gPEClockFrequencyInfo
.bus_clock_rate_hz
/ gPEClockFrequencyInfo
.dec_clock_rate_hz
;
225 pe_arm_get_soc_base_phys(void)
228 uintptr_t *ranges_prop
;
232 if (DTFindEntry("name", "arm-io", &entryP
) == kSuccess
) {
233 if (gPESoCDeviceType
== 0) {
234 DTGetProperty(entryP
, "device_type", (void **)&tmpStr
, &prop_size
);
235 strlcpy(gPESoCDeviceTypeBuffer
, tmpStr
, SOC_DEVICE_TYPE_BUFFER_SIZE
);
236 gPESoCDeviceType
= gPESoCDeviceTypeBuffer
;
238 DTGetProperty(entryP
, "ranges", (void **)&ranges_prop
, &prop_size
);
239 gPESoCBasePhys
= *(ranges_prop
+ 1);
241 return gPESoCBasePhys
;
247 pe_arm_get_soc_revision(void)
253 if ((DTFindEntry("name", "arm-io", &entryP
) == kSuccess
)
254 && (DTGetProperty(entryP
, "chip-revision", (void **)&value
, &size
) == kSuccess
)) {
256 return((uint32_t)*(unsigned long long *)value
);
264 extern void fleh_fiq_generic(void);
266 #if defined(ARM_BOARD_CLASS_S5L8960X)
267 static struct tbd_ops s5l8960x_funcs
= {NULL
, NULL
, NULL
};
268 #endif /* defined(ARM_BOARD_CLASS_S5L8960X) */
270 #if defined(ARM_BOARD_CLASS_T7000)
271 static struct tbd_ops t7000_funcs
= {NULL
, NULL
, NULL
};
272 #endif /* defined(ARM_BOARD_CLASS_T7000) */
274 #if defined(ARM_BOARD_CLASS_S7002)
275 extern void fleh_fiq_s7002(void);
276 extern uint32_t s7002_get_decrementer(void);
277 extern void s7002_set_decrementer(uint32_t);
278 static struct tbd_ops s7002_funcs
= {&fleh_fiq_s7002
, &s7002_get_decrementer
, &s7002_set_decrementer
};
279 #endif /* defined(ARM_BOARD_CLASS_S7002) */
281 #if defined(ARM_BOARD_CLASS_S8000)
282 static struct tbd_ops s8000_funcs
= {NULL
, NULL
, NULL
};
283 #endif /* defined(ARM_BOARD_CLASS_T7000) */
285 #if defined(ARM_BOARD_CLASS_T8002)
286 extern void fleh_fiq_t8002(void);
287 extern uint32_t t8002_get_decrementer(void);
288 extern void t8002_set_decrementer(uint32_t);
289 static struct tbd_ops t8002_funcs
= {&fleh_fiq_t8002
, &t8002_get_decrementer
, &t8002_set_decrementer
};
290 #endif /* defined(ARM_BOARD_CLASS_T8002) */
292 #if defined(ARM_BOARD_CLASS_T8010)
293 static struct tbd_ops t8010_funcs
= {NULL
, NULL
, NULL
};
294 #endif /* defined(ARM_BOARD_CLASS_T8010) */
296 #if defined(ARM_BOARD_CLASS_T8011)
297 static struct tbd_ops t8011_funcs
= {NULL
, NULL
, NULL
};
298 #endif /* defined(ARM_BOARD_CLASS_T8011) */
305 vm_offset_t gPicBase
;
306 vm_offset_t gTimerBase
;
307 vm_offset_t gSocPhys
;
309 #if DEVELOPMENT || DEBUG
310 // This block contains the panic trace implementation
312 // These variables are local to this file, and contain the panic trace configuration information
315 panic_trace_disabled
= 0,
318 panic_trace_alt_enabled
,
320 static panic_trace_t bootarg_panic_trace
;
322 // The command buffer contains the converted commands from the device tree for commanding cpu_halt, enable_trace, etc.
323 #define DEBUG_COMMAND_BUFFER_SIZE 100
324 typedef struct command_buffer_element
{
326 uint16_t destination_cpu_selector
;
328 } command_buffer_element_t
;
329 static command_buffer_element_t debug_command_buffer
[DEBUG_COMMAND_BUFFER_SIZE
]; // statically allocate to prevent needing alloc at runtime
330 static uint32_t next_command_bufffer_entry
= 0; // index of next unused slot in debug_command_buffer
332 #define CPU_SELECTOR_SHIFT ((sizeof(int)-2)*8)
333 #define CPU_SELECTOR_MASK (0xFFFF << CPU_SELECTOR_SHIFT)
334 #define REGISTER_OFFSET_MASK (~CPU_SELECTOR_MASK)
335 #define REGISTER_OFFSET(register_prop) (register_prop & REGISTER_OFFSET_MASK)
336 #define CPU_SELECTOR(register_offset) (register_offset >> CPU_SELECTOR_SHIFT) // Upper 16bits holds the cpu selector
337 #define MAX_WINDOW_SIZE 0xFFFF
338 #define PE_ISSPACE(c) (c == ' ' || c == '\t' || c == '\n' || c == '\12')
345 since it's 16bits, we can have up to 16 cpus
347 #define ALL_CPUS 0x0000
348 #define IS_CPU_SELECTED(cpu_number, cpu_selector) (cpu_selector == ALL_CPUS || (cpu_selector & (1<<cpu_number) ) != 0 )
350 #define RESET_VIRTUAL_ADDRESS_WINDOW 0xFFFFFFFF
352 // Pointers into debug_command_buffer for each operation. Assumes runtime will init them to zero.
353 static command_buffer_element_t
*cpu_halt
;
354 static command_buffer_element_t
*enable_trace
;
355 static command_buffer_element_t
*enable_alt_trace
;
356 static command_buffer_element_t
*trace_halt
;
358 // Record which CPU is currently running one of our debug commands, so we can trap panic reentrancy to PE_arm_debug_panic_hook.
359 static int running_debug_command_on_cpu_number
= -1;
362 pe_init_debug_command(DTEntry entryP
, command_buffer_element_t
**command_buffer
, const char* entry_name
)
365 uint32_t prop_size
, reg_window_size
= 0, command_starting_index
;
366 uintptr_t debug_reg_window
= 0;
368 if (command_buffer
== 0) {
372 if (DTGetProperty(entryP
, entry_name
, (void **)®_prop
, &prop_size
) != kSuccess
) {
373 panic("pe_init_debug_command: failed to read property %s\n", entry_name
);
376 // make sure command will fit
377 if (next_command_bufffer_entry
+ prop_size
/sizeof(uintptr_t) > DEBUG_COMMAND_BUFFER_SIZE
-1) {
378 panic("pe_init_debug_command: property %s is %u bytes, command buffer only has %lu bytes remaining\n",
379 entry_name
, prop_size
, ((DEBUG_COMMAND_BUFFER_SIZE
-1) - next_command_bufffer_entry
) * sizeof(uintptr_t) );
382 // Hold the pointer in a temp variable and later assign it to command buffer, in case we panic while half-initialized
383 command_starting_index
= next_command_bufffer_entry
;
385 // convert to real virt addresses and stuff commands into debug_command_buffer
386 for( ; prop_size
; reg_prop
+= 2, prop_size
-= 2*sizeof(uintptr_t) ) {
387 if (*reg_prop
== RESET_VIRTUAL_ADDRESS_WINDOW
) {
388 debug_reg_window
= 0; // Create a new window
390 else if (debug_reg_window
==0) {
391 // create a window from virtual address to the specified physical address
392 reg_window_size
= ((uint32_t)*(reg_prop
+ 1));
393 if (reg_window_size
> MAX_WINDOW_SIZE
) {
394 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
);
396 debug_reg_window
= ml_io_map(gSocPhys
+ *reg_prop
, reg_window_size
);
397 // for debug -- kprintf("pe_init_debug_command: %s registers @ 0x%08lX for 0x%08lX\n", entry_name, debug_reg_window, *(reg_prop + 1) );
399 if ((REGISTER_OFFSET(*reg_prop
)+ sizeof(uintptr_t)) >= reg_window_size
) {
400 panic("pe_init_debug_command: Command Offset is %lx, exceeds allocated size of %x\n", REGISTER_OFFSET(*reg_prop
),reg_window_size
);
402 debug_command_buffer
[next_command_bufffer_entry
].address
= debug_reg_window
+ REGISTER_OFFSET(*reg_prop
);
403 debug_command_buffer
[next_command_bufffer_entry
].destination_cpu_selector
= CPU_SELECTOR(*reg_prop
);
404 debug_command_buffer
[next_command_bufffer_entry
++].value
= *(reg_prop
+1);
408 // null terminate the address field of the command to end it
409 debug_command_buffer
[next_command_bufffer_entry
++].address
= 0;
411 // save pointer into table for this command
412 *command_buffer
= &debug_command_buffer
[command_starting_index
];
416 pe_run_debug_command(command_buffer_element_t
*command_buffer
)
418 // 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
419 simple_lock(&panic_trace_lock
);
420 running_debug_command_on_cpu_number
= cpu_number();
422 while( command_buffer
&& command_buffer
->address
) {
423 if (IS_CPU_SELECTED(running_debug_command_on_cpu_number
, command_buffer
->destination_cpu_selector
)) {
424 *((volatile uintptr_t*)(command_buffer
->address
)) = command_buffer
->value
; // register = value;
429 running_debug_command_on_cpu_number
= -1;
430 simple_unlock(&panic_trace_lock
);
435 PE_arm_debug_enable_trace(void)
437 switch (bootarg_panic_trace
) {
438 case panic_trace_enabled
:
439 pe_run_debug_command(enable_trace
);
442 case panic_trace_alt_enabled
:
443 pe_run_debug_command(enable_alt_trace
);
452 PEARMDebugPanicHook(const char *str
)
454 (void)str
; // not used
456 // if panic trace is enabled
457 if (bootarg_panic_trace
!= 0) {
458 if (running_debug_command_on_cpu_number
== cpu_number()) {
459 // This is going to end badly if we don't trap, since we'd be panic-ing during our own code
460 kprintf("## Panic Trace code caused the panic ##\n");
461 return; // allow the normal panic operation to occur.
464 // Stop tracing to freze the buffer and return to normal panic processing.
465 pe_run_debug_command(trace_halt
);
469 void (*PE_arm_debug_panic_hook
)(const char *str
) = PEARMDebugPanicHook
;
473 void (*PE_arm_debug_panic_hook
)(const char *str
) = NULL
;
475 #endif // DEVELOPMENT || DEBUG
478 pe_arm_init_debug(void *args
)
484 if (gSocPhys
== 0 ) {
485 kprintf("pe_arm_init_debug: failed to initialize gSocPhys == 0\n");
489 if ( DTFindEntry("device_type", "cpu-debug-interface", &entryP
) == kSuccess
) {
491 if (DTGetProperty(entryP
, "reg", (void **)®_prop
, &prop_size
) == kSuccess
) {
492 ml_init_arm_debug_interface(args
, ml_io_map(gSocPhys
+ *reg_prop
, *(reg_prop
+ 1)));
494 #if DEVELOPMENT || DEBUG
495 // When args != NULL, this means we're being called from arm_init on the boot CPU.
496 // This controls one-time initialization of the Panic Trace infrastructure
498 simple_lock_init(&panic_trace_lock
, 0); //assuming single threaded mode
500 // Panic_halt is deprecated. Please use panic_trace istead.
501 unsigned int temp_bootarg_panic_trace
;
502 if (PE_parse_boot_argn("panic_trace", &temp_bootarg_panic_trace
, sizeof(temp_bootarg_panic_trace
)) ||
503 PE_parse_boot_argn("panic_halt", &temp_bootarg_panic_trace
, sizeof(temp_bootarg_panic_trace
))) {
505 kprintf("pe_arm_init_debug: panic_trace=%d\n", temp_bootarg_panic_trace
);
507 // Prepare debug command buffers.
508 pe_init_debug_command(entryP
, &cpu_halt
, "cpu_halt");
509 pe_init_debug_command(entryP
, &enable_trace
, "enable_trace");
510 pe_init_debug_command(entryP
, &enable_alt_trace
, "enable_alt_trace");
511 pe_init_debug_command(entryP
, &trace_halt
, "trace_halt");
513 // now that init's are done, enable the panic halt capture (allows pe_init_debug_command to panic normally if necessary)
514 bootarg_panic_trace
= temp_bootarg_panic_trace
;
516 // start tracing now if enabled
517 PE_arm_debug_enable_trace();
522 kprintf("pe_arm_init_debug: failed to find cpu-debug-interface\n");
527 pe_arm_map_interrupt_controller(void)
532 vm_offset_t soc_phys
= 0;
534 gSocPhys
= pe_arm_get_soc_base_phys();
537 kprintf("pe_arm_map_interrupt_controller: soc_phys: 0x%lx\n", (unsigned long)soc_phys
);
541 if (DTFindEntry("interrupt-controller", "master", &entryP
) == kSuccess
) {
542 kprintf("pe_arm_map_interrupt_controller: found interrupt-controller\n");
543 DTGetProperty(entryP
, "reg", (void **)®_prop
, &prop_size
);
544 gPicBase
= ml_io_map(soc_phys
+ *reg_prop
, *(reg_prop
+ 1));
545 kprintf("pe_arm_map_interrupt_controller: gPicBase: 0x%lx\n", (unsigned long)gPicBase
);
548 kprintf("pe_arm_map_interrupt_controller: failed to find the interrupt-controller.\n");
552 if (DTFindEntry("device_type", "timer", &entryP
) == kSuccess
) {
553 kprintf("pe_arm_map_interrupt_controller: found timer\n");
554 DTGetProperty(entryP
, "reg", (void **)®_prop
, &prop_size
);
555 gTimerBase
= ml_io_map(soc_phys
+ *reg_prop
, *(reg_prop
+ 1));
556 kprintf("pe_arm_map_interrupt_controller: gTimerBase: 0x%lx\n", (unsigned long)gTimerBase
);
558 if (gTimerBase
== 0) {
559 kprintf("pe_arm_map_interrupt_controller: failed to find the timer.\n");
567 pe_arm_init_interrupts(void *args
)
569 kprintf("pe_arm_init_interrupts: args: %p\n", args
);
571 /* Set up mappings for interrupt controller and possibly timers (if they haven't been set up already) */
573 if (!pe_arm_map_interrupt_controller()) {
578 return pe_arm_init_timer(args
);
582 pe_arm_init_timer(void *args
)
584 vm_offset_t pic_base
= 0;
585 vm_offset_t timer_base
= 0;
586 vm_offset_t soc_phys
;
587 vm_offset_t eoi_addr
= 0;
588 uint32_t eoi_value
= 0;
589 struct tbd_ops generic_funcs
= {&fleh_fiq_generic
, NULL
, NULL
};
590 tbd_ops_t tbd_funcs
= &generic_funcs
;
592 /* The SoC headers expect to use pic_base, timer_base, etc... */
594 timer_base
= gTimerBase
;
597 #if defined(ARM_BOARD_CLASS_S5L8960X)
598 if (!strcmp(gPESoCDeviceType
, "s5l8960x-io")) {
600 tbd_funcs
= &s5l8960x_funcs
;
603 #if defined(ARM_BOARD_CLASS_T7000)
604 if (!strcmp(gPESoCDeviceType
, "t7000-io") ||
605 !strcmp(gPESoCDeviceType
, "t7001-io")) {
606 tbd_funcs
= &t7000_funcs
;
609 #if defined(ARM_BOARD_CLASS_S7002)
610 if (!strcmp(gPESoCDeviceType
, "s7002-io")) {
612 #ifdef ARM_BOARD_WFE_TIMEOUT_NS
613 // Enable the WFE Timer
614 rPMGR_EVENT_TMR_PERIOD
= ((uint64_t)(ARM_BOARD_WFE_TIMEOUT_NS
) * gPEClockFrequencyInfo
.timebase_frequency_hz
) / NSEC_PER_SEC
;
615 rPMGR_EVENT_TMR
= rPMGR_EVENT_TMR_PERIOD
;
616 rPMGR_EVENT_TMR_CTL
= PMGR_EVENT_TMR_CTL_EN
;
617 #endif /* ARM_BOARD_WFE_TIMEOUT_NS */
619 rPMGR_INTERVAL_TMR
= 0x7FFFFFFF;
620 rPMGR_INTERVAL_TMR_CTL
= PMGR_INTERVAL_TMR_CTL_EN
| PMGR_INTERVAL_TMR_CTL_CLR_INT
;
622 eoi_addr
= timer_base
;
623 eoi_value
= PMGR_INTERVAL_TMR_CTL_EN
| PMGR_INTERVAL_TMR_CTL_CLR_INT
;
624 tbd_funcs
= &s7002_funcs
;
627 #if defined(ARM_BOARD_CLASS_S8000)
628 if (!strcmp(gPESoCDeviceType
, "s8000-io") ||
629 !strcmp(gPESoCDeviceType
, "s8001-io")) {
630 tbd_funcs
= &s8000_funcs
;
633 #if defined(ARM_BOARD_CLASS_T8002)
634 if (!strcmp(gPESoCDeviceType
, "t8002-io") ||
635 !strcmp(gPESoCDeviceType
, "t8004-io")) {
637 /* Enable the Decrementer */
638 aic_write32(kAICTmrCnt
, 0x7FFFFFFF);
639 aic_write32(kAICTmrCfg
, kAICTmrCfgEn
);
640 aic_write32(kAICTmrIntStat
, kAICTmrIntStatPct
);
641 #ifdef ARM_BOARD_WFE_TIMEOUT_NS
642 // Enable the WFE Timer
643 rPMGR_EVENT_TMR_PERIOD
= ((uint64_t)(ARM_BOARD_WFE_TIMEOUT_NS
) * gPEClockFrequencyInfo
.timebase_frequency_hz
) / NSEC_PER_SEC
;
644 rPMGR_EVENT_TMR
= rPMGR_EVENT_TMR_PERIOD
;
645 rPMGR_EVENT_TMR_CTL
= PMGR_EVENT_TMR_CTL_EN
;
646 #endif /* ARM_BOARD_WFE_TIMEOUT_NS */
649 eoi_value
= kAICTmrIntStatPct
;
650 tbd_funcs
= &t8002_funcs
;
653 #if defined(ARM_BOARD_CLASS_T8010)
654 if (!strcmp(gPESoCDeviceType
, "t8010-io")) {
655 tbd_funcs
= &t8010_funcs
;
658 #if defined(ARM_BOARD_CLASS_T8011)
659 if (!strcmp(gPESoCDeviceType
, "t8011-io")) {
660 tbd_funcs
= &t8011_funcs
;
666 ml_init_timebase(args
, tbd_funcs
, eoi_addr
, eoi_value
);