zephyr
zephyr copied to clipboard
dts: i2c: Dynamic device address
Okay, I'm implementing a driver for ST's VL53L3CX and my board has two of them on the same I2C_0 bus. The driver should recognize this, shutdown the first instance (so the I2C bus is "clear") and program the new address for the second instance.
What is the suggested practice for defining it in DT? My first idea was something like this:
vl53l3cx@29 {
compatible = "st,vl53l3cx";
reg = <0x29>;
label = "VL53L3CX";
};
vl53l3cx@19 {
compatible = "st,vl53l3cx";
reg = <0x29 0x19>;
label = "VL53L3CX";
};
Where I'd use the first reg idx for the initial address and the second idx for the address to be programmed. But this throws some warnings:
warning: unit address and first address in 'reg' (0x29) don't match for /soc/i2c@40003000/vl53l3cx@19
But using the same unit address for both instances just overrides the first instance with the second instance.
Should I add a "reg-dynamic" prop? Or just use the dynamic address 0x19 for the second instance leaving it up to the driver to hardcode the initial address 0x29?
are they really at the same i2c address on your board? if so how do you control which one is active?
yes they are. There's a XSHUT pin which "mutes" the device so you can send a special instruction to reprogram the new address for the other instance. Pretty cool, eh? ;)
@avisconti any advice here?
To be honest I do not know this ToF component very musch. I explored it in the past but not in details. Anyway, my understanding now is that
- at the beginning they share the same I2C address
- It is possible to 'mute' a component thru the XSHUT pin
- It is possible to configure a new I2C address on the component
Is that correct?
If so, my proposal would be to describe them in dts in the way they should at the end be (first on 0x29, second on 0x19):
vl53l3cx@29 {
compatible = "st,vl53l3cx";
reg = <0x29>;
label = "VL53L3CX";
};
vl53l3cx@19 {
compatible = "st,vl53l3cx";
reg = <0x19>;
label = "VL53L3CX";
};
Then, when shutting down the first device the second will anyway answer on 0x29 as it was the first device. After the I2C change to 0x19 the dts will describe the correct situation.
It seems a trick, but I really think that dts should describe the final situation.
that's already what I do but it has some implications like that one has to define the devices in a specific order - the XSHUT resets the device's address as well. I guess I'll check that with some DT_ magic
I just wanted to confirm if I should add a new prop (which I think would be clearer) or not
that's already what I do but it has some implications like that one has to define the devices in a specific order - the XSHUT resets the device's address as well. I guess I'll check that with some DT_ magic
In a specific order? Is it really true?
(just landed here because I was looking if anyone had success with the new vl53l3cx hardware :))
2. It is possible to 'mute' a component thru the XSHUT pin
They get entirely shut down/disabled as long as the pin is toggled. They re-appear with the default address.
Common practice seem to be to disable all of the devices at the same bus, then enable one-after-the-other and assign a new addresses to all of them.
In a specific order? Is it really true?
It would not matter if all devices get a new address.
This is also an issue for other ST VL53 devices like the L0, L5, etc. My only real solution to this problem at the moment is to not use the devicetree for these sensors.
Note that this is already supported in vl53l0x, using VL53L0X_RECONFIGURE_ADDRESS
Kconfig option see https://github.com/zephyrproject-rtos/zephyr/pull/38315.