Re: [PATCH 1/4] dt-bindings: display: bridge: add the Hot-plug MIPI DSI connector
From: Luca Ceresoli
Date: Wed Apr 03 2024 - 15:33:49 EST
Hello Rob,
[+Cc Wolfram for the I2C discussion below]
thanks for your feedback.
On Wed, 27 Mar 2024 11:09:08 -0500
Rob Herring <robh@xxxxxxxxxx> wrote:
> On Tue, Mar 26, 2024 at 05:28:11PM +0100, Luca Ceresoli wrote:
> > Add bindings for a physical, hot-pluggable connector allowing the far end
> > of a MIPI DSI bus to be connected and disconnected at runtime.
> >
> > Signed-off-by: Luca Ceresoli <luca.ceresoli@xxxxxxxxxxx>
> > ---
> > .../bridge/hotplug-video-connector-dsi.yaml | 87 ++++++++++++++++++++++
> > MAINTAINERS | 5 ++
> > 2 files changed, 92 insertions(+)
> >
> > diff --git a/Documentation/devicetree/bindings/display/bridge/hotplug-video-connector-dsi.yaml b/Documentation/devicetree/bindings/display/bridge/hotplug-video-connector-dsi.yaml
> > new file mode 100644
> > index 000000000000..05beb8aa9ab4
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/display/bridge/hotplug-video-connector-dsi.yaml
> > @@ -0,0 +1,87 @@
> > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> > +%YAML 1.2
> > +---
> > +$id: http://devicetree.org/schemas/display/bridge/hotplug-video-connector-dsi.yaml#
> > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > +
> > +title: Hot-pluggable connector on a MIPI DSI bus
> > +
> > +maintainers:
> > + - Luca Ceresoli <luca.ceresoli@xxxxxxxxxxx>
> > +
> > +description:
> > + A bridge representing a physical, hot-pluggable connector on a MIPI DSI
> > + video bus. The connector splits the video pipeline in a fixed part and a
> > + removable part.
> > +
> > + The fixed part of the video pipeline includes all components up to the
> > + display controller and 0 or more bridges. The removable part includes one
> > + or more bridges and any other components up to the panel.
> > +
> > + The removable part of the pipeline can be physically disconnected at any
> > + moment, making all of its components not usable anymore. The same or a
> > + different removable part of the pipeline can be reconnected later on.
> > +
> > + Note that the hotplug-video-connector does not describe video busses
> > + having native hotplug capabilities in the hardware, such as HDMI.
> > +
> > +properties:
> > + compatible:
> > + const: hotplug-video-connector-dsi
>
> Got a spec for this connector? How do I know if I have one or not?
>
> The problem here is what else is on this connector? GPIO controls,
> power rails, etc.?
>
> If this is some kind of standard connector, then we need to be able to
> remap everything on the connector not just DSI signals. And for that,
> it's not just DSI signals, so I'd say we would need some sort of generic
> graph remapping that the core graph code handles transparently.
>
> If it is not standard, then you don't need any remapping and can just
> use an overlay that connects the ports directly.
This is not a standardized connector. And it couldn't be: to the best of
my knowledge no standard removable MIPI DSI connector exists at all.
This whole work is unavoidably breaking some long-standing assumptions
and opening some new challenges: giving a proper DT description to
runtime-pluggable hardware and breaking the dogma that a DRM pipeline
is not removable, to name some. So I think it's better to take a step
back and describe the big picture.
As mentioned in the cover letter ("Development roadmap" section),
together with Hervé we are working on a set of patches to allow this
sort of removable hardware to be handled properly by the Linux kernel.
From the cover letter:
> The use case we are working on is to support professional products that
> have a portable "main" part running on battery, with the main SoC and able
> to work autonomously with limited features, and that can be connected to an
> "add-on" part that is not portable and adds more features.
The add-on gets connected via a connector that is not standardized.
There is a well-defined part number for the mechanical connector, but
the pin usage is custom for the product. Connector pins include:
* I2C lines to access various chips on the add-on
- one of these chips is an EEPROM with the add-on product ID
* Some pins to report to the CPU whether the add-on is connected and
add-on power rails are stable (these are wired to SoC GPIOs)
* An interrupt line collecting IRQs from the add-on chips
* MIPI DSI to drive a panel on the add-on
* Gigabit Ethernet (4 pairs)
* USB lines
* A few more accessory pins
Some of these are not problematic: USB is hot-pluggable and
auto-discoverable by nature, Ethernet pins are just connected directly
to the RJ-45 connector so the add-on acts as an Ethernet or USB cable.
For everything else there is going to be a separate patch series
with code to detect add-on connection, read the ID, identify the
appropriate DT overlay and load it, and unload it on disconnection.
Before that, it's good to discuss how the device tree should describe
the whole hardware described above, in these terms:
1. Should device tree describe the connector?
2. If it does, how should the various busses on the connector
(especially I2C and MIPI DSI) be described and associated to the
connector?
To address question 1, I think we _do_ need to describe the connector
itself, because it is a part of the non-discoverable hardware that the
software needs to manage. Among others we need software to know which
GPIOs report the connection and power good statuses, and to know how to
locate the ID EEPROM.
Regarding question 2 I think there are a few open possibilities, and
I must admit the example provided in this series is just too simplistic
to be adequate. Apologies, this series is mostly aiming at discussing
the DRM implementation aspects.
Let me try a more realistic DT description that allows to:
1. associate the various busses to the connector they go through
2. map components of different base board models to the connector pins
3. map components of different add-on models to the connector pins
The 2nd and 3rd items allow decoupling the base and add-on hardware so
that different base board models and different add-on models can be
mixed in all combinations if they use the same connector pinout. This
obviously resembles the Beaglebone capes and RPi hats use case.
My draft proposal is as follows:
---------------------- [my-product.dts] ----------------------
/ {
// [0]
my_hotplug_connector: my-hotplug-connector {
compatible = "vendor-abc,product-xyz-connector";
// [1]
plugged-gpios = <&gpio4 2 GPIO_ACTIVE_LOW>;
powergood-gpios = <&gpio2 4 GPIO_ACTIVE_HIGH>;
// [5]
hotplug_dsi_bus: hotplug-dsi-video-bus@0 {
port@0 {
reg = <0>;
hotplug_dsi_in: endpoint {
remote-endpoint = <&bridge1>;
};
};
port@1 {
reg = <1>;
hotplug_dsi_out: endpoint {
// remote-endpoint to be added by overlay
};
};
};
// [3]
// Map "placeholder" i2cA to "physical" i2c3
i2cA: hotplug-i2c-bus@A {
hotplug-connector,base-bus = <&i2c3>;
};
i2cB: hotplug-i2c-bus@B {
hotplug-connector,base-bus = <&i2c5>;
};
};
};
// Video bridge or display controller on the base board
&bridge1 {
ports {
port@1 {
bridge1_out: endpoint {
remote-endpoint = <&hotplug_dsi_in>;
};
};
};
};
--------------------------------------------------------------
------------------- [my-add-on-common.dtso] ------------------
// [2]
&my_hotplug_connector {
nvmem-cells = <addon_id>;
nvmem-cell-names = "id";
};
// [4]
// i2cA is a "placeholder" name, mapped by the connector
// definition on the base dts to a physical bus on the base board
&i2cA {
eeprom@50 {
compatible = "atmel,24c02";
reg = <0x50>;
nvmem-layout {
compatible = "fixed-layout";
#address-cells = <1>;
#size-cells = <1>;
addon_id: addon-id@10 {
reg = <0x10 0x4>;
};
};
};
};
--------------------------------------------------------------
----------------- [my-add-on-model-xyz.dtso] -----------------
// [6]
&hotplug_dsi_out {
remote-endpoint = <&bridge2_in>; // Fill in the missing piece
};
&{/}
{
panel {
compatible = ...;
ports {
port@0 {
reg = <0>;
panel_in: endpoint {
remote-endpoint = <&bridge2_out>;
};
};
};
};
};
&i2cB {
// Video bridge chip on the add-on
bridge@22 {
// ... compatible, other props/nodes ...
ports {
port@0 {
bridge2_in: endpoint {
remote-endpoint = <&hotplug_dsi_out>;
};
};
port@1 {
bridge2_out: endpoint {
remote-endpoint = <&panel_in>;
};
};
};
};
};
--------------------------------------------------------------
The connector itself [0] is described under the root node because it is
not on any addressable bus, similarly to "sound" and "panel" nodes. I
don't think connectors addressable over I2C or other addressable busses
are going to appear in the forseeable future, but if they did they
could be represented as such in the device tree as well.
The connector GPIOs [1] allow the CPU to know the connection and "power
good" status of the connector. On the implementation side, those are the
inputs triggering overlay loading and unloading.
There is a "common" overlay which describes the common components of
all add-ons at least up to the NVMEM cell [2] holding the add-on ID
that is needed to load the model-specific overlay. This overlay adds
nvmem properties to the hotplug connector node to point to the specific
NVMEM cell. The nvmem-cells and nvmem-cell-names = "id" properties need
to be part of the hotplug-connector bindings.
The "placeholder" hotplug-i2c-bus nodes in the connector node [3] allow
decoupling the I2C bus segment on the base board from the segment on
the add-on. They point to the base bus controller phandle via
hotplug-connector,base-bus, and allow the overlay to use the
"placeholder" [4] instead of naming the "base" I2C bus name. This
allows using the same add-on and overlay on a different base board,
which could even have a totally different SoC, and where the same
connector pins are not wired to the SoC i2c3 but to e.g. i2c4.
In other words:
* [3] means connector pins X and Y are wired to i2c3 on this base board
* [4] means connector pins X and Y are wired to i2cA on this add-on
The specific pins X and Y are not described. Only the bus going through
the connector is.
This can be implemented in the I2C code similarly to a 1-port i2c-mux,
even though it might have an even better ad-hoc implementation that
avoids any unneeded overhead from the mux code, as we are not muxing
anything here, just "connecting wires". Whatever the implementation,
what it needs to do is ensure that i2cA and i2cB appear as regular I2C
busses to their subnodes (e.g. eeprom@50), and when drivers for those
subnodes try to probe they attach to the correct bus (i2c3, i2c5) in
some way -- anything else is an implementation detail. Let's call this
the "I2C decoupler driver".
Once the "common" overlay is loaded, software can read the add-on ID
from NVMEM and find out the overlay that describes the specific add-on
model, see my-add-on-model-xyz.dtso above. This other overlay needs to
be loaded and will populate all the remaining add-on hardware, possibly
using nodes from the first overlay (e.g. a regulator that is used both
by the eeprom@50 and by nodes in the 2nd overlay).
Now to the video bus. Back to the main dts, the hotplug-dsi-video-bus@0
node [5] describes the video pipeline up to the "main" board side of
the connector, represented by port@0. port@1 represents the beginning
of the add-on side of the pipeline, and as such it has no
remote-endpoint because no hardware is present before hotplug and anyway
which hardware will be connected is unknown.
Note DSI is used in the example, but it could as well be LVDS or
parallel video.
The model-specific overlay describes the continuation of the pipeline
up to the panel _and_ fills in the remote-endpoint of &hotplug_dsi_out
to connect the two segments. Just like the i2c example, the overlays
never refer to base board components: it only refers to what appears in
the hotplug connector definition node [0].
An alternative design is that the entire port@1 node is missing from the
hotplug-dsi-video-bus@0 node and is entirely added by the overlay. No
strong opinion on this, the example shows what is tested, but I think
either will be fine.
On the implementation side, the hotplug-dsi-video-bus@0 node does
materialize as the hotplug-bridge driver (patch 4 of this series). The
hotplug-bridge sits in the middle of a previous bridge and the first
bridge in the add-on to let each of them probe normally, and then
passes calls through as transparently as possible.
Still about the implementation, in this example there are 3 main
components that need an implementation:
1. the hotplug-connector driver for /my-hotplug-connector [0]
2. the I2C decoupler driver (possibly based on i2c-mux)
3. the hotplug-bridge driver (this series)
The hotplug-connector driver is responsible for monitoring the
status GPIOs, load the 1st overlay, read the NVMEM ID, load the 2nd
overlay. But it is also in charge of instantiating the "decoupling"
driver for hotplug-i2c-bus nodes [1] and hotplug-dsi-video-bus nodes
[3].
Generalizing the idea to other busses such as SPI should be quite
trivial.
This device tree representation is possibly complicated and verbose.
However I cannot think of a simpler one that can describe a connector
to a removable hardware without losing the ability of decoupling the
base hardware from the add-on hardware.
Your opinion on this will be very appreciated.
Best regards,
Luca
--
Luca Ceresoli, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com