Linux CME9210 + PCA9554 I2C

Hi all,
I am trying to interface a LCD display 2x16 with the Digi Connect ME 9210 through the PCA9554 I2C chip.
Environment:

  • Development platform: Digi ESP DEL-5.2 for Digi Embedded Linux 5.2

  • Linux Kernel configuration
    Device Drivers
    I2C support
    I2C device interface (M)
    Autoselect pertinent helper modules (Y)
    I2C Hardware Bus support
    Digi ns9360, ns921x (M)
    GPIO Support (Y)
    /sys/class/gpio… (sysfs interface) (Y)
    PCA953x, PCA955x, and MAX7310 I/O ports (M)

  • I2C LCD module: LCD display 2x16 + PCA9554 (connected to the SDA and SCL pins of the cme module)

  • An oscilloscope is connected to the SDA and SCL pins of the PCA9554 chip.

In the first time, I validated the i2c lcd display using an atmega8 micro controller configured as i2c master. In this configuration, I written successfully a “hello world” to the lcd display. My goal is to drive the LCD by the cme9210.

  1. I found some information about 9210 I2C in the thread “Embedded Linux -> Development -> CME 9210 + RTC”.

  2. The cme9210 don’t have the code to enable the I2C interface. So, I have based on the cme9215 machine code to patch the cme9210 machine code (file: kernel/linux/arch/arm/mach-ns9xxx/mach-cme9210js.c). I added somes debug traces to check it. Then, when the board starts, the I2C interface is well registered as shown in following debug messages messages:
    file kernel/linux/arch/arm/mach-ns9xxx/mach-cme9210js.c:
    Call ns9xxx_add_device_cme9210_i2c
    file kernel/linux/arch/arm/mach-ns9xxx/ns921x_devices.c:
    Configure clock
    file kernel/linux/drivers/base/platform.c:
    Adding device: success

  3. I loads successfully i2c-ns9xxx, i2c-core, pca953x and i2c-dev drivers. The /dev/i2c-0 device is well created. See debug messages above:

modprobe i2c-ns9xxx

dmesg


i2c-core: driver [dummy] registered
bus: ‘platform’: add driver i2c-ns9xxx
bus: ‘platform’: driver_probe_device: matched device i2c-ns9xxx with driver i2c-ns9xxx
i2c-ns9xxx i2c-ns9xxx: mapped I2C interface to virtual address0xc1078000
i2c-ns9xxx i2c-ns9xxx: I2C_NORMALSPEED: 100000
I2C adapter driver [i2c-ns9xxx] forgot to specify physical device
i2c-adapter i2c-0: adapter [i2c-ns9xxx] registered
i2c-ns9xxx i2c-ns9xxx: NS9XXX I2C adapter

modprobe pca953x

dmesg


bus: ‘i2c’: add driver pca953x
kobject: ‘pca953x’ (c06a0f80): kobject_add_internal: parent: ‘drivers’, set: ‘drivers’
bus: ‘i2c’: driver_probe_device: matched device 0-0020 with driver pca953x
bus: ‘i2c’: really_probe: probing driver pca953x with device 0-0020
pca953x 0-0020: probe
i2c-adapter i2c-0: master_xfer[0] W, addr=0x20, len=1
i2c-adapter i2c-0: master_xfer[1] R, addr=0x20, len=1
i2c-core: driver [pca953x] registered

modprobe i2c-dev

i2c /dev entries driver
i2c-core: driver [dev_driver] registered
i2c-dev: adapter [i2c-ns9xxx] registered as minor 0

ls -il /dev


47 crw-rw---- 1 root root 89, 0 Jan 1 00:13 i2c-0

lsmod

Module Size Used by Not tainted
i2c_dev 5988 0
pca953x 3168 0
i2c_ns9xxx 6656 0
i2c_core 20080 3 i2c_dev,pca953x,i2c_ns9xxx

ls -al /sys/bus/i2c/devices/0-0020/

