* Re: Question regarding clocks in the DW-HDMI DT bindings
From: Fabio Estevam @ 2016-11-25 12:43 UTC (permalink / raw)
To: Laurent Pinchart
Cc: devicetree@vger.kernel.org, Mike Turquette, Stephen Boyd,
DRI mailing list, Andy Yan, Vladimir Zapolskiy
In-Reply-To: <4461318.dYHS3nW9CP@avalon>
Hi Laurent,
On Thu, Nov 24, 2016 at 9:26 PM, Laurent Pinchart
<laurent.pinchart@ideasonboard.com> wrote:
> Another question I have about the bus clock (CC'ing the devicetree mailing
> list as well as the clock maintainers) is whether it should be made optional.
> The clock is obviously mandatory from a hardware point of view (given that APB
> is a synchronous bus and thus requires a clock), but in some SoCs
> (specifically for the Renesas SoCs) that clock is always on and can't be
> controlled. We already omit bus clocks in DT for most IP cores when the clock
> can never be controlled (and we also omit a bunch of other clocks that we
> don't even know exist), so it could make sense to make the clock optional.
> Otherwise there would be runtime overhead trying to handle a clock that can't
> be controlled.
What if you register the clock as a "dummy" clock instead?
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel
^ permalink raw reply
* [PATCH v2 8/8] ARM: dts: sun8i-h3: orange-pi-pc: Enable audio codec
From: Chen-Yu Tsai @ 2016-11-25 12:34 UTC (permalink / raw)
To: Liam Girdwood, Mark Brown, Maxime Ripard, Lee Jones
Cc: devicetree, alsa-devel, linux-kernel, Chen-Yu Tsai,
Mylene Josserand, linux-arm-kernel
In-Reply-To: <20161125123442.28410-1-wens@csie.org>
The Orange Pi PC routes the LINEOUT pins to the audio out jack on the
board. The onboard microphone is routed to MIC1, with MBIAS providing
power.
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
---
arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts b/arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts
index 98b85be61e17..d43978d3294e 100644
--- a/arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts
+++ b/arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts
@@ -90,6 +90,14 @@
};
};
+&codec {
+ allwinner,audio-routing =
+ "Line Out", "LINEOUT",
+ "MIC1", "Mic",
+ "Mic", "MBIAS";
+ status = "okay";
+};
+
&ehci1 {
status = "okay";
};
--
2.10.2
^ permalink raw reply related
* [PATCH v2 7/8] ARM: dts: sun8i-h3: Add device nodes for audio codec and its analog controls
From: Chen-Yu Tsai @ 2016-11-25 12:34 UTC (permalink / raw)
To: Liam Girdwood, Mark Brown, Maxime Ripard, Lee Jones
Cc: devicetree, alsa-devel, linux-kernel, Chen-Yu Tsai,
Mylene Josserand, linux-arm-kernel
In-Reply-To: <20161125123442.28410-1-wens@csie.org>
Now that we support the audio codec found on the Allwinner H3 SoC, add
device nodes for it.
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
---
arch/arm/boot/dts/sun8i-h3.dtsi | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/arch/arm/boot/dts/sun8i-h3.dtsi b/arch/arm/boot/dts/sun8i-h3.dtsi
index fca66bf2dec5..496efc564bbe 100644
--- a/arch/arm/boot/dts/sun8i-h3.dtsi
+++ b/arch/arm/boot/dts/sun8i-h3.dtsi
@@ -465,6 +465,20 @@
status = "disabled";
};
+ codec: codec@01c22c00 {
+ #sound-dai-cells = <0>;
+ compatible = "allwinner,sun8i-h3-codec";
+ reg = <0x01c22c00 0x400>;
+ interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_CODEC>, <&ccu CLK_AC_DIG>;
+ clock-names = "apb", "codec";
+ resets = <&ccu RST_BUS_CODEC>;
+ dmas = <&dma 15>, <&dma 15>;
+ dma-names = "rx", "tx";
+ allwinner,codec-analog-controls = <&codec_analog>;
+ status = "disabled";
+ };
+
uart0: serial@01c28000 {
compatible = "snps,dw-apb-uart";
reg = <0x01c28000 0x400>;
@@ -580,6 +594,11 @@
#reset-cells = <1>;
};
+ codec_analog: codec-analog@01f015c0 {
+ compatible = "allwinner,sun8i-h3-codec-analog";
+ reg = <0x01f015c0 0x4>;
+ };
+
ir: ir@01f02000 {
compatible = "allwinner,sun5i-a13-ir";
clocks = <&apb0_gates 1>, <&ir_clk>;
--
2.10.2
^ permalink raw reply related
* [PATCH v2 6/8] ASoC: sun4i-codec: Add support for H3 codec
From: Chen-Yu Tsai @ 2016-11-25 12:34 UTC (permalink / raw)
To: Liam Girdwood, Mark Brown, Maxime Ripard, Lee Jones
Cc: devicetree, alsa-devel, linux-kernel, Chen-Yu Tsai,
Mylene Josserand, linux-arm-kernel
In-Reply-To: <20161125123442.28410-1-wens@csie.org>
The codec on the H3 is similar to the one found on the A31. One key
difference is the analog path controls are routed through the PRCM
block. This is supported by the sun8i-codec-analog driver, and tied
into this codec driver with the audio card's aux_dev.
In addition, the H3 has no HP (headphone) and HBIAS support, and no
MIC3 input. The FIFO related registers are slightly rearranged.
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
Acked-by: Rob Herring <robh@kernel.org>
---
.../devicetree/bindings/sound/sun4i-codec.txt | 3 +
sound/soc/sunxi/sun4i-codec.c | 71 ++++++++++++++++++++++
2 files changed, 74 insertions(+)
diff --git a/Documentation/devicetree/bindings/sound/sun4i-codec.txt b/Documentation/devicetree/bindings/sound/sun4i-codec.txt
index f7a548b604fc..3033bd8aab0f 100644
--- a/Documentation/devicetree/bindings/sound/sun4i-codec.txt
+++ b/Documentation/devicetree/bindings/sound/sun4i-codec.txt
@@ -6,6 +6,7 @@ Required properties:
- "allwinner,sun6i-a31-codec"
- "allwinner,sun7i-a20-codec"
- "allwinner,sun8i-a23-codec"
+ - "allwinner,sun8i-h3-codec"
- reg: must contain the registers location and length
- interrupts: must contain the codec interrupt
- dmas: DMA channels for tx and rx dma. See the DMA client binding,
@@ -23,6 +24,7 @@ Optional properties:
Required properties for the following compatibles:
- "allwinner,sun6i-a31-codec"
- "allwinner,sun8i-a23-codec"
+ - "allwinner,sun8i-h3-codec"
- resets: phandle to the reset control for this device
- allwinner,audio-routing: A list of the connections between audio components.
Each entry is a pair of strings, the first being the
@@ -52,6 +54,7 @@ Required properties for the following compatibles:
Required properties for the following compatibles:
- "allwinner,sun8i-a23-codec"
+ - "allwinner,sun8i-h3-codec"
- allwinner,codec-analog-controls: A phandle to the codec analog controls
block in the PRCM.
diff --git a/sound/soc/sunxi/sun4i-codec.c b/sound/soc/sunxi/sun4i-codec.c
index ada5fa055950..848af01692a0 100644
--- a/sound/soc/sunxi/sun4i-codec.c
+++ b/sound/soc/sunxi/sun4i-codec.c
@@ -217,6 +217,13 @@
#define SUN8I_A23_CODEC_DAC_TXCNT (0x1c)
#define SUN8I_A23_CODEC_ADC_RXCNT (0x20)
+/* TX FIFO moved on H3 */
+#define SUN8I_H3_CODEC_DAC_TXDATA (0x20)
+#define SUN8I_H3_CODEC_DAC_DBG (0x48)
+#define SUN8I_H3_CODEC_ADC_DBG (0x4c)
+
+/* TODO H3 DAP (Digital Audio Processing) bits */
+
struct sun4i_codec {
struct device *dev;
struct regmap *regmap;
@@ -1293,6 +1300,44 @@ static struct snd_soc_card *sun8i_a23_codec_create_card(struct device *dev)
return card;
};
+static struct snd_soc_card *sun8i_h3_codec_create_card(struct device *dev)
+{
+ struct snd_soc_card *card;
+ int ret;
+
+ card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL);
+ if (!card)
+ return ERR_PTR(-ENOMEM);
+
+ aux_dev.codec_of_node = of_parse_phandle(dev->of_node,
+ "allwinner,codec-analog-controls",
+ 0);
+ if (!aux_dev.codec_of_node) {
+ dev_err(dev, "Can't find analog controls for codec.\n");
+ return ERR_PTR(-EINVAL);
+ };
+
+ card->dai_link = sun4i_codec_create_link(dev, &card->num_links);
+ if (!card->dai_link)
+ return ERR_PTR(-ENOMEM);
+
+ card->dev = dev;
+ card->name = "H3 Audio Codec";
+ card->dapm_widgets = sun6i_codec_card_dapm_widgets;
+ card->num_dapm_widgets = ARRAY_SIZE(sun6i_codec_card_dapm_widgets);
+ card->dapm_routes = sun8i_codec_card_routes;
+ card->num_dapm_routes = ARRAY_SIZE(sun8i_codec_card_routes);
+ card->aux_dev = &aux_dev;
+ card->num_aux_devs = 1;
+ card->fully_routed = true;
+
+ ret = snd_soc_of_parse_audio_routing(card, "allwinner,audio-routing");
+ if (ret)
+ dev_warn(dev, "failed to parse audio-routing: %d\n", ret);
+
+ return card;
+};
+
static const struct regmap_config sun4i_codec_regmap_config = {
.reg_bits = 32,
.reg_stride = 4,
@@ -1321,6 +1366,13 @@ static const struct regmap_config sun8i_a23_codec_regmap_config = {
.max_register = SUN8I_A23_CODEC_ADC_RXCNT,
};
+static const struct regmap_config sun8i_h3_codec_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = SUN8I_H3_CODEC_ADC_DBG,
+};
+
struct sun4i_codec_quirks {
const struct regmap_config *regmap_config;
const struct snd_soc_codec_driver *codec;
@@ -1369,6 +1421,21 @@ static const struct sun4i_codec_quirks sun8i_a23_codec_quirks = {
.has_reset = true,
};
+static const struct sun4i_codec_quirks sun8i_h3_codec_quirks = {
+ .regmap_config = &sun8i_h3_codec_regmap_config,
+ /*
+ * TODO Share the codec structure with A23 for now.
+ * This should be split out when adding digital audio
+ * processing support for the H3.
+ */
+ .codec = &sun8i_a23_codec_codec,
+ .create_card = sun8i_h3_codec_create_card,
+ .reg_adc_fifoc = REG_FIELD(SUN6I_CODEC_ADC_FIFOC, 0, 31),
+ .reg_dac_txdata = SUN8I_H3_CODEC_DAC_TXDATA,
+ .reg_adc_rxdata = SUN6I_CODEC_ADC_RXDATA,
+ .has_reset = true,
+};
+
static const struct of_device_id sun4i_codec_of_match[] = {
{
.compatible = "allwinner,sun4i-a10-codec",
@@ -1386,6 +1453,10 @@ static const struct of_device_id sun4i_codec_of_match[] = {
.compatible = "allwinner,sun8i-a23-codec",
.data = &sun8i_a23_codec_quirks,
},
+ {
+ .compatible = "allwinner,sun8i-h3-codec",
+ .data = &sun8i_h3_codec_quirks,
+ },
{}
};
MODULE_DEVICE_TABLE(of, sun4i_codec_of_match);
--
2.10.2
^ permalink raw reply related
* [PATCH v2 5/8] ARM: dts: sun8i-a23: q8-tablet: Enable internal audio codec
From: Chen-Yu Tsai @ 2016-11-25 12:34 UTC (permalink / raw)
To: Liam Girdwood, Mark Brown, Maxime Ripard, Lee Jones
Cc: devicetree, alsa-devel, linux-kernel, Chen-Yu Tsai,
Mylene Josserand, linux-arm-kernel
In-Reply-To: <20161125123442.28410-1-wens@csie.org>
The A23 Q8 tablets have an internal mono speaker w/ external amp
which has a shutdown control tied to a GPIO pin. Both the speaker
amp and the headphone jack are tied to the HP output pins. While
the speaker is mono, the headset jack is stereo. Unfortunately
the driver does not support automatic switching of this.
In addition, the headset is DC coupled, or "direct drive" enabled.
The headset's microphone is tied to MIC2 with HBIAS providing power.
A separate internal microphone is tied to MIC1 with MBIAS providing
power.
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
---
arch/arm/boot/dts/sun8i-a23-q8-tablet.dts | 23 +++++++++++++++++++++++
1 file changed, 23 insertions(+)
diff --git a/arch/arm/boot/dts/sun8i-a23-q8-tablet.dts b/arch/arm/boot/dts/sun8i-a23-q8-tablet.dts
index 956320a6cc78..3ab5c0c09d93 100644
--- a/arch/arm/boot/dts/sun8i-a23-q8-tablet.dts
+++ b/arch/arm/boot/dts/sun8i-a23-q8-tablet.dts
@@ -48,3 +48,26 @@
model = "Q8 A23 Tablet";
compatible = "allwinner,q8-a23", "allwinner,sun8i-a23";
};
+
+&codec {
+ pinctrl-0 = <&codec_pa_pin>;
+ allwinner,pa-gpios = <&pio 7 9 GPIO_ACTIVE_HIGH>; /* PH9 */
+ allwinner,audio-routing =
+ "Headphone", "HP",
+ "Headphone", "HPCOM",
+ "Speaker", "HP",
+ "MIC1", "Mic",
+ "MIC2", "Headset Mic",
+ "Mic", "MBIAS",
+ "Headset Mic", "HBIAS";
+ status = "okay";
+};
+
+&pio {
+ codec_pa_pin: codec_pa_pin@0 {
+ allwinner,pins = "PH9";
+ allwinner,function = "gpio_out";
+ allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+ allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+ };
+};
--
2.10.2
^ permalink raw reply related
* [PATCH v2 4/8] ARM: dts: sun8i-a23: Add device node for internal audio codec
From: Chen-Yu Tsai @ 2016-11-25 12:34 UTC (permalink / raw)
To: Liam Girdwood, Mark Brown, Maxime Ripard, Lee Jones
Cc: devicetree, alsa-devel, linux-kernel, Chen-Yu Tsai,
Mylene Josserand, linux-arm-kernel
In-Reply-To: <20161125123442.28410-1-wens@csie.org>
Now that we have a device tree binding and driver for the A23's
internal audio codec, add a device node for it.
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
---
arch/arm/boot/dts/sun8i-a23.dtsi | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/arch/arm/boot/dts/sun8i-a23.dtsi b/arch/arm/boot/dts/sun8i-a23.dtsi
index 54d045dab825..4d1f929780a8 100644
--- a/arch/arm/boot/dts/sun8i-a23.dtsi
+++ b/arch/arm/boot/dts/sun8i-a23.dtsi
@@ -48,6 +48,22 @@
memory {
reg = <0x40000000 0x40000000>;
};
+
+ soc@01c00000 {
+ codec: codec@01c22c00 {
+ #sound-dai-cells = <0>;
+ compatible = "allwinner,sun8i-a23-codec";
+ reg = <0x01c22c00 0x400>;
+ interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_CODEC>, <&ccu CLK_AC_DIG>;
+ clock-names = "apb", "codec";
+ resets = <&ccu RST_BUS_CODEC>;
+ dmas = <&dma 15>, <&dma 15>;
+ dma-names = "rx", "tx";
+ allwinner,codec-analog-controls = <&codec_analog>;
+ status = "disabled";
+ };
+ };
};
&ccu {
--
2.10.2
^ permalink raw reply related
* [PATCH v2 3/8] ARM: dts: sun8i: Add codec analog path controls node in PRCM for A23/A33
From: Chen-Yu Tsai @ 2016-11-25 12:34 UTC (permalink / raw)
To: Liam Girdwood, Mark Brown, Maxime Ripard, Lee Jones
Cc: devicetree, alsa-devel, linux-kernel, Chen-Yu Tsai,
Mylene Josserand, linux-arm-kernel
In-Reply-To: <20161125123442.28410-1-wens@csie.org>
On the A23/A33, the internal codec's analog path controls are located in
the PRCM node.
Add a sub-device node to the PRCM for it.
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
---
arch/arm/boot/dts/sun8i-a23-a33.dtsi | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/arch/arm/boot/dts/sun8i-a23-a33.dtsi b/arch/arm/boot/dts/sun8i-a23-a33.dtsi
index bc3e936edfcf..d9c6f16f95f1 100644
--- a/arch/arm/boot/dts/sun8i-a23-a33.dtsi
+++ b/arch/arm/boot/dts/sun8i-a23-a33.dtsi
@@ -538,6 +538,10 @@
compatible = "allwinner,sun6i-a31-clock-reset";
#reset-cells = <1>;
};
+
+ codec_analog: codec-analog {
+ compatible = "allwinner,sun8i-a23-codec-analog";
+ };
};
cpucfg@01f01c00 {
--
2.10.2
^ permalink raw reply related
* [PATCH v2 2/8] ASoC: sun4i-codec: Add support for A23 codec
From: Chen-Yu Tsai @ 2016-11-25 12:34 UTC (permalink / raw)
To: Liam Girdwood, Mark Brown, Maxime Ripard, Lee Jones
Cc: devicetree, alsa-devel, linux-kernel, Chen-Yu Tsai,
Mylene Josserand, linux-arm-kernel
In-Reply-To: <20161125123442.28410-1-wens@csie.org>
The codec in the A23 is similar to the one found on the A31. One key
difference is the analog path controls are routed through the PRCM
block. This is supported by the sun8i-codec-analog driver, and tied
into this codec driver with the audio card's aux_dev.
In addition, the A23 does not have LINEOUT, and it does not support
headset jack detection or buttons.
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
Acked-by: Rob Herring <robh@kernel.org>
---
.../devicetree/bindings/sound/sun4i-codec.txt | 11 ++-
sound/soc/sunxi/sun4i-codec.c | 108 +++++++++++++++++++++
2 files changed, 117 insertions(+), 2 deletions(-)
diff --git a/Documentation/devicetree/bindings/sound/sun4i-codec.txt b/Documentation/devicetree/bindings/sound/sun4i-codec.txt
index d91a95377f49..f7a548b604fc 100644
--- a/Documentation/devicetree/bindings/sound/sun4i-codec.txt
+++ b/Documentation/devicetree/bindings/sound/sun4i-codec.txt
@@ -5,6 +5,7 @@ Required properties:
- "allwinner,sun4i-a10-codec"
- "allwinner,sun6i-a31-codec"
- "allwinner,sun7i-a20-codec"
+ - "allwinner,sun8i-a23-codec"
- reg: must contain the registers location and length
- interrupts: must contain the codec interrupt
- dmas: DMA channels for tx and rx dma. See the DMA client binding,
@@ -21,6 +22,7 @@ Optional properties:
Required properties for the following compatibles:
- "allwinner,sun6i-a31-codec"
+ - "allwinner,sun8i-a23-codec"
- resets: phandle to the reset control for this device
- allwinner,audio-routing: A list of the connections between audio components.
Each entry is a pair of strings, the first being the
@@ -31,10 +33,10 @@ Required properties for the following compatibles:
"HP"
"HPCOM"
"LINEIN"
- "LINEOUT"
+ "LINEOUT" (not on sun8i-a23)
"MIC1"
"MIC2"
- "MIC3"
+ "MIC3" (sun6i-a31 only)
Microphone biases from the SoC:
"HBIAS"
@@ -48,6 +50,11 @@ Required properties for the following compatibles:
"Mic"
"Speaker"
+Required properties for the following compatibles:
+ - "allwinner,sun8i-a23-codec"
+- allwinner,codec-analog-controls: A phandle to the codec analog controls
+ block in the PRCM.
+
Example:
codec: codec@01c22c00 {
#sound-dai-cells = <0>;
diff --git a/sound/soc/sunxi/sun4i-codec.c b/sound/soc/sunxi/sun4i-codec.c
index 092fdcf6de95..ada5fa055950 100644
--- a/sound/soc/sunxi/sun4i-codec.c
+++ b/sound/soc/sunxi/sun4i-codec.c
@@ -213,6 +213,10 @@
/* TODO sun6i DAP (Digital Audio Processing) bits */
+/* FIFO counters moved on A23 */
+#define SUN8I_A23_CODEC_DAC_TXCNT (0x1c)
+#define SUN8I_A23_CODEC_ADC_RXCNT (0x20)
+
struct sun4i_codec {
struct device *dev;
struct regmap *regmap;
@@ -1067,6 +1071,32 @@ static struct snd_soc_codec_driver sun6i_codec_codec = {
},
};
+/* sun8i A23 codec */
+static const struct snd_kcontrol_new sun8i_a23_codec_codec_controls[] = {
+ SOC_SINGLE_TLV("DAC Playback Volume", SUN4I_CODEC_DAC_DPC,
+ SUN4I_CODEC_DAC_DPC_DVOL, 0x3f, 1,
+ sun6i_codec_dvol_scale),
+};
+
+static const struct snd_soc_dapm_widget sun8i_a23_codec_codec_widgets[] = {
+ /* Digital parts of the ADCs */
+ SND_SOC_DAPM_SUPPLY("ADC Enable", SUN6I_CODEC_ADC_FIFOC,
+ SUN6I_CODEC_ADC_FIFOC_EN_AD, 0, NULL, 0),
+ /* Digital parts of the DACs */
+ SND_SOC_DAPM_SUPPLY("DAC Enable", SUN4I_CODEC_DAC_DPC,
+ SUN4I_CODEC_DAC_DPC_EN_DA, 0, NULL, 0),
+
+};
+
+static struct snd_soc_codec_driver sun8i_a23_codec_codec = {
+ .component_driver = {
+ .controls = sun8i_a23_codec_codec_controls,
+ .num_controls = ARRAY_SIZE(sun8i_a23_codec_codec_controls),
+ .dapm_widgets = sun8i_a23_codec_codec_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(sun8i_a23_codec_codec_widgets),
+ },
+};
+
static const struct snd_soc_component_driver sun4i_codec_component = {
.name = "sun4i-codec",
};
@@ -1206,6 +1236,63 @@ static struct snd_soc_card *sun6i_codec_create_card(struct device *dev)
return card;
};
+/* Connect digital side enables to analog side widgets */
+static const struct snd_soc_dapm_route sun8i_codec_card_routes[] = {
+ /* ADC Routes */
+ { "Left ADC", NULL, "ADC Enable" },
+ { "Right ADC", NULL, "ADC Enable" },
+ { "Codec Capture", NULL, "Left ADC" },
+ { "Codec Capture", NULL, "Right ADC" },
+
+ /* DAC Routes */
+ { "Left DAC", NULL, "DAC Enable" },
+ { "Right DAC", NULL, "DAC Enable" },
+ { "Left DAC", NULL, "Codec Playback" },
+ { "Right DAC", NULL, "Codec Playback" },
+};
+
+static struct snd_soc_aux_dev aux_dev = {
+ .name = "Codec Analog Controls",
+};
+
+static struct snd_soc_card *sun8i_a23_codec_create_card(struct device *dev)
+{
+ struct snd_soc_card *card;
+ int ret;
+
+ card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL);
+ if (!card)
+ return ERR_PTR(-ENOMEM);
+
+ aux_dev.codec_of_node = of_parse_phandle(dev->of_node,
+ "allwinner,codec-analog-controls",
+ 0);
+ if (!aux_dev.codec_of_node) {
+ dev_err(dev, "Can't find analog controls for codec.\n");
+ return ERR_PTR(-EINVAL);
+ };
+
+ card->dai_link = sun4i_codec_create_link(dev, &card->num_links);
+ if (!card->dai_link)
+ return ERR_PTR(-ENOMEM);
+
+ card->dev = dev;
+ card->name = "A23 Audio Codec";
+ card->dapm_widgets = sun6i_codec_card_dapm_widgets;
+ card->num_dapm_widgets = ARRAY_SIZE(sun6i_codec_card_dapm_widgets);
+ card->dapm_routes = sun8i_codec_card_routes;
+ card->num_dapm_routes = ARRAY_SIZE(sun8i_codec_card_routes);
+ card->aux_dev = &aux_dev;
+ card->num_aux_devs = 1;
+ card->fully_routed = true;
+
+ ret = snd_soc_of_parse_audio_routing(card, "allwinner,audio-routing");
+ if (ret)
+ dev_warn(dev, "failed to parse audio-routing: %d\n", ret);
+
+ return card;
+};
+
static const struct regmap_config sun4i_codec_regmap_config = {
.reg_bits = 32,
.reg_stride = 4,
@@ -1227,6 +1314,13 @@ static const struct regmap_config sun7i_codec_regmap_config = {
.max_register = SUN7I_CODEC_AC_MIC_PHONE_CAL,
};
+static const struct regmap_config sun8i_a23_codec_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = SUN8I_A23_CODEC_ADC_RXCNT,
+};
+
struct sun4i_codec_quirks {
const struct regmap_config *regmap_config;
const struct snd_soc_codec_driver *codec;
@@ -1265,6 +1359,16 @@ static const struct sun4i_codec_quirks sun7i_codec_quirks = {
.reg_adc_rxdata = SUN4I_CODEC_ADC_RXDATA,
};
+static const struct sun4i_codec_quirks sun8i_a23_codec_quirks = {
+ .regmap_config = &sun8i_a23_codec_regmap_config,
+ .codec = &sun8i_a23_codec_codec,
+ .create_card = sun8i_a23_codec_create_card,
+ .reg_adc_fifoc = REG_FIELD(SUN6I_CODEC_ADC_FIFOC, 0, 31),
+ .reg_dac_txdata = SUN4I_CODEC_DAC_TXDATA,
+ .reg_adc_rxdata = SUN6I_CODEC_ADC_RXDATA,
+ .has_reset = true,
+};
+
static const struct of_device_id sun4i_codec_of_match[] = {
{
.compatible = "allwinner,sun4i-a10-codec",
@@ -1278,6 +1382,10 @@ static const struct of_device_id sun4i_codec_of_match[] = {
.compatible = "allwinner,sun7i-a20-codec",
.data = &sun7i_codec_quirks,
},
+ {
+ .compatible = "allwinner,sun8i-a23-codec",
+ .data = &sun8i_a23_codec_quirks,
+ },
{}
};
MODULE_DEVICE_TABLE(of, sun4i_codec_of_match);
--
2.10.2
^ permalink raw reply related
* [PATCH v2 1/8] mfd: sun6i-prcm: Add codec analog controls sub-device for Allwinner A23
From: Chen-Yu Tsai @ 2016-11-25 12:34 UTC (permalink / raw)
To: Liam Girdwood, Mark Brown, Maxime Ripard, Lee Jones
Cc: devicetree, alsa-devel, linux-kernel, Chen-Yu Tsai,
Mylene Josserand, linux-arm-kernel
In-Reply-To: <20161125123442.28410-1-wens@csie.org>
The PRCM block on the A23 contains a message box like interface to
the registers for the analog path controls of the internal codec.
Add a sub-device for it.
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
---
drivers/mfd/sun6i-prcm.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/drivers/mfd/sun6i-prcm.c b/drivers/mfd/sun6i-prcm.c
index 011fcc555945..2b658bed47db 100644
--- a/drivers/mfd/sun6i-prcm.c
+++ b/drivers/mfd/sun6i-prcm.c
@@ -12,6 +12,9 @@
#include <linux/init.h>
#include <linux/of.h>
+#define SUN8I_CODEC_ANALOG_BASE 0x1c0
+#define SUN8I_CODEC_ANALOG_SIZE 0x4
+
struct prcm_data {
int nsubdevs;
const struct mfd_cell *subdevs;
@@ -57,6 +60,10 @@ static const struct resource sun6i_a31_apb0_rstc_res[] = {
},
};
+static const struct resource sun8i_codec_analog_res[] = {
+ DEFINE_RES_MEM(SUN8I_CODEC_ANALOG_BASE, SUN8I_CODEC_ANALOG_SIZE),
+};
+
static const struct mfd_cell sun6i_a31_prcm_subdevs[] = {
{
.name = "sun6i-a31-ar100-clk",
@@ -109,6 +116,12 @@ static const struct mfd_cell sun8i_a23_prcm_subdevs[] = {
.num_resources = ARRAY_SIZE(sun6i_a31_apb0_rstc_res),
.resources = sun6i_a31_apb0_rstc_res,
},
+ {
+ .name = "sun8i-codec-analog",
+ .of_compatible = "allwinner,sun8i-a23-codec-analog",
+ .num_resources = ARRAY_SIZE(sun8i_codec_analog_res),
+ .resources = sun8i_codec_analog_res,
+ },
};
static const struct prcm_data sun6i_a31_prcm_data = {
--
2.10.2
^ permalink raw reply related
* [PATCH v2 0/8] ASoC: sunxi: Add support for audio codec in A23/H3 SoCs
From: Chen-Yu Tsai @ 2016-11-25 12:34 UTC (permalink / raw)
To: Liam Girdwood, Mark Brown, Maxime Ripard, Lee Jones
Cc: devicetree, alsa-devel, linux-kernel, Chen-Yu Tsai,
Mylene Josserand, linux-arm-kernel
Hi everyone,
This is v2 of my Allwinner A23 and H3 audio codec support series.
Changes since v1:
- Use DEFINE_RES_MEM for the analog path controls block resources.
- Added Rob's ack.
This series adds support for the audio codec found in Allwinner A23 and
H3 SoCs. The design and data paths are similar to the audio codec found
in earlier SoCs such as the A31. The analog audio paths are symmetrical
with left/right channels and down-mix selectors for mono differential
output.
What deviates from previous SoCs is that the analog path controls have
been moved to a separate control bus, accessed through a message box
like register interface in the PRCM block. This necessitates writing
a separate component driver for it, which is then tied into the sound
card as an ASoC auxiliary device.
Patch 1 adds the analog path controls block to the sun6i-prcm driver as
a sub-device, for the A23. The H3 currently does not use the PRCM driver.
Patch 2 adds PCM and card support for the A23 codec to the sun4i-codec
driver.
Patch 3 adds a device node for the analog path controls block to the A23
dtsi.
Patch 4 adds a device node for the audio codec, and the phandle for the
analog path controls block to the A23 dtsi.
Patch 5 enables the audio codec for the A23 Q8 tablets. On these tablets
the headphone output is driven in DC coupled, or "direct drive", mode.
Patch 6 adds PCM and card support for the H3 codec to the sun4i-codec
driver.
Patch 7 adds device nodes for the audio codec and analog path controls
block to the H3 dtsi.
Patch 8 enables the audio codec on the Orange Pi PC. The audio output
jack on the board is tied to the line out pins on the SoC.
Please take a look and let me know what you think.
In addition, the sun4i-codec driver is getting pretty large. Maybe we
want to split the different parts into different files?
Regards
ChenYu
Chen-Yu Tsai (8):
mfd: sun6i-prcm: Add codec analog controls sub-device for Allwinner
A23
ASoC: sun4i-codec: Add support for A23 codec
ARM: dts: sun8i: Add codec analog path controls node in PRCM for
A23/A33
ARM: dts: sun8i-a23: Add device node for internal audio codec
ARM: dts: sun8i-a23: q8-tablet: Enable internal audio codec
ASoC: sun4i-codec: Add support for H3 codec
ARM: dts: sun8i-h3: Add device nodes for audio codec and its analog
controls
ARM: dts: sun8i-h3: orange-pi-pc: Enable audio codec
.../devicetree/bindings/sound/sun4i-codec.txt | 14 +-
arch/arm/boot/dts/sun8i-a23-a33.dtsi | 4 +
arch/arm/boot/dts/sun8i-a23-q8-tablet.dts | 23 +++
arch/arm/boot/dts/sun8i-a23.dtsi | 16 ++
arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts | 8 +
arch/arm/boot/dts/sun8i-h3.dtsi | 19 +++
drivers/mfd/sun6i-prcm.c | 13 ++
sound/soc/sunxi/sun4i-codec.c | 179 +++++++++++++++++++++
8 files changed, 274 insertions(+), 2 deletions(-)
--
2.10.2
^ permalink raw reply
* [PATCH v10 4/4] tests: Add overlay tests
From: Pantelis Antoniou @ 2016-11-25 12:32 UTC (permalink / raw)
To: David Gibson
Cc: Jon Loeliger, Grant Likely, Frank Rowand, Rob Herring, Jan Luebbe,
Sascha Hauer, Phil Elwell, Simon Glass, Maxime Ripard,
Thomas Petazzoni, Boris Brezillon, Antoine Tenart, Stephen Boyd,
Devicetree Compiler, devicetree-u79uwXL29TY76Z2rM5mHXA,
Pantelis Antoniou
In-Reply-To: <1480077131-14526-1-git-send-email-pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w@public.gmane.org>
Add a number of tests for dynamic objects/overlays.
Re-use the original test by moving the contents to a .dtsi include
Signed-off-by: Pantelis Antoniou <pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w@public.gmane.org>
---
tests/overlay_overlay_dtc.dts | 76 +----------------------------------
tests/overlay_overlay_dtc.dtsi | 83 +++++++++++++++++++++++++++++++++++++++
tests/overlay_overlay_new_dtc.dts | 11 ++++++
tests/overlay_overlay_simple.dts | 12 ++++++
tests/run_tests.sh | 20 ++++++++++
5 files changed, 127 insertions(+), 75 deletions(-)
create mode 100644 tests/overlay_overlay_dtc.dtsi
create mode 100644 tests/overlay_overlay_new_dtc.dts
create mode 100644 tests/overlay_overlay_simple.dts
diff --git a/tests/overlay_overlay_dtc.dts b/tests/overlay_overlay_dtc.dts
index 30d2362..ca943ea 100644
--- a/tests/overlay_overlay_dtc.dts
+++ b/tests/overlay_overlay_dtc.dts
@@ -8,78 +8,4 @@
/dts-v1/;
/plugin/;
-/ {
- /* Test that we can change an int by another */
- fragment@0 {
- target = <&test>;
-
- __overlay__ {
- test-int-property = <43>;
- };
- };
-
- /* Test that we can replace a string by a longer one */
- fragment@1 {
- target = <&test>;
-
- __overlay__ {
- test-str-property = "foobar";
- };
- };
-
- /* Test that we add a new property */
- fragment@2 {
- target = <&test>;
-
- __overlay__ {
- test-str-property-2 = "foobar2";
- };
- };
-
- /* Test that we add a new node (by phandle) */
- fragment@3 {
- target = <&test>;
-
- __overlay__ {
- new-node {
- new-property;
- };
- };
- };
-
- fragment@5 {
- target = <&test>;
-
- __overlay__ {
- local: new-local-node {
- new-property;
- };
- };
- };
-
- fragment@6 {
- target = <&test>;
-
- __overlay__ {
- test-phandle = <&test>, <&local>;
- };
- };
-
- fragment@7 {
- target = <&test>;
-
- __overlay__ {
- test-several-phandle = <&local>, <&local>;
- };
- };
-
- fragment@8 {
- target = <&test>;
-
- __overlay__ {
- sub-test-node {
- new-sub-test-property;
- };
- };
- };
-};
+/include/ "overlay_overlay_dtc.dtsi"
diff --git a/tests/overlay_overlay_dtc.dtsi b/tests/overlay_overlay_dtc.dtsi
new file mode 100644
index 0000000..8ea8d5d
--- /dev/null
+++ b/tests/overlay_overlay_dtc.dtsi
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2016 NextThing Co
+ * Copyright (c) 2016 Free Electrons
+ * Copyright (c) 2016 Konsulko Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+/ {
+ /* Test that we can change an int by another */
+ fragment@0 {
+ target = <&test>;
+
+ __overlay__ {
+ test-int-property = <43>;
+ };
+ };
+
+ /* Test that we can replace a string by a longer one */
+ fragment@1 {
+ target = <&test>;
+
+ __overlay__ {
+ test-str-property = "foobar";
+ };
+ };
+
+ /* Test that we add a new property */
+ fragment@2 {
+ target = <&test>;
+
+ __overlay__ {
+ test-str-property-2 = "foobar2";
+ };
+ };
+
+ /* Test that we add a new node (by phandle) */
+ fragment@3 {
+ target = <&test>;
+
+ __overlay__ {
+ new-node {
+ new-property;
+ };
+ };
+ };
+
+ fragment@5 {
+ target = <&test>;
+
+ __overlay__ {
+ local: new-local-node {
+ new-property;
+ };
+ };
+ };
+
+ fragment@6 {
+ target = <&test>;
+
+ __overlay__ {
+ test-phandle = <&test>, <&local>;
+ };
+ };
+
+ fragment@7 {
+ target = <&test>;
+
+ __overlay__ {
+ test-several-phandle = <&local>, <&local>;
+ };
+ };
+
+ fragment@8 {
+ target = <&test>;
+
+ __overlay__ {
+ sub-test-node {
+ new-sub-test-property;
+ };
+ };
+ };
+};
diff --git a/tests/overlay_overlay_new_dtc.dts b/tests/overlay_overlay_new_dtc.dts
new file mode 100644
index 0000000..14d3f54
--- /dev/null
+++ b/tests/overlay_overlay_new_dtc.dts
@@ -0,0 +1,11 @@
+/*
+ * Copyright (c) 2016 NextThing Co
+ * Copyright (c) 2016 Free Electrons
+ * Copyright (c) 2016 Konsulko Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+/dts-v1/ /plugin/;
+
+/include/ "overlay_overlay_dtc.dtsi"
diff --git a/tests/overlay_overlay_simple.dts b/tests/overlay_overlay_simple.dts
new file mode 100644
index 0000000..8657e1e
--- /dev/null
+++ b/tests/overlay_overlay_simple.dts
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2016 Konsulko Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+/dts-v1/;
+/plugin/;
+
+&test {
+ test-int-property = <43>;
+};
diff --git a/tests/run_tests.sh b/tests/run_tests.sh
index e4139dd..99c09bc 100755
--- a/tests/run_tests.sh
+++ b/tests/run_tests.sh
@@ -181,6 +181,26 @@ overlay_tests () {
run_dtc_test -@ -I dts -O dtb -o overlay_base_with_symbols.test.dtb overlay_base.dts
run_dtc_test -@ -I dts -O dtb -o overlay_overlay_with_symbols.test.dtb overlay_overlay_dtc.dts
run_test overlay overlay_base_with_symbols.test.dtb overlay_overlay_with_symbols.test.dtb
+
+ # new /plugin/ format
+ run_dtc_test -@ -I dts -O dtb -o overlay_overlay_new_with_symbols.test.dtb overlay_overlay_new_dtc.dts
+
+ # test new magic option
+ run_dtc_test -M@ -I dts -O dtb -o overlay_overlay_with_symbols_new_magic.test.dtb overlay_overlay_dtc.dts
+
+ # test plugin source to dtb and back
+ run_dtc_test -@ -I dtb -O dts -o overlay_overlay_dtc.test.dts overlay_overlay_with_symbols.test.dtb
+ run_dtc_test -@ -I dts -O dtb -o overlay_overlay_with_symbols.test.test.dtb overlay_overlay_dtc.test.dts
+ run_test dtbs_equal_ordered overlay_overlay_with_symbols.test.dtb overlay_overlay_with_symbols.test.test.dtb
+
+ # test simplified plugin syntax
+ run_dtc_test -@ -I dts -O dtb -o overlay_overlay_simple.dtb overlay_overlay_simple.dts
+
+ # test plugin source to dtb and back (with new magic)
+ run_dtc_test -@ -I dtb -O dts -o overlay_overlay_dtc_new_magic.test.dts overlay_overlay_with_symbols_new_magic.test.dtb
+ run_dtc_test -@ -I dts -O dtb -o overlay_overlay_with_symbols_new_magic.test.test.dtb overlay_overlay_dtc_new_magic.test.dts
+ run_test dtbs_equal_ordered overlay_overlay_with_symbols_new_magic.test.dtb overlay_overlay_with_symbols_new_magic.test.test.dtb
+
fi
# Bad fixup tests
--
2.1.4
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH v10 3/4] dtc: Plugin and fixup support
From: Pantelis Antoniou @ 2016-11-25 12:32 UTC (permalink / raw)
To: David Gibson
Cc: Jon Loeliger, Grant Likely, Frank Rowand, Rob Herring, Jan Luebbe,
Sascha Hauer, Phil Elwell, Simon Glass, Maxime Ripard,
Thomas Petazzoni, Boris Brezillon, Antoine Tenart, Stephen Boyd,
Devicetree Compiler, devicetree-u79uwXL29TY76Z2rM5mHXA,
Pantelis Antoniou
In-Reply-To: <1480077131-14526-1-git-send-email-pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w@public.gmane.org>
This patch enable the generation of symbols & local fixup information
for trees compiled with the -@ (--symbols) option.
Using this patch labels in the tree and their users emit information
in __symbols__ and __local_fixups__ nodes.
The __fixups__ node make possible the dynamic resolution of phandle
references which are present in the plugin tree but lie in the
tree that are applying the overlay against.
While there is a new magic number for dynamic device tree/overlays blobs
it is by default enabled. Remember to use -M to generate compatible
blobs.
Signed-off-by: Pantelis Antoniou <pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w@public.gmane.org>
Signed-off-by: Sascha Hauer <s.hauer-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
Signed-off-by: Jan Luebbe <jlu-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
---
Documentation/manual.txt | 25 +++++-
checks.c | 8 +-
dtc-lexer.l | 5 ++
dtc-parser.y | 50 +++++++++--
dtc.c | 39 +++++++-
dtc.h | 20 ++++-
fdtdump.c | 2 +-
flattree.c | 17 ++--
fstree.c | 2 +-
libfdt/fdt.c | 2 +-
libfdt/fdt.h | 3 +-
livetree.c | 225 ++++++++++++++++++++++++++++++++++++++++++++++-
tests/mangle-layout.c | 7 +-
13 files changed, 375 insertions(+), 30 deletions(-)
diff --git a/Documentation/manual.txt b/Documentation/manual.txt
index 398de32..094893b 100644
--- a/Documentation/manual.txt
+++ b/Documentation/manual.txt
@@ -119,6 +119,24 @@ Options:
Make space for <number> reserve map entries
Relevant for dtb and asm output only.
+ -@
+ Generates a __symbols__ node at the root node of the resulting blob
+ for any node labels used, and for any local references using phandles
+ it also generates a __local_fixups__ node that tracks them.
+
+ When using the /plugin/ tag all unresolved label references to
+ be tracked in the __fixups__ node, making dynamic resolution possible.
+
+ -A
+ Generate automatically aliases for all node labels. This is similar to
+ the -@ option (the __symbols__ node contain identical information) but
+ the semantics are slightly different since no phandles are automatically
+ generated for labeled nodes.
+
+ -M
+ Generate blobs with the old FDT magic number for device tree objects.
+ By default blobs use the DTBO FDT magic number instead.
+
-S <bytes>
Ensure the blob at least <bytes> long, adding additional
space if needed.
@@ -146,13 +164,18 @@ Additionally, dtc performs various sanity checks on the tree.
Here is a very rough overview of the layout of a DTS source file:
- sourcefile: list_of_memreserve devicetree
+ sourcefile: versioninfo plugindecl list_of_memreserve devicetree
memreserve: label 'memreserve' ADDR ADDR ';'
| label 'memreserve' ADDR '-' ADDR ';'
devicetree: '/' nodedef
+ versioninfo: '/' 'dts-v1' '/' ';'
+
+ plugindecl: '/' 'plugin' '/' ';'
+ | /* empty */
+
nodedef: '{' list_of_property list_of_subnode '}' ';'
property: label PROPNAME '=' propdata ';'
diff --git a/checks.c b/checks.c
index 2bd27a4..4292f4b 100644
--- a/checks.c
+++ b/checks.c
@@ -487,8 +487,12 @@ static void fixup_phandle_references(struct check *c, struct boot_info *bi,
refnode = get_node_by_ref(dt, m->ref);
if (! refnode) {
- FAIL(c, "Reference to non-existent node or label \"%s\"\n",
- m->ref);
+ if (!(bi->versionflags & VF_PLUGIN))
+ FAIL(c, "Reference to non-existent node or "
+ "label \"%s\"\n", m->ref);
+ else /* mark the entry as unresolved */
+ *((cell_t *)(prop->val.val + m->offset)) =
+ cpu_to_fdt32(0xffffffff);
continue;
}
diff --git a/dtc-lexer.l b/dtc-lexer.l
index 790fbf6..40bbc87 100644
--- a/dtc-lexer.l
+++ b/dtc-lexer.l
@@ -121,6 +121,11 @@ static void lexical_error(const char *fmt, ...);
return DT_V1;
}
+<*>"/plugin/" {
+ DPRINT("Keyword: /plugin/\n");
+ return DT_PLUGIN;
+ }
+
<*>"/memreserve/" {
DPRINT("Keyword: /memreserve/\n");
BEGIN_DEFAULT();
diff --git a/dtc-parser.y b/dtc-parser.y
index 14aaf2e..1a1f660 100644
--- a/dtc-parser.y
+++ b/dtc-parser.y
@@ -19,6 +19,7 @@
*/
%{
#include <stdio.h>
+#include <inttypes.h>
#include "dtc.h"
#include "srcpos.h"
@@ -33,6 +34,7 @@ extern void yyerror(char const *s);
extern struct boot_info *the_boot_info;
extern bool treesource_error;
+
%}
%union {
@@ -52,9 +54,11 @@ extern bool treesource_error;
struct node *nodelist;
struct reserve_info *re;
uint64_t integer;
+ unsigned int flags;
}
%token DT_V1
+%token DT_PLUGIN
%token DT_MEMRESERVE
%token DT_LSHIFT DT_RSHIFT DT_LE DT_GE DT_EQ DT_NE DT_AND DT_OR
%token DT_BITS
@@ -71,6 +75,8 @@ extern bool treesource_error;
%type <data> propdata
%type <data> propdataprefix
+%type <flags> versioninfo
+%type <flags> plugindecl
%type <re> memreserve
%type <re> memreserves
%type <array> arrayprefix
@@ -101,16 +107,34 @@ extern bool treesource_error;
%%
sourcefile:
- v1tag memreserves devicetree
+ versioninfo plugindecl memreserves devicetree
+ {
+ the_boot_info = build_boot_info($1 | $2, $3, $4,
+ guess_boot_cpuid($4));
+ }
+ ;
+
+versioninfo:
+ v1tag
{
- the_boot_info = build_boot_info($2, $3,
- guess_boot_cpuid($3));
+ $$ = VF_DT_V1;
}
;
v1tag:
DT_V1 ';'
+ | DT_V1
| DT_V1 ';' v1tag
+
+plugindecl:
+ DT_PLUGIN ';'
+ {
+ $$ = VF_PLUGIN;
+ }
+ | /* empty */
+ {
+ $$ = 0;
+ }
;
memreserves:
@@ -161,10 +185,19 @@ devicetree:
{
struct node *target = get_node_by_ref($1, $2);
- if (target)
+ if (target) {
merge_nodes(target, $3);
- else
- ERROR(&@2, "Label or path %s not found", $2);
+ } else {
+ /*
+ * We rely on the rule being always:
+ * versioninfo plugindecl memreserves devicetree
+ * so $-1 is what we want (plugindecl)
+ */
+ if ($<flags>-1 & VF_PLUGIN)
+ add_orphan_node($1, $3, $2);
+ else
+ ERROR(&@2, "Label or path %s not found", $2);
+ }
$$ = $1;
}
| devicetree DT_DEL_NODE DT_REF ';'
@@ -179,6 +212,11 @@ devicetree:
$$ = $1;
}
+ | /* empty */
+ {
+ /* build empty node */
+ $$ = name_node(build_node(NULL, NULL), "");
+ }
;
nodedef:
diff --git a/dtc.c b/dtc.c
index 9dcf640..06e91bc 100644
--- a/dtc.c
+++ b/dtc.c
@@ -32,6 +32,9 @@ int minsize; /* Minimum blob size */
int padsize; /* Additional padding to blob */
int alignsize; /* Additional padding to blob accroding to the alignsize */
int phandle_format = PHANDLE_BOTH; /* Use linux,phandle or phandle properties */
+int symbol_fixup_support; /* enable symbols & fixup support */
+int auto_label_aliases; /* auto generate labels -> aliases */
+int no_dtbo_magic; /* use old FDT magic values for objects */
static int is_power_of_2(int x)
{
@@ -59,7 +62,7 @@ static void fill_fullpaths(struct node *tree, const char *prefix)
#define FDT_VERSION(version) _FDT_VERSION(version)
#define _FDT_VERSION(version) #version
static const char usage_synopsis[] = "dtc [options] <input file>";
-static const char usage_short_opts[] = "qI:O:o:V:d:R:S:p:a:fb:i:H:sW:E:hv";
+static const char usage_short_opts[] = "qI:O:o:V:d:R:S:p:a:fb:i:H:sW:E:@AMhv";
static struct option const usage_long_opts[] = {
{"quiet", no_argument, NULL, 'q'},
{"in-format", a_argument, NULL, 'I'},
@@ -78,6 +81,9 @@ static struct option const usage_long_opts[] = {
{"phandle", a_argument, NULL, 'H'},
{"warning", a_argument, NULL, 'W'},
{"error", a_argument, NULL, 'E'},
+ {"symbols", no_argument, NULL, '@'},
+ {"auto-alias", no_argument, NULL, 'A'},
+ {"no-dtbo-magic", no_argument, NULL, 'M'},
{"help", no_argument, NULL, 'h'},
{"version", no_argument, NULL, 'v'},
{NULL, no_argument, NULL, 0x0},
@@ -109,6 +115,9 @@ static const char * const usage_opts_help[] = {
"\t\tboth - Both \"linux,phandle\" and \"phandle\" properties",
"\n\tEnable/disable warnings (prefix with \"no-\")",
"\n\tEnable/disable errors (prefix with \"no-\")",
+ "\n\tEnable symbols/fixup support",
+ "\n\tEnable auto-alias of labels",
+ "\n\tDo not use DTBO magic value for plugin objects",
"\n\tPrint this help and exit",
"\n\tPrint version and exit",
NULL,
@@ -153,7 +162,7 @@ static const char *guess_input_format(const char *fname, const char *fallback)
fclose(f);
magic = fdt32_to_cpu(magic);
- if (magic == FDT_MAGIC)
+ if (magic == FDT_MAGIC || magic == FDT_MAGIC_DTBO)
return "dtb";
return guess_type_by_name(fname, fallback);
@@ -172,6 +181,7 @@ int main(int argc, char *argv[])
FILE *outf = NULL;
int outversion = DEFAULT_FDT_VERSION;
long long cmdline_boot_cpuid = -1;
+ fdt32_t out_magic = FDT_MAGIC;
quiet = 0;
reservenum = 0;
@@ -249,6 +259,16 @@ int main(int argc, char *argv[])
parse_checks_option(false, true, optarg);
break;
+ case '@':
+ symbol_fixup_support = 1;
+ break;
+ case 'A':
+ auto_label_aliases = 1;
+ break;
+ case 'M':
+ no_dtbo_magic = 1;
+ break;
+
case 'h':
usage(NULL);
default:
@@ -306,6 +326,14 @@ int main(int argc, char *argv[])
fill_fullpaths(bi->dt, "");
process_checks(force, bi);
+ if (auto_label_aliases)
+ generate_label_tree(bi->dt, "aliases", false);
+
+ if (symbol_fixup_support) {
+ generate_label_tree(bi->dt, "__symbols__", true);
+ generate_fixups_tree(bi->dt);
+ }
+
if (sort)
sort_tree(bi);
@@ -318,12 +346,15 @@ int main(int argc, char *argv[])
outname, strerror(errno));
}
+ if (!no_dtbo_magic && (bi->versionflags & VF_PLUGIN))
+ out_magic = FDT_MAGIC_DTBO;
+
if (streq(outform, "dts")) {
dt_to_source(outf, bi);
} else if (streq(outform, "dtb")) {
- dt_to_blob(outf, bi, outversion);
+ dt_to_blob(outf, bi, out_magic, outversion);
} else if (streq(outform, "asm")) {
- dt_to_asm(outf, bi, outversion);
+ dt_to_asm(outf, bi, out_magic, outversion);
} else if (streq(outform, "null")) {
/* do nothing */
} else {
diff --git a/dtc.h b/dtc.h
index 32009bc..581b3bf 100644
--- a/dtc.h
+++ b/dtc.h
@@ -55,6 +55,9 @@ extern int minsize; /* Minimum blob size */
extern int padsize; /* Additional padding to blob */
extern int alignsize; /* Additional padding to blob accroding to the alignsize */
extern int phandle_format; /* Use linux,phandle or phandle properties */
+extern int symbol_fixup_support;/* enable symbols & fixup support */
+extern int auto_label_aliases; /* auto generate labels -> aliases */
+extern int no_dtbo_magic; /* use old FDT magic values for objects */
#define PHANDLE_LEGACY 0x1
#define PHANDLE_EPAPR 0x2
@@ -195,6 +198,7 @@ struct node *build_node_delete(void);
struct node *name_node(struct node *node, char *name);
struct node *chain_node(struct node *first, struct node *list);
struct node *merge_nodes(struct node *old_node, struct node *new_node);
+void add_orphan_node(struct node *old_node, struct node *new_node, char *ref);
void add_property(struct node *node, struct property *prop);
void delete_property_by_name(struct node *node, char *name);
@@ -202,6 +206,8 @@ void delete_property(struct property *prop);
void add_child(struct node *parent, struct node *child);
void delete_node_by_name(struct node *parent, char *name);
void delete_node(struct node *node);
+void append_to_property(struct node *node,
+ char *name, const void *data, int len);
const char *get_unitname(struct node *node);
struct property *get_property(struct node *node, const char *propname);
@@ -237,14 +243,22 @@ struct reserve_info *add_reserve_entry(struct reserve_info *list,
struct boot_info {
+ unsigned int versionflags;
struct reserve_info *reservelist;
struct node *dt; /* the device tree */
uint32_t boot_cpuid_phys;
};
-struct boot_info *build_boot_info(struct reserve_info *reservelist,
+/* version flags definitions */
+#define VF_DT_V1 0x0001 /* /dts-v1/ */
+#define VF_PLUGIN 0x0002 /* /plugin/ */
+
+struct boot_info *build_boot_info(unsigned int versionflags,
+ struct reserve_info *reservelist,
struct node *tree, uint32_t boot_cpuid_phys);
void sort_tree(struct boot_info *bi);
+void generate_label_tree(struct node *dt, char *gen_node_name, bool allocph);
+void generate_fixups_tree(struct node *dt);
/* Checks */
@@ -253,8 +267,8 @@ void process_checks(bool force, struct boot_info *bi);
/* Flattened trees */
-void dt_to_blob(FILE *f, struct boot_info *bi, int version);
-void dt_to_asm(FILE *f, struct boot_info *bi, int version);
+void dt_to_blob(FILE *f, struct boot_info *bi, fdt32_t magic, int version);
+void dt_to_asm(FILE *f, struct boot_info *bi, fdt32_t magic, int version);
struct boot_info *dt_from_blob(const char *fname);
diff --git a/fdtdump.c b/fdtdump.c
index a9a2484..dd63ac2 100644
--- a/fdtdump.c
+++ b/fdtdump.c
@@ -201,7 +201,7 @@ int main(int argc, char *argv[])
p = memchr(p, smagic[0], endp - p - FDT_MAGIC_SIZE);
if (!p)
break;
- if (fdt_magic(p) == FDT_MAGIC) {
+ if (fdt_magic(p) == FDT_MAGIC || fdt_magic(p) == FDT_MAGIC_DTBO) {
/* try and validate the main struct */
off_t this_len = endp - p;
fdt32_t max_version = 17;
diff --git a/flattree.c b/flattree.c
index a9d9520..57d76cf 100644
--- a/flattree.c
+++ b/flattree.c
@@ -335,6 +335,7 @@ static struct data flatten_reserve_list(struct reserve_info *reservelist,
}
static void make_fdt_header(struct fdt_header *fdt,
+ fdt32_t magic,
struct version_info *vi,
int reservesize, int dtsize, int strsize,
int boot_cpuid_phys)
@@ -345,7 +346,7 @@ static void make_fdt_header(struct fdt_header *fdt,
memset(fdt, 0xff, sizeof(*fdt));
- fdt->magic = cpu_to_fdt32(FDT_MAGIC);
+ fdt->magic = cpu_to_fdt32(magic);
fdt->version = cpu_to_fdt32(vi->version);
fdt->last_comp_version = cpu_to_fdt32(vi->last_comp_version);
@@ -366,7 +367,7 @@ static void make_fdt_header(struct fdt_header *fdt,
fdt->size_dt_struct = cpu_to_fdt32(dtsize);
}
-void dt_to_blob(FILE *f, struct boot_info *bi, int version)
+void dt_to_blob(FILE *f, struct boot_info *bi, fdt32_t magic, int version)
{
struct version_info *vi = NULL;
int i;
@@ -390,7 +391,7 @@ void dt_to_blob(FILE *f, struct boot_info *bi, int version)
reservebuf = flatten_reserve_list(bi->reservelist, vi);
/* Make header */
- make_fdt_header(&fdt, vi, reservebuf.len, dtbuf.len, strbuf.len,
+ make_fdt_header(&fdt, magic, vi, reservebuf.len, dtbuf.len, strbuf.len,
bi->boot_cpuid_phys);
/*
@@ -467,7 +468,7 @@ static void dump_stringtable_asm(FILE *f, struct data strbuf)
}
}
-void dt_to_asm(FILE *f, struct boot_info *bi, int version)
+void dt_to_asm(FILE *f, struct boot_info *bi, fdt32_t magic, int version)
{
struct version_info *vi = NULL;
int i;
@@ -830,6 +831,7 @@ struct boot_info *dt_from_blob(const char *fname)
struct node *tree;
uint32_t val;
int flags = 0;
+ unsigned int versionflags = VF_DT_V1;
f = srcfile_relative_open(fname, NULL);
@@ -845,9 +847,12 @@ struct boot_info *dt_from_blob(const char *fname)
}
magic = fdt32_to_cpu(magic);
- if (magic != FDT_MAGIC)
+ if (magic != FDT_MAGIC && magic != FDT_MAGIC_DTBO)
die("Blob has incorrect magic number\n");
+ if (magic == FDT_MAGIC_DTBO)
+ versionflags |= VF_PLUGIN;
+
rc = fread(&totalsize, sizeof(totalsize), 1, f);
if (ferror(f))
die("Error reading DT blob size: %s\n", strerror(errno));
@@ -942,5 +947,5 @@ struct boot_info *dt_from_blob(const char *fname)
fclose(f);
- return build_boot_info(reservelist, tree, boot_cpuid_phys);
+ return build_boot_info(versionflags, reservelist, tree, boot_cpuid_phys);
}
diff --git a/fstree.c b/fstree.c
index 6d1beec..54f520b 100644
--- a/fstree.c
+++ b/fstree.c
@@ -86,6 +86,6 @@ struct boot_info *dt_from_fs(const char *dirname)
tree = read_fstree(dirname);
tree = name_node(tree, "");
- return build_boot_info(NULL, tree, guess_boot_cpuid(tree));
+ return build_boot_info(VF_DT_V1, NULL, tree, guess_boot_cpuid(tree));
}
diff --git a/libfdt/fdt.c b/libfdt/fdt.c
index 22286a1..28d422c 100644
--- a/libfdt/fdt.c
+++ b/libfdt/fdt.c
@@ -57,7 +57,7 @@
int fdt_check_header(const void *fdt)
{
- if (fdt_magic(fdt) == FDT_MAGIC) {
+ if (fdt_magic(fdt) == FDT_MAGIC || fdt_magic(fdt) == FDT_MAGIC_DTBO) {
/* Complete tree */
if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION)
return -FDT_ERR_BADVERSION;
diff --git a/libfdt/fdt.h b/libfdt/fdt.h
index 526aedb..493cd55 100644
--- a/libfdt/fdt.h
+++ b/libfdt/fdt.h
@@ -55,7 +55,7 @@
#ifndef __ASSEMBLY__
struct fdt_header {
- fdt32_t magic; /* magic word FDT_MAGIC */
+ fdt32_t magic; /* magic word FDT_MAGIC[|_DTBO] */
fdt32_t totalsize; /* total size of DT block */
fdt32_t off_dt_struct; /* offset to structure */
fdt32_t off_dt_strings; /* offset to strings */
@@ -93,6 +93,7 @@ struct fdt_property {
#endif /* !__ASSEMBLY */
#define FDT_MAGIC 0xd00dfeed /* 4: version, 4: total size */
+#define FDT_MAGIC_DTBO 0xd00dfdb0 /* DTBO magic */
#define FDT_TAGSIZE sizeof(fdt32_t)
#define FDT_BEGIN_NODE 0x1 /* Start node: full name */
diff --git a/livetree.c b/livetree.c
index 3dc7559..f2c86bd 100644
--- a/livetree.c
+++ b/livetree.c
@@ -216,6 +216,31 @@ struct node *merge_nodes(struct node *old_node, struct node *new_node)
return old_node;
}
+void add_orphan_node(struct node *dt, struct node *new_node, char *ref)
+{
+ static unsigned int next_orphan_fragment = 0;
+ struct node *node = build_node(NULL, NULL);
+ struct property *p;
+ struct data d = empty_data;
+ char *name;
+
+ memset(node, 0, sizeof(*node));
+
+ d = data_add_marker(d, REF_PHANDLE, ref);
+ d = data_append_integer(d, 0xffffffff, 32);
+
+ p = build_property("target", d);
+ add_property(node, p);
+
+ xasprintf(&name, "fragment@%u",
+ next_orphan_fragment++);
+ name_node(node, name);
+ name_node(new_node, "__overlay__");
+
+ add_child(dt, node);
+ add_child(node, new_node);
+}
+
struct node *chain_node(struct node *first, struct node *list)
{
assert(first->next_sibling == NULL);
@@ -296,6 +321,23 @@ void delete_node(struct node *node)
delete_labels(&node->labels);
}
+void append_to_property(struct node *node,
+ char *name, const void *data, int len)
+{
+ struct data d;
+ struct property *p;
+
+ p = get_property(node, name);
+ if (p) {
+ d = data_append_data(p->val, data, len);
+ p->val = d;
+ } else {
+ d = data_append_data(empty_data, data, len);
+ p = build_property(name, d);
+ add_property(node, p);
+ }
+}
+
struct reserve_info *build_reserve_entry(uint64_t address, uint64_t size)
{
struct reserve_info *new = xmalloc(sizeof(*new));
@@ -335,12 +377,14 @@ struct reserve_info *add_reserve_entry(struct reserve_info *list,
return list;
}
-struct boot_info *build_boot_info(struct reserve_info *reservelist,
+struct boot_info *build_boot_info(unsigned int versionflags,
+ struct reserve_info *reservelist,
struct node *tree, uint32_t boot_cpuid_phys)
{
struct boot_info *bi;
bi = xmalloc(sizeof(*bi));
+ bi->versionflags = versionflags;
bi->reservelist = reservelist;
bi->dt = tree;
bi->boot_cpuid_phys = boot_cpuid_phys;
@@ -709,3 +753,182 @@ void sort_tree(struct boot_info *bi)
sort_reserve_entries(bi);
sort_node(bi->dt);
}
+
+/* utility helper to avoid code duplication */
+static struct node *build_and_name_child_node(struct node *parent, char *name)
+{
+ struct node *node;
+
+ node = build_node(NULL, NULL);
+ name_node(node, xstrdup(name));
+ add_child(parent, node);
+
+ return node;
+}
+
+static void generate_label_tree_internal(struct node *dt, struct node *node,
+ struct node *an, bool allocph)
+{
+ struct node *c;
+ struct property *p;
+ struct label *l;
+
+ /* if if there are labels */
+ if (node->labels) {
+ /* now add the label in the node */
+ for_each_label(node->labels, l) {
+ /* check whether the label already exists */
+ p = get_property(an, l->label);
+ if (p) {
+ fprintf(stderr, "WARNING: label %s already"
+ " exists in /%s", l->label,
+ an->name);
+ continue;
+ }
+
+ /* insert it */
+ p = build_property(l->label,
+ data_copy_mem(node->fullpath,
+ strlen(node->fullpath) + 1));
+ add_property(an, p);
+ }
+
+ /* force allocation of a phandle for this node */
+ if (allocph)
+ (void)get_node_phandle(dt, node);
+ }
+
+ for_each_child(node, c)
+ generate_label_tree_internal(dt, c, an, allocph);
+}
+
+void generate_label_tree(struct node *dt, char *gen_node_name, bool allocph)
+{
+ struct node *an;
+
+ for_each_child(dt, an)
+ if (streq(gen_node_name, an->name))
+ break;
+
+ if (!an)
+ an = build_and_name_child_node(dt, gen_node_name);
+ if (!an)
+ die("Could not build label node /%s\n", gen_node_name);
+
+ generate_label_tree_internal(dt, dt, an, allocph);
+}
+
+#define FIXUPS "__fixups__"
+#define LOCAL_FIXUPS "__local_fixups__"
+
+static void add_fixup_entry(struct node *dt, struct node *node,
+ struct property *prop, struct marker *m)
+{
+ struct node *fn; /* fixup node */
+ char *entry;
+
+ /* m->ref can only be a REF_PHANDLE, but check anyway */
+ assert(m->type == REF_PHANDLE);
+
+ /* fn is the node we're putting entries in */
+ fn = get_subnode(dt, FIXUPS);
+ assert(fn != NULL);
+
+ /* there shouldn't be any ':' in the arguments */
+ if (strchr(node->fullpath, ':') || strchr(prop->name, ':'))
+ die("arguments should not contain ':'\n");
+
+ xasprintf(&entry, "%s:%s:%u",
+ node->fullpath, prop->name, m->offset);
+ append_to_property(fn, m->ref, entry, strlen(entry) + 1);
+}
+
+static void add_local_fixup_entry(struct node *dt, struct node *node,
+ struct property *prop, struct marker *m,
+ struct node *refnode)
+{
+ struct node *lfn, *wn, *nwn; /* local fixup node, walk node, new */
+ uint32_t value_32;
+ char *s, *e, *comp;
+ int len;
+
+ /* fn is the node we're putting entries in */
+ lfn = get_subnode(dt, LOCAL_FIXUPS);
+ assert(lfn != NULL);
+
+ /* walk the path components creating nodes if they don't exist */
+ comp = xmalloc(strlen(node->fullpath) + 1);
+ /* start skipping the first / */
+ s = node->fullpath + 1;
+ wn = lfn;
+ while (*s) {
+ /* retrieve path component */
+ e = strchr(s, '/');
+ if (e == NULL)
+ e = s + strlen(s);
+ len = e - s;
+ memcpy(comp, s, len);
+ comp[len] = '\0';
+
+ /* if no node exists, create it */
+ nwn = get_subnode(wn, comp);
+ if (!nwn)
+ nwn = build_and_name_child_node(wn, comp);
+ wn = nwn;
+
+ /* last path component */
+ if (!*e)
+ break;
+
+ /* next path component */
+ s = e + 1;
+ }
+ free(comp);
+
+ value_32 = cpu_to_fdt32(m->offset);
+ append_to_property(wn, prop->name, &value_32, sizeof(value_32));
+}
+
+static void generate_fixups_tree_internal(struct node *dt, struct node *node)
+{
+ struct node *c;
+ struct property *prop;
+ struct marker *m;
+ struct node *refnode;
+
+ for_each_property(node, prop) {
+ m = prop->val.markers;
+ for_each_marker_of_type(m, REF_PHANDLE) {
+ refnode = get_node_by_ref(dt, m->ref);
+ if (!refnode)
+ add_fixup_entry(dt, node, prop, m);
+ else
+ add_local_fixup_entry(dt, node, prop, m,
+ refnode);
+ }
+ }
+
+ for_each_child(node, c)
+ generate_fixups_tree_internal(dt, c);
+}
+
+void generate_fixups_tree(struct node *dt)
+{
+ struct node *an;
+
+ for_each_child(dt, an)
+ if (streq(FIXUPS, an->name))
+ break;
+
+ if (!an)
+ build_and_name_child_node(dt, FIXUPS);
+
+ for_each_child(dt, an)
+ if (streq(LOCAL_FIXUPS, an->name))
+ break;
+
+ if (!an)
+ build_and_name_child_node(dt, LOCAL_FIXUPS);
+
+ generate_fixups_tree_internal(dt, dt);
+}
diff --git a/tests/mangle-layout.c b/tests/mangle-layout.c
index a76e51e..d29ebc6 100644
--- a/tests/mangle-layout.c
+++ b/tests/mangle-layout.c
@@ -42,7 +42,8 @@ static void expand_buf(struct bufstate *buf, int newsize)
buf->size = newsize;
}
-static void new_header(struct bufstate *buf, int version, const void *fdt)
+static void new_header(struct bufstate *buf, fdt32_t magic, int version,
+ const void *fdt)
{
int hdrsize;
@@ -56,7 +57,7 @@ static void new_header(struct bufstate *buf, int version, const void *fdt)
expand_buf(buf, hdrsize);
memset(buf->buf, 0, hdrsize);
- fdt_set_magic(buf->buf, FDT_MAGIC);
+ fdt_set_magic(buf->buf, magic);
fdt_set_version(buf->buf, version);
fdt_set_last_comp_version(buf->buf, 16);
fdt_set_boot_cpuid_phys(buf->buf, fdt_boot_cpuid_phys(fdt));
@@ -145,7 +146,7 @@ int main(int argc, char *argv[])
if (fdt_version(fdt) < 17)
CONFIG("Input tree must be v17");
- new_header(&buf, version, fdt);
+ new_header(&buf, FDT_MAGIC, version, fdt);
while (*blockorder) {
add_block(&buf, version, *blockorder, fdt);
--
2.1.4
^ permalink raw reply related
* [PATCH v10 2/4] dtc: Document the dynamic plugin internals
From: Pantelis Antoniou @ 2016-11-25 12:32 UTC (permalink / raw)
To: David Gibson
Cc: Jon Loeliger, Grant Likely, Frank Rowand, Rob Herring, Jan Luebbe,
Sascha Hauer, Phil Elwell, Simon Glass, Maxime Ripard,
Thomas Petazzoni, Boris Brezillon, Antoine Tenart, Stephen Boyd,
Devicetree Compiler, devicetree-u79uwXL29TY76Z2rM5mHXA,
Pantelis Antoniou
In-Reply-To: <1480077131-14526-1-git-send-email-pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w@public.gmane.org>
Provides the document explaining the internal mechanics of
plugins and options.
Signed-off-by: Pantelis Antoniou <pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w@public.gmane.org>
---
Documentation/dt-object-internal.txt | 318 +++++++++++++++++++++++++++++++++++
1 file changed, 318 insertions(+)
create mode 100644 Documentation/dt-object-internal.txt
diff --git a/Documentation/dt-object-internal.txt b/Documentation/dt-object-internal.txt
new file mode 100644
index 0000000..d5b841e
--- /dev/null
+++ b/Documentation/dt-object-internal.txt
@@ -0,0 +1,318 @@
+Device Tree Dynamic Object format internals
+-------------------------------------------
+
+The Device Tree for most platforms is a static representation of
+the hardware capabilities. This is insufficient for many platforms
+that need to dynamically insert device tree fragments to the
+running kernel's live tree.
+
+This document explains the the device tree object format and the
+modifications made to the device tree compiler, which make it possible.
+
+1. Simplified Problem Definition
+--------------------------------
+
+Assume we have a platform which boots using following simplified device tree.
+
+---- foo.dts -----------------------------------------------------------------
+ /* FOO platform */
+ / {
+ compatible = "corp,foo";
+
+ /* shared resources */
+ res: res {
+ };
+
+ /* On chip peripherals */
+ ocp: ocp {
+ /* peripherals that are always instantiated */
+ peripheral1 { ... };
+ };
+ };
+---- foo.dts -----------------------------------------------------------------
+
+We have a number of peripherals that after probing (using some undefined method)
+should result in different device tree configuration.
+
+We cannot boot with this static tree because due to the configuration of the
+foo platform there exist multiple conficting peripherals DT fragments.
+
+So for the bar peripheral we would have this:
+
+---- foo+bar.dts -------------------------------------------------------------
+ /* FOO platform + bar peripheral */
+ / {
+ compatible = "corp,foo";
+
+ /* shared resources */
+ res: res {
+ };
+
+ /* On chip peripherals */
+ ocp: ocp {
+ /* peripherals that are always instantiated */
+ peripheral1 { ... };
+
+ /* bar peripheral */
+ bar {
+ compatible = "corp,bar";
+ ... /* various properties and child nodes */
+ };
+ };
+ };
+---- foo+bar.dts -------------------------------------------------------------
+
+While for the baz peripheral we would have this:
+
+---- foo+baz.dts -------------------------------------------------------------
+ /* FOO platform + baz peripheral */
+ / {
+ compatible = "corp,foo";
+
+ /* shared resources */
+ res: res {
+ /* baz resources */
+ baz_res: res_baz { ... };
+ };
+
+ /* On chip peripherals */
+ ocp: ocp {
+ /* peripherals that are always instantiated */
+ peripheral1 { ... };
+
+ /* baz peripheral */
+ baz {
+ compatible = "corp,baz";
+ /* reference to another point in the tree */
+ ref-to-res = <&baz_res>;
+ ... /* various properties and child nodes */
+ };
+ };
+ };
+---- foo+baz.dts -------------------------------------------------------------
+
+We note that the baz case is more complicated, since the baz peripheral needs to
+reference another node in the DT tree.
+
+2. Device Tree Object Format Requirements
+-----------------------------------------
+
+Since the device tree is used for booting a number of very different hardware
+platforms it is imperative that we tread very carefully.
+
+2.a) No changes to the Device Tree binary format for the base tree. We cannot
+modify the tree format at all and all the information we require should be
+encoded using device tree itself. We can add nodes that can be safely ignored
+by both bootloaders and the kernel. The plugin dtb's are optionally tagged
+with a different magic number in the header but otherwise they too are simple
+blobs.
+
+2.b) Changes to the DTS source format should be absolutely minimal, and should
+only be needed for the DT fragment definitions, and not the base boot DT.
+
+2.c) An explicit option should be used to instruct DTC to generate the required
+information needed for object resolution. Platforms that don't use the
+dynamic object format can safely ignore it.
+
+2.d) Finally, DT syntax changes should be kept to a minimum. It should be
+possible to express everything using the existing DT syntax.
+
+3. Implementation
+-----------------
+
+The basic unit of addressing in Device Tree is the phandle. Turns out it's
+relatively simple to extend the way phandles are generated and referenced
+so that it's possible to dynamically convert symbolic references (labels)
+to phandle values. This is a valid assumption as long as the author uses
+reference syntax and does not assign phandle values manually (which might
+be a problem with decompiled source files).
+
+We can roughly divide the operation into two steps.
+
+3.a) Compilation of the base board DTS file using the '-@' option
+generates a valid DT blob with an added __symbols__ node at the root node,
+containing a list of all nodes that are marked with a label.
+
+Using the foo.dts file above the following node will be generated;
+
+$ dtc -@ -O dtb -o foo.dtb -b 0 foo.dts
+$ fdtdump foo.dtb
+...
+/ {
+ ...
+ res {
+ ...
+ phandle = <0x00000001>;
+ ...
+ };
+ ocp {
+ ...
+ phandle = <0x00000002>;
+ ...
+ };
+ __symbols__ {
+ res="/res";
+ ocp="/ocp";
+ };
+};
+
+Notice that all the nodes that had a label have been recorded, and that
+phandles have been generated for them.
+
+This blob can be used to boot the board normally, the __symbols__ node will
+be safely ignored both by the bootloader and the kernel (the only loss will
+be a few bytes of memory and disk space).
+
+3.b) The Device Tree fragments must be compiled with the same option but they
+must also have a tag (/plugin/) that allows undefined references to nodes
+that are not present at compilation time to be recorded so that the runtime
+loader can fix them.
+
+So the bar peripheral's DTS format would be of the form:
+
+/dts-v1/ /plugin/; /* allow undefined references and record them */
+/ {
+ .... /* various properties for loader use; i.e. part id etc. */
+ fragment@0 {
+ target = <&ocp>;
+ __overlay__ {
+ /* bar peripheral */
+ bar {
+ compatible = "corp,bar";
+ ... /* various properties and child nodes */
+ }
+ };
+ };
+};
+
+Note that there's a target property that specifies the location where the
+contents of the overlay node will be placed, and it references the node
+in the foo.dts file.
+
+$ dtc -@ -O dtb -o bar.dtbo -b 0 bar.dts
+$ fdtdump bar.dtbo
+...
+/ {
+ ... /* properties */
+ fragment@0 {
+ target = <0xffffffff>;
+ __overlay__ {
+ bar {
+ compatible = "corp,bar";
+ ... /* various properties and child nodes */
+ }
+ };
+ };
+ __fixups__ {
+ ocp = "/fragment@0:target:0";
+ };
+};
+
+No __symbols__ has been generated (no label in bar.dts).
+Note that the target's ocp label is undefined, so the phandle handle
+value is filled with the illegal value '0xffffffff', while a __fixups__
+node has been generated, which marks the location in the tree where
+the label lookup should store the runtime phandle value of the ocp node.
+
+The format of the __fixups__ node entry is
+
+ <label> = "<local-full-path>:<property-name>:<offset>";
+
+<label> Is the label we're referring
+<local-full-path> Is the full path of the node the reference is
+<property-name> Is the name of the property containing the
+ reference
+<offset> The offset (in bytes) of where the property's
+ phandle value is located.
+
+Doing the same with the baz peripheral's DTS format is a little bit more
+involved, since baz contains references to local labels which require
+local fixups.
+
+/dts-v1/ /plugin/; /* allow undefined label references and record them */
+/ {
+ .... /* various properties for loader use; i.e. part id etc. */
+ fragment@0 {
+ target = <&res>;
+ __overlay__ {
+ /* baz resources */
+ baz_res: res_baz { ... };
+ };
+ };
+ fragment@1 {
+ target = <&ocp>;
+ __overlay__ {
+ /* baz peripheral */
+ baz {
+ compatible = "corp,baz";
+ /* reference to another point in the tree */
+ ref-to-res = <&baz_res>;
+ ... /* various properties and child nodes */
+ }
+ };
+ };
+};
+
+Note that &bar_res reference.
+
+$ dtc -@ -O dtb -o baz.dtbo -b 0 baz.dts
+$ fdtdump baz.dtbo
+...
+/ {
+ ... /* properties */
+ fragment@0 {
+ target = <0xffffffff>;
+ __overlay__ {
+ res_baz {
+ ....
+ phandle = <0x00000001>;
+ };
+ };
+ };
+ fragment@1 {
+ target = <0xffffffff>;
+ __overlay__ {
+ baz {
+ compatible = "corp,baz";
+ ... /* various properties and child nodes */
+ ref-to-res = <0x00000001>;
+ }
+ };
+ };
+ __fixups__ {
+ res = "/fragment@0:target:0";
+ ocp = "/fragment@1:target:0";
+ };
+ __local_fixups__ {
+ fragment@1 {
+ __overlay__ {
+ baz {
+ ref-to-res = <0>;
+ };
+ };
+ };
+ };
+};
+
+This is similar to the bar case, but the reference of a local label by the
+baz node generates a __local_fixups__ entry that records the place that the
+local reference is being made. No matter how phandles are allocated from dtc
+the run time loader must apply an offset to each phandle in every dynamic
+DT object loaded. The __local_fixups__ node records the place of every
+local reference so that the loader can apply the offset.
+
+There is an alternative syntax to the expanded form for overlays with phandle
+targets which makes the format similar to the one using in .dtsi include files.
+
+So for the &ocp target example above one can simply write:
+
+/dts-v1/ /plugin/;
+&ocp {
+ /* bar peripheral */
+ bar {
+ compatible = "corp,bar";
+ ... /* various properties and child nodes */
+ }
+};
+
+The resulting dtb object is identical.
--
2.1.4
^ permalink raw reply related
* [PATCH v10 1/4] checks: Pass boot_info instead of root node
From: Pantelis Antoniou @ 2016-11-25 12:32 UTC (permalink / raw)
To: David Gibson
Cc: Jon Loeliger, Grant Likely, Frank Rowand, Rob Herring, Jan Luebbe,
Sascha Hauer, Phil Elwell, Simon Glass, Maxime Ripard,
Thomas Petazzoni, Boris Brezillon, Antoine Tenart, Stephen Boyd,
Devicetree Compiler, devicetree-u79uwXL29TY76Z2rM5mHXA,
Pantelis Antoniou
In-Reply-To: <1480077131-14526-1-git-send-email-pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w@public.gmane.org>
As preparation for overlay support we need to pass the boot info
parameter instead of the root node to each check method.
The root node can be retrieved by accessing boot info's dt member.
No other functional changes are made.
Signed-off-by: Pantelis Antoniou <pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w@public.gmane.org>
---
checks.c | 78 ++++++++++++++++++++++++++++++++++------------------------------
1 file changed, 42 insertions(+), 36 deletions(-)
diff --git a/checks.c b/checks.c
index 0381c98..2bd27a4 100644
--- a/checks.c
+++ b/checks.c
@@ -40,7 +40,7 @@ enum checkstatus {
struct check;
-typedef void (*check_fn)(struct check *c, struct node *dt, struct node *node);
+typedef void (*check_fn)(struct check *c, struct boot_info *bi, struct node *node);
struct check {
const char *name;
@@ -97,20 +97,21 @@ static inline void check_msg(struct check *c, const char *fmt, ...)
check_msg((c), __VA_ARGS__); \
} while (0)
-static void check_nodes_props(struct check *c, struct node *dt, struct node *node)
+static void check_nodes_props(struct check *c, struct boot_info *bi, struct node *node)
{
struct node *child;
TRACE(c, "%s", node->fullpath);
if (c->fn)
- c->fn(c, dt, node);
+ c->fn(c, bi, node);
for_each_child(node, child)
- check_nodes_props(c, dt, child);
+ check_nodes_props(c, bi, child);
}
-static bool run_check(struct check *c, struct node *dt)
+static bool run_check(struct check *c, struct boot_info *bi)
{
+ struct node *dt = bi->dt;
bool error = false;
int i;
@@ -123,7 +124,7 @@ static bool run_check(struct check *c, struct node *dt)
for (i = 0; i < c->num_prereqs; i++) {
struct check *prq = c->prereq[i];
- error = error || run_check(prq, dt);
+ error = error || run_check(prq, bi);
if (prq->status != PASSED) {
c->status = PREREQ;
check_msg(c, "Failed prerequisite '%s'",
@@ -134,7 +135,7 @@ static bool run_check(struct check *c, struct node *dt)
if (c->status != UNCHECKED)
goto out;
- check_nodes_props(c, dt, dt);
+ check_nodes_props(c, bi, dt);
if (c->status == UNCHECKED)
c->status = PASSED;
@@ -153,14 +154,14 @@ out:
*/
/* A check which always fails, for testing purposes only */
-static inline void check_always_fail(struct check *c, struct node *dt,
+static inline void check_always_fail(struct check *c, struct boot_info *bi,
struct node *node)
{
FAIL(c, "always_fail check");
}
CHECK(always_fail, check_always_fail, NULL);
-static void check_is_string(struct check *c, struct node *root,
+static void check_is_string(struct check *c, struct boot_info *bi,
struct node *node)
{
struct property *prop;
@@ -179,7 +180,7 @@ static void check_is_string(struct check *c, struct node *root,
#define ERROR_IF_NOT_STRING(nm, propname) \
ERROR(nm, check_is_string, (propname))
-static void check_is_cell(struct check *c, struct node *root,
+static void check_is_cell(struct check *c, struct boot_info *bi,
struct node *node)
{
struct property *prop;
@@ -202,7 +203,7 @@ static void check_is_cell(struct check *c, struct node *root,
* Structural check functions
*/
-static void check_duplicate_node_names(struct check *c, struct node *dt,
+static void check_duplicate_node_names(struct check *c, struct boot_info *bi,
struct node *node)
{
struct node *child, *child2;
@@ -217,7 +218,7 @@ static void check_duplicate_node_names(struct check *c, struct node *dt,
}
ERROR(duplicate_node_names, check_duplicate_node_names, NULL);
-static void check_duplicate_property_names(struct check *c, struct node *dt,
+static void check_duplicate_property_names(struct check *c, struct boot_info *bi,
struct node *node)
{
struct property *prop, *prop2;
@@ -239,7 +240,7 @@ ERROR(duplicate_property_names, check_duplicate_property_names, NULL);
#define DIGITS "0123456789"
#define PROPNODECHARS LOWERCASE UPPERCASE DIGITS ",._+*#?-"
-static void check_node_name_chars(struct check *c, struct node *dt,
+static void check_node_name_chars(struct check *c, struct boot_info *bi,
struct node *node)
{
int n = strspn(node->name, c->data);
@@ -250,7 +251,7 @@ static void check_node_name_chars(struct check *c, struct node *dt,
}
ERROR(node_name_chars, check_node_name_chars, PROPNODECHARS "@");
-static void check_node_name_format(struct check *c, struct node *dt,
+static void check_node_name_format(struct check *c, struct boot_info *bi,
struct node *node)
{
if (strchr(get_unitname(node), '@'))
@@ -259,8 +260,8 @@ static void check_node_name_format(struct check *c, struct node *dt,
}
ERROR(node_name_format, check_node_name_format, NULL, &node_name_chars);
-static void check_unit_address_vs_reg(struct check *c, struct node *dt,
- struct node *node)
+static void check_unit_address_vs_reg(struct check *c, struct boot_info *bi,
+ struct node *node)
{
const char *unitname = get_unitname(node);
struct property *prop = get_property(node, "reg");
@@ -283,7 +284,7 @@ static void check_unit_address_vs_reg(struct check *c, struct node *dt,
}
WARNING(unit_address_vs_reg, check_unit_address_vs_reg, NULL);
-static void check_property_name_chars(struct check *c, struct node *dt,
+static void check_property_name_chars(struct check *c, struct boot_info *bi,
struct node *node)
{
struct property *prop;
@@ -305,10 +306,11 @@ ERROR(property_name_chars, check_property_name_chars, PROPNODECHARS);
((prop) ? (prop)->name : ""), \
((prop) ? "' in " : ""), (node)->fullpath
-static void check_duplicate_label(struct check *c, struct node *dt,
+static void check_duplicate_label(struct check *c, struct boot_info *bi,
const char *label, struct node *node,
struct property *prop, struct marker *mark)
{
+ struct node *dt = bi->dt;
struct node *othernode = NULL;
struct property *otherprop = NULL;
struct marker *othermark = NULL;
@@ -331,30 +333,31 @@ static void check_duplicate_label(struct check *c, struct node *dt,
DESCLABEL_ARGS(othernode, otherprop, othermark));
}
-static void check_duplicate_label_node(struct check *c, struct node *dt,
+static void check_duplicate_label_node(struct check *c, struct boot_info *bi,
struct node *node)
{
struct label *l;
struct property *prop;
for_each_label(node->labels, l)
- check_duplicate_label(c, dt, l->label, node, NULL, NULL);
+ check_duplicate_label(c, bi, l->label, node, NULL, NULL);
for_each_property(node, prop) {
struct marker *m = prop->val.markers;
for_each_label(prop->labels, l)
- check_duplicate_label(c, dt, l->label, node, prop, NULL);
+ check_duplicate_label(c, bi, l->label, node, prop, NULL);
for_each_marker_of_type(m, LABEL)
- check_duplicate_label(c, dt, m->ref, node, prop, m);
+ check_duplicate_label(c, bi, m->ref, node, prop, m);
}
}
ERROR(duplicate_label, check_duplicate_label_node, NULL);
-static cell_t check_phandle_prop(struct check *c, struct node *root,
+static cell_t check_phandle_prop(struct check *c, struct boot_info *bi,
struct node *node, const char *propname)
{
+ struct node *root = bi->dt;
struct property *prop;
struct marker *m;
cell_t phandle;
@@ -398,18 +401,19 @@ static cell_t check_phandle_prop(struct check *c, struct node *root,
return phandle;
}
-static void check_explicit_phandles(struct check *c, struct node *root,
+static void check_explicit_phandles(struct check *c, struct boot_info *bi,
struct node *node)
{
+ struct node *root = bi->dt;
struct node *other;
cell_t phandle, linux_phandle;
/* Nothing should have assigned phandles yet */
assert(!node->phandle);
- phandle = check_phandle_prop(c, root, node, "phandle");
+ phandle = check_phandle_prop(c, bi, node, "phandle");
- linux_phandle = check_phandle_prop(c, root, node, "linux,phandle");
+ linux_phandle = check_phandle_prop(c, bi, node, "linux,phandle");
if (!phandle && !linux_phandle)
/* No valid phandles; nothing further to check */
@@ -433,7 +437,7 @@ static void check_explicit_phandles(struct check *c, struct node *root,
}
ERROR(explicit_phandles, check_explicit_phandles, NULL);
-static void check_name_properties(struct check *c, struct node *root,
+static void check_name_properties(struct check *c, struct boot_info *bi,
struct node *node)
{
struct property **pp, *prop = NULL;
@@ -467,9 +471,10 @@ ERROR(name_properties, check_name_properties, NULL, &name_is_string);
* Reference fixup functions
*/
-static void fixup_phandle_references(struct check *c, struct node *dt,
+static void fixup_phandle_references(struct check *c, struct boot_info *bi,
struct node *node)
{
+ struct node *dt = bi->dt;
struct property *prop;
for_each_property(node, prop) {
@@ -495,9 +500,10 @@ static void fixup_phandle_references(struct check *c, struct node *dt,
ERROR(phandle_references, fixup_phandle_references, NULL,
&duplicate_node_names, &explicit_phandles);
-static void fixup_path_references(struct check *c, struct node *dt,
+static void fixup_path_references(struct check *c, struct boot_info *bi,
struct node *node)
{
+ struct node *dt = bi->dt;
struct property *prop;
for_each_property(node, prop) {
@@ -534,7 +540,7 @@ WARNING_IF_NOT_STRING(device_type_is_string, "device_type");
WARNING_IF_NOT_STRING(model_is_string, "model");
WARNING_IF_NOT_STRING(status_is_string, "status");
-static void fixup_addr_size_cells(struct check *c, struct node *dt,
+static void fixup_addr_size_cells(struct check *c, struct boot_info *bi,
struct node *node)
{
struct property *prop;
@@ -558,7 +564,7 @@ WARNING(addr_size_cells, fixup_addr_size_cells, NULL,
#define node_size_cells(n) \
(((n)->size_cells == -1) ? 1 : (n)->size_cells)
-static void check_reg_format(struct check *c, struct node *dt,
+static void check_reg_format(struct check *c, struct boot_info *bi,
struct node *node)
{
struct property *prop;
@@ -587,7 +593,7 @@ static void check_reg_format(struct check *c, struct node *dt,
}
WARNING(reg_format, check_reg_format, NULL, &addr_size_cells);
-static void check_ranges_format(struct check *c, struct node *dt,
+static void check_ranges_format(struct check *c, struct boot_info *bi,
struct node *node)
{
struct property *prop;
@@ -631,7 +637,7 @@ WARNING(ranges_format, check_ranges_format, NULL, &addr_size_cells);
/*
* Style checks
*/
-static void check_avoid_default_addr_size(struct check *c, struct node *dt,
+static void check_avoid_default_addr_size(struct check *c, struct boot_info *bi,
struct node *node)
{
struct property *reg, *ranges;
@@ -657,9 +663,10 @@ WARNING(avoid_default_addr_size, check_avoid_default_addr_size, NULL,
&addr_size_cells);
static void check_obsolete_chosen_interrupt_controller(struct check *c,
- struct node *dt,
+ struct boot_info *bi,
struct node *node)
{
+ struct node *dt = bi->dt;
struct node *chosen;
struct property *prop;
@@ -765,7 +772,6 @@ void parse_checks_option(bool warn, bool error, const char *arg)
void process_checks(bool force, struct boot_info *bi)
{
- struct node *dt = bi->dt;
int i;
int error = 0;
@@ -773,7 +779,7 @@ void process_checks(bool force, struct boot_info *bi)
struct check *c = check_table[i];
if (c->warn || c->error)
- error = error || run_check(c, dt);
+ error = error || run_check(c, bi);
}
if (error) {
--
2.1.4
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH v10 0/4] dtc: Dynamic DT support
From: Pantelis Antoniou @ 2016-11-25 12:32 UTC (permalink / raw)
To: David Gibson
Cc: Jon Loeliger, Grant Likely, Frank Rowand, Rob Herring, Jan Luebbe,
Sascha Hauer, Phil Elwell, Simon Glass, Maxime Ripard,
Thomas Petazzoni, Boris Brezillon, Antoine Tenart, Stephen Boyd,
Devicetree Compiler, devicetree-u79uwXL29TY76Z2rM5mHXA,
Pantelis Antoniou
This patchset adds Dynamic DT support in the DTC compiler
as used in a number of boards like the beaglebone/rpi/chip and others.
The first patch passes a boot_info argument instead of the root node
to the check methods.
The second patch documents the internals of overlay generation, while
the third one adds dynamic object/overlay support proper.
The last patch simply adds a few overlay tests verifying operation.
This patchset is against DTC mainline and is also available for a pull
request from https://github.com/pantoniou/dtc/tree/overlays
Regards
-- Pantelis
Changes since v9:
* Reversed -M switch to by default use new DTBO magic value.
* Removed global versionflags in the parser by using inherited
attributes.
* build_node instead of malloc at add_orphan_node().
* Do not use escape for path copy
* Do not generate /plugin/ when generating a dts file even when
the plugin flag is set..
Changes since v8:
* Removed extra member of boot_info in each node; passing boot_info
parameter to the check methods instead.
* Reworked yacc syntax that supports both old and new plugin syntax
* Added handling for new magic number (enabled by 'M' switch).
* Dropped dtbo/asmo formats.
* Added overlay testsuite.
* Addressed last version maintainer comments.
Changes since v7:
* Dropped xasprintf & backward compatibility patch
* Rebased against dgibson's overlay branch
* Minor doc wording fixes.
Changes since v6:
* Introduced xasprintf
* Added append_to_property and used it
* Changed some die()'s to assert
* Reordered node generation to respect sort
* Addressed remaining maintainer changes from v6
Changes since v5:
* Rebase to latest dtc version.
* Addressed all the maintainer requested changes from v5
* Added new magic value for dynamic objects and new format
Changes since v4:
* Rebase to latest dtc version.
* Completely redesigned the generation of resolution data.
Now instead of being generated as part of blob generation
they are created in the live tree.
* Consequently the patchset is much smaller.
* Added -A auto-label alias generation option.
* Addressed maintainer comments.
* Added syntactic sugar for overlays in the form of .dtsi
* Added /dts-v1/ /plugin/ preferred plugin form and deprecate
the previous form (although still works for backward compatibility)
Changes since v3:
* Rebase to latest dtc version.
Changes since v2:
* Split single patch to a patchset.
* Updated to dtc mainline.
* Changed __local_fixups__ format
* Clean up for better legibility.
Pantelis Antoniou (4):
checks: Pass boot_info instead of root node
dtc: Document the dynamic plugin internals
dtc: Plugin and fixup support
tests: Add overlay tests
Documentation/dt-object-internal.txt | 318 +++++++++++++++++++++++++++++++++++
Documentation/manual.txt | 25 ++-
checks.c | 86 +++++-----
dtc-lexer.l | 5 +
dtc-parser.y | 50 +++++-
dtc.c | 39 ++++-
dtc.h | 20 ++-
fdtdump.c | 2 +-
flattree.c | 17 +-
fstree.c | 2 +-
libfdt/fdt.c | 2 +-
libfdt/fdt.h | 3 +-
livetree.c | 225 ++++++++++++++++++++++++-
tests/mangle-layout.c | 7 +-
tests/overlay_overlay_dtc.dts | 76 +--------
tests/overlay_overlay_dtc.dtsi | 83 +++++++++
tests/overlay_overlay_new_dtc.dts | 11 ++
tests/overlay_overlay_simple.dts | 12 ++
tests/run_tests.sh | 20 +++
19 files changed, 862 insertions(+), 141 deletions(-)
create mode 100644 Documentation/dt-object-internal.txt
create mode 100644 tests/overlay_overlay_dtc.dtsi
create mode 100644 tests/overlay_overlay_new_dtc.dts
create mode 100644 tests/overlay_overlay_simple.dts
--
2.1.4
^ permalink raw reply
* Re: [RFC v2: PATCH 1/2] dt-bindings: Document the hi3660 reset bindings
From: zhangfei @ 2016-11-25 12:08 UTC (permalink / raw)
To: Philipp Zabel
Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
devicetree-u79uwXL29TY76Z2rM5mHXA, Arnd Bergmann, Stephen Boyd
In-Reply-To: <1480071241.4058.23.camel-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
On 2016年11月25日 18:54, Philipp Zabel wrote:
> Am Freitag, den 25.11.2016, 18:42 +0800 schrieb zhangfei:
>> On 2016年11月25日 18:25, Philipp Zabel wrote:
>>> Am Donnerstag, den 24.11.2016, 18:20 +0800 schrieb zhangfei:
>>>> On 2016年11月24日 17:50, Philipp Zabel wrote:
>>>>> Am Donnerstag, den 24.11.2016, 17:40 +0800 schrieb zhangfei:
>>>>>> On 2016年11月24日 17:26, Philipp Zabel wrote:
>>>>>>> Am Mittwoch, den 23.11.2016, 16:07 +0800 schrieb Zhangfei Gao:
>>>>>>>> Add DT bindings documentation for hi3660 SoC reset controller.
>>>>>>>>
>>>>>>>> Signed-off-by: Zhangfei Gao <zhangfei.gao-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
>>>>>>>> ---
>>>>>>>> .../bindings/reset/hisilicon,hi3660-reset.txt | 51 ++++++++++++++++++++++
>>>>>>>> 1 file changed, 51 insertions(+)
>>>>>>>> create mode 100644 Documentation/devicetree/bindings/reset/hisilicon,hi3660-reset.txt
>>>>>>>>
>>>>>>>> diff --git a/Documentation/devicetree/bindings/reset/hisilicon,hi3660-reset.txt b/Documentation/devicetree/bindings/reset/hisilicon,hi3660-reset.txt
>>>>>>>> new file mode 100644
>>>>>>>> index 0000000..250daf2
>>>>>>>> --- /dev/null
>>>>>>>> +++ b/Documentation/devicetree/bindings/reset/hisilicon,hi3660-reset.txt
>>>>>>>> @@ -0,0 +1,51 @@
>>>>>>>> +Hisilicon System Reset Controller
>>>>>>>> +======================================
>>>>>>>> +
>>>>>>>> +Please also refer to reset.txt in this directory for common reset
>>>>>>>> +controller binding usage.
>>>>>>>> +
>>>>>>>> +The reset controller registers are part of the system-ctl block on
>>>>>>>> +hi3660 SoC.
>>>>>>>> +
>>>>>>>> +Required properties:
>>>>>>>> +- compatible: should be
>>>>>>>> + "hisilicon,hi3660-reset"
>>>>>>>> +- #reset-cells: 1, see below
>>>>>>>> +- hisi,rst-syscon: phandle of the reset's syscon.
>>>>>>>> +- hisi,reset-bits: Contains the reset control register information
>>>>>>>> + Should contain 2 cells for each reset exposed to
>>>>>>>> + consumers, defined as:
>>>>>>>> + Cell #1 : offset from the syscon register base
>>>>>>>> + Cell #2 : bits position of the control register
>>>>>>>> +
>>>>>>>> +Example:
>>>>>>>> + iomcu: iomcu@ffd7e000 {
>>>>>>>> + compatible = "hisilicon,hi3660-iomcu", "syscon";
>>>>>>>> + reg = <0x0 0xffd7e000 0x0 0x1000>;
>>>>>>>> + };
>>>>>>>> +
>>>>>>>> + iomcu_rst: iomcu_rst_controller {
>>>>>>> This should be
>>>>>>> iomcu_rst: reset-controller {
>>>>>>>
>>>>>>>> + compatible = "hisilicon,hi3660-reset";
>>>>>>>> + #reset-cells = <1>;
>>>>>>>> + hisi,rst-syscon = <&iomcu>;
>>>>>>>> + hisi,reset-bits = <0x20 0x8 /* 0: i2c0 */
>>>>>>>> + 0x20 0x10 /* 1: i2c1 */
>>>>>>>> + 0x20 0x20 /* 2: i2c2 */
>>>>>>>> + 0x20 0x8000000>; /* 3: i2c6 */
>>>>>>>> + };
>>>>>>> The reset lines are controlled through iomcu bits, is there a reason not
>>>>>>> to put the iomcu_rst node inside the iomcu node? That way the
>>>>>>> hisi,rst-syscon property could be removed and the syscon could be
>>>>>>> retrieved via the reset-controller parent node.
>>>>>> iomcu is common registers, controls clock and reset, etc.
>>>>>> So we use syscon, without mapping the registers everywhere.
>>>>>> It is common case in hisilicon, same in hi6220.
>>>>>>
>>>>>> Also the #clock-cells and #reset-cells can not be put in the same node,
>>>>>> if they are both using probe, since reset_probe will not be called.
>>>>>>
>>>>>> So we use hisi,rst-syscon as a general solution.
>>>>> What I meant is this:
>>>>>
>>>>> iomcu: iomcu@ffd7e000 {
>>>>> compatible = "hisilicon,hi3660-iomcu", "syscon", "simple-mfd";
>>>>> reg = <0x0 0xffd7e000 0x0 0x1000>;
>>>> #clock-cells = <1>;
>>>>
>>>> In my test, if there add #clock-cells = <1>, reset_probe will not be
>>>> called any more.
>>>> Since clk_probe is called first.
>>>> No matter iomcu_rst is child node or not.
>>> I don't understand this, does the clock driver bind to the iomcu node
>>> using CLK_OF_DECLARE_DRIVER(..., "hisilicon,hi3660-iomcu", ...)?
>> This method:CLK_OF_DECLARE_DRIVER is not prefered in clock,
>> and we have to use probe instead, to make all driver build as modules as
>> possible.
>>
>> For example hi3660.
>> static struct platform_driver hi3660_clk_driver = {
>> .probe = hi3660_clk_probe,
>> .driver = {
>> .name = "hi3660-clk",
>> .of_match_table = hi3660_clk_match_table,
>> },
>> };
> hi3660_clk_match_table contains the "hisilicon,hi3660-iomcu" compatible?
> If so, you could call
> of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
> from hi3660_clk_probe instead of using "simple-mfd" to probe the iomcu
> node's children.
Not using simple-mfd:
Like
static const struct of_device_id hi3660_clk_match_table[] = {
{ .compatible = "hisilicon,hi3660-iomcu", },
{ }
};
MODULE_DEVICE_TABLE(of, hi3660_clk_match_table);
static int hi3660_clk_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct device_node *np = pdev->dev.of_node;
const struct of_device_id *of_id;
enum hi3660_clk_type type;
of_id = of_match_device(hi3660_clk_match_table, dev);
if (!of_id)
return -EINVAL;
~
}
If put iomcu_rst as child node, and set #clock-cells = <1> to iomcu,
then hi3660_clk_probe is called, hi3660_reset_probe will not be called.
So using "hisi,rst-syscon" as pointer does not have the issue.
Thanks
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH V4 2/2] pinctrl: tegra: Add driver to configure voltage and power of io pads
From: Laxman Dewangan @ 2016-11-25 12:04 UTC (permalink / raw)
To: Thierry Reding
Cc: linus.walleij, robh+dt, mark.rutland, swarren, gnurou, jonathanh,
joe, yamada.masahiro, linux-gpio, devicetree, linux-tegra,
linux-kernel
In-Reply-To: <20161125095744.GB11512@ulmo.ba.sec>
Thanks Thierry for review.
On Friday 25 November 2016 03:27 PM, Thierry Reding wrote:
> * PGP Signed by an unknown key
>
> On Thu, Nov 24, 2016 at 02:08:54PM +0530, Laxman Dewangan wrote:
>> + NVIDIA Tegra124/210 SoC has IO pads which supports multi-voltage
>> + level of interfacing and deep power down mode of IO pads. The
>> + voltage of IO pads are SW configurable based on IO rail of that
>> + pads on T210. This driver provides the interface to change IO pad
>> + voltage and power state via pincontrol interface.
> This has a lot of chip-specific text. Will all of that have to be
> updated if support for new chips is added?
Then saying that Tegra124 and later..
Hoping, people know our chip releasing sequence as numbering are not in
sequence.
>
>> +#include <linux/regulator/consumer.h>
>> +#include <soc/tegra/pmc.h>
> Have you considered moving this code into the PMC driver? It seems a
> little over the top to go through all of the platform device creation
> and driver registration dance only to call into a public API later on.
Yes, we had discussion on this and suggestion came to use the pinctrl
framework.
If we do in the pmc driver then we will need lots of DT processing for
getting information from DT which we can directly get from the pinctrl
core framework.
Also client driver may need to have the control dynamically and get the
IO pads from DT. So implementing all in pmc will be huge duplication
over already existing framework.
>
>> +#include "../core.h"
>> +#include "../pinconf.h"
>> +#include "../pinctrl-utils.h"
>> +
>> +#define TEGRA_IO_RAIL_1800000UV 1800000
>> +#define TEGRA_IO_RAIL_3300000UV 3300000
> Is there really a point in having these defines? They are really long
> and effectively don't carry more information than just the plain
> numbers.
using macros is always good instead of magic number in code and hence it
is there.
>
>
>> +#define tegra_io_uv_to_io_pads_uv(io_uv) \
>> + (((io_uv) == TEGRA_IO_RAIL_1800000UV) ? \
>> + TEGRA_IO_PAD_1800000UV : TEGRA_IO_PAD_3300000UV)
>> +
>> +#define tegra_io_voltage_is_valid(io_uv) \
>> + ({ typeof(io_uv) io_uv_ = (io_uv); \
>> + ((io_uv_ == TEGRA_IO_RAIL_1800000UV) || \
>> + (io_uv_ == TEGRA_IO_RAIL_3300000UV)); })
>>
> Maybe make both of these static inline functions to improve readability?
> I find the above very hard to read.
OK, will convert to the inline but dont think it will be less complex.
>> + enum tegra_io_pad_voltage pad_volt;
>>
>> +
>>
>> +
>> +#define TEGRA_IO_PAD_INFO(_pin, _name, _id, _lpstate, _vsupply) \
>> + { \
>> + .name = _name, \
>> + .pins = {(_pin)}, \
>> + .id = TEGRA_IO_PAD_##_id, \
>> + .vsupply = (_vsupply), \
>> + .supports_low_power = (_lpstate), \
>> + }
>> +
>> +static const struct tegra_io_pads_cfg tegra124_io_pads_cfg_info[] = {
>> + TEGRA124_PAD_INFO_TABLE(TEGRA_IO_PAD_INFO),
>> +};
>> +
>> +static const struct tegra_io_pads_cfg tegra210_io_pads_cfg_info[] = {
>> + TEGRA210_PAD_INFO_TABLE(TEGRA_IO_PAD_INFO),
>> +};
> That's a weird way of writing these tables. Why not do something simpler
> and much more common such as:
>
> #define TEGRA_IO_PAD_INFO(...) ...
>
> static const struct tegra_io_pads_cfg tegra124_io_pads_cfgs[] = {
> TEGRA_IO_PAD_INFO(...),
> ...
> };
>
> static const struct tegra_io_pads_cfg tegra210_io_pad_cfgs[] = {
> TEGRA_IO_PAD_INFO(...),
> ...
> };
This is done to use the same table for initialing two different
structure. If we go as above then we will endup with the two tables.
or define and then redefine the TEGRA_IO_PAD_INFO.
>
>> +
>>
>> +
>> +module_platform_driver(tegra_io_pads_pinctrl_driver);
>> +
>> +MODULE_DESCRIPTION("NVIDIA TEGRA IO pad Control Driver");
>> +MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
>> +MODULE_LICENSE("GPL v2");
> Like I said above, I think there's a lot of boilerplate in here that's
> simply there to create a virtual device and bind a driver to it. All of
> that comes with very little to no benefit. I think this could all just
> be moved into the PMC driver and be simplified quite a bit.
>
What did you not like here?
Let me specific to my query to get idea about your view:
1. Do you agree for the interface as pinctrl here?
2. Do you want to call the probe() function implemented here as simple
function call from pmc's probe?
3. If (2) is yes then how do you want to differentiate T124 or T210? Via
argument?
It will be really help if you can provide the pseudo code from PMC and
this driver so that I can implement the same in the next patch.
^ permalink raw reply
* Re: [PATCH V5 3/3] ARM64 LPC: LPC driver implementation on Hip06
From: Arnd Bergmann @ 2016-11-25 12:03 UTC (permalink / raw)
To: Gabriele Paoloni
Cc: linux-arm-kernel@lists.infradead.org, mark.rutland@arm.com,
catalin.marinas@arm.com, linux-pci@vger.kernel.org,
liviu.dudau@arm.com, Linuxarm, lorenzo.pieralisi@arm.com,
xuwei (O), Jason Gunthorpe, T homas Petazzoni,
linux-serial@vger.kernel.org, benh@kernel.crashing.org,
devicetree@vger.kernel.org, minyard@acm.org, will.deacon@arm.com
In-Reply-To: <EE11001F9E5DDD47B7634E2F8A612F2E1F939E0A@lhreml507-mbx>
On Friday, November 25, 2016 8:46:11 AM CET Gabriele Paoloni wrote:
> > From: Arnd Bergmann [mailto:arnd@arndb.de]
> >
> > On Wednesday, November 23, 2016 6:07:11 PM CET Arnd Bergmann wrote:
> > > On Wednesday, November 23, 2016 3:22:33 PM CET Gabriele Paoloni
> > wrote:
> > > > From: Arnd Bergmann [mailto:arnd@arndb.de]
> > > > > On Friday, November 18, 2016 5:03:11 PM CET Gabriele Paoloni
> > /*
> > @@ -549,9 +548,14 @@ static int of_translate_one(struct device_node
> > *parent, struct of_bus *bus,
> > * that translation is impossible (that is we are not dealing with a
> > value
> > * that can be mapped to a cpu physical address). This is not really
> > specified
> > * that way, but this is traditionally the way IBM at least do things
> > + *
> > + * Whenever the translation fails, the *host pointer will be set to
> > the
> > + * device that lacks a tranlation, and the return code is relative to
> > + * that node.
>
> This seems to be wrong to me. We are abusing of the error conditions.
> So effectively if there is a buggy DT for an IO resource we end up
> assuming that we are using a special IO device with unmapped addresses.
>
> The patch at the bottom apply on top of this one and I think is a more
> reasonable approach
It was meant as a logical extension to the existing interface,
translating the address as far as we can, and reporting back
how far we got.
Maybe we can return 'of_root' by instead of NULL to signify
that we have converted all the way to the root of the DT?
That would make it more consistent, but slightly more complicated
for the common case.
> > */
> > static u64 __of_translate_address(struct device_node *dev,
> > - const __be32 *in_addr, const char *rprop)
> > + const __be32 *in_addr, const char *rprop,
> > + struct device_node **host)
> > {
> > struct device_node *parent = NULL;
> > struct of_bus *bus, *pbus;
> > @@ -564,6 +568,7 @@ static u64 __of_translate_address(struct
> > device_node *dev,
> > /* Increase refcount at current level */
> > of_node_get(dev);
> >
> > + *host = NULL;
> > /* Get parent & match bus type */
> > parent = of_get_parent(dev);
> > if (parent == NULL)
> > @@ -600,8 +605,9 @@ static u64 __of_translate_address(struct
> > device_node *dev,
> > pbus = of_match_bus(parent);
> > pbus->count_cells(dev, &pna, &pns);
> > if (!OF_CHECK_COUNTS(pna, pns)) {
> > - pr_err("Bad cell count for %s\n",
> > - of_node_full_name(dev));
> > + pr_debug("Bad cell count for %s\n",
> > + of_node_full_name(dev));
> > + *host = of_node_get(parent);
> > break;
> > }
> >
> > @@ -609,7 +615,9 @@ static u64 __of_translate_address(struct
> > device_node *dev,
> > pbus->name, pna, pns, of_node_full_name(parent));
> >
> > /* Apply bus translation */
> > - if (of_translate_one(dev, bus, pbus, addr, na, ns, pna,
> > rprop))
> > + result = of_translate_one(dev, bus, pbus, addr, na, ns,
> > + pna, rprop);
> > + if (result == OF_BAD_ADDR)
>
> It seems to me that here you missed "*host = of_node_get(parent);"..?
>
Yes, Zhichang also pointed out the same thing, this is not
right yet. My thought was that we need to check the #address-cells
and #size-cells of the parent node and return if they are not set,
but the bus should really have those.
What we need to do instead is check the "ranges" of the parent
and fail if there is no translation. Simply setting the host
here however won't work either because that leads to returning
OF_BAD_ADDR.
> > /* Complete the move up one level */
> > @@ -628,13 +636,32 @@ static u64 __of_translate_address(struct
> > device_node *dev,
> >
> > u64 of_translate_address(struct device_node *dev, const __be32
> > *in_addr)
> > {
> > - return __of_translate_address(dev, in_addr, "ranges");
> > + struct device_node *host;
...
> > +
> > phys_addr_t pci_pio_to_address(unsigned long pio)
> > {
> > phys_addr_t address = (phys_addr_t)OF_BAD_ADDR;
> > diff --git a/include/linux/pci.h b/include/linux/pci.h
> > index 6bd94a803e8f..b7a8fa3da3ca 100644
> > --- a/include/linux/pci.h
> > +++ b/include/linux/pci.h
> > @@ -1192,7 +1192,8 @@ int __must_check pci_bus_alloc_resource(struct
> > pci_bus *bus,
> > void *alignf_data);
[Many lines of reply trimmed here, please make sure you don't quote too
much context when you reply, it's really annoying to read through
it otherwise]
> /*
> + * of_isa_indirect_io - get the IO address from some isa reg property value.
> + * For some isa/lpc devices, no ranges property in ancestor node.
> + * The device addresses are described directly in their regs property.
> + * This fixup function will be called to get the IO address of isa/lpc
> + * devices when the normal of_translation failed.
> + *
> + * @parent: points to the parent dts node;
> + * @bus: points to the of_bus which can be used to parse address;
> + * @addr: the address from reg property;
> + * @na: the address cell counter of @addr;
> + * @presult: store the address paresed from @addr;
> + *
> + * return 1 when successfully get the I/O address;
> + * 0 will return for some failures.
> + */
> +static int of_get_isa_indirect_io(struct device_node *parent,
> + struct of_bus *bus, __be32 *addr,
> + int na, u64 *presult)
> +{
> + unsigned int flags;
> + unsigned int rlen;
> +
> + /* whether support indirectIO */
> + if (!indirect_io_enabled())
> + return 0;
> +
> + if (!of_bus_isa_match(parent))
> + return 0;
> +
> + flags = bus->get_flags(addr);
> + if (!(flags & IORESOURCE_IO))
> + return 0;
> +
> + /* there is ranges property, apply the normal translation directly. */
> + if (of_get_property(parent, "ranges", &rlen))
> + return 0;
> +
> + *presult = of_read_number(addr + 1, na - 1);
> + /* this fixup is only valid for specific I/O range. */
> + return addr_is_indirect_io(*presult);
> +}
Right, this would work. The reason I didn't go down this route is
that I wanted to keep it generic enough to allow doing the same
for PCI host bridges with a nonlinear mapping of the I/O space.
There isn't really anything special about ISA here, other than the
fact that the one driver that needs it happens to be for ISA rather
than PCI.
> +/*
> * Translate an address from the device-tree into a CPU physical address,
> * this walks up the tree and applies the various bus mappings on the
> * way.
> @@ -600,14 +643,23 @@ static u64 __of_translate_address(struct device_node *dev,
> result = of_read_number(addr, na);
> break;
> }
> + /*
> + * For indirectIO device which has no ranges property, get
> + * the address from reg directly.
> + */
> + if (of_get_isa_indirect_io(dev, bus, addr, na, &result)) {
> + pr_debug("isa indirectIO matched(%s)..addr = 0x%llx\n",
> + of_node_full_name(dev), result);
> + *host = of_node_get(parent);
> + break;
> + }
>
If we do the special case for ISA as you suggest above, I would still want
to keep it in of_translate_ioport(), I think that's a useful change by
itself in my patch.
Arnde
^ permalink raw reply
* Re: [net-next PATCH v1 0/2] stmmac: dwmac-meson8b: configurable RGMII TX delay
From: Måns Rullgård @ 2016-11-25 12:01 UTC (permalink / raw)
To: Sebastian Frias
Cc: Florian Fainelli, Martin Blumenstingl, Jerome Brunet,
linux-amlogic, devicetree, netdev, davem, khilman, mark.rutland,
robh+dt, linux-arm-kernel, alexandre.torgue, peppe.cavallaro,
carlo, Andrew Lunn
In-Reply-To: <6a6af561-4e83-ca6e-d989-f421e18bce1e@laposte.net>
Sebastian Frias <sf84@laposte.net> writes:
> On 24/11/16 19:55, Florian Fainelli wrote:
>> Le 24/11/2016 à 09:05, Martin Blumenstingl a écrit :
>>> Based on what I found it seems that rgmii-id, rgmii-txid and
>>> rgmii-rxid are supposed to be handled by the PHY.
>>
>> Correct, the meaning of PHY_INTERFACE_MODE should be from the
>> perspective of the PHY device:
>>
>> - PHY_INTERFACE_MODE_RGMII_TXID means that the PHY is responsible for
>> adding a delay when the MAC transmits (TX MAC -> PHY (delay) -> wire)
>> - PHY_INTERFACE_MODE_RGMII_RXID means that the PHY is responsible for
>> adding a delay when the MAC receives (RX MAC <- (delay) PHY) <- wire)
>>
>
> Thanks for the explanation.
> Actually I had thought that the delay was to account for board routing
> (wires) between the MAC and the PHY.
> From your explanation it appears that the delay is to account for board
> routing (wires) between the PHY and the RJ45 socket.
The delay pertains to the RGMII link between MAC and PHY. The external
connection is self-clocking.
--
Måns Rullgård
^ permalink raw reply
* Re: [PATCH v5 2/2] DW DMAC: add multi-block property to device tree
From: Andy Shevchenko @ 2016-11-25 11:48 UTC (permalink / raw)
To: Eugeniy Paltsev
Cc: vinod.koul-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org,
linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org,
shiraz.linux.kernel-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org,
devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
vireshk-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org,
linux-snps-arc-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org,
mark.rutland-5wv7dgnIgG8@public.gmane.org,
dmaengine-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
christian.ruppert-Yycd8EPnGM5BDgjK7y7TUQ@public.gmane.org,
arnd-r2nGTMty4D4@public.gmane.org
In-Reply-To: <1480074030.2534.46.camel-HKixBCOQz3hWk0Htik3J/w@public.gmane.org>
On Fri, 2016-11-25 at 11:40 +0000, Eugeniy Paltsev wrote:
> On Thu, 2016-11-24 at 17:58 +0200, Andy Shevchenko wrote:
> > On Thu, 2016-11-24 at 17:52 +0200, Andy Shevchenko wrote:
> > >
> > > On Thu, 2016-11-24 at 18:04 +0300, Eugeniy Paltsev wrote:
> > > >
> > > > Several versions of DW DMAC have multi block transfers hardware
> > > > support. Hardware support of multi block transfers is disabled
> > > > by default if we use DT to configure DMAC and software emulation
> > > > of multi block transfers used instead.
> > > > Add multi-block property, so it is possible to enable hardware
> > > > multi block transfers (if present) via DT.
> > > >
> > > > Switch from per device is_nollp variable to multi_block array
> > > > to be able enable/disable multi block transfers separately per
> > > > channel.
> > >
> > > Thanks for an update. Basically I'm fine with this one.
> > >
> > > So, we still have question about autoconfiguration in SPEAr SoCs,
> > > and
> > > your ARC SoC but it's a different story. I would expect once you
> > > will
> > > clarify it.
> > >
> > > Another one is minor listed below, otherwise
> > >
> > > Acked-by: Andy Shevchenko <andriy.shevchenko-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
> > >
> > > >
> > > > @@ -152,6 +154,11 @@ dw_dma_parse_dt(struct platform_device
> > > > *pdev)
> > > > pdata->data_width[tmp] = BIT(arr[tmp] &
> > > > 0x07);
> > > > }
> > > >
> > > > + if (!of_property_read_u32_array(np, "multi-block",
> > > > chan,
> > > > nr_channels)) {
> > > > + for (tmp = 0; tmp < nr_channels; tmp++)
> > > > + pdata->multi_block[tmp] = chan[tmp];
> > >
> > > ...mb (as short of multi-block) would suit better.
> >
> > Oh, sorry, guys, but one more important thing. If there is no such
> > property, keep a default to "supported". Otherwise you will break
> > old
> > (working) DTBs.
>
> Should I remove explicit declaration "multi-block" property from
> existing DTS (which I added during v5 patch iteration)?
>
> I mean that:
> ---------------------->8-----------------------
> + multi-block = <1 1 1 1 1 1 1 1>;
> ---------------------->8-----------------------
>
> We don't actually need it, if we use use 1 ("supported") as "multi-
> block" property default value.
My understanding is better to leave to show that the new option has been
introduced.
It would be possible to do when you confirm that your ARC platform along
with SPEAr supports auto configuration including this property.
--
Andy Shevchenko <andriy.shevchenko-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
Intel Finland Oy
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH v5 2/2] DW DMAC: add multi-block property to device tree
From: Eugeniy Paltsev @ 2016-11-25 11:40 UTC (permalink / raw)
To: andriy.shevchenko@linux.intel.com
Cc: mark.rutland@arm.com, devicetree@vger.kernel.org,
christian.ruppert@alitech.com, arnd@arndb.de,
vinod.koul@intel.com, vireshk@kernel.org,
linux-kernel@vger.kernel.org, robh+dt@kernel.org,
dmaengine@vger.kernel.org, linux-snps-arc@lists.infradead.org,
shiraz.linux.kernel@gmail.com
In-Reply-To: <1480003098.20074.18.camel@linux.intel.com>
On Thu, 2016-11-24 at 17:58 +0200, Andy Shevchenko wrote:
> On Thu, 2016-11-24 at 17:52 +0200, Andy Shevchenko wrote:
> >
> > On Thu, 2016-11-24 at 18:04 +0300, Eugeniy Paltsev wrote:
> > >
> > > Several versions of DW DMAC have multi block transfers hardware
> > > support. Hardware support of multi block transfers is disabled
> > > by default if we use DT to configure DMAC and software emulation
> > > of multi block transfers used instead.
> > > Add multi-block property, so it is possible to enable hardware
> > > multi block transfers (if present) via DT.
> > >
> > > Switch from per device is_nollp variable to multi_block array
> > > to be able enable/disable multi block transfers separately per
> > > channel.
> > Thanks for an update. Basically I'm fine with this one.
> >
> > So, we still have question about autoconfiguration in SPEAr SoCs,
> > and
> > your ARC SoC but it's a different story. I would expect once you
> > will
> > clarify it.
> >
> > Another one is minor listed below, otherwise
> >
> > Acked-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
> >
> > >
> > > @@ -152,6 +154,11 @@ dw_dma_parse_dt(struct platform_device
> > > *pdev)
> > > pdata->data_width[tmp] = BIT(arr[tmp] &
> > > 0x07);
> > > }
> > >
> > > + if (!of_property_read_u32_array(np, "multi-block", chan,
> > > nr_channels)) {
> > > + for (tmp = 0; tmp < nr_channels; tmp++)
> > > + pdata->multi_block[tmp] = chan[tmp];
> > ...mb (as short of multi-block) would suit better.
> Oh, sorry, guys, but one more important thing. If there is no such
> property, keep a default to "supported". Otherwise you will break old
> (working) DTBs.
Should I remove explicit declaration "multi-block" property from
existing DTS (which I added during v5 patch iteration)?
I mean that:
---------------------->8-----------------------
+ multi-block = <1 1 1 1 1 1 1 1>;
---------------------->8-----------------------
We don't actually need it, if we use use 1 ("supported") as "multi-
block" property default value.
--
Paltsev Eugeniy
_______________________________________________
linux-snps-arc mailing list
linux-snps-arc@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-snps-arc
^ permalink raw reply
* Re: [PATCH V4 1/2] pinctrl: tegra: Add DT binding for io pads control
From: Laxman Dewangan @ 2016-11-25 11:40 UTC (permalink / raw)
To: Thierry Reding
Cc: linus.walleij-QSEj5FYQhm4dnm+yROfE0A,
robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8,
swarren-3lzwWm7+Weoh9ZMKESR00Q, gnurou-Re5JQEeQqe8AvxtiuMwx3w,
jonathanh-DDmLM1+adcrQT0dZR+AlfA, joe-6d6DIl74uiNBDgjK7y7TUQ,
yamada.masahiro-uWyLwvC0a2jby3iVrkZq2A,
linux-gpio-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-tegra-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20161125091354.GA11512-EkSeR96xj6Pcmrwk2tT4+A@public.gmane.org>
On Friday 25 November 2016 02:43 PM, Thierry Reding wrote:
> * PGP Signed by an unknown key
>
> On Thu, Nov 24, 2016 at 02:08:53PM +0530, Laxman Dewangan wrote:
>> +
>> +The DT property of the IO pads must be under the node of pmc i.e.
>> +pmc@7000e400 for Tegra124 onwards.
> The PMC is at a different address on Tegra186, so I think we should just
> drop this to avoid having to update it whenever a new chip relocates it
> to a different address.
I wanted to provide the example. So let me say that "i.e. pmc@7000e400
for Tegra124". In this way we will not need to update for every chips
and also give idea bout the node.
>
> Come to think of it, if these I/O pads are represented as subnodes in
> the PMC device tree node, perhaps this should be merged into the PMC
> documentation?
Based on my MFD and sub devices experience, maintainers prefer to have
different DT binding document for subsystem child devices.
So if we say the io-pad is sub device of pmc then it will be in
respective subsystem dt binding.
>
>> +
>> +See the TRM to determine which properties and values apply to each IO pads.
> Perhaps give a reference to where in the TRM this can be found?
Do we have fixed link for the TRM? and do we really need to provide the
link here? If link get changed then we will need to change all places.
>
>> +low-power-enable: enable low power mode.
>> +low-power-disable: disable low power mode.
> Why the extra padding with tabs? I find that difficult to read. Also, no
> need for a fullstop since it's not a proper sentence.
Just to make proper alignment. Regular typing is not preferred in general.
>> +IO voltage pin names are as follows:
>> + audio -> vddio-audio
>> + audio-hv -> vddio-audio-hv
>> + cam ->vddio-cam
>> + dbg -> vddio-dbg
>> + dmic -> vddio-dmic
>> + gpio -> vddio-gpio
>> + pex-ctrl -> vddio-pex-ctrl
>> + sdmmc1 -> vddio-sdmmc1
>> + sdmmc3 -> vddio-sdmmc3
>> + spi -> vddio-spi
>> + spi-hv -> vddio-spi-hv
>> + uart -> vddio-uart
> It's slightly confusing to only have this list for Tegra210. I assume
> that is because on Tegra124 there is no way to control the voltage of
> the pins, but I think that could be made clearer.
I think I made it in first few paragraph of this document but will add
here also.
> Also, it might be
> worth explicitly mentioning that this is a subset of the list of pins
> given above and that the other pins (those not in this list) don't
> support 1.8/3.3 V control, but only the low power state.
ok.
>
> + audio-hv {
> + pins = "audio-hv";
> + low-power-disable;
> + };
> I wonder if this is at all useful. Shouldn't we rather put all pads into
> a low-power state by default and only take them out of the low-power
> state when the driver decides to do so?
>
We can not do this all disable by default and enable by driver. it may
be possible that some of io-pads need to be enable during boot.
We need to only depends on platform specific data provided from DT here
for configurations.
However, for dynamic control, driver can use pinctrl framework for
optimizing the power.
^ permalink raw reply
* Re: [PATCH v9 3/4] dtc: Plugin and fixup support
From: David Gibson @ 2016-11-25 11:26 UTC (permalink / raw)
To: Pantelis Antoniou
Cc: Jon Loeliger, Grant Likely, Frank Rowand, Rob Herring, Jan Luebbe,
Sascha Hauer, Phil Elwell, Simon Glass, Maxime Ripard,
Thomas Petazzoni, Boris Brezillon, Antoine Tenart, Stephen Boyd,
Devicetree Compiler, devicetree-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <B39EF108-E592-4345-A5A7-951883AA099B-OWPKS81ov/FWk0Htik3J/w@public.gmane.org>
[-- Attachment #1: Type: text/plain, Size: 38932 bytes --]
On Fri, Nov 25, 2016 at 12:55:25PM +0200, Pantelis Antoniou wrote:
> Hi David,
>
> > On Nov 25, 2016, at 06:11 , David Gibson <david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org> wrote:
> >
> > On Thu, Nov 24, 2016 at 02:31:32PM +0200, Pantelis Antoniou wrote:
> >> This patch enable the generation of symbols & local fixup information
> >> for trees compiled with the -@ (--symbols) option.
> >>
> >> Using this patch labels in the tree and their users emit information
> >> in __symbols__ and __local_fixups__ nodes.
> >>
> >> The __fixups__ node make possible the dynamic resolution of phandle
> >> references which are present in the plugin tree but lie in the
> >> tree that are applying the overlay against.
> >>
> >> While there is a new magic number for dynamic device tree/overlays blobs
> >> it is by default disabled. This is in order to give time for DT blob
> >> methods to be updated.
> >>
> >> Signed-off-by: Pantelis Antoniou <pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w@public.gmane.org>
> >> Signed-off-by: Sascha Hauer <s.hauer-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
> >> Signed-off-by: Jan Luebbe <jlu-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
> >> ---
> >> Documentation/manual.txt | 25 +++++-
> >> checks.c | 8 +-
> >> dtc-lexer.l | 5 ++
> >> dtc-parser.y | 49 +++++++++--
> >> dtc.c | 39 +++++++-
> >> dtc.h | 20 ++++-
> >> fdtdump.c | 2 +-
> >> flattree.c | 17 ++--
> >> fstree.c | 2 +-
> >> libfdt/fdt.c | 2 +-
> >> libfdt/fdt.h | 3 +-
> >> livetree.c | 225 ++++++++++++++++++++++++++++++++++++++++++++++-
> >> tests/mangle-layout.c | 7 +-
> >> treesource.c | 7 +-
> >> 14 files changed, 380 insertions(+), 31 deletions(-)
> >>
> >> diff --git a/Documentation/manual.txt b/Documentation/manual.txt
> >> index 398de32..65fbf09 100644
> >> --- a/Documentation/manual.txt
> >> +++ b/Documentation/manual.txt
> >> @@ -119,6 +119,24 @@ Options:
> >> Make space for <number> reserve map entries
> >> Relevant for dtb and asm output only.
> >>
> >> + -@
> >> + Generates a __symbols__ node at the root node of the resulting blob
> >> + for any node labels used, and for any local references using phandles
> >> + it also generates a __local_fixups__ node that tracks them.
> >> +
> >> + When using the /plugin/ tag all unresolved label references to
> >> + be tracked in the __fixups__ node, making dynamic resolution possible.
> >> +
> >> + -A
> >> + Generate automatically aliases for all node labels. This is similar to
> >> + the -@ option (the __symbols__ node contain identical information) but
> >> + the semantics are slightly different since no phandles are automatically
> >> + generated for labeled nodes.
> >> +
> >> + -M
> >> + Generate blobs with the new FDT magic number. By default blobs with the
> >> + standard FDT magic number are generated.
> >
> > First, this description is incomplete since -M *only* affects the
> > magic number for /plugin/ input, not in other cases. Second, the
> > default is the wrong way around. If we make old-style the default,
> > then new-style will never be used, which defeats the purpose.
>
> Then we’ll break user-space that has this assumption (i.e. that the magic is the same).
> I can certainly do it the other way around.
Which userspace in particular?
> >> +
> >> -S <bytes>
> >> Ensure the blob at least <bytes> long, adding additional
> >> space if needed.
> >> @@ -146,13 +164,18 @@ Additionally, dtc performs various sanity checks on the tree.
> >> Here is a very rough overview of the layout of a DTS source file:
> >>
> >>
> >> - sourcefile: list_of_memreserve devicetree
> >> + sourcefile: versioninfo plugindecl list_of_memreserve devicetree
> >>
> >> memreserve: label 'memreserve' ADDR ADDR ';'
> >> | label 'memreserve' ADDR '-' ADDR ';'
> >>
> >> devicetree: '/' nodedef
> >>
> >> + versioninfo: '/' 'dts-v1' '/' ';'
> >> +
> >> + plugindecl: '/' 'plugin' '/' ';'
> >> + | /* empty */
> >> +
> >> nodedef: '{' list_of_property list_of_subnode '}' ';'
> >>
> >> property: label PROPNAME '=' propdata ';'
> >> diff --git a/checks.c b/checks.c
> >> index 609975a..bc03d42 100644
> >> --- a/checks.c
> >> +++ b/checks.c
> >> @@ -486,8 +486,12 @@ static void fixup_phandle_references(struct check *c, struct boot_info *bi,
> >>
> >> refnode = get_node_by_ref(dt, m->ref);
> >> if (! refnode) {
> >> - FAIL(c, "Reference to non-existent node or label \"%s\"\n",
> >> - m->ref);
> >> + if (!(bi->versionflags & VF_PLUGIN))
> >> + FAIL(c, "Reference to non-existent node or "
> >> + "label \"%s\"\n", m->ref);
> >> + else /* mark the entry as unresolved */
> >> + *((cell_t *)(prop->val.val + m->offset)) =
> >> + cpu_to_fdt32(0xffffffff);
> >> continue;
> >> }
> >>
> >> diff --git a/dtc-lexer.l b/dtc-lexer.l
> >> index 790fbf6..40bbc87 100644
> >> --- a/dtc-lexer.l
> >> +++ b/dtc-lexer.l
> >> @@ -121,6 +121,11 @@ static void lexical_error(const char *fmt, ...);
> >> return DT_V1;
> >> }
> >>
> >> +<*>"/plugin/" {
> >> + DPRINT("Keyword: /plugin/\n");
> >> + return DT_PLUGIN;
> >> + }
> >> +
> >> <*>"/memreserve/" {
> >> DPRINT("Keyword: /memreserve/\n");
> >> BEGIN_DEFAULT();
> >> diff --git a/dtc-parser.y b/dtc-parser.y
> >> index 14aaf2e..4afc592 100644
> >> --- a/dtc-parser.y
> >> +++ b/dtc-parser.y
> >> @@ -19,6 +19,7 @@
> >> */
> >> %{
> >> #include <stdio.h>
> >> +#include <inttypes.h>
> >>
> >> #include "dtc.h"
> >> #include "srcpos.h"
> >> @@ -33,6 +34,9 @@ extern void yyerror(char const *s);
> >>
> >> extern struct boot_info *the_boot_info;
> >> extern bool treesource_error;
> >> +
> >> +/* temporary while the tree is not built */
> >> +static unsigned int the_versionflags;
> >
> > Hrm. Using a global during parsing is pretty dangerous - it makes
> > assumptions about the order in which bison will execute semantic
> > actions that may not always be correct.
> >
> > It'll probably work in practice, so I *might* be convinced it's
> > adequate for a first cut. I'm a bit reluctant though, since I suspect
> > once merged it will become entrenched.
> >
>
> We use bison, globals are the way of life. It’s not going to be used
> anywhere else, it’s static in the parser file.
Using globals to communicate the final result is inevitable (well, not
without using the whole different re-entrant interface stuff). That
just assumes that the start symbol's semantic action is executed
before the parser competes, which is guaranteed.
This is a different matter - using a global to communicate between
different parts of the parser. More specifically different parts of
the parser that are in different arms of the parse tree. That makes
assumptions about the relative order of semantic actions which are
*not* guaranteed. In theory the parser could generate the entire
parse tree and semantic action dependency graph, then execute them in
an arbitrary order (well, it would have to be a topologically sorted
order, but that won't help).
> We could allocate the boot_info earlier (when the v1tag is detected) but
> that would be quite a big change for something as trivial.
That wouldn't help. You still wouldn't have a guarantee on the order
between setting the version flags and using the version flags.
> > The correct way to handle this, IMO, is not to ever attempt to apply
> > overlays during the parse. Basically, we'd change the overall
> > structure so that the output from the parser is not a single tree, but
> > a list of overlays / fragments. Then, once the parse is complete, so
> > versioninfo (which could now become a member of bootinfo) is well
> > defined, we either apply the fragments in place (base tree) or encode
> > them into the overlay structure (plugin mode).
> >
> > See https://github.com/dgibson/dtc/tree/overlay for some incomplete
> > work I did in this direction.
> >
>
> This tree is pretty stale; last commit was back in march.
Yes, it was a while since I worked on it. It rebased clean, though.
> I thing there’s a wrong assumption here. The purpose of this patch is not
> to apply overlays during compile time, is to generate a blob that can be
> applied at runtime by another piece of software.
No, I realise what you're doing. But the input is in the form of a
batch of overlays, regardless. You then have two modes of operation:
for base trees you resolve those overlays during the compile, for
plugins you assemble those overlays into a blob which can be applied
later.
Because it wasn't designed with runtime overlays in mind, the current
code handles the resolution of those overlays during the parse. Your
patch extends that by rather than resolving them, just putting them
together with metadata into the dtbo.
I'm saying that resolution or assembly should be moved out of the
parser. Instead, the parser output would be an (ordered) list of
overlay fragments. In the main program the two modes of operation
become explicit: for base trees we resolve the overlays into a single
tree, for plugins we collate the pieces into the dtbo format.
> > In addition to not making unsafe assumptions about parser operation, I
> > think this will also allow for better error reporting. It also moves
> > more code into plain-old-C instead of potentially hard to follow bison
> > code fragments.
> >
>
> We don’t try to apply overlays during parse, and especially in the parse code.
The existing code does this, and you don't change it. Furthermore you
absolutely do do the assembly of the fragments within the parser -
that's exactly what add_orphan_node() called directly from semantic
actions does. To verify this, all you need to do is look at the
parser output: the boot_info structure has just a single tree, not a
list of overlays.
> The global is used only for the syntactic sugar method of turning a &ref { };
> node into an overlay.
I'm saying that treating that as mere syntactic sugar is a fundamental
error in design. We could get away with it when the &ref {} stuff was
always resolved immediately. Now that that resolution can be delayed
until later, it gets worse. We should move that resolution outside of
the parser.
>
> >> %}
> >>
> >> %union {
> >> @@ -52,9 +56,11 @@ extern bool treesource_error;
> >> struct node *nodelist;
> >> struct reserve_info *re;
> >> uint64_t integer;
> >> + unsigned int flags;
> >> }
> >>
> >> %token DT_V1
> >> +%token DT_PLUGIN
> >> %token DT_MEMRESERVE
> >> %token DT_LSHIFT DT_RSHIFT DT_LE DT_GE DT_EQ DT_NE DT_AND DT_OR
> >> %token DT_BITS
> >> @@ -71,6 +77,8 @@ extern bool treesource_error;
> >>
> >> %type <data> propdata
> >> %type <data> propdataprefix
> >> +%type <flags> versioninfo
> >> +%type <flags> plugindecl
> >> %type <re> memreserve
> >> %type <re> memreserves
> >> %type <array> arrayprefix
> >> @@ -101,16 +109,36 @@ extern bool treesource_error;
> >> %%
> >>
> >> sourcefile:
> >> - v1tag memreserves devicetree
> >> + versioninfo plugindecl memreserves devicetree
> >> + {
> >> + the_boot_info = build_boot_info($1 | $2, $3, $4,
> >> + guess_boot_cpuid($4));
> >> + }
> >> + ;
> >> +
> >> +versioninfo:
> >> + v1tag
> >> {
> >> - the_boot_info = build_boot_info($2, $3,
> >> - guess_boot_cpuid($3));
> >> + the_versionflags |= VF_DT_V1;
> >> + $$ = the_versionflags;
> >> }
> >> ;
> >>
> >> v1tag:
> >> DT_V1 ';'
> >> + | DT_V1
> >> | DT_V1 ';' v1tag
> >> +
> >> +plugindecl:
> >> + DT_PLUGIN ';'
> >> + {
> >> + the_versionflags |= VF_PLUGIN;
> >> + $$ = VF_PLUGIN;
> >> + }
> >> + | /* empty */
> >> + {
> >> + $$ = 0;
> >> + }
> >> ;
> >>
> >> memreserves:
> >> @@ -161,10 +189,14 @@ devicetree:
> >> {
> >> struct node *target = get_node_by_ref($1, $2);
> >>
> >> - if (target)
> >> + if (target) {
> >> merge_nodes(target, $3);
> >> - else
> >> - ERROR(&@2, "Label or path %s not found", $2);
> >> + } else {
> >> + if (the_versionflags & VF_PLUGIN)
> >> + add_orphan_node($1, $3, $2);
> >> + else
> >> + ERROR(&@2, "Label or path %s not found", $2);
> >> + }
> >> $$ = $1;
> >> }
> >> | devicetree DT_DEL_NODE DT_REF ';'
> >> @@ -179,6 +211,11 @@ devicetree:
> >>
> >> $$ = $1;
> >> }
> >> + | /* empty */
> >> + {
> >> + /* build empty node */
> >> + $$ = name_node(build_node(NULL, NULL), "");
> >> + }
> >> ;
> >>
> >> nodedef:
> >> diff --git a/dtc.c b/dtc.c
> >> index 9dcf640..a654267 100644
> >> --- a/dtc.c
> >> +++ b/dtc.c
> >> @@ -32,6 +32,9 @@ int minsize; /* Minimum blob size */
> >> int padsize; /* Additional padding to blob */
> >> int alignsize; /* Additional padding to blob accroding to the alignsize */
> >> int phandle_format = PHANDLE_BOTH; /* Use linux,phandle or phandle properties */
> >> +int symbol_fixup_support; /* enable symbols & fixup support */
> >> +int auto_label_aliases; /* auto generate labels -> aliases */
> >> +int new_magic; /* use new FDT magic values for objects */
> >>
> >> static int is_power_of_2(int x)
> >> {
> >> @@ -59,7 +62,7 @@ static void fill_fullpaths(struct node *tree, const char *prefix)
> >> #define FDT_VERSION(version) _FDT_VERSION(version)
> >> #define _FDT_VERSION(version) #version
> >> static const char usage_synopsis[] = "dtc [options] <input file>";
> >> -static const char usage_short_opts[] = "qI:O:o:V:d:R:S:p:a:fb:i:H:sW:E:hv";
> >> +static const char usage_short_opts[] = "qI:O:o:V:d:R:S:p:a:fb:i:H:sW:E:@AMhv";
> >> static struct option const usage_long_opts[] = {
> >> {"quiet", no_argument, NULL, 'q'},
> >> {"in-format", a_argument, NULL, 'I'},
> >> @@ -78,6 +81,9 @@ static struct option const usage_long_opts[] = {
> >> {"phandle", a_argument, NULL, 'H'},
> >> {"warning", a_argument, NULL, 'W'},
> >> {"error", a_argument, NULL, 'E'},
> >> + {"symbols", no_argument, NULL, '@'},
> >> + {"auto-alias", no_argument, NULL, 'A'},
> >> + {"new-magic", no_argument, NULL, 'M'},
> >> {"help", no_argument, NULL, 'h'},
> >> {"version", no_argument, NULL, 'v'},
> >> {NULL, no_argument, NULL, 0x0},
> >> @@ -109,6 +115,9 @@ static const char * const usage_opts_help[] = {
> >> "\t\tboth - Both \"linux,phandle\" and \"phandle\" properties",
> >> "\n\tEnable/disable warnings (prefix with \"no-\")",
> >> "\n\tEnable/disable errors (prefix with \"no-\")",
> >> + "\n\tEnable symbols/fixup support",
> >> + "\n\tEnable auto-alias of labels",
> >> + "\n\tUse new blog magic value",
> >> "\n\tPrint this help and exit",
> >> "\n\tPrint version and exit",
> >> NULL,
> >> @@ -153,7 +162,7 @@ static const char *guess_input_format(const char *fname, const char *fallback)
> >> fclose(f);
> >>
> >> magic = fdt32_to_cpu(magic);
> >> - if (magic == FDT_MAGIC)
> >> + if (magic == FDT_MAGIC || magic == FDT_MAGIC_DTBO)
> >> return "dtb";
> >>
> >> return guess_type_by_name(fname, fallback);
> >> @@ -172,6 +181,7 @@ int main(int argc, char *argv[])
> >> FILE *outf = NULL;
> >> int outversion = DEFAULT_FDT_VERSION;
> >> long long cmdline_boot_cpuid = -1;
> >> + fdt32_t out_magic = FDT_MAGIC;
> >>
> >> quiet = 0;
> >> reservenum = 0;
> >> @@ -249,6 +259,16 @@ int main(int argc, char *argv[])
> >> parse_checks_option(false, true, optarg);
> >> break;
> >>
> >> + case '@':
> >> + symbol_fixup_support = 1;
> >> + break;
> >> + case 'A':
> >> + auto_label_aliases = 1;
> >> + break;
> >> + case 'M':
> >> + new_magic = 1;
> >> + break;
> >> +
> >> case 'h':
> >> usage(NULL);
> >> default:
> >> @@ -306,6 +326,14 @@ int main(int argc, char *argv[])
> >> fill_fullpaths(bi->dt, "");
> >> process_checks(force, bi);
> >>
> >> + if (auto_label_aliases)
> >> + generate_label_tree(bi->dt, "aliases", false);
> >> +
> >> + if (symbol_fixup_support) {
> >> + generate_label_tree(bi->dt, "__symbols__", true);
> >> + generate_fixups_tree(bi->dt);
> >> + }
> >> +
> >> if (sort)
> >> sort_tree(bi);
> >>
> >> @@ -318,12 +346,15 @@ int main(int argc, char *argv[])
> >> outname, strerror(errno));
> >> }
> >>
> >> + if (new_magic && (bi->versionflags & VF_PLUGIN))
> >> + out_magic = FDT_MAGIC_DTBO;
> >> +
> >> if (streq(outform, "dts")) {
> >> dt_to_source(outf, bi);
> >> } else if (streq(outform, "dtb")) {
> >> - dt_to_blob(outf, bi, outversion);
> >> + dt_to_blob(outf, bi, out_magic, outversion);
> >> } else if (streq(outform, "asm")) {
> >> - dt_to_asm(outf, bi, outversion);
> >> + dt_to_asm(outf, bi, out_magic, outversion);
> >> } else if (streq(outform, "null")) {
> >> /* do nothing */
> >> } else {
> >> diff --git a/dtc.h b/dtc.h
> >> index 32009bc..889b8f8 100644
> >> --- a/dtc.h
> >> +++ b/dtc.h
> >> @@ -55,6 +55,9 @@ extern int minsize; /* Minimum blob size */
> >> extern int padsize; /* Additional padding to blob */
> >> extern int alignsize; /* Additional padding to blob accroding to the alignsize */
> >> extern int phandle_format; /* Use linux,phandle or phandle properties */
> >> +extern int symbol_fixup_support;/* enable symbols & fixup support */
> >> +extern int auto_label_aliases; /* auto generate labels -> aliases */
> >> +extern int new_magic; /* use new FDT magic values for objects */
> >>
> >> #define PHANDLE_LEGACY 0x1
> >> #define PHANDLE_EPAPR 0x2
> >> @@ -195,6 +198,7 @@ struct node *build_node_delete(void);
> >> struct node *name_node(struct node *node, char *name);
> >> struct node *chain_node(struct node *first, struct node *list);
> >> struct node *merge_nodes(struct node *old_node, struct node *new_node);
> >> +void add_orphan_node(struct node *old_node, struct node *new_node, char *ref);
> >>
> >> void add_property(struct node *node, struct property *prop);
> >> void delete_property_by_name(struct node *node, char *name);
> >> @@ -202,6 +206,8 @@ void delete_property(struct property *prop);
> >> void add_child(struct node *parent, struct node *child);
> >> void delete_node_by_name(struct node *parent, char *name);
> >> void delete_node(struct node *node);
> >> +void append_to_property(struct node *node,
> >> + char *name, const void *data, int len);
> >>
> >> const char *get_unitname(struct node *node);
> >> struct property *get_property(struct node *node, const char *propname);
> >> @@ -237,14 +243,22 @@ struct reserve_info *add_reserve_entry(struct reserve_info *list,
> >>
> >>
> >> struct boot_info {
> >> + unsigned int versionflags;
> >> struct reserve_info *reservelist;
> >> struct node *dt; /* the device tree */
> >> uint32_t boot_cpuid_phys;
> >> };
> >>
> >> -struct boot_info *build_boot_info(struct reserve_info *reservelist,
> >> +/* version flags definitions */
> >> +#define VF_DT_V1 0x0001 /* /dts-v1/ */
> >> +#define VF_PLUGIN 0x0002 /* /plugin/ */
> >> +
> >> +struct boot_info *build_boot_info(unsigned int versionflags,
> >> + struct reserve_info *reservelist,
> >> struct node *tree, uint32_t boot_cpuid_phys);
> >> void sort_tree(struct boot_info *bi);
> >> +void generate_label_tree(struct node *dt, char *gen_node_name, bool allocph);
> >> +void generate_fixups_tree(struct node *dt);
> >>
> >> /* Checks */
> >>
> >> @@ -253,8 +267,8 @@ void process_checks(bool force, struct boot_info *bi);
> >>
> >> /* Flattened trees */
> >>
> >> -void dt_to_blob(FILE *f, struct boot_info *bi, int version);
> >> -void dt_to_asm(FILE *f, struct boot_info *bi, int version);
> >> +void dt_to_blob(FILE *f, struct boot_info *bi, fdt32_t magic, int version);
> >> +void dt_to_asm(FILE *f, struct boot_info *bi, fdt32_t magic, int version);
> >>
> >> struct boot_info *dt_from_blob(const char *fname);
> >>
> >> diff --git a/fdtdump.c b/fdtdump.c
> >> index a9a2484..dd63ac2 100644
> >> --- a/fdtdump.c
> >> +++ b/fdtdump.c
> >> @@ -201,7 +201,7 @@ int main(int argc, char *argv[])
> >> p = memchr(p, smagic[0], endp - p - FDT_MAGIC_SIZE);
> >> if (!p)
> >> break;
> >> - if (fdt_magic(p) == FDT_MAGIC) {
> >> + if (fdt_magic(p) == FDT_MAGIC || fdt_magic(p) == FDT_MAGIC_DTBO) {
> >> /* try and validate the main struct */
> >> off_t this_len = endp - p;
> >> fdt32_t max_version = 17;
> >> diff --git a/flattree.c b/flattree.c
> >> index a9d9520..57d76cf 100644
> >> --- a/flattree.c
> >> +++ b/flattree.c
> >> @@ -335,6 +335,7 @@ static struct data flatten_reserve_list(struct reserve_info *reservelist,
> >> }
> >>
> >> static void make_fdt_header(struct fdt_header *fdt,
> >> + fdt32_t magic,
> >> struct version_info *vi,
> >> int reservesize, int dtsize, int strsize,
> >> int boot_cpuid_phys)
> >> @@ -345,7 +346,7 @@ static void make_fdt_header(struct fdt_header *fdt,
> >>
> >> memset(fdt, 0xff, sizeof(*fdt));
> >>
> >> - fdt->magic = cpu_to_fdt32(FDT_MAGIC);
> >> + fdt->magic = cpu_to_fdt32(magic);
> >> fdt->version = cpu_to_fdt32(vi->version);
> >> fdt->last_comp_version = cpu_to_fdt32(vi->last_comp_version);
> >>
> >> @@ -366,7 +367,7 @@ static void make_fdt_header(struct fdt_header *fdt,
> >> fdt->size_dt_struct = cpu_to_fdt32(dtsize);
> >> }
> >>
> >> -void dt_to_blob(FILE *f, struct boot_info *bi, int version)
> >> +void dt_to_blob(FILE *f, struct boot_info *bi, fdt32_t magic, int version)
> >> {
> >> struct version_info *vi = NULL;
> >> int i;
> >> @@ -390,7 +391,7 @@ void dt_to_blob(FILE *f, struct boot_info *bi, int version)
> >> reservebuf = flatten_reserve_list(bi->reservelist, vi);
> >>
> >> /* Make header */
> >> - make_fdt_header(&fdt, vi, reservebuf.len, dtbuf.len, strbuf.len,
> >> + make_fdt_header(&fdt, magic, vi, reservebuf.len, dtbuf.len, strbuf.len,
> >> bi->boot_cpuid_phys);
> >>
> >> /*
> >> @@ -467,7 +468,7 @@ static void dump_stringtable_asm(FILE *f, struct data strbuf)
> >> }
> >> }
> >>
> >> -void dt_to_asm(FILE *f, struct boot_info *bi, int version)
> >> +void dt_to_asm(FILE *f, struct boot_info *bi, fdt32_t magic, int version)
> >> {
> >> struct version_info *vi = NULL;
> >> int i;
> >> @@ -830,6 +831,7 @@ struct boot_info *dt_from_blob(const char *fname)
> >> struct node *tree;
> >> uint32_t val;
> >> int flags = 0;
> >> + unsigned int versionflags = VF_DT_V1;
> >>
> >> f = srcfile_relative_open(fname, NULL);
> >>
> >> @@ -845,9 +847,12 @@ struct boot_info *dt_from_blob(const char *fname)
> >> }
> >>
> >> magic = fdt32_to_cpu(magic);
> >> - if (magic != FDT_MAGIC)
> >> + if (magic != FDT_MAGIC && magic != FDT_MAGIC_DTBO)
> >> die("Blob has incorrect magic number\n");
> >>
> >> + if (magic == FDT_MAGIC_DTBO)
> >> + versionflags |= VF_PLUGIN;
> >> +
> >> rc = fread(&totalsize, sizeof(totalsize), 1, f);
> >> if (ferror(f))
> >> die("Error reading DT blob size: %s\n", strerror(errno));
> >> @@ -942,5 +947,5 @@ struct boot_info *dt_from_blob(const char *fname)
> >>
> >> fclose(f);
> >>
> >> - return build_boot_info(reservelist, tree, boot_cpuid_phys);
> >> + return build_boot_info(versionflags, reservelist, tree, boot_cpuid_phys);
> >> }
> >> diff --git a/fstree.c b/fstree.c
> >> index 6d1beec..54f520b 100644
> >> --- a/fstree.c
> >> +++ b/fstree.c
> >> @@ -86,6 +86,6 @@ struct boot_info *dt_from_fs(const char *dirname)
> >> tree = read_fstree(dirname);
> >> tree = name_node(tree, "");
> >>
> >> - return build_boot_info(NULL, tree, guess_boot_cpuid(tree));
> >> + return build_boot_info(VF_DT_V1, NULL, tree, guess_boot_cpuid(tree));
> >> }
> >>
> >> diff --git a/libfdt/fdt.c b/libfdt/fdt.c
> >> index 22286a1..28d422c 100644
> >> --- a/libfdt/fdt.c
> >> +++ b/libfdt/fdt.c
> >> @@ -57,7 +57,7 @@
> >>
> >> int fdt_check_header(const void *fdt)
> >> {
> >> - if (fdt_magic(fdt) == FDT_MAGIC) {
> >> + if (fdt_magic(fdt) == FDT_MAGIC || fdt_magic(fdt) == FDT_MAGIC_DTBO) {
> >> /* Complete tree */
> >> if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION)
> >> return -FDT_ERR_BADVERSION;
> >> diff --git a/libfdt/fdt.h b/libfdt/fdt.h
> >> index 526aedb..493cd55 100644
> >> --- a/libfdt/fdt.h
> >> +++ b/libfdt/fdt.h
> >> @@ -55,7 +55,7 @@
> >> #ifndef __ASSEMBLY__
> >>
> >> struct fdt_header {
> >> - fdt32_t magic; /* magic word FDT_MAGIC */
> >> + fdt32_t magic; /* magic word FDT_MAGIC[|_DTBO] */
> >> fdt32_t totalsize; /* total size of DT block */
> >> fdt32_t off_dt_struct; /* offset to structure */
> >> fdt32_t off_dt_strings; /* offset to strings */
> >> @@ -93,6 +93,7 @@ struct fdt_property {
> >> #endif /* !__ASSEMBLY */
> >>
> >> #define FDT_MAGIC 0xd00dfeed /* 4: version, 4: total size */
> >> +#define FDT_MAGIC_DTBO 0xd00dfdb0 /* DTBO magic */
> >> #define FDT_TAGSIZE sizeof(fdt32_t)
> >>
> >> #define FDT_BEGIN_NODE 0x1 /* Start node: full name */
> >> diff --git a/livetree.c b/livetree.c
> >> index 3dc7559..1a2f4b1 100644
> >> --- a/livetree.c
> >> +++ b/livetree.c
> >> @@ -216,6 +216,31 @@ struct node *merge_nodes(struct node *old_node, struct node *new_node)
> >> return old_node;
> >> }
> >>
> >> +void add_orphan_node(struct node *dt, struct node *new_node, char *ref)
> >> +{
> >> + static unsigned int next_orphan_fragment = 0;
> >> + struct node *node = xmalloc(sizeof(*node));
> >
> > You shouldn't use a bare malloc() for a node. Use build_node() instead.
> >
>
> OK.
>
> >> + struct property *p;
> >> + struct data d = empty_data;
> >> + char *name;
> >> +
> >> + memset(node, 0, sizeof(*node));
> >> +
> >> + d = data_add_marker(d, REF_PHANDLE, ref);
> >> + d = data_append_integer(d, 0xffffffff, 32);
> >> +
> >> + p = build_property("target", d);
> >> + add_property(node, p);
> >> +
> >> + xasprintf(&name, "fragment@%u",
> >> + next_orphan_fragment++);
> >> + name_node(node, name);
> >> + name_node(new_node, "__overlay__");
> >> +
> >> + add_child(dt, node);
> >> + add_child(node, new_node);
> >> +}
> >> +
> >> struct node *chain_node(struct node *first, struct node *list)
> >> {
> >> assert(first->next_sibling == NULL);
> >> @@ -296,6 +321,23 @@ void delete_node(struct node *node)
> >> delete_labels(&node->labels);
> >> }
> >>
> >> +void append_to_property(struct node *node,
> >> + char *name, const void *data, int len)
> >> +{
> >> + struct data d;
> >> + struct property *p;
> >> +
> >> + p = get_property(node, name);
> >> + if (p) {
> >> + d = data_append_data(p->val, data, len);
> >> + p->val = d;
> >> + } else {
> >> + d = data_append_data(empty_data, data, len);
> >> + p = build_property(name, d);
> >> + add_property(node, p);
> >> + }
> >> +}
> >> +
> >> struct reserve_info *build_reserve_entry(uint64_t address, uint64_t size)
> >> {
> >> struct reserve_info *new = xmalloc(sizeof(*new));
> >> @@ -335,12 +377,14 @@ struct reserve_info *add_reserve_entry(struct reserve_info *list,
> >> return list;
> >> }
> >>
> >> -struct boot_info *build_boot_info(struct reserve_info *reservelist,
> >> +struct boot_info *build_boot_info(unsigned int versionflags,
> >> + struct reserve_info *reservelist,
> >> struct node *tree, uint32_t boot_cpuid_phys)
> >> {
> >> struct boot_info *bi;
> >>
> >> bi = xmalloc(sizeof(*bi));
> >> + bi->versionflags = versionflags;
> >> bi->reservelist = reservelist;
> >> bi->dt = tree;
> >> bi->boot_cpuid_phys = boot_cpuid_phys;
> >> @@ -709,3 +753,182 @@ void sort_tree(struct boot_info *bi)
> >> sort_reserve_entries(bi);
> >> sort_node(bi->dt);
> >> }
> >> +
> >> +/* utility helper to avoid code duplication */
> >> +static struct node *build_and_name_child_node(struct node *parent, char *name)
> >> +{
> >> + struct node *node;
> >> +
> >> + node = build_node(NULL, NULL);
> >> + name_node(node, xstrdup(name));
> >> + add_child(parent, node);
> >> +
> >> + return node;
> >> +}
> >> +
> >> +static void generate_label_tree_internal(struct node *dt, struct node *node,
> >> + struct node *an, bool allocph)
> >> +{
> >> + struct node *c;
> >> + struct property *p;
> >> + struct label *l;
> >> +
> >> + /* if if there are labels */
> >> + if (node->labels) {
> >> + /* now add the label in the node */
> >> + for_each_label(node->labels, l) {
> >> + /* check whether the label already exists */
> >> + p = get_property(an, l->label);
> >> + if (p) {
> >> + fprintf(stderr, "WARNING: label %s already"
> >> + " exists in /%s", l->label,
> >> + an->name);
> >> + continue;
> >> + }
> >> +
> >> + /* insert it */
> >> + p = build_property(l->label,
> >> + data_copy_escape_string(node->fullpath,
> >> + strlen(node->fullpath)));
> >
> > Um.. what? The node path should absolutely not be an escape string.
> > It shouldn't contain escapes to begin with, and if it does, we
> > absolutely shouldn't be turning them into special characters here.
> >
>
> OK, trivial enough to do. I tried to play it safe here but this is an overkill.
It's not overkill, it's Just Plain Wrong. Resolving escapes is not
idempotent. If you somehow had a node path with a backslash in it -
well, that would be bad to begin with - but trying to resolve that
backslash as an escape would be unambiguously worse.
> >> + add_property(an, p);
> >> + }
> >> +
> >> + /* force allocation of a phandle for this node */
> >> + if (allocph)
> >> + (void)get_node_phandle(dt, node);
> >> + }
> >> +
> >> + for_each_child(node, c)
> >> + generate_label_tree_internal(dt, c, an, allocph);
> >> +}
> >> +
> >> +void generate_label_tree(struct node *dt, char *gen_node_name, bool allocph)
> >> +{
> >> + struct node *an;
> >> +
> >> + for_each_child(dt, an)
> >> + if (streq(gen_node_name, an->name))
> >> + break;
> >> +
> >> + if (!an)
> >> + an = build_and_name_child_node(dt, gen_node_name);
> >> + if (!an)
> >> + die("Could not build label node /%s\n", gen_node_name);
> >> +
> >> + generate_label_tree_internal(dt, dt, an, allocph);
> >> +}
> >> +
> >> +static char *fixups_name = "__fixups__";
> >> +static char *local_fixups_name = "__local_fixups__";
> >
> > I'd actually prefer #defines for these, and all-caps names, so it's
> > more obvious when they're used that these are global constants.
> >
>
> OK.
>
> >> +
> >> +static void add_fixup_entry(struct node *dt, struct node *node,
> >> + struct property *prop, struct marker *m)
> >> +{
> >> + struct node *fn; /* fixup node */
> >> + char *entry;
> >> +
> >> + /* m->ref can only be a REF_PHANDLE, but check anyway */
> >> + assert(m->type == REF_PHANDLE);
> >> +
> >> + /* fn is the node we're putting entries in */
> >> + fn = get_subnode(dt, fixups_name);
> >> + assert(fn != NULL);
> >> +
> >> + /* there shouldn't be any ':' in the arguments */
> >> + if (strchr(node->fullpath, ':') || strchr(prop->name, ':'))
> >> + die("arguments should not contain ':'\n");
> >> +
> >> + xasprintf(&entry, "%s:%s:%u",
> >> + node->fullpath, prop->name, m->offset);
> >> + append_to_property(fn, m->ref, entry, strlen(entry) + 1);
> >> +}
> >> +
> >> +static void add_local_fixup_entry(struct node *dt, struct node *node,
> >> + struct property *prop, struct marker *m,
> >> + struct node *refnode)
> >> +{
> >> + struct node *lfn, *wn, *nwn; /* local fixup node, walk node, new */
> >> + uint32_t value_32;
> >> + char *s, *e, *comp;
> >> + int len;
> >> +
> >> + /* fn is the node we're putting entries in */
> >> + lfn = get_subnode(dt, local_fixups_name);
> >> + assert(lfn != NULL);
> >> +
> >> + /* walk the path components creating nodes if they don't exist */
> >> + comp = xmalloc(strlen(node->fullpath) + 1);
> >> + /* start skipping the first / */
> >> + s = node->fullpath + 1;
> >> + wn = lfn;
> >> + while (*s) {
> >> + /* retrieve path component */
> >> + e = strchr(s, '/');
> >> + if (e == NULL)
> >> + e = s + strlen(s);
> >> + len = e - s;
> >> + memcpy(comp, s, len);
> >> + comp[len] = '\0';
> >> +
> >> + /* if no node exists, create it */
> >> + nwn = get_subnode(wn, comp);
> >> + if (!nwn)
> >> + nwn = build_and_name_child_node(wn, comp);
> >> + wn = nwn;
> >> +
> >> + /* last path component */
> >> + if (!*e)
> >> + break;
> >> +
> >> + /* next path component */
> >> + s = e + 1;
> >> + }
> >> + free(comp);
> >> +
> >> + value_32 = cpu_to_fdt32(m->offset);
> >> + append_to_property(wn, prop->name, &value_32, sizeof(value_32));
> >> +}
> >> +
> >> +static void generate_fixups_tree_internal(struct node *dt, struct node *node)
> >> +{
> >> + struct node *c;
> >> + struct property *prop;
> >> + struct marker *m;
> >> + struct node *refnode;
> >> +
> >> + for_each_property(node, prop) {
> >> + m = prop->val.markers;
> >> + for_each_marker_of_type(m, REF_PHANDLE) {
> >> + refnode = get_node_by_ref(dt, m->ref);
> >> + if (!refnode)
> >> + add_fixup_entry(dt, node, prop, m);
> >> + else
> >> + add_local_fixup_entry(dt, node, prop, m,
> >> + refnode);
> >> + }
> >> + }
> >> +
> >> + for_each_child(node, c)
> >> + generate_fixups_tree_internal(dt, c);
> >> +}
> >> +
> >> +void generate_fixups_tree(struct node *dt)
> >> +{
> >> + struct node *an;
> >> +
> >> + for_each_child(dt, an)
> >> + if (streq(fixups_name, an->name))
> >> + break;
> >> +
> >> + if (!an)
> >> + build_and_name_child_node(dt, fixups_name);
> >> +
> >> + for_each_child(dt, an)
> >> + if (streq(local_fixups_name, an->name))
> >> + break;
> >> +
> >> + if (!an)
> >> + build_and_name_child_node(dt, local_fixups_name);
> >> +
> >> + generate_fixups_tree_internal(dt, dt);
> >> +}
> >> diff --git a/tests/mangle-layout.c b/tests/mangle-layout.c
> >> index a76e51e..d29ebc6 100644
> >> --- a/tests/mangle-layout.c
> >> +++ b/tests/mangle-layout.c
> >> @@ -42,7 +42,8 @@ static void expand_buf(struct bufstate *buf, int newsize)
> >> buf->size = newsize;
> >> }
> >>
> >> -static void new_header(struct bufstate *buf, int version, const void *fdt)
> >> +static void new_header(struct bufstate *buf, fdt32_t magic, int version,
> >> + const void *fdt)
> >> {
> >> int hdrsize;
> >>
> >> @@ -56,7 +57,7 @@ static void new_header(struct bufstate *buf, int version, const void *fdt)
> >> expand_buf(buf, hdrsize);
> >> memset(buf->buf, 0, hdrsize);
> >>
> >> - fdt_set_magic(buf->buf, FDT_MAGIC);
> >> + fdt_set_magic(buf->buf, magic);
> >> fdt_set_version(buf->buf, version);
> >> fdt_set_last_comp_version(buf->buf, 16);
> >> fdt_set_boot_cpuid_phys(buf->buf, fdt_boot_cpuid_phys(fdt));
> >> @@ -145,7 +146,7 @@ int main(int argc, char *argv[])
> >> if (fdt_version(fdt) < 17)
> >> CONFIG("Input tree must be v17");
> >>
> >> - new_header(&buf, version, fdt);
> >> + new_header(&buf, FDT_MAGIC, version, fdt);
> >>
> >> while (*blockorder) {
> >> add_block(&buf, version, *blockorder, fdt);
> >> diff --git a/treesource.c b/treesource.c
> >> index a55d1d1..75e920d 100644
> >> --- a/treesource.c
> >> +++ b/treesource.c
> >> @@ -267,7 +267,12 @@ void dt_to_source(FILE *f, struct boot_info *bi)
> >> {
> >> struct reserve_info *re;
> >>
> >> - fprintf(f, "/dts-v1/;\n\n");
> >> + fprintf(f, "/dts-v1/");
> >> +
> >> + if (bi->versionflags & VF_PLUGIN)
> >> + fprintf(f, " /plugin/");
> >> +
> >> + fprintf(f, ";\n\n");
> >
> > I'm not sure this really makes sense. The /plugin/ tag triggers the
> > fixup construction and encoding of overlay fragments. But in an
> > incoming dtb, that processing has already been done once, doing it
> > again would not make sense. So I think the output should not have the
> > /plugin/ tag, even if the input did.
> >
> > Unless, of course, you parsed the input into an explicit list of
> > overlays, then output it here again as a list of overlays, not the
> > encoded fragments. i.e. if this was the original tree:
> >
> > /dts-v1/ /plugin/;
> >
> > &somwhere {
> > name = "value";
> > };
> >
> > then legitimately the output of -I dts -O dts could be either:
> >
> > /dts-v1/ /plugin/;
> >
> > &somwhere {
> > name = "value";
> > };
> >
> > OR
> >
> > /dts-v1/;
> >
> > / {
> > fragment@0 {
> > target = <0xffffffff>;
> > __overlay__{
> > name = "value";
> > };
> > };
> > __fixups__ {
> > somewhere = "/fragment@0:target:0";
> > };
> > };
> >
> > But it doesn't make sense to combine the two: the second structure
> > with the "/plugin/" tag.
> >
>
> > Another advantage of moving the overlay application out of the parser
> > is you can sanely produce either output, both of which could be useful
> > in the right circumstances. You can potentially even produce the
> > first output (or something close) from dtb input, with correct parsing
> > of the overlay structure on dtb input.
> >
>
> Yes, this makes sense. For now I’ll remove the plugin tag, but if the blob
> was compiled with -@ you could conceivably reverse back to a form that contains
> labels and phandle references correctly.
>
> But this is quite complicated to undertake in this patch series.
>
> To re-iterate though there is no overlay application here :)
Well, I think we've both been a bit sloppy with terminology - does
"overlay" refer to a dtbo file, or to one of the &ref { ... }
fragments in the source, or to both.
But whatever the right term is for the &ref { .. } fragments in the
source they absolutely *are* applied during compile for the base tree
case. And while they're not resolved fully, they are encoded into
part of a larger tree structure for the plugin case.
The confusion will be reduced if we make these
overlays/fragments/whatever first class objects in the "live tree"
phase of the compile, and move the resolution and/or assembly of them
a stage that's separate from the parse. In addition, it opens the way
for decompiling a dtbo more naturally, though as you say that's a
moderate amount of extra work.
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]
^ permalink raw reply
* Re: [net-next PATCH v1 0/2] stmmac: dwmac-meson8b: configurable RGMII TX delay
From: Sebastian Frias @ 2016-11-25 11:13 UTC (permalink / raw)
To: Florian Fainelli, Martin Blumenstingl, Jerome Brunet
Cc: mark.rutland, devicetree, Mans Rullgard, alexandre.torgue,
Andrew Lunn, khilman, peppe.cavallaro, robh+dt, netdev, carlo,
linux-amlogic, davem, linux-arm-kernel
In-Reply-To: <e6ca0941-e2e3-dd93-d4d3-8fbd76b60e17@gmail.com>
On 24/11/16 19:55, Florian Fainelli wrote:
> Le 24/11/2016 à 09:05, Martin Blumenstingl a écrit :
>> On Thu, Nov 24, 2016 at 4:56 PM, Jerome Brunet <jbrunet@baylibre.com> wrote:
>>> On Thu, 2016-11-24 at 15:34 +0100, Martin Blumenstingl wrote:
>>>> Currently the dwmac-meson8b stmmac glue driver uses a hardcoded 1/4
>>>> cycle TX clock delay. This seems to work fine for many boards (for
>>>> example Odroid-C2 or Amlogic's reference boards) but there are some
>>>> others where TX traffic is simply broken.
>>>> There are probably multiple reasons why it's working on some boards
>>>> while it's broken on others:
>>>> - some of Amlogic's reference boards are using a Micrel PHY
>>>> - hardware circuit design
>>>> - maybe more...
>>>>
>>>> This raises a question though:
>>>> Which device is supposed to enable the TX delay when both MAC and PHY
>>>> support it? And should we implement it for each PHY / MAC separately
>>>> or should we think about a more generic solution (currently it's not
>>>> possible to disable the TX delay generated by the RTL8211F PHY via
>>>> devicetree when using phy-mode "rgmii")?
>>>
>>> Actually you can skip the part which activate the Tx-delay on the phy
>>> by setting "phy-mode = "rgmii-id" instead of "rgmii"
>>>
>>> phy->interface will no longer be PHY_INTERFACE_MODE_RGMII
>>> but PHY_INTERFACE_MODE_RGMII_ID.
>> unfortunately this is not true for RTL8211F (I did my previous tests
>> with the same expectation in mind)!
>> the code seems to suggest that TX-delay is disabled whenever mode !=
>> PHY_INTERFACE_MODE_RGMII.
>> BUT: on my device RTL8211F_TX_DELAY is set even before
>> "phy_write(phydev, 0x11, reg);"!
If you look at the Atheros 803x PHY and its driver
'drivers/net/phy/at803x.c':
- by default (as HW reset preset) the PHY has RX delay enabled, TX
delay disabled
- the driver only enables RX, or TX, or both, according to "rgmii-rxid",
"rgmii-txid", or "rgmii-id" respectively, but does not alter HW reset
presets. In other words:
a "rgmii-rxid" results in RX enabled (expected)
b "rgmii-txid" results in RX *and* TX enabled (unexpected?)
c "rgmii-id" results in RX *and* TX enabled (expected)
d "rgmii" results in RX enabled (unexpected?)
This is a bit surprising and I think that some boards and PHY<->MAC
combinations are working a little bit by chance, unless I'm missing
something.
>
> (Adding Sebastian (and Mans, and Andrew) since he raised the same
> question a while ago. I think I now understand a bit better what
> Sebastian was after a couple of weeks ago)
>
Thanks for CCing us, it is indeed a very similar issue.
>>
>> Based on what I found it seems that rgmii-id, rgmii-txid and
>> rgmii-rxid are supposed to be handled by the PHY.
>
> Correct, the meaning of PHY_INTERFACE_MODE should be from the
> perspective of the PHY device:
>
> - PHY_INTERFACE_MODE_RGMII_TXID means that the PHY is responsible for
> adding a delay when the MAC transmits (TX MAC -> PHY (delay) -> wire)
> - PHY_INTERFACE_MODE_RGMII_RXID means that the PHY is responsible for
> adding a delay when the MAC receives (RX MAC <- (delay) PHY) <- wire)
>
Thanks for the explanation.
Actually I had thought that the delay was to account for board routing
(wires) between the MAC and the PHY.
From your explanation it appears that the delay is to account for board
routing (wires) between the PHY and the RJ45 socket.
>> That would mean that we have two problems here:
>> 1) drivers/net/phy/realtek.c:rtl8211f_config_init should check for
>> PHY_INTERFACE_MODE_RGMII_ID or PHY_INTERFACE_MODE_RGMII_TXID and
>> enable the TX-delay in that case - otherwise explicitly disable it
>
> Agreed.
>
>> 2) dwmac-meson8b.c should only use the configured TX-delay for
>> PHY_INTERFACE_MODE_RGMII
>> @Florian: could you please share your thoughts on this (who handles
>> the TX delay in which case)?
>
> This also seems reasonable to do, provided that the PHY is also properly
> configured not to add delays in both directions, and therefore assumes
> that the MAC does it.
>
> We have a fairly large problem with how RGMII delays are done in PHYLIB
> and Ethernet MAC drivers (or just in general), where we can't really
> intersect properly what a PHY is supporting (in terms of internal
> delays), and what the MAC supports either. One possible approach could
> be to update PHY drivers a list of PHY_INTERFACE_MODE_* that they
> support (ideally, even with normalized nanosecond delay values),
Just to make sure I understood this, the DT would say something like:
phy-connection-type = "rgmii-txid";
txid-delay-ns = <3>;
For a 3ns TX delay, would that be good?
>and
> then intersect that with the requested phy_interface_t during
> phy_{attach,connect} time, and feed this back to the MAC with a special
> error code/callback, so we could gracefully try to choose another
> PHY_INTERFACE_MODE_* value that the MAC supports....
>
> A larger problem is that a number of drivers have been deployed, and
> Device Trees, possibly with the meaning of "phy-mode" and
> "phy-connection-type" being from the MAC perspective, and not the PHY
> perspective *sigh*, good luck auditing those.
>
> So from there, here is possibly what we could do
>
> - submit a series of patches that update the PHYLIB documentation (there
> are other things missing here) and make it clear from which entity (PHY
> or MAC) does the delay apply to, document the "intersection" problem here
I think documenting is necessary, thanks in advance!
However, I'm wondering if there's a way to make this work in all cases.
Indeed, if we consider for example that TX delay is required, we have 4
cases:
PHY | MAC | Who applies?
TXID supported | TXID supported | PHY
TXID supported | TXID not supported | PHY
TXID not supported | TXID supported | MAC
TXID not supported | TXID not supported | cannot be done
That is basically what my patch:
https://marc.info/?l=linux-netdev&m=147869658031783&w=2
attempted to achieve. That would allow more combinations of MAC<->PHY to
work, right?
Nevertheless, I think we also need to keep in mind that most of this
discussion assumes the case where both, MAC and PHY have equal capabilities.
Could it happen that the PHY supports only 2ns delay, and the MAC only
1ns delay?
Could it happen that the delay is bigger than what is supported by
either the PHY or MAC alone? maybe if combined it could work, for example
a 3ns delay required and the PHY supporting 2ns and the MAC 1ns, combined
it could work?
I don't know if these are cases worth supporting, nor if they are valid.
>
> - have you document the configured behavior for dwmac-meson8b that we
> just discussed here in v2 of this patch series
>
> Sorry for the long post, here is a virtual potato: 0
>
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH v9 3/4] dtc: Plugin and fixup support
From: Pantelis Antoniou @ 2016-11-25 10:55 UTC (permalink / raw)
To: David Gibson
Cc: Jon Loeliger, Grant Likely, Frank Rowand, Rob Herring, Jan Luebbe,
Sascha Hauer, Phil Elwell, Simon Glass, Maxime Ripard,
Thomas Petazzoni, Boris Brezillon, Antoine Tenart, Stephen Boyd,
Devicetree Compiler, devicetree-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20161125041124.GB12287-K0bRW+63XPQe6aEkudXLsA@public.gmane.org>
Hi David,
> On Nov 25, 2016, at 06:11 , David Gibson <david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org> wrote:
>
> On Thu, Nov 24, 2016 at 02:31:32PM +0200, Pantelis Antoniou wrote:
>> This patch enable the generation of symbols & local fixup information
>> for trees compiled with the -@ (--symbols) option.
>>
>> Using this patch labels in the tree and their users emit information
>> in __symbols__ and __local_fixups__ nodes.
>>
>> The __fixups__ node make possible the dynamic resolution of phandle
>> references which are present in the plugin tree but lie in the
>> tree that are applying the overlay against.
>>
>> While there is a new magic number for dynamic device tree/overlays blobs
>> it is by default disabled. This is in order to give time for DT blob
>> methods to be updated.
>>
>> Signed-off-by: Pantelis Antoniou <pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w@public.gmane.org>
>> Signed-off-by: Sascha Hauer <s.hauer-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
>> Signed-off-by: Jan Luebbe <jlu-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
>> ---
>> Documentation/manual.txt | 25 +++++-
>> checks.c | 8 +-
>> dtc-lexer.l | 5 ++
>> dtc-parser.y | 49 +++++++++--
>> dtc.c | 39 +++++++-
>> dtc.h | 20 ++++-
>> fdtdump.c | 2 +-
>> flattree.c | 17 ++--
>> fstree.c | 2 +-
>> libfdt/fdt.c | 2 +-
>> libfdt/fdt.h | 3 +-
>> livetree.c | 225 ++++++++++++++++++++++++++++++++++++++++++++++-
>> tests/mangle-layout.c | 7 +-
>> treesource.c | 7 +-
>> 14 files changed, 380 insertions(+), 31 deletions(-)
>>
>> diff --git a/Documentation/manual.txt b/Documentation/manual.txt
>> index 398de32..65fbf09 100644
>> --- a/Documentation/manual.txt
>> +++ b/Documentation/manual.txt
>> @@ -119,6 +119,24 @@ Options:
>> Make space for <number> reserve map entries
>> Relevant for dtb and asm output only.
>>
>> + -@
>> + Generates a __symbols__ node at the root node of the resulting blob
>> + for any node labels used, and for any local references using phandles
>> + it also generates a __local_fixups__ node that tracks them.
>> +
>> + When using the /plugin/ tag all unresolved label references to
>> + be tracked in the __fixups__ node, making dynamic resolution possible.
>> +
>> + -A
>> + Generate automatically aliases for all node labels. This is similar to
>> + the -@ option (the __symbols__ node contain identical information) but
>> + the semantics are slightly different since no phandles are automatically
>> + generated for labeled nodes.
>> +
>> + -M
>> + Generate blobs with the new FDT magic number. By default blobs with the
>> + standard FDT magic number are generated.
>
> First, this description is incomplete since -M *only* affects the
> magic number for /plugin/ input, not in other cases. Second, the
> default is the wrong way around. If we make old-style the default,
> then new-style will never be used, which defeats the purpose.
>
Then we’ll break user-space that has this assumption (i.e. that the magic is the same).
I can certainly do it the other way around.
>> +
>> -S <bytes>
>> Ensure the blob at least <bytes> long, adding additional
>> space if needed.
>> @@ -146,13 +164,18 @@ Additionally, dtc performs various sanity checks on the tree.
>> Here is a very rough overview of the layout of a DTS source file:
>>
>>
>> - sourcefile: list_of_memreserve devicetree
>> + sourcefile: versioninfo plugindecl list_of_memreserve devicetree
>>
>> memreserve: label 'memreserve' ADDR ADDR ';'
>> | label 'memreserve' ADDR '-' ADDR ';'
>>
>> devicetree: '/' nodedef
>>
>> + versioninfo: '/' 'dts-v1' '/' ';'
>> +
>> + plugindecl: '/' 'plugin' '/' ';'
>> + | /* empty */
>> +
>> nodedef: '{' list_of_property list_of_subnode '}' ';'
>>
>> property: label PROPNAME '=' propdata ';'
>> diff --git a/checks.c b/checks.c
>> index 609975a..bc03d42 100644
>> --- a/checks.c
>> +++ b/checks.c
>> @@ -486,8 +486,12 @@ static void fixup_phandle_references(struct check *c, struct boot_info *bi,
>>
>> refnode = get_node_by_ref(dt, m->ref);
>> if (! refnode) {
>> - FAIL(c, "Reference to non-existent node or label \"%s\"\n",
>> - m->ref);
>> + if (!(bi->versionflags & VF_PLUGIN))
>> + FAIL(c, "Reference to non-existent node or "
>> + "label \"%s\"\n", m->ref);
>> + else /* mark the entry as unresolved */
>> + *((cell_t *)(prop->val.val + m->offset)) =
>> + cpu_to_fdt32(0xffffffff);
>> continue;
>> }
>>
>> diff --git a/dtc-lexer.l b/dtc-lexer.l
>> index 790fbf6..40bbc87 100644
>> --- a/dtc-lexer.l
>> +++ b/dtc-lexer.l
>> @@ -121,6 +121,11 @@ static void lexical_error(const char *fmt, ...);
>> return DT_V1;
>> }
>>
>> +<*>"/plugin/" {
>> + DPRINT("Keyword: /plugin/\n");
>> + return DT_PLUGIN;
>> + }
>> +
>> <*>"/memreserve/" {
>> DPRINT("Keyword: /memreserve/\n");
>> BEGIN_DEFAULT();
>> diff --git a/dtc-parser.y b/dtc-parser.y
>> index 14aaf2e..4afc592 100644
>> --- a/dtc-parser.y
>> +++ b/dtc-parser.y
>> @@ -19,6 +19,7 @@
>> */
>> %{
>> #include <stdio.h>
>> +#include <inttypes.h>
>>
>> #include "dtc.h"
>> #include "srcpos.h"
>> @@ -33,6 +34,9 @@ extern void yyerror(char const *s);
>>
>> extern struct boot_info *the_boot_info;
>> extern bool treesource_error;
>> +
>> +/* temporary while the tree is not built */
>> +static unsigned int the_versionflags;
>
> Hrm. Using a global during parsing is pretty dangerous - it makes
> assumptions about the order in which bison will execute semantic
> actions that may not always be correct.
>
> It'll probably work in practice, so I *might* be convinced it's
> adequate for a first cut. I'm a bit reluctant though, since I suspect
> once merged it will become entrenched.
>
We use bison, globals are the way of life. It’s not going to be used
anywhere else, it’s static in the parser file.
We could allocate the boot_info earlier (when the v1tag is detected) but
that would be quite a big change for something as trivial.
> The correct way to handle this, IMO, is not to ever attempt to apply
> overlays during the parse. Basically, we'd change the overall
> structure so that the output from the parser is not a single tree, but
> a list of overlays / fragments. Then, once the parse is complete, so
> versioninfo (which could now become a member of bootinfo) is well
> defined, we either apply the fragments in place (base tree) or encode
> them into the overlay structure (plugin mode).
>
> See https://github.com/dgibson/dtc/tree/overlay for some incomplete
> work I did in this direction.
>
This tree is pretty stale; last commit was back in march.
I thing there’s a wrong assumption here. The purpose of this patch is not
to apply overlays during compile time, is to generate a blob that can be
applied at runtime by another piece of software.
> In addition to not making unsafe assumptions about parser operation, I
> think this will also allow for better error reporting. It also moves
> more code into plain-old-C instead of potentially hard to follow bison
> code fragments.
>
We don’t try to apply overlays during parse, and especially in the parse code.
The global is used only for the syntactic sugar method of turning a &ref { };
node into an overlay.
>> %}
>>
>> %union {
>> @@ -52,9 +56,11 @@ extern bool treesource_error;
>> struct node *nodelist;
>> struct reserve_info *re;
>> uint64_t integer;
>> + unsigned int flags;
>> }
>>
>> %token DT_V1
>> +%token DT_PLUGIN
>> %token DT_MEMRESERVE
>> %token DT_LSHIFT DT_RSHIFT DT_LE DT_GE DT_EQ DT_NE DT_AND DT_OR
>> %token DT_BITS
>> @@ -71,6 +77,8 @@ extern bool treesource_error;
>>
>> %type <data> propdata
>> %type <data> propdataprefix
>> +%type <flags> versioninfo
>> +%type <flags> plugindecl
>> %type <re> memreserve
>> %type <re> memreserves
>> %type <array> arrayprefix
>> @@ -101,16 +109,36 @@ extern bool treesource_error;
>> %%
>>
>> sourcefile:
>> - v1tag memreserves devicetree
>> + versioninfo plugindecl memreserves devicetree
>> + {
>> + the_boot_info = build_boot_info($1 | $2, $3, $4,
>> + guess_boot_cpuid($4));
>> + }
>> + ;
>> +
>> +versioninfo:
>> + v1tag
>> {
>> - the_boot_info = build_boot_info($2, $3,
>> - guess_boot_cpuid($3));
>> + the_versionflags |= VF_DT_V1;
>> + $$ = the_versionflags;
>> }
>> ;
>>
>> v1tag:
>> DT_V1 ';'
>> + | DT_V1
>> | DT_V1 ';' v1tag
>> +
>> +plugindecl:
>> + DT_PLUGIN ';'
>> + {
>> + the_versionflags |= VF_PLUGIN;
>> + $$ = VF_PLUGIN;
>> + }
>> + | /* empty */
>> + {
>> + $$ = 0;
>> + }
>> ;
>>
>> memreserves:
>> @@ -161,10 +189,14 @@ devicetree:
>> {
>> struct node *target = get_node_by_ref($1, $2);
>>
>> - if (target)
>> + if (target) {
>> merge_nodes(target, $3);
>> - else
>> - ERROR(&@2, "Label or path %s not found", $2);
>> + } else {
>> + if (the_versionflags & VF_PLUGIN)
>> + add_orphan_node($1, $3, $2);
>> + else
>> + ERROR(&@2, "Label or path %s not found", $2);
>> + }
>> $$ = $1;
>> }
>> | devicetree DT_DEL_NODE DT_REF ';'
>> @@ -179,6 +211,11 @@ devicetree:
>>
>> $$ = $1;
>> }
>> + | /* empty */
>> + {
>> + /* build empty node */
>> + $$ = name_node(build_node(NULL, NULL), "");
>> + }
>> ;
>>
>> nodedef:
>> diff --git a/dtc.c b/dtc.c
>> index 9dcf640..a654267 100644
>> --- a/dtc.c
>> +++ b/dtc.c
>> @@ -32,6 +32,9 @@ int minsize; /* Minimum blob size */
>> int padsize; /* Additional padding to blob */
>> int alignsize; /* Additional padding to blob accroding to the alignsize */
>> int phandle_format = PHANDLE_BOTH; /* Use linux,phandle or phandle properties */
>> +int symbol_fixup_support; /* enable symbols & fixup support */
>> +int auto_label_aliases; /* auto generate labels -> aliases */
>> +int new_magic; /* use new FDT magic values for objects */
>>
>> static int is_power_of_2(int x)
>> {
>> @@ -59,7 +62,7 @@ static void fill_fullpaths(struct node *tree, const char *prefix)
>> #define FDT_VERSION(version) _FDT_VERSION(version)
>> #define _FDT_VERSION(version) #version
>> static const char usage_synopsis[] = "dtc [options] <input file>";
>> -static const char usage_short_opts[] = "qI:O:o:V:d:R:S:p:a:fb:i:H:sW:E:hv";
>> +static const char usage_short_opts[] = "qI:O:o:V:d:R:S:p:a:fb:i:H:sW:E:@AMhv";
>> static struct option const usage_long_opts[] = {
>> {"quiet", no_argument, NULL, 'q'},
>> {"in-format", a_argument, NULL, 'I'},
>> @@ -78,6 +81,9 @@ static struct option const usage_long_opts[] = {
>> {"phandle", a_argument, NULL, 'H'},
>> {"warning", a_argument, NULL, 'W'},
>> {"error", a_argument, NULL, 'E'},
>> + {"symbols", no_argument, NULL, '@'},
>> + {"auto-alias", no_argument, NULL, 'A'},
>> + {"new-magic", no_argument, NULL, 'M'},
>> {"help", no_argument, NULL, 'h'},
>> {"version", no_argument, NULL, 'v'},
>> {NULL, no_argument, NULL, 0x0},
>> @@ -109,6 +115,9 @@ static const char * const usage_opts_help[] = {
>> "\t\tboth - Both \"linux,phandle\" and \"phandle\" properties",
>> "\n\tEnable/disable warnings (prefix with \"no-\")",
>> "\n\tEnable/disable errors (prefix with \"no-\")",
>> + "\n\tEnable symbols/fixup support",
>> + "\n\tEnable auto-alias of labels",
>> + "\n\tUse new blog magic value",
>> "\n\tPrint this help and exit",
>> "\n\tPrint version and exit",
>> NULL,
>> @@ -153,7 +162,7 @@ static const char *guess_input_format(const char *fname, const char *fallback)
>> fclose(f);
>>
>> magic = fdt32_to_cpu(magic);
>> - if (magic == FDT_MAGIC)
>> + if (magic == FDT_MAGIC || magic == FDT_MAGIC_DTBO)
>> return "dtb";
>>
>> return guess_type_by_name(fname, fallback);
>> @@ -172,6 +181,7 @@ int main(int argc, char *argv[])
>> FILE *outf = NULL;
>> int outversion = DEFAULT_FDT_VERSION;
>> long long cmdline_boot_cpuid = -1;
>> + fdt32_t out_magic = FDT_MAGIC;
>>
>> quiet = 0;
>> reservenum = 0;
>> @@ -249,6 +259,16 @@ int main(int argc, char *argv[])
>> parse_checks_option(false, true, optarg);
>> break;
>>
>> + case '@':
>> + symbol_fixup_support = 1;
>> + break;
>> + case 'A':
>> + auto_label_aliases = 1;
>> + break;
>> + case 'M':
>> + new_magic = 1;
>> + break;
>> +
>> case 'h':
>> usage(NULL);
>> default:
>> @@ -306,6 +326,14 @@ int main(int argc, char *argv[])
>> fill_fullpaths(bi->dt, "");
>> process_checks(force, bi);
>>
>> + if (auto_label_aliases)
>> + generate_label_tree(bi->dt, "aliases", false);
>> +
>> + if (symbol_fixup_support) {
>> + generate_label_tree(bi->dt, "__symbols__", true);
>> + generate_fixups_tree(bi->dt);
>> + }
>> +
>> if (sort)
>> sort_tree(bi);
>>
>> @@ -318,12 +346,15 @@ int main(int argc, char *argv[])
>> outname, strerror(errno));
>> }
>>
>> + if (new_magic && (bi->versionflags & VF_PLUGIN))
>> + out_magic = FDT_MAGIC_DTBO;
>> +
>> if (streq(outform, "dts")) {
>> dt_to_source(outf, bi);
>> } else if (streq(outform, "dtb")) {
>> - dt_to_blob(outf, bi, outversion);
>> + dt_to_blob(outf, bi, out_magic, outversion);
>> } else if (streq(outform, "asm")) {
>> - dt_to_asm(outf, bi, outversion);
>> + dt_to_asm(outf, bi, out_magic, outversion);
>> } else if (streq(outform, "null")) {
>> /* do nothing */
>> } else {
>> diff --git a/dtc.h b/dtc.h
>> index 32009bc..889b8f8 100644
>> --- a/dtc.h
>> +++ b/dtc.h
>> @@ -55,6 +55,9 @@ extern int minsize; /* Minimum blob size */
>> extern int padsize; /* Additional padding to blob */
>> extern int alignsize; /* Additional padding to blob accroding to the alignsize */
>> extern int phandle_format; /* Use linux,phandle or phandle properties */
>> +extern int symbol_fixup_support;/* enable symbols & fixup support */
>> +extern int auto_label_aliases; /* auto generate labels -> aliases */
>> +extern int new_magic; /* use new FDT magic values for objects */
>>
>> #define PHANDLE_LEGACY 0x1
>> #define PHANDLE_EPAPR 0x2
>> @@ -195,6 +198,7 @@ struct node *build_node_delete(void);
>> struct node *name_node(struct node *node, char *name);
>> struct node *chain_node(struct node *first, struct node *list);
>> struct node *merge_nodes(struct node *old_node, struct node *new_node);
>> +void add_orphan_node(struct node *old_node, struct node *new_node, char *ref);
>>
>> void add_property(struct node *node, struct property *prop);
>> void delete_property_by_name(struct node *node, char *name);
>> @@ -202,6 +206,8 @@ void delete_property(struct property *prop);
>> void add_child(struct node *parent, struct node *child);
>> void delete_node_by_name(struct node *parent, char *name);
>> void delete_node(struct node *node);
>> +void append_to_property(struct node *node,
>> + char *name, const void *data, int len);
>>
>> const char *get_unitname(struct node *node);
>> struct property *get_property(struct node *node, const char *propname);
>> @@ -237,14 +243,22 @@ struct reserve_info *add_reserve_entry(struct reserve_info *list,
>>
>>
>> struct boot_info {
>> + unsigned int versionflags;
>> struct reserve_info *reservelist;
>> struct node *dt; /* the device tree */
>> uint32_t boot_cpuid_phys;
>> };
>>
>> -struct boot_info *build_boot_info(struct reserve_info *reservelist,
>> +/* version flags definitions */
>> +#define VF_DT_V1 0x0001 /* /dts-v1/ */
>> +#define VF_PLUGIN 0x0002 /* /plugin/ */
>> +
>> +struct boot_info *build_boot_info(unsigned int versionflags,
>> + struct reserve_info *reservelist,
>> struct node *tree, uint32_t boot_cpuid_phys);
>> void sort_tree(struct boot_info *bi);
>> +void generate_label_tree(struct node *dt, char *gen_node_name, bool allocph);
>> +void generate_fixups_tree(struct node *dt);
>>
>> /* Checks */
>>
>> @@ -253,8 +267,8 @@ void process_checks(bool force, struct boot_info *bi);
>>
>> /* Flattened trees */
>>
>> -void dt_to_blob(FILE *f, struct boot_info *bi, int version);
>> -void dt_to_asm(FILE *f, struct boot_info *bi, int version);
>> +void dt_to_blob(FILE *f, struct boot_info *bi, fdt32_t magic, int version);
>> +void dt_to_asm(FILE *f, struct boot_info *bi, fdt32_t magic, int version);
>>
>> struct boot_info *dt_from_blob(const char *fname);
>>
>> diff --git a/fdtdump.c b/fdtdump.c
>> index a9a2484..dd63ac2 100644
>> --- a/fdtdump.c
>> +++ b/fdtdump.c
>> @@ -201,7 +201,7 @@ int main(int argc, char *argv[])
>> p = memchr(p, smagic[0], endp - p - FDT_MAGIC_SIZE);
>> if (!p)
>> break;
>> - if (fdt_magic(p) == FDT_MAGIC) {
>> + if (fdt_magic(p) == FDT_MAGIC || fdt_magic(p) == FDT_MAGIC_DTBO) {
>> /* try and validate the main struct */
>> off_t this_len = endp - p;
>> fdt32_t max_version = 17;
>> diff --git a/flattree.c b/flattree.c
>> index a9d9520..57d76cf 100644
>> --- a/flattree.c
>> +++ b/flattree.c
>> @@ -335,6 +335,7 @@ static struct data flatten_reserve_list(struct reserve_info *reservelist,
>> }
>>
>> static void make_fdt_header(struct fdt_header *fdt,
>> + fdt32_t magic,
>> struct version_info *vi,
>> int reservesize, int dtsize, int strsize,
>> int boot_cpuid_phys)
>> @@ -345,7 +346,7 @@ static void make_fdt_header(struct fdt_header *fdt,
>>
>> memset(fdt, 0xff, sizeof(*fdt));
>>
>> - fdt->magic = cpu_to_fdt32(FDT_MAGIC);
>> + fdt->magic = cpu_to_fdt32(magic);
>> fdt->version = cpu_to_fdt32(vi->version);
>> fdt->last_comp_version = cpu_to_fdt32(vi->last_comp_version);
>>
>> @@ -366,7 +367,7 @@ static void make_fdt_header(struct fdt_header *fdt,
>> fdt->size_dt_struct = cpu_to_fdt32(dtsize);
>> }
>>
>> -void dt_to_blob(FILE *f, struct boot_info *bi, int version)
>> +void dt_to_blob(FILE *f, struct boot_info *bi, fdt32_t magic, int version)
>> {
>> struct version_info *vi = NULL;
>> int i;
>> @@ -390,7 +391,7 @@ void dt_to_blob(FILE *f, struct boot_info *bi, int version)
>> reservebuf = flatten_reserve_list(bi->reservelist, vi);
>>
>> /* Make header */
>> - make_fdt_header(&fdt, vi, reservebuf.len, dtbuf.len, strbuf.len,
>> + make_fdt_header(&fdt, magic, vi, reservebuf.len, dtbuf.len, strbuf.len,
>> bi->boot_cpuid_phys);
>>
>> /*
>> @@ -467,7 +468,7 @@ static void dump_stringtable_asm(FILE *f, struct data strbuf)
>> }
>> }
>>
>> -void dt_to_asm(FILE *f, struct boot_info *bi, int version)
>> +void dt_to_asm(FILE *f, struct boot_info *bi, fdt32_t magic, int version)
>> {
>> struct version_info *vi = NULL;
>> int i;
>> @@ -830,6 +831,7 @@ struct boot_info *dt_from_blob(const char *fname)
>> struct node *tree;
>> uint32_t val;
>> int flags = 0;
>> + unsigned int versionflags = VF_DT_V1;
>>
>> f = srcfile_relative_open(fname, NULL);
>>
>> @@ -845,9 +847,12 @@ struct boot_info *dt_from_blob(const char *fname)
>> }
>>
>> magic = fdt32_to_cpu(magic);
>> - if (magic != FDT_MAGIC)
>> + if (magic != FDT_MAGIC && magic != FDT_MAGIC_DTBO)
>> die("Blob has incorrect magic number\n");
>>
>> + if (magic == FDT_MAGIC_DTBO)
>> + versionflags |= VF_PLUGIN;
>> +
>> rc = fread(&totalsize, sizeof(totalsize), 1, f);
>> if (ferror(f))
>> die("Error reading DT blob size: %s\n", strerror(errno));
>> @@ -942,5 +947,5 @@ struct boot_info *dt_from_blob(const char *fname)
>>
>> fclose(f);
>>
>> - return build_boot_info(reservelist, tree, boot_cpuid_phys);
>> + return build_boot_info(versionflags, reservelist, tree, boot_cpuid_phys);
>> }
>> diff --git a/fstree.c b/fstree.c
>> index 6d1beec..54f520b 100644
>> --- a/fstree.c
>> +++ b/fstree.c
>> @@ -86,6 +86,6 @@ struct boot_info *dt_from_fs(const char *dirname)
>> tree = read_fstree(dirname);
>> tree = name_node(tree, "");
>>
>> - return build_boot_info(NULL, tree, guess_boot_cpuid(tree));
>> + return build_boot_info(VF_DT_V1, NULL, tree, guess_boot_cpuid(tree));
>> }
>>
>> diff --git a/libfdt/fdt.c b/libfdt/fdt.c
>> index 22286a1..28d422c 100644
>> --- a/libfdt/fdt.c
>> +++ b/libfdt/fdt.c
>> @@ -57,7 +57,7 @@
>>
>> int fdt_check_header(const void *fdt)
>> {
>> - if (fdt_magic(fdt) == FDT_MAGIC) {
>> + if (fdt_magic(fdt) == FDT_MAGIC || fdt_magic(fdt) == FDT_MAGIC_DTBO) {
>> /* Complete tree */
>> if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION)
>> return -FDT_ERR_BADVERSION;
>> diff --git a/libfdt/fdt.h b/libfdt/fdt.h
>> index 526aedb..493cd55 100644
>> --- a/libfdt/fdt.h
>> +++ b/libfdt/fdt.h
>> @@ -55,7 +55,7 @@
>> #ifndef __ASSEMBLY__
>>
>> struct fdt_header {
>> - fdt32_t magic; /* magic word FDT_MAGIC */
>> + fdt32_t magic; /* magic word FDT_MAGIC[|_DTBO] */
>> fdt32_t totalsize; /* total size of DT block */
>> fdt32_t off_dt_struct; /* offset to structure */
>> fdt32_t off_dt_strings; /* offset to strings */
>> @@ -93,6 +93,7 @@ struct fdt_property {
>> #endif /* !__ASSEMBLY */
>>
>> #define FDT_MAGIC 0xd00dfeed /* 4: version, 4: total size */
>> +#define FDT_MAGIC_DTBO 0xd00dfdb0 /* DTBO magic */
>> #define FDT_TAGSIZE sizeof(fdt32_t)
>>
>> #define FDT_BEGIN_NODE 0x1 /* Start node: full name */
>> diff --git a/livetree.c b/livetree.c
>> index 3dc7559..1a2f4b1 100644
>> --- a/livetree.c
>> +++ b/livetree.c
>> @@ -216,6 +216,31 @@ struct node *merge_nodes(struct node *old_node, struct node *new_node)
>> return old_node;
>> }
>>
>> +void add_orphan_node(struct node *dt, struct node *new_node, char *ref)
>> +{
>> + static unsigned int next_orphan_fragment = 0;
>> + struct node *node = xmalloc(sizeof(*node));
>
> You shouldn't use a bare malloc() for a node. Use build_node() instead.
>
OK.
>> + struct property *p;
>> + struct data d = empty_data;
>> + char *name;
>> +
>> + memset(node, 0, sizeof(*node));
>> +
>> + d = data_add_marker(d, REF_PHANDLE, ref);
>> + d = data_append_integer(d, 0xffffffff, 32);
>> +
>> + p = build_property("target", d);
>> + add_property(node, p);
>> +
>> + xasprintf(&name, "fragment@%u",
>> + next_orphan_fragment++);
>> + name_node(node, name);
>> + name_node(new_node, "__overlay__");
>> +
>> + add_child(dt, node);
>> + add_child(node, new_node);
>> +}
>> +
>> struct node *chain_node(struct node *first, struct node *list)
>> {
>> assert(first->next_sibling == NULL);
>> @@ -296,6 +321,23 @@ void delete_node(struct node *node)
>> delete_labels(&node->labels);
>> }
>>
>> +void append_to_property(struct node *node,
>> + char *name, const void *data, int len)
>> +{
>> + struct data d;
>> + struct property *p;
>> +
>> + p = get_property(node, name);
>> + if (p) {
>> + d = data_append_data(p->val, data, len);
>> + p->val = d;
>> + } else {
>> + d = data_append_data(empty_data, data, len);
>> + p = build_property(name, d);
>> + add_property(node, p);
>> + }
>> +}
>> +
>> struct reserve_info *build_reserve_entry(uint64_t address, uint64_t size)
>> {
>> struct reserve_info *new = xmalloc(sizeof(*new));
>> @@ -335,12 +377,14 @@ struct reserve_info *add_reserve_entry(struct reserve_info *list,
>> return list;
>> }
>>
>> -struct boot_info *build_boot_info(struct reserve_info *reservelist,
>> +struct boot_info *build_boot_info(unsigned int versionflags,
>> + struct reserve_info *reservelist,
>> struct node *tree, uint32_t boot_cpuid_phys)
>> {
>> struct boot_info *bi;
>>
>> bi = xmalloc(sizeof(*bi));
>> + bi->versionflags = versionflags;
>> bi->reservelist = reservelist;
>> bi->dt = tree;
>> bi->boot_cpuid_phys = boot_cpuid_phys;
>> @@ -709,3 +753,182 @@ void sort_tree(struct boot_info *bi)
>> sort_reserve_entries(bi);
>> sort_node(bi->dt);
>> }
>> +
>> +/* utility helper to avoid code duplication */
>> +static struct node *build_and_name_child_node(struct node *parent, char *name)
>> +{
>> + struct node *node;
>> +
>> + node = build_node(NULL, NULL);
>> + name_node(node, xstrdup(name));
>> + add_child(parent, node);
>> +
>> + return node;
>> +}
>> +
>> +static void generate_label_tree_internal(struct node *dt, struct node *node,
>> + struct node *an, bool allocph)
>> +{
>> + struct node *c;
>> + struct property *p;
>> + struct label *l;
>> +
>> + /* if if there are labels */
>> + if (node->labels) {
>> + /* now add the label in the node */
>> + for_each_label(node->labels, l) {
>> + /* check whether the label already exists */
>> + p = get_property(an, l->label);
>> + if (p) {
>> + fprintf(stderr, "WARNING: label %s already"
>> + " exists in /%s", l->label,
>> + an->name);
>> + continue;
>> + }
>> +
>> + /* insert it */
>> + p = build_property(l->label,
>> + data_copy_escape_string(node->fullpath,
>> + strlen(node->fullpath)));
>
> Um.. what? The node path should absolutely not be an escape string.
> It shouldn't contain escapes to begin with, and if it does, we
> absolutely shouldn't be turning them into special characters here.
>
OK, trivial enough to do. I tried to play it safe here but this is an overkill.
>> + add_property(an, p);
>> + }
>> +
>> + /* force allocation of a phandle for this node */
>> + if (allocph)
>> + (void)get_node_phandle(dt, node);
>> + }
>> +
>> + for_each_child(node, c)
>> + generate_label_tree_internal(dt, c, an, allocph);
>> +}
>> +
>> +void generate_label_tree(struct node *dt, char *gen_node_name, bool allocph)
>> +{
>> + struct node *an;
>> +
>> + for_each_child(dt, an)
>> + if (streq(gen_node_name, an->name))
>> + break;
>> +
>> + if (!an)
>> + an = build_and_name_child_node(dt, gen_node_name);
>> + if (!an)
>> + die("Could not build label node /%s\n", gen_node_name);
>> +
>> + generate_label_tree_internal(dt, dt, an, allocph);
>> +}
>> +
>> +static char *fixups_name = "__fixups__";
>> +static char *local_fixups_name = "__local_fixups__";
>
> I'd actually prefer #defines for these, and all-caps names, so it's
> more obvious when they're used that these are global constants.
>
OK.
>> +
>> +static void add_fixup_entry(struct node *dt, struct node *node,
>> + struct property *prop, struct marker *m)
>> +{
>> + struct node *fn; /* fixup node */
>> + char *entry;
>> +
>> + /* m->ref can only be a REF_PHANDLE, but check anyway */
>> + assert(m->type == REF_PHANDLE);
>> +
>> + /* fn is the node we're putting entries in */
>> + fn = get_subnode(dt, fixups_name);
>> + assert(fn != NULL);
>> +
>> + /* there shouldn't be any ':' in the arguments */
>> + if (strchr(node->fullpath, ':') || strchr(prop->name, ':'))
>> + die("arguments should not contain ':'\n");
>> +
>> + xasprintf(&entry, "%s:%s:%u",
>> + node->fullpath, prop->name, m->offset);
>> + append_to_property(fn, m->ref, entry, strlen(entry) + 1);
>> +}
>> +
>> +static void add_local_fixup_entry(struct node *dt, struct node *node,
>> + struct property *prop, struct marker *m,
>> + struct node *refnode)
>> +{
>> + struct node *lfn, *wn, *nwn; /* local fixup node, walk node, new */
>> + uint32_t value_32;
>> + char *s, *e, *comp;
>> + int len;
>> +
>> + /* fn is the node we're putting entries in */
>> + lfn = get_subnode(dt, local_fixups_name);
>> + assert(lfn != NULL);
>> +
>> + /* walk the path components creating nodes if they don't exist */
>> + comp = xmalloc(strlen(node->fullpath) + 1);
>> + /* start skipping the first / */
>> + s = node->fullpath + 1;
>> + wn = lfn;
>> + while (*s) {
>> + /* retrieve path component */
>> + e = strchr(s, '/');
>> + if (e == NULL)
>> + e = s + strlen(s);
>> + len = e - s;
>> + memcpy(comp, s, len);
>> + comp[len] = '\0';
>> +
>> + /* if no node exists, create it */
>> + nwn = get_subnode(wn, comp);
>> + if (!nwn)
>> + nwn = build_and_name_child_node(wn, comp);
>> + wn = nwn;
>> +
>> + /* last path component */
>> + if (!*e)
>> + break;
>> +
>> + /* next path component */
>> + s = e + 1;
>> + }
>> + free(comp);
>> +
>> + value_32 = cpu_to_fdt32(m->offset);
>> + append_to_property(wn, prop->name, &value_32, sizeof(value_32));
>> +}
>> +
>> +static void generate_fixups_tree_internal(struct node *dt, struct node *node)
>> +{
>> + struct node *c;
>> + struct property *prop;
>> + struct marker *m;
>> + struct node *refnode;
>> +
>> + for_each_property(node, prop) {
>> + m = prop->val.markers;
>> + for_each_marker_of_type(m, REF_PHANDLE) {
>> + refnode = get_node_by_ref(dt, m->ref);
>> + if (!refnode)
>> + add_fixup_entry(dt, node, prop, m);
>> + else
>> + add_local_fixup_entry(dt, node, prop, m,
>> + refnode);
>> + }
>> + }
>> +
>> + for_each_child(node, c)
>> + generate_fixups_tree_internal(dt, c);
>> +}
>> +
>> +void generate_fixups_tree(struct node *dt)
>> +{
>> + struct node *an;
>> +
>> + for_each_child(dt, an)
>> + if (streq(fixups_name, an->name))
>> + break;
>> +
>> + if (!an)
>> + build_and_name_child_node(dt, fixups_name);
>> +
>> + for_each_child(dt, an)
>> + if (streq(local_fixups_name, an->name))
>> + break;
>> +
>> + if (!an)
>> + build_and_name_child_node(dt, local_fixups_name);
>> +
>> + generate_fixups_tree_internal(dt, dt);
>> +}
>> diff --git a/tests/mangle-layout.c b/tests/mangle-layout.c
>> index a76e51e..d29ebc6 100644
>> --- a/tests/mangle-layout.c
>> +++ b/tests/mangle-layout.c
>> @@ -42,7 +42,8 @@ static void expand_buf(struct bufstate *buf, int newsize)
>> buf->size = newsize;
>> }
>>
>> -static void new_header(struct bufstate *buf, int version, const void *fdt)
>> +static void new_header(struct bufstate *buf, fdt32_t magic, int version,
>> + const void *fdt)
>> {
>> int hdrsize;
>>
>> @@ -56,7 +57,7 @@ static void new_header(struct bufstate *buf, int version, const void *fdt)
>> expand_buf(buf, hdrsize);
>> memset(buf->buf, 0, hdrsize);
>>
>> - fdt_set_magic(buf->buf, FDT_MAGIC);
>> + fdt_set_magic(buf->buf, magic);
>> fdt_set_version(buf->buf, version);
>> fdt_set_last_comp_version(buf->buf, 16);
>> fdt_set_boot_cpuid_phys(buf->buf, fdt_boot_cpuid_phys(fdt));
>> @@ -145,7 +146,7 @@ int main(int argc, char *argv[])
>> if (fdt_version(fdt) < 17)
>> CONFIG("Input tree must be v17");
>>
>> - new_header(&buf, version, fdt);
>> + new_header(&buf, FDT_MAGIC, version, fdt);
>>
>> while (*blockorder) {
>> add_block(&buf, version, *blockorder, fdt);
>> diff --git a/treesource.c b/treesource.c
>> index a55d1d1..75e920d 100644
>> --- a/treesource.c
>> +++ b/treesource.c
>> @@ -267,7 +267,12 @@ void dt_to_source(FILE *f, struct boot_info *bi)
>> {
>> struct reserve_info *re;
>>
>> - fprintf(f, "/dts-v1/;\n\n");
>> + fprintf(f, "/dts-v1/");
>> +
>> + if (bi->versionflags & VF_PLUGIN)
>> + fprintf(f, " /plugin/");
>> +
>> + fprintf(f, ";\n\n");
>
> I'm not sure this really makes sense. The /plugin/ tag triggers the
> fixup construction and encoding of overlay fragments. But in an
> incoming dtb, that processing has already been done once, doing it
> again would not make sense. So I think the output should not have the
> /plugin/ tag, even if the input did.
>
> Unless, of course, you parsed the input into an explicit list of
> overlays, then output it here again as a list of overlays, not the
> encoded fragments. i.e. if this was the original tree:
>
> /dts-v1/ /plugin/;
>
> &somwhere {
> name = "value";
> };
>
> then legitimately the output of -I dts -O dts could be either:
>
> /dts-v1/ /plugin/;
>
> &somwhere {
> name = "value";
> };
>
> OR
>
> /dts-v1/;
>
> / {
> fragment@0 {
> target = <0xffffffff>;
> __overlay__{
> name = "value";
> };
> };
> __fixups__ {
> somewhere = "/fragment@0:target:0";
> };
> };
>
> But it doesn't make sense to combine the two: the second structure
> with the "/plugin/" tag.
>
> Another advantage of moving the overlay application out of the parser
> is you can sanely produce either output, both of which could be useful
> in the right circumstances. You can potentially even produce the
> first output (or something close) from dtb input, with correct parsing
> of the overlay structure on dtb input.
>
Yes, this makes sense. For now I’ll remove the plugin tag, but if the blob
was compiled with -@ you could conceivably reverse back to a form that contains
labels and phandle references correctly.
But this is quite complicated to undertake in this patch series.
To re-iterate though there is no overlay application here :)
> --
> David Gibson | I'll have my music baroque, and my code
> david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
> | _way_ _around_!
> http://www.ozlabs.org/~dgibson
Regards
— Pantelis
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox