cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
maske.dhananjay
Observer
Observer
4,498 Views
Registered: ‎07-27-2017

I2C Mux on ZC702

Jump to solution

Hi All,

         I am trying to configure the I2C mux on the ZC702 board using I2c tools. it uses PCA9548 mux. As per the device tree, the Mux is connected to I2C bus-0 and has the address 0x74. I enabled the channel 1 by writing 0x01 and I could see silabs device at 0x5d which is as per device tree. But when i try to write 0x02, i.e enable channel 2, I am expecting to see the eeprom at address 0x54, but i see extra devices. Also when i try to read the data from the mux, it shows up some random values (i2cdump). Can anyone please help why its like that? Do we have any extra devices connected to channel 2?. I have disabled the PCA954x driver from kernel configuration.

 

Tests:

======

# i2cdetect -r 0
i2cdetect: WARNING! This program can confuse your I2C bus
Continue? [y/N] y
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- 74 -- -- --
#
# i2cset -y 0 0x74 0x00 0x01
# i2cdetect -r 0
i2cdetect: WARNING! This program can confuse your I2C bus
Continue? [y/N] y
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- 5d -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- 74 -- -- --
# i2cset -y 0 0x74 0x00 0x00
# i2cdetect -r 0
i2cdetect: WARNING! This program can confuse your I2C bus
Continue? [y/N] y
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- 74 -- -- --
# i2cset -y 0 0x74 0x00 0x02
# i2cdetect -r 0
i2cdetect: WARNING! This program can confuse your I2C bus
Continue? [y/N] y
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- 38 39 -- -- 3c -- 3e 3f
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- 74 -- -- --
# i2cset -y 0 0x74 0x00 0x01
# i2cdetect -r 0
i2cdetect: WARNING! This program can confuse your I2C bus
Continue? [y/N] y
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- 5d -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- 74 -- -- --
#

