.. _SD.Clocks:

.. include:: /content/swdocs.rsts

.. spelling::
   actmon
   bpmp
   clk
   debugfs
   devfreq
   gp
   gv
   knobpath
   Pathnames
   screenful
   undistinctive
   userspace
   wmark

Clocks
!!!!!!

|NVIDIA(r)| |Jetson(tm)| Board Support Package (BSP) supports configuring Jetson clocks and peripheral clocks through software. This topic describes how to check clock status, get maximum rates for clocks, and configure clock sources for |NVIDIA(r)| Jetson Xavier NX series, |NVIDIA(r)| Jetson AGX Xavier series, and |NVIDIA(r)| Jetson AGX Orin family series devices.

.. note::
   For information about available Jetson clock sources and capabilities, see the “Clock and Reset Controller” section of the `Technical Reference Manual <https://developer.nvidia.com/embedded/downloads#?search=technical%20reference%20manual>`__ (TRM) for your Jetson processor. This section of the TRM also describes clock source multiplexers and provides descriptions of available clock sources for each component.

Linux kernel supports the common clock framework (CCF) from version 4.9. As a result:

- All device drivers use the public CCF API defined by ``include/linux/clk.h`` and
  ``include/linux/clk-provider.h``, including functions such as ``clk_get()``, ``clk_enable()``, ``devm_clk_get()``, ``clk_prepare_enable()``, ``clk_prepare_disable()``, ``clk_disable()``, and others, instead of device-specific APIs.

- All clock drivers, including the Jetson custom clk driver, implement the structure ``clk_ops``.

- Clock sources and clocks required by devices are defined in the device tree.

- Clocks are controlled by an R5 called the Boot and Power Management Processor.
  It runs RTOS software from ``bpmp.bin``. The Linux kernel running on CCPLEX requests this software for clock programming.

The |NVIDIA(r)| |Jetson(tm)| Linux clock driver wrapper is available at ``nvidia/drivers/clk/tegra/``.

To check clock status
@@@@@@@@@@@@@@@@@@@@@

On the device, enter the following command to launch debugfs and check the clock::

    $ sudo -s
    # cat /sys/kernel/debug/bpmp/debug/clk/clk_tree

This is a portion of example of ``debugfs`` output from the above command on the |NVIDIA(r)| |Jetson AGX Xavier(tm)| device::

    clock                                             on       rate bpmp  mrq vdd
    -----------------------------------------------------------------------------
    clk_m                                              1   19200000    8    1
        actmon                                         1   19200000    1    1
        cec                                            1   19200000    1    1
        hda2hdmicodec                                  0   19200000    0    0
        kfuse                                          0   19200000    0    0
        rce_cpu_nic                                    1   19200000    2    1
            rce_nic                                    1    4800000    2    1
        sce_cpu_nic                                    1   19200000    1    0
            sce_nic                                    1   19200000    1    0
        sor0_ref                                       0   19200000    0    0
        sor1_ref                                       0   19200000    0    0
        tach                                           1    1010526    1    1 vdd_core@634570
        ufsdev_ref                                     0   19200000    0    0
        sor3_ref                                       0   19200000    0    0
        nvlink_sys                                     0   19200000    0    0
        nvlink_tx                                      1   19200000    1    0 vdd_nvhs@1000000
            nvlink_rx                                  1   19200000    1    0 vdd_nvhs@1000000

Overriding Default Clock Rates
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

The default clock rate of each component is set during system boot time and updated under control of the Jetson custom clk driver by sending requests to the BPMP to adjust the clock rate. The ``debugfs`` affords a way to override the default clock rate and set a fixed clock rate. However, you should use ``debugfs`` for debugging and experimental purposes only.

Here is an example to check the clock-specific attributes of the ``emc`` clock node under the ``debugfs``::

    # cd /sys/kernel/debug/bpmp/debug/clk
    # ls emc

    dvfs        flags   max_rate  mrqcount         parent       rate      state
    dvfs_table  hz_off  min_rate  mrq_rate_locked  pto_counter  refcount  vdd_core

You can use these attributes to change the clock parent, clock rate, and so on.

