Last Updated on Friday, 24 August 2012 16:40
How to use GPIO with Gumstix Overo.
Here is a small project that demonstrates some gpio access within a kernel module - overo-irqlat.
The motivation for the project was to measure the latency in the gpio sub-system of a Linux OMAP3 kernel.
There are two tests in the code.
Both tests require an oscilloscope to monitor the timings, but you can just look at the code to get an example of how to use gpio in your own module. If you have an oscope, you might want to go ahead and do the measurements yourself. The README for the project explains where to measure.
Another good place to look for gpio code is in the Overo board file arch/arm/mach-omap2/board-overo.c
You can control GPIO pins from userspace like so
root@overo# echo 146 > /sys/class/gpio/export
If you have an expansion card with a 40 pin header, then this will be controlling pin 27. You can use pin 1 for a ground. Schematics and pin-outs for the Gumstix expansion boards can be found here.
Now for some details.
See the kernel docs gpio.txt for an overview of gpio and the userspace sysfs interface. The "Sysfs Interface for Userspace (OPTIONAL)" section near the end discusses the userspace implementation.
See the OMAP35X Technical Reference Manual Section 7.6.3 PADCONFS Register Description and Table 7.5 Core Control Module PadConf Register Field in Section 22.214.171.124 Pad Multiplexing Register Fields for identifying the possible MUX configuration for each GPIO.
Then see the U-Boot source code, board/overo/overo.h for how the pins on the Overo are actually being muxed. See include/asm-arm/arch-omap3/mux.h in the U-Boot tree for the definitions used in overo.h. The pins in mux mode M4 are already configured for GPIO.
Currently most of the GPIO multiplexing for the Overo's is being done by the bootloader U-Boot, so the conventional way to modify the pin muxing is to edit board/overo/overo.h in the U-Boot source and rebuild it. I have some instructions for that here - Gumstix U-Boot development.
You can also change the pin mux configuration from within Linux. One simple approach is to do it from userspace accessing /dev/mem. A program devmem2 is part of the omap3-console-image and will work. See the examples below.
If you are writing your own kernel module, you can also read/write the PADCONF registers the way you normally would after an ioremap.
Third, there is a mux framework in the kernel now that gives you some additional utility functions to change the pin muxing during initialization. There are some examples in the latest overo board file arch/arm/mach-omap2/ board-overo.c. Search for omap_mux_init_signal(). I believe you can only use this framework during initialization so it wouldn't work for an external loadable module. I'm not sure about this and need to check.
Just because pins are configured as GPIO in u-boot, doesn't necessarily mean you can use them. If you look at /sys/class/gpio on a default Overo, you'll get something like this.
root@overo:~# ls /sys/class/gpio
The reason you see some GPIO already exported is because the linux code in arch/arm/mach-omap2/board-overo.c is explicitly exporting these pins for another use. Whether the pins are required depends on the expansion board you are using. The kernel also uses pins configured as GPIO that it doesn't export. These depend on the kernel drivers included which is specified in the kernel configuration.
To be more explicit, look inside board-overo.c, you'll see these definitions
#define OVERO_GPIO_BT_XGATE 15
Follow their usage inside the file and you will be able to explain the /sys/class/gpio output you see above.
Any of the pins may have been configured as input-only or output-only when they were mux'd or when they were explicitly exported by the kernel. In those cases you won't be able to change the direction from userspace.
Remember, the logic is 1.8v.
Here's a few GPIO on the expansion header you can use immediately from userspace without any u-boot or kernel changes.
Pin 4 - gpio114
Pin 19 - gpio170
Pin 27 - gpio146
Pin 28 - gpio145
There are some addition GPIO exposed on the Gumstix LCD capable expansion boards.
For kernels prior to 2.6.36 or if you disable the 'leds-gpio' or 'gpio-keys' platform drivers in your kernel, you can use these pins in the following fashion.
LED D2 - gpio21
Switch - gpio14
For kernels 2.6.36 and greater, there are additional drivers controlling the LED and button pins. Instructions for their use can be found here Button and LED control on Gumstix LCD boards.
If you aren't using SPI bus 1, then are 5 SPI pins on the 40-pin expansion header that you could re-purpose for GPIO. The SPI bus is used by the touchscreen controller, but if you aren't using a touchscreen then these pins are available.
Pin 3 - gpio171(spi1_clk)
The first step is to find the appropriate PADCONF register address for each gpio from Table 7.5 of the TRM. Pay attention to whether it is the low or high order 16 bits for each gpio. You should find these values.
gpio171 : 0x4800 21C8
Using devmem2, here is how you could read the current PADCONF value for what could be gpio171
root@overo# devmem2 0x480021c8 h
Which corresponds to a mux value of (IEN | PTD | DIS | M0) using the U-Boot mux.h definitions. Mux mode 0 for this pin is the spi1_clk configuration found by looking in Table 7.5 of the TRM.
To reconfigure pin 3 to be gpio171, as input or output with inputs pulled low, write 0x010C to the controlling PADCONF register. This would correspond to (IEN | PTD | EN | M4). The bit fields are defined in the TRM Section 7.6.3.
root@overo# devmem2 0x480021c8 h 0x10c
Now you can export and configure this gpio171 from userspace like the example with gpio146 at the beginning.
If you want this multiplexing to be permanent, then you would modify the U-Boot file board/overo/overo.h and rebuild U-Boot. If you are using OE, then you'll want to generate a patch file to be used in the u-boot-omap3 recipe. Instructions for doing that are here.
The Beagleboard guide to OMAP3 pin muxing - BeagleBoardPinMux
I wrote a small kernel module to probe the PADCONF registers of a running system. It's just for debugging but it will show you the pin mux state of any gpio pin you pass it. The project is here on github - omap3-mux.