I2C Touchscreen controller in Apalis iMX6

Hello,

As a follow-up of my previous question, my quest for a successful display integration on Apalis continues…

This time is the touchscreen controller: Pixcir Tango C48

I am connecting the touchscreen controller through a custom adapter to the capacitive touch port on Ixora (X24) using a flat cable (which is longer than needed).

I’ve added the appropriate blob to the device tree according to this page and this page as well.

Recompiled the kernel and… It does not work.

i2c probe from U-Boot does not detect the address (0x5c)

i2cdetect from Linux does not detect either

Output from the driver:

[    4.971325] pixcir_ts 1-005c: pixcir_set_power_mode: can't read reg 0x33 : -5
[    4.980077] pixcir_ts 1-005c: Failed to set IDLE mode
[    4.994909] pixcir_ts: probe of 1-005c failed with error -5

I have used an oscilloscope and every time I use i2cdetect -y -r 1 I can see the SCL and SDA lines getting the signals (I confirmed the clock and I spotted something on the data lane i just don’t know if it is correct or not)

I have also used a multimeter to confirm all connections (I am testing if the pins in the custom adapter board and the i2c pins in the extension header X27 beep (they do beep)

Here’s my i2c1 blob on the ixora device tree (the pn5xx works properly, it worked out of the box actually)

/* GEN1_I2C: I2C1_SDA/SCL on MXM3 209/211 (e.g. RTC on carrier board) */
&i2c1 {
        clock-frequency = <100000>;  
        pinctrl-names = "default";  
        pinctrl-0 = <&pinctrl_i2c1>;  
        status = "okay";  

    pixcir: pixcir_ts@5c {
     compatible = "pixcir,pixcir_tangoc";
     reg = <0x5c>;
     interrupt-parent = <&gpio6>;
     interrupts = <10 2>; //high to low edge triggered
     attb-gpio = <&gpio6 10 1>; // INT GPIO
     //interrupt-gpios = <&gpio6 10 1>;  //INT gpio 
     reset-gpios = <&gpio6 9 1>; // 1 - active low
     touchscreen-size-x = <800>;
     touchscreen-size-y = <480>;
   };


        pn547: pn547@28 {  
                compatible = "nxp,pn547";  
                reg = <0x28>;  
                //clock-frequency = <400000>;  
                interrupt-parent = <&gpio2>;  
                interrupt-gpios = <&gpio2 4 0>;  //MXM3 1
                enable-gpios = <&gpio2 5 0>;  //MXM3 3
        };  
};

I have also done a bunch of kernel tweaks like SMBus extensions, Tango C series driver added here but does not work either so I gave up on that one and continued to try on the one that already exists in the kernel.

What can be the causes of this?

Faulty hardware? (the display’s touch controller works, confirmed by a colleague in another legacy board from the company)

Faulty connections? (Maybe the length of the data cable)

Lack of pull-up resistors (I removed the ones on the adapter board since ixora already has 1.8k Ohm resistors)

Any kind of help would be appreciated.

Best regards,

João

Hi

I2C should allow for quite long connections (meaning smaller than 100cm), so that would not be the first place I’d look.

Assuming that i2cdetect is able to detect that specific controller this is the first thing I would look at.

Is your legacy device also Linux based and can you detect the controller there with i2cdetect?

You could also try to only access your controller to have a clearer picture on what your oscilloscope tells you. E.g. by using i2cget to get the register which also the kernel driver tryies to read:

i2cget -f 1 0x5c 0x33

Maybe comparing this oscilloscope trace with reading one byte from the RTC helps, e.g.

i2cget -f 1 0x68 0x00

Max

Hi Max

i2c detect does not detect the controller.

The legacy board is not linux based. I did not work on that project so if I it comes to that i’ll have to explore it.

Now here’s where it gets weird.

I had some poor connections on the adapter board, got it fixed. Now I get error -110 on the driver and all my i2c addresses get timeout errors!

i2cdetect takes a long time after this (no longer “instant” after i start the command) and all addresses appear as ‘–’. If i try to i2cget through RTC i2cget: read failed: Connection timed out

In U-Boot I tried i2c probe and all addresses give the following output in i2c0:

Valid chip addresses:wait_for_sr_state: failed sr=81 cr=a0 state=2020 i2c_init_transfer: failed for chip 0x0 retry=0 wait_for_sr_state: failed sr=81 cr=a0 state=2020 i2c_init_transfer: failed for chip 0x0 retry=1 wait_for_sr_state: failed sr=81 cr=a0 state=2020 i2c_init_transfer: failed for chip 0x0 retry=2 i2c_init_transfer: give up i2c_regs=0x21a0000 (...)

I was using only the internal pull up resistors, installed the external (10k Ohm) too, did not solve the issue.

What is this I2C controller sorcery? What could be wrong? This controller is definitively ruining the bus but I have no idea why!

Any insights?

Joao

After some extra playing around with the oscilloscope, the breakthrough that I got is that when i connect the i2c bus from the touch controller, the line NEVER goes low. I think this is the cause of my issues, because it times out the RTC (which is connected to the same bus) and times out all kinds of probing / detection on that i2c bus.

I tried to deactivate the internal pull ups (while maintaining my externals of 10k Ohm), no changes

I deactivated by changing the value on the i2c1 lines from 0x4001b8b1 to 0x4001a8b1 in imx6qdl-apalis.dtsi (bit 12 from 1 to 0)

What could force the bus to high? Is it a missconnection on the adapter board? Should i increase the external resistance and keep internal off? Am I missing a key point?

Regards

Hi Joao

I2C is a open drain bus. So the line is high because of pullups (typically between 1…4.7k) and the I2C master and/or slave devices pull it low.

If the line always stays low this means that you either have a wrong wiring of SDA/SCL e.g. to 3.3V or to a push/pull output or your touch controller is defective.

Max

Hi Max

I had some faulty connections, which are now fixed. I can now see the signals reaching the device.

Although, i still cannot detect it. With the oscilloscope i spot a NACK at the end.

Is there any chance the RTC is messing with the lines?

The interrupt line of the touch screen works as intended, it goes LOW as soon as i touch it. The driver also resets the device before probing.

I also tested the controller again on the legacy board and it works properly.

What could be causing the issue on the i2c?

Hi

The RTC will not access the lines if it is not addressed.

Can you send the oscilloscope picture together with the command you did to trigger the I2C communication?

Max

Yellow SDA
Green SCL

UBOOT - scope_0: i2c probe 0x38 (Yes, i had wrong info. The touch controller is a ft5x06 - address 0x38)

LINUX - scope_1: i2cget -f 1 0x38 0x33
followed by I/O error (because it cant establish the connection and read the byte)

I should’ve also included the interrupt line. As soon as I press the display, it goes active low, so it is powered.

Also, my last test was to provide the driver the RTC address and moves the cursor to the bottom left corner when I touch it. So I can only see an issue in the i2c. I just tried so many things I don’t know any more.

Regards

Images

Hi

The waveform look good, the pullup seem to be reasonably low for your load capacitance and I2C speed.

The the ACK bit is ‘1’ likely means likely that no device listens on address 0x38.

  • Are you sure that the touch controller answers on the bus address 0x38 (or is that an 8bit address and you have to read 0x1c?
  • Do you see a new device with i2cdetect?
  • Is SCL and SDA crossed on the connection to your touch controller?

Max

Hi Max,

Answering your questions… The address according to almost everyone that uses this device + documentation on the kernels point to 0x38. I just tested the legacy board with an oscilloscope and the controller ACKs the 0x38 address.

i2c detect only catches the RTC. Even my NFC reader (pn5xx) does not get detected but it works when i run the application.

SCL and SDA are connected properly to the controller.

At this point I have no clue why it doesn’t work. I’ll work on the driver for now.

EDIT: I’m trying to study the i2c part of the kernel. Is there any chance that i’m missing any kernel configuration?

Regards

Hi

i2c detect only catches the RTC. Even my NFC reader (pn5xx) does not get detected but it works when i run the application.

I2cdetect cannot detect all kind of slave devices. It depends on how the slave device uses I2C.

At this point I have no clue why it doesn’t work.

The oscilloscope pictures you sent show the I2C master writing to the I2C slave with address 0x38 but that one does not even ack that first byte and thus the I2C master stops communicating.

Since you say that the RTC gets detected there is likely no issue with the I2C master and thus no need to fiddle with the kernel right now.

You will have to find out why your device which you think is on 0x38 does not even send the ACK bit.

Max

Hi,

I felt the need to update this.

No success so far on getting the connection up and running.

I had access to the board I told you that the touch screen works and I analyzed it with an oscilloscope so I could check the slave address and the data transferred via I2C.

With this I confirmed that the address is 0x38 + R / W goes to 0x70 / 0x71, which is the exact same byte I send in Linux.

I double checked all connections and everything looks good. I switched the external pull ups to 10k, same results.

I also tried to edit the driver by scanning the whole i2c bus for the chip: nothing. Tried to ignore the probing, the chip generates an interrupt (which gets detected in the assigned GPIO) and I get thrown a bunch of error -5 messages from the driver which can’t read from i2c (Also getting the same 0x70 NACKed)

Additionally, I changed from i2c1 to i2c3, same results.

I am using a custom adapter board (which works with the other board), an Ixora adapter board that splits the 40pin FCC from the first adapter board into 2 (Unif. Display port / Capacitive port) to ixora. The board is tiny and preety straight forward, just splits the signals and optional pull up resistors (which I do have - 10k)

I also checked with the NFC; UBoot finds 0x28 but i2cdetect does not. Also tried to assign the NFC driver the touch address, still does not detect.

I used all my guns at this point. Does anyone know what could be missing?

Hi

I really run out of explanations.

The signals generated by the I2C master look correct but the slave is not even Acking the first byte.

So something on the slave side is likely different between your old system and the Apalis iMX6 system.

  • Power supply?
  • Reset signal which is in reset?
  • SDA / SCL swapped?

Can you measure directly on the I2C slave side with your oscilloscope?

Max

Okay, I -finally- got it.

I removed the I2C connection from the “splitter” board which splits the 40 pin FFC from the display into the 2 FFC’s - Unified display port and capacitive port in Ixora.

I soldered the I2C lines directly from the board to the X27 Extension header, just like I did with NFC instead of using the capacitive display port (X24)

Guess what? It works.

I2c detect, Uboot I2c probe and driver.

I can only assume the line has too much capacitance and ruins the timings by the time the chip tries to ACK the address it’s already too late.

Thank you for the time and support you gave to me, this was a really weird one but it’s finally out of the way.

Best Regards,
João

Hi @Joao,

I’m attempting to integrate a Tango C44 as well and found your old conversation here. I think I have all my connections correct, but I can seem to get documentation for the I2C instruction set for the chip.

After establishing the I2C device at address 0x5C, what are the instruction codes to write instructions and read data back from the device? I’ve looked all over the internet and cannot find datasheets for the Tango series.

Regards,
stukemanmini