uart and big-endian targets

M. Warner Losh imp at bsdimp.com
Tue Jan 20 13:18:30 PST 2009


In message: <20090120.133113.-1630673491.imp at bsdimp.com>
            "M. Warner Losh" <imp at bsdimp.com> writes:
: 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...

actually, the more I've thought about this, and chatted with folks
offline, I think the right way to fix this is in bus_space...

Warner



More information about the freebsd-hackers mailing list