diff --git a/.cirrus.yml b/.cirrus.yml new file mode 100644 index 0000000..825aeb7 --- /dev/null +++ b/.cirrus.yml @@ -0,0 +1,39 @@ +# FreeBSD build with multiple versions +freebsd_versions_task: + name: FreeBSD $FREEBSD_VERSION make build + freebsd_instance: + image_family: $FREEBSD_IMAGE + matrix: + - env: + FREEBSD_VERSION: "13.5" + FREEBSD_IMAGE: freebsd-13-5 + - env: + FREEBSD_VERSION: "14.3" + FREEBSD_IMAGE: freebsd-14-3 + install_script: + - pkg install -y git gmake flex bison python3 py312-setuptools swig libyaml pkgconf + build_script: + - gmake + check_script: + - gmake check + +# FreeBSD meson builds with multiple versions +freebsd_meson_versions_task: + name: FreeBSD $FREEBSD_VERSION meson build + freebsd_instance: + image_family: $FREEBSD_IMAGE + matrix: + - env: + FREEBSD_VERSION: "13.5" + FREEBSD_IMAGE: freebsd-13-5 + - env: + FREEBSD_VERSION: "14.3" + FREEBSD_IMAGE: freebsd-14-3 + install_script: + - pkg install -y git meson ninja flex bison python3 py312-setuptools swig libyaml pkgconf + setup_script: + - meson setup -D python=enabled -D yaml=enabled build + build_script: + - meson compile -C build + test_script: + - if ! meson test -C build; then cat build/meson-logs/testlog.txt; false; fi diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..e5d1518 --- /dev/null +++ b/.clang-format @@ -0,0 +1,135 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# clang-format configuration file. Intended for clang-format >= 11. +# +# For more information, see: +# +# Documentation/dev-tools/clang-format.rst +# https://clang.llvm.org/docs/ClangFormat.html +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html +# +--- +AccessModifierOffset: -4 +AlignAfterOpenBracket: Align +AlignConsecutiveAssignments: false +AlignConsecutiveDeclarations: false +AlignEscapedNewlines: Left +AlignOperands: true +AlignTrailingComments: false +AllowAllParametersOfDeclarationOnNextLine: false +AllowShortBlocksOnASingleLine: false +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: None +AllowShortIfStatementsOnASingleLine: false +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: false +BinPackArguments: true +BinPackParameters: true +BraceWrapping: + AfterClass: false + AfterControlStatement: false + AfterEnum: false + AfterFunction: true + AfterNamespace: true + AfterObjCDeclaration: false + AfterStruct: false + AfterUnion: false + AfterExternBlock: false + BeforeCatch: false + BeforeElse: false + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true +BreakBeforeBinaryOperators: None +BreakBeforeBraces: Custom +BreakBeforeInheritanceComma: false +BreakBeforeTernaryOperators: false +BreakConstructorInitializersBeforeComma: false +BreakConstructorInitializers: BeforeComma +BreakAfterJavaFieldAnnotations: false +BreakStringLiterals: false +ColumnLimit: 80 +CommentPragmas: '^ IWYU pragma:' +CompactNamespaces: false +ConstructorInitializerAllOnOneLineOrOnePerLine: false +ConstructorInitializerIndentWidth: 8 +ContinuationIndentWidth: 8 +Cpp11BracedListStyle: false +DerivePointerAlignment: false +DisableFormat: false +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: false + +# Taken from: +# git grep -h '^#define [^[:space:]]*for_each[^[:space:]]*(' \ +# | sed "s,^#define \([^[:space:]]*for_each[^[:space:]]*\)(.*$, - '\1'," \ +# | LC_ALL=C sort -u +ForEachMacros: + - 'fdt_for_each_property_offset' + - 'fdt_for_each_subnode' + - 'for_each_child' + - 'for_each_child_withdel' + - 'for_each_label' + - 'for_each_label_withdel' + - 'for_each_marker' + - 'for_each_marker_of_type' + - 'for_each_property' + - 'for_each_property_withdel' + +IncludeBlocks: Preserve +IncludeCategories: + - Regex: '.*' + Priority: 1 +IncludeIsMainRegex: '(Test)?$' +IndentCaseLabels: false +IndentGotoLabels: false +IndentPPDirectives: None +IndentWidth: 8 +IndentWrappedFunctionNames: false +JavaScriptQuotes: Leave +JavaScriptWrapImports: true +KeepEmptyLinesAtTheStartOfBlocks: false +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +ObjCBinPackProtocolList: Auto +ObjCBlockIndentWidth: 8 +ObjCSpaceAfterProperty: true +ObjCSpaceBeforeProtocolList: true + +# Taken from git's rules +PenaltyBreakAssignment: 10 +PenaltyBreakBeforeFirstCallParameter: 30 +PenaltyBreakComment: 10 +PenaltyBreakFirstLessLess: 0 +PenaltyBreakString: 10 +PenaltyExcessCharacter: 100 +PenaltyReturnTypeOnItsOwnLine: 60 + +PointerAlignment: Right +ReflowComments: false +SortIncludes: false +SortUsingDeclarations: false +SpaceAfterCStyleCast: false +SpaceAfterTemplateKeyword: true +SpaceBeforeAssignmentOperators: true +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeParens: ControlStatementsExceptForEachMacros +SpaceBeforeRangeBasedForLoopColon: true +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: false +SpacesInContainerLiterals: false +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +Standard: Cpp03 +TabWidth: 8 +UseTab: Always +... diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..4ba0212 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,33 @@ +# EditorConfig is a file format and collection of text editor plugins +# for maintaining consistent coding styles between different editors +# and IDEs. Most popular editors support this either natively or via +# plugin. +# +# Check https://editorconfig.org for details. + +root = true + +[*] +end_of_line = lf +insert_final_newline = true +charset = utf-8 +indent_style = space + +[Makefile*] +indent_style = tab +indent_size = 8 +file_type_emacs = makefile + +[*.[ch]] +indent_style = tab +indent_size = 8 + +[*.py] +indent_size = 4 + +[meson.build] +indent_style = space +indent_size = 2 + +[*.lds] +indent_style = tab diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..b6e0a9c --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,114 @@ +--- +name: Build test +'on': + push: + branches: + - main + - ci + pull_request: + branches: + - main + +# ensure that the workflow is only triggered once per PR, subsequent pushes to the PR will cancel +# and restart the workflow. See https://docs.github.com/en/actions/using-jobs/using-concurrency +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +jobs: + build-make: + runs-on: ubuntu-latest + + strategy: + fail-fast: false + matrix: + os: [ "alpine", "archlinux", "fedora", "ubuntu" ] + + container: + image: ${{ matrix.os }} + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install Dependencies + run: | + ./scripts/install-deps.sh + + - name: Build + run: | + make + + - name: Run check + run: | + make check + + build-meson: + runs-on: ubuntu-latest + + strategy: + fail-fast: false + matrix: + os: [ "alpine", "archlinux", "fedora", "ubuntu" ] + + container: + image: ${{ matrix.os }} + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install Dependencies + run: | + ./scripts/install-deps.sh + + - name: Setup + run: meson setup -D python=enabled -D yaml=enabled build + + - name: Build + run: meson compile -C build + + - name: Run check + run: if ! meson test -C build; then cat build/meson-logs/testlog.txt; false; fi + + build-windows: + runs-on: windows-latest + strategy: + fail-fast: false + matrix: + include: + - { sys: mingw32 } + - { sys: mingw64 } + - { sys: ucrt64 } + - { sys: clang64 } + name: ${{ matrix.sys }} + defaults: + run: + shell: msys2 {0} + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Setup MSYS2 + uses: msys2/setup-msys2@v2 + with: + msystem: ${{matrix.sys}} + update: true + install: >- + git + flex + bison + pacboy: >- + toolchain:p + meson:p + ninja:p + libyaml:p + swig:p + python-setuptools-scm:p + + - name: '🚧 Build' + run: | + meson setup -Dtools=true -Dtests=false build + meson compile -C build diff --git a/.gitignore b/.gitignore index 85ccca2..8e1e0c0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,30 @@ *.o *.d +*.a +*.patch +*.so +*.so.* +*~ +*.bak *.tab.[ch] lex.yy.c -dtc -ftdump +*.lex.c +.*.swp +/dtc +/fdtdump +/convert-dtsv0 +/version_gen.h +/fdtget +/fdtput +/fdtoverlay +/patches +/.pc + +# cscope files +cscope.* +ncscope.* + +.eggs/ +build/ +dist/ +*.egg-info/ diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000..f5b1fb1 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,65 @@ +stages: + - build + +variables: + GIT_DEPTH: 1 + +workflow: + rules: + - if: $CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == "main" + - if: $CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == "ci" + - if: $CI_PIPELINE_SOURCE == "merge_request_event" + +# Linux builds with make +.build-make-template: &build-make-template + stage: build + before_script: + - ./scripts/install-deps.sh + script: + - make + - make check + interruptible: true + +build-make-alpine: + <<: *build-make-template + image: alpine:latest + +build-make-archlinux: + <<: *build-make-template + image: archlinux:latest + +build-make-fedora: + <<: *build-make-template + image: fedora:latest + +build-make-ubuntu: + <<: *build-make-template + image: ubuntu:latest + +# Linux builds with meson +.build-meson-template: &build-meson-template + stage: build + before_script: + - ./scripts/install-deps.sh + script: + - meson setup -D python=enabled -D yaml=enabled build + - meson compile -C build + - if ! meson test -C build; then cat build/meson-logs/testlog.txt; false; fi + interruptible: true + +build-meson-alpine: + <<: *build-meson-template + image: alpine:latest + +build-meson-archlinux: + <<: *build-meson-template + image: archlinux:latest + +build-meson-fedora: + <<: *build-meson-template + image: fedora:latest + +build-meson-ubuntu: + <<: *build-meson-template + image: ubuntu:latest + diff --git a/BSD-2-Clause b/BSD-2-Clause new file mode 100644 index 0000000..da366e2 --- /dev/null +++ b/BSD-2-Clause @@ -0,0 +1,32 @@ +Valid-License-Identifier: BSD-2-Clause +SPDX-URL: https://spdx.org/licenses/BSD-2-Clause.html +Usage-Guide: + To use the BSD 2-clause "Simplified" License put the following SPDX + tag/value pair into a comment according to the placement guidelines in + the licensing rules documentation: + SPDX-License-Identifier: BSD-2-Clause +License-Text: + +Copyright (c) . All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..48c8efd --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,79 @@ +# Contributing to dtc or libfdt + +There are two ways to submit changes for dtc or libfdt: + +* Post patches directly to the + [devicetree-compiler](mailto:devicetree-compiler@vger.kernel.org) + mailing list. +* Submit pull requests via + [Github](https://github.com/dgibson/dtc/pulls) + +## Adding a new function to libfdt.h + +The shared library uses `libfdt/version.lds` to list the exported +functions, so add your new function there. Check that your function +works with pylibfdt. If it cannot be supported, put the declaration in +`libfdt.h` behind `#ifndef SWIG` so that swig ignores it. + +## Tests + +Test files are kept in the `tests/` directory. Use `make check` to build and run +all tests. + +If you want to adjust a test file, be aware that `tree_tree1.dts` is compiled +and checked against a binary tree from assembler macros in `trees.S`. So +if you change that file you must change `tree.S` also. + +## Developer's Certificate of Origin + +Like many other projects, dtc and libfdt have adopted the "Developer's +Certificate of Origin" (Signed-off-by) process created by the Linux +kernel community to improve tracking of who did what. Here's how it +works (this is a very slight modification of the description from +`Documentation/process/submitting-patches.rst` in the kernel tree): + +The sign-off is a simple line at the end of the explanation for the +patch, which certifies that you wrote it or otherwise have the right +to pass it on as an open-source patch. The rules are pretty simple: +if you can certify the below: + + Developer's Certificate of Origin 1.1 + + By making a contribution to this project, I certify that: + + (a) The contribution was created in whole or in part by me and I + have the right to submit it under the open source license + indicated in the file; or + + (b) The contribution is based upon previous work that, to the best + of my knowledge, is covered under an appropriate open source + license and I have the right under that license to submit that + work with modifications, whether created in whole or in part + by me, under the same open source license (unless I am + permitted to submit under a different license), as indicated + in the file; or + + (c) The contribution was provided directly to me by some other + person who certified (a), (b) or (c) and I have not modified + it. + + (d) I understand and agree that this project and the contribution + are public and that a record of the contribution (including all + personal information I submit with it, including my sign-off) is + maintained indefinitely and may be redistributed consistent with + this project or the open source license(s) involved. + +then you just add a line saying:: + + Signed-off-by: Random J Developer + +using your real name (sorry, no pseudonyms or anonymous +contributions.) This will be done for you automatically if you use +`git commit -s`. Reverts should also include "Signed-off-by". `git +revert -s` does that for you. + +Any further SoBs (Signed-off-by:'s) following the author's SoB are +from people handling and transporting the patch, but were not involved +in its development. SoB chains should reflect the **real** route a +patch took as it was propagated to the maintainers, with the first SoB +entry signalling primary authorship of a single author. diff --git a/Documentation/booting-without-of.txt b/Documentation/booting-without-of.txt deleted file mode 100644 index 60d5b7a..0000000 --- a/Documentation/booting-without-of.txt +++ /dev/null @@ -1,1420 +0,0 @@ - Booting the Linux/ppc kernel without Open Firmware - -------------------------------------------------- - - -(c) 2005 Benjamin Herrenschmidt , - IBM Corp. -(c) 2005 Becky Bruce , - Freescale Semiconductor, FSL SOC and 32-bit additions - - May 18, 2005: Rev 0.1 - Initial draft, no chapter III yet. - - May 19, 2005: Rev 0.2 - Add chapter III and bits & pieces here or - clarifies the fact that a lot of things are - optional, the kernel only requires a very - small device tree, though it is encouraged - to provide an as complete one as possible. - - May 24, 2005: Rev 0.3 - Precise that DT block has to be in RAM - - Misc fixes - - Define version 3 and new format version 16 - for the DT block (version 16 needs kernel - patches, will be fwd separately). - String block now has a size, and full path - is replaced by unit name for more - compactness. - linux,phandle is made optional, only nodes - that are referenced by other nodes need it. - "name" property is now automatically - deduced from the unit name - - June 1, 2005: Rev 0.4 - Correct confusion between OF_DT_END and - OF_DT_END_NODE in structure definition. - - Change version 16 format to always align - property data to 4 bytes. Since tokens are - already aligned, that means no specific - required alignement between property size - and property data. The old style variable - alignment would make it impossible to do - "simple" insertion of properties using - memove (thanks Milton for - noticing). Updated kernel patch as well - - Correct a few more alignement constraints - - Add a chapter about the device-tree - compiler and the textural representation of - the tree that can be "compiled" by dtc. - - - November 21, 2005: Rev 0.5 - - Additions/generalizations for 32-bit - - Changed to reflect the new arch/powerpc - structure - - Added chapter VI - - - ToDo: - - Add some definitions of interrupt tree (simple/complex) - - Add some definitions for pci host bridges - - Add some common address format examples - - Add definitions for standard properties and "compatible" - names for cells that are not already defined by the existing - OF spec. - - Compare FSL SOC use of PCI to standard and make sure no new - node definition required. - - Add more information about node definitions for SOC devices - that currently have no standard, like the FSL CPM. - - -I - Introduction -================ - -During the recent development of the Linux/ppc64 kernel, and more -specifically, the addition of new platform types outside of the old -IBM pSeries/iSeries pair, it was decided to enforce some strict rules -regarding the kernel entry and bootloader <-> kernel interfaces, in -order to avoid the degeneration that had become the ppc32 kernel entry -point and the way a new platform should be added to the kernel. The -legacy iSeries platform breaks those rules as it predates this scheme, -but no new board support will be accepted in the main tree that -doesn't follows them properly. In addition, since the advent of the -arch/powerpc merged architecture for ppc32 and ppc64, new 32-bit -platforms and 32-bit platforms which move into arch/powerpc will be -required to use these rules as well. - -The main requirement that will be defined in more detail below is -the presence of a device-tree whose format is defined after Open -Firmware specification. However, in order to make life easier -to embedded board vendors, the kernel doesn't require the device-tree -to represent every device in the system and only requires some nodes -and properties to be present. This will be described in detail in -section III, but, for example, the kernel does not require you to -create a node for every PCI device in the system. It is a requirement -to have a node for PCI host bridges in order to provide interrupt -routing informations and memory/IO ranges, among others. It is also -recommended to define nodes for on chip devices and other busses that -don't specifically fit in an existing OF specification. This creates a -great flexibility in the way the kernel can then probe those and match -drivers to device, without having to hard code all sorts of tables. It -also makes it more flexible for board vendors to do minor hardware -upgrades without significantly impacting the kernel code or cluttering -it with special cases. - - -1) Entry point for arch/powerpc -------------------------------- - - There is one and one single entry point to the kernel, at the start - of the kernel image. That entry point supports two calling - conventions: - - a) Boot from Open Firmware. If your firmware is compatible - with Open Firmware (IEEE 1275) or provides an OF compatible - client interface API (support for "interpret" callback of - forth words isn't required), you can enter the kernel with: - - r5 : OF callback pointer as defined by IEEE 1275 - bindings to powerpc. Only the 32 bit client interface - is currently supported - - r3, r4 : address & length of an initrd if any or 0 - - The MMU is either on or off; the kernel will run the - trampoline located in arch/powerpc/kernel/prom_init.c to - extract the device-tree and other information from open - firmware and build a flattened device-tree as described - in b). prom_init() will then re-enter the kernel using - the second method. This trampoline code runs in the - context of the firmware, which is supposed to handle all - exceptions during that time. - - b) Direct entry with a flattened device-tree block. This entry - point is called by a) after the OF trampoline and can also be - called directly by a bootloader that does not support the Open - Firmware client interface. It is also used by "kexec" to - implement "hot" booting of a new kernel from a previous - running one. This method is what I will describe in more - details in this document, as method a) is simply standard Open - Firmware, and thus should be implemented according to the - various standard documents defining it and its binding to the - PowerPC platform. The entry point definition then becomes: - - r3 : physical pointer to the device-tree block - (defined in chapter II) in RAM - - r4 : physical pointer to the kernel itself. This is - used by the assembly code to properly disable the MMU - in case you are entering the kernel with MMU enabled - and a non-1:1 mapping. - - r5 : NULL (as to differenciate with method a) - - Note about SMP entry: Either your firmware puts your other - CPUs in some sleep loop or spin loop in ROM where you can get - them out via a soft reset or some other means, in which case - you don't need to care, or you'll have to enter the kernel - with all CPUs. The way to do that with method b) will be - described in a later revision of this document. - - -2) Board support ----------------- - -64-bit kernels: - - Board supports (platforms) are not exclusive config options. An - arbitrary set of board supports can be built in a single kernel - image. The kernel will "know" what set of functions to use for a - given platform based on the content of the device-tree. Thus, you - should: - - a) add your platform support as a _boolean_ option in - arch/powerpc/Kconfig, following the example of PPC_PSERIES, - PPC_PMAC and PPC_MAPLE. The later is probably a good - example of a board support to start from. - - b) create your main platform file as - "arch/powerpc/platforms/myplatform/myboard_setup.c" and add it - to the Makefile under the condition of your CONFIG_ - option. This file will define a structure of type "ppc_md" - containing the various callbacks that the generic code will - use to get to your platform specific code - - c) Add a reference to your "ppc_md" structure in the - "machines" table in arch/powerpc/kernel/setup_64.c if you are - a 64-bit platform. - - d) request and get assigned a platform number (see PLATFORM_* - constants in include/asm-powerpc/processor.h - -32-bit embedded kernels: - - Currently, board support is essentially an exclusive config option. - The kernel is configured for a single platform. Part of the reason - for this is to keep kernels on embedded systems small and efficient; - part of this is due to the fact the code is already that way. In the - future, a kernel may support multiple platforms, but only if the - platforms feature the same core architectire. A single kernel build - cannot support both configurations with Book E and configurations - with classic Powerpc architectures. - - 32-bit embedded platforms that are moved into arch/powerpc using a - flattened device tree should adopt the merged tree practice of - setting ppc_md up dynamically, even though the kernel is currently - built with support for only a single platform at a time. This allows - unification of the setup code, and will make it easier to go to a - multiple-platform-support model in the future. - -NOTE: I believe the above will be true once Ben's done with the merge -of the boot sequences.... someone speak up if this is wrong! - - To add a 32-bit embedded platform support, follow the instructions - for 64-bit platforms above, with the exception that the Kconfig - option should be set up such that the kernel builds exclusively for - the platform selected. The processor type for the platform should - enable another config option to select the specific board - supported. - -NOTE: If ben doesn't merge the setup files, may need to change this to -point to setup_32.c - - - I will describe later the boot process and various callbacks that - your platform should implement. - - -II - The DT block format -======================== - - -This chapter defines the actual format of the flattened device-tree -passed to the kernel. The actual content of it and kernel requirements -are described later. You can find example of code manipulating that -format in various places, including arch/powerpc/kernel/prom_init.c -which will generate a flattened device-tree from the Open Firmware -representation, or the fs2dt utility which is part of the kexec tools -which will generate one from a filesystem representation. It is -expected that a bootloader like uboot provides a bit more support, -that will be discussed later as well. - -Note: The block has to be in main memory. It has to be accessible in -both real mode and virtual mode with no mapping other than main -memory. If you are writing a simple flash bootloader, it should copy -the block to RAM before passing it to the kernel. - - -1) Header ---------- - - The kernel is entered with r3 pointing to an area of memory that is - roughtly described in include/asm-powerpc/prom.h by the structure - boot_param_header: - -struct boot_param_header { - u32 magic; /* magic word OF_DT_HEADER */ - u32 totalsize; /* total size of DT block */ - u32 off_dt_struct; /* offset to structure */ - u32 off_dt_strings; /* offset to strings */ - u32 off_mem_rsvmap; /* offset to memory reserve map -*/ - u32 version; /* format version */ - u32 last_comp_version; /* last compatible version */ - - /* version 2 fields below */ - u32 boot_cpuid_phys; /* Which physical CPU id we're - booting on */ - /* version 3 fields below */ - u32 size_dt_strings; /* size of the strings block */ -}; - - Along with the constants: - -/* Definitions used by the flattened device tree */ -#define OF_DT_HEADER 0xd00dfeed /* 4: version, - 4: total size */ -#define OF_DT_BEGIN_NODE 0x1 /* Start node: full name -*/ -#define OF_DT_END_NODE 0x2 /* End node */ -#define OF_DT_PROP 0x3 /* Property: name off, - size, content */ -#define OF_DT_END 0x9 - - All values in this header are in big endian format, the various - fields in this header are defined more precisely below. All - "offset" values are in bytes from the start of the header; that is - from the value of r3. - - - magic - - This is a magic value that "marks" the beginning of the - device-tree block header. It contains the value 0xd00dfeed and is - defined by the constant OF_DT_HEADER - - - totalsize - - This is the total size of the DT block including the header. The - "DT" block should enclose all data structures defined in this - chapter (who are pointed to by offsets in this header). That is, - the device-tree structure, strings, and the memory reserve map. - - - off_dt_struct - - This is an offset from the beginning of the header to the start - of the "structure" part the device tree. (see 2) device tree) - - - off_dt_strings - - This is an offset from the beginning of the header to the start - of the "strings" part of the device-tree - - - off_mem_rsvmap - - This is an offset from the beginning of the header to the start - of the reserved memory map. This map is a list of pairs of 64 - bit integers. Each pair is a physical address and a size. The - - list is terminated by an entry of size 0. This map provides the - kernel with a list of physical memory areas that are "reserved" - and thus not to be used for memory allocations, especially during - early initialization. The kernel needs to allocate memory during - boot for things like un-flattening the device-tree, allocating an - MMU hash table, etc... Those allocations must be done in such a - way to avoid overriding critical things like, on Open Firmware - capable machines, the RTAS instance, or on some pSeries, the TCE - tables used for the iommu. Typically, the reserve map should - contain _at least_ this DT block itself (header,total_size). If - you are passing an initrd to the kernel, you should reserve it as - well. You do not need to reserve the kernel image itself. The map - should be 64 bit aligned. - - - version - - This is the version of this structure. Version 1 stops - here. Version 2 adds an additional field boot_cpuid_phys. - Version 3 adds the size of the strings block, allowing the kernel - to reallocate it easily at boot and free up the unused flattened - structure after expansion. Version 16 introduces a new more - "compact" format for the tree itself that is however not backward - compatible. You should always generate a structure of the highest - version defined at the time of your implementation. Currently - that is version 16, unless you explicitely aim at being backward - compatible. - - - last_comp_version - - Last compatible version. This indicates down to what version of - the DT block you are backward compatible. For example, version 2 - is backward compatible with version 1 (that is, a kernel build - for version 1 will be able to boot with a version 2 format). You - should put a 1 in this field if you generate a device tree of - version 1 to 3, or 0x10 if you generate a tree of version 0x10 - using the new unit name format. - - - boot_cpuid_phys - - This field only exist on version 2 headers. It indicate which - physical CPU ID is calling the kernel entry point. This is used, - among others, by kexec. If you are on an SMP system, this value - should match the content of the "reg" property of the CPU node in - the device-tree corresponding to the CPU calling the kernel entry - point (see further chapters for more informations on the required - device-tree contents) - - - So the typical layout of a DT block (though the various parts don't - need to be in that order) looks like this (addresses go from top to - bottom): - - - ------------------------------ - r3 -> | struct boot_param_header | - ------------------------------ - | (alignment gap) (*) | - ------------------------------ - | memory reserve map | - ------------------------------ - | (alignment gap) | - ------------------------------ - | | - | device-tree structure | - | | - ------------------------------ - | (alignment gap) | - ------------------------------ - | | - | device-tree strings | - | | - -----> ------------------------------ - | - | - --- (r3 + totalsize) - - (*) The alignment gaps are not necessarily present; their presence - and size are dependent on the various alignment requirements of - the individual data blocks. - - -2) Device tree generalities ---------------------------- - -This device-tree itself is separated in two different blocks, a -structure block and a strings block. Both need to be aligned to a 4 -byte boundary. - -First, let's quickly describe the device-tree concept before detailing -the storage format. This chapter does _not_ describe the detail of the -required types of nodes & properties for the kernel, this is done -later in chapter III. - -The device-tree layout is strongly inherited from the definition of -the Open Firmware IEEE 1275 device-tree. It's basically a tree of -nodes, each node having two or more named properties. A property can -have a value or not. - -It is a tree, so each node has one and only one parent except for the -root node who has no parent. - -A node has 2 names. The actual node name is generally contained in a -property of type "name" in the node property list whose value is a -zero terminated string and is mandatory for version 1 to 3 of the -format definition (as it is in Open Firmware). Version 0x10 makes it -optional as it can generate it from the unit name defined below. - -There is also a "unit name" that is used to differenciate nodes with -the same name at the same level, it is usually made of the node -name's, the "@" sign, and a "unit address", which definition is -specific to the bus type the node sits on. - -The unit name doesn't exist as a property per-se but is included in -the device-tree structure. It is typically used to represent "path" in -the device-tree. More details about the actual format of these will be -below. - -The kernel powerpc generic code does not make any formal use of the -unit address (though some board support code may do) so the only real -requirement here for the unit address is to ensure uniqueness of -the node unit name at a given level of the tree. Nodes with no notion -of address and no possible sibling of the same name (like /memory or -/cpus) may omit the unit address in the context of this specification, -or use the "@0" default unit address. The unit name is used to define -a node "full path", which is the concatenation of all parent node -unit names separated with "/". - -The root node doesn't have a defined name, and isn't required to have -a name property either if you are using version 3 or earlier of the -format. It also has no unit address (no @ symbol followed by a unit -address). The root node unit name is thus an empty string. The full -path to the root node is "/". - -Every node which actually represents an actual device (that is, a node -which isn't only a virtual "container" for more nodes, like "/cpus" -is) is also required to have a "device_type" property indicating the -type of node . - -Finally, every node that can be referenced from a property in another -node is required to have a "linux,phandle" property. Real open -firmware implementations provide a unique "phandle" value for every -node that the "prom_init()" trampoline code turns into -"linux,phandle" properties. However, this is made optional if the -flattened device tree is used directly. An example of a node -referencing another node via "phandle" is when laying out the -interrupt tree which will be described in a further version of this -document. - -This "linux, phandle" property is a 32 bit value that uniquely -identifies a node. You are free to use whatever values or system of -values, internal pointers, or whatever to generate these, the only -requirement is that every node for which you provide that property has -a unique value for it. - -Here is an example of a simple device-tree. In this example, an "o" -designates a node followed by the node unit name. Properties are -presented with their name followed by their content. "content" -represents an ASCII string (zero terminated) value, while -represents a 32 bit hexadecimal value. The various nodes in this -example will be discussed in a later chapter. At this point, it is -only meant to give you a idea of what a device-tree looks like. I have -purposefully kept the "name" and "linux,phandle" properties which -aren't necessary in order to give you a better idea of what the tree -looks like in practice. - - / o device-tree - |- name = "device-tree" - |- model = "MyBoardName" - |- compatible = "MyBoardFamilyName" - |- #address-cells = <2> - |- #size-cells = <2> - |- linux,phandle = <0> - | - o cpus - | | - name = "cpus" - | | - linux,phandle = <1> - | | - #address-cells = <1> - | | - #size-cells = <0> - | | - | o PowerPC,970@0 - | |- name = "PowerPC,970" - | |- device_type = "cpu" - | |- reg = <0> - | |- clock-frequency = <5f5e1000> - | |- linux,boot-cpu - | |- linux,phandle = <2> - | - o memory@0 - | |- name = "memory" - | |- device_type = "memory" - | |- reg = <00000000 00000000 00000000 20000000> - | |- linux,phandle = <3> - | - o chosen - |- name = "chosen" - |- bootargs = "root=/dev/sda2" - |- linux,platform = <00000600> - |- linux,phandle = <4> - -This tree is almost a minimal tree. It pretty much contains the -minimal set of required nodes and properties to boot a linux kernel; -that is, some basic model informations at the root, the CPUs, and the -physical memory layout. It also includes misc information passed -through /chosen, like in this example, the platform type (mandatory) -and the kernel command line arguments (optional). - -The /cpus/PowerPC,970@0/linux,boot-cpu property is an example of a -property without a value. All other properties have a value. The -significance of the #address-cells and #size-cells properties will be -explained in chapter IV which defines precisely the required nodes and -properties and their content. - - -3) Device tree "structure" block - -The structure of the device tree is a linearized tree structure. The -"OF_DT_BEGIN_NODE" token starts a new node, and the "OF_DT_END_NODE" -ends that node definition. Child nodes are simply defined before -"OF_DT_END_NODE" (that is nodes within the node). A 'token' is a 32 -bit value. The tree has to be "finished" with a OF_DT_END token - -Here's the basic structure of a single node: - - * token OF_DT_BEGIN_NODE (that is 0x00000001) - * for version 1 to 3, this is the node full path as a zero - terminated string, starting with "/". For version 16 and later, - this is the node unit name only (or an empty string for the - root node) - * [align gap to next 4 bytes boundary] - * for each property: - * token OF_DT_PROP (that is 0x00000003) - * 32 bit value of property value size in bytes (or 0 of no - * value) - * 32 bit value of offset in string block of property name - * property value data if any - * [align gap to next 4 bytes boundary] - * [child nodes if any] - * token OF_DT_END_NODE (that is 0x00000002) - -So the node content can be summmarised as a start token, a full path, -a list of properties, a list of child node and an end token. Every -child node is a full node structure itself as defined above. - -4) Device tree 'strings" block - -In order to save space, property names, which are generally redundant, -are stored separately in the "strings" block. This block is simply the -whole bunch of zero terminated strings for all property names -concatenated together. The device-tree property definitions in the -structure block will contain offset values from the beginning of the -strings block. - - -III - Required content of the device tree -========================================= - -WARNING: All "linux,*" properties defined in this document apply only -to a flattened device-tree. If your platform uses a real -implementation of Open Firmware or an implementation compatible with -the Open Firmware client interface, those properties will be created -by the trampoline code in the kernel's prom_init() file. For example, -that's where you'll have to add code to detect your board model and -set the platform number. However, when using the flatenned device-tree -entry point, there is no prom_init() pass, and thus you have to -provide those properties yourself. - - -1) Note about cells and address representation ----------------------------------------------- - -The general rule is documented in the various Open Firmware -documentations. If you chose to describe a bus with the device-tree -and there exist an OF bus binding, then you should follow the -specification. However, the kernel does not require every single -device or bus to be described by the device tree. - -In general, the format of an address for a device is defined by the -parent bus type, based on the #address-cells and #size-cells -property. In the absence of such a property, the parent's parent -values are used, etc... The kernel requires the root node to have -those properties defining addresses format for devices directly mapped -on the processor bus. - -Those 2 properties define 'cells' for representing an address and a -size. A "cell" is a 32 bit number. For example, if both contain 2 -like the example tree given above, then an address and a size are both -composed of 2 cells, and each is a 64 bit number (cells are -concatenated and expected to be in big endian format). Another example -is the way Apple firmware defines them, with 2 cells for an address -and one cell for a size. Most 32-bit implementations should define -#address-cells and #size-cells to 1, which represents a 32-bit value. -Some 32-bit processors allow for physical addresses greater than 32 -bits; these processors should define #address-cells as 2. - -"reg" properties are always a tuple of the type "address size" where -the number of cells of address and size is specified by the bus -#address-cells and #size-cells. When a bus supports various address -spaces and other flags relative to a given address allocation (like -prefetchable, etc...) those flags are usually added to the top level -bits of the physical address. For example, a PCI physical address is -made of 3 cells, the bottom two containing the actual address itself -while the top cell contains address space indication, flags, and pci -bus & device numbers. - -For busses that support dynamic allocation, it's the accepted practice -to then not provide the address in "reg" (keep it 0) though while -providing a flag indicating the address is dynamically allocated, and -then, to provide a separate "assigned-addresses" property that -contains the fully allocated addresses. See the PCI OF bindings for -details. - -In general, a simple bus with no address space bits and no dynamic -allocation is preferred if it reflects your hardware, as the existing -kernel address parsing functions will work out of the box. If you -define a bus type with a more complex address format, including things -like address space bits, you'll have to add a bus translator to the -prom_parse.c file of the recent kernels for your bus type. - -The "reg" property only defines addresses and sizes (if #size-cells -is -non-0) within a given bus. In order to translate addresses upward -(that is into parent bus addresses, and possibly into cpu physical -addresses), all busses must contain a "ranges" property. If the -"ranges" property is missing at a given level, it's assumed that -translation isn't possible. The format of the "ranges" proprety for a -bus is a list of: - - bus address, parent bus address, size - -"bus address" is in the format of the bus this bus node is defining, -that is, for a PCI bridge, it would be a PCI address. Thus, (bus -address, size) defines a range of addresses for child devices. "parent -bus address" is in the format of the parent bus of this bus. For -example, for a PCI host controller, that would be a CPU address. For a -PCI<->ISA bridge, that would be a PCI address. It defines the base -address in the parent bus where the beginning of that range is mapped. - -For a new 64 bit powerpc board, I recommend either the 2/2 format or -Apple's 2/1 format which is slightly more compact since sizes usually -fit in a single 32 bit word. New 32 bit powerpc boards should use a -1/1 format, unless the processor supports physical addresses greater -than 32-bits, in which case a 2/1 format is recommended. - - -2) Note about "compatible" properties -------------------------------------- - -These properties are optional, but recommended in devices and the root -node. The format of a "compatible" property is a list of concatenated -zero terminated strings. They allow a device to express its -compatibility with a family of similar devices, in some cases, -allowing a single driver to match against several devices regardless -of their actual names. - -3) Note about "name" properties -------------------------------- - -While earlier users of Open Firmware like OldWorld macintoshes tended -to use the actual device name for the "name" property, it's nowadays -considered a good practice to use a name that is closer to the device -class (often equal to device_type). For example, nowadays, ethernet -controllers are named "ethernet", an additional "model" property -defining precisely the chip type/model, and "compatible" property -defining the family in case a single driver can driver more than one -of these chips. However, the kernel doesn't generally put any -restriction on the "name" property; it is simply considered good -practice to follow the standard and its evolutions as closely as -possible. - -Note also that the new format version 16 makes the "name" property -optional. If it's absent for a node, then the node's unit name is then -used to reconstruct the name. That is, the part of the unit name -before the "@" sign is used (or the entire unit name if no "@" sign -is present). - -4) Note about node and property names and character set -------------------------------------------------------- - -While open firmware provides more flexibe usage of 8859-1, this -specification enforces more strict rules. Nodes and properties should -be comprised only of ASCII characters 'a' to 'z', '0' to -'9', ',', '.', '_', '+', '#', '?', and '-'. Node names additionally -allow uppercase characters 'A' to 'Z' (property names should be -lowercase. The fact that vendors like Apple don't respect this rule is -irrelevant here). Additionally, node and property names should always -begin with a character in the range 'a' to 'z' (or 'A' to 'Z' for node -names). - -The maximum number of characters for both nodes and property names -is 31. In the case of node names, this is only the leftmost part of -a unit name (the pure "name" property), it doesn't include the unit -address which can extend beyond that limit. - - -5) Required nodes and properties --------------------------------- - These are all that are currently required. However, it is strongly - recommended that you expose PCI host bridges as documented in the - PCI binding to open firmware, and your interrupt tree as documented - in OF interrupt tree specification. - - a) The root node - - The root node requires some properties to be present: - - - model : this is your board name/model - - #address-cells : address representation for "root" devices - - #size-cells: the size representation for "root" devices - - Additionally, some recommended properties are: - - - compatible : the board "family" generally finds its way here, - for example, if you have 2 board models with a similar layout, - that typically get driven by the same platform code in the - kernel, you would use a different "model" property but put a - value in "compatible". The kernel doesn't directly use that - value (see /chosen/linux,platform for how the kernel choses a - platform type) but it is generally useful. - - The root node is also generally where you add additional properties - specific to your board like the serial number if any, that sort of - thing. it is recommended that if you add any "custom" property whose - name may clash with standard defined ones, you prefix them with your - vendor name and a comma. - - b) The /cpus node - - This node is the parent of all individual CPU nodes. It doesn't - have any specific requirements, though it's generally good practice - to have at least: - - #address-cells = <00000001> - #size-cells = <00000000> - - This defines that the "address" for a CPU is a single cell, and has - no meaningful size. This is not necessary but the kernel will assume - that format when reading the "reg" properties of a CPU node, see - below - - c) The /cpus/* nodes - - So under /cpus, you are supposed to create a node for every CPU on - the machine. There is no specific restriction on the name of the - CPU, though It's common practice to call it PowerPC,. For - example, Apple uses PowerPC,G5 while IBM uses PowerPC,970FX. - - Required properties: - - - device_type : has to be "cpu" - - reg : This is the physical cpu number, it's a single 32 bit cell - and is also used as-is as the unit number for constructing the - unit name in the full path. For example, with 2 CPUs, you would - have the full path: - /cpus/PowerPC,970FX@0 - /cpus/PowerPC,970FX@1 - (unit addresses do not require leading zeroes) - - d-cache-line-size : one cell, L1 data cache line size in bytes - - i-cache-line-size : one cell, L1 instruction cache line size in - bytes - - d-cache-size : one cell, size of L1 data cache in bytes - - i-cache-size : one cell, size of L1 instruction cache in bytes - - linux, boot-cpu : Should be defined if this cpu is the boot cpu. - - Recommended properties: - - - timebase-frequency : a cell indicating the frequency of the - timebase in Hz. This is not directly used by the generic code, - but you are welcome to copy/paste the pSeries code for setting - the kernel timebase/decrementer calibration based on this - value. - - clock-frequency : a cell indicating the CPU core clock frequency - in Hz. A new property will be defined for 64 bit values, but if - your frequency is < 4Ghz, one cell is enough. Here as well as - for the above, the common code doesn't use that property, but - you are welcome to re-use the pSeries or Maple one. A future - kernel version might provide a common function for this. - - You are welcome to add any property you find relevant to your board, - like some information about the mechanism used to soft-reset the - CPUs. For example, Apple puts the GPIO number for CPU soft reset - lines in there as a "soft-reset" property since they start secondary - CPUs by soft-resetting them. - - - d) the /memory node(s) - - To define the physical memory layout of your board, you should - create one or more memory node(s). You can either create a single - node with all memory ranges in its reg property, or you can create - several nodes, as you wish. The unit address (@ part) used for the - full path is the address of the first range of memory defined by a - given node. If you use a single memory node, this will typically be - @0. - - Required properties: - - - device_type : has to be "memory" - - reg : This property contains all the physical memory ranges of - your board. It's a list of addresses/sizes concatenated - together, with the number of cells of each defined by the - #address-cells and #size-cells of the root node. For example, - with both of these properties beeing 2 like in the example given - earlier, a 970 based machine with 6Gb of RAM could typically - have a "reg" property here that looks like: - - 00000000 00000000 00000000 80000000 - 00000001 00000000 00000001 00000000 - - That is a range starting at 0 of 0x80000000 bytes and a range - starting at 0x100000000 and of 0x100000000 bytes. You can see - that there is no memory covering the IO hole between 2Gb and - 4Gb. Some vendors prefer splitting those ranges into smaller - segments, but the kernel doesn't care. - - e) The /chosen node - - This node is a bit "special". Normally, that's where open firmware - puts some variable environment information, like the arguments, or - phandle pointers to nodes like the main interrupt controller, or the - default input/output devices. - - This specification makes a few of these mandatory, but also defines - some linux-specific properties that would be normally constructed by - the prom_init() trampoline when booting with an OF client interface, - but that you have to provide yourself when using the flattened format. - - Required properties: - - - linux,platform : This is your platform number as assigned by the - architecture maintainers - - Recommended properties: - - - bootargs : This zero-terminated string is passed as the kernel - command line - - linux,stdout-path : This is the full path to your standard - console device if any. Typically, if you have serial devices on - your board, you may want to put the full path to the one set as - the default console in the firmware here, for the kernel to pick - it up as it's own default console. If you look at the funciton - set_preferred_console() in arch/ppc64/kernel/setup.c, you'll see - that the kernel tries to find out the default console and has - knowledge of various types like 8250 serial ports. You may want - to extend this function to add your own. - - interrupt-controller : This is one cell containing a phandle - value that matches the "linux,phandle" property of your main - interrupt controller node. May be used for interrupt routing. - - - Note that u-boot creates and fills in the chosen node for platforms - that use it. - - f) the /soc node - - This node is used to represent a system-on-a-chip (SOC) and must be - present if the processor is a SOC. The top-level soc node contains - information that is global to all devices on the SOC. The node name - should contain a unit address for the SOC, which is the base address - of the memory-mapped register set for the SOC. The name of an soc - node should start with "soc", and the remainder of the name should - represent the part number for the soc. For example, the MPC8540's - soc node would be called "soc8540". - - Required properties: - - - device_type : Should be "soc" - - ranges : Should be defined as specified in 1) to describe the - translation of SOC addresses for memory mapped SOC registers. - - Recommended properties: - - - reg : This property defines the address and size of the - memory-mapped registers that are used for the SOC node itself. - It does not include the child device registers - these will be - defined inside each child node. The address specified in the - "reg" property should match the unit address of the SOC node. - - #address-cells : Address representation for "soc" devices. The - format of this field may vary depending on whether or not the - device registers are memory mapped. For memory mapped - registers, this field represents the number of cells needed to - represent the address of the registers. For SOCs that do not - use MMIO, a special address format should be defined that - contains enough cells to represent the required information. - See 1) above for more details on defining #address-cells. - - #size-cells : Size representation for "soc" devices - - #interrupt-cells : Defines the width of cells used to represent - interrupts. Typically this value is <2>, which includes a - 32-bit number that represents the interrupt number, and a - 32-bit number that represents the interrupt sense and level. - This field is only needed if the SOC contains an interrupt - controller. - - The SOC node may contain child nodes for each SOC device that the - platform uses. Nodes should not be created for devices which exist - on the SOC but are not used by a particular platform. See chapter VI - for more information on how to specify devices that are part of an -SOC. - - Example SOC node for the MPC8540: - - soc8540@e0000000 { - #address-cells = <1>; - #size-cells = <1>; - #interrupt-cells = <2>; - device_type = "soc"; - ranges = <00000000 e0000000 00100000> - reg = ; - } - - - -IV - "dtc", the device tree compiler -==================================== - - -dtc source code can be found at - - -WARNING: This version is still in early development stage; the -resulting device-tree "blobs" have not yet been validated with the -kernel. The current generated bloc lacks a useful reserve map (it will -be fixed to generate an empty one, it's up to the bootloader to fill -it up) among others. The error handling needs work, bugs are lurking, -etc... - -dtc basically takes a device-tree in a given format and outputs a -device-tree in another format. The currently supported formats are: - - Input formats: - ------------- - - - "dtb": "blob" format, that is a flattened device-tree block - with - header all in a binary blob. - - "dts": "source" format. This is a text file containing a - "source" for a device-tree. The format is defined later in this - chapter. - - "fs" format. This is a representation equivalent to the - output of /proc/device-tree, that is nodes are directories and - properties are files - - Output formats: - --------------- - - - "dtb": "blob" format - - "dts": "source" format - - "asm": assembly language file. This is a file that can be - sourced by gas to generate a device-tree "blob". That file can - then simply be added to your Makefile. Additionally, the - assembly file exports some symbols that can be use - - -The syntax of the dtc tool is - - dtc [-I ] [-O ] - [-o output-filename] [-V output_version] input_filename - - -The "output_version" defines what versio of the "blob" format will be -generated. Supported versions are 1,2,3 and 16. The default is -currently version 3 but that may change in the future to version 16. - -Additionally, dtc performs various sanity checks on the tree, like the -uniqueness of linux,phandle properties, validity of strings, etc... - -The format of the .dts "source" file is "C" like, supports C and C++ -style commments. - -/ { -} - -The above is the "device-tree" definition. It's the only statement -supported currently at the toplevel. - -/ { - property1 = "string_value"; /* define a property containing a 0 - * terminated string - */ - - property2 = <1234abcd>; /* define a property containing a - * numerical 32 bits value (hexadecimal) - */ - - property3 = <12345678 12345678 deadbeef>; - /* define a property containing 3 - * numerical 32 bits values (cells) in - * hexadecimal - */ - property4 = [0a 0b 0c 0d de ea ad be ef]; - /* define a property whose content is - * an arbitrary array of bytes - */ - - childnode@addresss { /* define a child node named "childnode" - * whose unit name is "childnode at - * address" - */ - - childprop = "hello\n"; /* define a property "childprop" of - * childnode (in this case, a string) - */ - }; -}; - -Nodes can contain other nodes etc... thus defining the hierarchical -structure of the tree. - -Strings support common escape sequences from C: "\n", "\t", "\r", -"\(octal value)", "\x(hex value)". - -It is also suggested that you pipe your source file through cpp (gcc -preprocessor) so you can use #include's, #define for constants, etc... - -Finally, various options are planned but not yet implemented, like -automatic generation of phandles, labels (exported to the asm file so -you can point to a property content and change it easily from whatever -you link the device-tree with), label or path instead of numeric value -in some cells to "point" to a node (replaced by a phandle at compile -time), export of reserve map address to the asm file, ability to -specify reserve map content at compile time, etc... - -We may provide a .h include file with common definitions of that -proves useful for some properties (like building PCI properties or -interrupt maps) though it may be better to add a notion of struct -definitions to the compiler... - - -V - Recommendations for a bootloader -==================================== - - -Here are some various ideas/recommendations that have been proposed -while all this has been defined and implemented. - - - The bootloader may want to be able to use the device-tree itself - and may want to manipulate it (to add/edit some properties, - like physical memory size or kernel arguments). At this point, 2 - choices can be made. Either the bootloader works directly on the - flattened format, or the bootloader has its own internal tree - representation with pointers (similar to the kernel one) and - re-flattens the tree when booting the kernel. The former is a bit - more difficult to edit/modify, the later requires probably a bit - more code to handle the tree structure. Note that the structure - format has been designed so it's relatively easy to "insert" - properties or nodes or delete them by just memmoving things - around. It contains no internal offsets or pointers for this - purpose. - - - An example of code for iterating nodes & retreiving properties - directly from the flattened tree format can be found in the kernel - file arch/ppc64/kernel/prom.c, look at scan_flat_dt() function, - it's usage in early_init_devtree(), and the corresponding various - early_init_dt_scan_*() callbacks. That code can be re-used in a - GPL bootloader, and as the author of that code, I would be happy - do discuss possible free licencing to any vendor who wishes to - integrate all or part of this code into a non-GPL bootloader. - - - -VI - System-on-a-chip devices and nodes -======================================= - -Many companies are now starting to develop system-on-a-chip -processors, where the processor core (cpu) and many peripheral devices -exist on a single piece of silicon. For these SOCs, an SOC node -should be used that defines child nodes for the devices that make -up the SOC. While platforms are not required to use this model in -order to boot the kernel, it is highly encouraged that all SOC -implementations define as complete a flat-device-tree as possible to -describe the devices on the SOC. This will allow for the -genericization of much of the kernel code. - - -1) Defining child nodes of an SOC ---------------------------------- - -Each device that is part of an SOC may have its own node entry inside -the SOC node. For each device that is included in the SOC, the unit -address property represents the address offset for this device's -memory-mapped registers in the parent's address space. The parent's -address space is defined by the "ranges" property in the top-level soc -node. The "reg" property for each node that exists directly under the -SOC node should contain the address mapping from the child address space -to the parent SOC address space and the size of the device's -memory-mapped register file. - -For many devices that may exist inside an SOC, there are predefined -specifications for the format of the device tree node. All SOC child -nodes should follow these specifications, except where noted in this -document. - -See appendix A for an example partial SOC node definition for the -MPC8540. - - -2) Specifying interrupt information for SOC devices ---------------------------------------------------- - -Each device that is part of an SOC and which generates interrupts -should have the following properties: - - - interrupt-parent : contains the phandle of the interrupt - controller which handles interrupts for this device - - interrupts : a list of tuples representing the interrupt - number and the interrupt sense and level for each interupt - for this device. - -This information is used by the kernel to build the interrupt table -for the interrupt controllers in the system. - -Sense and level information should be encoded as follows: - - Devices connected to openPIC-compatible controllers should encode - sense and polarity as follows: - - 0 = high to low edge sensitive type enabled - 1 = active low level sensitive type enabled - 2 = low to high edge sensitive type enabled - 3 = active high level sensitive type enabled - - ISA PIC interrupt controllers should adhere to the ISA PIC - encodings listed below: - - 0 = active low level sensitive type enabled - 1 = active high level sensitive type enabled - 2 = high to low edge sensitive type enabled - 3 = low to high edge sensitive type enabled - - - -3) Representing devices without a current OF specification ----------------------------------------------------------- - -Currently, there are many devices on SOCs that do not have a standard -representation pre-defined as part of the open firmware -specifications, mainly because the boards that contain these SOCs are -not currently booted using open firmware. This section contains -descriptions for the SOC devices for which new nodes have been -defined; this list will expand as more and more SOC-containing -platforms are moved over to use the flattened-device-tree model. - - a) MDIO IO device - - The MDIO is a bus to which the PHY devices are connected. For each - device that exists on this bus, a child node should be created. See - the definition of the PHY node below for an example of how to define - a PHY. - - Required properties: - - reg : Offset and length of the register set for the device - - device_type : Should be "mdio" - - compatible : Should define the compatible device type for the - mdio. Currently, this is most likely to be "gianfar" - - Example: - - mdio@24520 { - reg = <24520 20>; - - ethernet-phy@0 { - ...... - }; - }; - - - b) Gianfar-compatible ethernet nodes - - Required properties: - - - device_type : Should be "network" - - model : Model of the device. Can be "TSEC", "eTSEC", or "FEC" - - compatible : Should be "gianfar" - - reg : Offset and length of the register set for the device - - address : List of bytes representing the ethernet address of - this controller - - interrupts : where a is the interrupt number and b is a - field that represents an encoding of the sense and level - information for the interrupt. This should be encoded based on - the information in section 2) depending on the type of interrupt - controller you have. - - interrupt-parent : the phandle for the interrupt controller that - services interrupts for this device. - - phy-handle : The phandle for the PHY connected to this ethernet - controller. - - Example: - - ethernet@24000 { - #size-cells = <0>; - device_type = "network"; - model = "TSEC"; - compatible = "gianfar"; - reg = <24000 1000>; - address = [ 00 E0 0C 00 73 00 ]; - interrupts = ; - interrupt-parent = <40000>; - phy-handle = <2452000> - }; - - - - c) PHY nodes - - Required properties: - - - device_type : Should be "ethernet-phy" - - interrupts : where a is the interrupt number and b is a - field that represents an encoding of the sense and level - information for the interrupt. This should be encoded based on - the information in section 2) depending on the type of interrupt - controller you have. - - interrupt-parent : the phandle for the interrupt controller that - services interrupts for this device. - - reg : The ID number for the phy, usually a small integer - - linux,phandle : phandle for this node; likely referenced by an - ethernet controller node. - - - Example: - - ethernet-phy@0 { - linux,phandle = <2452000> - interrupt-parent = <40000>; - interrupts = <35 1>; - reg = <0>; - device_type = "ethernet-phy"; - }; - - - d) Interrupt controllers - - Some SOC devices contain interrupt controllers that are different - from the standard Open PIC specification. The SOC device nodes for - these types of controllers should be specified just like a standard - OpenPIC controller. Sense and level information should be encoded - as specified in section 2) of this chapter for each device that - specifies an interrupt. - - Example : - - pic@40000 { - linux,phandle = <40000>; - clock-frequency = <0>; - interrupt-controller; - #address-cells = <0>; - reg = <40000 40000>; - built-in; - compatible = "chrp,open-pic"; - device_type = "open-pic"; - big-endian; - }; - - - e) I2C - - Required properties : - - - device_type : Should be "i2c" - - reg : Offset and length of the register set for the device - - Recommended properties : - - - compatible : Should be "fsl-i2c" for parts compatible with - Freescale I2C specifications. - - interrupts : where a is the interrupt number and b is a - field that represents an encoding of the sense and level - information for the interrupt. This should be encoded based on - the information in section 2) depending on the type of interrupt - controller you have. - - interrupt-parent : the phandle for the interrupt controller that - services interrupts for this device. - - dfsrr : boolean; if defined, indicates that this I2C device has - a digital filter sampling rate register - - fsl5200-clocking : boolean; if defined, indicated that this device - uses the FSL 5200 clocking mechanism. - - Example : - - i2c@3000 { - interrupt-parent = <40000>; - interrupts = <1b 3>; - reg = <3000 18>; - device_type = "i2c"; - compatible = "fsl-i2c"; - dfsrr; - }; - - - More devices will be defined as this spec matures. - - -Appendix A - Sample SOC node for MPC8540 -======================================== - -Note that the #address-cells and #size-cells for the SoC node -in this example have been explicitly listed; these are likely -not necessary as they are usually the same as the root node. - - soc8540@e0000000 { - #address-cells = <1>; - #size-cells = <1>; - #interrupt-cells = <2>; - device_type = "soc"; - ranges = <00000000 e0000000 00100000> - reg = ; - - mdio@24520 { - reg = <24520 20>; - device_type = "mdio"; - compatible = "gianfar"; - - ethernet-phy@0 { - linux,phandle = <2452000> - interrupt-parent = <40000>; - interrupts = <35 1>; - reg = <0>; - device_type = "ethernet-phy"; - }; - - ethernet-phy@1 { - linux,phandle = <2452001> - interrupt-parent = <40000>; - interrupts = <35 1>; - reg = <1>; - device_type = "ethernet-phy"; - }; - - ethernet-phy@3 { - linux,phandle = <2452002> - interrupt-parent = <40000>; - interrupts = <35 1>; - reg = <3>; - device_type = "ethernet-phy"; - }; - - }; - - ethernet@24000 { - #size-cells = <0>; - device_type = "network"; - model = "TSEC"; - compatible = "gianfar"; - reg = <24000 1000>; - address = [ 00 E0 0C 00 73 00 ]; - interrupts = ; - interrupt-parent = <40000>; - phy-handle = <2452000>; - }; - - ethernet@25000 { - #address-cells = <1>; - #size-cells = <0>; - device_type = "network"; - model = "TSEC"; - compatible = "gianfar"; - reg = <25000 1000>; - address = [ 00 E0 0C 00 73 01 ]; - interrupts = <13 3 14 3 18 3>; - interrupt-parent = <40000>; - phy-handle = <2452001>; - }; - - ethernet@26000 { - #address-cells = <1>; - #size-cells = <0>; - device_type = "network"; - model = "FEC"; - compatible = "gianfar"; - reg = <26000 1000>; - address = [ 00 E0 0C 00 73 02 ]; - interrupts = <19 3>; - interrupt-parent = <40000>; - phy-handle = <2452002>; - }; - - serial@4500 { - device_type = "serial"; - compatible = "ns16550"; - reg = <4500 100>; - clock-frequency = <0>; - interrupts = <1a 3>; - interrupt-parent = <40000>; - }; - - pic@40000 { - linux,phandle = <40000>; - clock-frequency = <0>; - interrupt-controller; - #address-cells = <0>; - reg = <40000 40000>; - built-in; - compatible = "chrp,open-pic"; - device_type = "open-pic"; - big-endian; - }; - - i2c@3000 { - interrupt-parent = <40000>; - interrupts = <1b 3>; - reg = <3000 18>; - device_type = "i2c"; - compatible = "fsl-i2c"; - dfsrr; - }; - - }; diff --git a/Documentation/dt-object-internal.txt b/Documentation/dt-object-internal.txt new file mode 100644 index 0000000..dbbbcea --- /dev/null +++ b/Documentation/dt-object-internal.txt @@ -0,0 +1,310 @@ +Device Tree Dynamic Object format internals +------------------------------------------- + +The Device Tree for most platforms is a static representation of +the hardware capabilities. This is insufficient for platforms +that need to dynamically insert Device Tree fragments into the +live tree. + +This document explains the Device Tree object format and +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 conflicting 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 dtbs are optionally tagged +with a different magic number in the header but otherwise they're 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). + +We generate a __symbols__ node to record nodes that had labels in the base +tree (or subsequent loaded overlays) so that they can be matched up with +references made to them in Device Tree objects. + +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__ node has been generated (no label in bar.dts). +Note that the target's ocp label is undefined, so the phandle +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 + +