You don't need to create a kernel module to do this. Linux already provides the user space mmap() functionality to do this. Here is an userspace example I posted earlier on this group. And it works on the MPC8349 if your bootloader/bios maps the IMMR to 0xE0000000 address area. It is EXTREMELY IMPORTANT to note that which ever registers you are writing to may also be written/read by the kernel device drivers. So make sure you don't load any device driver that undoes what you are trying to do.
Full man can be found at
formatting link
Example: /* * Maps real memory address to a virtual address. The virtual address * then could be used to read/write the real memory as if it was accessed * directly. * Adapted by Janaka Subhawickrama. Copyright 2007. * GPL software. */ #include #include #include #include #include #include #include #include #include #include
//Virtual address that is associated with the physical address static char *regmap_addr = NULL;
//The following is the physical address of memory mapped registers of the CPU #define REGISTRY_MAP_ADDRESS_OFFSET (0xE0000000) #define REGISTRY_MAP_SIZE (0x000FFFFF) #define GPIO2_DATA_DIR_REG_OFFSET (0x00000D00) #define GPIO2_DATA_REG_OFFSET (0x00000D08)
#define GPIO2_DONE_PIN (0x00800000) #define GPIO2_FAULT_PIN (0x00400000) #define GPIO2_PROGB_PIN (0x01000000)
int main(int argc, char *argv[]) { int devmem; // this is the "/dev/mem" descriptor //Registers of the CPU I am using is 32bit volatile unsigned int uiGet; volatile unsigned int *ptmp = NULL;
//On embedded systems you may have to mknod /dev/mem printf("\nOpening /dev/mem"); devmem = open("/dev/mem", O_RDWR | O_SYNC);
if (devmem < 0) { printf("\nOpening of /dev/mem failed with (%d) %s\n", errno, strerror(errno)); return -1; }
printf("\nMapping Memory mapped registers at %08X with size %08X", REGISTRY_MAP_SIZE, REGISTRY_MAP_ADDRESS_OFFSET); regmap_addr = (char *)mmap( 0, REGISTRY_MAP_SIZE, PROT_READ| PROT_WRITE, MAP_SHARED, devmem, REGISTRY_MAP_ADDRESS_OFFSET);
if (regmap_addr == (char *)MAP_FAILED) { printf("\nCould not map registers (%d) %s", errno, strerror(errno)); close(devmem); return -1; }
//Now you can write to CPU registers as if you were from a boot loader
//Setup directions of GPIO pins *(volatile unsigned int *)(regmap_addr + GPIO2_DATA_DIR_REG_OFFSET) = GPIO2_FAULT_PIN | GPIO2_PROGB_PIN; //Turn some GPIO Pins on *(volatile unsigned int *)(regmap_addr + GPIO2_DATA_REG_OFFSET) = GPIO2_FAULT_PIN | GPIO2_PROGB_PIN; //Get some values of GPIO lines uiGet = *(volatile unsigned int *)(regmap_addr + GPIO2_DATA_REG_OFFSET);
printf("\nGPIO register %08X", uiGet);
//Cleanup munmap((void *)REGISTRY_MAP_ADDRESS_OFFSET, REGISTRY_MAP_SIZE); close(devmem); return 0;