Low frequency on PWMs needed

Hello,

I have a problem with setting up low frequencies on PWMs on jetson nano dev kit. The highest possible period I could set with sysfs was 43696744 ns (around 22,8 Hz). Is it possible to get PWM to as low as 1Hz?

I would be greatful for some tips.

hello jakub6,

may I know what’s the actual use-case?
you may calculate possible rate of a PWM controller, which depends-on the clock sources.
for example, the clock source pllp_out0, which has a rate of 102 MHz.
the PWM available range is 48.63Hz to 398437Hz.

you may examine all the possible clock parents.
for example, $ cat /sys/kernel/debug/bpmp/debug/clk/pwm*/possible_parents
please set a new source from possible sources if you’re looking for lower frequency,
thanks

Could you let me know what changes to device tree should I make to change the clock source? The PWM node for jetson nano development kit () looks like this:

pwm@7000a000 {
                compatible = "nvidia,tegra124-pwm", "nvidia,tegra20-pwm";
                reg = <0x0 0x7000a000 0x0 0x100>;
                #pwm-cells = <0x2>;
                status = "okay";
                clocks = <0x26 0x11 0x26 0xf3>;
                clock-names = "pwm", "parent";
                resets = <0x26 0x11>;
                reset-names = "pwm";
                nvidia,no-clk-sleeping-in-ops;
                linux,phandle = <0xa9>;
                phandle = <0xa9>;
        };

Could I change the parent clock of pwm clock? If so, where should I do it?

Thanks for the fast reply!

Okey, I have changed the “parent” clock to clk_32k (hex 0xe8) and now I am able to setup the pwm to 1Hz:

pwm@7000a000 {
                compatible = "nvidia,tegra124-pwm", "nvidia,tegra20-pwm";
                reg = <0x0 0x7000a000 0x0 0x100>;
                #pwm-cells = <0x2>;
                status = "okay";
                clocks = <0x26 0x11 0x26 0xe8>;
                clock-names = "pwm", "parent";
                resets = <0x26 0x11>;
                reset-names = "pwm";
                nvidia,no-clk-sleeping-in-ops;
                linux,phandle = <0xa9>;
                phandle = <0xa9>;
        };

Thanks a lot for the tip!

hello jakub6,

glad to know it works,
actually, you may check possible_parents and set a new source from possible sources via sysfs,
for example, $ echo <new_source> > /sys/kernel/debug/bpmp/debug/clk/pwmN/parent

Unfortunately new clock source makes PWM very inaccurate. Period set by sysfs is far from what I get from the pwm output. Any ideas? Is it possible that the clock source division makes it so inaccurate? For low frequencies (1-10Hz) the difference between the sysfs setup and the actual output are not so high, but the higher is the frequency (around 100Hz), the bigger gets the difference.

Thanks for the help.

hello jakub6,

please evaluate the max/min rate.
here’s an example, for using clock=102 MHz.
Max Rate = 102Mhz/ 256 = 398437 Hz = 2510 ns
Min Rate = 102Mhz/ (256* 2^13) (i.e. 13-bits Frequency divider (bits 0:12)) = 48.63Hz = 20561324 ns

I do not know exactly what You mean.
For 32768Hz clock source the pwm max/min rate is:

Max Rate = 32768Hz / 256 = 128Hz
Min Rate = 32768Hz / (256* 2^13) = 15,625mHz

The max rate is not a problem for me but if I set the PWM to 100Hz I would like it to be around 100Hz not 127Hz.
Is there anything I could do to make it right?

Okey, so only discrete possible values of PWM I can get are in the form of:

clk_source / (256 * n)

where n is a whole number between 1 and 2^13. So I need to choose different clock source to get better accuracy. But also I want min rate to be at least 1 Hz so frequency of the clock source cannot be higher than 2097152Hz.

pwm clock source’s has only 4 possible parrent clocks and only one of them has frequency below that threshold (clk_32k). Is there anything I can do to get custom clock source for PWM controller to maximize accuracy between specified range of PWM frequencies?

hello jakub6,

the lowest PWM frequency we’ve test is 10Hz; and this has been tested on AGX Xavier series.
may I know what’s your actual use-case, thanks

Hello JerryChang,

I am trying to control a power supply driver and it has strict pwm frequency limitations (up to 50Hz). I would like to control pwm from 1Hz to 50 Hz with good accuracy. Is there any possibility to make it work?

Thanks in advance.

hello jakub6,

could you please dump possible_parents and share all the possible sources via sysfs for reference,
i.e. $ cat /sys/kernel/debug/bpmp/debug/clk/pwmN/possible_parents