For example, you can override the `emc` rate by entering these commands::

    # echo 1 > /sys/kernel/debug/bpmp/debug/clk/emc/mrq_rate_locked
    # echo 1 > /sys/kernel/debug/bpmp/debug/clk/emc/state
    # echo x > /sys/kernel/debug/bpmp/debug/clk/emc/rate

The ``x`` value in the third command can be any value between the ``min_rate`` and the ``max_rate``.

Configuring GPU Clocks
@@@@@@@@@@@@@@@@@@@@@@

With GPU `DVFS <#frequency-boost-feature>`__ enabled using the devfreq framework, GPU frequency changes
based on load. You can run the GPU at a fixed frequency instead if necessary.

To run the GPU at a fixed frequency
###################################

#. Enter one of these commands:

   - For the GPU on the Jetson AGX Orin series devices::

        # cd /sys/devices/17000000.ga10b/devfreq/17000000.ga10b/

   - For the GPU on the Jetson AGX Xavier series devices::

        # cd /sys/devices/17000000.gv11b/devfreq/17000000.gv11b/

#. List the available frequencies::

    # cat available_frequencies

   The command displays a list of available frequencies like this::

    114750000 216750000 318750000 420750000 522750000 624750000 675750000 828750000 905250000 1032750000 1198500000 1236750000 1338750000 1377000000

#. Fix the frequency.

   - To fix the frequency at the maximum supported value::

        # echo <max> min_freq

     Where ``<max>`` in the maximum supported frequency. For example, to fix the frequency at the maximum supported frequency from the list in step 2::

        # echo 1377000000> min_freq

   - To fix the frequency at any other supported value::

        # echo <freq> > min_freq
        # echo <freq> > max_freq

     Where ``<freq>`` in the desired frequency range.

     For example, to fix the frequency at 828750000::

        # echo 828750000 > min_freq
        # echo 828750000 > max_freq

Configuring VIC Clocks
@@@@@@@@@@@@@@@@@@@@@@

**Video Image Compositor** (VIC) provides a set of video processing
services, including geometry transform processing for lens distortion
correction and temporal noise reduction. The VIC voltage and frequency
are dynamically scaled to conserve power, based on utilization as
measured by the **activity monitor** (actmon).

For more information about VIC, see the “Video Image Compositor” section in the
`Technical Reference Manual <https://developer.nvidia.com/embedded/downloads#?search=technical%20reference%20manual>`__
(TRM) for your Jetson processor.

VIC Dynamic Voltage and Frequency Scaling
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

.. _dvfs:

**VIC actmon** is a hardware block which monitors VIC active cycles in a
fixed time window. It works with the ``wmark_active`` devfreq governor to
perform **dynamic voltage and frequency scaling** (DVFS) operations for VIC.

``wmark_active`` tries to keep the **current load** (the ratio of
VIC active cycle to total cycle, scaled to [0, 1000]) within a certain
percentage range. It sets upper and lower bounds for the current load.
When current load goes outside these bounds, VIC actmon raises an
interrupt which causes ``wmark_active`` to raise the VIC frequency, reducing
the current load, or lower the frequency, increasing it.

The control logic in wmark_active is:

.. _current-load:

#. Compute the current load:

        :math:`\text{cur}{r\_ load}_{} = \ \frac{\text{VIC}\ \text{active}\ \text{cycle}}{\text{VIC}\ \text{total}\ \text{cycle}\ @\text{current}\ \text{frequency}}*1000`

