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:
Andre Przywara 2024-02-18 13:51:13 +00:00 committed by Paul Kocialkowski
parent e3f41d48f2
commit 2f55111def

View File

@ -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 */