Changelog:
1.2.0 | 2003-11-12 | Removed 4801gpio.c from the tarball (it was not used at all) |
1.2.1 | 2003-11-27 | Bugfixes to reading error_led and gpio ports, thanks to Dave Johnson |
1.3.0 | 2004-01-25 | Added support for the voltage and temperature monitors on the 4801 Cleaned up proc handling Added drivertest program, to make sure all functions still work after a code change Reorganized the code so there's only one (somewhat bigger) module for 4801 and 45xx |
1.3.1 | 2004-01-26 | Since the previous release was not quite finished (but released to respond to an inquiry on the soekris-tech list) this release takes care of all open issues (documentation, test-program) Fixed bug with writing to /dev/gpio1 (4801 only) |
1.3.2 | 2004-02-24 | Fixed warning "unresolved symbol __number_of_pins", that occurred if the module was stripped Fixed (?) problem with MODVERSIONS enabled in the kernel Corrected JP5 description in 4801gpio.h |
Download: gpio-1.3.2.tar.gz
Here you can find a small driver to access the GPIO ports under linux. There are others available (especially a userland app which may serve your purpose better than my driver - you can find it in the soekris-tech-list archives, posted on 27 Feb 2003, the subject of the message is "Linux userland code for twiddling GPIO lines" - but note, this will only work for the net4501).
This driver is a kernel module, because the intended target platform does not allow userland applications to access to IO-ports (due to the grsecurity kernel patches).
For the driver to work on the net4801, you need at least BIOS release version 1.22 available here - the driver does not work with earlier versions of the BIOS.
Simply extract the archive to a directory of your choice, and then edit the makefile (sorry, creating an autoconf-setup for something as small as this sounds like overkill to me) so that the variable KERNELDIR points to the kernel source you want to compile the module against. Normally, this would be
/usr/src/linux-2.4/Note that the variable is commented out by default (since the environment I compile the modules in automatically sets this value as an environment variable).
Once you're done, simply type
makeand hopefully you'll end up with a set of modules.
Note: please make sure that you're using the same version of gcc used to compile the kernel (important if you're running Fedora core for example - on Fedora, one needs to
"export CC=gcc32"
before running make).
You'll now have the following .o files in the gpio-1.3.1 directory:
4501driver.o 4801driver.o gpio.o writelcd.o common.o common_writelcd.o
Of these, only 2 are actual modules (the other ones are temporary object files, created during the compile) - namely
gpio.o writelcd.o
The gpio.o file is the actual driver, the writelcd.o file is a simplistic LCD driver that will simply display "Booting..." on an HD44780 compatible LCD (see below).
The gpio.o module will work both on the Elan SC520 based Soekris boxes (namely on the net4501, net4511 and net4521) and the Geode SC1100 based net4801.
The GPIO drivers can be used in 3 different ways
This is the easiest to use (to set GPIO ports manually or via a shell script), but also the slowest method (I wouldn't want to drive an LCD using the proc filesystem). The driver registers 3 files in the proc filesystem:
To turn on the error LED:
echo 1 > /proc/driver/soekris_error_led
To turn off the error LED:
echo 0 > /proc/driver/soekris_error_led
To read the status of the error LED:
cat /proc/driver/soekris_error_led
To turn on GPIO5 and GPIO1:
echo 00100010 > /proc/driver/soekris_gpio
To turn on GPIO7 :
echo 10000000 > /proc/driver/soekris_gpio
To read the status of the GPIOs
cat /proc/driver/soekris_gpio
If a certain GPIO is set to input, writing a value to this GPIO will have no effect.
Since the net4801 has 12 GPIO ports, the usage of the proc interface is slightly different.
To turn on GPIO5 and GPIO1:
echo 000000100010 > /proc/driver/soekris_gpio
To turn on GPIO7 :
echo 000010000000 > /proc/driver/soekris_gpio
To turn on GPIO11:
echo 100000000000 > /proc/driver/soekris_gpio
To read the status of the GPIOs
cat /proc/driver/soekris_gpio
If a certain GPIO is set to input, writing a value to this GPIO will have no effect.
When loaded, the modules register a major number dynamically. This means that the modules do not have a fixed major number assigned to them, but rather use one that's assigned by the system.
After loading the module, you can find out which major number has been assigned with
cat /proc/devices
Creating the devices:
Once you know the major number that's been assigned to the driver (usually 254, but don't rely on it), you can create the corresponding device files with the following commands:
export major=254 mknod /dev/gpio0 c $major 0 mknod /dev/gpio1 c $major 1 mknod /dev/gpio254 c $major 254
Minor 0:
Controls GPIO ports 0 to 7. Each byte sent to/read from the device file represents a bit-mask for the 8 GPIO ports (bit 0 corresponds with GPIO0 and so on).
Minor 1:
Controls GPIO ports 0 to 11 (net4801 only). Each word sent to/read from the device file (low byte first) represents a bit-mask for the 12 GPIO ports (bit 0 corresponds with GPIO0 and so on).
Minor 254:
Controls the error LED. Sending a value of 0 turns the led off, sending anything else turns the LED on (the same applies for when data is read from the device).
Expects a pointer to an unsigned int. Sets/returns the direction of the given gpio ports according to the value given (bit=1 means output, bit=0 means input).
net4501:
Expects a pointer to an unsigned int. Sets/returns the value of the gpio ports 0 to 7.
net4801
Expects a pointer to an unsigned int. Sets/returns the value of the gpio ports 0 to 11.
The driver also implements some IOCTL calls from ppdev - mainly so that the GPIO ports could be used as a simple replacement for driving an LCD display (see below).
These don't do anything, but don't cause an error either
Data line direction for GPIO0-3: non-zero for input mode (note - this is reversed from the logic used in GPIORDDIRECTION and GPIOWRDIRECTION).
This is not "generic" at all, but very much hard-wired towards being able to use an HD44780 LCD on the GPIO pins (in 4-bit mode) and being able to do so using generic ppdev instructions
So, GPIO4-GPIO7 will _always_ be set to output after this call, only GPIO0-GPIO3 are changed
Reads/writes to the gpio0-7 (minor 0) or the error led (minor 254)
cat /proc/driver/soekris_tempShould show something like this:
Temp 0 0xcd 127 C Temp 1 0xcd 127 C Temp 2 0x81 46 CIt seems that Temp 0 and 1 are not connected (they always show 127 C) The first value in hex is the contents of the "Temperature Channel Configuration and Status Register". See the readme or the the PC87366 spec for the meaning of the contents of this register The second value is the temperature in Celsius
cat /proc/driver/soekris_voltageShould show something like this:
avi0 3.01 V avi1 2.04 V VCC 5.08 V VPWR 12.29 V avi4 2.54 V avi5 2.54 V avi6 0.00 V Vsb 3.33 V Vdd 3.35 V Vbat 3.01 V AVdd 3.33 V ts0 1.56 V ts1 1.58 V ts2 1.50 VThe mapping of the different values to avi0 and so on is taken from http://phk.freebsd.dk/soekris/env4801/ - until Soekris Engineering releases some official specifications.
Todo: add sample code/scripts (contributions welcome)
I use the driver described above to run an HD44780 compatible LCD connected to my soekris boxes. The software used to control the LCD is lcd4linux.
The wiring used is the 4-Bit wiring (since the net4501 doesn't have enough GPIO ports for anything else).
Do not connect the backlight pins to the Soekris 5V or 3.3V pins!
Sample config file for lcd4linux (this is what was used on the picture above):
Display HD44780 Port /dev/gpio0 Size 20x4 GPOs 0 # 4 Bit protocol/wiring Bits 4 Wire.RS "DB4" Wire.RW "DB5" Wire.ENABLE "DB6" Wire.GPO "GND" #--------------------------------------- # display config Row1 \040\040\040 %o %v \040\040&1 Row2 CPU %cb%%$r10cb Row3 Net %nm $R10nr+nw Row4 Load%l1 $r10cs+cb Row5 \040\040\040 %o %v \040\040&1 Row6 CPU %cb%% $r10cb Row7 Net %nm $R10nr+nw Row8 PPP %ti $R8ti+to %to Rows 8 Scroll 4 Turn 5000 Tick.Text 400 Tick.Bar 100 Tick.Icon 250 Tick.GPO 100 Overload 2.0 Icons 1 Icon1.Bitmap1 .....|.....|..... Icon1.Bitmap2 .*.*.|.*.*.|..... Icon1.Bitmap3 *****|*****|.*.*. Icon1.Bitmap4 *****|*****|.***. Icon1.Bitmap5 .***.|.***.|.***. Icon1.Bitmap6 .***.|.***.|..*.. Icon1.Bitmap7 ..*..|..*..|..... Icon1.Bitmap8 .....|.....|.....
The driver works well on my test-boxes - net4501 and net4801 running linux (Bering uClibc) with a 2.4.26 kernel, but it hasn't received any widespread testing yet (especially the functions that are not needed for controlling an LCD). So chances are that you will find some bugs when using the modules.
Error reports, suggestions and especially patches are greatly appreciated and should be sent to linux@hejl.de