-
Notifications
You must be signed in to change notification settings - Fork 13
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
rngb: add the support for TRNG for imx6ull
The driver starts by creating basic structures for a phonix driver. Then it sets flags for tests of rngb and seeding, sequentially. The last things is waiting for system messaga. JIRA: RTOS-317
- Loading branch information
1 parent
05214c6
commit 14ec313
Showing
1 changed file
with
306 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,306 @@ | ||
/* | ||
* Phoenix-RTOS | ||
* | ||
* i.MX 6ULL RNGB driver | ||
* | ||
* Copyright 2023 Phoenix Systems | ||
* Author: Dawid Szpejna | ||
* | ||
* This file is part of Phoenix-RTOS. | ||
* | ||
* %LICENSE% | ||
*/ | ||
|
||
#include <string.h> | ||
#include <fcntl.h> | ||
#include <errno.h> | ||
#include <stdint.h> | ||
#include <stdio.h> | ||
#include <unistd.h> | ||
#include <posix/utils.h> | ||
#include <sys/debug.h> | ||
#include <sys/platform.h> | ||
#include <sys/interrupt.h> | ||
#include <sys/threads.h> | ||
#include <sys/mman.h> | ||
#include <sys/msg.h> | ||
|
||
|
||
#define RNG_VER 0 | ||
#define RNG_CMD 1 | ||
#define RNG_CR 2 | ||
#define RNG_SR 3 | ||
#define RNG_ESR 4 | ||
#define RNG_OUT 5 | ||
|
||
|
||
#define RNGB_START_ADDRESS 0x02284000 | ||
#define RNGB_IRQ (6 + 32) | ||
|
||
|
||
#define ERROR_OCCURRED 3U | ||
#define MMAP_SIZE 4096 | ||
|
||
|
||
#define FIELD(address, top, length) (((*(address)) << (31 - (top))) >> (32 - (length))) | ||
|
||
|
||
/* intr_st indicates status of interrupts */ | ||
static struct { | ||
volatile uint32_t *base; | ||
volatile uint32_t intr_st; | ||
uint32_t port; | ||
|
||
handle_t lock; | ||
handle_t cond; | ||
} common_rngb; | ||
|
||
|
||
static int rngb_intr(unsigned int n, void *arg) | ||
{ | ||
uint32_t filed = *(common_rngb.base + RNG_SR); | ||
|
||
/* Self tests are done */ | ||
if ((filed & 0x10) != 0) { | ||
common_rngb.intr_st = 1U; | ||
} | ||
|
||
/* Seeding is done*/ | ||
if ((filed & 0x20) != 0) { | ||
common_rngb.intr_st = 2U; | ||
} | ||
|
||
/* An error occurred*/ | ||
if ((filed & (1 << 16)) != 0) { | ||
common_rngb.intr_st = ERROR_OCCURRED; | ||
} | ||
|
||
// Clear interrupt | ||
*(common_rngb.base + RNG_CMD) = 0x20; | ||
return 1; | ||
} | ||
|
||
|
||
static void systemCleanup(int level) | ||
{ | ||
if (level > 0) { | ||
munmap((void *)common_rngb.base, MMAP_SIZE); | ||
} | ||
|
||
if (level > 1) { | ||
portDestroy(common_rngb.port); | ||
} | ||
|
||
if (level > 2) { | ||
resourceDestroy(common_rngb.lock); | ||
} | ||
|
||
if (level > 3) { | ||
resourceDestroy(common_rngb.cond); | ||
} | ||
} | ||
|
||
|
||
static int systeminit(void) | ||
{ | ||
const char devpath[] = "random"; | ||
int err; | ||
oid_t dev; | ||
|
||
common_rngb.base = mmap(NULL, MMAP_SIZE, PROT_READ | PROT_WRITE, MAP_DEVICE | MAP_UNCACHED, OID_PHYSMEM, RNGB_START_ADDRESS); | ||
if (common_rngb.base == MAP_FAILED) { | ||
printf("rngb: Could not map addr\n"); | ||
return -1; | ||
} | ||
|
||
err = portCreate(&common_rngb.port); | ||
if (err != EOK) { | ||
printf("rngb: Could not create port\n"); | ||
|
||
systemCleanup(1); | ||
return -1; | ||
} | ||
|
||
dev.port = common_rngb.port; | ||
dev.id = 0; | ||
|
||
err = create_dev(&dev, devpath); | ||
if (err != EOK) { | ||
printf("rngb: Could not create port file %s (err %d)\n", devpath, err); | ||
|
||
systemCleanup(2); | ||
return -1; | ||
} | ||
|
||
err = mutexCreate(&common_rngb.lock); | ||
if (err != EOK) { | ||
printf("rngb: Could not create mutex for rngb\n"); | ||
|
||
systemCleanup(2); | ||
return -1; | ||
} | ||
|
||
err = condCreate(&common_rngb.cond); | ||
if (err != EOK) { | ||
printf("rngb: Could not create cond for rngb\n"); | ||
|
||
systemCleanup(3); | ||
return -1; | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
|
||
static int hardwareinit(void) | ||
{ | ||
int err; | ||
|
||
/* Reset and wait until rngb is sleeping */ | ||
*(common_rngb.base + RNG_CMD) = 0x40; | ||
do { | ||
err = *(common_rngb.base + RNG_SR) & 0x4; | ||
} while (err == 0); | ||
|
||
interrupt(RNGB_IRQ, rngb_intr, NULL, common_rngb.cond, NULL); | ||
|
||
/* Run self test */ | ||
*(common_rngb.base + RNG_CMD) = 0x1; | ||
while (common_rngb.intr_st == 0) { | ||
condWait(common_rngb.cond, common_rngb.lock, 0); | ||
} | ||
|
||
if (common_rngb.intr_st == ERROR_OCCURRED) { | ||
printf("rngb: self-test failed\n"); | ||
|
||
systemCleanup(4); | ||
return -1; | ||
} | ||
|
||
common_rngb.intr_st = 0; | ||
|
||
/* Run seeding */ | ||
*(common_rngb.base + RNG_CMD) = 0x2; | ||
while (common_rngb.intr_st == 0) { | ||
condWait(common_rngb.cond, common_rngb.lock, 0); | ||
} | ||
|
||
if (common_rngb.intr_st == ERROR_OCCURRED) { | ||
printf("rngb: error after generating seed\n"); | ||
|
||
systemCleanup(4); | ||
return -1; | ||
} | ||
|
||
common_rngb.intr_st = 0; | ||
|
||
/* Enable automatic seeding */ | ||
*(common_rngb.base + RNG_CR) = 0x10; | ||
return 0; | ||
} | ||
|
||
|
||
static int readrandoms(char *buff, size_t size, unsigned mode) | ||
{ | ||
char val[sizeof(uint32_t)]; | ||
unsigned int i; | ||
int err, level; | ||
|
||
if (size == 0) { | ||
return 0; | ||
} | ||
|
||
mutexLock(common_rngb.lock); | ||
for (i = 0; i < size; i++) { | ||
err = *(common_rngb.base + RNG_SR) & (1 << 16); | ||
if (err != 0) { | ||
mutexUnlock(common_rngb.lock); | ||
return -EIO; | ||
} | ||
|
||
if (i % sizeof(uint32_t) == 0) { | ||
level = FIELD(common_rngb.base + RNG_SR, 11, 4); | ||
if (level == 0) { | ||
if ((mode & O_NONBLOCK) != 0) { | ||
break; | ||
} | ||
|
||
/* wait for new values in FIFO */ | ||
i--; | ||
continue; | ||
} | ||
|
||
*((uint32_t *)val) = *(common_rngb.base + RNG_OUT); | ||
} | ||
|
||
buff[i] = val[i % sizeof(uint32_t)]; | ||
} | ||
mutexUnlock(common_rngb.lock); | ||
|
||
return i == 0 ? -1 : i; | ||
} | ||
|
||
|
||
static void handleMsg(void *arg) | ||
{ | ||
msg_t msg; | ||
unsigned long int rid; | ||
int err; | ||
|
||
while (1) { | ||
err = msgRecv(common_rngb.port, &msg, &rid); | ||
if (err < 0) { | ||
if (err == -EINTR) { | ||
continue; | ||
} | ||
else { | ||
printf("rngb: msgRecv returned error: %s\n", strerror(-err)); | ||
break; | ||
} | ||
} | ||
|
||
switch (msg.type) { | ||
case mtClose: | ||
case mtOpen: | ||
msg.o.io.err = msg.i.openclose.oid.id != 0 ? -ENOENT : EOK; | ||
break; | ||
|
||
case mtRead: | ||
if (msg.o.data != NULL) { | ||
msg.o.size = msg.o.size > 512 ? 512 : msg.o.size; | ||
err = readrandoms(msg.o.data, msg.o.size, msg.i.io.mode); | ||
msg.o.io.err = err == -1 ? -EAGAIN : err; | ||
} | ||
else { | ||
msg.o.io.err = -EINVAL; | ||
} | ||
break; | ||
|
||
default: | ||
msg.o.io.err = -EINVAL; | ||
break; | ||
} | ||
|
||
msgRespond(common_rngb.port, &msg, rid); | ||
} | ||
} | ||
|
||
|
||
int main(int argc, char **argv) | ||
{ | ||
oid_t root; | ||
(void)argc; | ||
(void)argv; | ||
|
||
while (lookup("/", NULL, &root) < 0) { | ||
usleep(10000); | ||
} | ||
|
||
if (systeminit() || hardwareinit()) { | ||
return EIO; | ||
} | ||
|
||
handleMsg(NULL); | ||
|
||
return 0; | ||
} |