# i2cdump 0 0x74
i2cdump: WARNING! This program can confuse your I2C bus
Continue? [y/N] y
0 1 2 3 4 5 6 7 8 9 a b c d e f 0123456789abcdef
00: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f .???????????????
10: 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f ????????????????
20: 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f !"#$%&'()*+,-./
30: 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f 0123456789:;<=>?
40: 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f @ABCDEFGHIJKLMNO
50: 50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f PQRSTUVWXYZ[\]^_
60: 60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f `abcdefghijklmno
70: 70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e 7f pqrstuvwxyz{|}~?
80: 80 81 82 83 84 85 86 87 88 89 8a 8b 8c 8d 8e 8f ????????????????
90: 90 91 92 93 94 95 96 97 98 99 9a 9b 9c 9d 9e 9f ????????????????
a0: a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 aa ab ac ad ae af ????????????????
b0: b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 ba bb bc bd be bf ????????????????
c0: c0 c1 c2 c3 c4 c5 c6 c7 c8 c9 ca cb cc cd ce cf ????????????????
d0: d0 d1 d2 d3 d4 d5 d6 d7 d8 d9 da db dc dd de df ????????????????
e0: e0 e1 e2 e3 e4 e5 e6 e7 e8 e9 ea eb ec ed ee ef ????????????????
f0: f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 fa fb fc fd fe ff ???????????????.

 

 

Device tree

===========

 

&i2c0 {
status = "okay";
clock-frequency = <400000>;
pinctrl-names = "default", "gpio";
pinctrl-0 = <&pinctrl_i2c0_default>;
pinctrl-1 = <&pinctrl_i2c0_gpio>;
scl-gpios = <&gpio0 50 0>;
sda-gpios = <&gpio0 51 0>;

i2cswitch@74 {
// compatible = "nxp,pca9548";
#address-cells = <1>;
#size-cells = <0>;
reg = <0x74>;


i2c@0 {
#address-cells = <1>;
#size-cells = <0>;
reg = <0>;
si570: clock-generator@5d {
#clock-cells = <0>;
// compatible = "silabs,si570";
temperature-stability = <50>;
reg = <0x5d>;
factory-fout = <156250000>;
clock-frequency = <148500000>;
};
};

i2c@1 {
#address-cells = <1>;
#size-cells = <0>;
reg = <1>;
adv7511: hdmi-tx@39 {
// compatible = "adi,adv7511";
reg = <0x39>;
adi,input-depth = <8>;
adi,input-colorspace = "yuv422";
adi,input-clock = "1x";
adi,input-style = <3>;
adi,input-justification = "right";
};
};
i2c@2 {
#address-cells = <1>;
#size-cells = <0>;
reg = <2>;
eeprom@54 {
// compatible = "at,24c08";

reg = <0x54>;
};
};

i2c@3 {
#address-cells = <1>;
#size-cells = <0>;
reg = <3>;
gpio@21 {
// compatible = "ti,tca6416";
reg = <0x21>;
gpio-controller;
#gpio-cells = <2>;
};
};
i2c@4 {
#address-cells = <1>;
#size-cells = <0>;
reg = <4>;
rtc@51 {
// compatible = "nxp,pcf8563";
reg = <0x51>;
};
};

i2c@7 {
#address-cells = <1>;
#size-cells = <0>;
reg = <7>;
hwmon@52 {
// compatible = "ti,ucd9248";
reg = <52>;
};
hwmon@53 {
// compatible = "ti,ucd9248";
reg = <53>;
};
hwmon@54 {
// compatible = "ti,ucd9248";
reg = <54>;
};
};
};
};

0 Kudos
1 Solution

Accepted Solutions
hpoetzl
Voyager
Voyager
6,265 Views
Registered: ‎06-24-2013

Hey @maske.dhananjay,

 

I am writing my driver in userpace using "i2c_smbus_read/write_byte/data" functions provided with i2c-dev.h file.

That's perfectly fine, you can also use i2cget and i2cset to test stuff on the command line.

 

I was wondering about interrupts and how can i handle them in case I need to for devices like hwmon etc.

Well, you don't have many options there. Real interrupts require a handler and that has to be implemented in the kernel (but read on ...), so the only option for userspace is to poll the interrupt flags. But in Linux there is also the UIO driver, which was designed to handle IO in userspace and will handle the interrupts for you by mapping them to blocking reads.

 

That said, the typical interrupts found on hardware monitors (temperature, voltage, etc) are not really that critical and have been more a convenience feature for slow and otherwise busy CPUs or just an output for some kind of alert feature. Note that for an interrupt to trigger, an actual interrupt line is required in addition to the I2C interface.

 

since i am doing everything from userspace, I am not loading kernel drivers for it and commented that in my device tree

Do you see any side effect of this?

This is actually the proper way to address this, as you don't want a kernel driver to claim the devices and subsequently interfere with your userspace device access. By the way, you can tell that an I2C slave address is claimed by a kernel driver when i2cdetect shows the address as UU.

 

Hope this helps,

Herbert

-------------- Yes, I do this for fun!

View solution in original post

0 Kudos
7 Replies
hpoetzl
Voyager
Voyager
4,481 Views
Registered: ‎06-24-2013

Hey @maske.dhananjay,

 

But when i try to write 0x02, i.e enable channel 2 ...

With writing 0x02 to the MUX, you are selecting the second branch, i.e. the one with the ADV7511 on it.

(Details about the channels can be found in Table 1-19 of UG850)

 

I am expecting to see the eeprom at address 0x54, but i see extra devices.

If you want to get the third channel (i.e. the I2C EEPROM) you need to write 0x04 to the MUX register.

(For details on the MUX see Figure 7 and Table 2 of the PCA9548 Datasheet)

 

For the ADV7511, what you see is completely normal as it shows up on a number of different slave addresses and all but one can be configured (so you can have completely different addresses with the same chip).

 

The main address [register map] for the ADV7511 is either 0x39 [0x72] or 0x3D [0x7A] depending on the PD/AD pin at power up. This contains a bunch of registers (0x43-0x45, 0xE1 and 0xF9) which set the slave addresses for the secondary addresses for EDID and Packet memory as well as CEC. You can find the details and the defaults in the ADV7511 Programming Guide, section 4.1 I2C Bus.

 

Hope this clarifies,

Herbert

-------------- Yes, I do this for fun!
0 Kudos
maske.dhananjay
Observer
Observer
4,429 Views
Registered: ‎07-27-2017

Hi,

    Thank you for your reply. So I tried with 0x04 for the eeprom which is at 0x54 address and I see other extra devices too (0x55, 56 etc). what are these ones?.

 

Welcome to Buildroot
buildroot login: root
Password:
#
#
#
# i2cdetect -r 0
i2cdetect: WARNING! This program can confuse your I2C bus
Continue? [y/N] y
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- 74 -- -- --
#
# i2cset 0 0x74 0x04
i2cset: WARNING! This program can confuse your I2C bus
Continue? [y/N] y
# i2cdetect -r 0
i2cdetect: WARNING! This program can confuse your I2C bus
Continue? [y/N] u
i2cdetect: aborting
# i2cdetect -r 0
i2cdetect: WARNING! This program can confuse your I2C bus
Continue? [y/N] y
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- 54 55 56 57 -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- 74 -- -- --
#

 

Regards,

Dhananjay

0 Kudos
maske.dhananjay
Observer
Observer
4,424 Views
Registered: ‎07-27-2017

Also one more question. The datasheet talks about the control register. But no where it has mentioned the register address for that control register. I have seen that in most of the PCA/TCA data sheets. How do i know what offset to write for control register?.

 

Regards,

Dhananjay

0 Kudos
hpoetzl
Voyager
Voyager
4,420 Views
Registered: ‎06-24-2013

Hey @maske.dhananjay,

 

I tried with 0x04 for the eeprom which is at 0x54 address and I see other extra devices too (0x55, 56 etc).

what are these ones?

The ZC702 has an M24C08 EEPROM with 1kB of memory space. The I2C bus is 8bit based, so it comes kind of natural to access 256 bytes as 256 registers, and because earlier EEPROMs were way smaller, this is how the interface got designed. For compatibility reasons, the 1kB EEPROM shows up as four 256B EEPROMs on consecutive addresses.

 

The datasheet talks about the control register.

But no where it has mentioned the register address for that control register.

How do i know what offset to write for control register?

I presume that you are referring to the PCA9548 here ...

 

The MUX only has one 'register' and you are already writing to it, so there is no offset or register address associated.

From the datasheet (section 9.6.2) ...

Following the successful acknowledgment of the address byte, the bus master sends a command byte that is stored in the control register in the PCA9548A (see Figure 7). This register can be written and read via the I2C bus. Each bit in the command byte corresponds to a SCn/SDn channel and a high (or 1) selects this channel.

 

Hope this clarifies,

Herbert

-------------- Yes, I do this for fun!
0 Kudos
maske.dhananjay
Observer
Observer
4,413 Views
Registered: ‎07-27-2017

Thanks Herbert. That clarifies it. 

 

I am writing my driver in userpace using "i2c_smbus_read/write_byte/data" functions provided with i2c-dev.h file. I was wondering about interrupts and how can i handle them in case I need to for devices like hwmon etc. We are using TCA9545a mux and it has some interrupt bits in its control register (which i may need to handle).  Can you please let know how can i handle interrupts in this other than minimal kernel module or polling method from userspace ?.

 

I have not worked on hwmon/sysmon so far and googling about it didnt give me satisfying answer on how it works (i.e whether it raises interrupt upon detection of temperature anamolies etc). Is there any good document you can point me to or clarify what i may need to do for interrupts? and specific devices like hwmon/sysmon?. 

 

Also apart from this, since i am doing everything from userspace, I am not loading kernel drivers for it and commented that in my device tree. Do you see any side effect of this?.

 

Regards,

Dhananjay 

0 Kudos
hpoetzl
Voyager
Voyager
6,266 Views
Registered: ‎06-24-2013

Hey @maske.dhananjay,

 

I am writing my driver in userpace using "i2c_smbus_read/write_byte/data" functions provided with i2c-dev.h file.

That's perfectly fine, you can also use i2cget and i2cset to test stuff on the command line.

 

I was wondering about interrupts and how can i handle them in case I need to for devices like hwmon etc.

Well, you don't have many options there. Real interrupts require a handler and that has to be implemented in the kernel (but read on ...), so the only option for userspace is to poll the interrupt flags. But in Linux there is also the UIO driver, which was designed to handle IO in userspace and will handle the interrupts for you by mapping them to blocking reads.

 

That said, the typical interrupts found on hardware monitors (temperature, voltage, etc) are not really that critical and have been more a convenience feature for slow and otherwise busy CPUs or just an output for some kind of alert feature. Note that for an interrupt to trigger, an actual interrupt line is required in addition to the I2C interface.

 

since i am doing everything from userspace, I am not loading kernel drivers for it and commented that in my device tree

Do you see any side effect of this?

This is actually the proper way to address this, as you don't want a kernel driver to claim the devices and subsequently interfere with your userspace device access. By the way, you can tell that an I2C slave address is claimed by a kernel driver when i2cdetect shows the address as UU.

 

Hope this helps,

Herbert

-------------- Yes, I do this for fun!

View solution in original post

0 Kudos
maske.dhananjay
Observer
Observer
4,401 Views
Registered: ‎07-27-2017

Thank you herbert for your reply. Do you know of any existing temperature sensor/hw mon guide that explains its working in detail?. I have googled but couldnt find any relevant resource.

 

Regards,

Dhananjay

0 Kudos