I've been down a bit of a rabbit hole trying to get the Linux AMBA-CLCD driver for versatilepb target's graphics to work with modern Linux kernels. After a good deal of reading of both the Linux kernel code and the qemu code, I discovered why it won't work and why it probably has never worked since the transition to devicetree in the kernel about a decade ago.
The driver chooses between PL110 and PL111 mode by taking the identifier from the AMBA bus:
if (amba_manf(fb->dev) == 0x41 && amba_part(fb->dev) == 0x111) {
fb->off_ienb = CLCD_PL111_IENB;
fb->off_cntl = CLCD_PL111_CNTL;
} else {
fb->off_ienb = CLCD_PL110_IENB;
fb->off_cntl = CLCD_PL110_CNTL;
}
While Qemu thinks that the PL110_versatile ought to have the PL110 device ID, but the PL111 behaviour.
static const unsigned char *idregs[] = {
pl110_id,
/* The ARM documentation (DDI0224C) says the CLCDC on the Versatile board
* has a different ID (0x93, 0x10, 0x04, 0x00, ...). However the hardware
* itself has the same ID values as a stock PL110, and guests (in
* particular Linux) rely on this. We emulate what the hardware does,
* rather than what the docs claim it ought to do.
*/
pl110_id,
pl111_id
};
So the Linux driver writes the wrong control register and the device is never enabled.
I'm at a loss to know what to do about this. This hardware emulation worked with pre-devicetree kernels, and possibly making this change will break that, I really don't know. I also don't own the real hardware so I can't observe what the real behaviour is.
I'm possibly the only person to actually care about this in about a decade, and the CLCD driver has recently been removed from Linux. I only care about it because I'm trying to run some old software unmodified.
I'm happy to write a patch for Qemu if anyone can suggest an approach to fixing this, anyone have any ideas?