Skip to contentSkip to conversation

pca953x GPIO

DISCUSSION Joan Pau Beltran 2 participants 7 messages Dec 17, 2010 – Dec 21, 2011 9 messages not in the archive I2C subsystem host drivers

lore
Share & tools
lore
#0 lore raw

Hi everyone,

We are also working with an Advantech PCM3362 board in an underwater vehicle, and want to use the GPIO port to monitor the battery charge (a battery board is connected to the GPIO port and sets a pin to 1 when voltage goes below 20V).

We need to use Ubuntu, currently 10.04 with kernel linux-image-2.6-32-26-generic.

As Giampolo says, out of the box there aren't any chips under /sys/class/gpio (only import/export files).
After checking that i2c-gpio and pca953x are shipped with the kernel but no loaded by default, I tried to modprobe them and they load successfully, but the chip does not appear in /sys/class/gpio. i2cdetect does not list any bus.

The battery board is not connected to the GPIO now. Actually nothing is connected to it. I suppose that the chip should be detected even if there is nothing attached to it. But just to be sure, do I need to connect it to some device to get the chip appear under /sys/class/gpio?

Giampolo (ore anyone on the list), did you success using the GPIO port on that board? In that case, could you point me what steps have you done? It's the first time I use a GPIO port and I read the Documentation and both examples pointed out by Jean but still can not figure out why the chip is not recognized under /sys/class/gpio or how to access it.

Thanks Jean for pointing out about the address alignment difference in Linux. For sure I won't even thought about it reading the Advantech manual.

Thanks in advance, and please excuse my English!

A message that is not in the archive (sent off-list or not yet received): 4D0B9C35.5000802-i5CWTa81U/[email protected]

#2 lore raw

Hi Joan,

Quoted 8 lines · Joan Pau Beltran

We are also working with an Advantech PCM3362 board in an underwater vehicle, and want to use the GPIO port to monitor the battery charge (a battery board is connected to the GPIO port and sets a pin to 1 when voltage goes below 20V).

We need to use Ubuntu, currently 10.04 with kernel linux-image-2.6-32-26-generic.

Quoted 6 lines

As Giampolo says, out of the box there aren't any chips under /sys/class/gpio (only import/export files).
After checking that i2c-gpio and pca953x are shipped with the kernel but no loaded by default, I tried to modprobe them and they load successfully, but the chip does not appear in /sys/class/gpio. i2cdetect does not list any bus.

When you load the i2c-gpio driver, it looks for support devices. So your platform initialization code must instantiate a platform device with name "i2c-gpio" and proper platform data (GPIO pin descriptions). There are several examples under arch/blackfin and arch/arm you can look at.

If done properly, after loading i2c-dev, i2cdetect should see your I2C bus. Until you manage to get there, there is no point in using driver pca953x, it simply can't work.

Quoted 13 lines

The battery board is not connected to the GPIO now. Actually nothing is connected to it. I suppose that the chip should be detected even if there is nothing attached to it. But just to be sure, do I need to connect it to some device to get the chip appear under /sys/class/gpio?

Giampolo (ore anyone on the list), did you success using the GPIO port on that board? In that case, could you point me what steps have you done? It's the first time I use a GPIO port and I read the Documentation and both examples pointed out by Jean but still can not figure out why the chip is not recognized under /sys/class/gpio or how to access it.

Thanks Jean for pointing out about the address alignment difference in Linux. For sure I won't even thought about it reading the Advantech manual.

Signature · 1 line
Jean Delvare

A message that is not in the archive (sent off-list or not yet received): [email protected]

A message that is not in the archive (sent off-list or not yet received): AANLkTi=LQ56S43=BL8tdo=MakP-PRzVK0ieJM07y_O_1-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org

#5 lore raw

Thank you very much Giampolo
(and funny to see that my name is the same than yours, but in Catalan)

From your notes:

Quoted 5 lines

