Sorry, you need to enable JavaScript to visit this website.

Help with Linux UIO based driver a.k.a. what's the best simple way to drive a new IP core in PL from Linux?

4 posts / 0 new
jsgray's picture
Help with Linux UIO based driver a.k.a. what's the best simple way to drive a new IP core in PL from Linux?

My question pertains to Linux UserIO (UIO) based user mode device driver access to memory mapped PL devices.

I have Linaro Ubuntu Linux running on my ZedBoard. For starters I followed the directions here:

I have also built a new Zynq system config with just one peripheral (a simple counter) in PL -- no display controller etc. I am able to read and write that counter from a standalone C program.

I am also able to boot Ubuntu Linux on that config. To do so I modified and rebuilt my devicetree.dtb so it configures no (zero) PL based peripherals. Nevertheless it comes up nicely, network works, SD works, etc. It has no frame buffer / display but I can still get a GUI via remote desktop (by installing and running xrdp/xvnc). The nice thing about this set-up is I don't waste any PL on an extraneous display controller, etc. And I can travel and do GUI Zynq Linux development with just a laptop and the ZedBoard.

Running Linux, I am also able to talk to my counter peripheral directly, e.g. by opening /dev/mem, mmaping a view of memory on my counter's physical address, and reading and writing that. It works great. But it is hack. I hate opening /dev/mem. And it won't help when/if I start trying to send interrupts to my app.

Then I read about Linux UIO here:
That seems ideal. Then my Linux app would open /dev/uio0 (for example), mmap a view on it. And even wait for interrupts by reading from it.

UNfortunately I haven't been able to get UIO working. I edited my kernel configuration and enabled devices uio, uio_pdrv, uio_pdrv_genirq, and rebuilt it.

I also edited my devicetree .dts to add:
cnt0: cnt@7c800000 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "generic-uio", "uio", "uio_pdrv";
reg = <0x7c800000 0x1000>;

Then when I boot this system, I see
1. No uio device console message at boot time.
2. No /dev/uio0 (was I supposed to mknod it manually?)
3. /sys/class/uio exists, but is empty.
4. /proc/devices includes the uio device

I imagine my .dts is foobar but various tweaks of it do not improve the situation. I am going to dig into the kernel sources to see how the devicetree is processed but I was wondering if others out there:

1. Use UIO to write user-model device drivers?
2. Or prefer some other approach?
3. Is it as simple as rebuilding Linux kernel to add in the uio* drivers?
4. What does your DTS look like to enable UIO to a memory mapped device control register?
5. Do you have to mknod an entry for it in /dev/uio[0123] etc. or does that happen automagically?
6. Do you have to do anything to set up /sys/class/uio/* or does that also happen automagically?

Thank you for any pointers.

nightseas's picture
Well, I think the simplest

Well, I think the simplest way is using the ioremap fuction with a static device address (0x7C800000 in your design). That's what I do and it works.

trioflex's picture
I do not see in your

I do not see in your description that you have changed the linux kernel config and made a kernel rebuild. So naturally the UIO will not show up if you only edit dts file

jsgray's picture