#. If (*freq_boost_en* && *curr_load* >= *load_max*):

        :math:`curr\_ ideal\_ freq = \ F_{\max}`

   else:

        :math:`curr\_ ideal\_ freq = \ \frac{curr\_ load}{load\_ target}*curr\_ freq`

        :math:`\text{av}{g\_ target\_ freq}_{\text{current}} = \ \frac{\text{smooth}}{\text{smooth}\  + \ 1}*\text{av}{g\_ target\_ freq}_{\text{previous}} + \ \frac{1}{\text{smooth}\  + \ 1}*\text{cur}{r\_ ideal\_ freq}_{}`

   Where:

   - *curr_load* is the current load.

   - *freq_boost_en* is a knob which enables or disables the `frequency boost <#frequency-boost-feature>`__ feature.

   - *F*\ :sub:`max` is the maximum possible VIC frequency.

   - *load_max* is the **frequency boost threshold**. Its range is [0, 1000]. ``wmark_active`` boosts the VIC frequency to *F*\ :sub:`max` when *load_level* exceeds this threshold.

   .. _load-target:

   - *load_target* (the **load target**) is the value of *curr_load* that ``wmark_active`` tries to maintain.

   - *curr_freq* is the current VIC frequency, in hertz.

   - *curr_ideal_freq* is the VIC frequency, in hertz, that would yield a *curr_load* value of *load_target* under current instantaneous operating conditions.

   - *avg_target_freq* is the moving average of the target frequency, in
     hertz. It is used to avoid abrupt changes in *curr_freq* when it is recalculated. This property is described more fully in
     `To customize VIC DVFS with control knobs <#to-customize-vic-dvfs-with-control-knobs>`__.

Select the first available frequency step that is greater than or equal to *avg_target_freq*\ :sub:`current`.

Sysfs Paths for DVFS Control
@@@@@@@@@@@@@@@@@@@@@@@@@@@@

This section describes the use of several knobs that control the
operation of VIC DVFS.

Pathnames of Sysfs Nodes for DVFS Control
#########################################

The sysfs nodes that control VIC knobs are located in a pair of
directories whose locations are device-dependent. The descriptions
that follow use these placeholders to represent those directories:

- For |NVIDIA(r)| Jetson AGX Orin family series:

  - ``<knobpath>`` represents ``/sys/devices/platform/13e40000.host1x/15340000.vic``.

  - ``<knobpath_devfreq>`` represents ``/sys/devices/platform/13e40000.host1x/15340000.vic/devfreq/15340000.vic``

- For |NVIDIA(r)| |Jetson Xavier(tm) NX| series and Jetson AGX Xavier series:

  - ``<knobpath>`` represents ``/sys/devices/platform/13e10000.host1x/15340000.vic/``.

  - ``<knobpath_devfreq>`` represents ``/sys/devices/platform/13e10000.host1x/15340000.vic/devfreq/15340000.vic``

In the following procedures, replace these placeholders with the appropriate pathnames for your Jetson device.

VIC DVFS Control Terminology
############################

Many of the control knobs concern the `current load <#current-load>`__ and the `load target <#load-target>`__.  The default load target is 700, i.e. ``wmark_active`` tries to keep the VIC active cycle at 70% of the current VIC frequency.

A lower load target makes VIC frequency scaling more aggressive, because the VIC frequency scales up to *F*\ :sub:`max` when the VIC active cycle exceeds (load target / 1000) |times| *F*\ :sub:`max`.

To enable or disable VIC DVFS
#############################

VIC DVFS is enabled by default. You can disable VIC DVFS by changing the underlying devfreq governor to ``userspace`` governor for the VIC engine.

Here is an example to change the devfreq governor of the VIC engine::

    $ echo <gov> > <knobpath_devfreq>/governor

Where ``<gov>`` is the name of the VIC devfreq governor to be used:

- To enable VIC DVFS, type ``wmark_active`` for the ``<gov>``
- To disable VIC DVFS, type ``userspace`` for the ``<gov>``

To customize VIC DVFS with control knobs
########################################

- The ``block_window`` control knob defines the shortest period between VIC frequency scaling operations, in microseconds. VIC actmon skips frequency scaling if the last VIC frequency scaling operation was performed less than ``block_window`` microseconds ago.

  To set ``block_window``, enter the command::

    $ echo <period> > <knobpath>/block_window

  Where ``<period>`` is the ``block_window`` value to set.

- The ``load_target`` control knob sets the VIC load target. To set the load_target, enter the command::

    $ echo <target> > <knobpath>/load_target

  Where ``<target>`` is the load target to set. The value range for the ``<target>`` is between 0 and 1000.

.. _frequency-boost-feature:

- The ``freq_boost_en`` control knob enables or disables the **frequency
  boost** feature. If frequency boost is enabled, ``wmark_active`` boosts the VIC frequency to *F*\ :sub:`max` when the VIC load level exceeds the frequency boost threshold (set by the ``load_max`` control knob, below).

  To enable or disable frequency boost, enter the command::

    $ echo <b> > <knobpath>/freq_boost_en

  Where ``<b>`` is 1 to enable frequency boost, or 0 to disable it.

- The ``load_max`` control knob sets the **frequency boost threshold**.
  ``wmark_active`` boosts the VIC frequency to *F*\ :sub:`max` when the VIC load level exceeds the frequency boost threshold. Its range is [0, 1000]. Its default value is 900.

  Note that ``wmark_active`` boosts the VIC frequency only if ``freq_boost_en`` (above) is enabled.

  To set the frequency boost threshold, enter the command::

    $ echo <max> > <knobpath>/load_max

  Where ``<max>`` is the frequency boost threshold to set.

- *curr_ideal_freq* is the VIC frequency, in hertz, that would yield a
  *curr_load* value of *load_target* under current instantaneous operating conditions.

- *avg_target_freq* is the average target frequency, in hertz. That is, it is a
  moving average of the target frequency, in hertz.

  The ``smooth`` knob adjusts the weights that *avg_target_freq*\ :sub:`previous` and *curr_ideal_freq* are given in adjusting the value of *avg_target_freq* toward the target frequency:

    :math:`{\text{avg}\_\text{target}\_\text{freq}}_{\text{current}} = \ \frac{\text{smooth}}{\text{smooth}\  + \ 1}*{\text{avg}\_\text{target}\_\text{freq}}_{\text{previous}}\  + \ \frac{1}{\text{smooth}\  + \ 1}*\text{curr}\_\text{ideal}\_\text{freq}`

  If ``smooth`` is 0, the weight of *avg_target_freqprevious* is 0% and the weight of *curr_ideal_freq* is 100%, so *avg_target_freqcurrent* is set to *curr_ideal_freq* each time it is adjusted.

  To set smooth, enter the command::

    $ echo <value> > <knobpath>/smooth

  Where ``<value>`` is the value to set.

Setting the Static VIC Frequency
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

For debugging or power/performance evaluation, you may want to set the
VIC frequency to a fixed value. You can set the **static VIC frequency**
directly if you disable VIC DVFS.

.. _SD.Clocks.SettingTheStaticVicFrequency.ToSetTheStaticVicFrequency:

To set the static VIC frequency
###############################

#. Disable VIC runtime power management (PM) suspend. This forces the
   VIC hardware block into a power-on state so that you can configure
   the VIC frequency with commands::

    $ echo on > <knobpath>/power/control

#. Read the runtime status::

    $ cat <knobpath>/power/runtime_status

   The command should display a runtime status of *active*.

#. Disable VIC DVFS::

    $ echo userspace > <knobpath_devfreq>/governor

#. Check the available VIC frequency settings::

    $ cat <knobpath_devfreq>/available_frequencies

   The command lists the available frequencies like this::

    115200000 268800000 409600000 550400000 691200000 844800000 985600000 1036800000

#. Choose one of the available frequencies, and set the VIC maximum
   frequency and the VIC frequency to that value::

    $ echo <frequency> > <knobpath_devfreq>/max_freq
    $ echo <frequency> > <knobpath_devfreq>/userspace/set_freq

#. Enable VIC runtime PM suspend::

    $ echo auto > <knobpath>/power/control

.. _SD.Clocks.ConfiguringClocks:

Configuring Clocks
@@@@@@@@@@@@@@@@@@

In general, each block or module has a dedicated clock source register. For detailed information about a given register, see your Jetson device's
`Technical Reference Manual <https://developer.nvidia.com/embedded/downloads#?search=technical%20reference%20manual>`__
for information about ``CLK_RST_CONTROLLER_CLK_SOURCE_<module_name>``.

Clock source registers provide clock source selection and clock divider
control for the module. The divider is typically 8 bits: 7 integer bits
and 1 fractional bit (U7.1).

To change clock configurations in the kernel device driver module
#################################################################