mknod /dev/i2c-0 c 89 0
modprobe i2c-dev
i2cdetect -l

Quoted 1 line
Quoted 1 line
Quoted 1 line

i2c-0 smbus SMBus I801 adapter at 0400 SMBus adapter

i2cget 0 0x20

I see that you can access the chip. I will test it on monday or tuesday.
Do you know if we can access the N'th pin on the chip with 'i2cget 0 0x20 N' (N in 0..7)? And do you know if we can access these pins directly from a C program (I mean without using a system call) ?

Thanks again for your responses!

A message that is not in the archive (sent off-list or not yet received): [email protected]

A message that is not in the archive (sent off-list or not yet received): AANLkTinSuVYAVQqPHRtrnTPrtEZA1aCHOb6X4H8u2OW1-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org

#8 lore raw

Hi everyone

Giampolo, thank you so much for your time.
I hope you and everyone in the list enjoy a happy and not too white Christmas.

My tries following Giampolo's steps first failed,
but thanks to his first mail on this subject and his last suggestions, I get what I think are lectures from the gpio pins.

Here it goes the whole story:

After successfully loading the i2c-dev module via modprobe,
two new devices are automatically created (i2c-0 and i2c-1) with major number 89 and minor numbers 0 and 1 respectively. This seems ok. However any of them appears to i2cdetect as a SMBus
(in contrast with Giampolo's console output):

i2cdetect -l

i2c-0    i2c        intel drm CRTDDC_A           I2C adapter
i2c-1    i2c        intel drm LVDSDDC_C          I2C adapter

i2cdetect 0 (or i2cdetect 1) does not find any device at any address. I get the same results in Ubuntu Lucid and Maverick on the same machine (with kernels 2.6.32-27 and 2.6.35-22 respectively).

Also in contrast with Giampolo's kernel messages in the first post (i801_smbus 0000:00:1f.3: PCI INT C -> GSI 17 (level, low) -> IRQ 17), there aren't any smbus mentions in my dmesg.

Looking for smbus modules, in Maverick I found the module i2c-smbus,
but after loading successfully it has no effect. i2cdetect does not show any extra bus. In Lucid, I did not found the i2c-smbus module, but thanks to Giampolo's dmesg line I eventually caught the i2c-i801 module in the output of modprobe -l.

After loading it, i2cdectect shows an extra bus:

i2c-0    i2c       intel drm CRTDDC_A             I2C adapter
i2c-1    i2c       intel drm LVDSDDC_C            I2C adapter
i2c-2    smbus     SMBus I801 adapter at 0400     SMBus adapter

Now i2cdump give this output
(all lines except the first one stripped because they are empty):

i2cdump -y 2 0x20
No size specified (using byte-data access)

     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef

00: ff ff ff ff 00 00 ff ff XX XX XX XX XX XX XX XX ........XXXXXXXX

I am surprised about these values. The port has 8 gpio pins available, so it seems their addresses are the ones in 000-007
(or shoud I say they are represented in the chip's register 000-007?). However, since there is nothing connected to the gpio pins, I expected all their values to be equal 00. Is this normal? From where can these values can come from?

Giampolo, do you remember which distribution did you use? Did it load some smbus driver automatically (maybe through udev)? Or do you remember adding any extra module to /etc/modules.

It seems that I should add i2c-dev and i2c-i801 to my /etc/modules. Can someone confirm that? Would it be better to make udev load them automatically? How can this be done?

Sorry for the long mail, I wrote it expecting that it could be useful for other people dealing with similar issues.

Thanks again.

Al 25/12/10 12:24, En/na Giampaolo Bellini ha escrit:

Quoted 38 lines

Hello Joan Pau.... an happy christmas !

if I don't remember wrong, 0x20 is the address of the port/function... while the first number is the address of the bus.
the value returned from the command should be the hexadecimal-encoded status of the port (viewed as an input)

in order to control the port you should use i2cput with a third number that is the hex value of the desired outputs.
I'm writing using a window machine now... so I cannot check it right now.

from within a C program you can just open the /dev/i2c-0 device and do ioctl on it... maybe that's the simplest way.

Buon Natale,

Giampaolo

2010/12/24 Joan Pau Beltran<joanpau.beltran-i5CWTa81U/[email protected]>:

Quoted 18 lines

Thank you very much Giampolo
(and funny to see that my name is the same than yours, but in Catalan)

From your notes:

Quoted 6 lines

mknod /dev/i2c-0 c 89 0
modprobe i2c-dev
i2cdetect -l

Quoted 2 lines
Quoted 2 lines
Quoted 2 lines

i2c-0 smbus SMBus I801 adapter at 0400 SMBus
adapter

i2cget 0 0x20

I see that you can access the chip. I will test it on monday or tuesday. Do you know if we can access the N'th pin on the chip with 'i2cget 0 0x20 N' (N in 0..7)?
And do you know if we can access these pins directly from a C program (I mean without using a system call) ?

Thanks again for your responses!

A message that is not in the archive (sent off-list or not yet received): 4D1A0A95.7020408-i5CWTa81U/[email protected]

#10 lore raw
Quoted 11 lines · Joan Pau Beltran

Now i2cdump give this output
(all lines except the first one stripped because they are empty):

i2cdump -y 2 0x20
No size specified (using byte-data access)

      0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef

00: ff ff ff ff 00 00 ff ff XX XX XX XX XX XX XX XX ........XXXXXXXX

I am surprised about these values. The port has 8 gpio pins available, so it seems their addresses are the ones in 000-007
(or shoud I say they are represented in the chip's register 000-007?).

No, it doesn't work like that. You'll have to download the datasheet for your GPIO chip from nxp.com, to find out the meaning of each register. The details are normally hidden from you if you use the pca953x driver, but as you decided to go the hard way...

Quoted 3 lines

However, since there is nothing connected to the gpio pins, I expected all their values to be equal 00. Is this normal?
From where can these values can come from?

You really want to read the datasheet. With i2cdump, i2cget and i2cset, you get raw access to the device registers, so don't expect anything to be easy and straightforward.

Quoted 5 lines

(...)
It seems that I should add i2c-dev and i2c-i801 to my /etc/modules. Can someone confirm that? Would it be better to make udev load them automatically?
How can this be done?

i2c-i801 should get loaded automatically, as it is a PCI driver. If it isn't on your system, make sure you didn't blacklist it. The following command may help:

$ /sbin/modprobe -c | grep i2c_i801

i2c-dev is never loaded automatically, so you indeed have to add it to /etc/modules (or whatever your distribution-specific mechanism is) if you need it. OTOH you have to be root to run i2cdump or i2cget, so you might as well load i2c-dev manually as root too.

Signature · 2 lines
Jean Delvare
http://khali.linux-fr.org/wishlist.html

A message that is not in the archive (sent off-list or not yet received): [email protected] vare

A message that is not in the archive (sent off-list or not yet received): [email protected] vare

#13 lore raw

Hello everyone!

Al 06/01/11 16:22, En/na Jean Delvare ha escrit:

Quoted 9 lines · Joan Pau Beltran
Quoted 8 lines

Now i2cdump give this output
(all lines except the first one stripped because they are empty):

i2cdump -y 2 0x20
No size specified (using byte-data access)

       0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef

00: ff ff ff ff 00 00 ff ff XX XX XX XX XX XX XX XX ........XXXXXXXX

Quoted 7 lines
Quoted 3 lines

I am surprised about these values. The port has 8 gpio pins available, so it seems their addresses are the ones in 000-007
(or shoud I say they are represented in the chip's register 000-007?).

No, it doesn't work like that. You'll have to download the datasheet for your GPIO chip from nxp.com, to find out the meaning of each register. The details are normally hidden from you if you use the pca953x driver, but as you decided to go the hard way...

You are right. I noticed that after playing around with the chip and the demo application from Advantech (for windows only). Then I went straight to the chip's data sheet and found each register's function.

The chip has 2 input/output ports (port0 and port1), each one with 8 GPIO pins
(so it seems that only the first one is available for the user with these board).
The eight registers are for (respectively) Input0 (0), Input1(1), Output0 (2), Output1 (3), Polarity Inversion0 (4), Polarity Inversion1 (5), Direction0 (6) and Direction1 (7).
The byte in each register represent the state of the eight pins as a bitmask.
To read the state of a pin (no matter if it is an input or output pin) you should read the register 0 (0xff mean all pins high, 0x00 means all pins low, 0xf0 means the first four pins low and the other four pins high, etc). The direction of each pin may be set the same way with the register 6 (1 means input and 0 means output, so setting the register to 0xf0 means the first four pins are for output and the other for for input, etc). The polarity inversion for each pin may be set the same way but with register 4.
To set the state of the output pins you should write to the register 2 the bitmask representing the pins you want to bring up (if you want to raise pins 0 and 1 you should write 0x03, etc).

I think we will do the things this way (with i2c-dev and reading the chip's registers) because the code to read the state of the pins is simple and we do not need to recompile the kernel. The cost is that root privileges will be needed to manage the GPIO. But I agree that a more elegant way could be adding platform code for the kernel and use the sysfs interface, allowing non-root access to the GPIO.

Quoted 10 lines
Quoted 5 lines

(...)
It seems that I should add i2c-dev and i2c-i801 to my /etc/modules. Can someone confirm that? Would it be better to make udev load them automatically?
How can this be done?

i2c-i801 should get loaded automatically, as it is a PCI driver. If it isn't on your system, make sure you didn't blacklist it. The following command may help:

$ /sbin/modprobe -c | grep i2c_i801

This is the above command's output:

modprobe -c | grep i2c_i801

blacklist i2c_i801
alias pci:v00008086d00001C22sv*sd*bc*sc*i* i2c_i801
...

And more alias. So the module is effectively blacklisted. In /etc/modprobe.d/blacklist.conf we found

# causes failure to suspend on HP compaq nc6000 (Ubuntu: #10306)
blacklist i2c_i801

Commenting the line should allow automatic loading of the module.

Thank you very much everyone for this discussion, specially Giampolo and Jean. Your help has been invaluable.

A message that is not in the archive (sent off-list or not yet received): 4D274E8B.8050600-i5CWTa81U/[email protected]

#15 lore raw

Hi everyone,

This mail is to let everybody notice that since kernel version 3.1, the pca953x module handles properly the chip WITHOUT the need of platform specific data. This means that, from user space, you can manage the pins through the /sys/class/gpio interface (provided by kernel's gpiolib framework) without building a new kernel with the platform code. You just need to read / write to the correct files. E.g.

# Register the chip on the proper bus.
# A new directory should whose name ends with a chip number N:
# /sys/class/gpio/gpiochip240
echo pca9555 0x20 > /sys/bus/i2c/devices/i2c-0/new_device

# Request the wanted pin number M on the chip number N (chip number + pin number). # A new directory should appear:
# /sys/class/gpio/gpioN+M
echo 240 > /sys/class/gpio/export
echo 241 > /sys/class/gpio/export

# Get the pin state:
cat /sys/class/gpio/gpio240/value

# Set pin direction:
echo 'out' > /sys/class/gpio/gpio241/direction

# Set pin state:
echo '1' > /sys/class/gpio/gpio241/value

Regards,

Signature · 7 lines
Joan Pau Beltran
Grup de Sistemes, Robòtica i Visió - DMI
Universitat de les Illes Balears
Ctra. Valldemossa, km 7.5 07122 Palma
Campus Universitari, edifici Anselm Turmeda
Telf (+34) 971 17 28 13
Fax (+34) 971 17 30 03