Skip to content

Commit

Permalink
gpdma: export informative-relative DMA types to uapi to allow get_inf…
Browse files Browse the repository at this point in the history
…o API
  • Loading branch information
pthierry-ledger committed Oct 7, 2024
1 parent 5a4e91a commit 3ce1310
Show file tree
Hide file tree
Showing 13 changed files with 212 additions and 155 deletions.
125 changes: 7 additions & 118 deletions kernel/include/bsp/drivers/dma/gpdma.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,133 +16,22 @@

#include <sentry/zlib/compiler.h>
#include <dt-bindings/dma/stm32_dma.h>
#include <uapi/types.h>
#include <uapi/dma.h>

/**
* @brief generic state value definition for a DMA channel
*
* This enumerate aliasing UAPI to keep unified gpdma_ prefixed content at driver level
* @see dma_chan_state_t definition for corresponding content.
* @see dma_chan_state_t definition in uapi/dma.h for corresponding content.
*/
typedef dma_chan_state_t gpdma_chan_state_t;

/**
* @enum gpdma_chan_trigger
*
* @brief type of DMA tranfer triggers request. This enum is made for bitfield manipulation,
* allowing multitple triggers at the same time if needed.
*/
typedef enum gpdma_chan_int {
GPDMA_INT_TC = 1, /**< DMA channel trigger on transfer complete */
GPDMA_INT_HT = 2, /**< DMA channel trigger on half transfer and transfer complete */
GPDMA_INT_ERROR = 4, /**< triggers on DMA transfer or config error, get status for complete information */
} gpdma_chan_int_t;

/**
* @brief generic DMA streams and channel status
*
* list DMA-generic status types that can be used by upper layer,
* whatever the DMA controller and driver is.
*/
typedef struct __PACKED gpdma_chan_status {
uint32_t state: 3;
uint32_t half_reached: 1;
uint32_t completed: 1;
uint32_t reserved: 2;
} gpdma_chan_status_t;

/**
* @enum gpdma_transfer_type
*
* @brief possible DMA transfer types
*/
typedef enum gpdma_transfer_type {
GPDMA_TRANSFER_MEMORY_TO_DEVICE = 0,
GPDMA_TRANSFER_DEVICE_TO_MEMORY = 1,
GPDMA_TRANSFER_MEMORY_TO_MEMORY = 2,
GPDMA_TRANSFER_DEVICE_TO_DEVICE = 3,
} gpdma_transfer_type_t;

/**
* @enum gpdma_transfer_mode
*
* @brief possible DMA transfer mode
*
* This enumerate behaves as a bitfield, allowing multiple values to be set
* at the same time.
*/
typedef enum gpdma_transfer_mode {
GPDMA_TRANSFER_MODE_INCREMENT_NONE = 0, /**< no increment at all of src and dest */
GPDMA_TRANSFER_MODE_INCREMENT_SRC = 1, /**< increment src at each burst */
GPDMA_TRANSFER_MODE_INCREMENT_DEST = 2, /**< increment dest at each burst */
} gpdma_transfer_mode_t;

/**
* @enum gpdma_beat_len
*
* @brief possible DMA single manipulation data len (denoted beat)
* the beat len, associated to the transfer mode and the burst number defined how the
* DMA behaves.
*
* This defines the way burst works and impact the increment calculation. This
* is defined for both source and dest and may differ, allowing differenciated increment
*/
typedef enum gpdma_beat_len {
GPDMA_BEAT_LEN_BYTE = 0, /**< data len to manipulate is a byte */
GPDMA_BEAT_LEN_HALFWORD = 1, /**< data len to manipulate is a half word */
GPDMA_BEAT_LEN_WORD = 2, /**< data len to manipulate is a word */
} gpdma_beat_len_t;

/**
* @enum gpdma_priority
*
* @brief DMA stream priority in comparison with others
*/
typedef enum gpdma_priority {
GPDMA_PRIORITY_LOW = 0,
GPDMA_PRIORITY_MEDIUM = 1,
GPDMA_PRIORITY_HIGH = 2,
GPDMA_PRIORITY_VERY_HIGH = 3,
} gpdma_priority_t;

