Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sparcv8leon3: add DMA support to uart driver #469

Merged
merged 4 commits into from
Mar 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion _targets/Makefile.sparcv8leon3-gr716
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@
# Copyright 2023 Phoenix Systems
#

DEFAULT_COMPONENTS := gr716-flash grlib-multi
DEFAULT_COMPONENTS := gr716-flash grlib-multi libgrdmac2
11 changes: 11 additions & 0 deletions dma/grdmac2/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#
# Makefile for Phoenix-RTOS grlib-dmac2 API
#
# Copyright 2024 Phoenix Systems
#

NAME := libgrdmac2
LOCAL_SRCS := grdmac2.c
LOCAL_HEADERS := grdmac2.h

include $(static-lib.mk)
139 changes: 139 additions & 0 deletions dma/grdmac2/grdmac2.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
/*
* Phoenix-RTOS
*
* GRLIB DMA Controller driver
*
* Copyright 2024 Phoenix Systems
* Author: Lukasz Leczkowski
*
* This file is part of Phoenix-RTOS.
*
* %LICENSE%
*/

#include <errno.h>
#include <stdlib.h>

#include <sys/mman.h>
#include <sys/platform.h>

#include <phoenix/arch/sparcv8leon3/sparcv8leon3.h>

#include "grdmac2.h"

/* GRDMAC2 Registers */
#define GRDMAC2_CTRL 0 /* 0x00 Control */
#define GRDMAC2_STS 1 /* 0x04 Status */
#define GRDMAC2_TIMER 2 /* 0x08 Timer reset value */
#define GRDMAC2_CAPAB 3 /* 0x0c Capability */
#define GRDMAC2_FIRST 4 /* 0x10 First descriptor pointer */


/* GRDMAC2_CTRL bits */
#define CTRL_EN (1 << 0) /* Enable */
#define CTRL_RST (1 << 1) /* Reset */
#define CTRL_KICK (1 << 2) /* Read the next descriptor pointer */
#define CTRL_RT (1 << 3) /* Restart current descriptor queue */
#define CTRL_IE (1 << 4) /* Interrupt enable */
#define CTRL_IM (1 << 5) /* Mask irq on descriptor completion */
#define CTRL_IER (1 << 6) /* Interrupt enable on error */
#define CTRL_TE (1 << 7) /* Timeout check */


void grdma_setup(grdma_ctx_t *ctx, void *first)
{
*(ctx->base + GRDMAC2_CTRL) = CTRL_RST;
*(ctx->base + GRDMAC2_TIMER) = 0xffffffff;
*(ctx->base + GRDMAC2_FIRST) = (uintptr_t)first;
}


void grdma_start(grdma_ctx_t *ctx)
{
*(ctx->base + GRDMAC2_CTRL) = CTRL_EN | CTRL_IE;
}


void grdma_restart(grdma_ctx_t *ctx)
{
*(ctx->base + GRDMAC2_CTRL) |= CTRL_RT;
}


bool grdma_finished(grdma_ctx_t *ctx)
{
return (*(ctx->base + GRDMAC2_STS) & 0x1) != 0;
}


int grdma_descrAlloc(grdma_ctx_t *ctx, size_t size)
{
size = (size + _PAGE_SIZE - 1) & ~(_PAGE_SIZE - 1);
void *descr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_UNCACHED | MAP_ANONYMOUS | MAP_CONTIGUOUS, -1, 0);
if (descr == MAP_FAILED) {
return -ENOMEM;
}

ctx->descr = descr;
ctx->descrSize = size;

return EOK;
}


void grdma_destroy(grdma_ctx_t *ctx)
{
if (ctx != NULL) {
if (ctx->descr != NULL) {
(void)munmap(ctx->descr, ctx->descrSize);
}
if (ctx->base != NULL) {
(void)munmap((void *)ctx->base, _PAGE_SIZE);
}
}
free(ctx);
lukileczo marked this conversation as resolved.
Show resolved Hide resolved
}


