coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
dma.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <device/mmio.h>
4 #include <console/console.h>
5 #include <stdint.h>
6 #include <soc/addressmap.h>
7 #include <soc/dma.h>
8 
9 struct apb_dma * const apb_dma = (struct apb_dma *)TEGRA_APB_DMA_BASE;
10 
11 #define APB_DMA_OFFSET(n) \
12  (struct apb_dma_channel_regs *)(TEGRA_APB_DMA_BASE + n)
14  { .num = 0, .regs = APB_DMA_OFFSET(0x1000) },
15  { .num = 1, .regs = APB_DMA_OFFSET(0x1040) },
16  { .num = 2, .regs = APB_DMA_OFFSET(0x1080) },
17  { .num = 3, .regs = APB_DMA_OFFSET(0x10c0) },
18  { .num = 4, .regs = APB_DMA_OFFSET(0x1100) },
19  { .num = 5, .regs = APB_DMA_OFFSET(0x1140) },
20  { .num = 6, .regs = APB_DMA_OFFSET(0x1180) },
21  { .num = 7, .regs = APB_DMA_OFFSET(0x11c0) },
22  { .num = 8, .regs = APB_DMA_OFFSET(0x1200) },
23  { .num = 9, .regs = APB_DMA_OFFSET(0x1240) },
24  { .num = 10, .regs = APB_DMA_OFFSET(0x1280) },
25  { .num = 11, .regs = APB_DMA_OFFSET(0x12c0) },
26  { .num = 12, .regs = APB_DMA_OFFSET(0x1300) },
27  { .num = 13, .regs = APB_DMA_OFFSET(0x1340) },
28  { .num = 14, .regs = APB_DMA_OFFSET(0x1380) },
29  { .num = 15, .regs = APB_DMA_OFFSET(0x13c0) },
30  { .num = 16, .regs = APB_DMA_OFFSET(0x1400) },
31  { .num = 17, .regs = APB_DMA_OFFSET(0x1440) },
32  { .num = 18, .regs = APB_DMA_OFFSET(0x1480) },
33  { .num = 19, .regs = APB_DMA_OFFSET(0x14c0) },
34  { .num = 20, .regs = APB_DMA_OFFSET(0x1500) },
35  { .num = 21, .regs = APB_DMA_OFFSET(0x1540) },
36  { .num = 22, .regs = APB_DMA_OFFSET(0x1580) },
37  { .num = 23, .regs = APB_DMA_OFFSET(0x15c0) },
38  { .num = 24, .regs = APB_DMA_OFFSET(0x1600) },
39  { .num = 25, .regs = APB_DMA_OFFSET(0x1640) },
40  { .num = 26, .regs = APB_DMA_OFFSET(0x1680) },
41  { .num = 27, .regs = APB_DMA_OFFSET(0x16c0) },
42  { .num = 28, .regs = APB_DMA_OFFSET(0x1700) },
43  { .num = 29, .regs = APB_DMA_OFFSET(0x1740) },
44  { .num = 30, .regs = APB_DMA_OFFSET(0x1780) },
45  { .num = 31, .regs = APB_DMA_OFFSET(0x17c0) },
46 };
47 
48 int dma_busy(struct apb_dma_channel * const channel)
49 {
50  /*
51  * In continuous mode, the BSY_n bit in APB_DMA_STATUS and
52  * BSY in APBDMACHAN_CHANNEL_n_STA_0 will remain set as '1' so long
53  * as the channel is enabled. So for this function we'll use the
54  * DMA_ACTIVITY bit.
55  */
56  return read32(&channel->regs->sta) & APB_STA_DMA_ACTIVITY ? 1 : 0;
57 }
58 /* claim a DMA channel */
59 struct apb_dma_channel * const dma_claim(void)
60 {
61  int i;
62  struct apb_dma_channel_regs *regs = NULL;
63 
64  /*
65  * Set global enable bit, otherwise register access to channel
66  * DMA registers will not be possible.
67  */
69 
70  for (i = 0; i < ARRAY_SIZE(apb_dma_channels); i++) {
72 
73  if (!apb_dma_channels[i].in_use) {
74  u32 status = read32(&regs->sta);
75  if (status & (1 << i)) {
76  /* FIXME: should this be fatal? */
77  printk(BIOS_DEBUG, "%s: DMA channel %d busy?\n",
78  __func__, i);
79  }
80  break;
81  }
82  }
83 
84  if (i == ARRAY_SIZE(apb_dma_channels))
85  return NULL;
86 
87  apb_dma_channels[i].in_use = 1;
88  return &apb_dma_channels[i];
89 }
90 
91 /* release a DMA channel */
92 void dma_release(struct apb_dma_channel * const channel)
93 {
94  int i;
95 
96  /* FIXME: make this "thread" friendly */
97  while (dma_busy(channel))
98  ;
99 
100  channel->in_use = 0;
101 
102  /* clear the global enable bit if no channels are in use */
103  for (i = 0; i < ARRAY_SIZE(apb_dma_channels); i++) {
104  if (apb_dma_channels[i].in_use)
105  return;
106  }
107 
109 }
110 
111 int dma_start(struct apb_dma_channel * const channel)
112 {
113  struct apb_dma_channel_regs *regs = channel->regs;
114 
115  /* Set ENB bit for this channel */
116  setbits32(&regs->csr, APB_CSR_ENB);
117 
118  return 0;
119 }
120 
121 int dma_stop(struct apb_dma_channel * const channel)
122 {
123  struct apb_dma_channel_regs *regs = channel->regs;
124 
125  /* Clear ENB bit for this channel */
126  clrbits32(&regs->csr, APB_CSR_ENB);
127 
128  return 0;
129 }
static uint32_t read32(const void *addr)
Definition: mmio.h:22
#define ARRAY_SIZE(a)
Definition: helpers.h:12
#define printk(level,...)
Definition: stdlib.h:16
#define setbits32(addr, set)
Definition: mmio.h:21
#define clrbits32(addr, clear)
Definition: mmio.h:26
#define BIOS_DEBUG
BIOS_DEBUG - Verbose output.
Definition: loglevel.h:128
@ TEGRA_APB_DMA_BASE
Definition: addressmap.h:25
#define NULL
Definition: stddef.h:19
uint32_t u32
Definition: stdint.h:51
const int num
Definition: dma.h:158
struct apb_dma_channel_regs * regs
Definition: dma.h:159
int in_use
Definition: dma.h:165
Definition: dma.h:34
u32 command
Definition: dma.h:35
int dma_start(struct apb_dma_channel *const channel)
Definition: dma.c:111
int dma_stop(struct apb_dma_channel *const channel)
Definition: dma.c:121
void dma_release(struct apb_dma_channel *const channel)
Definition: dma.c:92
struct apb_dma_channel apb_dma_channels[]
Definition: dma.c:13
#define APB_DMA_OFFSET(n)
Definition: dma.c:11
int dma_busy(struct apb_dma_channel *const channel)
Definition: dma.c:48
struct apb_dma_channel *const dma_claim(void)
Definition: dma.c:59
#define APB_COMMAND_GEN
Definition: dma.h:30
#define APB_STA_DMA_ACTIVITY
Definition: dma.h:111
#define APB_CSR_ENB
Definition: dma.h:63