On 7/28/22 20:53, Tom Rini wrote:
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 <tr...@konsulko.com>
---
RFCv2:
- 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
   well.
- 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
   configuration.

RFCv1:
- 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 | 121 +++++++++++++++++++++++++++
  3 files changed, 122 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
-  "CONFIG_SYS_".
-
-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
-build.
-
-
  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
     designprinciples
     process
     release_cycle
+   system_configuration

  Implementation
  --------------
diff --git a/doc/develop/system_configuration.rst 
b/doc/develop/system_configuration.rst
new file mode 100644
index 000000000000..bb09d1f974d4
--- /dev/null
+++ b/doc/develop/system_configuration.rst
@@ -0,0 +1,121 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+U-Boot system configuration

Thanks Tom for adding this helpful text on configuration. Overall we
should even more move the focus from "namespace" to configuration
mechanism. See below.


%s/U-Boot system/System/

We know that we are talking about U-Boot.

+===========================
+
+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 is preferred over build time. But when making these

%s/run time/run time configuration/
%s/build time/build time configuration/

+decision, we also need to consider if we're talking about feature that could be

%s/decision/decisions/

%s/feature/a feature/

+useful to virtually every platform or something specific to a single hardware
+platform. The resulting image size is also another important consideration.
+Finally, the overall requirements of being able to do run time detection will
+have an impact on if it's possible or not.

I guess you mean that run time detection is not always feasible? How about:

"Run time detection depends on the physical hardware and may not always
be possible."

+
+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
+is:
+
+#. Simple run time. One example here are chip revision checks. Another is

%s/Simple run time\./Run time feature detection./

+   knowing that we've checked GPIOs and are on revision B of a platform, rather

Do you mean: "On some boards the revision may be detected by reading
GPIOs."?

+   than doing a more expensive device tree check. This allows us to use a 
single
+   device tree for revision A and B in this case and perform fixups as needed
+   rather than storing two device trees.
+
+#. Making use of our Kconfig infrastructure and the ``CONFIG`` namespace. The
+   primary method of build time configuration is done via the ``CONFIG``
+   namespace and Kconfig infrastructure. 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.
+
+#. 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 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 the ``CFG`` namespace. This is
+   useful when for various reasons we cannot get configuration values that we
+   need from the device tree so instead have them defined in a header and use
+   the prefix ``CFG_`` in their definition.
+
+Dynamic run time configuration methods.
+---------------------------------------
+
+For more information in general on how to make use of this please start with 
the
+:doc:`driver model <driver-model/index>` documentation.
+
+Static build time configuration methods
+---------------------------------------
+
+There are two namespaces used to control the build time configuration of

The focus on the word 'namespaces' does not provide clarity here. The
choice is between:

* defining configuration variables via Kconfig
* defining configuration variables via headers files

The namespace thing is secondary to this choice.

+U-Boot, ``CONFIG`` and ``CFG``. 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 first of these, ``CONFIG``` is managed in the `Kconfig language
+<https://www.kernel.org/doc/html/latest/kbuild/kconfig-language.html>`_ that is
+most commonly associated with the Linux kernel and the Kconfig files found
+throughout our sources. Adding options to this namespace 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 second of these, ``CFG`` is implemented directly as C preprocessor values 
or
+macros, depending on what they are in turn describing. The nature of U-Boot
+means that while we have some functionality that is very reasonable to expose 
to

%s/The nature of U-Boot means that while/While/

The removed words do not add clarity.

+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,

%s/tree \./tree./

+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 namespace
+^^^^^^^^^^^^^^^^^^^^^^^^^^

The paragraphs below are not about namespaces but about when to use
Kconfig and when to use arch/Soc/board specific constants defined in
headers.

+
+While there are some cases where it should be fairly obvious where to use each
+namespace, as for example a command would be ``CONFIG`` 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. In general,
+configuration *options* should be ``CONFIG`` and configuration *settings* 
should
+be ``CFG``. Since it is not always clear however, let us discuss things to
+keep in mind when adding to either namespace.

Why can't we make this is a hard rule:

If it is in Kconfig it is CONFIG_.
It is is not in Kconfig it is CFG_

Nothing comes to my mind where such a rule cannot be applied.

+
+A thing to keep in mind is that we have a strong preference for using the
+``CONFIG`` namespace first. Options expressed this way let us make use of the

The usage of namespace is irritating me here.

"We prefer to use Kconfig."

Best regards

Heinrich


+Kconfig language to express dependencies and abstractions. 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 symbol that is ``select``'ed by the SoC symbol which would in turn
+be ``select``'ed by the board option, which is user visible. This means that
+hardware features that are either present or not present should be in the
+``CONFIG`` namespace 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.
+And for practical reasons, we cannot get this information at run time from the
+device tree. This is a case where it is reasonable to instead make use of the
+``CFG`` namespace and that it is pure C preprocessor macros to define that
+``CFG_SYS_FOO_REG`` is ``(CFG_SYS_FOO_BASE + 0x200)`` and have blocks of those
+under ``#if defined(CONFIG_SOC_FOO1) ... #elif defined(CONFIG_SOC_FOO2) ...
+#endif`` in a system header file. Another example here is register values. 
Often
+it will make the most sense to construct these from other values and then using
+masks and shifts to turn a list of "magic values" in to something that is 
easier
+for humans to parse as well.
+
+When it has been determined that the practical solution for where to have
+something is in the ``CFG`` namespace, 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.

Reply via email to