Reading PIT registers with C code

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Reading PIT registers with C code

Jump to solution
1,615 Views
michaelworster
Contributor IV

I'm trying to read one of the PIT (Perioditic Interrupt Timers) registers. For now, I don't really care which one I just want to run a test read from a Linux module. I've tried two methods:

    unsigned int PIT_MCR = 0;

    //Attempt one:

    //PIT_MCR = *((unsigned int *)(void *)(0x40037000));

    //Attempt two:

    PIT_MCR = __raw_readl(0x40037000);

    printk("PIT_MCR(0x4003_7000): %u\n", PIT_MCR);

Both of these attempts to access the register fail in the same way. An "Oops" message stating the memory can't be reached:

"Unable to handle kernel paging request at virtual address 40037000"

Is there anything special that has to be done in order to access/read from these registers?

Labels (3)
0 Kudos
1 Solution
862 Views
timesyssupport
Senior Contributor II

Hi Mike,

Please see inline my responses below:

>>When I look at the memory map, that's not accessible:
>>/usr # cat /proc/iomem
>>00001000-00001000 : offset_jr0
>>
>>40034000-400341ff : fsl-usb2-udc
>><-- Should have been here
>>40038000-40038fff : mxc_pwm.1

The information in /proc/iomem comes from the kernel driver mapping the I/O memory using ioremap. The PIT register is not visible in /proc/iomem for this reason.

>>And when I try to check out what value is in this region of memory:

>>unsigned int PIT_MCR = 0;

>>PIT_MCR = *((unsigned int *)(void *)(0x40037000));

>>printk("In the HW init\nPIT_MCR(0x4003_7000): %u\n", PIT_MCR);

>>the result is an Oops: Unable to handle kernel paging request at virtual address 40037000

>>pgd = 863c0000

>>[40037000] *pgd=00000000

>>Internal error: Oops: 5 [#1]

>>Which is not too surprising because it's not in the memory map. I'd like to ask what is different and what you had to do in order to 

>>access/manipulate the memory in the PIT registers.

In order to access the registers, the driver / kernel module needs to map the physical memory to virtual memory using ioremap. Alternatively it can also be done using the MVF_IO_ADDRESS macro for Vybrid which returns the virtual memory address for a given physical address.

<Examples>

void __iomem *pit_mcr_register_base;

pit_mcr_register_base = MVF_IO_ADDRESS(0x40037000)

pit_mcr_register_val = readl(pit_mcr_register_base);

or

pit_mcr_register = (uint32_t *) ioremap(0x40037000, <size>)

pit_mcr_register_val = readl(pit_mcr_register);

Thanks,

Linux Engineer

Timesys Support

View solution in original post

0 Kudos
3 Replies
862 Views
michaelworster
Contributor IV

I found one example which shows that the proper Clock Gating register must be enabled prior to accessing the PIT registers.

 

set_ccgr_register(PIT_CCGR_INDEX, CLK_ON_ALL_MODES); // PIT_CCGR_INDEX = 23 CLK_ON_ALL_MODES = 0x2

 

The gist of this function is that the CCM CCRG1 (0x4006B044) needs to be up dated to access the PIT module, however the issue is that this CCM CCRG1 register itself is not accessible and any attempt to access it results in the same type of Oops kernel paging fault.

I'm not sure if there's an additional step to access the CCM registers, or, more likely, there's a problem with the manner in which I'm attempting to access registers in general from a kernel module.

0 Kudos
863 Views
timesyssupport
Senior Contributor II

Hi Mike,

Please see inline my responses below:

>>When I look at the memory map, that's not accessible:
>>/usr # cat /proc/iomem
>>00001000-00001000 : offset_jr0
>>
>>40034000-400341ff : fsl-usb2-udc
>><-- Should have been here
>>40038000-40038fff : mxc_pwm.1

The information in /proc/iomem comes from the kernel driver mapping the I/O memory using ioremap. The PIT register is not visible in /proc/iomem for this reason.

>>And when I try to check out what value is in this region of memory:

>>unsigned int PIT_MCR = 0;

>>PIT_MCR = *((unsigned int *)(void *)(0x40037000));

>>printk("In the HW init\nPIT_MCR(0x4003_7000): %u\n", PIT_MCR);

>>the result is an Oops: Unable to handle kernel paging request at virtual address 40037000

>>pgd = 863c0000

>>[40037000] *pgd=00000000

>>Internal error: Oops: 5 [#1]

>>Which is not too surprising because it's not in the memory map. I'd like to ask what is different and what you had to do in order to 

>>access/manipulate the memory in the PIT registers.

In order to access the registers, the driver / kernel module needs to map the physical memory to virtual memory using ioremap. Alternatively it can also be done using the MVF_IO_ADDRESS macro for Vybrid which returns the virtual memory address for a given physical address.

<Examples>

void __iomem *pit_mcr_register_base;

pit_mcr_register_base = MVF_IO_ADDRESS(0x40037000)

pit_mcr_register_val = readl(pit_mcr_register_base);

or

pit_mcr_register = (uint32_t *) ioremap(0x40037000, <size>)

pit_mcr_register_val = readl(pit_mcr_register);

Thanks,

Linux Engineer

Timesys Support

0 Kudos
862 Views
karina_valencia
NXP Apps Support
NXP Apps Support

timesyssupport can you help on this case?

0 Kudos