root / hw / soc_dma.c @ 47e699dc
History | View | Annotate | Download (11.7 kB)
1 | afbb5194 | balrog | /*
|
---|---|---|---|
2 | afbb5194 | balrog | * On-chip DMA controller framework.
|
3 | afbb5194 | balrog | *
|
4 | afbb5194 | balrog | * Copyright (C) 2008 Nokia Corporation
|
5 | afbb5194 | balrog | * Written by Andrzej Zaborowski <andrew@openedhand.com>
|
6 | afbb5194 | balrog | *
|
7 | afbb5194 | balrog | * This program is free software; you can redistribute it and/or
|
8 | afbb5194 | balrog | * modify it under the terms of the GNU General Public License as
|
9 | afbb5194 | balrog | * published by the Free Software Foundation; either version 2 or
|
10 | afbb5194 | balrog | * (at your option) version 3 of the License.
|
11 | afbb5194 | balrog | *
|
12 | afbb5194 | balrog | * This program is distributed in the hope that it will be useful,
|
13 | afbb5194 | balrog | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14 | afbb5194 | balrog | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15 | afbb5194 | balrog | * GNU General Public License for more details.
|
16 | afbb5194 | balrog | *
|
17 | afbb5194 | balrog | * You should have received a copy of the GNU General Public License
|
18 | afbb5194 | balrog | * along with this program; if not, write to the Free Software
|
19 | afbb5194 | balrog | * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
20 | afbb5194 | balrog | * MA 02111-1307 USA
|
21 | afbb5194 | balrog | */
|
22 | afbb5194 | balrog | #include "qemu-common.h" |
23 | afbb5194 | balrog | #include "qemu-timer.h" |
24 | afbb5194 | balrog | #include "soc_dma.h" |
25 | afbb5194 | balrog | |
26 | afbb5194 | balrog | void transfer_mem2mem(struct soc_dma_ch_s *ch) |
27 | afbb5194 | balrog | { |
28 | afbb5194 | balrog | memcpy(ch->paddr[0], ch->paddr[1], ch->bytes); |
29 | afbb5194 | balrog | ch->paddr[0] += ch->bytes;
|
30 | afbb5194 | balrog | ch->paddr[1] += ch->bytes;
|
31 | afbb5194 | balrog | } |
32 | afbb5194 | balrog | |
33 | afbb5194 | balrog | void transfer_mem2fifo(struct soc_dma_ch_s *ch) |
34 | afbb5194 | balrog | { |
35 | afbb5194 | balrog | ch->io_fn[1](ch->io_opaque[1], ch->paddr[0], ch->bytes); |
36 | afbb5194 | balrog | ch->paddr[0] += ch->bytes;
|
37 | afbb5194 | balrog | } |
38 | afbb5194 | balrog | |
39 | afbb5194 | balrog | void transfer_fifo2mem(struct soc_dma_ch_s *ch) |
40 | afbb5194 | balrog | { |
41 | afbb5194 | balrog | ch->io_fn[0](ch->io_opaque[0], ch->paddr[1], ch->bytes); |
42 | afbb5194 | balrog | ch->paddr[1] += ch->bytes;
|
43 | afbb5194 | balrog | } |
44 | afbb5194 | balrog | |
45 | afbb5194 | balrog | /* This is further optimisable but isn't very important because often
|
46 | afbb5194 | balrog | * DMA peripherals forbid this kind of transfers and even when they don't,
|
47 | afbb5194 | balrog | * oprating systems may not need to use them. */
|
48 | afbb5194 | balrog | static void *fifo_buf; |
49 | afbb5194 | balrog | static int fifo_size; |
50 | afbb5194 | balrog | void transfer_fifo2fifo(struct soc_dma_ch_s *ch) |
51 | afbb5194 | balrog | { |
52 | d4066479 | balrog | if (ch->bytes > fifo_size)
|
53 | 2137b4cc | ths | fifo_buf = qemu_realloc(fifo_buf, fifo_size = ch->bytes); |
54 | afbb5194 | balrog | |
55 | afbb5194 | balrog | /* Implement as transfer_fifo2linear + transfer_linear2fifo. */
|
56 | afbb5194 | balrog | ch->io_fn[0](ch->io_opaque[0], fifo_buf, ch->bytes); |
57 | afbb5194 | balrog | ch->io_fn[1](ch->io_opaque[1], fifo_buf, ch->bytes); |
58 | afbb5194 | balrog | } |
59 | afbb5194 | balrog | |
60 | afbb5194 | balrog | struct dma_s {
|
61 | afbb5194 | balrog | struct soc_dma_s soc;
|
62 | afbb5194 | balrog | int chnum;
|
63 | afbb5194 | balrog | uint64_t ch_enable_mask; |
64 | afbb5194 | balrog | int64_t channel_freq; |
65 | afbb5194 | balrog | int enabled_count;
|
66 | afbb5194 | balrog | |
67 | afbb5194 | balrog | struct memmap_entry_s {
|
68 | afbb5194 | balrog | enum soc_dma_port_type type;
|
69 | afbb5194 | balrog | target_phys_addr_t addr; |
70 | afbb5194 | balrog | union {
|
71 | afbb5194 | balrog | struct {
|
72 | afbb5194 | balrog | void *opaque;
|
73 | afbb5194 | balrog | soc_dma_io_t fn; |
74 | afbb5194 | balrog | int out;
|
75 | afbb5194 | balrog | } fifo; |
76 | afbb5194 | balrog | struct {
|
77 | afbb5194 | balrog | void *base;
|
78 | afbb5194 | balrog | size_t size; |
79 | afbb5194 | balrog | } mem; |
80 | afbb5194 | balrog | } u; |
81 | afbb5194 | balrog | } *memmap; |
82 | afbb5194 | balrog | int memmap_size;
|
83 | afbb5194 | balrog | |
84 | afbb5194 | balrog | struct soc_dma_ch_s ch[0]; |
85 | afbb5194 | balrog | }; |
86 | afbb5194 | balrog | |
87 | afbb5194 | balrog | static void soc_dma_ch_schedule(struct soc_dma_ch_s *ch, int delay_bytes) |
88 | afbb5194 | balrog | { |
89 | afbb5194 | balrog | int64_t now = qemu_get_clock(vm_clock); |
90 | afbb5194 | balrog | struct dma_s *dma = (struct dma_s *) ch->dma; |
91 | afbb5194 | balrog | |
92 | afbb5194 | balrog | qemu_mod_timer(ch->timer, now + delay_bytes / dma->channel_freq); |
93 | afbb5194 | balrog | } |
94 | afbb5194 | balrog | |
95 | afbb5194 | balrog | static void soc_dma_ch_run(void *opaque) |
96 | afbb5194 | balrog | { |
97 | afbb5194 | balrog | struct soc_dma_ch_s *ch = (struct soc_dma_ch_s *) opaque; |
98 | afbb5194 | balrog | |
99 | afbb5194 | balrog | ch->running = 1;
|
100 | afbb5194 | balrog | ch->dma->setup_fn(ch); |
101 | afbb5194 | balrog | ch->transfer_fn(ch); |
102 | afbb5194 | balrog | ch->running = 0;
|
103 | afbb5194 | balrog | |
104 | afbb5194 | balrog | if (ch->enable)
|
105 | afbb5194 | balrog | soc_dma_ch_schedule(ch, ch->bytes); |
106 | afbb5194 | balrog | ch->bytes = 0;
|
107 | afbb5194 | balrog | } |
108 | afbb5194 | balrog | |
109 | afbb5194 | balrog | static inline struct memmap_entry_s *soc_dma_lookup(struct dma_s *dma, |
110 | afbb5194 | balrog | target_phys_addr_t addr) |
111 | afbb5194 | balrog | { |
112 | afbb5194 | balrog | struct memmap_entry_s *lo;
|
113 | afbb5194 | balrog | int hi;
|
114 | afbb5194 | balrog | |
115 | afbb5194 | balrog | lo = dma->memmap; |
116 | afbb5194 | balrog | hi = dma->memmap_size; |
117 | afbb5194 | balrog | |
118 | afbb5194 | balrog | while (hi > 1) { |
119 | afbb5194 | balrog | hi /= 2;
|
120 | afbb5194 | balrog | if (lo[hi].addr <= addr)
|
121 | afbb5194 | balrog | lo += hi; |
122 | afbb5194 | balrog | } |
123 | afbb5194 | balrog | |
124 | afbb5194 | balrog | return lo;
|
125 | afbb5194 | balrog | } |
126 | afbb5194 | balrog | |
127 | afbb5194 | balrog | static inline enum soc_dma_port_type soc_dma_ch_update_type( |
128 | afbb5194 | balrog | struct soc_dma_ch_s *ch, int port) |
129 | afbb5194 | balrog | { |
130 | afbb5194 | balrog | struct dma_s *dma = (struct dma_s *) ch->dma; |
131 | afbb5194 | balrog | struct memmap_entry_s *entry = soc_dma_lookup(dma, ch->vaddr[port]);
|
132 | afbb5194 | balrog | |
133 | afbb5194 | balrog | if (entry->type == soc_dma_port_fifo) {
|
134 | afbb5194 | balrog | while (entry < dma->memmap + dma->memmap_size &&
|
135 | afbb5194 | balrog | entry->u.fifo.out != port) |
136 | afbb5194 | balrog | entry ++; |
137 | afbb5194 | balrog | if (entry->addr != ch->vaddr[port] || entry->u.fifo.out != port)
|
138 | afbb5194 | balrog | return soc_dma_port_other;
|
139 | afbb5194 | balrog | |
140 | afbb5194 | balrog | if (ch->type[port] != soc_dma_access_const)
|
141 | afbb5194 | balrog | return soc_dma_port_other;
|
142 | afbb5194 | balrog | |
143 | afbb5194 | balrog | ch->io_fn[port] = entry->u.fifo.fn; |
144 | afbb5194 | balrog | ch->io_opaque[port] = entry->u.fifo.opaque; |
145 | afbb5194 | balrog | return soc_dma_port_fifo;
|
146 | afbb5194 | balrog | } else if (entry->type == soc_dma_port_mem) { |
147 | afbb5194 | balrog | if (entry->addr > ch->vaddr[port] ||
|
148 | afbb5194 | balrog | entry->addr + entry->u.mem.size <= ch->vaddr[port]) |
149 | afbb5194 | balrog | return soc_dma_port_other;
|
150 | afbb5194 | balrog | |
151 | afbb5194 | balrog | /* TODO: support constant memory address for source port as used for
|
152 | afbb5194 | balrog | * drawing solid rectangles by PalmOS(R). */
|
153 | afbb5194 | balrog | if (ch->type[port] != soc_dma_access_const)
|
154 | afbb5194 | balrog | return soc_dma_port_other;
|
155 | afbb5194 | balrog | |
156 | afbb5194 | balrog | ch->paddr[port] = (uint8_t *) entry->u.mem.base + |
157 | afbb5194 | balrog | (ch->vaddr[port] - entry->addr); |
158 | afbb5194 | balrog | /* TODO: save bytes left to the end of the mapping somewhere so we
|
159 | afbb5194 | balrog | * can check we're not reading beyond it. */
|
160 | afbb5194 | balrog | return soc_dma_port_mem;
|
161 | afbb5194 | balrog | } else
|
162 | afbb5194 | balrog | return soc_dma_port_other;
|
163 | afbb5194 | balrog | } |
164 | afbb5194 | balrog | |
165 | afbb5194 | balrog | void soc_dma_ch_update(struct soc_dma_ch_s *ch) |
166 | afbb5194 | balrog | { |
167 | afbb5194 | balrog | enum soc_dma_port_type src, dst;
|
168 | afbb5194 | balrog | |
169 | afbb5194 | balrog | src = soc_dma_ch_update_type(ch, 0);
|
170 | afbb5194 | balrog | if (src == soc_dma_port_other) {
|
171 | afbb5194 | balrog | ch->update = 0;
|
172 | afbb5194 | balrog | ch->transfer_fn = ch->dma->transfer_fn; |
173 | afbb5194 | balrog | return;
|
174 | afbb5194 | balrog | } |
175 | afbb5194 | balrog | dst = soc_dma_ch_update_type(ch, 1);
|
176 | afbb5194 | balrog | |
177 | afbb5194 | balrog | /* TODO: use src and dst as array indices. */
|
178 | afbb5194 | balrog | if (src == soc_dma_port_mem && dst == soc_dma_port_mem)
|
179 | afbb5194 | balrog | ch->transfer_fn = transfer_mem2mem; |
180 | afbb5194 | balrog | else if (src == soc_dma_port_mem && dst == soc_dma_port_fifo) |
181 | afbb5194 | balrog | ch->transfer_fn = transfer_mem2fifo; |
182 | afbb5194 | balrog | else if (src == soc_dma_port_fifo && dst == soc_dma_port_mem) |
183 | afbb5194 | balrog | ch->transfer_fn = transfer_fifo2mem; |
184 | afbb5194 | balrog | else if (src == soc_dma_port_fifo && dst == soc_dma_port_fifo) |
185 | afbb5194 | balrog | ch->transfer_fn = transfer_fifo2fifo; |
186 | afbb5194 | balrog | else
|
187 | afbb5194 | balrog | ch->transfer_fn = ch->dma->transfer_fn; |
188 | afbb5194 | balrog | |
189 | afbb5194 | balrog | ch->update = (dst != soc_dma_port_other); |
190 | afbb5194 | balrog | } |
191 | afbb5194 | balrog | |
192 | afbb5194 | balrog | static void soc_dma_ch_freq_update(struct dma_s *s) |
193 | afbb5194 | balrog | { |
194 | afbb5194 | balrog | if (s->enabled_count)
|
195 | afbb5194 | balrog | /* We completely ignore channel priorities and stuff */
|
196 | afbb5194 | balrog | s->channel_freq = s->soc.freq / s->enabled_count; |
197 | afbb5194 | balrog | else
|
198 | afbb5194 | balrog | /* TODO: Signal that we want to disable the functional clock and let
|
199 | afbb5194 | balrog | * the platform code decide what to do with it, i.e. check that
|
200 | afbb5194 | balrog | * auto-idle is enabled in the clock controller and if we are stopping
|
201 | afbb5194 | balrog | * the clock, do the same with any parent clocks that had only one
|
202 | afbb5194 | balrog | * user keeping them on and auto-idle enabled. */;
|
203 | afbb5194 | balrog | } |
204 | afbb5194 | balrog | |
205 | afbb5194 | balrog | void soc_dma_set_request(struct soc_dma_ch_s *ch, int level) |
206 | afbb5194 | balrog | { |
207 | afbb5194 | balrog | struct dma_s *dma = (struct dma_s *) ch->dma; |
208 | afbb5194 | balrog | |
209 | afbb5194 | balrog | dma->enabled_count += level - ch->enable; |
210 | afbb5194 | balrog | |
211 | afbb5194 | balrog | if (level)
|
212 | afbb5194 | balrog | dma->ch_enable_mask |= 1 << ch->num;
|
213 | afbb5194 | balrog | else
|
214 | afbb5194 | balrog | dma->ch_enable_mask &= ~(1 << ch->num);
|
215 | afbb5194 | balrog | |
216 | afbb5194 | balrog | if (level != ch->enable) {
|
217 | afbb5194 | balrog | soc_dma_ch_freq_update(dma); |
218 | afbb5194 | balrog | ch->enable = level; |
219 | afbb5194 | balrog | |
220 | afbb5194 | balrog | if (!ch->enable)
|
221 | afbb5194 | balrog | qemu_del_timer(ch->timer); |
222 | afbb5194 | balrog | else if (!ch->running) |
223 | afbb5194 | balrog | soc_dma_ch_run(ch); |
224 | afbb5194 | balrog | else
|
225 | afbb5194 | balrog | soc_dma_ch_schedule(ch, 1);
|
226 | afbb5194 | balrog | } |
227 | afbb5194 | balrog | } |
228 | afbb5194 | balrog | |
229 | afbb5194 | balrog | void soc_dma_reset(struct soc_dma_s *soc) |
230 | afbb5194 | balrog | { |
231 | afbb5194 | balrog | struct dma_s *s = (struct dma_s *) soc; |
232 | afbb5194 | balrog | |
233 | afbb5194 | balrog | s->soc.drqbmp = 0;
|
234 | afbb5194 | balrog | s->ch_enable_mask = 0;
|
235 | afbb5194 | balrog | s->enabled_count = 0;
|
236 | afbb5194 | balrog | soc_dma_ch_freq_update(s); |
237 | afbb5194 | balrog | } |
238 | afbb5194 | balrog | |
239 | afbb5194 | balrog | /* TODO: take a functional-clock argument */
|
240 | afbb5194 | balrog | struct soc_dma_s *soc_dma_init(int n) |
241 | afbb5194 | balrog | { |
242 | afbb5194 | balrog | int i;
|
243 | afbb5194 | balrog | struct dma_s *s = qemu_mallocz(sizeof(*s) + n * sizeof(*s->ch)); |
244 | afbb5194 | balrog | |
245 | afbb5194 | balrog | s->chnum = n; |
246 | afbb5194 | balrog | s->soc.ch = s->ch; |
247 | afbb5194 | balrog | for (i = 0; i < n; i ++) { |
248 | afbb5194 | balrog | s->ch[i].dma = &s->soc; |
249 | afbb5194 | balrog | s->ch[i].num = i; |
250 | afbb5194 | balrog | s->ch[i].timer = qemu_new_timer(vm_clock, soc_dma_ch_run, &s->ch[i]); |
251 | afbb5194 | balrog | } |
252 | afbb5194 | balrog | |
253 | afbb5194 | balrog | soc_dma_reset(&s->soc); |
254 | d4066479 | balrog | fifo_size = 0;
|
255 | afbb5194 | balrog | |
256 | afbb5194 | balrog | return &s->soc;
|
257 | afbb5194 | balrog | } |
258 | afbb5194 | balrog | |
259 | afbb5194 | balrog | void soc_dma_port_add_fifo(struct soc_dma_s *soc, target_phys_addr_t virt_base, |
260 | afbb5194 | balrog | soc_dma_io_t fn, void *opaque, int out) |
261 | afbb5194 | balrog | { |
262 | afbb5194 | balrog | struct memmap_entry_s *entry;
|
263 | afbb5194 | balrog | struct dma_s *dma = (struct dma_s *) soc; |
264 | afbb5194 | balrog | |
265 | 2137b4cc | ths | dma->memmap = qemu_realloc(dma->memmap, sizeof(*entry) *
|
266 | afbb5194 | balrog | (dma->memmap_size + 1));
|
267 | afbb5194 | balrog | entry = soc_dma_lookup(dma, virt_base); |
268 | afbb5194 | balrog | |
269 | afbb5194 | balrog | if (dma->memmap_size) {
|
270 | afbb5194 | balrog | if (entry->type == soc_dma_port_mem) {
|
271 | afbb5194 | balrog | if (entry->addr <= virt_base &&
|
272 | afbb5194 | balrog | entry->addr + entry->u.mem.size > virt_base) { |
273 | afbb5194 | balrog | fprintf(stderr, "%s: FIFO at " TARGET_FMT_lx
|
274 | afbb5194 | balrog | " collides with RAM region at " TARGET_FMT_lx
|
275 | afbb5194 | balrog | "-" TARGET_FMT_lx "\n", __FUNCTION__, |
276 | afbb5194 | balrog | (target_ulong) virt_base, |
277 | afbb5194 | balrog | (target_ulong) entry->addr, (target_ulong) |
278 | afbb5194 | balrog | (entry->addr + entry->u.mem.size)); |
279 | afbb5194 | balrog | exit(-1);
|
280 | afbb5194 | balrog | } |
281 | afbb5194 | balrog | |
282 | afbb5194 | balrog | if (entry->addr <= virt_base)
|
283 | afbb5194 | balrog | entry ++; |
284 | afbb5194 | balrog | } else
|
285 | afbb5194 | balrog | while (entry < dma->memmap + dma->memmap_size &&
|
286 | afbb5194 | balrog | entry->addr <= virt_base) { |
287 | afbb5194 | balrog | if (entry->addr == virt_base && entry->u.fifo.out == out) {
|
288 | afbb5194 | balrog | fprintf(stderr, "%s: FIFO at " TARGET_FMT_lx
|
289 | afbb5194 | balrog | " collides FIFO at " TARGET_FMT_lx "\n", |
290 | afbb5194 | balrog | __FUNCTION__, (target_ulong) virt_base, |
291 | afbb5194 | balrog | (target_ulong) entry->addr); |
292 | afbb5194 | balrog | exit(-1);
|
293 | afbb5194 | balrog | } |
294 | afbb5194 | balrog | |
295 | afbb5194 | balrog | entry ++; |
296 | afbb5194 | balrog | } |
297 | afbb5194 | balrog | |
298 | afbb5194 | balrog | memmove(entry + 1, entry,
|
299 | afbb5194 | balrog | (uint8_t *) (dma->memmap + dma->memmap_size ++) - |
300 | afbb5194 | balrog | (uint8_t *) entry); |
301 | afbb5194 | balrog | } else
|
302 | afbb5194 | balrog | dma->memmap_size ++; |
303 | afbb5194 | balrog | |
304 | afbb5194 | balrog | entry->addr = virt_base; |
305 | afbb5194 | balrog | entry->type = soc_dma_port_fifo; |
306 | afbb5194 | balrog | entry->u.fifo.fn = fn; |
307 | afbb5194 | balrog | entry->u.fifo.opaque = opaque; |
308 | afbb5194 | balrog | entry->u.fifo.out = out; |
309 | afbb5194 | balrog | } |
310 | afbb5194 | balrog | |
311 | afbb5194 | balrog | void soc_dma_port_add_mem(struct soc_dma_s *soc, uint8_t *phys_base, |
312 | afbb5194 | balrog | target_phys_addr_t virt_base, size_t size) |
313 | afbb5194 | balrog | { |
314 | afbb5194 | balrog | struct memmap_entry_s *entry;
|
315 | afbb5194 | balrog | struct dma_s *dma = (struct dma_s *) soc; |
316 | afbb5194 | balrog | |
317 | 2137b4cc | ths | dma->memmap = qemu_realloc(dma->memmap, sizeof(*entry) *
|
318 | afbb5194 | balrog | (dma->memmap_size + 1));
|
319 | afbb5194 | balrog | entry = soc_dma_lookup(dma, virt_base); |
320 | afbb5194 | balrog | |
321 | afbb5194 | balrog | if (dma->memmap_size) {
|
322 | afbb5194 | balrog | if (entry->type == soc_dma_port_mem) {
|
323 | afbb5194 | balrog | if ((entry->addr >= virt_base && entry->addr < virt_base + size) ||
|
324 | afbb5194 | balrog | (entry->addr <= virt_base && |
325 | afbb5194 | balrog | entry->addr + entry->u.mem.size > virt_base)) { |
326 | afbb5194 | balrog | fprintf(stderr, "%s: RAM at " TARGET_FMT_lx "-" TARGET_FMT_lx |
327 | afbb5194 | balrog | " collides with RAM region at " TARGET_FMT_lx
|
328 | afbb5194 | balrog | "-" TARGET_FMT_lx "\n", __FUNCTION__, |
329 | afbb5194 | balrog | (target_ulong) virt_base, |
330 | afbb5194 | balrog | (target_ulong) (virt_base + size), |
331 | afbb5194 | balrog | (target_ulong) entry->addr, (target_ulong) |
332 | afbb5194 | balrog | (entry->addr + entry->u.mem.size)); |
333 | afbb5194 | balrog | exit(-1);
|
334 | afbb5194 | balrog | } |
335 | afbb5194 | balrog | |
336 | afbb5194 | balrog | if (entry->addr <= virt_base)
|
337 | afbb5194 | balrog | entry ++; |
338 | afbb5194 | balrog | } else {
|
339 | afbb5194 | balrog | if (entry->addr >= virt_base &&
|
340 | afbb5194 | balrog | entry->addr < virt_base + size) { |
341 | afbb5194 | balrog | fprintf(stderr, "%s: RAM at " TARGET_FMT_lx "-" TARGET_FMT_lx |
342 | afbb5194 | balrog | " collides with FIFO at " TARGET_FMT_lx
|
343 | afbb5194 | balrog | "\n", __FUNCTION__,
|
344 | afbb5194 | balrog | (target_ulong) virt_base, |
345 | afbb5194 | balrog | (target_ulong) (virt_base + size), |
346 | afbb5194 | balrog | (target_ulong) entry->addr); |
347 | afbb5194 | balrog | exit(-1);
|
348 | afbb5194 | balrog | } |
349 | afbb5194 | balrog | |
350 | afbb5194 | balrog | while (entry < dma->memmap + dma->memmap_size &&
|
351 | afbb5194 | balrog | entry->addr <= virt_base) |
352 | afbb5194 | balrog | entry ++; |
353 | afbb5194 | balrog | } |
354 | afbb5194 | balrog | |
355 | afbb5194 | balrog | memmove(entry + 1, entry,
|
356 | afbb5194 | balrog | (uint8_t *) (dma->memmap + dma->memmap_size ++) - |
357 | afbb5194 | balrog | (uint8_t *) entry); |
358 | afbb5194 | balrog | } else
|
359 | afbb5194 | balrog | dma->memmap_size ++; |
360 | afbb5194 | balrog | |
361 | afbb5194 | balrog | entry->addr = virt_base; |
362 | afbb5194 | balrog | entry->type = soc_dma_port_mem; |
363 | afbb5194 | balrog | entry->u.mem.base = phys_base; |
364 | afbb5194 | balrog | entry->u.mem.size = size; |
365 | afbb5194 | balrog | } |
366 | afbb5194 | balrog | |
367 | afbb5194 | balrog | /* TODO: port removal for ports like PCMCIA memory */ |