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