reading and writing a register linux device driver

4.6k views Asked by At

I am writing a watchdog timer device driver for Pandaboard(Omap4) for educational purposes(I know the driver already exist). I want to know how I can access watchdog timer registers (e.g. WDT_WLDR(timer load register) has address offset 0x0000002C and Physical L4 interconnect address 0x4A31402C) in kernel space. Please guide in the write direction so that I can write my own watchdog device driver. Regards

================================================================================== Now I wrote this module however it is not working how it is supposed to be

ioread32(reg_WLDR) returns 0

==================================================================================

dmesg returns

[   72.798461] Now in kernel space
[   72.798583] Starting to read
[   72.798583] 
[   72.798645] 0
[   72.798645] ------------[ cut here ]------------
[   72.798645] WARNING: at arch/arm/mach-omap2/omap_l3_noc.c:113 l3_interrupt_handler+0x)
[   72.798706] L3 custom error: MASTER:MPU TARGET:L4CFG
[   72.798706] Modules linked in: test_device(O+)
[   72.798706] 2nd Read
[   72.798736] 
[   72.798736]   (null)
[   72.798736] 
[   72.798797] [<c001a0f4>] (unwind_backtrace+0x0/0xec) from [<c003a298>] (warn_slowpath)
[   72.798797] [<c003a298>] (warn_slowpath_common+0x4c/0x64) from [<c003a344>] (warn_slo)
[   72.798797] [<c003a344>] (warn_slowpath_fmt+0x30/0x40) from [<c002efe8>] (l3_interrup)
[   72.798858] [<c002efe8>] (l3_interrupt_handler+0x120/0x16c) from [<c0092af4>] (handle)
[   72.798889] [<c0092af4>] (handle_irq_event_percpu+0x74/0x1f8) from [<c0092cb4>] (hand)
[   72.798889] [<c0092cb4>] (handle_irq_event+0x3c/0x5c) from [<c0095958>] (handle_faste)
[   72.798950] [<c0095958>] (handle_fasteoi_irq+0xd4/0x110) from [<c00925b4>] (generic_h)
[   72.798950] [<c00925b4>] (generic_handle_irq+0x30/0x48) from [<c0014208>] (handle_IRQ)
[   72.798950] [<c0014208>] (handle_IRQ+0x78/0xb8) from [<c00084b8>] (gic_handle_irq+0x8)
[   72.799072] [<c00084b8>] (gic_handle_irq+0x80/0xac) from [<c04b74c4>] (__irq_svc+0x44)
[   72.799072] Exception stack(0xece47ec0 to 0xece47f08)
[   72.799102] 7ec0: ecdbc0e0 00000004 c0748c64 00000000 000080d0 c0743a88 ecdbc0e0 ee270
[   72.799102] 7ee0: c0013328 00000000 c0c99720 00020348 ece46000 ece47f08 c0081c38 c03ac
[   72.799102] 7f00: 60000013 ffffffff
[   72.799102] [<c04b74c4>] (__irq_svc+0x44/0x60) from [<c03a610c>] (sk_prot_alloc+0x50/)
[   72.799102] [<c03a610c>] (sk_prot_alloc+0x50/0x14c) from [<c03a6268>] (sk_alloc+0x1c/)
[   72.799102] [<c03a6268>] (sk_alloc+0x1c/0xd8) from [<c042789c>] (unix_create1+0x50/0x)
[   72.799255] [<c042789c>] (unix_create1+0x50/0x178) from [<c0427a34>] (unix_create+0x7)
[   72.799255] [<c0427a34>] (unix_create+0x70/0x90) from [<c03a3878>] (__sock_create+0x1)
[   72.799255] [<c03a3878>] (__sock_create+0x19c/0x2b8) from [<c03a3a10>] (sock_create+0)
[   72.799316] [<c03a3a10>] (sock_create+0x40/0x48) from [<c03a3b8c>] (sys_socket+0x2c/0)
[   72.799346] [<c03a3b8c>] (sys_socket+0x2c/0x68) from [<c0013160>] (ret_fast_syscall+0)
[   72.799346] ---[ end trace 4316415ef3b8cf4c ]---

==================================================================================

Code

#include </home/salman/kernel_panda_compile/linux/include/linux/version.h>
#include </home/salman/kernel_panda_compile/linux/include/linux/module.h>
#include </home/salman/kernel_panda_compile/linux/include/linux/miscdevice.h>
#include </home/salman/kernel_panda_compile/linux/include/linux/highmem.h>
#include </home/salman/kernel_panda_compile/linux/include/linux/fs.h>
#include </home/salman/kernel_panda_compile/linux/arch/arm/include/asm/unistd.h>
#include </home/salman/kernel_panda_compile/linux/include/linux/unistd.h>
#include </home/salman/kernel_panda_compile/linux/include/linux/kernel.h>
#include </home/salman/kernel_panda_compile/linux/include/linux/moduleparam.h>
#include </home/salman/kernel_panda_compile/linux/include/linux/io.h>
#include </home/salman/kernel_panda_compile/linux/arch/arm/include/asm/io.h>
#include </home/salman/kernel_panda_compile/linux/include/linux/ioport.h>


static void *reg_WLDR;
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Muhammad Salman Khalid");
MODULE_VERSION("0.100");



static int start_module(void)
{
int retval;

printk(KERN_INFO "Now in kernel space\n");

//  retval = misc_register(&our_device);
    reg_WLDR = ioremap(0x4A31402C,0x001);//0x4A31402C is the physical address (L4 Interconnect) of WDT_WLDR register of watchdog timer(pandaboard omap4) it is readable & writeable 
    iowrite32(252,reg_WLDR);
printk(KERN_ALERT "Starting to read\n");
printk(KERN_ALERT "\n%d\n",ioread32(reg_WLDR));
printk(KERN_ALERT "2nd Read\n");
    printk(KERN_ALERT "\n%p\n",ioread32(reg_WLDR));
iounmap(reg_WLDR);
return retval;
 }


static void finish_module(void)
{


printk(KERN_INFO "Leaving kernel space\n");

//  misc_deregister(&our_device);


return;
}








module_init(start_module);
module_exit(finish_module);
2

There are 2 answers

1
a.saurabh On

If you plan to use Linux Kernel then you can use following api's for reading and writing to peripheral registers: 1. ioremap() (Map the physical address into kernel virtual memory) 2. ioread32() (Read from 32 bit register) 3. iowrite32() (Write to 32 bit register)

and finally iounmap() (Unmapping memory which you allocated with ioremap())

Now please refer to below two things: 1. OMAP4 datasheet/manual to get the physical address of registers. 2. Link for explaining above mentioned api's: http://www.makelinux.net/ldd3/chp-9-sect-4

0
a.saurabh On

Try replacing this line: ioremap(0x4A31402C,0x001) in your code with this: ioremap(0x4A31402C,0x04) and then check.