From: Markus Brunner <hidden> Date: 2008-07-21 19:46:00
Hi,
I'm unable to get UIO working on the ppc405ep onchip registers (e.g. gpio/iic)
however it's working fine on peripherals.
It seems to me to be a problem with UIO on powerpc, because if I change the
address (and nothing more) to point to a external FPGA it's working fine.
I also tried the generic uio_pdrv which had the same problems.
Sometimes I get a "bus error" sometimes it only produces wrong results.
The "bus error" occurred when not a full 32 bit register was read (e.g. only a
byte of it), but I'm not sure if it doesn't occur for other reasons as well.
Here is a simple example against 2.6.26. It should toggle the GPIO pin 0 on
ppc405ep, but can be changed easily to work on other ppc variants.
Can anyone reproduce this problem, did anyone already succeed in writing a UIO
driver for the onchip registers? How can I fix this?
Might this be something like commit c9698d6b1a90929e427a165bd8283f803f57d9bd which
added pgprot_noncached() to UIO mmap code to get it work on ppc?
Regards
Markus
diff -upNr linux-2.6.26/drivers/uio-orig/Kconfig linux-2.6.26/drivers/uio/Kconfig
@@ -0,0 +1,59 @@+#include<sys/types.h>+#include<sys/time.h>+#include<sys/stat.h>+#include<sys/mman.h>+#include<fcntl.h>+#include<unistd.h>+#include<stdio.h>+#include<stdlib.h>++constunsignedlongpin_mask(unsignedintpin){return(0x80000000>>(pin));}++constcharUIO_DEV[]="/dev/uio0";+constunsignedintUIO_SIZE=0x1000;+constunsignedintUIO_ADDR=0xef600700;++constintor=0;+constinttcr=1;++constunsignedintgpio_pin=0;/* What gpio pin do you want to toggle? */++volatileunsignedlong*gpio_regs;++intmain(intargc,char*argv[])+{+intuiofd=open(UIO_DEV,O_RDWR);+if(uiofd<0)+returnuiofd;++unsignedlong*map_addr=mmap(NULL,+UIO_SIZE,+PROT_READ|PROT_WRITE,+MAP_SHARED,+uiofd,+0);+if(map_addr==((unsignedlong*)-1))+return-1;+gpio_regs=(volatileunsignedlong*)map_addr;+printf("Mapped %0lx bytes from %08lx to %08lx\n",UIO_SIZE,UIO_ADDR,(unsignedlong)map_addr);++printf("TCR = %08lx\n",gpio_regs[tcr]);+printf("TCR = %08lx\n",gpio_regs[tcr]);+printf("setting TCR\n");+gpio_regs[tcr]=gpio_regs[tcr]|pin_mask(gpio_pin);// set tcr for pin to 1+printf("TCR = %08lx\n",gpio_regs[tcr]);+printf("TCR = %08lx\n",gpio_regs[tcr]);++printf("OR = %08lx\n",gpio_regs[or]);+printf("OR = %08lx\n",gpio_regs[or]);+printf("setting OR\n");+gpio_regs[or]=gpio_regs[or]|pin_mask(gpio_pin);// set tcr for pin to 1+printf("OR = %08lx\n",gpio_regs[or]);+printf("OR = %08lx\n",gpio_regs[or]);+sleep(3);+printf("setting OR\n");+gpio_regs[or]=gpio_regs[or]&~pin_mask(gpio_pin);// set tcr for pin to 0+printf("OR = %08lx\n",gpio_regs[or]);+printf("OR = %08lx\n",gpio_regs[or]);++}
I'm unable to get UIO working on the ppc405ep onchip registers (e.g. gpio/iic)
however it's working fine on peripherals.
I don't know powerpc in general nor ppc405ep in detail but IIRC arm has
problems if some memory is mapped twice. Might this be the problem
here?
It seems to me to be a problem with UIO on powerpc, because if I change the
address (and nothing more) to point to a external FPGA it's working fine.
I also tried the generic uio_pdrv which had the same problems.
Sometimes I get a "bus error" sometimes it only produces wrong results.
The "bus error" occurred when not a full 32 bit register was read (e.g. only a
byte of it), but I'm not sure if it doesn't occur for other reasons as well.
Well, if this is a 32bit memory mapped device and you do a non-32 bit
access strage things can happen.
@@ -0,0 +1,59 @@+#include<sys/types.h>+#include<sys/time.h>+#include<sys/stat.h>+#include<sys/mman.h>+#include<fcntl.h>+#include<unistd.h>+#include<stdio.h>+#include<stdlib.h>++constunsignedlongpin_mask(unsignedintpin){return(0x80000000>>(pin));}++constcharUIO_DEV[]="/dev/uio0";+constunsignedintUIO_SIZE=0x1000;+constunsignedintUIO_ADDR=0xef600700;++constintor=0;+constinttcr=1;++constunsignedintgpio_pin=0;/* What gpio pin do you want to toggle? */++volatileunsignedlong*gpio_regs;++intmain(intargc,char*argv[])+{+intuiofd=open(UIO_DEV,O_RDWR);
For debugging this is OK, in the final application you should add some
tests. Check the UIO documentation for the details.
Are you sure that overwriting info.mem[0].addr is a good idea? Then
unbinding the platform device and rebinding it fails to do the right
thing for sure.
The header says this is GPL v2. So you should use "GPL v2" here, too.
Best regards
Uwe
--
Uwe Kleine-König, Software Engineer
Digi International GmbH Branch Breisach, Küferstrasse 8, 79206 Breisach, Germany
Tax: 315/5781/0242 / VAT: DE153662976 / Reg. Amtsgericht Dortmund HRB 13962
From: Ben Nizette <hidden> Date: 2008-07-22 06:42:57
Hey Markus,
quoted
+config UIO_GPIO
+ tristate "Driver for PPC_4xx GPIO"
As an aside, you sure you want to do this anyway? I'd suggest that you
just do a gpio chip driver for this, tie it in to gpiolib and use the
gpiolib user interface (which IIRC has only made it as far as -mm but is
on the way up). This gives kernel internals nice access to the pins as
well through the standard gpio framework.
Thanks :-)
--Ben.
Are you sure that overwriting info.mem[0].addr is a good idea? Then
unbinding the platform device and rebinding it fails to do the right
thing for sure.
This was stolen from uio_dummy. So this might become a common error :(
Thanks a lot for your comments, I will try to get an exclusive memory regio=
n=20
mapped.
Markus
I'd suggest that you
just do a gpio chip driver for this, tie it in to gpiolib and use the
gpiolib user interface (which IIRC has only made it as far as -mm but is
on the way up). This gives kernel internals nice access to the pins as
well through the standard gpio framework.
This was just an example to make it others easier to reproduce my problem. My
goal is to have a soft spi driver in userspace, which would probably be
slower if it uses gpiolib. This driver is integrated in the application I
want to port to Linux.
Thanks
Markus
From: Ben Nizette <hidden> Date: 2008-07-22 07:52:58
On Tue, 2008-07-22 at 09:48 +0200, super.firetwister@googlemail.com
wrote:
On Tuesday 22 July 2008, Ben Nizette wrote:
quoted
As an aside, you sure you want to do this anyway?
No ;)
quoted
I'd suggest that you
just do a gpio chip driver for this, tie it in to gpiolib and use the
gpiolib user interface (which IIRC has only made it as far as -mm but is
on the way up). This gives kernel internals nice access to the pins as
well through the standard gpio framework.
This was just an example to make it others easier to reproduce my problem. My
goal is to have a soft spi driver in userspace, which would probably be
slower if it uses gpiolib. This driver is integrated in the application I
want to port to Linux.
Ah right, cool. I donno what the speed would be like, but both David
Brownell and Michael Buesch both have spi-over-gpio patches floating
around (eg [1]). That, plus the spidev interface, might at least be
worth a try..?
But I'll let you get back to solving the UIO problem at hand :-D
--Ben.
[1] http://lwn.net/Articles/290066/
From: Markus Brunner <hidden> Date: 2008-09-05 06:09:14
On Tuesday 22 July 2008, Ben Nizette wrote:
But I'll let you get back to solving the UIO problem at hand :-D
I already surrendered and created (hacked) a read/write driver, which let me
use the old userspace drivers I'm trying to port (with some changes of
course). This was way faster than understanding all the involved APIs and
creating glue code between them. And the amount of time it needs was easy to
estimate.
However accidently I ran over the "old school" userland mmap code
with /dev/mem. I already knew mapping with /dev/mem is possible but I haven't
thought this could make a difference.
http://ozlabs.org/pipermail/linuxppc-embedded/2006-August/023811.html
Also I was wrong with my assumption that uio worked well on the peripherals.
It worked (very) well on the leds, just to fool me!!! But it returned crap on
some version registers.
With a working and a non working version of mmap it should be rather easy to
trace this bug. Unfortunately I was already short of time before running into
this (and other) problems and it didn't get any better.
So I would need some help from someone with more experience to fix this.
Any instructions?
Markus