Re: UIO not working on ppc405 onchip registers
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 ___ Linuxppc-dev mailing list Linuxppc-dev@ozlabs.org https://ozlabs.org/mailman/listinfo/linuxppc-dev
Re: UIO not working on ppc405 onchip registers
On Tuesday 22 July 2008, [EMAIL PROTECTED] wrote: > Hello Uwe, > > On Tuesday 22 July 2008, Uwe Kleine-König wrote: > > 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? > > Maybee, the emac0 (0xef600800) and emac1 (0xef600900) get mapped as well, > because AFAIK I have to map a whole pagesize (0x1000). Same problem without emac module loaded. Did anybody tried to reproduce the problem? Regards Markus ___ Linuxppc-dev mailing list Linuxppc-dev@ozlabs.org https://ozlabs.org/mailman/listinfo/linuxppc-dev
Re: UIO not working on ppc405 onchip registers
On Tue, 2008-07-22 at 09:48 +0200, [EMAIL PROTECTED] wrote: > On Tuesday 22 July 2008, Ben Nizette wrote: > > > As an aside, you sure you want to do this anyway? > > No ;) > > > > 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/ ___ Linuxppc-dev mailing list Linuxppc-dev@ozlabs.org https://ozlabs.org/mailman/listinfo/linuxppc-dev
Re: UIO not working on ppc405 onchip registers
Hello Markus, Markus Brunner wrote: > 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. > > diff -upNr linux-2.6.26/drivers/uio-orig/Kconfig > linux-2.6.26/drivers/uio/Kconfig > --- linux-2.6.26/drivers/uio-orig/Kconfig 2008-07-18 09:15:51.0 > +0200 > +++ linux-2.6.26/drivers/uio/Kconfig2008-07-18 09:16:18.0 +0200 > @@ -39,4 +39,12 @@ config UIO_SMX > > If you compile this as a module, it will be called uio_smx. > > +config UIO_GPIO > + tristate "Driver for PPC_4xx GPIO" > + depends on UIO > + default n > + help > + Driver for PPC_4xx GPIO Registers > + > endif This endif matches an "if UIO", so there is no need to depend on UIO explicitly. > diff -upNr linux-2.6.26/drivers/uio-orig/Makefile > linux-2.6.26/drivers/uio/Makefile > --- linux-2.6.26/drivers/uio-orig/Makefile 2008-07-18 09:27:18.0 > +0200 > +++ linux-2.6.26/drivers/uio/Makefile 2008-07-18 09:16:50.0 +0200 > @@ -1,3 +1,4 @@ > obj-$(CONFIG_UIO) += uio.o > obj-$(CONFIG_UIO_CIF) += uio_cif.o > obj-$(CONFIG_UIO_SMX) += uio_smx.o > +obj-$(CONFIG_UIO_GPIO) += uio_ppc_4xx-gpio.o > diff -upNr linux-2.6.26/drivers/uio-orig/uio-gpio.c > linux-2.6.26/drivers/uio/uio-gpio.c > --- linux-2.6.26/drivers/uio-orig/uio-gpio.c1970-01-01 01:00:00.0 > +0100 > +++ linux-2.6.26/drivers/uio/uio-gpio.c 2008-07-18 09:18:56.0 +0200 > @@ -0,0 +1,59 @@ > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +const unsigned long pin_mask( unsigned int pin) { return (0x8000 >> > (pin));} > + > +const char UIO_DEV[] = "/dev/uio0"; > +const unsigned int UIO_SIZE = 0x1000; > +const unsigned int UIO_ADDR = 0xef600700; > + > +const int or = 0; > +const int tcr = 1; > + > +const unsigned int gpio_pin = 0;/* What gpio pin do you want to > toggle? */ > + > +volatile unsigned long *gpio_regs; > + > +int main(int argc, char *argv[]) > +{ > + int uiofd = 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. > + if (uiofd < 0) > + return uiofd; > + > + unsigned long* map_addr = mmap(NULL, > + UIO_SIZE, > + PROT_READ | PROT_WRITE, > + MAP_SHARED, > + uiofd, > + 0); > + if (map_addr == ((unsigned long*) -1)) > + return -1; > [...] > diff -upNr linux-2.6.26/drivers/uio-orig/uio_ppc_4xx-gpio.c > linux-2.6.26/drivers/uio/uio_ppc_4xx-gpio.c > --- linux-2.6.26/drivers/uio-orig/uio_ppc_4xx-gpio.c1970-01-01 > 01:00:00.0 +0100 > +++ linux-2.6.26/drivers/uio/uio_ppc_4xx-gpio.c 2008-07-18 09:23:32.0 > +0200 > @@ -0,0 +1,74 @@ > +/* > + * simple UIO GPIO driver. > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License version 2 as > + * published by the Free Software Foundation. > + * > + */ > + > +#include > +#include > +#include > +#include > + > +#include > + > +static struct uio_info info = { > + .name = "uio_gpio", > + .version = "0.0.0", > + .irq = UIO_IRQ_NONE, > + .irq_flags = 0, > +.mem[0].addr = 0xef600700, > +.mem[0].size = 0x1000, > + .mem[0].memtype = UIO_MEM_PHYS, > +}; IIRC you should initialise the other mem members. > +static int __devinit uio_gpio_probe(struct device *dev) > +{ > + if (uio_register_device(dev, &info)){ > + printk(KERN_ERR "uio_gpio: uio_register_device failed\n"); > + return -ENODEV; > + } > + return 0; > +} > + > +static int uio_gpio_remove(struct device *dev) > +{ > + uio_unregister_device(&info); > + info.mem[0].addr = 0; > + info.mem[0].size = 0; > + return 0; > +} 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. > +static struct platform_device *u
Re: UIO not working on ppc405 onchip registers
Hey Markus, > > > > +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. ___ Linuxppc-dev mailing list Linuxppc-dev@ozlabs.org https://ozlabs.org/mailman/listinfo/linuxppc-dev
Re: UIO not working on ppc405 onchip registers
On Tuesday 22 July 2008, Ben Nizette wrote: > As an aside, you sure you want to do this anyway? No ;) > 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 ___ Linuxppc-dev mailing list Linuxppc-dev@ozlabs.org https://ozlabs.org/mailman/listinfo/linuxppc-dev
Re: UIO not working on ppc405 onchip registers
Hello Uwe, On Tuesday 22 July 2008, Uwe Kleine-König wrote: > 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? Maybee, the emac0 (0xef600800) and emac1 (0xef600900) get mapped as well, because AFAIK I have to map a whole pagesize (0x1000). > > + int uiofd = 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. The whole example was meant to be short. > > +static int uio_gpio_remove(struct device *dev) > > +{ > > + uio_unregister_device(&info); > > + info.mem[0].addr = 0; > > + info.mem[0].size = 0; > > + return 0; > > +} > > 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 region mapped. Markus ___ Linuxppc-dev mailing list Linuxppc-dev@ozlabs.org https://ozlabs.org/mailman/listinfo/linuxppc-dev
UIO not working on ppc405 onchip registers
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 --- linux-2.6.26/drivers/uio-orig/Kconfig 2008-07-18 09:15:51.0 +0200 +++ linux-2.6.26/drivers/uio/Kconfig2008-07-18 09:16:18.0 +0200 @@ -39,4 +39,12 @@ config UIO_SMX If you compile this as a module, it will be called uio_smx. +config UIO_GPIO + tristate "Driver for PPC_4xx GPIO" + depends on UIO + default n + help + Driver for PPC_4xx GPIO Registers + endif + diff -upNr linux-2.6.26/drivers/uio-orig/Makefile linux-2.6.26/drivers/uio/Makefile --- linux-2.6.26/drivers/uio-orig/Makefile 2008-07-18 09:27:18.0 +0200 +++ linux-2.6.26/drivers/uio/Makefile 2008-07-18 09:16:50.0 +0200 @@ -1,3 +1,4 @@ obj-$(CONFIG_UIO) += uio.o obj-$(CONFIG_UIO_CIF) += uio_cif.o obj-$(CONFIG_UIO_SMX) += uio_smx.o +obj-$(CONFIG_UIO_GPIO) += uio_ppc_4xx-gpio.o diff -upNr linux-2.6.26/drivers/uio-orig/uio-gpio.c linux-2.6.26/drivers/uio/uio-gpio.c --- linux-2.6.26/drivers/uio-orig/uio-gpio.c1970-01-01 01:00:00.0 +0100 +++ linux-2.6.26/drivers/uio/uio-gpio.c 2008-07-18 09:18:56.0 +0200 @@ -0,0 +1,59 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +const unsigned long pin_mask( unsigned int pin) { return (0x8000 >> (pin));} + +const char UIO_DEV[] = "/dev/uio0"; +const unsigned int UIO_SIZE = 0x1000; +const unsigned int UIO_ADDR = 0xef600700; + +const int or = 0; +const int tcr = 1; + +const unsigned int gpio_pin = 0;/* What gpio pin do you want to toggle? */ + +volatile unsigned long *gpio_regs; + +int main(int argc, char *argv[]) +{ + int uiofd = open(UIO_DEV,O_RDWR); + if (uiofd < 0) + return uiofd; + + unsigned long* map_addr = mmap(NULL, + UIO_SIZE, + PROT_READ | PROT_WRITE, + MAP_SHARED, + uiofd, + 0); + if (map_addr == ((unsigned long*) -1)) + return -1; +gpio_regs = (volatile unsigned long*) map_addr; + printf("Mapped %0lx bytes from %08lx to %08lx\n", UIO_SIZE, UIO_ADDR, (unsigned long)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]); + +} diff -upNr linux-2.6.26/drivers/uio-orig/uio_ppc_4xx-gpio.c linux-2.6.26/drivers/uio/uio_ppc_4xx-gpio.c --- linux-2.6.26/drivers/uio-orig/uio_ppc_4xx-gpio.c1970-01-01 01:00:00.0 +0100 +++ linux-2.6.26/drivers/uio/uio_ppc_4xx-gpio.c 2008-07-18 09:23:32.0 +0200 @@ -0,0 +1,74 @@ +/* + * simple UIO GPIO driver. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include +#include +#include +#include + +#include + +static struct uio_info info = { + .name = "uio_gpio", + .version = "0.0.0", + .irq = UIO_IRQ_NONE, + .irq_flags = 0, +