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