Portable Device Tree Connector -- conceptual

From: Frank Rowand
Date: Thu Jun 30 2016 - 20:02:30 EST


Hi All,

I've been trying to wrap my head around what Pantelis and Rob have written
on the subject of a device tree representation of a connector for a
daughter board to connect to (eg a cape or a shield) and the representation
of the daughter board. (Or any other physically pluggable object.)

After trying to make sense of what had been written (or presented via slides
at a conference - thanks Pantelis!), I decided to go back to first principals
of what we are trying to accomplish. I came up with some really simple bogus
examples to try to explain what my thought process is.

To start with, assume that the device that will eventually be on a daughter
board is first soldered onto the main board. Then the device tree will
look like:

$ cat board.dts
/dts-v1/;

/ {
#address-cells = < 1 >;
#size-cells = < 1 >;

tree_1: soc@0 {
reg = <0x0 0x0>;

spi_1: spi1 {
};
};

};

&spi_1 {
ethernet-switch@0 {
compatible = "micrel,ks8995m";
};
};

#include "spi_codec.dtsi"

$ cat spi_codec.dtsi
&spi_1 {
codec@1 {
compatible = "ti,tlv320aic26";
};
};


#----- codec chip on cape

Then suppose I move the codec chip to a cape. Then I will have the same
exact .dts and .dtsi and everything still works.


@----- codec chip on cape, overlay

If I want to use overlays, I only have to add the version and "/plugin/",
then use the '-@' flag for dtc (both for the previous board.dts and
this spi_codec_overlay.dts):

$ cat spi_codec_overlay.dts
/dts-v1/;

/plugin/;

&spi_1 {
codec@1 {
compatible = "ti,tlv320aic26";
};
};


#----- codec chip on cape, overlay, connector

Now we move into the realm of connectors. My mental model of what the
hardware and driver look like has not changed. The only thing that has
changed is that I want to be able to specify that the connector that
the cape is plugged into has some pins that are the spi bus /soc/spi1.

The following _almost_ but not quite gets me what I want. Note that
the only thing the connector node does is provide some kind of
pointer or reference to what node(s) are physically routed through
the connector. (This node will turn out to not actually work in
this example.)

$ cat board_with_connector.dts
/dts-v1/;

/ {
#address-cells = < 1 >;
#size-cells = < 1 >;

tree_1: soc@0 {
reg = <0x0 0x0>;

spi_1: spi1 {
};
};

connector_1: connector_1 {
spi1 {
target_phandle = <&spi_1>;
target_path = "/soc/spi1";
};
};

};

&spi_1 {
ethernet-switch@0 {
compatible = "micrel,ks8995m";
};
};

$ cat spi_codec_overlay_with_connector.dts
/dts-v1/;

/plugin/;

&connector_1 {
spi1 {
codec@1 {
compatible = "ti,tlv320aic26";
};
};
};

The result is that the overlay fixup for spi1 on the cape will
relocate the spi1 node to /connector_1 in the host tree, so
this does not solve the connector linkage yet:

-- chunk from the decompiled board_with_connector.dtb:

__symbols__ {
connector_1 = "/connector_1";
};

-- chunk from the decompiled spi_codec_overlay_with_connector.dtb:

fragment@0 {
target = <0xffffffff>;
__overlay__ {
spi1 {
codec@1 {
compatible = "ti,tlv320aic26";
};
};
};
};
__fixups__ {
connector_1 = "/fragment@0:target:0";
};


#----- magic new dtc syntax

What I really want is some way to tell dtc that I want to do one
level of dereferencing when resolving the path of device nodes
contained by the connector node in the overlay dts.

The exact syntax does not matter here, I am just trying to get the
concept. I will add the not yet implemented dtc feature of
"/connector/" to the connector node in both the tree dts and the
overlay dts, and show how the output of dtc would change. The
"/connector/" directive tells dtc that for a base dts (hand
waving how it knows base vs overlay dts file) to look into
each node at that level and determine what other node it
maps to (again, hand waving, in this example just to
show the linkage, I have hard coded both the path and the
phandle of the target node that the connector child node
maps to). The "/connector/" directive tells dtc that for
an overlay dts (again hand waving) to provide a fixup for
each child node.

$ cat board_with_connector_v2.dts
/dts-v1/;

/ {
#address-cells = < 1 >;
#size-cells = < 1 >;

tree_1: soc@0 {
reg = <0x0 0x0>;

spi_1: spi1 {
};
};

connector_1: connector_1 {
/connector/;
spi1 {
target_phandle = <&spi_1>;
target_path = "/soc/spi1";
};
};

};

&spi_1 {
ethernet-switch@0 {
compatible = "micrel,ks8995m";
};
};

$ cat spi_codec_overlay_with_connector_v2.dts

/dts-v1/;

/plugin/;

&connector_1 {
/connector/;
spi1 {
codec@1 {
compatible = "ti,tlv320aic26";
};
};
};

-- chunk from the decompiled board_with_connector_v2.dtb:

__symbols__ {
connector_1 {
spi1 = "/soc@0/spi1";
};
};

-- chunk from the decompiled spi_codec_overlay_with_connector_v2.dtb:

/ {

fragment@0 {
target = <0xffffffff>;
__overlay__ {
spi1 {
codec@1 {
compatible = "ti,tlv320aic26";
};
};
};
};
__fixups__ {
connector_1 {
spi1 = "/fragment@0/__overlay__:spi1:0";
};
};

Of course the overlay loader will also have to be modified to understand
the new information.

Exact format of the __symbols__ and __fixups__ are implementation
details, I am just trying to present the model.

Ignoring device tree source syntax and dtc implementation issues, does
this conceptual model look more straight forward and a better direction
for how to represent connectors?

-Frank