http://thread.gmane.org/gmane.linux.ports.arm.kernel/117626

From: Linus Walleij <linus.walleij <at> linaro.org>
Subject: On __raw_readl readl_relaxed and readl nocheinmal
Newsgroups: gmane.linux.ports.arm.kernel
Date: 2011-05-20 10:04:48 GMT (7 weeks, 6 days, 13 hours and 33 minutes ago)
Now I get thes questions about I/O accessors from all over the
place where I'm working. It seems some public clarification is needed...

My current understanding:

__raw_writel(a, reg1);
__raw_writel(b, reg2);

This does not guarantee that the write of b into reg2 is even done
after writing a into reg1 due to instruction reeordering.

writel_relaxed(a, reg1);
writel_relaxed(b, reg2);

This will insert a barrier() so we know that the CPU will execute the
write of a before the write of b. However it does not mandate that
reg2 is written with b before reg1 is written with a at the hardware
register level.

writel(a, reg1);
writel(b, reg2);

This actually pushes the value all the way through so that you know
that the values has landed in the hardware after each statement.

What we would like to know is the effect of things like this:

__raw_writel(a, reg1);
__raw_writel(b, reg1);
__raw_writel(c, reg1);

writel_relaxed(a, reg1);
writel_relaxed(b, reg1);
writel_relaxed(c, reg1);

My *guess* is that in the first case the pipeline may even remove
the write if a and b to reg1 since it's only caring about the end
result (insert the volatile story in
Documentation/volatile_considered_harmful.txt here)

The second case (writel_relaxed() to the same register) would
make sure that the writes actually happens in sequence,
but after the last statement it may take a while before the
actual hardware write happens.

And what about this:

writel_relaxed(a, reg1);
writel_relaxed(b, reg1);
writel(c, reg1);

I *think* this means that the writes will be done in sequence,
and after the last statement you know all writes have commenced.

So beat me up now.

Yours,
Linus Walleij

Reply via email to