6

I trying to write into system control register from linux kernel. But result is segmentation fault:

Unable to handle kernel paging request at virtual address 20050004

Code from kernel module:

#define REGBASE 0x20050000

void writeRegister(void){
    __raw_writel( 0x00000002, REGBASE + 0x0004 );
}

How to access on-chip memory where system control registers located?

HardRock
  • 81
  • 1
  • 6
  • Possible duplicate: [What does `request_mem_region()` do?](http://stackoverflow.com/questions/7682422/what-does-request-mem-region-actually-do-and-when-it-is-needed) – artless noise Jun 05 '13 at 14:31

2 Answers2

7

I'm guessing that REGBASE is a physical address and not a virtual one. You need to ask the kernel to map it into the address space before you can use it. Most of the time you'd use ioremap to map it in.

For example:

void __iomem *io = ioremap(REGBASE, SZ_4K);
writel(0x00000002, io + 0x0004);
tangrs
  • 9,709
  • 1
  • 38
  • 53
2

I know that is not exactly the answer you are looking for, but there is a way to do it in user space, if you want to avoid to program a kernel module for your application.

This is an example for GPIO access in Raspberry Pi3:

#define RASPBERRY_PI_PERI_BASE  0x3F000000
#define GPIO_BASE               (RASPBERRY_PI_PERI_BASE + 0x200000) // GPIO controller

#define BLOCK_SIZE              (4*1024)

static volatile uint32_t *gpio = NULL;

int GPIO_init(void) {
    int   fd;

    if ((fd = open ("/dev/mem", O_RDWR | O_SYNC | O_CLOEXEC) ) < 0) return -1; // printf("Failed to open /dev/mem, try checking permissions.\n");
    gpio = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPIO_BASE);
    if ((int32_t)gpio == -1) return -1; // printf("Failed mmap (GPIO): %s\n", strerror (errno)); 

    return 0;
}

Now you have a simply pointer variable *gpio that links to the hardware's memory address. You do it mapping "mem" device on memory, that exists for you "for free" :-)

Regards.

omotto
  • 1,721
  • 19
  • 20