On Thu, Nov 10, 2022 at 10:59 AM Simon Glass <s...@chromium.org> wrote:
>
> U-Boot has some particular challenges with device tree and devices:
>
> - U-Boot has multiple build phases, such as a Secondary Program Loader
>   (SPL) phase which typically runs in a pre-SDRAM environment where code
>   and data space are limited. In particular, there may not be enough
>   space for the full device tree blob. U-Boot uses various automated
>   techniques to reduce the size from perhaps 40KB to 3KB. It is not
>   always possible to handle these tags entirely at build time, since
>   U-Boot proper must have the full device tree, even though we do not
>   want it to process all nodes until after relocation.
> - Some U-Boot phases needs to run before the clocks are properly set up,
>   where the CPU may be running very slowly. Therefore it is important to
>   bind only those devices which are actually needed in that phase
> - U-Boot uses lazy initialisation for its devices, with 'bind' and
>   'probe' being separate steps. Even if a device is bound, it is not
>   actually probed until it is used. This is necessary to keep the boot
>   time reasonable, e.g. to under a second
>
> The phases of U-Boot in order are: TPL, VPL, SPL, U-Boot (first
> pre-relocation, then post-relocation). ALl but the last two are optional.
>
> For the above reasons, U-Boot only includes the full device tree in the
> final 'U-Boot proper' build. Even then, before relocation U-Boot only
> processes nodes which are marked as being needed.
>
> For this to work, U-Boot's driver model[1] provides a way to mark device
> tree nodes as applicable for a particular phase. This works by adding a
> tag to the node, e.g.:
>
>    cru: clock-controller@ff760000 {
>       phase-all;
>       compatible = "rockchip,rk3399-cru";
>       reg = <0x0 0xff760000 0x0 0x1000>;
>       rockchip,grf = <&grf>;
>       #clock-cells = <1>;
>       #reset-cells = <1>;
>       ...
>    };
>
> Here the "phase-all" tag indicates that the node must be present in all
> phases, since the clock driver is required.
>
> There has been discussion over the years about whether this could be done
> in a property instead, e.g.
>
>    options {
>       phase-all = <&cru> <&gpio_a> ...;
>       ...
>    };
>
> Some problems with this:
>
> - we need to be able to merge several such tags from different .dtsi files
>   since many boards have their own specific requirements
> - it is hard to find and cross-reference the affected nodes
> - it is more error-prone
> - it requires significant tool rework in U-Boot, including fdtgrep and
>   the build system
> - is harder (slower, more code) to process since it involves scanning
>   another node/property to find out what to do with a particular node
> - we don't want to add phandle arguments to the above since we are
>   referring, e.g., to the clock device as a whole, not a paricular clock
> - the of-platdata feature[2], which converts device tree to C for even
>   more constrained environments, would need to become aware of the
>   /options node
>
> There is also the question about whether this needs to be U-Boot-specific,
> or whether the tags could be generic. From what I can tell, U-Boot is the
> only bootloader which seriously attempts to use a runtime device tree in
> all cases. For this version, an attempt is made to name the phases in a
> generic manner.
>
> It should also be noted that the approach provided here has stood the test
> of time, used in U-Boot for 8 years so far.

I guess if no one else has any input at all on alternatives to a
boolean per phase, then we should just stick with that as that's the
easiest.

However, I do still think parent nodes need to be implicitly included
rather than explicitly. Otherwise, the result can be invalid DTs
(primarily with 'reg' and addressing)


> So add the schema for this. This will allow a major class of schema
> exceptions to be dropped from the U-Boot source tree.
>
> This being sent to the mailing list since it might attract more review.
> A PR will be sent when this has had some review. That is why the file
> path is set up for https://github.com/devicetree-org/dt-schema rather
> than the Linux kernel.
>
> [1] https://u-boot.readthedocs.io/en/latest/develop/driver-model/index.html
> [2] https://u-boot.readthedocs.io/en/latest/develop/driver-model/of-plat.html
>
> Signed-off-by: Simon Glass <s...@chromium.org>
> ---
>
> Changes in v5:
> - Fix instructions to run test
> - Update binding title
> - Use 'phase-' instead of 'phase,'
>
> Changes in v4:
> - Drop some unnecessary context from the commit message
> - Explain why parent nodes do not automatically inherit their children's
>   tags
> - Rename the tags to use a phase,xxx format, explaining each one
>
> Changes in v3:
> - Fix an incorrect schema path in $id
>
> Changes in v2:
> - Expand docs to include a description of each tag
> - Fix some typos and unclear wording
>
>  dtschema/lib.py             |  5 +++
>  dtschema/schemas/phase.yaml | 74 +++++++++++++++++++++++++++++++++++++
>  test/phases.dts             | 23 ++++++++++++
>  3 files changed, 102 insertions(+)
>  create mode 100644 dtschema/schemas/phase.yaml
>  create mode 100644 test/phases.dts
>
> diff --git a/dtschema/lib.py b/dtschema/lib.py
> index 1bce070..d65a0fc 100644
> --- a/dtschema/lib.py
> +++ b/dtschema/lib.py
> @@ -514,6 +514,11 @@ def fixup_node_props(schema):
>      schema['properties'].setdefault('status', True)
>      schema['properties'].setdefault('secure-status', True)
>      schema['properties'].setdefault('$nodename', True)
> +    schema['properties'].setdefault('phase-pre-sram', True)
> +    schema['properties'].setdefault('phase-verify', True)
> +    schema['properties'].setdefault('phase-pre-ram', True)
> +    schema['properties'].setdefault('phase-some-ram', True)
> +    schema['properties'].setdefault('phase-all', True)
>
>      keys = list()
>      if 'properties' in schema:
> diff --git a/dtschema/schemas/phase.yaml b/dtschema/schemas/phase.yaml
> new file mode 100644
> index 0000000..a6f090d
> --- /dev/null
> +++ b/dtschema/schemas/phase.yaml
> @@ -0,0 +1,74 @@
> +# SPDX-License-Identifier: BSD-2-Clause
> +# Copyright 2022 Google LLC
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/phase.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Boot-phase-specific device nodes
> +
> +maintainers:
> +  - Simon Glass <s...@chromium.org>
> +
> +patternProperties:
> +  "^phase-(pre-sram,verify,pre-ram,some-ram,all)$":

