PWM on JETSON XAVIER open points

Hi all,

I am testing PWM directly in Jetson Xavier board, I have few concerns during testing for which I need your support.

Test with below configuration:

- pwmchip0 --> c340000.pwm --> PWM4 --> FAN CONTROL
- pwmchip1 --> 32c0000.pwm --> PWM5 --> Pin18 of 40pins Header
- pwmchip2 --> 32f0000.pwm --> PWM8 --> Pin13 of 40pins Header, LCD_BLT_PWM
- pwmchip4 --> 39c0000.pwm --> TACH --> Tachometer function

I was able to export PWM5 and PWM8 to /sys/class/pwm/pwmchipX, X is as above, then set-up their period/duty_cycle are the same: period=2600000, duty=2400000. Then enable PWM5/PWM8 for pulses out, I observed by oscilloscope the pulses out for both PWM5/PWM8.

Point #1: at the beginning phase deviation between PWM5, PWM8 was 1ms, but it was shifting slowly over the time, the phase deviation was not always fixed. From my understanding, they are hardware PWM modules using fixed clock_source, there should not be phase shift. Is this correct?

Point #2: digging deeply for PWM clock_source from clk_tree, I figured out that PWM clocked source for PWM5–> CLK_M:19.2Mhz but PWM8–>PLLP:408Mhz. Please let me know how to change their clock source in device tree for PWM modules, so that it can be loaded during startup.

<b>tegra194-soc-pwm.dtsi</b>
        tegra_pwm5: pwm@32c0000 {
		compatible = "nvidia,tegra194-pwm";
		reg = <0x0 0x32c0000 0x0 0x10000>;
		nvidia,hw-instance-id = <0x4>;
		clocks = <&bpmp_clks TEGRA194_CLK_PWM5>;
		clock-names = "pwm";
		#pwm-cells = <2>;
		resets = <&bpmp_resets TEGRA194_RESET_PWM5>;
		reset-names = "pwm";
		status = "disabled";
	}; 
        ...
	tegra_pwm8: pwm@32f0000 {
		compatible = "nvidia,tegra194-pwm";
		reg = <0x0 0x32f0000 0x0 0x10000>;
		nvidia,hw-instance-id = <0x7>;
		clocks = <&bpmp_clks TEGRA194_CLK_PWM8>;
		clock-names = "pwm";
		#pwm-cells = <2>;
		resets = <&bpmp_resets TEGRA194_RESET_PWM8>;
		reset-names = "pwm";
		status = "disabled";
	};
<b>tegra194-clock.h</b>
#define TEGRA194_CLK_PWM1			105U
/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_PWM2 */
#define TEGRA194_CLK_PWM2			106U
/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_PWM3 */
#define TEGRA194_CLK_PWM3			107U
/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_PWM4 */
#define TEGRA194_CLK_PWM4			108U
/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_PWM5 */
#define TEGRA194_CLK_PWM5			109U
/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_PWM6 */
#define TEGRA194_CLK_PWM6			110U
/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_PWM7 */
#define TEGRA194_CLK_PWM7			111U
/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_PWM8 */
#define TEGRA194_CLK_PWM8	                112U
static const char *mux_pllp_pllc_clk32_clkm[] = {
	"pll_p", "pll_c", "clk_32k", "clk_m"
};
...
MUX("pwm", mux_pllp_pllc_clk32_clkm, CLK_SOURCE_PWM, 17, TEGRA_PERIPH_ON_APB, tegra_clk_pwm),

Point #3
PWM1–> 3280000 → Pin15 of 40pins header
It has not been added to any pwmchip controller. Please let me know the steps to use PWM1.

Point #4
Is it possible/any solution to count number of pulses generated from PWM module.

Thanks for your support!

Hi,

Please anyone let me know if PWM modules mentioned in Lowspeed IO of Technical Reference Manual and PWM mentioned in VGPIO are the same or not.

From my understanding, they are different as VGPIO → PWM use VI_CFG_PWM_CONTROL_0 register.
And PWM modules in LSIO use PWM_CONTROLLER_PWM_CSR_0_0 register.

Please let me know how to use VGPIO PWM if they are different.

Many thanks in advance!

Hi Hung-Lam,

We’re investigating this PWM output drifting issue now, the status will be updated once clarified.

Thanks

Hi Hung-Lam,

Please refer below notes for your queries.

Point-1 (Clock drifting)

PWM5 is clocked by CLK_M (19.2Mhz)
PWM8 is clocked by PLLP (408Mhz)

Since you are trying to set same rate (2.6 M) to both the PWM controllers, the divisor at each Clock is behaving differently to generate 2.6 M out of 19.2Mhz and 408Mhz clock sources.
Hence it is almost always possible to get clock drifting.
On my local setup, while setting same clock parent to both the PWM controllers, drifting is not seen.

Point-2 (Changing clock source)

Add or edit the pwm number and entries in the clock-common.dtsi
PATH: $TEGRA_TOP/platform/bpmp-t19x/include/parts/policy/clocks-common.dtsi

= <clock ID, clock_source, rate, enable mask>

below is an example for setting pwm5 clock source as pllp
pwm5 = <TEGRA194_CLK_PWM5 TEGRA194_CLK_PLLP_OUT0 0 0>;
rate and enable mask are set to zero, they will be updated during driver’s probe.

Point-3 (Enabling PWM1)

This can be done with enabling kernel dt node for pwm1 controller.
Change has been pushed to enable this. It is yet to get merged.

At your setup it can be enabled by adding the below code snippet:
$TEGRA_TOP/hardware/nvidia/platform/t19x/galen/kernel-dts/common/tegra194-p2888-0001-p2822-0000-common.dtsi

pwm@3280000 {
        status = "okay";
};

Point-4 (count number of pulses generated from PWM module)

I am looking into it now. Will update you soon.

Hope this helps.
Please let us know if you still have any issues.

Thanks & Regards,
Sandipan

Hi Sandipan,

Thanks a lot for your update!

Looking forward to see your input regarding to point #4.

Regards,
Hung-Lam

Hi Hung-Lam,

You can count the number of pulses via software using GPIO pin (interruptible pin).
There is no existing implementation available promptly on Tegra but let me provide the steps to implement and check.

  1. Connect the pwm output pin to a gpio input pin (There are multiple gpio pins configured as input)
  2. A driver program to configure the GPIO pin and ISR for this pin. gpio_request_one(), gpio_to_irq() etc will be required.
  3. Configure the gpio as interruptible and configure only raising edge interrupt. So accordingly time difference can be measured between every raising interrupt will give how many pulses are generated in a predefined time limit.
  4. You can also check /proc/interrupts to get how many interrupts are received.

Thanks & Regards,
Sandipan

Hi Hung Lam,

I am trying to use the pwm pins to control servos in a robot. Could you please describe the steps which enabled you to generate an output on the pwm pins and how to modify the pulse width / time period.

Thank You!

hi,

You can follow below steps to test your pwm, my assumption is to use pwmchip2

cd /sys/devices/32f0000.pwm/pwm/pwmchip2
echo 0 > export
cd pwm0
echo 10000 > period (in ns)
echo 5000 > duty_cycle (in ns)
echo 1 > enable (start pwm)

in order to set the clock for pwm modules you can follow above instructions from nvidia colleague.

Thanks!