doc/hardware/porting/soc_porting.rst
.. _soc_porting_guide:
SoC Porting Guide ###################
This page describes how to add support for a new :term:SoC in Zephyr, be it in
the upstream Zephyr project or locally in your own repository.
SoC Definitions
It is expected that you are familiar with the board concept in Zephyr.
A high level overview of the hardware support hierarchy and terms used in the
Zephyr documentation can be seen in :ref:hw_support_hierarchy.
For SoC porting, the most important terms are:
See :ref:architecture_porting_guide.
Create your SoC directory
Each SoC must have a unique name. Use the official name given by the SoC vendor
and check that it's not already in use. In some cases someone else may have
contributed a SoC with identical name. If the SoC name is already in use, then
you should probably improve the existing SoC instead of creating a new one.
The script list_hardware can be used to retrieve a list of all SoCs known
in Zephyr, for example ./scripts/list_hardware.py --soc-root=. --socs from
the Zephyr base directory for a list of names that are already in use.
Start by creating the directory zephyr/soc/<VENDOR>/soc1, where
<VENDOR> is your vendor subdirectory.
.. note::
A <VENDOR> subdirectory is mandatory if contributing your SoC
to Zephyr, but if your SoC is placed in a local repo, then any folder
structure under <your-repo>/soc is permitted.
The <VENDOR> subdirectory must match a vendor defined in the list in
:zephyr_file:dts/bindings/vendor-prefixes.txt. If the SoC vendor does not
have a prefix in that list, then one must be created.
.. note::
The SoC directory name does not need to match the name of the SoC. Multiple SoCs can even be defined in one directory. In Zephyr, SoCs are often organized in sub-folders in a common SoC Family or SoC Series tree.
Your SoC directory should look like this:
.. code-block:: none
soc/<VENDOR>/<soc-name> ├── soc.yml ├── soc.h ├── CMakeLists.txt ├── Kconfig ├── Kconfig.soc └── Kconfig.defconfig
Replace <soc-name> with your SoC's name.
The mandatory files are:
#. :file:soc.yml: a YAML file describing the high-level meta data of the
SoC such as:
#. :file:soc.h: a header file which can be used to describe or provide
configuration macros for the SoC. The :file:soc.h will often be included in
drivers, sub-systems, boards, and other source code found in Zephyr.
#. :file:Kconfig.soc: the base SoC configuration which defines a Kconfig SoC
symbol in the form of config SOC_<soc-name> and provides the SoC name to
the Kconfig SOC setting.
If the soc.yml describes a SoC family and series, then those must also
be defined in this file. Kconfig settings outside of the SoC tree must not be
selected. To select general Zephyr Kconfig settings the :file:Kconfig file
must be used.
#. :file:CMakeLists.txt: CMake file loaded by the Zephyr build system. This
CMake file can define additional include paths and/or source files to be used
when a build targets the SoC. Also the base line linker script to use must be
defined.
The optional files are:
Kconfig, :file:Kconfig.defconfig software configuration in
:ref:kconfig format. These select the architecture and peripherals
available.Write your SoC YAML
The SoC YAML file describes the SoC family, SoC series, and SoC at a high level.
Detailed configurations, such as hardware description and configuration are done in devicetree and Kconfig.
The skeleton of a simple SoC YAML file containing just one SoC is:
.. code-block:: yaml
socs: - name: <soc1>
It is possible to have multiple SoC located in the SoC folder.
For example if they belong to a common family or series it is recommended to
locate such SoC in a common tree.
Multiple SoCs and SoC series in a common folder can be described in the
:file:soc.yml file as:
.. code-block:: yaml
family: - name: <family-name> series: - name: <series-1-name> socs: - name: <soc1> cpuclusters: - name: <coreA> - name: <coreB> ... - name: <soc2> - name: <series-2-name> ...
Write your SoC devicetree
SoC devicetree include files are located in the :file:<zephyr-repo>/dts folder
under a corresponding :file:<ARCH>/<VENDOR>.
The SoC :file:dts/<ARCH>/<VENDOR>/<soc>.dtsi describes your SoC hardware in
the Devicetree Source (DTS) format and must be included by any boards which use
the SoC.
If a highlevel :file:<arch>.dtsi file exists, then a good starting point is to
include this file in your :file:<soc>.dtsi.
In general, :file:<soc>.dtsi should look like this:
.. code-block:: devicetree
#include <arch>/<arch>.dtsi
/ { chosen { /* common chosen settings for your SoC */ };
cpus {
#address-cells = <m>;
#size-cells = <n>;
cpu@0 {
device_type = "cpu";
compatible = "<compatibles>";
/* ... your CPU definitions ... */
};
soc {
/* Your SoC definitions and peripherals */
/* such as ram, clock, buses, peripherals. */
};
};
.. hint::
It is possible to structure multiple :file:<VENDOR>/<soc>.dtsi files in
sub-directories for a cleaner file system structure. For example organized
pre SoC series, like this: :file:<VENDOR>/<SERIES>/<soc>.dtsi.
Devicetree reflects the hardware. The memory space and peripherals available to
one CPU cluster can be very different from another CPU cluster, therefore each
CPU cluster will often have its own :file:.dtsi file.
CPU cluster :file:.dtsi files should follow the naming scheme
:file:<soc>_<cluster>.dtsi. A :file:<soc>_<cluster>.dtsi file will look
similar to a SoC :file:.dtsi without CPU clusters.
Write Kconfig files
Zephyr uses the Kconfig language to configure software features. Your SoC needs to provide some Kconfig settings before you can compile a Zephyr application for it.
Setting Kconfig configuration values is documented in detail in
:ref:setting_configuration_values.
There is one mandatory Kconfig file in the SoC directory, and two optional files for a SoC:
.. code-block:: none
soc/<vendor>/<your soc> ├── Kconfig.soc ├── Kconfig └── Kconfig.defconfig
:file:Kconfig.soc
A shared Kconfig file which can be sourced both in Zephyr Kconfig and sysbuild
Kconfig trees.
This file selects the SoC family and series in the Kconfig tree and potential other SoC related Kconfig settings. In some cases a SOC_PART_NUMBER. This file must not select anything outside the reusable Kconfig SoC tree.
A :file:Kconfig.soc may look like this:
.. code-block:: kconfig
config SOC_FAMILY_<SOC_FAMILY_NAME>
bool
config SOC_SERIES_<SOC_SERIES_NAME>
bool
select SOC_FAMILY_<SOC_FAMILY_NAME>
config SOC_<SOC_NAME>
bool
select SOC_SERIES_<SOC_SERIES_NAME>
config SOC_FAMILY
default "<soc_family_name>" if SOC_FAMILY_<SOC_FAMILY_NAME>
config SOC_SERIES
default "<soc_series_name>" if SOC_SERIES_<SOC_SERIES_NAME>
config SOC
default "<soc_name>" if SOC_<SOC_NAME>
Notice that SOC_NAME is a pure uppercase version of the SoC name, SOC_SERIES_NAME is
a pure uppercase version of SoC series name and SOC_FAMILY_NAME is a pure uppercase version
of the SoC family name. If these fields do not appear in the :file:soc.yml file then they
should not be present in the :file:Kconfig.soc file.
The Kconfigs SOC, SOC_SERIES and SOC_FAMILY settings are globally defined as
strings and therefore the :file:Kconfig.soc file shall only define the default string values
and not the types. Notice that the string values must match the values used in the
:file:soc.yml file.
.. note::
The build system supports any variation of case for soc_name, soc_series_name and
soc_family_mame, but when submitting boards for inclusion in Zephyr itself, these must be
purely lowercase versions of the Kconfig names
:file:Kconfig
Included by :zephyr_file:soc/Kconfig.
This file can add Kconfig settings which are specific to the current SoC.
The :file:Kconfig will often indicate given hardware support using a setting
of the form HAS_<support>.
.. code-block:: kconfig
config SOC_<SOC_NAME>
select ARM
select CPU_HAS_FPU
If the setting name is identical to an existing Kconfig setting in Zephyr and
only modifies the default value of said setting, then
:file:Kconfig.defconfig should be used instead.
:file:Kconfig.defconfig
SoC specific default values for Kconfig options.
Not all SoCs have a :file:Kconfig.defconfig file.
The entire file should be inside a pair of if SOC_<SOC_NAME> / endif
or if SOC_SERIES_<SERIES_NAME> / endif, like this:
.. code-block:: kconfig
if SOC_<SOC_NAME>
config NUM_IRQS
default 32
endif # SOC_<SOC_NAME>
CPU clusters must provide additional Kconfig settings in the :file:Kconfig.soc
file. This will usually be in the form of SOC_<SOC_NAME>_<CLUSTER> so for
a given soc1 with two clusters clusterA and clusterB, then this
will look like:
SoC's When a SoC defines CPU cluster
.. code-block:: kconfig
config SOC_SOC1_CLUSTERA
bool
select SOC_SOC1
config SOC_SOC1_CLUSTERB
bool
select SOC_SOC1