modifying GPIO drivers 'leds' and 'buttons'

Nicolas Briand
Hello All,    [precedent post = 'GPIO driver']

To use mini2440 to interface with real world, I intend using all GPIO's
pins available on mini2440 CON4 connector.

1) Available IO on mini2440, Side effects/Conflicts
The following IOs are available on CON4 connector:
GPB[0..1], GPE[11,13..15],GPF[0..6], GPG[0..3,5..7,9..11],GPH[9..10]
- The leds device handles GPIO pins GPB[5..8].
- The buttons device handles GPIO pins GPG[0,3,5..7,11].
- All others GPIO pins are used to interface TSP, LCDDATA, LCDCTRL, UART,
SDIO, NANDCTRL.
Is there risks of side effects or conflicts using GPIO free bits available
on CON4, the way 'leds' driver does ?

2) modifying leds driver using include/mach/regs-gpio.h 
leds driver source code in linux-2.6.29/drivers/char/mini2440_leds.c ,
refers to /arch/arm/mach-s3c2410/include/mach/regs-gpio.h where all GPIO's
IO port are defined.
Does setting led_table[] and led_cfg_tabl[] arrays in mini2440_leds.c with
appropriate new GPIO pins references from regs-gpio.h allows to handle
extra GPIO pins available on CON4 ? 
Is modifying leds driver that simple ? 
:-( beside compiling and rebuilding the kernel)

3) Camera interface
The Camera IF connector CON20 gives access to GPIO GPE[[14,15], GPG[12],
GPJ[0..12]. 
Does anybody develop a device driver to fully handle GPJ port ?
Is there conflict with the BIOS using CON20 for private use ?

Thanks for Help-Best Regards
-nico-

davef
Would be interested in the outcomes.  Working out how to drive GPIO has
been the main focus of my learning experience on this platform.

My direction was to use 2.6.30.5, or whatever is the most recent, and just
compile that.  The file on buserrors site seems to enable this
functionality (sys/class/gpio?)

Just out of interest where is mini2440_leds.c?

Good luck

Dave

Yossarian
I also want to use as many GPIOs as possible.

My linux 2.6.29 build only supports up to GPIOG
in the /sys/class/gpio so I don't know how to
access GPIOH and GPIOJ.

Has anybody figured out anything useful?

davef
I don't see any sys/class/gpio on my factory build of 2.6.29

My understanding is that you need one of the later kernels (which have gpio
enabled) or rebuild 2.6.29 with gpio enabled.

Your request prompted me to search for mini2440_led.c as mentioned in a
previous post.  I found a Mini2440Essentials.pdf produced by Industrial
ARMworks and I see there is a
<Linux&#8208;2.6.29/drivers/char/mini2440_leds.c>, just where is it located
is still a mystery.  Can't find it on the factory DVD. Perhaps addahammer
include it on their distribution.

I am still working on this, just real slowly.

Good luck and report back if you find out.

eduardo
Hi guys,

To see sys/class/gpio Iīd to recompile my kernel.
So, I just followed the steps described on micro2440 user manual. Itīs in
chinese, so use the google translator. 
Read chapters 5, 6 and 7. Itīs all described there.

Davef, try to download other kernel source for mini.

I modified the linux-2.6.29/drivers/char/mini2440_leds.c to a
"mini2440_gpio". Compiled as a module (dont know if this is rigth) and put
it into my mini2440.
But now I'll try to enable the /dev/gpio device to use the gpio pins.
I dont have any idea how to do that...

Should i use /dev/leds, /dev/buttons and others devices to use the gpio
pins?
Or someone know if there's a way to create this damn /dev/gpio?

best regards

eduardo
davef, 
there is no sys/class/gpio on factory build... you will have to recompile
the kernel.

Patrick Robin
You can also use the GPIOs directly by writing to the control and data
registers for the various ports/ios.

If some ar einterested I can post an example.

Patrick

davef
Patrick,

An example is always welcomed! I assume this method directly accesses the
kernel.

As a beginner to the ARM/Linux world I was told it was safer working with 
sys/class/gpio, however how much can go wrong?

Thanks,
Dave

JazzD
An explanation on the ADC ports would be nice too, the adc driver in the
kernel only gives you access to ONE pin, what is this?! Any Ideas getting
to read every adc channel?

Patrick Robin
Much can go wrong by writing to the ports directly.

Reading is no problem. When writing, you have to make sure you are not
corrupting other pins in the same register. In some cases, it may be
impossible without a driver. It depends what else is shared/used in that 32
bit IO register.

Patrick

Patrick Robin
"An explanation on the ADC ports would be nice too, the adc driver in the
kernel only gives you access to ONE pin, what is this?! Any Ideas getting
to read every adc channel?"

Look at the user guide for the processor. That user guide is on the DVD and
describes all IOs as well as their register addresses and functions.

you can memmap the register to user space and read it

Patrick Robin

Patrick Robin
This code will read the LED register adress (0x56000014) and print it. Same
code can be used to read any register. Register addresses are described in
the processor user guide on the DVD

Patrick


#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <signal.h>
#include <fcntl.h>
#include <ctype.h>
#include <termios.h>
#include <sys/types.h>
#include <sys/mman.h>
  
#define FATAL do { fprintf(stderr, "Error at line %d, file %s (%d) [%s]\n",
\
  __LINE__, __FILE__, errno, strerror(errno)); exit(1); } while(0)
 
