uart0-helloworld-sdboot: rework SRAM version register detection
The SRAM controller's version register, which we use to identify a SoC,
is mapped at different locations in the different SoC generations. To find
the right MMIO address, we try to read some GICD_IIDR register, which
tells us which SoC generation we are dealing with.
Looking forward, this will need to be more flexible, as the A80 and A523
will not work with this scheme anymore: the A80 uses a completely
different memory map, and the A523 has a GICv3.
Rework the generation detection to be more flexible and easier to extend:
- First read the MIDR, and check for a Cortex-A8 core. This is the early
generation of SoCs (A10/A10s/A13), which don't have a GIC at all. Use
the legacy SRAM controller address in this case.
- Next check the address of the GIC in the H6 generation ("NCAT"). Its
base address is unmapped at all the other SoCs tested, so this is safe.
- Finally check the GIC address of the "legacy" generation of SoCs
(A20-A64).
- If nothing matches, we are dealing with an unknown SoC, and must stop.
The A80 detection was a nice idea, but didn't work, since the boot
cluster is the one with the A7 cores, so the boot CPU looks like all the
other 32-bit SoCs. Remove that, as the A80 is not supported anyways.
Signed-off-by: Andre Przywara <osp@andrep.de>
This commit is contained in:
parent
e3f41d48f2
commit
2f55111def
@ -276,28 +276,22 @@ static u32 soc_id;
|
||||
|
||||
void soc_detection_init(void)
|
||||
{
|
||||
u32 reg;
|
||||
u32 midr;
|
||||
|
||||
asm volatile("mrc p15, 0, %0, c0, c0, 0" : "=r" (midr));
|
||||
|
||||
if (((midr >> 4) & 0xFFF) == 0xC0F) {
|
||||
soc_id = 0x1639; /* ARM Cortex-A15, so likely Allwinner A80 */
|
||||
if (((midr >> 4) & 0xFFF) == 0xc08) { /* ARM Cortex-A8: A10/A10s/A13 */
|
||||
reg = VER_REG;
|
||||
} else if ((readl(0x03021008) & 0xfff) == 0x43b) {// GICD_IIDR @ NCAT
|
||||
reg = H6_VER_REG;
|
||||
} else if ((readl(0x01c81008) & 0xfff) == 0x43b) {// GICD_IIDR @ legacy
|
||||
reg = VER_REG;
|
||||
} else {
|
||||
u32 reg;
|
||||
|
||||
/*
|
||||
* This register is GICD_IIDR on H6, but unmapped according to
|
||||
* other known SoCs' user manuals.
|
||||
*/
|
||||
reg = readl(0x03021008);
|
||||
|
||||
if ((reg & 0xfff) == 0x43b) /* Found GICv2 here, so it's a H6 */
|
||||
reg = H6_VER_REG;
|
||||
else
|
||||
reg = VER_REG;
|
||||
|
||||
set_wbit(reg, 1 << 15);
|
||||
soc_id = readl(reg) >> 16;
|
||||
while (1); // unknown
|
||||
}
|
||||
|
||||
set_wbit(reg, 1U << 15);
|
||||
soc_id = readl(reg) >> 16;
|
||||
}
|
||||
|
||||
/* Most SoCs can reliably be distinguished by simply checking their ID value */
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user