s/,/|/

To bikeshed the name again, I find 'phase' a bit vague. Perhaps
'boot-phase-'? Or 'boot-ph-'?

> +    type: boolean
> +    description: |
> +      Some programs run in memory-constrained environments yet want to make 
> use
> +      of device tree.
> +
> +      The full device tree is often quite large (e.g. 40KB) and cannot fit 
> into

What's 'large' depends on the platform and time, so maybe better to
not give sizes.

...quite large relative to the available memory of a boot phase...

> +      every phase of the boot process. Even when memory is not a problem, 
> some
> +      phases may wish to limit which device nodes are present, so as to 
> reduce
> +      execution time.
> +
> +      This binding supports adding tags to device tree nodes to allow them 
> to be
> +      marked according to the phases where they should be included.
> +
> +      Without any tags, nodes are included only in the final phase, where all
> +      memory is available. Any untagged nodes are dropped from previous 
> phases
> +      and are ignored before the final phase is reached.
> +
> +      The build process produces a separate executable for each phase. It can
> +      use fdtgrep to drop any nodes which are not needed for a particular 
> build.
> +      For example, the pre-sram build will drop any nodes which are not 
> marked
> +      with phase-pre-sram or phase-all tags.
> +
> +      The available tags are as follows, in order of phase execution:
> +
> +        phase-pre-sram:
> +          Enable this node when SRAM is not available. This phase must set up
> +          some SRAM or cache-as-RAM so it can obtain data/BSS space to use
> +          during execution.
> +
> +        phase-verify:
> +          Enable this node in the verification step, which decides which of 
> the
> +          available images should be run next.
> +
> +        phase-pre-ram:
> +          Enable this node in the phase that sets up SDRAM.
> +
> +        phase-some-ram:
> +          Enable this node in the phase that is run after SDRAM is working 
> but
> +          before all of it is available. Some RAM is available but it is 
> limited
> +          (e.g. it may be split into two pieces by the location of the 
> running
> +          program) because the program code is not yet relocated out of the 
> way.
> +
> +        phase-all:
> +          Include this node in all phases (for U-Boot see enum u_boot_phase)

Since you need a section for each tag, do away with the pattern and
list them under 'properties' as a proper schema. And then move the
overview to top-level 'description'.

> +
> +      Note that phase builds may drop the tags, since they have served their
> +      purpose by that point. So when looking at phase-specific device tree 
> files
> +      you may not see these tags.
> +
> +      Multiple tags can be used in the same node.
> +
> +      One complication with fdtgrep is that tags apply only to the node they 
> are
> +      added to, not to any parents. This means that you often need to add the
> +      same tag to parent nodes so that any properties needed by the parent
> +      driver are included. Without that, the parent node may have no 
> properties,
> +      or may not be bound before relocation (meaning that its child will not 
> be
> +      bound either). This is for implementation reasons and it may be 
> possible
> +      to address this in the future.

I think we should state the opposite here. u-boot can internally
deviate if needed at least until these properties start showing up in
'Linux DTs'.

> +
> +additionalProperties: true
> diff --git a/test/phases.dts b/test/phases.dts
> new file mode 100644
> index 0000000..d36cb82
> --- /dev/null
> +++ b/test/phases.dts
> @@ -0,0 +1,23 @@
> +// SPDX-License-Identifier: BSD-2-Clause
> +// Copyright 2022 Google LLC
> +
> +// An attempt to provide a device tree to validate the phase properties
> +
> +// dt-mk-schema -j test/schemas/ > processed-schema.json
> +// dtc -O dtb -o test.dtb test/phases.dts && tools/dt-validate -s 
> processed-schema.json test.dtb
> +
> +
> +/dts-v1/;
> +
> +/ {
> +       model = "none";
> +       compatible = "foo";
> +
> +       #address-cells = <1>;
> +       #size-cells = <1>;
> +
> +       some-device {
> +               compatible = "vendor,soc1-ip";
> +               phase-pre-sram;
> +       };
> +};
> --
> 2.38.1.431.g37b22c650d-goog
>

Reply via email to