uart and big-endian targets

M. Warner Losh imp at bsdimp.com
Tue Jan 20 12:33:49 PST 2009


In message: <4976297C.7020405 at bluezbox.com>
            Oleksandr Tymoshenko <gonzo at bluezbox.com> writes:
:      Yesterday I ran into a "problem" with uart(4) on big-endian MIPS
: board. uart code treats registers as bytes and reads/writes them using
: bus_space_read_1/bus_space_write_1. To handle word-aligned registers we
: have regshft in uart_bas structure. It works for little-endian flags
: where lowest byte resides at uart_base + (regnum << regshft) address
: but for big endian targets actual data resides at
: uart_base + ((regnum + 1) << regshft) - 1.

That's not the problem.  The problem is that we're trying to do byte
accesses to word registers.  That's why we see a disconnect between
the addresses since we're reading the wrong byte.  also, we may be
getting lucky with this access, but many chips have issues when you
access word registers as bytes.

: One way to solve it is to increase uart_base when setting uart_bas,
: but it's not obvious and requires knowledge of uart(4) internals.
: I think better solution would be to take into account endianess
: when defining uart_regofs. Or if other BE devices have data in
: highest byte new field should be added to uart_bas (defaulted to 0)
: 
: Any thoughts?

The base problem here is:

uart.h:

#define	uart_getreg(bas, reg)		\
	bus_space_read_1((bas)->bst, (bas)->bsh, uart_regofs(bas, reg))
#define	uart_setreg(bas, reg, value)	\
	bus_space_write_1((bas)->bst, (bas)->bsh, uart_regofs(bas, reg), value)

These should be, for the platform you are using:

#define	uart_getreg(bas, reg)		\
	bus_space_read_4((bas)->bst, (bas)->bsh, uart_regofs(bas, reg))
#define	uart_setreg(bas, reg, value)	\
	bus_space_write_4((bas)->bst, (bas)->bsh, uart_regofs(bas, reg), value)

There's no easy way to swap these out, nor is there a way to have
variants for different kinds of hardware attached to the same machine
(the UART on the SoC will have different access patterns than the UART
on the modem on the PC Card that's plugged in, for example).  This is
a short-coming in the design of UART.  One that's relatively easy to
fix, mind you, and one that could easily be fixed.  There's so many
twists like this that it can be hard to anticipate them all.

The Octeon port basically copies uart_dev_ns8250.c and provides its
own set of accessors.  This is right from a accessing the hardware
correctly point of view, but a pita from a code reuse point of view.
Were it not for the other quirks in Cavium's serial ports, there'd be
little reason to go this route...

Warner


More information about the freebsd-hackers mailing list