70 lines
1.2 KiB
C
70 lines
1.2 KiB
C
/*
|
|
* dma.c
|
|
*
|
|
* Copyright (C) 2019-2020 Sylvain Munaut <tnt@246tNt.com>
|
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
|
*/
|
|
|
|
#include <stdbool.h>
|
|
#include <stdint.h>
|
|
|
|
#include "config.h"
|
|
#include "dma.h"
|
|
|
|
|
|
struct dma {
|
|
uint32_t csr;
|
|
uint32_t _rsvd;
|
|
uint32_t addr_e1;
|
|
uint32_t addr_usb;
|
|
} __attribute__((packed,aligned(4)));
|
|
|
|
#define DMA_CSR_GO (1 << 15)
|
|
#define DMA_CSR_BUSY (1 << 15)
|
|
#define DMA_DIR_E1_TO_USB (0 << 14)
|
|
#define DMA_DIR_USB_TO_E1 (1 << 14)
|
|
#define DMA_CSR_LEN(x) (((x)-2) & 0x1fff)
|
|
|
|
static volatile struct dma * const dma_regs = (void*)(DMA_BASE);
|
|
|
|
static struct {
|
|
bool pending;
|
|
dma_cb cb_fn;
|
|
void *cb_data;
|
|
} g_dma;
|
|
|
|
|
|
bool
|
|
dma_ready(void)
|
|
{
|
|
return !(dma_regs->csr & DMA_CSR_BUSY);
|
|
}
|
|
|
|
void
|
|
dma_exec(unsigned addr_e1, unsigned addr_usb, unsigned len, bool dir,
|
|
dma_cb cb_fn, void *cb_data)
|
|
{
|
|
dma_regs->addr_e1 = addr_e1;
|
|
dma_regs->addr_usb = addr_usb;
|
|
dma_regs->csr =
|
|
DMA_CSR_GO |
|
|
(dir ? DMA_DIR_USB_TO_E1 : DMA_DIR_E1_TO_USB) |
|
|
DMA_CSR_LEN(len);
|
|
|
|
g_dma.pending = true;
|
|
g_dma.cb_fn = cb_fn;
|
|
g_dma.cb_data = cb_data;
|
|
}
|
|
|
|
bool
|
|
dma_poll(void)
|
|
{
|
|
if (g_dma.pending && dma_ready()) {
|
|
g_dma.pending = false;
|
|
if (g_dma.cb_fn)
|
|
g_dma.cb_fn(g_dma.cb_data);
|
|
}
|
|
|
|
return g_dma.pending;
|
|
}
|