/**
* @struct gpdma_stream_cfg
*
* @brief DMA transfer definition
*
* Depending on the hardware, the notion of channels and stream may vary,
* as sometime the controller hold stream with various channels configuration,
* or hold channels with various stream (request type) configuration.
*
* In order to avoid any difficulties at upper layer:
* - a channel is always denoted 'channel'
* - a stream can be a request
* This couple is always defined in the device-tree file, so that it
* properly identify a configuration, meaning that the DMA controller
* configuration is correctly shared between requester at configure time.
*
* This means that whatever the driver is, the correct selection of a working
* stream/channel configuration is fixed and is not automatically detected at
* run time.
* NOTE: the gpdma_stream_cfg_t is a shared data content with user interface
* the goal is to allow easy user access to stream config through a dedicated syscall,
* without any manipulation of the device tree.
* This structure is arch-independent and IP-independent.
* @see uapi/types.h for the structure definition.
*/
typedef struct gpdma_stream_cfg {
uint16_t channel; /**< channel identifier */
uint16_t stream; /**< request identifier */
uint16_t controller; /**< controller identifier */
uint16_t transfer_type; /**< type of transfer, @see gpdma_transfer_type */
size_t source; /**< source address, for memory-to-x requests */
size_t dest; /**< destination address, for x-to-memory requests */
size_t transfer_len; /**< overall steam transfer length in bytes */
bool circular_source; /**< make DMA stream restart from initial source addr at trigger time */
bool circular_dest; /**< make DMA stream restart from initial dest addr at trigger time */
uint8_t interrupts; /**< interrupt requested, @see gpdma_chan_int */
bool is_triggered; /**< specify if the DMA stream is triggered or not */
uint8_t trigger; /**< trigger id that (re)arm DMA data transfer */
uint8_t priority; /**< DMA stream priority in comparison with others, @see gpdma_priority */
uint8_t transfer_mode; /**< DMA transfer mode, @see gpdma_transfer_mode*/
uint8_t src_beat_len; /**< source burst length @see gpdma_beat_len */
uint8_t dest_beat_len; /**< source burst length @see gpdma_beat_len */
} gpdma_stream_cfg_t;

/**
* @brief probe given GPDMA controller identifier
Expand Down
10 changes: 2 additions & 8 deletions kernel/include/sentry/managers/dma.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
#define SENTRY_MANAGERS_DMA_H

#include <inttypes.h>
#include <uapi/device.h>
#include <uapi/handle.h>
#include <uapi/dma.h>
#include <sentry/ktypes.h>
#include <bsp/drivers/dma/gpdma.h>

Expand Down Expand Up @@ -39,16 +39,10 @@ kstatus_t mgr_dma_get_handle(uint32_t label, dmah_t * handle);

kstatus_t mgr_dma_get_dmah_from_interrupt(uint16_t IRQn, dmah_t *dmah);

kstatus_t mgr_dma_get_state(dmah_t d, dma_chan_state_t *state);
kstatus_t mgr_dma_get_state(dmah_t d, gpdma_chan_state_t *state);

#endif/* HAS_GPDMA */

/**
* Iterate over the device list, starting with id==id.
* Return the devinfo of the current id increment, or set devinfo to NULL and return K_ERROR_NOENT if
* the dev list walk is terminated
*/
//kstatus_t mgr_dma_walk(const devinfo_t **devinfo, uint8_t id);

#ifdef __cplusplus
} /* extern "C" */
Expand Down
5 changes: 3 additions & 2 deletions kernel/include/sentry/managers/task.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

#include <uapi/uapi.h>
#include <uapi/handle.h>
#include <uapi/dma.h>
#include <sentry/managers/security.h>
#include <sentry/managers/device.h>
#include <sentry/managers/task_metadata.h>
Expand Down Expand Up @@ -182,8 +183,8 @@ kstatus_t mgr_task_autotest(void);
#endif

#if CONFIG_HAS_GPDMA
kstatus_t mgr_task_push_dma_event(taskh_t target, dmah_t dma_stream, dma_chan_state_t dma_event);
kstatus_t mgr_task_load_dma_event(taskh_t target, dmah_t *dma_stream, dma_chan_state_t *dma_event);
kstatus_t mgr_task_push_dma_event(taskh_t target, dmah_t dma_stream, gpdma_chan_state_t dma_event);
kstatus_t mgr_task_load_dma_event(taskh_t target, dmah_t *dma_stream, gpdma_chan_state_t *dma_event);
#endif

/* specialized event pushing API, do not use directly but instead Generic below */
Expand Down
2 changes: 1 addition & 1 deletion kernel/src/managers/dma/dma-dt.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
* @file Sentry DMA streams access API
*/
#include <inttypes.h>
#include <bsp/drivers/dma/gpdma.h>
#include <uapi/dma.h>

