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)
13 struct apb_dma_channel apb_dma_channels[] = {
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
dma_busy(struct apb_dma_channel * const channel)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 in case of continuous mode.
55 *
56 * However, for ONCE mode, the BSY_n bit in APB_DMA_STATUS will be used
57 * to determine end of dma operation.
58 */
59 uint32_t bit;
60
61 if (read32(&channel->regs->csr) & APB_CSR_ONCE)
62 /* Once mode */
63 bit = APB_STA_BSY;
64 else
65 /* Continuous mode */
66 bit = APB_STA_DMA_ACTIVITY;
67
68 return read32(&channel->regs->sta) & bit ? 1 : 0;
69 }
70 /* claim a DMA channel */
dma_claim(void)71 struct apb_dma_channel * const dma_claim(void)
72 {
73 int i;
74 struct apb_dma_channel_regs *regs = NULL;
75
76 /*
77 * Set global enable bit, otherwise register access to channel
78 * DMA registers will not be possible.
79 */
80 setbits32(&apb_dma->command, APB_COMMAND_GEN);
81
82 for (i = 0; i < ARRAY_SIZE(apb_dma_channels); i++) {
83 regs = apb_dma_channels[i].regs;
84
85 if (!apb_dma_channels[i].in_use) {
86 u32 status = read32(®s->sta);
87 if (status & (1 << i)) {
88 /* FIXME: should this be fatal? */
89 printk(BIOS_DEBUG, "%s: DMA channel %d busy?\n",
90 __func__, i);
91 }
92 break;
93 }
94 }
95
96 if (i == ARRAY_SIZE(apb_dma_channels))
97 return NULL;
98
99 apb_dma_channels[i].in_use = 1;
100 return &apb_dma_channels[i];
101 }
102
103 /* release a DMA channel */
dma_release(struct apb_dma_channel * const channel)104 void dma_release(struct apb_dma_channel * const channel)
105 {
106 int i;
107
108 /* FIXME: make this "thread" friendly */
109 while (dma_busy(channel))
110 ;
111
112 channel->in_use = 0;
113
114 /* clear the global enable bit if no channels are in use */
115 for (i = 0; i < ARRAY_SIZE(apb_dma_channels); i++) {
116 if (apb_dma_channels[i].in_use)
117 return;
118 }
119
120 clrbits32(&apb_dma->command, APB_COMMAND_GEN);
121 }
122
dma_start(struct apb_dma_channel * const channel)123 int dma_start(struct apb_dma_channel * const channel)
124 {
125 struct apb_dma_channel_regs *regs = channel->regs;
126
127 /* Set ENB bit for this channel */
128 setbits32(®s->csr, APB_CSR_ENB);
129
130 return 0;
131 }
132
dma_stop(struct apb_dma_channel * const channel)133 int dma_stop(struct apb_dma_channel * const channel)
134 {
135 struct apb_dma_channel_regs *regs = channel->regs;
136
137 /* Clear ENB bit for this channel */
138 clrbits32(®s->csr, APB_CSR_ENB);
139
140 return 0;
141 }
142