#define MAP_SIZE 4096UL
#define MAP_MASK (MAP_SIZE - 1)

int main(int argc, char **argv) {
    int fd;
    void *map_base, *virt_addr; 
  unsigned long read_result, writeval;
  off_t target,control;
  int access_type = 'w';
  
  control=0x56000014;
  
  
    if((fd = open("/dev/mem", O_RDWR | O_SYNC)) == -1) FATAL;
    printf("/dev/mem opened.\n"); 
    fflush(stdout);
    
    /* Map one page */
    map_base = mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd,
control & ~MAP_MASK);
    if(map_base == (void *) -1) FATAL;
    printf("Memory mapped at address %p.\n", map_base); 
    fflush(stdout);
    
    virt_addr = map_base + (control & MAP_MASK);
    switch(access_type) {
    case 'b':
      read_result = *((unsigned char *) virt_addr);
      break;
    case 'h':
      read_result = *((unsigned short *) virt_addr);
      break;
    case 'w':
      read_result = *((unsigned long *) virt_addr);
      break;
    default:
      fprintf(stderr, "Illegal data type '%c'.\n", access_type);
      exit(2);
  }
    printf("Value at address 0x%X (%p): 0x%X\n", control, virt_addr,
read_result); 
    fflush(stdout);
   
    if(munmap(map_base, MAP_SIZE) == -1) FATAL;
    close(fd);
    return 0;
}

Patrick Robin
Processor user manual is on DVD in Data Sheets/S3C2440.pdf

Tom
It's also on the download site:
http://www.friendlyarm.net/downloads#datasheets

davef
Patrick,

Thank you for the example.  My comment, "how much can go wrong?" was a bit
"tougue-in-cheek".  I was told direct access could be problematic.

Being able to read them using your example will be an interesting exercise.

Cheers,
Dave

Yossarian
I was able to compile 2.6.29 with the GPIO enabled.

However, i still don't see entries in /sys/class/gpio
for GPIOH and GPIOJ.

It stops at gpiochip192, which is GPIOG.

I was reading a little code and found that there
isn't a GPIOJ defined in regs-gpio.h

linux-2.6.29/arch/arm/mach-s3c2410/include/mach/regs-gpio.h

There's a cryptic comment regarding GPIOJ but I don't get it.

/* The S3C2412 and S3C2413 move the GPJ register set to after
 * GPH, which means all registers after 0x80 are now offset by 0x10
 * for the 2412/2413 from the 2410/2440/2442
*/

Also, in gpiolib.c, there are only entries up to GPIOG
in the array: s3c24xx_gpios.

Maybe I'll try adding in the GPIOH entry but how will I get
GPIOJ to work?

eduardo
Yossarian, 

Take a look at ../include/mach/regs-gpioj.h file. 
Hope this help you.

regards

Yossarian
I was able to get the GPIOH registers
by altering gpiolib.c and adding
extra array elements.

It turns out that GPIOG also had to be
slightly altered to add a couple of
gpios.

I saw the regs-gpioj.h file (thanks, eduardo!)
but adding the GPIOJ to the array didn't
add anything to the /sys/class/gpio
directory.

So now it seems that I can access all of the
GPIOs available on the board except 
GPIOJ (which is 13 pins on the camera connector)
through the /sys/class/gpio.

I haven't noticed any side effects yet.  :)

mmm
Can anyone post a example to use the gpio pins?

eduardo
dear mmm,

Look for s3c2410_gpio_getpin, s3c2410_gpio_setpin and s3c2410_gpio_cfgpin
functions.
Download the User Manual (only chinese yet, but a google translator will
help you) and read the chapter 7. The other chapters will help you too.
You will have to recompile your kernel and add a new driver to use these
functions.


Yossarian, 

Now Im mapping the gpio pins to know which can i use for input/output. If
you have something like this please post here. :D
My driver support gpioj read/write (I created an array with mapping
constants), but i didnt try to set values to it yet.

regards

Vikas
dear eduardo,

Please can you post how did you make your driver support gpioj?

I found following two gpiolib.c files.  Which one to use?

