Port-arm archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: Arm drivers: are device tree descriptions required for every device?



> On Apr 12, 2023, at 4:40 AM, Dave Tyson <dtyson%anduin.org.uk@localhost> wrote:
> 
> I apologise for the length of this post but it does highlight some
> anomalies in device detection.
> 
> I have struggled to understand the attachment of devices on buses such
> as i2c and spi on arm soc's.
> 
> I understand the need to have an fdt entry so the kernel knows where
> i2c or spi bus are located so it can address them. Taking for example a
> Raspberry Pi zero there are two physically accessible i2c buses 
> i2c@7e205000 and i2c@7e804000) and one spi bus at spi@7e204000. With
> these entries in the fdt the kernel correctly attaches i2c1, i2c2 and
> spi0. (Note there is also an extra i2c0 bus but this is inaccessible,
> cannot be used and I have omitted it the examples below)
> 
> The fun starts when you add physical devices to these busses. If I
> attach two bme280 sensors, both with base address 0x76, to i2c1 and
> i2c2 then adding an appropriate line into /etc/modules.conf they are
> automagically detected with a standard GENERIC kernel:

Right, what’s going on here is that there are multiple ways to specify the location of that device to the kernel.  Yes, I know this can be super confusing.

When the module is loaded, a control message is sent to the kernel saying “attach an instance of the device RIGHT AT THIS SPOT”.

> [   1.0000000] NetBSD 10.0_BETA (RPI) #0: Fri Mar 24 15:44:06 GMT 2023
> ...
> [   1.0000000] bsciic1 at simplebus1: Broadcom Serial Controller
> [   1.0000000] bsciic1: interrupting on icu irq 53
> [   1.0000000] iic1 at bsciic1: I2C bus
> [   1.0000000] bsciic2 at simplebus1: Broadcom Serial Controller
> [   1.0000000] bsciic2: interrupting on icu irq 53
> [   1.0000000] iic2 at bsciic2: I2C bus
> ...
> Loading modules.
> [   3.1312420] bmx280thp0 at iic1 addr 0x76
> [   3.1713100] bmx280thp0: Bosch Sensortec BME280, Chip ID: 0x60
> [   3.2027150] bmx280thp1 at iic2 addr 0x76
> [   3.2427840] bmx280thp1: Bosch Sensortec BME280, Chip ID: 0x60
> 
> rpi# envstat
>                 Current  CritMax  WarnMax  WarnMin  CritMin  Unit
> [bmx280thp0]
>  temperature:    19.560                                      degC
>     pressure:   978.300                                       hPa
>     humidity:    45.404                                       %rH
> [bmx280thp1]
>  temperature:    19.610                                      degC
>     pressure:   978.680                                       hPa
>     humidity:    45.103                                       %rH
> [vcmbox0]
>  temperature:    33.628   85.000                             degC
> 
> OK, so a module attach works fine and correctly finds the devices at
> the known base address of 0x76 or 0x77.
> What about configuring a kernel which explicitly has the devices listed
> in the config so we don't have to use modules?  Add a line to the RPI
> config:
> 
> bmx280thp* at iic? addr 0x76
> 
> Reboot with the new kernel and note:
> 
> [   1.0000000] NetBSD 10.0_BETA (RPI_SPI_I2C) #3: Sun Apr  2 22:24:21
> BST 2023
> ...
> [   1.0000000] bsciic1 at simplebus1: Broadcom Serial Controller
> [   1.0000000] bsciic1: interrupting on icu irq 53
> [   1.0000000] iic1 at bsciic1: I2C bus
> [   1.0000000] bsciic2 at simplebus1: Broadcom Serial Controller
> [   1.0000000] bsciic2: interrupting on icu irq 53
> [   1.0000000] iic2 at bsciic2: I2C bus
> 
> No sensors found...

Right, this is because when a platform uses Device Tree, the auto configuration pass at boot time considers the device tree to be authoritative.  The kernel config file in this case doesn’t specify “YO A DEVICE IS RIGHT HERE!”, instead it’s specifying the *matching criteria* for an instance of that driver.  Make sense?