grdma_ctx_t *grdma_init(unsigned int instance)
{
/* Get DMA core info */
ambapp_dev_t dev = { .devId = CORE_ID_GRDMAC2 };
platformctl_t pctl = {
.action = pctl_get,
.type = pctl_ambapp,
.ambapp = {
.dev = &dev,
.instance = &instance,
}
};

if (platformctl(&pctl) < 0) {
return NULL;
}

if (dev.bus != BUS_AMBA_APB) {
/* GRDMAC2 should be on APB bus */
return NULL;
}

grdma_ctx_t *ctx = malloc(sizeof(grdma_ctx_t));
if (ctx == NULL) {
return NULL;
}

uintptr_t base = ((uintptr_t)dev.info.apb.base) & ~(_PAGE_SIZE - 1);
ctx->base = mmap(NULL, _PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_DEVICE | MAP_PHYSMEM | MAP_ANONYMOUS, -1, (off_t)base);
if (ctx->base == MAP_FAILED) {
free(ctx);
return NULL;
}

ctx->base += ((uintptr_t)dev.info.apb.base - base) / sizeof(uintptr_t);
ctx->irq = dev.irqn;

ctx->descr = NULL;
ctx->descrSize = 0u;

return ctx;
}
104 changes: 104 additions & 0 deletions dma/grdmac2/grdmac2.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
/*
* Phoenix-RTOS
*
* GRLIB DMA Controller driver
*
* Copyright 2024 Phoenix Systems
* Author: Lukasz Leczkowski
*
* This file is part of Phoenix-RTOS.
*
* %LICENSE%
*/

#ifndef _GRDMAC2_H_
#define _GRDMAC2_H_


#include <stdint.h>
#include <stdbool.h>


/* Descriptor type: 0 - data, 1 - polling, 2 - triggering, 3 - poll on trigger */
#define GRDMA_DESC_TYPE(x) (((x) & 0xf) << 1)
lukileczo marked this conversation as resolved.
Show resolved Hide resolved

/* Data descriptor ctrl */
#define GRDMA_DATA_EN (1 << 0) /* Enable */
#define GRDMA_DATA_WB (1 << 5) /* Write back status */
#define GRDMA_DATA_IE (1 << 8) /* Interrupt enable on descr. complete */
#define GRDMA_DATA_SF (1 << 9) /* Source address fixed */
#define GRDMA_DATA_DF (1 << 10) /* Destination address fixed */
#define GRDMA_DATA_SZ(x) (((x) & 0x1fffff) << 11) /* Transfer size (in bytes) */
lukileczo marked this conversation as resolved.
Show resolved Hide resolved


typedef struct {
uint32_t ctrl; /* Control word */
uint32_t next; /* Next descriptor address */
uint32_t dest; /* Destination base address */
uint32_t src; /* Source base address */
volatile uint32_t sts; /* Status word */
} __attribute__((packed, aligned(4))) grdma_dataDescr_t;


/* Conditional descriptor ctrl */
#define GRDMA_COND_EN (1 << 0) /* Enable */
#define GRDMA_COND_WB (1 << 5) /* Write back status */
#define GRDMA_COND_IRQN(x) (((x) & 0x3f) << 7) /* Interrupt line number to be monitored */
#define GRDMA_COND_ERRTO (1 << 13) /* Treat timeout as error */
#define GRDMA_COND_IE (1 << 14) /* Interrupt enable on descr. complete */
#define GRDMA_COND_TRIG(x) (((x) & 0x1) << 15) /* Expected trigger: 0 - edge, 1 - level */
#define GRDMA_COND_INTRV(x) (((x) & 0xff) << 16) /* Clock cycles between polls */
#define GRDMA_COND_CNT(x) (((x) & 0xff) << 24) /* Number of polls */
lukileczo marked this conversation as resolved.
Show resolved Hide resolved


typedef struct {
uint32_t ctrl; /* Control word */
uint32_t next; /* Next descriptor address */
uint32_t nextFail; /* Next descriptor address on fail */
uint32_t poll; /* Poll address */
volatile uint32_t sts; /* Status word */
uint32_t expData; /* Expected data */
uint32_t mask; /* Conditional mask */
} __attribute__((packed, aligned(4))) grdma_condDescr_t;


typedef struct {
volatile uint32_t *base;
uint8_t irq;
void *descr;
size_t descrSize;
} grdma_ctx_t;


/* Setup GRDMA descriptors
* Writes the `first` descriptor address to GRDMA register.
* Following descriptors are read based on the `next` field of the descriptor.
*/
void grdma_setup(grdma_ctx_t *ctx, void *first);


/* Map memory for descriptors */
int grdma_descrAlloc(grdma_ctx_t *ctx, size_t size);


/* Start operation */
void grdma_start(grdma_ctx_t *ctx);


/* Restart operation */
void grdma_restart(grdma_ctx_t *ctx);


