linux-raspi 6.17: secondary RP1 PL011 programs wrong baud divider, stty 115200 actually programs ~4098 baud at the silicon
Shannon Kerr
shannon at exaviz.com
Sun May 17 22:34:05 UTC 2026
Hi all,
I have a fairly clean reproduction of what looks like a baud-divider bug in linux-raspi 6.17 affecting the secondary RP1 PL011 UART instances on Pi 5 / CM5 (compatible "arm,pl011-axi", e.g. /dev/ttyAMA3 at MMIO 0x1F0003C000). I don't have a Launchpad account, so I'm sending here. Phil is CC'd because the original AXI probe path is his.
On linux-raspi 6.17.0-1014.14 under Ubuntu 25.10, after stty -F /dev/ttyAMA3 115200 raw -echo, the PL011 IBRD/FBRD registers contain values that correspond to an effective line rate of ~4098 baud rather than 115200. The same physical board, with the same overlay and userspace, programs the dividers correctly under Raspberry Pi Foundation's 6.12.62+rpt-rpi-2712 kernel from rpi-6.12.y.
Direct reads via busybox devmem on the broken kernel:
IBRD @ 0x1F0003C024 = 0x000002FA (decimal 762)
FBRD @ 0x1F0003C028 = 0x00000024 (decimal 36)
LCR_H @ 0x1F0003C02C = 0x00000070 (8N1, FIFO enabled, no parity, 1 stop)
CR @ 0x1F0003C030 = 0x00000F01 (UARTEN | TXE | RXE | RTSEN | CTSEN)
DMACR @ 0x1F0003C048 = 0x00000000 (no DMA)
/sys/class/tty/ttyAMA3/uartclk = 50000000
By the standard PL011 formula, baud = 50_000_000 / (16 * (762 + 36/64)) = 4098.0. stty -F /dev/ttyAMA3 is internally consistent and reports "speed 4098 baud" back. It isn't 115200-specific: stty 9600 produces IBRD=0xAB00, FBRD=0x27, effective baud ~71.4. At every standard rate I've tested, the divider has no correct relationship to the requested baud.
For comparison, on the same board running Raspberry Pi OS / Debian Trixie with 6.12.62+rpt-rpi-2712, the kernel programs IBRD=27, FBRD=8 (which is what you'd expect for 50 MHz UARTCLK at 115200: quot = DIV_ROUND_CLOSEST(50e6 * 4, 115200) = 1736, IBRD = quot >> 6 = 27, FBRD = quot & 0x3f = 8), stty reports "speed 115200 baud", and /proc/tty/driver/ttyAMA records zero framing errors over tens of millions of received bytes. On the broken kernel the same row records framing errors at ~67% of received bytes, consistent with a sample-rate mismatch this large where start-bit alignment is effectively random:
Ubuntu 25.10 (broken):
3: uart:PL011 AXI mmio:0x1F0003C000 irq:148 tx:30 rx:123447 fe:83789 brk:2991 RTS|CTS|DTR|DSR|CD|RI
Debian Trixie (works):
3: uart:PL011 AXI mmio:0x1F0003C000 irq:146 tx:1821 rx:54628866 RTS|CTS|DTR|DSR|CD|RI
(note: no fe/brk columns, i.e. zero across 54M+ bytes)
dmesg on the broken kernel confirms the device binds via the AXI platform driver:
[ 1.172205] pl011-axi 1f0003c000.serial: cts_event_workaround enabled
[ 1.172818] 1f0003c000.serial: ttyAMA3 at MMIO 0x1f0003c000 (irq = 148, base_baud = 0) is a PL011 AXI
Things I've ruled out:
* Pinmux. /sys/kernel/debug/pinctrl/1f000d0000.gpio-pinctrl-rp1/pinmux-pins shows pin 8/9 claimed by 1f0003c000.serial function uart3 under both kernels. pinctrl get reports alt2 with pull-up, idling high.
* uartclk reported wrong. /sys/class/tty/ttyAMA3/uartclk reads 50000000 under both kernels; clk_summary shows the same parent clock feeding 1f0003c000.serial in both.
* Userspace termios drift. stty -a output is byte-identical between the two kernels after the same userspace command.
* The Phil Elwell AXI patch missing. I pulled the matching linux-raspi source (git clone git://git.launchpad.net/~ubuntu-kernel/ubuntu/+source/linux-raspi/+git/questing at tag Ubuntu-raspi-6.17.0-1014.14, commit 7b372786ef5effbbd802924a59382c91921c8916) and the whole pl011_axi_probe / vendor_arm_axi / arm,pl011-axi platform driver is present in drivers/tty/serial/amba-pl011.c. The vendor_arm_axi struct and pl011_axi_probe body are byte-identical to rpi-6.12.y.
* DMA. DMACR=0 on the broken kernel.
* ttyAMA0 kernel console contention. Removing console=serial0,115200 from /boot/firmware/current/cmdline.txt and rebooting (so ttyAMA0 shows tx:0 rx:0 in /proc/tty/driver/ttyAMA) has zero effect on ttyAMA3's divider or framing error rate.
* The "amba_pl011: Round input clock up" downstream-only patch (raspberrypi/linux commit ab3f1b39537f6d3825b8873006fbe2fc5ff057b7). uartclk is exactly 50000000, no rounding needed.
* pl011_set_termios itself. Diffing the function between rpi-6.12.y and the linux-raspi 6.17 source shows only a cosmetic refactor (ns_to_ktime wrap on rs485_tx_drain_interval). The math and the IBRD/FBRD writes are unchanged.
Where I think it IS but haven't pinpointed: somewhere in the 465-line diff between drivers/tty/serial/amba-pl011.c on rpi-6.12.y vs the linux-raspi 6.17 base. I haven't narrowed it further than "something between the termios input and the IBRD/FBRD write is wrong on this port" - could be uart_get_baud_rate returning the wrong value, the wrong clock being read inside set_termios, or a later overwrite of the dividers. I can't discriminate from userspace, and I haven't set up a kernel build environment yet.
Reproducer, no peripheral hardware needed beyond a Pi 5 or CM5 with /dev/ttyAMA3 enabled (any overlay that activates &uart3, e.g. dtoverlay=uart3 in /boot/firmware/config.txt):
apt-get install -y busybox-static
stty -F /dev/ttyAMA3 115200 raw -echo
busybox devmem 0x1F0003C024 32 # expect 0x1B (27); observed 0x2FA (762)
busybox devmem 0x1F0003C028 32 # expect 0x08 (8); observed 0x24 (36)
stty -F /dev/ttyAMA3 # expect "speed 115200 baud"; observed "speed 4098 baud"
This silently breaks any Pi 5 or CM5 deployment using a secondary RP1 UART under Ubuntu. stty reports the requested baud back so there's no visible error, just garbled bytes on the wire. The practical workaround today is "use Debian or Pi OS on these boards instead."
If anyone wants additional probes (ftrace, kprobes on uart_get_baud_rate or pl011_set_termios, a custom kernel with printk in the relevant paths, kernel-side bisection across the linux-raspi tree), I can supply raw data, scripts, or shell access on the reproducer board.
Environment:
$ uname -a
Linux <host> 6.17.0-1014-raspi #14-Ubuntu SMP PREEMPT_DYNAMIC Wed Apr 15 12:09:19 UTC 2026 aarch64 GNU/Linux
$ cat /etc/os-release | head -3
PRETTY_NAME="Ubuntu 25.10"
NAME="Ubuntu"
VERSION_ID="25.10"
$ dpkg -l linux-image-$(uname -r) | tail -1
ii linux-image-6.17.0-1014-raspi 6.17.0-1014.14 arm64
Comparison kernel:
$ uname -a
Linux <host> 6.12.62+rpt-rpi-2712 #1 SMP PREEMPT Debian 1:6.12.62-1+rpt1 (2025-12-18) aarch64 GNU/Linux
Thanks for looking,
Shannon
More information about the kernel-team
mailing list