/* * Copyright (c) 2020 Antmicro * * SPDX-License-Identifier: Apache-2.0 */ #include #include #include #include #include /* Test defines */ /* Select clock outputs for tests [0-6] */ #define LITEX_CLK_TEST_CLK1 0 #define LITEX_CLK_TEST_CLK2 1 /* Values for frequency test */ #define LITEX_TEST_FREQUENCY_DUTY_VAL 50 /* [%] */ #define LITEX_TEST_FREQUENCY_PHASE_VAL 0 /* [deg] */ #define LITEX_TEST_FREQUENCY_DELAY_MS 1000 /* [ms] */ #define LITEX_TEST_FREQUENCY_MIN 5000000 /* [Hz] */ #define LITEX_TEST_FREQUENCY_MAX 1200000000 /* [Hz] */ #define LITEX_TEST_FREQUENCY_STEP 1000000 /* [Hz] */ /* Values for duty test */ #define LITEX_TEST_DUTY_FREQ_VAL 20000000 /* [Hz] */ #define LITEX_TEST_DUTY_PHASE_VAL 0 /* [deg] */ #define LITEX_TEST_DUTY_DELAY_MS 250 /* [ms] */ #define LITEX_TEST_DUTY_MIN 0 /* [%] */ #define LITEX_TEST_DUTY_MAX 100 /* [%] */ #define LITEX_TEST_DUTY_STEP 1 /* [%] */ /* Values for phase test */ #define LITEX_TEST_PHASE_FREQ_VAL 25000000 /* [Hz] */ #define LITEX_TEST_PHASE_DUTY_VAL 50 /* [%] */ #define LITEX_TEST_PHASE_DELAY_MS 50 /* [ms] */ #define LITEX_TEST_PHASE_MIN 0 /* [deg] */ #define LITEX_TEST_PHASE_MAX 360 /* [deg] */ #define LITEX_TEST_PHASE_STEP 1 /* [deg] */ /* Values for single parameters test */ #define LITEX_TEST_SINGLE_FREQ_VAL 15000000 /* [Hz] */ #define LITEX_TEST_SINGLE_DUTY_VAL 25 /* [%] */ #define LITEX_TEST_SINGLE_PHASE_VAL 90 /* [deg] */ #define LITEX_TEST_SINGLE_FREQ_VAL2 15000000 /* [Hz] */ #define LITEX_TEST_SINGLE_DUTY_VAL2 75 /* [%] */ #define LITEX_TEST_SINGLE_PHASE_VAL2 0 /* [deg] */ /* loop tests infinitely if true, otherwise do one loop */ #define LITEX_TEST_LOOP 0 /* Choose test type */ #define LITEX_TEST 4 #define LITEX_TEST_FREQUENCY 1 #define LITEX_TEST_DUTY 2 #define LITEX_TEST_PHASE 3 #define LITEX_TEST_SINGLE 4 #define LITEX_TEST_DUTY_DEN 100 /* LiteX Common Clock Driver tests */ int litex_clk_test_getters(const struct device *dev) { struct litex_clk_setup setup; uint32_t rate; int i; clock_control_subsys_t sub_system = (clock_control_subsys_t)&setup; printf("Getters test\n"); for (i = 0; i < NCLKOUT; i++) { setup.clkout_nr = i; clock_control_get_status(dev, sub_system); printf("CLKOUT%d: get_status: rate:%d phase:%d duty:%d\n", i, setup.rate, setup.phase, setup.duty); clock_control_get_rate(dev, sub_system, &rate); printf("CLKOUT%d: get_rate:%d\n", i, rate); } return 0; } int litex_clk_test_single(const struct device *dev) { struct litex_clk_setup setup1 = { .clkout_nr = LITEX_CLK_TEST_CLK1, .rate = LITEX_TEST_SINGLE_FREQ_VAL, .duty = LITEX_TEST_SINGLE_DUTY_VAL, .phase = LITEX_TEST_SINGLE_PHASE_VAL }; struct litex_clk_setup setup2 = { .clkout_nr = LITEX_CLK_TEST_CLK2, .rate = LITEX_TEST_SINGLE_FREQ_VAL2, .duty = LITEX_TEST_SINGLE_DUTY_VAL2, .phase = LITEX_TEST_SINGLE_PHASE_VAL2, }; uint32_t ret = 0; clock_control_subsys_t sub_system1 = (clock_control_subsys_t)&setup1; clock_control_subsys_t sub_system2 = (clock_control_subsys_t)&setup2; printf("Single test\n"); ret = clock_control_on(dev, sub_system1); if (ret != 0) { return ret; } ret = clock_control_on(dev, sub_system2); if (ret != 0) { return ret; } litex_clk_test_getters(dev); return 0; } int litex_clk_test_freq(const struct device *dev) { struct litex_clk_setup setup = { .clkout_nr = LITEX_CLK_TEST_CLK1, .duty = LITEX_TEST_FREQUENCY_DUTY_VAL, .phase = LITEX_TEST_FREQUENCY_PHASE_VAL }; clock_control_subsys_t sub_system = (clock_control_subsys_t)&setup; uint32_t i, ret = 0; printf("Frequency test\n"); do { for (i = LITEX_TEST_FREQUENCY_MIN; i < LITEX_TEST_FREQUENCY_MAX; i += LITEX_TEST_FREQUENCY_STEP) { setup.clkout_nr = LITEX_CLK_TEST_CLK1; setup.rate = i; sub_system = (clock_control_subsys_t)&setup; /* * Don't check for ENOTSUP here because it is expected. * The reason is that set of possible frequencies for * specific clock output depends on devicetree config * (including margin) and also on other active clock * outputs configuration. Some configurations may cause * errors when the driver is trying to update one of * the clkouts. * Ignoring these errors ensure that * test will be finished * */ ret = clock_control_on(dev, sub_system); if (ret != 0 && ret != -ENOTSUP) { return ret; } setup.clkout_nr = LITEX_CLK_TEST_CLK2; ret = clock_control_on(dev, sub_system); if (ret != 0) { return ret; } k_sleep(K_MSEC(LITEX_TEST_FREQUENCY_DELAY_MS)); } for (i = LITEX_TEST_FREQUENCY_MAX; i > LITEX_TEST_FREQUENCY_MIN; i -= LITEX_TEST_FREQUENCY_STEP) { setup.clkout_nr = LITEX_CLK_TEST_CLK1; setup.rate = i; sub_system = (clock_control_subsys_t)&setup; ret = clock_control_on(dev, sub_system); if (ret != 0 && ret != -ENOTSUP) { return ret; } setup.clkout_nr = LITEX_CLK_TEST_CLK2; ret = clock_control_on(dev, sub_system); if (ret != 0) { return ret; } k_sleep(K_MSEC(LITEX_TEST_FREQUENCY_DELAY_MS)); } } while (LITEX_TEST_LOOP); return 0; } int litex_clk_test_phase(const struct device *dev) { struct litex_clk_setup setup1 = { .clkout_nr = LITEX_CLK_TEST_CLK1, .rate = LITEX_TEST_PHASE_FREQ_VAL, .duty = LITEX_TEST_PHASE_DUTY_VAL, .phase = 0 }; struct litex_clk_setup setup2 = { .clkout_nr = LITEX_CLK_TEST_CLK2, .rate = LITEX_TEST_PHASE_FREQ_VAL, .duty = LITEX_TEST_PHASE_DUTY_VAL }; clock_control_subsys_t sub_system1 = (clock_control_subsys_t)&setup1; clock_control_subsys_t sub_system2 = (clock_control_subsys_t)&setup2; uint32_t ret = 0; int i; printf("Phase test\n"); ret = clock_control_on(dev, sub_system1); if (ret != 0 && ret != -ENOTSUP) { return ret; } do { for (i = LITEX_TEST_PHASE_MIN; i <= LITEX_TEST_PHASE_MAX; i += LITEX_TEST_PHASE_STEP) { setup2.phase = i; sub_system2 = (clock_control_subsys_t)&setup2; ret = clock_control_on(dev, sub_system2); if (ret != 0) { return ret; } k_sleep(K_MSEC(LITEX_TEST_PHASE_DELAY_MS)); } } while (LITEX_TEST_LOOP); return 0; } int litex_clk_test_duty(const struct device *dev) { struct litex_clk_setup setup1 = { .clkout_nr = LITEX_CLK_TEST_CLK1, .rate = LITEX_TEST_DUTY_FREQ_VAL, .phase = LITEX_TEST_DUTY_PHASE_VAL, .duty = 0 }; struct litex_clk_setup setup2 = { .clkout_nr = LITEX_CLK_TEST_CLK2, .rate = LITEX_TEST_DUTY_FREQ_VAL, .phase = LITEX_TEST_DUTY_PHASE_VAL, .duty = 0 }; uint32_t ret = 0, i; clock_control_subsys_t sub_system1 = (clock_control_subsys_t)&setup1; clock_control_subsys_t sub_system2 = (clock_control_subsys_t)&setup2; ret = clock_control_on(dev, sub_system1); if (ret != 0 && ret != -ENOTSUP) { return ret; } ret = clock_control_on(dev, sub_system2); if (ret != 0 && ret != -ENOTSUP) { return ret; } printf("Duty test\n"); do { for (i = LITEX_TEST_DUTY_MIN; i <= LITEX_TEST_DUTY_MAX; i += LITEX_TEST_DUTY_STEP) { setup1.duty = i; sub_system1 = (clock_control_subsys_t)&setup1; ret = clock_control_on(dev, sub_system1); if (ret != 0) { return ret; } setup2.duty = 100 - i; sub_system2 = (clock_control_subsys_t)&setup2; ret = clock_control_on(dev, sub_system2); if (ret != 0) { return ret; } k_sleep(K_MSEC(LITEX_TEST_DUTY_DELAY_MS)); } for (i = LITEX_TEST_DUTY_MAX; i > LITEX_TEST_DUTY_MIN; i -= LITEX_TEST_DUTY_STEP) { setup1.duty = i; sub_system1 = (clock_control_subsys_t)&setup1; ret = clock_control_on(dev, sub_system1); if (ret != 0) { return ret; } setup2.duty = 100 - i; sub_system2 = (clock_control_subsys_t)&setup2; ret = clock_control_on(dev, sub_system2); if (ret != 0) { return ret; } k_sleep(K_MSEC(LITEX_TEST_DUTY_DELAY_MS)); } } while (LITEX_TEST_LOOP); return 0; } int litex_clk_test(const struct device *dev) { int ret; printf("Clock test\n"); switch (LITEX_TEST) { case LITEX_TEST_DUTY: ret = litex_clk_test_duty(dev); break; case LITEX_TEST_PHASE: ret = litex_clk_test_phase(dev); break; case LITEX_TEST_FREQUENCY: ret = litex_clk_test_freq(dev); break; case LITEX_TEST_SINGLE: default: ret = litex_clk_test_single(dev); } printf("Clock test done returning: %d\n", ret); return ret; } int main(void) { const struct device *const dev = DEVICE_DT_GET(MMCM); printf("Clock Control Example! %s\n", CONFIG_ARCH); printf("device name: %s\n", dev->name); if (!device_is_ready(dev)) { printf("error: device %s is not ready\n", dev->name); return 0; } printf("clock control device is %p, name is %s\n", dev, dev->name); litex_clk_test(dev); return 0; }