blob: a2c81cceae9d61d31d17d6446806497ae8958dad [file] [log] [blame]
Sylvain Munaut26bc4652020-09-14 10:19:49 +02001/*
2 * dma.c
3 *
4 * Copyright (C) 2019-2020 Sylvain Munaut <tnt@246tNt.com>
5 * SPDX-License-Identifier: GPL-3.0-or-later
6 */
7
8#include <stdbool.h>
9#include <stdint.h>
10
11#include "config.h"
12#include "dma.h"
13
14
15struct dma {
16 uint32_t csr;
17 uint32_t _rsvd;
18 uint32_t addr_e1;
19 uint32_t addr_usb;
20} __attribute__((packed,aligned(4)));
21
22#define DMA_CSR_GO (1 << 15)
23#define DMA_CSR_BUSY (1 << 15)
24#define DMA_DIR_E1_TO_USB (0 << 14)
25#define DMA_DIR_USB_TO_E1 (1 << 14)
26#define DMA_CSR_LEN(x) (((x)-2) & 0x1fff)
27
28static volatile struct dma * const dma_regs = (void*)(DMA_BASE);
29
30static struct {
31 bool pending;
32 dma_cb cb_fn;
33 void *cb_data;
34} g_dma;
35
36
37bool
38dma_ready(void)
39{
40 return !(dma_regs->csr & DMA_CSR_BUSY);
41}
42
43void
44dma_exec(unsigned addr_e1, unsigned addr_usb, unsigned len, bool dir,
45 dma_cb cb_fn, void *cb_data)
46{
47 dma_regs->addr_e1 = addr_e1;
48 dma_regs->addr_usb = addr_usb;
49 dma_regs->csr =
50 DMA_CSR_GO |
51 (dir ? DMA_DIR_USB_TO_E1 : DMA_DIR_E1_TO_USB) |
52 DMA_CSR_LEN(len);
53
54 g_dma.pending = true;
55 g_dma.cb_fn = cb_fn;
56 g_dma.cb_data = cb_data;
57}
58
59bool
60dma_poll(void)
61{
62 if (g_dma.pending && dma_ready()) {
63 g_dma.pending = false;
64 if (g_dma.cb_fn)
65 g_dma.cb_fn(g_dma.cb_data);
66 }
67
68 return g_dma.pending;
69}