> 
> rpi# envstat
>                 Current  CritMax  WarnMax  WarnMin  CritMin  Unit
> [vcmbox0]
>  temperature:    35.780   85.000                             degC
> 
> So that doesn't work!
> 
> However Brad Spenser <brad%anduin.elder.org@localhost> who wrote the
> driver and has been very helpful suggested adding an overlay dtbo to
> list the devices explicitly:
> 
> /dts-v1/;
> /plugin/;
> 
> / {
>        compatible = "brcm,bcm2835";
> 
>        fragment@1 {
>                target-path = "/soc/i2c@7e205000";
> 
>                __overlay__ {
>                        status = "okay";
>                        #address-cells = <0x01>;
>                        #size-cells = <0x00>;
>                        clock-frequency = <0x61a80>;
> 
>                        bmx280thp@76 {
>                                compatible = "bosch,bmx280";
>                                reg = <0x76>;
>                        };
> 
>                };
>        };
> 
>        fragment@2 {
>                target-path = "/soc/i2c@7e804000";
> 
>                __overlay__ {
>                        status = "okay";
>                        #address-cells = <0x01>;
>                        #size-cells = <0x00>;
>                        clock-frequency = <0x61a80>;
> 
>                        bmx280thp@76 {
>                                compatible = "bosch,bmx280";
>                                reg = <0x76>;
>                        };
> 
>                };
>        };
> };
> 
> adding this to the boot config results in:
> 
> [   1.0000000] bsciic1 at simplebus1: Broadcom Serial Controller
> [   1.0000000] bsciic1: interrupting on icu irq 53
> [   1.0000000] iic1 at bsciic1: I2C bus
> [   1.0000000] bmx280thp0 at iic1 addr 0x76
> [   1.0000000] bmx280thp0: Bosch Sensortec BME280, Chip ID: 0x60
> 
> [   1.0000000] bsciic2 at simplebus1: Broadcom Serial Controller
> [   1.0000000] bsciic2: interrupting on icu irq 53
> [   1.0000000] iic2 at bsciic2: I2C bus
> [   1.0000000] bmx280thp1 at iic2 addr 0x76
> [   1.0000000] bmx280thp1: Failed to reset chip: 5
> [   1.0000000] bmx280thp1: Bosch Sensortec BME280, Chip ID: 0x60
> ...
> 
> rpi# envstat
>                 Current  CritMax  WarnMax  WarnMin  CritMin  Unit
> [bmx280thp0]
>  temperature:    19.930                                      degC
>     pressure:   977.320                                       hPa
>     humidity:    44.551                                       %rH
> [bmx280thp1]
>  temperature:    19.990                                      degC
>     pressure:   977.630                                       hPa
>     humidity:    44.610                                       %rH
> [vcmbox0]
>  temperature:    35.780   85.000                             degC
> 
> So that works now.

Right, as expected :-)

> Let's keep the same config but pull one of the
> chips:
> 
> [     1.000000] iic1 at bsciic1: I2C bus
> [     1.000000] bmx280thp0 at iic1 addr 0x76
> [     1.000000] bmx280thp0: Bosch Sensortec BME280, Chip ID: 0x60
> [     1.000000] bsciic2 at simplebus1: Broadcom Serial Controller
> [     1.000000] bsciic2: interrupting on icu irq 53
> [     1.000000] iic2 at bsciic2: I2C bus
> [     1.000000] bmx280thp1 at iic2 addr 0x76
> [     1.000000] bmx280thp1: autoconfiguration error: Failed to reset
> chip: 5
> [     1.000000] bmx280thp1: autoconfiguration error: Unable to setup
> device
> 
> Well I guess that's expected, but it's a bit noisy! Certainly if you
> used the module attach then there would be just one entry and no error
> message.

Well, this makes sense actually because you have told the kernel, via the device tree overlay, “Hey!  There absolutely is a device here!"

> So it would appear that module attach just works and probes the devices

Well, in the case of module attach, you told it exactly where the device is when you loaded the module.  I2C is not a self-describing bus and here is no reliable way to “probe” it (there are some techniques that work to varying degrees to see if *a* device responds to an address, but there’s no reliable way to determine what kind of device it is, or even if it is really a actual device at all… some I2C addresses are used to talk to multiple devices at once … and this is all dependent on what you have connected to the I2C bus…)

> OK, but using a static config needs extra work to explicitly list the
> devices in the fdt hardware config. This doesn't seem right as its
> duplicating info unnecessarily.

If you have a DT overlay, you can just have this in the kernel config:

bmx280thp* at iic?

What that says is “hey, include the bmx280thp driver in the kernel, and allow it to attach to any i2c bus at any address”, and the i2c bus will use the device tree information to enumerate the devices and there you go.

> I think the moral of this story is there is some inconsistency here. I
> understand the need for the fdt to list the physical buses together
> with their attachment point, but it should not be necessary to list
> the individual devices you ae going to put on the bus via an overlay.

No, this is actually the preferred way.  The DT overlay is more specific to the machine and its hardware configuration, and it allows the kernel to be much more generic.  Trust me, it’s better this way. :-)

> The kernel config should have entries for any devices you want to use
> together with their base address and they should be enumerated at boot
> time.

No, that means having to build a different kernel for each individual machine’s device configuration.  This is … not great.

> Brad noted that spi attached devices don't work with the bme280x
> modules - you need to specify the entry in the kernel config - I have
> still to test this properly...

I have a bunch of improvements to i2c and spi device autoconfiguration that I’ve been working on for some time, but haven’t pushed in yet.  I should find the time to resurrect them.

> one final thing to note is that i2cscan (which is the subject of at
> least one PR) is still broken, reporting multiple non-existent devices!

See my statement above.  i2c “scanning” is a crap shoot at best, and that’s basically because of how I2C works.

-- thorpej



Home | Main Index | Thread Index | Old Index