1.. zephyr:code-sample:: clock-control-litex 2 :name: LiteX clock control driver 3 :relevant-api: clock_control_interface 4 5 Use LiteX clock control driver to generate multiple clock signals. 6 7Introduction 8************ 9 10This sample is providing an overview of LiteX clock control driver capabilities. 11The driver uses Mixed Mode Clock Manager (MMCM) module to generate up to 7 clocks with defined phase, frequency and duty cycle. 12 13Requirements 14************ 15* LiteX-capable FPGA platform with MMCM modules (for example Digilent Arty A7 development board) 16* SoC configuration with VexRiscv soft CPU and Xilinx 7-series MMCM interface in LiteX (S7MMCM module) 17* Optional: clock output signals redirected to output pins for testing 18 19Configuration 20************* 21Basic configuration of the driver, including default settings for clock outputs, is held in Device Tree clock control nodes. 22 23.. literalinclude:: ../../../dts/riscv/riscv32-litex-vexriscv.dtsi 24 :language: dts 25 :start-at: clk0: clock-controller@0 { 26 :end-at: }; 27 :dedent: 28 29.. literalinclude:: ../../../dts/riscv/riscv32-litex-vexriscv.dtsi 30 :language: dts 31 :start-at: clk1: clock-controller@1 { 32 :end-at: }; 33 :dedent: 34 35.. literalinclude:: ../../../dts/riscv/riscv32-litex-vexriscv.dtsi 36 :language: dts 37 :start-at: clock0: clock@e0004800 { 38 :end-at: }; 39 :dedent: 40 41This configuration defines 2 clock outputs: ``clk0`` and ``clk1`` with default frequency set to 100MHz, 0 degrees phase offset and 50% duty cycle. Special care should be taken when defining values for FPGA-specific configuration (parameters from ``litex,divclk-divide-min`` to ``litex,vco-margin``). 42 43**Important note:** ``reg`` properties in ``clk0`` and ``clk1`` nodes reference the clock output number (``clkout_nr``) 44 45Driver Usage 46************ 47 48The driver is interfaced with the :ref:`Clock Control API <clock_control_api>` function ``clock_control_on()`` and a LiteX driver specific structure (:c:struct:`litex_clk_setup`). 49 50| To change clock parameter it is needed to cast a pointer to structure :c:struct:`litex_clk_setup` onto :c:type:`clock_control_subsys_t` and use it with :c:func:`clock_control_on()`. 51| This code will try to set on ``clk0`` frequency 50MHz, 90 degrees of phase offset and 75% duty cycle. 52 53.. code-block:: c 54 55 struct device *dev; 56 int ret; 57 struct litex_clk_setup setup = { 58 .clkout_nr = 0, 59 .rate = 50000000, 60 .duty = 75, 61 .phase = 90 62 }; 63 dev = DEVICE_DT_GET(MMCM); 64 clock_control_subsys_t sub_system = (clock_control_subsys_t)&setup; 65 if ((ret = clock_control_on(dev, sub_system)) != 0) { 66 LOG_ERR("Set CLKOUT%d param error!", setup.clkout_nr); 67 return ret; 68 } 69 70Clock output status (frequency, duty and phase offset) can be acquired with function ``clock_control_get_status()`` and clock output frequency only can be queried with ``clock_control_get_rate()`` 71 72In both getter functions, basic usage is similar to ``clock_control_on()``. Structure ``litex_clk_setup`` is used to set ``clkout_nr`` of clock output from which data is to be acquired. 73 74Sample usage 75************ 76 77This example provides a simple way of checking various clock output settings. User can pick one of 4 possible scenarios: 78 79* Frequency range, 80* Duty cycle range, 81* Phase range, 82* Setting frequency, duty and phase at once, then check clock status and rate, 83 84Scenarios are selected by defining ``LITEX_CLK_TEST`` as one of: 85 86* ``LITEX_TEST_FREQUENCY`` 87* ``LITEX_TEST_DUTY`` 88* ``LITEX_TEST_PHASE`` 89* ``LITEX_TEST_SINGLE`` 90 91Code is performed on 2 clock outputs with ``clkout_nr`` defined in ``LITEX_CLK_TEST_CLK1`` and ``LITEX_CLK_TEST_CLK2``. Tests are controlled by separate defines for each scenario. 92 93Building 94******** 95 96.. code-block:: none 97 98 west build -b litex_vexriscv zephyr/samples/drivers/clock_control 99 100Drivers prints a lot of useful debugging information to the log. It is highly recommended to enable logging and synchronous processing of log messages and set log level to ``Info``. 101 102Sample output 103************* 104 105.. code-block:: none 106 107 [00:00:00.200,000] <inf> CLK_CTRL_LITEX: CLKOUT0: set rate: 100000000 HZ 108 [00:00:00.240,000] <inf> CLK_CTRL_LITEX: CLKOUT1: updated rate: 100000000 to 100000000 HZ 109 [00:00:00.280,000] <inf> CLK_CTRL_LITEX: CLKOUT0: set duty: 50% 110 [00:00:00.320,000] <inf> CLK_CTRL_LITEX: CLKOUT0: set phase: 0 deg 111 [00:00:00.360,000] <inf> CLK_CTRL_LITEX: CLKOUT1: set rate: 100000000 HZ 112 [00:00:00.400,000] <inf> CLK_CTRL_LITEX: CLKOUT1: set duty: 50% 113 [00:00:00.440,000] <inf> CLK_CTRL_LITEX: CLKOUT1: set phase: 0 deg 114 [00:00:00.440,000] <inf> CLK_CTRL_LITEX: LiteX Clock Control driver initialized 115 *** Booting Zephyr OS build zephyr-v2.2.0-2810-g1ca5dda196c3 *** 116 Clock Control Example! riscv32 117 device name: clock0 118 clock control device is 0x40013460, name is clock0 119 Clock test 120 Single test 121 [00:00:00.510,000] <inf> CLK_CTRL_LITEX: CLKOUT0: set rate: 15000000 HZ 122 [00:00:00.550,000] <inf> CLK_CTRL_LITEX: CLKOUT0: set phase: 90 deg 123 [00:00:00.590,000] <inf> CLK_CTRL_LITEX: CLKOUT0: set duty: 25% 124 [00:00:00.630,000] <inf> CLK_CTRL_LITEX: CLKOUT1: set rate: 15000000 HZ 125 [00:00:00.670,000] <inf> CLK_CTRL_LITEX: CLKOUT1: set duty: 75% 126 Getters test 127 CLKOUT0: get_status: rate:15000000 phase:90 duty:25 128 CLKOUT0: get_rate:15000000 129 CLKOUT1: get_status: rate:15000000 phase:0 duty:75 130 CLKOUT1: get_rate:15000000 131 Clock test done returning: 0 132 133References 134********** 135- :ref:`litex-vexriscv` 136