Hi, as far as you use SEMA4 on Linux userspace, you don't even need to enable the kernel driver. You can just access to SEMA4 registers directly via mmap'ing.
How to access SEMA4 registers
1. Find out the SEMA4 register addresses (base, gates, INE, NTF, etc). They should be on the reference manual. For example, SEMA4 base address for the iMX8MP is 0x30AC0000.
2. MMAP the base address so that you can access it from the userspace. You can access related registers by adding proper offsets to the base address. One thing to be aware of is that each register needs to be accessed by a specific type of pointer. (u8, u16, 32, etc). It's written in the reference manual.
* You can't lock/unlock CP1 gates from CP0, vice versa. iMX8 looks where register access coming from and protect any improper write access.
Ok, here's a rough sample code how to access the register. Hope this helps to give you an idea.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdbool.h>
#include <fcntl.h>
#include <string.h>
#include <assert.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#define PAGESIZE (4096)
#define SEMA4_BASE (0x30AC0000u)
#define SEMA4_UNLOCK (0x0)
#define SEMA4_CP0_LOCK (0x1)
#define SEMA4_CP1_LOCK (0x2)
int main(void)
{
void* pSEMA4 = NULL;
volatile __u8 *mmPtr = NULL;
int fd = open("/dev/mem", O_RDWR);
pSEMA4 = mmap(NULL, PAGESIZE, PROT_READ|PROT_WRITE,
MAP_SHARED, fd, SEMA4_BASE);
close(fd);
assert(pSEMA4 != MAP_FAILED);
// Locking SEMA4 Gate0 (CP0)
// CP0 refers the application core, in my case it's A53.
mmPtr = (__u8 *)(pSEMA4 + 0x0); // Gate0 offset is 0x0
*mmPtr = SEMA4_CP0_LOCK;
if (*mmPtr == SEMA4_CP0_LOCK) {
printf("SEMA4 lock success\n");
} else {
printf("SEMA4 lock failed : Currently locked by the other core\n");
}
// Unlocking
*mmPtr = SEMA4_UNLOCK;
if (*mmPtr == SEMA4_UNLOCK) {
printf("SEMA4 unlock success\n");
} else {
printf("SEMA4 unlock failed : Currently locked by the other core\n");
}
}