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 endianness. 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 in hardware. 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 further questions. Maciej