This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Linux/AM3354: ioremap segfault on hardware registers which are used by unknown process

Part Number: AM3354

Tool/software: Linux

I'm still trying to gain access to MCSPI0-registers on the BeagleBone Black Wireless mapped at 0x4800_0000->0x4800_0FFF

With loadable kernel module, i try to request_mem_region, and use ioremap() after. request_mem_region returns NULL, and forcing through ioremap() gives segmentation fault.

#include <linux/init.h>             // Macros used to mark up functions e.g., __init __exit
#include <linux/module.h>           // Core header for loading LKMs into the kernel
#include <linux/kernel.h>           // Contains types, macros, functions for the kernel
#include <linux/version.h>
#include <linux/ioport.h>
#include <asm/io.h>
MODULE_LICENSE("GPL");              ///< The license type -- this affects runtime behavior
MODULE_AUTHOR("Derek Molloy");      ///< The author -- visible when you use modinfo
MODULE_DESCRIPTION("A simple Linux driver for the BBB.");  ///< The description -- see modinfo
MODULE_VERSION("0.1");              ///< The version of the module
#define DRIVER_NAME     "TEST"
#define MCSPI0_START    0x48030000
#define MCSPI0_SIZE     0xFFF
static char *name =     "world";        ///< An example LKM argument -- default value is "world"
void *regs;
long unsigned int int_reg;
module_param(name, charp, S_IRUGO); ///< Param desc. charp = char ptr, S_IRUGO can be read/not changed
MODULE_PARM_DESC(name, "The name to display in /var/log/kern.log");  ///< parameter description
/** @brief The LKM initialization function
 *  The static keyword restricts the visibility of the function to within this C file. The __init
 *  macro means that for a built-in driver (not a LKM) the function is only used at initialization
 *  time and that it can be discarded and its memory freed up after that point.
 *  @return returns 0 if successful
 */
static void __exit helloBBB_exit(void){
   printk(KERN_INFO "EBB: Goodbye %s from the BBB LKM!\n", name);
}
static int request_memory(void)
{
        if (request_mem_region( MCSPI0_START,MCSPI0_SIZE, DRIVER_NAME ) == NULL)
        {
                printk(KERN_INFO "Could not reserve memory\n");
                return 1;
        } 
        return 1;
}

static int testfun(void)
{
        //printk(KERN_INFO "testRead: %d from regs!\n", (int)int_reg);
        return 0;
}


static int __init helloBBB_init(void){
        printk(KERN_INFO "EBB: Hello %s from the BBB LKM!\n", name);
        if (request_memory() != 0)
        {
        regs = ioremap(0x48030000, 0xFFF);
        int_reg = ioread8(regs);
        testfun();
        }
   return 0;
}


module_init(helloBBB_init);
module_exit(helloBBB_exit);

cat /proc/iomem | grep spi:

48030000-480303ff : /ocp/spi@48030000

Is there any way for me to shut down the process occupying hardware registers to gain access? Have I missed something?

  • Hi Jonas,

    Do you use AM335x PSDK Linux? If yes, which version? Latest version is 5.03:

    software-dl.ti.com/.../index_FDS.html

    Check also below e2e thread:

    e2e.ti.com/.../793506

    Regards,
    Pavel
  • Thanks for the help!

    Enabling the CM_PER_SPI0_CLKCTRL allowed me to get access to the mcSPI0-registers, i am now able to read all of them. Still, there is a process running which is preventing me from reserving the memory. Any idea of how i could kill it?

    (Example LKM printing all addresses to kernel log: /var/log/kern.log)



    #include <linux/init.h> // Macros used to mark up functions e.g., __init __exit #include <linux/module.h> // Core header for loading LKMs into the kernel #include <linux/kernel.h> // Contains types, macros, functions for the kernel #include <linux/version.h> #include <linux/ioport.h> #include <asm/io.h> MODULE_LICENSE("GPL"); ///< The license type -- this affects runtime behavior MODULE_AUTHOR("Derek Molloy"); ///< The author -- visible when you use modinfo MODULE_DESCRIPTION("A simple Linux driver for the BBB."); ///< The description -- see modinfo MODULE_VERSION("0.1"); ///< The version of the module #define DRIVER_NAME "TEST" #define MCSPI0_START 0xb6fd5000 #define MCSPI0_SIZE 0xFFF static char *name = "world"; ///< An example LKM argument -- default value is "world" void *regs; long unsigned int int_reg; module_param(name, charp, S_IRUGO); ///< Param desc. charp = char ptr, S_IRUGO can be read/not changed MODULE_PARM_DESC(name, "The name to display in /var/log/kern.log"); ///< parameter description static void __exit helloBBB_exit(void){ printk(KERN_INFO "EBB: Goodbye %s from the BBB LKM!\n", name); } static int request_memory(void) { if (request_mem_region( MCSPI0_START,MCSPI0_SIZE, DRIVER_NAME ) == NULL) { printk(KERN_INFO "Could not reserve memory\n"); return 1; } return 1; } static int testfun(void) { //printk(KERN_INFO "testRead: %d from regs!\n", (int)int_reg); return 0; } static int __init helloBBB_init(void){ printk(KERN_INFO "EBB: Hello %s from the BBB LKM!\n", name); if (request_memory() != 0) { int n = 0; void *regs = ioremap(0x48000000, 0xFFF); for (n = 0; n <= 0xFFF; n++) { printk(KERN_INFO "testval %d\n",ioread32(regs+n)); } testfun(); } return 0; } module_init(helloBBB_init); module_exit(helloBBB_exit);

  • (This is done on the current latest debian image for the BeagleBone Black by the way)
  • Jonas,

    "Still, there is a process running which is preventing me from reserving the memory. Any idea of how i could kill it?"

    "This is done on the current latest debian image for the BeagleBone Black"

    In this forum we can help for question related to Arago Linux, the one that comes with AM335x TI PSDK Linux. For Debian Linux support, you need to check with the beagleboard community.

    Regards,
    Pavel