[beagleboard] Re: GPIO - how to ?

Did test this way. But couldn't change the GPIOs.

I write a 0x2 to GPIO.SYSCONFIG and read back 0, which seems to be ok.
But in GPIO.OE I read a 0xfffffff (all Input), and can't change that value.

I also tried to mmap the area where the MUX bits are. But get a message:
"Mapped failed".

Mpfhhhh.

I was able to mmap the System Control Module's PADCONFS area by
mapping the entire SCM register space at 0x48002000 with a size of
0x1000 (4KB).
mmap() restricts the size and alignment of memory blocks in an
implementation-specific way.
Trying to mmap just the PADCONFS area at 0x48002030 failed for me
since it wasn't aligned to a 4KB boundary.

Hope this helps.

John Beetem wrote:

I was able to mmap the System Control Module's PADCONFS area by
mapping the entire SCM register space at 0x48002000 with a size of
0x1000 (4KB).
mmap() restricts the size and alignment of memory blocks in an
implementation-specific way.
Trying to mmap just the PADCONFS area at 0x48002030 failed for me
since it wasn't aligned to a 4KB boundary.

Indeed. Your addresses and sizes must be 4K-aligned on ARM.

b.g.

Yes that works fine, thanks
Although there is sometime strong delays and artefacts accessing
GPIOs.
My program does via the mmap somewhat like

set padconfig = 0x00040004 //GPIO mode
set outputenable = 0
set dataout or set_bits or clear_bits ...

But it really works only the second time I call it. Somehow
strange ...
Any idea about that?

Sorry, I don't know why it wouldn't work the first time. My only
direct experience is playing with the user LEDs. Even then, when I
turn on the user LEDs one of them only stays on until Ångström blinks
it. Fortunately, that seems to be the only artifact.

As Bill mentioned above, you do have to consider that other processes
may be accessing these same registers. That creates all sorts of
nasty situations. For example, if process A updates a peripheral
register by doing a read-modify-write, there is a tiny chance that
process B may interrupt A's read-modify-write and do its own read-
modify-write. Then when control returns to process A it completes its
read-modify-write overwriting the effect of process B. This sort of
bug occurs very infrequenty and is extremely hard to reproduce. The
solution is to suspend interrupts during the read-modify-write --
perhaps ARM has an instruction that does this atomically.

I totally doubt that's causing your problem, since it is a very low
probablility of occurrence.

Another common issue with device registers is making sure they're in
an uncacheable memory. I would hope that mmap() would take care of
this automatically. The kernel should know what can be cached and
what cannot, i.e., normal program instructions and data can be cached,
but the peripheral register area cannot be. This is actually
consistent with your symptoms, since the first writes may only update
data cache and the OMAP registers only get updated when the cache
flushes. I would be surprised if this is what's happening since the
kernel should set up the memory map properly, but it might be worth
checking the memory management tables if it's not too hard just to
rule it out definitively.

Using a well-written device driver should avoid these problems. In
general, if you're writing an application that will run under an OS
with other applications that you didn't write, you're best off using a
device driver so the OS can manage shared resources. If you're
writing what is essentially a stand-alone application and using Linux
as a temporary development tool, direct access to OMAP registers makes
the most sense

Another common consideration is the use of "volatile" in C programs.
Declaring a variable "volatile" tells the compiler that each use of
the variable in the program must result in an actual load or store
instruction, and that those loads and stores must use the exact
declared size of the variable. Otherwise the compiler is free to
optimize access to the variable, e.g., put it in a register and avoid
what the compiler considers to be unnecessary loads and stores.
"volatile" tells the compiler that the variable could change value at
any time and that all stores are signficant. Variables shared between
processes should usually be declared "volatile".

Sometimes the compiler will do the right thing even if you don't use
"volatile". But then when you change the compiler's optimization
options or update to a new compiler release, suddenly code that you
haven't looked at in years stops working. What fun!

John

John Beetem wrote:

Another common issue with device registers is making sure they're in
an uncacheable memory. I would hope that mmap() would take care of
this automatically.

Funny you should mention that. AT91 has had problems with that in the past, I
wonder if OMAP does too?

b.g.

Thanks for your details. I am working on a driver now.
Than I can use the
gpio_request(), gpio_direction_output(), gpio_set_value()
functions.
Unfortunatly the gpio_request doesn't set the padmux to mode4 (GPIO)
as I expected.
Even there seems to be no support in the recent kernel (mux.h) for
Omap35xx.
So my beginner question is:
what is the best way to address (read/write) registers of Omap (like
padconf) from kernel-space? I've seen that the max frequency of
toggling a GPIO pin via gpio_set_value() isn't quite exciting fast. So
guess I have to implent parts not via this kernel function but via
direct register access, maybe even in Assembler.

For now the best way is to use the kernel APIs to configure the PAD
config registers, I don't think we support dynamic configuration of
these pins, but you could do this in board file, the current Latest
GIT kernel does support these APIs, as you mentioned you have to
update the mux.h accordingly.

But, I think we should also support dynamic configuring of PAD registers

Regards,
Khasim

For me as a beginner "git" is a too big issue.
You are writing : use the kernel API to set - but that's exactly the
question - how does it works?
A very simple example would be fine.
For me even a static setting is fine. In board.h I couldn't find
somewhat like a default Padconf mapping,
at least I can't find that.
But nevertheless the question - how to access Padconf and other
registers
as simple a simple memory access from a driver - so from inside the
kernel space. A simple
memcopy(0x48xxxxxx,) does not work.

The same as for

  unsigned char *padconfaddr99 = 0x48002114;
  padconf_gpio = (IO_PAD_MUXMODE4 << IO_PAD_HIGH_SHIFT) +
IO_PAD_MUXMODE4;
  *padconfaddr99 = padconf_gpio;

Unable to handle kernel paging request at virtual address 48002114

same with
  writel(padconf_gpio, padconfaddr99);

I don't want to write to a virtual address, want to have the real
address.