[v3] doc: develop: Describe system configuration

Tom Rini trini at konsulko.com
Fri Jul 29 18:07:38 CEST 2022

Start by describing in general the best practices for how to implement
configuration of some aspect of U-Boot.  This generally means finding
the right choices for when something should be static or dynamically
configured and enabled.  Then further document when to use CONFIG or CFG
namespaces for static configuration.

Signed-off-by: Tom Rini <trini at konsulko.com>
Changes in v3:
- Drop RFC prefix.
- Incorporate most of the specific wording changes Heinrich requested
  against v2.
- Heinrich disliked the "namespace" wording in v2, and that in turn was
  a hold over from when this talked only about CONFIG vs CFG. Remove
  that word entirely and instead talk about configuration mechanisms.
  Reword a number of sections and examples so that they read better or
  hopefully more clearly now that we talk about different mechanisms.
- Expand on when to use each configuration mechanism.  Generally don't
  refer to CONFIG but instead Kconfig.

- Based on Pali's feedback, remove the README section and start a new
  section in this document to cover when to use each namespace. Try and
  be clear about when to use "hidden" Kconfig options rather than CFG as
- Based on Heinrich's feedback, rename this to system_configuration.rst
  and include some introductory remarks on when to use some dynamic or
  static configuration.  Link to the driver model code for dynamic
  configuration and then explain the CONFIG vs CFG namespaces for static

- This is essentially my idea on how to better handle the problem of
  CONFIG values that just don't fit in Kconfig because it makes much
  more sense to define them statically for a given SoC or calculate them
  from other values, and so on.  One example here would be to revert
  c7fad78ec0ee ("Convert CONFIG_SYS_BR0_PRELIM et al to Kconfig") and
  re-name these to CFG_SYS_.. instead. Another big example here would be
  a global search-and-replace of 's/CONFIG_HPS_/CFG_HPS_/g' as that's
  all tool-generated. Not all CONFIG_SYS_ options would get this as
  boolean choices are well handled in Kconfig, and that may not be clear
  enough in what I wrote here?
 README                               |  21 -----
 doc/develop/index.rst                |   1 +
 doc/develop/system_configuration.rst | 132 +++++++++++++++++++++++++++
 3 files changed, 133 insertions(+), 21 deletions(-)
 create mode 100644 doc/develop/system_configuration.rst

diff --git a/README b/README
index 2c4bde0b3297..623f35907217 100644
--- a/README
+++ b/README
@@ -166,27 +166,6 @@ Directory Hierarchy:
 Software Configuration:
-Configuration is usually done using C preprocessor defines; the
-rationale behind that is to avoid dead code whenever possible.
-There are two classes of configuration variables:
-* Configuration _OPTIONS_:
-  These are selectable by the user and have names beginning with
-  "CONFIG_".
-* Configuration _SETTINGS_:
-  These depend on the hardware etc. and should not be meddled with if
-  you don't know what you're doing; they have names beginning with
-Previously, all configuration was done by hand, which involved creating
-symbolic links and editing configuration files manually. More recently,
-U-Boot has added the Kbuild infrastructure used by the Linux kernel,
-allowing you to use the "make menuconfig" command to configure your
 Selection of Processor Architecture and Board Type:
