2 * Copyright 2006, Ingo Weinhold <bonefish@cs.tu-berlin.de>.
3 * All rights reserved. Distributed under the terms of the MIT License.
6 #include <arch_platform.h>
10 #include <KernelExport.h>
12 #include <arch/generic/debug_uart.h>
13 #include <boot/kernel_args.h>
14 #include <platform/openfirmware/openfirmware.h>
15 #include <real_time_clock.h>
16 #include <util/kernel_cpp.h>
19 // TODO: declare this in some header
21 extern DebugUART
*debug_uart_from_fdt(const void *fdt
);
23 static PPCPlatform
*sPPCPlatform
;
27 PPCPlatform::PPCPlatform(ppc_platform_type platformType
)
28 : fPlatformType(platformType
)
33 PPCPlatform::~PPCPlatform()
39 PPCPlatform::Default()
45 // #pragma mark - Open Firmware
50 class PPCOpenFirmware
: public PPCPlatform
{
53 virtual ~PPCOpenFirmware();
55 virtual status_t
Init(struct kernel_args
*kernelArgs
);
56 virtual status_t
InitSerialDebug(struct kernel_args
*kernelArgs
);
57 virtual status_t
InitPostVM(struct kernel_args
*kernelArgs
);
58 virtual status_t
InitRTC(struct kernel_args
*kernelArgs
,
59 struct real_time_data
*data
);
61 virtual char SerialDebugGetChar();
62 virtual void SerialDebugPutChar(char c
);
64 virtual void SetHardwareRTC(uint32 seconds
);
65 virtual uint32
GetHardwareRTC();
67 virtual void ShutDown(bool reboot
);
75 } // namespace BPrivate
77 using BPrivate::PPCOpenFirmware
;
80 // OF debugger commands
82 // debug_command_of_exit
84 debug_command_of_exit(int argc
, char **argv
)
87 kprintf("of_exit() failed!\n");
91 // debug_command_of_enter
93 debug_command_of_enter(int argc
, char **argv
)
95 of_call_client_function("enter", 0, 0);
101 PPCOpenFirmware::PPCOpenFirmware()
102 : PPCPlatform(PPC_PLATFORM_OPEN_FIRMWARE
),
110 PPCOpenFirmware::~PPCOpenFirmware()
116 PPCOpenFirmware::Init(struct kernel_args
*kernelArgs
)
119 (int(*)(void*))kernelArgs
->platform_args
.openfirmware_entry
);
124 PPCOpenFirmware::InitSerialDebug(struct kernel_args
*kernelArgs
)
126 if (of_getprop(gChosen
, "stdin", &fInput
, sizeof(int)) == OF_FAILED
)
128 if (!kernelArgs
->frame_buffer
.enabled
) {
129 if (of_getprop(gChosen
, "stdout", &fOutput
, sizeof(int)) == OF_FAILED
)
138 PPCOpenFirmware::InitPostVM(struct kernel_args
*kernelArgs
)
140 add_debugger_command("of_exit", &debug_command_of_exit
,
141 "Exit to the Open Firmware prompt. No way to get back into the OS!");
142 add_debugger_command("of_enter", &debug_command_of_enter
,
143 "Enter a subordinate Open Firmware interpreter. Quitting it returns "
151 PPCOpenFirmware::InitRTC(struct kernel_args
*kernelArgs
,
152 struct real_time_data
*data
)
155 fRTC
= of_open(kernelArgs
->platform_args
.rtc_path
);
156 if (fRTC
== OF_FAILED
) {
157 dprintf("PPCOpenFirmware::InitRTC(): Failed open RTC device!\n");
164 // DebugSerialGetChar
166 PPCOpenFirmware::SerialDebugGetChar()
169 if (of_interpret("key", 0, 1, &key
) == OF_FAILED
)
174 // DebugSerialPutChar
176 PPCOpenFirmware::SerialDebugPutChar(char c
)
182 of_write(fOutput
, "\r\n", 2);
184 of_write(fOutput
, &c
, 1);
189 PPCOpenFirmware::SetHardwareRTC(uint32 seconds
)
192 rtc_secs_to_tm(seconds
, &t
);
194 t
.tm_year
+= RTC_EPOCH_BASE_YEAR
;
197 if (of_call_method(fRTC
, "set-time", 6, 0, t
.tm_year
, t
.tm_mon
, t
.tm_mday
,
198 t
.tm_hour
, t
.tm_min
, t
.tm_sec
) == OF_FAILED
) {
199 dprintf("PPCOpenFirmware::SetHardwareRTC(): Failed to set RTC!\n");
205 PPCOpenFirmware::GetHardwareRTC()
208 if (of_call_method(fRTC
, "get-time", 0, 6, &t
.tm_year
, &t
.tm_mon
,
209 &t
.tm_mday
, &t
.tm_hour
, &t
.tm_min
, &t
.tm_sec
) == OF_FAILED
) {
210 dprintf("PPCOpenFirmware::GetHardwareRTC(): Failed to get RTC!\n");
214 t
.tm_year
-= RTC_EPOCH_BASE_YEAR
;
217 return rtc_tm_to_secs(&t
);
222 PPCOpenFirmware::ShutDown(bool reboot
)
225 of_interpret("reset-all", 0, 0);
227 // not standardized, so it might fail
228 of_interpret("shut-down", 0, 0);
233 // #pragma mark - U-Boot + FDT
238 class PPCUBoot
: public PPCPlatform
{
243 virtual status_t
Init(struct kernel_args
*kernelArgs
);
244 virtual status_t
InitSerialDebug(struct kernel_args
*kernelArgs
);
245 virtual status_t
InitPostVM(struct kernel_args
*kernelArgs
);
246 virtual status_t
InitRTC(struct kernel_args
*kernelArgs
,
247 struct real_time_data
*data
);
249 virtual char SerialDebugGetChar();
250 virtual void SerialDebugPutChar(char c
);
252 virtual void SetHardwareRTC(uint32 seconds
);
253 virtual uint32
GetHardwareRTC();
255 virtual void ShutDown(bool reboot
);
261 DebugUART
*fDebugUART
;
264 } // namespace BPrivate
266 using BPrivate::PPCUBoot
;
271 : PPCPlatform(PPC_PLATFORM_U_BOOT
),
280 PPCUBoot::~PPCUBoot()
286 PPCUBoot::Init(struct kernel_args
*kernelArgs
)
288 gFDT
= kernelArgs
->platform_args
.fdt
;
289 // XXX: do we error out if no FDT?
295 PPCUBoot::InitSerialDebug(struct kernel_args
*kernelArgs
)
297 fDebugUART
= debug_uart_from_fdt(gFDT
);
298 if (fDebugUART
== NULL
)
305 PPCUBoot::InitPostVM(struct kernel_args
*kernelArgs
)
312 PPCUBoot::InitRTC(struct kernel_args
*kernelArgs
,
313 struct real_time_data
*data
)
318 // DebugSerialGetChar
320 PPCUBoot::SerialDebugGetChar()
323 return fDebugUART
->GetChar(false);
327 // DebugSerialPutChar
329 PPCUBoot::SerialDebugPutChar(char c
)
332 fDebugUART
->PutChar(c
);
337 PPCUBoot::SetHardwareRTC(uint32 seconds
)
343 PPCUBoot::GetHardwareRTC()
350 PPCUBoot::ShutDown(bool reboot
)
358 #define PLATFORM_BUFFER_SIZE MAX(sizeof(PPCOpenFirmware),sizeof(PPCUBoot))
359 // static buffer for constructing the actual PPCPlatform
360 static char *sPPCPlatformBuffer
[PLATFORM_BUFFER_SIZE
];
363 arch_platform_init(struct kernel_args
*kernelArgs
)
365 // only OpenFirmware supported for now
366 switch (kernelArgs
->arch_args
.platform
) {
367 case PPC_PLATFORM_OPEN_FIRMWARE
:
368 sPPCPlatform
= new(sPPCPlatformBuffer
) PPCOpenFirmware
;
370 case PPC_PLATFORM_U_BOOT
:
371 sPPCPlatform
= new(sPPCPlatformBuffer
) PPCUBoot
;
377 return sPPCPlatform
->Init(kernelArgs
);
382 arch_platform_init_post_vm(struct kernel_args
*kernelArgs
)
384 return sPPCPlatform
->InitPostVM(kernelArgs
);
389 arch_platform_init_post_thread(struct kernel_args
*kernelArgs
)