UARTs not working on a Supermicro A2SAV / Linux works ;-(

Kurt Lidl lidl at
Tue Mar 13 21:00:42 UTC 2018

On 3/13/18 1:14 PM, Andre Albsmeier wrote:
> The UARTs on the brand new Supermicro A2SAV mainboard
> (
> are detected on 11.1-STABLE as
> uart0: <16550 or compatible> port 0x3f8-0x3ff irq 4 flags 0x10 on acpi0
> uart1: <16550 or compatible> port 0x2f8-0x2ff irq 3 on acpi0
> which is consistent with the BIOS settings.
> Everything seems to work when it comes to setting of parameters and even
> the DTR and RTS lines change state when opening cuau0 or cuau1, e.g. with
> minicom.
> But sending or receiving characters fails -- to be exact, no single
> character will be received and only the very first one will be sent to
> the remote device.
> We remember this behaviour from the good old times when we had to jumper
> base port addresses and IRQs on ISA cards: If we got the IRQ wrong the
> same effect happened: The first char could be sent because the TX register
> was empty but the IRQ telling the kernel that it can send the next char
> never arrived.
> When using debug.uart_force_poll=1 in loader.conf it works (at least if
> we type in characters slowly, of course).
> So it really seems to have to do with interrupts again but I have no
> idea where to look.
> The A2SAV manual talks about the Super I/O being a Nuvoton NCT5523D. Can
> it be that we miss some support for this? But if the devices really behave
> like standard 16550s we shouldn't need any specific support at all, I think.
> I disabled the corresponding ACPI functions by using
> debug.acpi.avoid="\_SB_.PCI0.SBRG.UAR1 \_SB_.PCI0.SBRG.UAR2"
> and the devices were detected properly as
> uart0: <16550 or compatible> at port 0x3f8 irq 4 flags 0x10 on isa0
> uart1: <16550 or compatible> at port 0x2f8 irq 3 on isa0
> but this didn't help (same behaviour).
> The really bad news are: Using Linux (Ubuntu 16.04) it works. Devices are
> detected here as:
> ...
> [    0.261209] pnp 00:01: [dma 0 disabled]
> [    0.261295] pnp 00:01: Plug and Play ACPI device, IDs PNP0501 (active)
> [    0.261774] pnp 00:02: [dma 0 disabled]
> [    0.261868] pnp 00:02: Plug and Play ACPI device, IDs PNP0501 (active)
> ...
> [    1.479082] Serial: 8250/16550 driver, 32 ports, IRQ sharing enabled
> [    1.499962] 00:01: ttyS0 at I/O 0x3f8 (irq = 4, base_baud = 115200) is a 16550A
> [    1.520943] 00:02: ttyS1 at I/O 0x2f8 (irq = 3, base_baud = 115200) is a 16550A
> and we can send and receive characters without problems.
> So it really seems FreeBSD does something wrong on the A2SAV board when
> it comes to interrupts of the serial ports.
> Any ideas how to start?

So, at my prior job, we had a custom board that used the Novuton NCT5104
as the chip that provided the serial ports.  One of the interesting
things about the NCT5104 is that one can use in a PCI-only environments
to provide serial ports.  It offers the serial ports that traditionally
would be provided by the traditonal Super I/O chipset, except that
rather than having a large number of I/O lines, it's a LPC
"low pin count" device.  We had no legacy parts on the boards we
manufactured, but we really, really wanted serial ports, so we ended up
with this chip to provide the serial ports.

Anyhow -- we had pretty much the same exact problem with the serial
ports on our card.  To make a long story short, I wrote a low-level
register dumper for the NCT5104. One can make it act like a traditional
NS16550A part, if you're willing to dink with the specific setup for
the NCT5104.

Here's the diff of the "non-working" serial port diagnostic, compared
to the corrected version:
diff results_broken.txt results_fixed.txt
< sio register 0xf0 - value: 0x00
 > sio register 0xf0 - value: 0x40
< 	IRQ mode: level
 > 	IRQ mode: pulse mode (for sharing)

If you have a BIOS setting that allows you to control the IRQ method
for the NCT part, try setting it to "pulse mode", rather than "level".

We ended up resolving the issue by having the board manufacturer rev
the BIOS, so that "BIOS defaults" value was set to "pulse mode", rather
than "level" for this controller, and then FreeBSD was happy to use
it as a regular old serial port.  Alternatively, you can probably
stick a little initialization bit of code in, to program the NCT5523D
to change the interrupt setting.

I was able to get the programming guide from Nuvoton just by asking
nicely, so you can probably get it too, if you needed it.


More information about the freebsd-hackers mailing list