U-Boot: PPC: Spice up CPU detection, trying both PVR and FDT

* Read the PVR register to determine the CPU type.
* Also check the FDT /cpu/cpu@0 node for model string
  (we use the FDT calls directly since the OF wrapper isn't initialized yet).
* Use this to enable the FPU APU hack for 440 (instead of #ifdef).
This commit is contained in:
François Revol
2013-02-18 00:22:56 +01:00
parent cb77e62c17
commit f4b31e85b5
2 changed files with 77 additions and 11 deletions
@@ -6,6 +6,8 @@ UsePrivateHeaders kernel [ FDirName kernel arch $(TARGET_KERNEL_ARCH) ]
[ FDirName kernel boot platform $(HAIKU_BOOT_PLATFORM) ] ;
UsePrivateHeaders [ FDirName kernel arch $(TARGET_KERNEL_ARCH) board $(TARGET_BOOT_BOARD) ] ;
UseLibraryHeaders [ FDirName libfdt ] ;
SubDirC++Flags -fno-rtti ;
BootMergeObject boot_platform_u-boot_ppc.o :
@@ -22,8 +22,16 @@
#include <string.h>
extern "C" {
#include <fdt.h>
#include <libfdt.h>
#include <libfdt_env.h>
};
//#define TRACE_CPU
extern void *gFDT;
#define TRACE_CPU
#ifdef TRACE_CPU
# define TRACE(x) dprintf x
#else
@@ -44,17 +52,67 @@ static status_t
check_cpu_features()
{
uint32 msr;
uint32 pvr;
bool is_440 = false;
bool is_460 = false;
bool pvr_unknown = false;
bool fdt_unknown = true;
const char *fdt_model = NULL;
#if BOARD_CPU_TYPE_PPC440
// the FPU is implemented as an Auxiliary Processing Unit,
// so we must enable transfers by setting the DAPUIB bit to 0
asm volatile(
"mfccr0 %%r3\n"
"\tlis %%r4,~(1<<(20-16))\n"
"\tand %%r3,%%r3,%%r4\n"
"\tmtccr0 %%r3"
: : : "r3", "r4");
#endif
// attempt to detect processor version, either from PVR or FDT
// TODO:someday we'll support other things than 440/460...
// read the Processor Version Register
pvr = get_pvr();
uint16 version = (uint16)(pvr >> 16);
uint16 revision = (uint16)(pvr & 0xffff);
switch (version) {
case AMCC440EP:
is_440 = true;
break;
case AMCC460EX:
is_460 = true;
break;
default:
pvr_unknown = true;
}
// if we have an FDT...
// XXX: use it only as fallback?
if (gFDT != NULL/* && pvr_unknown*/) {
// TODO: for MP support we must checn /chosen/cpu first
int node = fdt_path_offset(gFDT, "/cpus/cpu@0");
int len;
fdt_model = (const char *)fdt_getprop(gFDT, node, "model", &len);
// TODO: partial match ? "PowerPC,440" && isalpha(next char) ?
if (fdt_model) {
if (!strcmp(fdt_model, "PowerPC,440EP")) {
is_440 = true;
fdt_unknown = false;
} else if (!strcmp(fdt_model, "PowerPC,460EX")) {
is_460 = true;
fdt_unknown = false;
}
}
}
if (is_460)
is_440 = true;
// some cpu-dependent tweaking
if (is_440) {
// the FPU is implemented as an Auxiliary Processing Unit,
// so we must enable transfers by setting the DAPUIB bit to 0
asm volatile(
"mfccr0 %%r3\n"
"\tlis %%r4,~(1<<(20-16))\n"
"\tand %%r3,%%r3,%%r4\n"
"\tmtccr0 %%r3"
: : : "r3", "r4");
}
// we do need an FPU for vsnprintf to work
// on Sam460ex at least U-Boot doesn't enable the FPU for us
@@ -68,6 +126,11 @@ check_cpu_features()
return B_ERROR;
}
TRACE(("CPU detection:\n"));
TRACE(("PVR revision %sknown: 0x%8lx\n", pvr_unknown ? "un" : "", pvr));
TRACE(("FDT model %sknown: %s\n", fdt_unknown ? "un" : "", fdt_model));
TRACE(("flags: %s440 %s460\n", is_440 ? "" : "!", is_460 ? "" : "!"));
return B_OK;
}
@@ -103,6 +166,7 @@ boot_arch_cpu_init(void)
gKernelArgs.num_cpus = 1;
// this will eventually be corrected later on
// TODO:iterate on /cpus/*
return B_OK;
}