This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Linux/AM3354: Timer clock source configuration

Part Number: AM3354
Other Parts Discussed in Thread: AM4372

Tool/software: Linux

Hello,

I'm running the 4.9.59 kernel on a custom AM3354 board.

I'm trying to change the clock source for my dmtimer-pwm output.  By default it is using the 32768 Hz clock and the shortest period I can set on that is 45752 ns.  I want to use the high-frequency system clock instead so I can get at least a 100 kHz PWM signal.

According to this documentation, I can change the clock source in the device tree:

elixir.bootlin.com/.../pwm-omap-dmtimer.txt

My device tree entry looks like this:

&am33xx_pinmux {

        pwm6_pins: pinmux_pwm6_pins {
                pinctrl-single,pins = <
            AM33XX_IOPAD(0x9b0, PIN_OUTPUT_PULLDOWN | MUX_MODE2)  /* (C15) xdma_event_intr0.timer4 */
            >;
        };
};

&timer4 {
        status = "okay";
        ti,timer-pwm;
};

/ {
        pwm6: dmtimer-pwm@4 {
                compatible = "ti,omap-dmtimer-pwm";
                ti,timers = <&timer4>;
                #pwm-cells = <3>;
                pinctrl-names = "default";
                pinctrl-0 = <&pwm6_pins>;
                ti,clock-source = <0x0>;
        };
};

But when I try to set a 10000 ns period, I get this error:

omap-dmtimer-pwm dmtimer-pwm@7: period 10000 ns too short for clock rate 32786 Hz

So it doesn't appear to actually change the clock source.  When I run dtc -I fs /proc/device-tree, the nodes look like this:

        dmtimer-pwm@4 {
                compatible = "ti,omap-dmtimer-pwm";
                ti,timers = <0x4c>;
                pinctrl-0 = <0x4d>;
                #pwm-cells = <0x3>;
                pinctrl-names = "default";
        };

                timer@48044000 {
                        compatible = "ti,am335x-timer";
                        ti,timer-pwm;
                        ti,hwmods = "timer4";
                        status = "okay";
                        interrupts = <0x5c>;
                        phandle = <0x4c>;
                        reg = <0x48044000 0x400>;
                        linux,phandle = <0x4c>;
                };

The ti,clock-source is missing from the dmtimer-pwm.

Is it possible to use the high frequency clock with a DMTimer PWM?

  • Hi Matt,

    Timer4 source clock can be supplied by: 32786Hz coming from PLL, Main OSC, TCLKIN input pin. See AM335x TRM, section 8.1.6.13 Timer Clock Structure. This is selected through CLKSEL_TIMER4_CLK register. Can you check this register value, what is the value before "ti,clock-source" update and afterwards?

    See also below e2e thread for example:

    e2e.ti.com/.../692308

    Matt Barclay9 said:
    ti,clock-source = <0x0>;

    This means you are providing clock from TCLKIN pin to Timer4. Do you have a clock generator attached to TCLKIN pin?

    Regards,
    Pavel

  • Looks like there's a mismatch between the driver documentation and the TRM.  The driver binding documentation says:

    - ti,clock-source: Set dmtimer parent clock, values between 0 and 2:
      - 0x00 - high-frequency system clock (timer_sys_ck)
      - 0x01 - 32-kHz always-on clock (timer_32k_ck)
      - 0x02 - external clock (timer_ext_ck, OMAP2 only)


    TRM says:

    0x0 = SEL1: Select TCLKIN clock
    0x1 = SEL2: Select CLK_M_OSC clock
    0x2 = SEL3: Select CLK_32KHZ clock

    ( I trust the TRM )

    Reading the register value for CLKSEL_TIMER4_CLK:


    # devmem2 0x44e00510
    /dev/mem opened.
    Memory mapped at address 0xb6f6e000.
    Read at address  0x44E00510 (0xb6f6e510): 0x00000002


    I've tried setting value 0x01:


    # devmem2 0x44e00510 b 1
    /dev/mem opened.
    Memory mapped at address 0xb6f72000.
    Read at address  0x44E00510 (0xb6f72510): 0x02
    Write at address 0x44E00510 (0xb6f72510): 0x01, readback 0x01


    However, after un-exporting and re-exporting the pwm, I still get an error when requesting 100kHz period:


    root@testplat1:/sys/class/pwm/pwmchip1/pwm0# echo 10000 > period
    [ 3357.760307] omap-dmtimer-pwm dmtimer-pwm@4: period 10000 ns too short for clock rate 32786 Hz
    -sh: echo: write error: Invalid argument


    I was expecting a clock rate of 24 Mhz or 3.428 Mhz if it applied the prescaler....





  • After enabling Dynamic Debug in my Kernel and setting the CLKSEL_TIMER4_CLK Register to 1. I unexport and re-export the PWM and attempt to set the period:

    # echo 10000 > period
    [ 582.550777] omap-dmtimer-pwm dmtimer-pwm@4: clk rate: 32786Hz
    [ 582.556591] omap-dmtimer-pwm dmtimer-pwm@4: period 10000 ns too short for clock rate 32786 Hz

    The first line is from drivers/pwm/pwm-omap-dmtimer.c, line 128.

    Is there anything else I need to do when changing the clock source? e.g. Reset the Timer? Or stop the timer before changing source?
  • Matt Barclay9 said:

    The driver binding documentation says:

    - ti,clock-source: Set dmtimer parent clock, values between 0 and 2:
      - 0x00 - high-frequency system clock (timer_sys_ck)
      - 0x01 - 32-kHz always-on clock (timer_32k_ck)
      - 0x02 - external clock (timer_ext_ck, OMAP2 only)


    TRM says:

    0x0 = SEL1: Select TCLKIN clock
    0x1 = SEL2: Select CLK_M_OSC clock
    0x2 = SEL3: Select CLK_32KHZ clock

    Seems that pwm-omap-dmtimer.txt file is providing info specific for DMTIMER1 1ms, where this is true. Check AM335x TRM register CLKSEL_TIMER1MS_CLK.

    Check also file linux-kernel/arch/arm/boot/dts/am33xx-clocks.dtsi

    timer1_fck: timer1_fck@528 {
            #clock-cells = <0>;
            compatible = "ti,mux-clock";
            clocks = <&sys_clkin_ck>, <&clkdiv32k_ick>, <&tclkin_ck>, <&clk_rc32k_ck>, <&clk_32768_ck>;
            reg = <0x0528>;
        };

    timer4_fck: timer4_fck@510 {
            #clock-cells = <0>;
            compatible = "ti,mux-clock";
            clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clkdiv32k_ick>;
            reg = <0x0510>;
        };

    Regards,
    Pavel

  • Matt Barclay9 said:
    # echo 10000 > period
    [ 582.550777] omap-dmtimer-pwm dmtimer-pwm@4: clk rate: 32786Hz

    Before setting period, please check again register CLKSEL_TIMER4_CLK value with devmem2.

    I would suggest you to change CLKSEL_TIMER4_CLK value with DTS "ti,clock-source" entry or using the Clock framework to change timer4_fck parent clock.

    Check also file linux-kernel/drivers/clk/ti/clk-33xx.c

    Regards,
    Pavel

  • You can also try with "clocks = <&sys_clkin_ck>;" entry in timer4 node in DTS file.

    See below files for details and examples:

    linux-kernel/Documentation/devicetree/bindings/clock/ti/mux.txt
    linux-kernel/arch/arm/boot/dts/am4372.dtsi

    Regards,
    Pavel