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/DM388: Access to timers in 4.4 kernel device tree

Part Number: DM388

Tool/software: Linux

I'm in the midst of porting from a prior implementation before the introduction of the device tree.  In that world, I was able to invoke omap_dm_timer_request_specific(x) where 'x' is an integer selecting one of the 8 general purpose timers.  In my specific case, I was requesting timer4 and timer5.  In the new world defined by "DM38x IPNC RDK GA Release (v3.9.1)" where there's a device tree, that invocation fails with a message "Please use omap_dm_timer_request_by_cap/node()".  As a first shot, I tried changing the invocation to a simple omap_dm_timer_request() which, I believe, is supposed to return the next available unclaimed timer.  That function appears to believe that there are no more available timers.

My device tree is defined via a '.dts' which is based on dm38x-csk.dts.  That file includes ti81xx.dtsi which defines only timer1 & timer2.  Experimentally I added definitions for timers 3-8 to that file however that was either wrong or insufficient as I'm getting messages such as "platform 48042000.timer: Cannot lookup hwmod 'timer3'" and omap_dm_timer_request() is still failing.

So, how am I supposed to access the other DM388 timers?

  • Hi David,

    You can explore how timer1/2 are used in the default kernel configuration and DTS and re-use the same approach. The additional timers should be add to ti81xx.dtsi. Then see the below wiki:

    processors.wiki.ti.com/.../IPNC_RDK_DM38x_,_DM8127

    The function omap2_pm_wakeup_on_timer() is used. You should use also the below timer driver:

    kernel/arch/arm/mach-omap2/timer.c

    See also the below pointers:

    kernel/Documentation/devicetree/bindings/arm/omap/timer.txt

    kernel/arch/arm/mach-omap2/remoteproc.c -> timer = omap_dm_timer_request_by_node(np);

    kernel/arch/arm/plat-omap/include/plat/dmtimer.h
    kernel/arch/arm/plat-omap/dmtimer.c

    e2e.ti.com/.../464956
    e2e.ti.com/.../421917
    e2e.ti.com/.../506664
    e2e.ti.com/.../415079

    Regards,
    Pavel
  • Thank you for your response which I shall certainly study in detail, however there is one portion of your advice which I've already tried and which is problematic, namely "The additional timers should be add to ti81xx.dtsi.".

    Here is an example of my addition of timer3 to ti81xx.dtsi:

    timer3: timer@42000 {
        compatible = "ti,dm814-timer";
        reg = <0x42000 0x2000>;
        interrupts = <69>;
        ti,hwmods = "timer3";
    };


    Here is the corresponding decoded output from the dtb:

    timer@42000 {
        compatible = "ti,dm814-timer";
        reg = <0x00042000 0x00002000>;
        interrupts = <0x00000045>;
        ti,hwmods = "timer3";
    };

    Finally, here is the error message from the kernel showing that there's a problem:

    platform 48042000.timer: Cannot lookup hwmod 'timer3'

    So either my .dtsi entry was incorrect or there's something else that I have to do.

  • You require a hwmod  for timer3 , add it in arch/arm/mach-omap2/omap_hwmod_81xx_data.c.

    something similar as below you have to add , below is entry you find for timer1,

    static struct omap_hwmod_ocp_if dm814x_l4_ls__timer1 = {
        .master     = &dm81xx_l4_ls_hwmod,
        .slave      = &dm814x_timer1_hwmod,
        .clk        = "timer_sys_ck",
        .user       = OCP_USER_MPU,
    };

    same as to be added to the list of hwmods,

    static struct omap_hwmod_ocp_if *ti81xx_hwmod_ocp_ifs_dm38x[] __initdata = {

    Thanks & Regards,

    Vishwanath Patil

  • So a little further down the rabbit hole.

    I've added this to omap_hwmod_81xx_data.c for timer 3:

    static struct omap_hwmod_ocp_if dm814x_l4_ls__timer3 = {
        .master     = &dm81xx_l4_ls_hwmod,
        .slave      = &dm814x_timer3_hwmod,
        .clk        = "timer_sys_ck",
        .user       = OCP_USER_MPU,
    };


    Only dm814x_timer3_hwmod didn't exist so I also added this:


    static struct omap_hwmod dm814x_timer3_hwmod = {
        .name        = "timer3",
        .clkdm_name  = "alwon_l3s_clkdm",
        .main_clk    = "timer3_fck",
        .dev_attr    = &capability_alwon_dev_attr,
        .class       = &dm816x_timer_hwmod_class,
        .flags       = HWMOD_NO_IDLEST,
    }

    And now I get this kernel error message:

    platform 48042000.timer: clk_get for timer3_fck failed
    ------------[ cut here ]------------
    WARNING: CPU: 0 PID: 1 at arch/arm/mach-omap2/omap_hwmod.c:2119 _enable+0x340/0x350()
    omap_hwmod: gpio1: enabled state can only be entered from initialized, idle, or disabled state
    Modules linked in:
    CPU: 0 PID: 1 Comm: swapper Tainted: G        W       4.4.12 #1
    Hardware name: Generic TI81xx (Flattened Device Tree)
    Backtrace:
    [<c0013170>] (dump_backtrace) from [<c001336c>] (show_stack+0x18/0x1c)
     r6:c001f538 r5:00000009 r4:00000000 r3:00000000
    [<c0013354>] (show_stack) from [<c0217144>] (dump_stack+0x24/0x28)
    [<c0217120>] (dump_stack) from [<c00348e0>] (warn_slowpath_common+0x8c/0xb8)
    [<c0034854>] (warn_slowpath_common) from [<c0034944>] (warn_slowpath_fmt+0x38/0x40)
     r8:00000000 r7:00000004 r6:c4919200 r5:00000000 r4:c05a9668
    [<c0034910>] (warn_slowpath_fmt) from [<c001f538>] (_enable+0x340/0x350)
     r3:c05ae52c r2:c05a9668
     r4:c06a8b44
    [<c001f1f8>] (_enable) from [<c001fd40>] (omap_hwmod_enable+0x20/0x30)
     r7:00000004 r6:c4919200 r5:00000000 r4:a0000093
    [<c001fd20>] (omap_hwmod_enable) from [<c00210ac>] (omap_device_enable+0x48/0x98)
     r4:00000001 r3:c4919240
    [<c0021064>] (omap_device_enable) from [<c0021114>] (_od_runtime_resume+0x18/0x2c)
     r6:c06add00 r5:c00210fc r4:c4915e10 r3:00000002
    [<c00210fc>] (_od_runtime_resume) from [<c02a5d3c>] (rpm_callback+0xb0/0xcc)
     r4:c4915e10 r3:00000002
    [<c02a5c8c>] (rpm_callback) from [<c02a6abc>] (rpm_resume+0x310/0x4f4)
     r5:c00210fc r4:c490ce10
    [<c02a67ac>] (rpm_resume) from [<c02a6cdc>] (__pm_runtime_resume+0x3c/0x44)
     r10:c025121c r9:0000001e r8:c4915e10 r7:c04b6274 r6:c4915e00 r5:c4911850
     r4:60000013
    [<c02a6ca0>] (__pm_runtime_resume) from [<c0251604>] (omap_gpio_probe+0x1e0/0x670)
     r4:c491a010 r3:00000001
    [<c0251424>] (omap_gpio_probe) from [<c029f9ec>] (platform_drv_probe+0x54/0xb8)
     r10:00000000 r9:00000000 r8:c06b5874 r7:fffffdfb r6:c06b5874 r5:c4915e10
     r4:c0711ec0
    [<c029f998>] (platform_drv_probe) from [<c029dc3c>] (driver_probe_device+0x238/0x480)
     r7:00000000 r6:c06da610 r5:c4915e10 r4:c0711ec0
    [<c029da04>] (driver_probe_device) from [<c029dfe4>] (__device_attach_driver+0x88/0x94)
     r9:00000000 r8:c0711e9c r7:00000001 r6:c4915e10 r5:c486bc88 r4:c06b5874
    [<c029df5c>] (__device_attach_driver) from [<c029bd78>] (bus_for_each_drv+0x6c/0xa0)
     r6:c029df5c r5:c486bc88 r4:00000000 r3:c49072c0
    [<c029bd0c>] (bus_for_each_drv) from [<c029d8fc>] (__device_attach+0xac/0x13c)
     r6:c4915e44 r5:c4915e10 r4:c4915e10
    [<c029d850>] (__device_attach) from [<c029e13c>] (device_initial_probe+0x14/0x18)
     r7:00000000 r6:c06ba750 r5:c4915e10 r4:c4915e18
    [<c029e128>] (device_initial_probe) from [<c029cdd0>] (bus_probe_device+0x8c/0x94)
    [<c029cd44>] (bus_probe_device) from [<c029ad78>] (device_add+0x418/0x5b0)
     r6:c4915e10 r5:c490ce10 r4:c4915e18 r3:c4801900
    [<c029a960>] (device_add) from [<c0359688>] (of_device_add+0x3c/0x44)
     r10:c490ce10 r9:00000000 r8:c0690414 r7:00000000 r6:c4915e10 r5:c4d2a3d4
     r4:c4915e00
    [<c035964c>] (of_device_add) from [<c0359f10>] (of_platform_device_create_pdata+0x94/0xd4)
    [<c0359e7c>] (of_platform_device_create_pdata) from [<c035a070>] (of_platform_bus_create+0x104/0x228)
     r7:00000001 r6:c068cfb8 r5:c4d2a3d4 r4:00000000
    [<c0359f6c>] (of_platform_bus_create) from [<c035a0c8>] (of_platform_bus_create+0x15c/0x228)
     r10:c490ce10 r9:c06dde68 r8:c0690414 r7:00000001 r6:c068cfb8 r5:c4cfede4
     r4:c4d2a3d4
    [<c0359f6c>] (of_platform_bus_create) from [<c035a0c8>] (of_platform_bus_create+0x15c/0x228)
     r10:c490cc10 r9:c06dde68 r8:c0690414 r7:00000001 r6:c068cfb8 r5:c4cfec48
     r4:c4cfede4
    [<c0359f6c>] (of_platform_bus_create) from [<c035a320>] (of_platform_populate+0x64/0xc0)
     r10:00000000 r9:00000001 r8:00000000 r7:c068cfb8 r6:c0690414 r5:c4cfdb78
     r4:c4cfec48
    [<c035a2bc>] (of_platform_populate) from [<c065c96c>] (pdata_quirks_init+0x64/0x7c)
     r9:c069c6d8 r8:00000060 r7:c064f940 r6:c4908600 r5:00000000 r4:c0690414
    [<c065c908>] (pdata_quirks_init) from [<c065c540>] (omap_generic_init+0x1c/0x24)
     r4:36d61600 r3:c06842f0
    [<c065c524>] (omap_generic_init) from [<c064f968>] (customize_machine+0x28/0x48)
    [<c064f940>] (customize_machine) from [<c0009754>] (do_one_initcall+0x184/0x1f8)
    [<c00095d0>] (do_one_initcall) from [<c064de74>] (kernel_init_freeable+0x154/0x1f0)
     r10:c0685824 r9:c064d608 r8:00000060 r7:c0685838 r6:c06e03c0 r5:00000003
     r4:c0695e7c
    [<c064dd20>] (kernel_init_freeable) from [<c048b24c>] (kernel_init+0x10/0xfc)
     r10:00000000 r9:00000000 r8:00000000 r7:00000000 r6:00000000 r5:c048b23c
     r4:00000000
    [<c048b23c>] (kernel_init) from [<c00103e8>] (ret_from_fork+0x14/0x2c)
     r4:00000000 r3:c486a000
    ---[ end trace 16675a450d09faff ]---

    This doesn't seem good ;-)

  • David,

    You should update *ti81xx_hwmod_ocp_ifs_dm38x[] (from file omap-hwmod-81xx-data.c) with &dm814x_l4_ls__timer3

    And you should update drivers/clk/ti/clk-814x.c file with timer3_fck

    Regards,
    Pavel
  • There was yet one more booby trap waiting to blow my leg off.  My posted examples were all for timer 3 but I'd actually been adding support for timers 3-8.  After making this last change, I again got all sorts of kernel crashes when the code got to timer 4.  There's a ti81xx-clocks.dtsi which defines all of the "_fck" clocks.  For reasons that I do not understand, unlike timers 1-3 and 5-8, there is no timer4_fck.  Instead it's called gpt4_fck!  After making the appropriate change in clk-814x.c, I finally got a kernel that wouldn't throw up all over the place.

    However even after adding all these timers, omap_dm_timer_request() still fails to find one ;-(  Time for some printk's.

  • David Olson61 said:
    However even after adding all these timers, omap_dm_timer_request() still fails to find one ;-(  Time for some printk's.

    Per mine understanding, when timers are described in device tree file, omap_dm_timer_request_by_node() should be used

  • After dealing with some distractions, I returned to this issue and discovered that none of the omap_dm_timer_request....() suite would work because all the new timers I described weren't being registered.  That's because I followed the model for the existing timer 1 & 2 in ti81xx.dtsi and set the 'compatible' string for the newly added timers to "ti,dm814-timer".

    There's two files that reference a set of ti timer compatibility strings, arch/arm/mach-omap2/timer.c & arch/arm/plat-omap/dmtimer.c.  Both those are part of my build and both contain a nearly identical list of timer compatibility strings, the only difference being the lack of "ti,dm814-timer" (and "ti,dm816-timer") in dmtimer.c.

    So, I added those strings ... and things still didn't work!  The timers were now registered and omap_dm_timer_request() would find one.  It would then invoke the internal function omap_dm_timer_prepare().  That function ended by invoking omap_dm_timer_set_source(timer, OMAP_TIMER_SRC_32_KHZ).  That function turned OMAP_TIMER_SRC_32_KHZ into a search for a clock named "timer_32k_ck".  That reference is supposed to be resolved by referring to a struct in drivers/clk/ti/clk-814x.c.  That struct contains no such entry.  It does contain an entry for "timer_sys_ck" which is associated with the constant OMAP_TIMER_SRC_SYS_CLK so I changed omap_dm_timer_prepare() to set the source to that value and finally I was able to get hold of a timer!

    This whole process has involved a lot of "poke & hope" and I'm not claiming that what I've done is correct.  All I know is that I'm committing my changes to my repository and moving on the the next issue.