/* Check if queue is finished */
bool grdma_finished(grdma_ctx_t *ctx);


/* Initialize GRDMA context */
grdma_ctx_t *grdma_init(unsigned int instance);


/* Destroy GRDMA context */
void grdma_destroy(grdma_ctx_t *ctx);


#endif
2 changes: 1 addition & 1 deletion multi/grlib-multi/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,6 @@
NAME := grlib-multi
LOCAL_SRCS := adc.c gpio.c spacewire.c spi.c uart.c grlib-multi.c
LOCAL_HEADERS := grlib-multi.h
DEP_LIBS := libtty libklog libpseudodev
DEP_LIBS := libtty libklog libpseudodev libgrdmac2

include $(binary.mk)
9 changes: 1 addition & 8 deletions multi/grlib-multi/adc.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,6 @@
#include <sys/threads.h>
#include <posix/utils.h>

#if defined(__CPU_GR716)
#include <phoenix/arch/sparcv8leon3/gr716/gr716.h>
#elif defined(__CPU_GR712RC)
#include <phoenix/arch/sparcv8leon3/gr712rc/gr712rc.h>
#else
#error "Unsupported target"
#endif

#include <phoenix/arch/sparcv8leon3/sparcv8leon3.h>

#include "adc.h"
Expand Down Expand Up @@ -242,6 +234,7 @@ int adc_createDevs(oid_t *oid)
return -1;
}

oid->id = id_adc0 + i;
if (create_dev(oid, buf) < 0) {
return -1;
}
Expand Down
9 changes: 1 addition & 8 deletions multi/grlib-multi/gpio.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,6 @@
#include "gpio.h"
#include "grlib-multi.h"

#if defined(__CPU_GR716)
#include <phoenix/arch/sparcv8leon3/gr716/gr716.h>
#elif defined(__CPU_GR712RC)
#include <phoenix/arch/sparcv8leon3/gr712rc/gr712rc.h>
#else
#error "Unsupported target"
#endif

#include <phoenix/arch/sparcv8leon3/sparcv8leon3.h>

#define GPIO_PORT_0 0
Expand Down Expand Up @@ -208,6 +200,7 @@ int gpio_createDevs(oid_t *oid)
return -1;
}

oid->id = id_gpio0 + i;
if (create_dev(oid, buf) < 0) {
return -1;
}
Expand Down
12 changes: 11 additions & 1 deletion multi/grlib-multi/grlib-multi.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
#include <sys/threads.h>
#include <posix/utils.h>

#include <phoenix/ioctl.h>

#if PSEUDODEV
#include <pseudodev.h>
#endif
Expand Down Expand Up @@ -97,6 +99,7 @@ static int multi_createDevs(void)
}

for (int i = 0; pseudo_devs[i] != NULL; i++) {
multi_common.multiOid.id = id_pseudoNull + i;
if (create_dev(&multi_common.multiOid, pseudo_devs[i]) < 0) {
LOG_ERROR("Failed to create %s device file", pseudo_devs[i]);
return -1;
Expand Down Expand Up @@ -238,7 +241,14 @@ static void multi_thread(void *arg)

static void uart_dispatchMsg(msg_t *msg)
{
id_t id = multi_getId(msg);
id_t id;

if (msg->type == mtDevCtl) {
id = ((ioctl_in_t *)msg->i.raw)->id;
}
else {
id = multi_getId(msg);
}

switch (id) {
case id_console:
Expand Down
1 change: 1 addition & 0 deletions multi/grlib-multi/spacewire.c
Original file line number Diff line number Diff line change
Expand Up @@ -635,6 +635,7 @@ int spw_createDevs(oid_t *oid)
return -1;
}

oid->id = id_spw0 + i;
if (create_dev(oid, buf) < 0) {
return -1;
}
Expand Down
8 changes: 0 additions & 8 deletions multi/grlib-multi/spi.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,6 @@
#include <sys/threads.h>
#include <posix/utils.h>

#if defined(__CPU_GR716)
#include <phoenix/arch/sparcv8leon3/gr716/gr716.h>
#elif defined(__CPU_GR712RC)
#include <phoenix/arch/sparcv8leon3/gr712rc/gr712rc.h>
#else
#error "Unsupported target"
#endif

#include <phoenix/arch/sparcv8leon3/sparcv8leon3.h>

#include "spi.h"
Expand Down
Loading
Loading