drwxr-xr-x 4 root root 0 Jan 1 00:02 .
drwxr-xr-x 5 root root 0 Jan 1 00:06 …
lrwxrwxrwx 1 root root 0 Jan 1 00:18 driver -> …/…/…/…/…/bus/i2c/drivers/pca953x
drwxr-xr-x 3 root root 0 Jan 1 00:02 gpio
-r–r–r-- 1 root root 4096 Jan 1 00:18 modalias
-r–r–r-- 1 root root 4096 Jan 1 00:18 name
drwxr-xr-x 2 root root 0 Jan 1 00:18 power
lrwxrwxrwx 1 root root 0 Jan 1 00:18 subsystem -> …/…/…/…/…/bus/i2c
-rw-r–r-- 1 root root 4096 Jan 1 00:18 uevent

  1. I have implemented a simple C program “test.exe” to send a byte to the PCA9554. See example in the documentation kernel/linux/Documentation/i2c/dev_interface. Here is the main part of the code:

    int test(void)
    {
    int file;
    char* filename=“/dev/i2c-0”; /* I2C user device /
    int addr = 0x40; /
    The I2C address */
    char buf[4];

if ((file = open(filename, O_WRONLY)) < 0) {
// ERROR HANDLING; you can check errno to see what went wrong
fprintf(stderr, “Failed to open %s: %s”, filename, strerror(errno));
return(-1);
}
if (ioctl(file, I2C_SLAVE, addr) < 0) {
// ERROR HANDLING; you can check errno to see what went wrong
fprintf(stderr, “Failed to set %d: %s”, file, strerror(errno));
close(file);
return(-1);
}

buf[0] = 0x01;
buf[1] = 0x02;
if (write(file, buf, 2) < 0) {
/* ERROR HANDLING: i2c transaction failed */
fprintf(stderr, “Failed to write to %d: %s”, file, strerror(errno));
close(file);
return(-1);
}
close(file);
return(0);
}

  1. When I launch the test.exe program, I can see several signals in the scope, probably the I2C initialization. The /dev/i2c-0 is opened successfully. But writing failed with error: “Failed to write to 3: Input/output error”. And all PCA9554 output pins (DB0 to DB7) are high (5V measured), which confirm that nothing have been writen.

  2. I have tryied the smbus function “i2c_smbus_write_byte()” instead of the “write()” and encountered the same issue (Input/output error).

  3. I saw a similar problem in the thread “Embedded Linux -> Development -> CME 9210 + RTC”, but cannot get the PCA9554 works.

I am very wondered by this issue. I have re-validated the LCD module with the atmega8 micro controller. I have also verifyied several times the kernel configuration, the C program code, electrical connexions between PCA9554 and the cme9210 module…

Does anyone port the PCA9554 on the cme9210 module? What have I missed? How can I use directly the class ns9xxx driver interface instead of the /dev/i2c-0
Please help me. I am very blocked. Don’t hesitate to ask further informations.

Hi all,
Finally I found that the problem came from the manner that the slave was setting up. I used I2C_SLAVE while seeting up the slave device. Using I2C_SLAVE_FORCE in the ioctl instead of I2C_SLAVE solve the problem. Now I can communicate with the pca9554.
I have displayed my first “hello world” using the /dev/i2c-0 of the cme9210 :wink:

Now I am using the cme9210 to drive a lcd display interfaced by the pca9554 i2c chip.
But I am wondered by another issue: My cme9210 is connected to an atmega8 over the rs232 port and to the pca9554 over the i2c port. In this configuration, sometimes a crash occurs on the rs232 channel: cme9210 blocked during writing to the rs232.
But when i2c is not enabled (pca9554 support disabled in the kernel), the rs232 crash never occurs.
What can explains this behaviour? Does anybody encountered this issue?

wixxk,
I use a Digi9210ME with :
FIM UART,FIM I2C and never faced such problems.
check again for proper updates, and kernel config
Cheers