On Sat, 21 Feb 2015, Robert P. J. Day wrote:
> > > has anyone else ever needed to do this? or is this some weird,
> > > one-off hack that perhaps applies *only* to some bizarre feature of
> > > this board?
> > My guess is that the peripherals attached to the internal bus
> > only undestand little endian, and the bus doesn't do byte swaps when
> > the core isn't configured for LE. I.e. the BE feature is only
> > implemented in the mips core and the rest was designed for LE only.
> ok, that makes sense ... so it's very likely a "issue with *this*
> particular board and setup" kind of thing. thanks.
It looks to me like either a platform setup or a driver bug, as for this
very purpose we have two sets of these access macros, one that preserves
the bit ordering (IOW the value accessed) and another that preserves the
byte ordering (but the value accessed may come out byte-swapped). The
former will usually be used for accessing MMIO registers of peripherals
and the latter for byte streams exchanged between a peripheral and host
memory via DMA. This is so that generic code (e.g. a PCI device driver
that will run on any processor or system it is thrown at) does not have to
be concerned about the actual host bus endianness.
The names of these macros reflect their usual purpose, and there's a
pass-through set of macros too that never byte-swaps, so you'll use:
* `readl'/`writel'/etc. -- to access MMIO, preserving the bit ordering,
* `__mem_readl'/`__mem_writel'/etc. -- to access DMA memory, preserving
the byte ordering,
* `__raw_readl'/`__raw_writel'/etc. -- to access data as it shows on the
bus it comes from or goes to.
Please note that there is only ever any difference between these accessors
if a platform has a bus whose endianness is fixed regardless of the host
For example PCI is fixed at the little endianness and therefore all these
macros pass data through unchanged on a little-endian host. When the host
bus is big-endian then `readl'/`writel' will byte-swap data unless byte
lane swapping already happens at the PCI host bridge. In that case it is
likely that `__mem_readl'/`__mem_writel' will have to swap data instead.
And then you'll use `__raw_readl'/`__raw_writel' to access host MMIO
registers that are never swapped, e.g. on-chip SOC registers, or host-side
registers of the PCI host bridge.
All this is arranged in a system-specific manner with the use of a set of
`*ioswab?' macros, that a platform has to define in `mangle-port.h' unless
it wants to use the defaults. See the existing examples for a reference.
There's a set of `__swizzle_addr_?' macros there too, for systems that
need to adjust the address accessed to account for byte lane swapping done
Overall it all is system dependent, and there are systems in existence
for example that have an alternative byte-lane swapping address space and
therefore for accesses that need to be swapped they can take advantage of
that feature and switch the address space rather than shuffling bytes, for
a small performance advantage. We don't use this feature at the moment
though; it would be most beneficial for string I/O where a single address
adjustment operation would do for the whole transfer whereas byte-swapping
has to be done for every individual piece of data transferred.
In any case it looks very likely to me that either a driver uses the
wrong set of macros to access a resource or the platform has failed to
define its `*ioswab*' macros correctly.
Feel free to let me know if you find anything of this unclear or have any