Context
I am developing a LKM for a communication with a CPLD, which involves access to GPIO. To prototype this, I use a beaglebone black equipped with a TI processor, the Sitara AM3358 (ARM Cortex-A8). I built a minimal system using buildroot (Linux kernel is 4.6). For performance reason, I want a direct access to the GPIO registers instead of using gpiolib.
Note: I am a beginner in development of LKMs but I am used to develop device drivers for microcontrollers
What I did
As seen in this post : What does request_mem_region() actually do and when it is needed?
I tried to use request_mem_region with ioremap before reading and writing to registers.
The code looks like this :
if(request_mem_region(GPIO0_BASE_ADDR, GPIO_BLOCK_SIZE, DEVICE_NAME) == NULL)
{
printk(KERN_ALERT
"[%s] Unable to request mem region for GPIO0\n",
DEVICE_NAME);
status = -EBUSY;
goto error;
}
gpio0 = ioremap(GPIO0_BASE_ADDR, GPIO_BLOCK_SIZE);
//Set somme pins as output
gpio_oe = ioread32(gpio0 + GPIO_OE);
gpio_oe &= ~GPIO0_PIN_MASK;
iowrite32(gpio_oe, gpio0 + GPIO_OE);
The request_mem_region fails because some other driver or "entity" has already reserved this region.
/proc/iomem shows :
40300000-4030ffff : 40300000.ocmcram
44e07000-44e07fff : /ocp/gpio@44e07000
44e09000-44e0afff : /ocp/serial@44e09000
44e0b000-44e0bfff : /ocp/i2c@44e0b000
44e10650-44e10653 : gmii-sel
44e10800-44e10a37 : pinctrl-single
44e10f90-44e10fcf : /ocp/l4_wkup@44c00000/scm@210000/dma-router@f90
48042000-480423ff : /ocp/timer@48042000
48044000-480443ff : /ocp/timer@48044000
48046000-480463ff : /ocp/timer@48046000
48048000-480483ff : /ocp/timer@48048000
4804a000-4804a3ff : /ocp/timer@4804a000
4804c000-4804cfff : /ocp/gpio@4804c000
48060000-48060fff : /ocp/mmc@48060000
4819c000-4819cfff : /ocp/i2c@4819c000
481ac000-481acfff : /ocp/gpio@481ac000
481ae000-481aefff : /ocp/gpio@481ae000
481d8000-481d8fff : /ocp/mmc@481d8000
49000000-4900ffff : edma3_cc
4a100000-4a1007ff : /ocp/ethernet@4a100000
4a101000-4a1010ff : /ocp/ethernet@4a100000/mdio@4a101000
4a101200-4a1012ff : /ocp/ethernet@4a100000
80000000-9fdfffff : System RAM
80008000-80a70ac7 : Kernel code
80c00000-814b381f : Kernel data
This line 44e07000-44e07fff : /ocp/gpio@44e07000 is the memory area I am trying to reserve. Hmm little problem here.
Questions
Two approaches here.
- My driver is the only one in his world to access to GPIO0 block (but just using a few pins)
I have to find which driver has reserved the memory and remove it. But how ? Is it pinctrl-single ? The "ocp" appears in the device tree for the beaglebone, but I don't understand very well the relation it might have between what is in the device tree and this reserved memory region...
- Several drivers are potentially accessing the GPIO0 block
Let's imagine a use case where some driver wants access to GPIO0.1 and another one wants access to GPIO0.2, both of them need access to GPIO0 registers. The exclusive reservation of memory is no more possible here, how can this be properly managed ? Specificaly in cases like above where I have somme sequences of read-modify-write...
TL;DR
In a linux kernel module how to get access to registers which can be accessed from other drivers ? How to manage locking mechanisms during the access ?
Thanks