/**
* @brief Manager level stream configuration
Expand Down
17 changes: 16 additions & 1 deletion kernel/src/managers/dma/dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,21 @@ static dma_stream_config_t *mgr_dma_get_config(const dmah_t dmah)
return cfg;
}

static kstatus_t mgr_dma_get_info(const dmah_t dmah, gpdma_stream_cfg_t const ** infos)
{
kstatus_t status = K_ERROR_INVPARAM;
if (unlikely(infos == NULL)) {
goto end;
}
for (size_t streamid = 0; streamid < STREAM_LIST_SIZE; ++streamid) {
if (stream_config[streamid].handle == dmah) {
*infos = &stream_config[streamid].meta->config;
goto end;
}
}
end:
return status;
}

kstatus_t mgr_dma_watchdog(void)
{
Expand Down Expand Up @@ -149,7 +164,7 @@ kstatus_t mgr_dma_get_owner(dmah_t d, taskh_t *owner)
/*@
requires \valid(state);
*/
kstatus_t mgr_dma_get_state(dmah_t d, dma_chan_state_t *state)
kstatus_t mgr_dma_get_state(dmah_t d, gpdma_chan_state_t *state)
{
kstatus_t status = K_ERROR_INVPARAM;
/*@ assert \valid(state); */
Expand Down
2 changes: 1 addition & 1 deletion kernel/src/managers/dma/dma.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ typedef struct dma_stream_config {
dmah_t handle; /**< associated DMA handle (opaque format) */
taskh_t owner; /**< stream owner task handle */
dma_stream_state_t state; /**< DMA stream state (configuration relative state) */
dma_chan_state_t status; /**< DMA channel status, stream-relative dynamic */
gpdma_chan_state_t status; /**< DMA channel status, stream-relative dynamic */
} dma_stream_config_t;


Expand Down
4 changes: 2 additions & 2 deletions kernel/src/managers/interrupt/interrupt.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ static inline stack_frame_t *devisr_handler(stack_frame_t *frame, int IRQn)
*
* This function is agnostic of the DMA vent properties only push the event to the target task input FIFO.
*/
static inline void dma_push_and_schedule(taskh_t owner, dmah_t handle, dma_chan_state_t event)
static inline void dma_push_and_schedule(taskh_t owner, dmah_t handle, gpdma_chan_state_t event)
{
job_state_t owner_state;

Expand Down Expand Up @@ -109,7 +109,7 @@ static inline stack_frame_t *dmaisr_handler(stack_frame_t *frame, int IRQn)
{
dmah_t dma;
taskh_t owner = 0;
dma_chan_state_t event;
gpdma_chan_state_t event;

/* get the dmah owning the interrupt */
if (unlikely(mgr_dma_get_dmah_from_interrupt(IRQn, &dma) != K_STATUS_OKAY)) {
Expand Down
4 changes: 2 additions & 2 deletions kernel/src/managers/task/task_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -629,7 +629,7 @@ kstatus_t mgr_task_load_ipc_event(taskh_t context)
* @param[in] dma_event: DMA stream event that has just risen
*
*/
kstatus_t mgr_task_push_dma_event(taskh_t target, dmah_t dma_stream, dma_chan_state_t dma_event)
kstatus_t mgr_task_push_dma_event(taskh_t target, dmah_t dma_stream, gpdma_chan_state_t dma_event)
{
kstatus_t status = K_ERROR_INVPARAM;
task_t * tsk = task_get_from_handle(target);
Expand Down Expand Up @@ -657,7 +657,7 @@ kstatus_t mgr_task_push_dma_event(taskh_t target, dmah_t dma_stream, dma_chan_st
/**
* @fn mgr_task_load_dma_event - get back firstly pushed DMA event not yet fetched
*/
kstatus_t mgr_task_load_dma_event(taskh_t context, dmah_t *handle, dma_chan_state_t *event)
kstatus_t mgr_task_load_dma_event(taskh_t context, dmah_t *handle, gpdma_chan_state_t *event)
{
kstatus_t status = K_ERROR_NOENT;

Expand Down
5 changes: 3 additions & 2 deletions kernel/src/syscalls/sysgate_waitforevent.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@
#include <sentry/managers/time.h>
#include <sentry/sched.h>
#include <uapi/types.h>
#include <uapi/dma.h>


static inline void gate_waitforevent_populate_dma(taskh_t current, dmah_t dma, dma_chan_state_t event)
static inline void gate_waitforevent_populate_dma(taskh_t current, dmah_t dma, gpdma_chan_state_t event)
{
task_meta_t const *meta;
uint8_t *svc;
Expand Down Expand Up @@ -92,7 +93,7 @@ stack_frame_t *gate_waitforevent(stack_frame_t *frame,
#if CONFIG_HAS_GPDMA
if (mask & EVENT_TYPE_DMA) {
dmah_t dmah;
dma_chan_state_t event;
gpdma_chan_state_t event;
if (mgr_task_load_dma_event(current, &dmah, &event) == K_STATUS_OKAY) {
gate_waitforevent_populate_dma(current, dmah, event);
mgr_task_set_sysreturn(current, STATUS_OK);
Expand Down
8 changes: 7 additions & 1 deletion uapi/include/uapi/device.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@
#ifndef UAPI_DEVICE_H
#define UAPI_DEVICE_H

#ifdef __cplusplus
extern "C" {
#endif // __cplusplus

#include <assert.h>
#include <inttypes.h>
#include <stddef.h>
Expand Down Expand Up @@ -63,6 +67,8 @@ typedef struct shminfo {
size_t size; /**< for mappable devices, mapped size */
} shminfo_t;


#ifdef __cplusplus
} /* extern "C" */
#endif // __cplusplus

#endif/*UAPI_DEVICE_H*/
Loading

0 comments on commit 3ce1310

Please sign in to comment.