How to access GPIO registers in loadable kernel module

Hi,

I am implementing a kernel module for reading inputs from several GPIO
pins synchronously. I found that gpio_get_value() takes to long so I'd
like to read from the GPIO register directly to get the input level
for several pins without calling gpip_get_value() for several times.

I've tried to read the register directly and the kernel crashed. Can
anyone guide me to read hardware registers in kernel module?

Thanks,
Chuankai

To do what you describe you need to first map the io space/registers into your address space and then you can access it. There is a call you need to make to map the IO space into the kernels address space first. I am not that familiar with the current kernel modules, but that is what you need to look for. Also remember to release the mapping when you are done, or various safety checks will catch you. The free electron slides had a section about those calls.

http://www.kernel.org/doc/Documentation/gpio.txt

2010/10/3 Chuankai <lin.chuankai@gmail.com>

This is my implementation:

    int j, tmp, val;
    void __iomem *base;
    volatile unsigned long *ptr;
    if (!request_mem_region (0x49058000, 1024, "gpio-test")) {
      printk(KERN_INFO "request_mem_region failed");
      result = -1;
      goto fail;
    }

    base = ioremap (0x49058000, 1024);
    if (!base) {
      printk(KERN_INFO "ioremap failed");
      result = -1;
      goto fail;
    }
    val = *(int*) 0x49058038;
    printk(KERN_INFO "val: %d", val);

However, it fails with OOPS.... Any ideas?

Regards,
Chuankai

Chuankai wrote:

This is my implementation:

    int j, tmp, val;
    void __iomem *base;
    volatile unsigned long *ptr;
    if (!request_mem_region (0x49058000, 1024, "gpio-test")) {
      printk(KERN_INFO "request_mem_region failed");
      result = -1;
      goto fail;
    }

    base = ioremap (0x49058000, 1024);
    if (!base) {
      printk(KERN_INFO "ioremap failed");
      result = -1;
      goto fail;
    }
    val = *(int*) 0x49058038;
    printk(KERN_INFO "val: %d", val);

However, it fails with OOPS.... Any ideas?

  Is your GPIO bank clocked? The TRM reckons GPIO6 is clocked by
GPIO6_ICLK and you probably want to clk_get() and then clk_enable()
it before you try to mess with the registers in that bank.

  GPIO6_ICLK is fed by PER_L4_CLK which is, I think, active by
default but you may need to set its speed if it's programmable,

  Also, you will want to use (volatile int *) to make sure the
processor doesn't cache the results of your memory dereference,
though __raw_readl() /__raw_writel() in <asm/io.h> are, I believe,
the Right Way du jour to do this.

Richard.

This is my implementation:

    int j, tmp, val;
    void __iomem *base;
    volatile unsigned long *ptr;
    if (!request_mem_region (0x49058000, 1024, "gpio-test")) {
      printk(KERN_INFO "request_mem_region failed");
      result = -1;
      goto fail;
    }

    base = ioremap (0x49058000, 1024);
    if (!base) {
      printk(KERN_INFO "ioremap failed");
      result = -1;
      goto fail;
    }
    val = *(int*) 0x49058038;
    printk(KERN_INFO "val: %d", val);

However, it fails with OOPS.... Any ideas?

You need to use the virtual address returned from ioremap, not the
physical address.
                 val = *(int *)((char *)base + 0x0038));

BTW, accessing registers like this is truly horrible :frowning: At least use
the predefined OMAP structures...