diff --git a/doc/develop/index.rst b/doc/develop/index.rst
index 73741ceb6a2f..7c41e3f1b6e5 100644
--- a/doc/develop/index.rst
+++ b/doc/develop/index.rst
@@ -13,6 +13,7 @@ General
+   system_configuration
diff --git a/doc/develop/system_configuration.rst b/doc/develop/system_configuration.rst
new file mode 100644
index 000000000000..1279d12cb7ae
--- /dev/null
+++ b/doc/develop/system_configuration.rst
@@ -0,0 +1,132 @@
+.. SPDX-License-Identifier: GPL-2.0+
+System configuration
+There are a number of different aspects to configuring U-Boot to build and then
+run on a given platform or set of platforms. Broadly speaking, some aspects of
+the world can be configured at run time and others must be done at build time.
+In general run time configuration is preferred over build time configuration.
+But when making these decisions, we also need to consider if we're talking about
+a feature that could be useful to virtually every platform or something specific
+to a single hardware platform. The resulting image size is also another
+important consideration. Finally, run time configuration has additional overhead
+both in terms of resource requirements and wall clock time. All of this means
+that care must be taken when writing new code to select the most appropriate
+configuration mechanism.
+When adding new features to U-Boot, be they a new subsystem or SoC support or
+new platform for an existing supported SoC, the preferred configuration order
+#. Hardware based run time configuration. Examples of this include reading
+   processor specific registers, or a set of board specific GPIOs or an EEPROM
+   with a known format to it. These are the cases where we either cannot or
+   should not be relying on device tree checks. We use this for cases such as
+   optimized boot time or starting with a generic device tree and then enabling
+   or disabling features as we boot.
+#. Making use of our Kconfig infrastructure and C preprocessor macros that have
+   the prefix ``CONFIG``. This is the primary method of build time
+   configuration. This is generally the best fit for when we want to enable or
+   disable some sort of feature, such as the SoC or network support. The
+   ``CONFIG`` prefix for C preprocessor macros is strictly reserved for Kconfig
+   usage only.
+#. Making use of the :doc:`device tree <devicetree/control>` to determine at
+   run time how to configure a feature that we have enabled via Kconfig. For
+   example, we would use Kconfig to enable an i2c chip driver, but use the device
+   tree to know where the i2c chip resides in memory and other details we need
+   in order to configure the bus.
+#. Making use of C header files directly and defining C preprocessor macros that
+   have the ``CFG`` prefix. While the ``CFG`` prefix is reserved for this build
+   time configuration mechanism, the usage is ad hoc. This is to be used when the
+   previously mentioned mechanisms are not possible, or for legacy code that has
+   not been converted.
+Dynamic run time configuration methods.
+Details of hardware specific run time configuration methods are found within the
+documentation for a given processor family or board.
+Details of how to use run time configuration based on :doc:`driver model
+<driver-model/index>` are covered in that documentation section.
+Static build time configuration methods
+There are two mechanisms used to control the build time configuration of U-Boot.
+One is utilizing Kconfig and ``CONFIG`` prefixed macros and the other is ad hoc
+usage of ``CFG`` prefixed macros. Both of these are used when it is either not
+possible or not practical to make a run time determination about some
+functionality of the hardware or a required software feature or similar. Each of
+these has their own places where they are better suited than the other for use.
+The `Kconfig language
+<https://www.kernel.org/doc/html/latest/kbuild/kconfig-language.html>`_ is well
+documented and used in a number of projects, including the Linux kernel. We
+implement this with the Kconfig files found throughout our sources. This
+mechanism is the preferred way of exposing new configuration options as there
+are a number of ways for both users and system integrators to manage and change
+these options. Some common examples here are to enable a specific command within
+U-Boot or even a whole subsystem such as NAND flash or network connectivity.
+The ``CFG`` mechanism is implemented directly as C preprocessor values or
+macros, depending on what they are in turn describing. While we have some
+functionality that is very reasonable to expose to the end user to enable or
+disable we have other places where we need to describe things such as register
+locations or values, memory map ranges and so on. When practical, we should be
+getting these values from the device tree. However, there are cases where this
+is either not practical due to when we need the information and may not have a
+device tree yet or due to legacy reasons code has not been rewritten.
+When to use each mechanism
+While there are some cases where it should be fairly obvious where to use each
+namespace, as for example a command would done via Kconfig, a new i2c driver
+should use Kconfig and be configured via driver model and a header of values
+generated by an external tool should be ``CFG``, there will be cases where it's
+less clear and one needs to take care when implementing it. In general,
+configuration *options* should be done in Kconfig and configuration *settings*
+should done in driver model or ``CFG``. Let us discuss things to keep in mind
+when picking the appropriate mechanism.
+A thing to keep in mind is that we have a strong preference for using Kconfig as
+the primary build time configuration mechanism. Options expressed this way let
+us easily express dependencies and abstractions. In addition, given that many
+projects use this mechanism means it has a broad set of tooling and existing
+knowledge base.
+Consider the example of a SHA256 hardware acceleration engine. This would be a
+feature of the SoC and so something to not ask the user if it exists, but we
+would want to have our generic framework for such engines be optionally
+available and depend on knowing we have this engine on a given hardware
+platform. Expressing this should be done as a hidden Kconfig symbol that is
+``select``'ed by the SoC symbol which would in turn be ``select``'ed by the
+board option, which is user visible. Hardware features that are either present
+or not present should be expressed in Kconfig and in a similar manner, features
+which will always have a constant value such as "this SoC always has 4 cores and
+4 threads per core" should be as well.
+This brings us to differentiating between a configuration *setting* versus a
+hardware feature. To build on the previous example, while we may know the number
+of cores and threads, it's possible that within a given family of SoCs the base
+addresses of peripherals has changed, but the register offsets within have not.
+The preference in this case is to get our information from the device tree and
+perform run time configuration. However, this is not always practical and in
+those cases we instead rely on the ``CFG`` mechanism. While it would be possible
+to use Kconfig in this case, it would result in using calculated rather than
+constructed values, resulting in less clear code. Consider the example of a set
+of register values for a memory controller. Defining this as a series of logical
+ORs and shifts based on other defines is more clear than the Kconfig entry that
+set the calculated value alone.
+When it has been determined that the practical solution is to utilize the
+``CFG`` mechanism, the next decision is where to place these settings. It is
+strongly encouraged to place these in the architecture header files, if they are
+generic to a given SoC, or under the board directory if board specific. Placing
+them under the board.h file in the *include/configs/* directory should be seen
+as a last resort.

More information about the U-Boot mailing list