zephyr/doc/hardware/porting/soc_porting.rst

305 lines
9.5 KiB
ReStructuredText

.. _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:
- SoC: the exact system on a chip the board's CPU is part of.
- SoC series: a group of tightly related SoCs.
- SoC family: a wider group of SoCs with similar characteristics.
- CPU Cluster: a cluster of one or more CPU cores.
- CPU core: a particular CPU instance of a given architecture.
- Architecture: an instruction set architecture.
Architecture
============
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:
- SoC name: the name of the SoC
- CPU clusters: CPU clusters if the SoC contains one or more clusters
- SoC series: the SoC series to which the SoC belong
- SoC family: the SoC family to which the series belong
#. :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:
- :file:`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>
cpucluster:
- 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`.
Multiple CPU clusters
=====================
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 re-usable Kconfig SoC tree.
A :file:`Kconfig.soc` may look like this:
.. code-block:: kconfig
config SOC_<series name>
bool
config SOC_<SOC_NAME>
bool
select SOC_SERIES_<series name>
config SOC
default "SoC name" if SOC_<SOC_NAME>
Notice that ``SOC_NAME`` is a pure upper case version of the SoC name.
The Kconfig ``SOC`` setting is globally defined as a string and therefore the
:file:`Kconfig.soc` file shall only define the default string value and not
the type. Notice that the string value must match the SoC name used in the
:file:`soc.yml` file.
: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>
Multiple CPU clusters
=====================
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