2001-07-03 00:23:20

by David T Eger

[permalink] [raw]
Subject: readl() / writel() on PowerPC


I have been working on a driver for a PowerPC PCI card/framebuffer device,
and noticed that the standard readl() and writel() for this platform to
byte swapping, since PowerPC runs big-endian. However, at least for my
hardware it's *really* not needed, and should just do a regular load
store, as is done for CONFIG_APUS. Looking at another driver
(drivers/char/bttv.h) I notice that Mr. Metzler redefines his read and
write routines for PowerPC as well to do simple loads and stores to IO
regions.

Am I missing something? Is there some reason that readl() and
writel() should byte-swap by default?



2001-07-03 00:54:36

by David Schleef

[permalink] [raw]
Subject: Re: readl() / writel() on PowerPC

On Mon, Jul 02, 2001 at 08:22:55PM -0400, David T Eger wrote:
>
> I have been working on a driver for a PowerPC PCI card/framebuffer device,
> and noticed that the standard readl() and writel() for this platform to
> byte swapping, since PowerPC runs big-endian. However, at least for my
> hardware it's *really* not needed, and should just do a regular load
> store, as is done for CONFIG_APUS. Looking at another driver
> (drivers/char/bttv.h) I notice that Mr. Metzler redefines his read and
> write routines for PowerPC as well to do simple loads and stores to IO
> regions.


I believe you are looking for __raw_readl(), __raw_writel().



dave...

2001-07-03 02:39:51

by James Simmons

[permalink] [raw]
Subject: Re: readl() / writel() on PowerPC


> I have been working on a driver for a PowerPC PCI card/framebuffer device,
> and noticed that the standard readl() and writel() for this platform to
> byte swapping, since PowerPC runs big-endian. However, at least for my
> hardware it's *really* not needed, and should just do a regular load
> store, as is done for CONFIG_APUS. Looking at another driver
> (drivers/char/bttv.h) I notice that Mr. Metzler redefines his read and
> write routines for PowerPC as well to do simple loads and stores to IO
> regions.
>
> Am I missing something? Is there some reason that readl() and
> writel() should byte-swap by default?

Use the fb_writeX/fb_readX functions in fbcon.h. They take care of these
issues.

P.S
Watchout for userland programs. You can NOT use memset on the
framebuffer on PPC due to caching issues. Use have to use tricks similar
to what is done in fbcon.h with fb_memset.


2001-07-04 07:53:47

by Paul Mackerras

[permalink] [raw]
Subject: Re: readl() / writel() on PowerPC

David T Eger writes:

> Am I missing something? Is there some reason that readl() and
> writel() should byte-swap by default?

readl()/writel() are defined to access PCI memory space in units of 32
bits. PCI is by definition little-endian, PowerPC is (natively at
least) big-endian, hence the byte-swap. Same for inl/outl etc., but
not insl/outsl - they don't swap because they are typically used for
transferring arrays of bytes, just doing it 4 bytes at a time (2 at a
time for insw/outsw).

You can use __raw_readl/__raw_writel if you don't want byte-swapping,
but they also don't give you any barriers. Thus if you do

__raw_writel(v, addr);
x = __raw_readl(addr);

it is quite possible for the read to hit the device before the write.
If you want to prevent that you need to put an iobarrier_rw() call in
between the read and the write. You don't need a barrier between
successive writes unless you want to prevent any potential
store-gathering from happening, because PowerPC's don't reorder writes
to I/O regions.

Paul.