The branch main has been updated by imp: URL: https://cgit.FreeBSD.org/src/commit/?id=dea3eef94cafb3bb1e5f04bc96b5636ffca92ee7
commit dea3eef94cafb3bb1e5f04bc96b5636ffca92ee7 Author: Warner Losh <i...@freebsd.org> AuthorDate: 2025-01-15 02:17:46 +0000 Commit: Warner Losh <i...@freebsd.org> CommitDate: 2025-01-15 02:24:35 +0000 uart: Ingore pl011 historic mistakes Some veresions of EDK-II and QEMU reported the wrong values for the register shift and the region I/O size. Detect those and set it to the correct values. In general, anything other than a shift of 2 and a regio width of 4 (bytes, or 32 bits) is a mistake. However, allow for overrides in the future by only overriding the buggy values. Otherwise, we will fail to boot. PR: 282936 Sponsored by: Netflix Reviewed by: emaste Differential Revision: https://reviews.freebsd.org/D47946 --- sys/dev/uart/uart_dev_pl011.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/sys/dev/uart/uart_dev_pl011.c b/sys/dev/uart/uart_dev_pl011.c index 4f946f7c5f36..e7a2ff7a85f1 100644 --- a/sys/dev/uart/uart_dev_pl011.c +++ b/sys/dev/uart/uart_dev_pl011.c @@ -172,6 +172,27 @@ static int uart_pl011_probe(struct uart_bas *bas) { + /* + * Versions of QEMU before 41f7b58b634e (8.3) reported bogus values for + * this tabel. The PL011 IP is always 32-bits wide and should be shifted + * 2 to match the 4-byte size of the data. QEMU reported these values + * incorrectly before that. + * https://github.com/qemu/qemu/commit/41f7b58b634ec3b60ae874375d2bbb61d790971e + * + * In additon, other hardware vendors also reported this value + * incorrectly. It's not tied to what the ACPI device node is, but was a + * misunderstanding coupled with a Linux driver that didn't need the + * right values. Quirks used to be used to ignore the bad values, now we + * detect the historic mistake and override (to allow for a future where + * we may need to override these values). + * + * PL011 Docs: https://developer.arm.com/documentation/ddi0183/latest/ + */ + if (bas->regshft == 0 || bas->regiowidth == 1) { + bas->regshft = 2; + bas->regiowidth = 4; + } + return (0); } @@ -356,7 +377,8 @@ static struct uart_class uart_pl011_class = { .uc_ops = &uart_pl011_ops, .uc_range = 0x48, .uc_rclk = 0, - .uc_rshift = 2 + .uc_rshift = 2, + .uc_riowidth = 4, }; UART_CLASS(uart_pl011_class);