#. Declare the clocks in the device tree. For example, for ``padctl-uphy``, clocks
   can be declared like this::

    clocks = <&tegra_car TEGRA210_CLK_HSIC_TRK>,
            <&tegra_car TEGRA210_CLK_USB2_TRK>,
            <&tegra_car TEGRA210_CLK_PLL_E>;
    clock-names = "hsic_trk", "usb2_trk", "pll_e";

#. Use ``devm_clk_get()`` to obtain the desired clock source using ``clock-names``.

#. Use ``clk_get_parent()`` to obtain the parent clock for the desired clock.

#. Use ``clk_set_parent()`` to select the specified clock source for the target clock.

#. Use ``clk_set_rate()`` to set the frequency of the target clock.

   The divider is calculated automatically according to the target rate. Successful clock frequency settings must meet use one of the available dividers of that module and the frequency of the clock source.

#. Use ``clk_round_rate()`` to get the exact clock frequency that can be configured from the current clock source.

#. Use ``clk_prepare_enable()``, or ``clk_prepare()`` and ``clk_enable()``, to enable the clock. You can use ``clk_prepare()`` instead of ``clk_enable()`` to enable a clock if the operation may sleep.


To use PLLAON as clock source
#############################

To conserve power, the PLLAON clock is disabled by default on Jetson devices with T194 processors.

You may want to enable PLLAON to obtain a higher clock rate or greater accuracy in certain use cases like high speed communication between controllers in controller-area-network(CAN). You can do this by first adding PLLAON as a possible parent of a clock, then setting the parent of the clock to PLLAON.

You make these changes by modifying the BPMP firmware DTB and kernel DTB files. The BPMP firmware DTB holds the configuration for clocks; the kernel DTB contains the setting that enables and disables PLLAON.

Taking the CAN use case as an example, follow these steps to add PLLAON as a possible parent:

#. Convert the BPMPFW DTB (e.g. ``tegra194-a02-bpmp-p2888-a04.dtb``) to a DTS
   using the ``dtc`` tool.

#. Edit the DTS file to add the PLLAON clock ID to the list of possible parents.

   In the DTS file under clocks, add the clock ID for PLLAON (symbol ``CLK_PLLAON``, decimal 94, hex ``0x5e``), to the allowed-parents list::

    clocks {
        clock@can1 {
            clk-id = <9>;                       /* confirming TEGRA194_CLK_CAN1 */
            allowed-parents <nn,nn,nn,...,94>;  /* TEGRA194_CLK_PLLAON */
        };
        ...
    };

   This allows PLLAON to be set as parent of CAN1.

#. Convert the DTS file back to a DTB.

#. Convert the kernel DTB (e.g, ``tegra194-p2888-0001-p2822-0000.dtb``) to a
   DTS file using ``dtc``, or obtain the kernel’s source DTS file.

#. Edit the kernel DTS file to make CAN use PLLAON as parent and remove
   PLLAON (entry ``0x4 0x5e``) from the list of clocks to be disabled::

    clocks-init {
        compatible = "nvidia,clocks-config";
        disable {
            /* Edit clocks property to remove clock provider + clock id pair for
             PLLAON. */
            clocks = <nn nn, nn nn,...>;
        };
    };

#. To change the ``mttcan`` node to select PLLAON as parent, add ``"pllaon"``
   to the list in ``clock-names``, and add an entry for ``0x4 0x5e`` to the list in ``clocks``::

    mttcan@c310000 {
        pll_source = "pllaon";
        clocks = <..., 0x4 0x5e>;       /*New entry*/
        clock-names = <name>, <name>, <name>, ..., "pllaon";
    };

#. Convert the DTS file to DTB, or build the kernel DTB if you edited the source files.

#. Flash the board with the modified DTB files.

Clocks that Can Have PLLAON as Parent
#####################################

The following clocks can be configured to have PLLAON as a parent:

- ``TEGRA194_CLK_CAN1``
- ``TEGRA194_CLK_CAN2``
- ``TEGRA194_CLK_DMIC5``
- ``TEGRA194_CLK_I2C2``
- ``TEGRA194_CLK_I2C8``
- ``TEGRA194_CLK_PWM4``
- ``TEGRA194_CLK_SPI2``
- ``TEGRA194_CLK_UARTG``