Hi JerryChang

The dump looks like this:

$ cat /sys/kernel/debug/clk/pwm/clk_possible_parents
pll_p pll_c clk_32k clk_m

Please notice that I have a little different directory structure.

hello jakub6,

please have a try to modify the device tree directly by using clock, clk_s in order to reach 1Hz.

In the device tree there is no clk_s clock listed in clock-names.
Dump from clock_names

clock-names = "ispb", "rtc", "timer", "uarta", "gpio", "sdmmc2", "i2s1", "i2c1", "sdmmc1", "sdmmc4", "pwm", "i2s2", "vi", "usbd", "ispa", "disp2", "disp1", "host1x", "i2s0", "mc", "ahbdma", "apbdma", "pmc", "kfuse", "sbc1", "sbc2", "sbc3", "i2c5", "dsia", "csi", "i2c2", "uartc", "mipi_cal", "emc", "usb2", "bsev", "uartd", "i2c3", "sbc4", "sdmmc3", "pcie", "owr", "afi", "csite", "la", "soc_therm", "dtv", "i2cslow", "dsib", "tsec", "xusb_host", "csus", "mselect", "tsensor", "i2s3", "i2s4", "i2c4", "d_audio", "apb2ape", "hda2codec_2x", "spdif_2x", "actmon", "extern1", "extern2", "extern3", "sata_oob", "sata", "hda", "se", "hda2hdmi", "sata_cold", "cec", "xusb_gate", "cilab", "cilcd", "cile", "dsialp", "dsiblp", "entropy", "dp2", "xusb_ss", "dmic1", "dmic2", "i2c6", "mc_capa", "mc_cbpa", "vim2_clk", "mipibif", "clk72mhz", "vic03", "dpaux", "sor0", "sor1", "gpu", "dbgapb", "pll_p_out_adsp", "pll_g_ref", "sdmmc_legacy", "nvdec", "nvjpg", "dmic3", "ape", "adsp", "mc_cdpa", "mc_ccpa", "maud", "tsecb", "dpaux1", "vi_i2c", "hsic_trk", "usb2_trk", "qspi", "uartape", "adsp_neon", "nvenc", "iqc2", "iqc1", "sor_safe", "pll_p_out_cpu", "uartb", "vfir", "spdif_in", "spdif_out", "vi_sensor", "fuse", "fuse_burn", "clk_32k", "clk_m", "clk_m_div2", "clk_m_div4", "pll_ref", "pll_c", "pll_c_out1", "pll_c2", "pll_c3", "pll_m", "pll_m_out1", "pll_p", "pll_p_out1", "pll_p_out2", "pll_p_out3", "pll_p_out4", "pll_a", "pll_a_out0", "pll_d", "pll_d_out0", "pll_d2", "pll_d2_out0", "pll_u", "pll_u_480m", "pll_u_60m", "pll_u_48m", "pll_x", "pll_x_out0", "pll_re_vco", "pll_re_out", "pll_e", "spdif_in_sync", "i2s0_sync", "i2s1_sync", "i2s2_sync", "i2s3_sync", "i2s4_sync", "vimclk_sync", "audio0", "audio1", "audio2", "audio3", "audio4", "spdif", "clk_out_1", "clk_out_2", "clk_out_3", "blink", "qspi_out", "xusb_host_src", "xusb_falcon_src", "xusb_fs_src", "xusb_ss_src", "xusb_dev_src", "xusb_dev", "xusb_hs_src", "sclk", "hclk", "pclk", "cclk_g", "cclk_lp", "dfll_ref", "dfll_soc", "vi_sensor2", "pll_p_out5", "cml0", "cml1", "pll_c4", "pll_dp", "pll_e_mux", "pll_mb", "pll_a1", "pll_d_dsi_out", "pll_c4_out0", "pll_c4_out1", "pll_c4_out2", "pll_c4_out3", "pll_u_out", "pll_u_out1", "pll_u_out2", "usb2_hsic_trk", "pll_p_out_hsio", "pll_p_out_xusb", "xusb_ssp_src", "pll_re_out1", "pll_mb_ud", "pll_p_ud", "isp", "pll_a_out_adsp", "pll_a_out0_out_adsp", "audio0_mux", "audio1_mux", "audio2_mux", "audio3_mux", "audio4_mux", "spdif_mux", "clk_out_1_mux", "clk_out_2_mux", "clk_out_3_mux", "dsia_mux", "dsib_mux", "sor0_lvds", "xusb_ss_div2", "pll_m_ud", "pll_c_ud", "sclk_mux", "sor1_brick", "sor1_mux", "pd2vi", "vi_output", "aclk", "sclk_skipper", "disp1_slcg_ovr", "disp2_slcg_ovr", "vi_slcg_ovr", "ispa_slcg_ovr", "ispb_slcg_ovr", "nvdec_slcg_ovr", "nvenc_slcg_ovr", "nvjpg_slcg_ovr", "vic03_slcg_ovr", "xusb_dev_slcg_ovr", "xusb_host_slcg_ovr", "d_audio_slcg_ovr", "ape_slcg_ovr", "sata_slcg_ovr", "sata_slcg_ovr_ipfs", "sata_slcg_ovr_fpci", "dmic1_sync_clk", "dmic1_sync_clk_mux", "dmic2_sync_clk", "dmic2_sync_clk_mux", "dmic3_sync_clk", "dmic3_sync_clk_mux", "aclk_slcg_ovr", "c2bus", "c3bus", "vic03_cbus", "nvjpg_cbus", "se_cbus", "tsecb_cbus", "cap_c2bus", "cap_vcore_c2bus", "cap_throttle_c2bus", "floor_c2bus", "override_c2bus", "edp_c2bus", "nvenc_cbus", "nvdec_cbus", "vic_floor_cbus", "cap_c3bus", "cap_vcore_c3bus", "cap_throttle_c3bus", "floor_c3bus", "override_c3bus", "vi_cbus", "isp_cbus", "override_cbus", "cap_vcore_cbus", "via_vi_cbus", "vib_vi_cbus", "ispa_isp_cbus", "ispb_isp_cbus", "sbus", "avp_sclk", "bsea_sclk", "usbd_sclk", "usb1_sclk", "usb2_sclk", "usb3_sclk", "wake_sclk", "camera_sclk", "mon_avp", "cap_sclk", "cap_vcore_sclk", "cap_throttle_sclk", "floor_sclk", "override_sclk", "sbc1_sclk", "sbc2_sclk", "sbc3_sclk", "sbc4_sclk", "qspi_sclk", "boot_apb_sclk", "emc_master", "avp_emc", "cpu_emc", "disp1_emc", "disp2_emc", "disp1_la_emc", "disp2_la_emc", "usbd_emc", "usb1_emc", "usb2_emc", "usb3_emc", "sdmmc3_emc", "sdmmc4_emc", "mon_emc", "cap_emc", "cap_vcore_emc", "cap_throttle_emc", "gr3d_emc", "nvenc_emc", "nvjpg_emc", "nvdec_emc", "tsec_emc", "tsecb_emc", "camera_emc", "via_emc", "vib_emc", "ispa_emc", "ispb_emc", "iso_emc", "floor_emc", "override_emc", "edp_emc", "vic_emc", "vic_shared_emc", "ape_emc", "pcie_emc", "xusb_emc", "gbus", "gm20b_gbus", "cap_gbus", "edp_gbus", "cap_vgpu_gbus", "cap_throttle_gbus", "cap_profile_gbus", "override_gbus", "floor_gbus", "floor_profile_gbus", "host1x_master", "nv_host1x", "vi_host1x", "vii2c_host1x", "cap_host1x", "cap_vcore_host1x", "floor_host1x", "override_host1x", "mselect_master", "cpu_mselect", "pcie_mselect", "cap_vcore_mselect", "override_mselect", "ape_master", "adma_ape", "adsp_ape", "xbar_ape", "cap_vcore_ape", "override_ape", "abus", "adsp_cpu_abus", "cap_vcore_abus", "override_abus", "vcm_sclk", "vcm_ahb_sclk", "vcm_apb_sclk", "ahb_sclk", "apb_sclk", "sdmmc4_ahb_sclk", "battery_emc", "cbus";

sorry, it’s clock naming translation, you should choose clk_32k for software implementation.

I have already done that and mentioned it here:

But new problem arouse that the 32kHz frequency is too low because the division only let me set pwm to:
32768Hz/(256*n)=128/n.
So only possible values for n<8 are: 18.29Hz, 21.33Hz, 25.6Hz, 32Hz, 42.67Hz, 64Hz, 128Hz and NOTHING in between. I have already written about that problem here:

I would like to have precise PWM in the range of 1-50Hz which I have already mentioned:

Are there any chances to achive what I wish for on jetson nano dev kit?

Thanks for a fast response.

Is there anyone who could help me with that problem?

Hi,
It may not be possible to have accurate 1Hz, 2Hz by using PWM. Would need to consider divider. Are you able to use GPIO pin for this purpose?

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.