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/AM3358: Can't read DM Timer control register

Part Number: AM3358


Tool/software: Linux

I'm using AM3358 SoC on Beagle Bone Black compatible board. I want to use DM timers (timer 6 and 7). But I can't read from timer 6's control register. I do it the following way:

.....

#define TIMER6_BASE_REG 0x48048000

.....

....

    printk(KERN_INFO"!!!Trying to read Timer6 register manualy with readl...\n");
    printk(KERN_INFO"!!!Timer6 control register address:%x...\n",TIMER6_BASE_REG + (OMAP_TIMER_CTRL_REG & 0xff));
    
    void __iomem *io = ioremap(TIMER6_BASE_REG + (OMAP_TIMER_CTRL_REG & 0xff), SZ_4K);
    printk(KERN_INFO"!!!Remapped address:%x...\n",(unsigned long*) io);
    printk(KERN_INFO"!!!Trying to read...\n");

....

    //omap_dm_timer_enable(cpts->odt);
    //omap_dm_timer_enable(cpts->odt2);

    unsigned int address = 0;
    address = readl(io);
    printk(KERN_INFO"!!!Value:%x...\n",address);
    printk(KERN_INFO"!!!Reading done succesfully...\n");


This causes page fault as far as I understood. Here is dmesg output:
....
[  116.075307] !!!Trying to read Timer6 register manualy with readl...
[  116.081849] !!!Timer6 control register address:48048024...
[  116.087630] !!!Remapped address:fa048024...
[  116.091998] !!!Trying to read...
[  116.095419] Unhandled fault: external abort on non-linefetch (0x1028) at 0xfa048024
[  116.103413] pgd = db0b8000
[  116.106244] [fa048024] *pgd=48011452(bad)
[  116.110450] Internal error: : 1028 [#1] SMP ARM
[  116.115181] Modules linked in: rpmsg_rpc rpmsg_char virtio_rpmsg_bus pruss_soc_bus pru_rproc pruss_intc rpmsg_pru rpmsg_core pruss omap_mailbox
[  116.128689] CPU: 0 PID: 141 Comm: sh Not tainted 4.14.40 #126
[  116.134687] Hardware name: Generic AM33XX (Flattened Device Tree)
[  116.141050] task: dbc48380 task.stack: dbf5e000
[  116.145797] PC is at cpts_ptp_enable+0x290/0x4c4
[  116.150613] LR is at cpts_ptp_enable+0x290/0x4c4
[  116.155432] pc : [<c065c00c>]    lr : [<c065c00c>]    psr: 60000013
[  116.161982] sp : dbf5fe50  ip : 00000003  fp : 00000000
[  116.167427] r10: 00000000  r9 : dbf5ff80  r8 : c1ef9350
[  116.172882] r7 : dbf42810  r6 : c170aa44  r5 : fa048024  r4 : dbf42820
[  116.179696] r3 : c1748028  r2 : c1748028  r1 : ffffff30  r0 : 00000014
[  116.186508] Flags: nZCv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment none
[  116.193954] Control: 10c5387d  Table: 9b0b8019  DAC: 00000051
[  116.199946] Process sh (pid: 141, stack limit = 0xdbf5e218)
[  116.205764] Stack: (0xdbf5fe50 to 0xdbf60000)
[  116.210317] fe40:                                     00000002 dbf42820 db09c040 db09c040
[  116.218860] fe60: 000cd2f0 dbf5ff80 00000000 c0674258 00000000 00000001 00000002 00000000
[  116.227399] fe80: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[  116.235949] fea0: 00000000 00000000 00000000 00000000 00000000 00000000 00000002 db006e50
[  116.244484] fec0: db006e40 c034603c 00000000 00000000 00000000 c0345f40 00000002 000cd2f0
[  116.253020] fee0: dbf5ff80 00000000 00000002 00000000 000cb2e0 c02c1708 c02c1a2c c0194c78
[  116.261565] ff00: c1789e54 c17c8b0b 00000000 c01b2f60 dbf731fc c01b34bc 00000000 dbf731fc
[  116.270102] ff20: 00000000 c02c35a8 00000001 00000000 c02c1a2c 000cb008 dbf86c80 00000002
[  116.278638] ff40: 000cd2f0 dbf86c80 00000002 000cd2f0 dbf5ff80 c02c197c dbf86c80 de03b200
[  116.287170] ff60: de03b180 dbf86c80 dbf86c80 00000000 00000000 000cd2f0 00000002 c02c1b44
[  116.295708] ff80: 00000000 00000000 00000000 00000000 00000001 000cd2f0 00000004 c0108064
[  116.304255] ffa0: dbf5e000 c0107ea0 00000000 00000001 00000001 000cd2f0 00000002 00000000
[  116.312788] ffc0: 00000000 00000001 000cd2f0 00000004 000cab64 00000020 00096bc4 000cb2e0
[  116.321323] ffe0: 000ca244 bef9c910 0001a358 b6ebaab8 60000010 00000001 9fdf6861 9fdf6c61
[  116.329888] [<c065c00c>] (cpts_ptp_enable) from [<c0674258>] (pps_enable_store+0x74/0x98)
[  116.338430] [<c0674258>] (pps_enable_store) from [<c034603c>] (kernfs_fop_write+0xfc/0x1dc)
[  116.347162] [<c034603c>] (kernfs_fop_write) from [<c02c1708>] (__vfs_write+0x1c/0x120)
[  116.355428] [<c02c1708>] (__vfs_write) from [<c02c197c>] (vfs_write+0xa0/0x168)
[  116.363067] [<c02c197c>] (vfs_write) from [<c02c1b44>] (SyS_write+0x3c/0x90)
[  116.370438] [<c02c1b44>] (SyS_write) from [<c0107ea0>] (ret_fast_syscall+0x0/0x28)
[  116.378344] Code: e59f0214 ebed2656 e59f0210 ebed2654 (e5951000) 
[  116.384714] ---[ end trace 2960ceeb42aafca8 ]---
....

I tried to read from ethernet registers the same way (from 4a100000 physical address) and it's working fine... My guess was that I couldn't access the DM Timer control register because the timer itself (or the clock of the timer) were not enabled and I tried the following before accessing register:

omap_dm_timer_enable(cpts->odt);
omap_dm_timer_enable(cpts->odt2);

Also I tried to comment the following string in /drivers/clocksource/time-ti-dm.c in omap_dm_timer_prepare function:
//omap_dm_timer_disable(timer);

Nothing seemed to help...

I am using buildroot to build zImage. The kernel is 4.14.40 linux kernel from git://git.ti.com/processor-sdk/processor-sdk-linux.git (SDK 5.0, commit 47961). My device tree andre attached to the post. What can be the problem, why I can't access DM Timer control register?

https://e2e.ti.com/cfs-file/__key/communityserver-discussions-components-files/791/config_5F00_and_5F00_device_5F00_tree.7z

  • Hi Andrey,

    Are you trying to read timer registers from user space with application code?

    If yes, I would suggest you to try to read 0x48048024 register first with devmem2 and/or omapconf tool. If successful, you need to align your application code to devmem2 and/or omapconf tool software.

    If still fails, you need to check if timer6 is enabled in AM335x PRCM module register CM_PER_TIMER6_CLKCTRL

    Regards,
    Pavel
  • Thank you for the reply!) I am reading the register from kernel space. I'm doing it in cpts_pps_start() function from /drivers/net/ethernet/ti/cpts.c
  • Andrey,

    What about the value in CM_PER_TIMER6_CLKCTRL register? Please check and make sure timer6 is enabled.

    Regarding print registers in kernel space, you can get example code from below e2e thread:

    e2e.ti.com/.../2128676

    Regards,
    Pavel
  • I failed to read from 3-7 timers with help of devmem2 but succeeded to read form timer1 and timer 2 .The error is (for timer 7):
    # devmem2 0x4804a024
    /dev/mem opened.
    Memory mapped at address 0xb6ff4000.
    Bus error

    Then I started to check CM_PER_TIMERX_CLKCTRL registers and they all seemed to be zero (it should be 0x2 I guess):
    # devmem2 0x200080
    /dev/mem opened.
    Memory mapped at address 0xb6fad000.
    Value at address 0x200080 (0xb6fad080): 0x0
    # devmem2 0x2000F0
    /dev/mem opened.
    Memory mapped at address 0xb6f54000.
    Value at address 0x2000F0 (0xb6f540f0): 0x0

    I tried to override these zeros but I didn't manage to do it:
    # devmem2 0x200080 w 0x2
    /dev/mem opened.
    Memory mapped at address 0xb6f68000.
    Value at address 0x200080 (0xb6f68080): 0x0
    Written 0x2; readback 0x2
    # devmem2 0x200080
    /dev/mem opened.
    Memory mapped at address 0xb6f6f000.
    Value at address 0x200080 (0xb6f6f080): 0x0
    #

    What am I doing wrong?
  • I'll try to print these registers from kernel space also...
  • Andrey,

    CM_PER_TIMERX_CLKCTRL register address that you are using (0x200080) seems not correct.

    CM_PER_TIMER6_CLKCTRL is at address 0x44DF8D50. CM_PER (0x44DF8800) + offset (0x550)

    CM_PER_TIMER7_CLKCTRL is at address 0x44DF8D58.

    And timer6/7 should be enabled in kernel DTS file, status okay.

    Regards,
    Pavel
  • Thanks for reply!) Still couldn't access anything on 0x44DF8D50 and 0x44DF8D58 addresses:
    # devmem2 0x44DF8D50
    /dev/mem opened.
    Memory mapped at address 0xb6f17000.
    Bus error
    # devmem2 0x44DF8D58
    /dev/mem opened.
    Memory mapped at address 0xb6f52000.
    Bus error
    #

    Also where did you get these addresses? I thought the right address of the PRCM module is in device tree in the following section:

    prcm@200000 {
    compatible = "ti,am3-prcm";
    reg = <0x200000 0x4000>;

    clocks {
    #address-cells = <0x1>;
    #size-cells = <0x0>;

    clk_32768_ck {
    #clock-cells = <0x0>;

    And the offsets in the AM335xand AMIC110Sitara™ ProcessorsTechnicalReferenceManual (8.1.12ClockModuleRegisters), and there is no 0x550 offset... What am I missing?

    I also tried to read CM_PER_TIMER from kernel space like this (in cpts_pps_start() function from drivers/net/ethernet/ti/cpts.c):

    static void __iomem *mcasp3_base;
    uint32_t value,ui_temp;

    mcasp3_base = ioremap(0x200080, 4);
    value = __raw_readl(mcasp3_base);
    printk(KERN_INFO "!!!<<<TIMER2 CLK CNTRL:%x\n",value);

    mcasp3_base = ioremap(0x2000F0, 4);
    value = __raw_readl(mcasp3_base);
    printk(KERN_INFO "!!!<<<TIMER6 CLK CNTRL:%x\n",value);

    The output is:

    [ 66.943978] !!!<<<TIMER2 CLK CNTRL:0
    [ 66.947790] !!!<<<TIMER6 CLK CNTRL:0

    I'll try to use 0x44DF8D50/0x44F8D58 to read from kernel space instead of 0x200080/0x2000F0...
  • Andrey,

    By mistake I was looking into AM437x TRM.

    For AM335x device, the correct registers are:

    CM_PER_TIMER6_CLKCTRL 0x44E000F0 - CM_PER (0x44E00000) + offset (0XF0)
    CM_PER_TIMER7_CLKCTRL 0x44E0007C - CM_PER (0x44E00000) + offset (0X7C)

    Regards,
    Pavel
  • Using 0x44DF8D50/0x44F8D58 instead of 0x200080/0x2000F0 causes unhandled page fault:
    [ 88.512773] Unhandled fault: external abort on non-linefetch (0x1028) at 0xf9df8d50
    [ 88.520770] pgd = db0bc000
    [ 88.523601] [f9df8d50] *pgd=44c11452(bad)
    [ 88.527823] Internal error: : 1028 [#1] SMP ARM
    [ 88.532561] Modules linked in: rpmsg_rpc rpmsg_char virtio_rpmsg_bus pruss_soc_bus pru_rproc pruss_intc rpmsg_pru rpmsg_core pruss omap_mailbox
    [ 88.546074] CPU: 0 PID: 141 Comm: sh Not tainted 4.14.40 #143
    [ 88.552076] Hardware name: Generic AM33XX (Flattened Device Tree)
    [ 88.558439] task: dbfb81c0 task.stack: dbf96000
    [ 88.563187] PC is at cpts_ptp_enable+0x264/0x730
    [ 88.568010] LR is at 0x0
    [ 88.570652] pc : [<c065bfe0>] lr : [<00000000>] psr: a0000013
    [ 88.577194] sp : dbf97e50 ip : dfdfffb0 fp : 00000000
    [ 88.582646] r10: 00000000 r9 : dbf97f80 r8 : c1ef9350
    [ 88.588104] r7 : dbf44810 r6 : c170aa44 r5 : 0003a048 r4 : dbf44820
    [ 88.594925] r3 : 44ffffff r2 : c170da04 r1 : 44c00000 r0 : f9df8d50
    [ 88.601752] Flags: NzCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment none
    [ 88.609206] Control: 10c5387d Table: 9b0bc019 DAC: 00000051
    [ 88.615217] Process sh (pid: 141, stack limit = 0xdbf96218)
    [ 88.621043] Stack: (0xdbf97e50 to 0xdbf98000)
  • Thanks a lot! 0x44E000F0/ 0x44E0007C addresses seem to be correct:
    # devmem2 0x44E000F0
    /dev/mem opened.
    Memory mapped at address 0xb6f9a000.
    Value at address 0x44E000F0 (0xb6f9a0f0): 0x2
    # devmem2 0x44E0007C
    /dev/mem opened.
    Memory mapped at address 0xb6f17000.
    Value at address 0x44E0007C (0xb6f1707c): 0x2

    By the way where did you get this addresses, why didn't they match the address of PRCM module in device tree? Also according to above output the timers seem to be enabled, also they are enabled in device tree by status = "okey"; What can be the problem?
  • Ok, I see, these addresses are in the AM335x's datasheet (Table 2-2). Can't get why is it "prcm@200000 {" in device tree source file.
  • In am33xx.dtsi file we have:

    l4_wkup: l4_wkup@44c00000 {
    prcm: prcm@200000 {

    0x44c00000 + 0x200000 = 0x44E00000

    When reading timer6 register in kernel space, just before that you should read CM_PER_TIMER6_CLKCTRL/0x44E000F0 register and verify it has the correct value.

    Regards,
    Pavel
  • I've done what you've suggested with the following code:

    #define TIMER6_BASE_REG 0x48048000
    #define TIMER7_BASE_REG 0x4804a000

    /*******************************************/

    static void __iomem *mcasp3_base;
    uint32_t value,ui_temp;

    mcasp3_base = ioremap(0x44E000F0, 4);
    value = __raw_readl(mcasp3_base);
    printk(KERN_INFO "!!!<<<TIMER6 CLK CNTRL:%x\n",value);

    mcasp3_base = ioremap(0x44E0007C, 4);
    value = __raw_readl(mcasp3_base);
    printk(KERN_INFO "!!!<<<TIMER7 CLK CNTRL:%x\n",value);

    /*******************************************/

    //-------------------------------------
    printk(KERN_INFO"!!!Trying to read Timer6 register manualy with readl...\n");
    printk(KERN_INFO"!!!Timer6 control register address:%x...\n",TIMER6_BASE_REG + (OMAP_TIMER_CTRL_REG & 0xff));

    void __iomem *io6 = ioremap(TIMER6_BASE_REG + (OMAP_TIMER_CTRL_REG & 0xff), SZ_4K);
    printk(KERN_INFO"!!!Remapped address:%x...\n",(unsigned long*) io6);
    printk(KERN_INFO"!!!Trying to read...\n");

    unsigned int address6 = 0;
    address6 = readl(io6);
    printk(KERN_INFO"!!!Value:%x...\n",address6);
    printk(KERN_INFO"!!!Reading done succesfully...\n");
    //-------------------------------------

    //-------------------------------------
    printk(KERN_INFO"!!!Trying to read Timer7 register manualy with readl...\n");
    printk(KERN_INFO"!!!Timer7 control register address:%x...\n",TIMER7_BASE_REG + (OMAP_TIMER_CTRL_REG & 0xff));

    void __iomem *io7 = ioremap(TIMER7_BASE_REG + (OMAP_TIMER_CTRL_REG & 0xff), SZ_4K);
    printk(KERN_INFO"!!!Remapped address:%x...\n",(unsigned long*) io7);
    printk(KERN_INFO"!!!Trying to read...\n");

    unsigned int address7 = 0;
    address7 = readl(io7);
    printk(KERN_INFO"!!!Value:%x...\n",address7);
    printk(KERN_INFO"!!!Reading done succesfully...\n");
    //-------------------------------------

    The output is:
    [ 68.365340] !!!<<<TIMER6 CLK CNTRL:2
    [ 68.369086] !!!<<<TIMER7 CLK CNTRL:2
    [ 68.372820] !!!Trying to read Timer6 register manualy with readl...
    [ 68.379414] !!!Timer6 control register address:48048024...
    [ 68.385190] !!!Remapped address:fa048024...
    [ 68.389569] !!!Trying to read...
    [ 68.392950] Unhandled fault: external abort on non-linefetch (0x1028) at 0xfa048024


    The timers seem to be enabled, but still accessing timer's registers triggers Unhandled page fault... Can't get what is going on with timers( I'll be digging further...
  • Andrey,

    I would suggest you to simplify your code as:

    static void __iomem *timer6_base;
    uint32_t value, temp;

    timer6_base = ioremap(0x48048000, SZ_4K);

    printk("TIMER6 IRQSTATUS_RAW = %x\n", __raw_readl(timer6_base + 0x24);

    Regards,
    Pavel
  • Tried to use the simplified code:
    /*******************************************/

    static void __iomem *mcasp3_base;
    uint32_t value,ui_temp;

    mcasp3_base = ioremap(0x44E000F0, 4);
    value = __raw_readl(mcasp3_base);
    printk(KERN_INFO "!!!<<<TIMER6 CLK CNTRL:%x\n",value);

    mcasp3_base = ioremap(0x44E0007C, 4);
    value = __raw_readl(mcasp3_base);
    printk(KERN_INFO "!!!<<<TIMER7 CLK CNTRL:%x\n",value);

    /*******************************************/


    static void __iomem *timer6_base;

    timer6_base = ioremap(0x48048000, SZ_4K);

    printk("TIMER6 IRQSTATUS_RAW = %x\n", __raw_readl(timer6_base + 0x24));


    It still triggers Unhandled page fault...
  • Andrey,

    You can also try to align with the code used in /drivers/net/ethernet/ti/cpts.c

    #define cpts_read32(c, r) readl_relaxed(&c->reg->r)

    u32 r = cpts_read32(cpts, intstat_raw);


    Explore how CPTS_INTSTAT_RAW register is read and reuse that approach.

    Regards,
    Pavel
  • It's strange but I figured out that the reason of this unhandled page fault was two options in my kernel config file: CONFIG_TI_1PPS_DM_TIMER and CONFIG_TI_CPTS. If these options are both enabled then the timers are not available anymore. I didn't completely get why but maybe somehow cpts driver or some other code some kind of lock the timers or something...
  • Andrey,

    Seems that you are using wrong defconfig file for your AM335x Beagle Bone Black compatible board. In the AM335x defconfig file we this disabled by default:

    linux-kernel/arch/arm/configs/tisdk_am335x-evm_defconfig
    # CONFIG_TI_1PPS_DM_TIMER is not set

    While this Timer feature is enabled by default for AM57x device.

    linux-kernel/arch/arm/configs/tisdk_am57xx-evm_defconfig
    CONFIG_TI_1PPS_DM_TIMER=y


    Regards,
    Pavel