-rw-r--r-- 1 kailas src  3322 2009-03-24 04:42
./arch/arm/plat-s3c24xx/gpiolib.c
-rw-r--r-- 1 kailas src 31701 2009-03-24 04:42 ./drivers/gpio/gpiolib.c

I guess I have to modify the first one, but not sure what to modify :(

eduardo
Dear Vikas,

I based my driver on two files:

eduardo@eduardo-desktop:/opt/FriendlyARM/mini2440/linux-2.6.29/arch/arm/mach-s3c
2410/include/mach$
ls -la | grep regs-gpio
-rw-r--r-- 1 root root 42539 2009-03-23 20:12 regs-gpio.h
-rw-r--r-- 1 root root  3924 2009-03-23 20:12 regs-gpioj.h
eduardo@eduardo-desktop:/opt/FriendlyARM/mini2440/linux-2.6.29/arch/arm/mach-s3c
2410/include/mach$


I built a new device driver using the gpio map available on these files.
My new driver is located at:
eduardo@eduardo-desktop:/opt/FriendlyARM/mini2440/linux-2.6.29/drivers/char$


You will have to use s3c2410_gpio_getpin, s3c2410_gpio_setpin and
s3c2410_gpio_cfgpin functions.
Take a look at mini2440_buttons.c, i built something like that, but using
the functions above.
To build your own kernel with the new driver, please read the chapter 7 of
micro 2440 user manual (if you dont know chinese, use google translator).


regards

Vikas
Hi eduardo,

I wrote something similar to mini2440_leds.  I am trying to set GPJ0-GPJ12
as output lines.  After setting 8-9 lines, the board hangs.  I hv written
kernel module for this.

would you be able to share your code, (only if you are okay with sharing)?

Vikas
oh my mistake,

I had changed BANKJ address by mistake and that is why it was hanging.

Harihar
Hi, 
i compiled the the kernel with gpio support, but in the /sys/class/gpio/
directory i am getting only these entries as show below....


[root@FriendlyARM gpio]# ls
export       gpiochip128  gpiochip192  gpiochip32   gpiochip96
gpiochip0    gpiochip160  gpiochip224  gpiochip64   unexport


But these are only the base port gpio's, i want to use all the left gpio's
like GPB[0..1], GPE[11,13..15],GPF[0..6], GPG[0..3,5..7,9..11],GPH[9..10]
etc...

can anybody tell me the procedure to get all the GPIO's working. Which
files are to be changed.

I am using micro2440. its not mini2440 board which is having 34 pin
connector. my board is having 56 pin connector.

please help me out.

Thanks

eduardo
Hi Harihar,

Please read my post above.

regards

Harihar
Hi endurdo,

Thanks for the reply.

I gone through the files mentioned in the post. Can you give me example
sample code of how and where to put changes so that other GPIO,s get
enabled for me.

Thanks

Harihar
Hi,

By changing the array i am getting The H port, but still in the
/sys/class/gpio/ there is no entry for J port.

it stops at 224.

I gone through all the related file but unable to figure out.

Please help me to get out of these problem.

Thanks

Harihar
Hi All,

can anyone help me to get GPIOJ enabled.

I tried all the mentioned file.

Can any one tell me where exactly make the changes and in which file.

Thanks

rabut
can anyone tell me up : if i am using the GPIO for I/O in each sec will the
flash be having any problem as the /sys/class/gpio/gpioxxx/value is being
written each time in flash & flash has a limited write cycles as I have
configured the J port now for GPIO but will it work for long i am worried
or will i hv to implement pipe if so how to do that

mgdaubo
Hi,
I have a question same as rabut.
Use fopen() and fwrite() to access file in /sys/class/gpio.. , my
application will write to /sys/class/gpio/gpioxxx/value about 10 times a
second. So is there any problem when running for long time?

miniarm
@Patric,

Thanks for the example, I am also interested to access gpio pin directly
from the userspace.

Thanks & Regards,
miniarm

Juergen Beisert
mgdaubo,

everything in 'sys/' is a so called 'virtual filesystem' (refer 'sysfs').
It only exist in the RAM of your target. So changing anything in
"/sys/class/gpio/gpioxxx/value" does not touch your flash.

asha
hey 
cn smeby xplain me...
how to get sys/class/gpio??its not present in my tiny6410 android
m tryin hard to get acess but its not doing...:(
not only gpio but also led ,adc none of the files are available...
n i ve read the forum post they say to recompile kernel...
n even dont how to do dat..
if nyone could provide me the solution...
thnks in advance...

sss
Hi,

Can anybody help me how to use the GPIO of tiny 6410 board .

I want to use the unused header GPIO pins on the board for my application .

I am using Linux platform .Please help me how to add the GPIO support in
the sys/class/  .