sim: bfin: new port
[deliverable/binutils-gdb.git] / sim / bfin / dv-bfin_dmac.c
1 /* Blackfin Direct Memory Access (DMA) Controller model.
2
3 Copyright (C) 2010-2011 Free Software Foundation, Inc.
4 Contributed by Analog Devices, Inc.
5
6 This file is part of simulators.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>. */
20
21 #include "config.h"
22
23 #include "sim-main.h"
24 #include "sim-hw.h"
25 #include "devices.h"
26 #include "hw-device.h"
27 #include "dv-bfin_dma.h"
28 #include "dv-bfin_dmac.h"
29
30 struct bfin_dmac
31 {
32 /* This top portion matches common dv_bfin struct. */
33 bu32 base;
34 struct hw *dma_master;
35 bool acked;
36
37 const char **pmap;
38 unsigned int pmap_count;
39 };
40
41 struct hw *
42 bfin_dmac_get_peer (struct hw *dma, bu16 pmap)
43 {
44 struct hw *ret, *me;
45 struct bfin_dmac *dmac;
46 char peer[100];
47
48 me = hw_parent (dma);
49 dmac = hw_data (me);
50 if (pmap & CTYPE)
51 {
52 /* MDMA channel. */
53 unsigned int chan_num = dv_get_bus_num (dma);
54 if (chan_num & 1)
55 chan_num &= ~1;
56 else
57 chan_num |= 1;
58 sprintf (peer, "%s/bfin_dma@%u", hw_path (me), chan_num);
59 }
60 else
61 {
62 unsigned int idx = pmap >> 12;
63 if (idx >= dmac->pmap_count)
64 hw_abort (me, "Invalid DMA peripheral_map %#x", pmap);
65 else
66 sprintf (peer, "/core/bfin_%s", dmac->pmap[idx]);
67 }
68
69 ret = hw_tree_find_device (me, peer);
70 if (!ret)
71 hw_abort (me, "Unable to locate peer for %s (pmap:%#x %s)",
72 hw_name (dma), pmap, peer);
73 return ret;
74 }
75
76 bu16
77 bfin_dmac_default_pmap (struct hw *dma)
78 {
79 unsigned int chan_num = dv_get_bus_num (dma);
80
81 if (chan_num < BFIN_DMAC_MDMA_BASE)
82 return (chan_num % 12) << 12;
83 else
84 return CTYPE; /* MDMA */
85 }
86
87 static const char *bfin_dmac_50x_pmap[] = {
88 "ppi@0", "rsi", "sport@0", "sport@0", "sport@1", "sport@1",
89 "spi@0", "spi@1", "uart2@0", "uart2@0", "uart2@1", "uart2@1",
90 };
91
92 /* XXX: Need to figure out how to handle portmuxed DMA channels. */
93 static const struct hw_port_descriptor bfin_dmac_50x_ports[] = {
94 { "ppi@0", 0, 0, input_port, },
95 { "rsi", 1, 0, input_port, },
96 { "sport@0_rx", 2, 0, input_port, },
97 { "sport@0_tx", 3, 0, input_port, },
98 { "sport@1_tx", 4, 0, input_port, },
99 { "sport@1_rx", 5, 0, input_port, },
100 { "spi@0", 6, 0, input_port, },
101 { "spi@1", 7, 0, input_port, },
102 { "uart2@0_rx", 8, 0, input_port, },
103 { "uart2@0_tx", 9, 0, input_port, },
104 { "uart2@1_rx", 10, 0, input_port, },
105 { "uart2@1_tx", 11, 0, input_port, },
106 { NULL, 0, 0, 0, },
107 };
108
109 static const char *bfin_dmac_51x_pmap[] = {
110 "ppi@0", "emac", "emac", "sport@0", "sport@0", "sport@1",
111 "sport@1", "spi@0", "uart@0", "uart@0", "uart@1", "uart@1",
112 };
113
114 /* XXX: Need to figure out how to handle portmuxed DMA channels. */
115 static const struct hw_port_descriptor bfin_dmac_51x_ports[] = {
116 { "ppi@0", 0, 0, input_port, },
117 { "emac_rx", 1, 0, input_port, },
118 { "emac_tx", 2, 0, input_port, },
119 { "sport@0_rx", 3, 0, input_port, },
120 { "sport@0_tx", 4, 0, input_port, },
121 /*{ "rsi", 4, 0, input_port, },*/
122 { "sport@1_tx", 5, 0, input_port, },
123 /*{ "spi@1", 5, 0, input_port, },*/
124 { "sport@1_rx", 6, 0, input_port, },
125 { "spi@0", 7, 0, input_port, },
126 { "uart@0_rx", 8, 0, input_port, },
127 { "uart@0_tx", 9, 0, input_port, },
128 { "uart@1_rx", 10, 0, input_port, },
129 { "uart@1_tx", 11, 0, input_port, },
130 { NULL, 0, 0, 0, },
131 };
132
133 static const char *bfin_dmac_52x_pmap[] = {
134 "ppi@0", "emac", "emac", "sport@0", "sport@0", "sport@1",
135 "sport@1", "spi", "uart@0", "uart@0", "uart@1", "uart@1",
136 };
137
138 /* XXX: Need to figure out how to handle portmuxed DMA channels
139 like PPI/NFC here which share DMA0. */
140 static const struct hw_port_descriptor bfin_dmac_52x_ports[] = {
141 { "ppi@0", 0, 0, input_port, },
142 /*{ "nfc", 0, 0, input_port, },*/
143 { "emac_rx", 1, 0, input_port, },
144 /*{ "hostdp", 1, 0, input_port, },*/
145 { "emac_tx", 2, 0, input_port, },
146 /*{ "nfc", 2, 0, input_port, },*/
147 { "sport@0_tx", 3, 0, input_port, },
148 { "sport@0_rx", 4, 0, input_port, },
149 { "sport@1_tx", 5, 0, input_port, },
150 { "sport@1_rx", 6, 0, input_port, },
151 { "spi", 7, 0, input_port, },
152 { "uart@0_tx", 8, 0, input_port, },
153 { "uart@0_rx", 9, 0, input_port, },
154 { "uart@1_tx", 10, 0, input_port, },
155 { "uart@1_rx", 11, 0, input_port, },
156 { NULL, 0, 0, 0, },
157 };
158
159 static const char *bfin_dmac_533_pmap[] = {
160 "ppi@0", "sport@0", "sport@0", "sport@1", "sport@1", "spi",
161 "uart@0", "uart@0",
162 };
163
164 static const struct hw_port_descriptor bfin_dmac_533_ports[] = {
165 { "ppi@0", 0, 0, input_port, },
166 { "sport@0_tx", 1, 0, input_port, },
167 { "sport@0_rx", 2, 0, input_port, },
168 { "sport@1_tx", 3, 0, input_port, },
169 { "sport@1_rx", 4, 0, input_port, },
170 { "spi", 5, 0, input_port, },
171 { "uart@0_tx", 6, 0, input_port, },
172 { "uart@0_rx", 7, 0, input_port, },
173 { NULL, 0, 0, 0, },
174 };
175
176 static const char *bfin_dmac_537_pmap[] = {
177 "ppi@0", "emac", "emac", "sport@0", "sport@0", "sport@1",
178 "sport@1", "spi", "uart@0", "uart@0", "uart@1", "uart@1",
179 };
180
181 static const struct hw_port_descriptor bfin_dmac_537_ports[] = {
182 { "ppi@0", 0, 0, input_port, },
183 { "emac_rx", 1, 0, input_port, },
184 { "emac_tx", 2, 0, input_port, },
185 { "sport@0_tx", 3, 0, input_port, },
186 { "sport@0_rx", 4, 0, input_port, },
187 { "sport@1_tx", 5, 0, input_port, },
188 { "sport@1_rx", 6, 0, input_port, },
189 { "spi", 7, 0, input_port, },
190 { "uart@0_tx", 8, 0, input_port, },
191 { "uart@0_rx", 9, 0, input_port, },
192 { "uart@1_tx", 10, 0, input_port, },
193 { "uart@1_rx", 11, 0, input_port, },
194 { NULL, 0, 0, 0, },
195 };
196
197 static const char *bfin_dmac0_538_pmap[] = {
198 "ppi@0", "sport@0", "sport@0", "sport@1", "sport@1", "spi@0",
199 "uart@0", "uart@0",
200 };
201
202 static const struct hw_port_descriptor bfin_dmac0_538_ports[] = {
203 { "ppi@0", 0, 0, input_port, },
204 { "sport@0_rx", 1, 0, input_port, },
205 { "sport@0_tx", 2, 0, input_port, },
206 { "sport@1_rx", 3, 0, input_port, },
207 { "sport@1_tx", 4, 0, input_port, },
208 { "spi@0", 5, 0, input_port, },
209 { "uart@0_rx", 6, 0, input_port, },
210 { "uart@0_tx", 7, 0, input_port, },
211 { NULL, 0, 0, 0, },
212 };
213
214 static const char *bfin_dmac1_538_pmap[] = {
215 "sport@2", "sport@2", "sport@3", "sport@3", NULL, NULL,
216 "spi@1", "spi@2", "uart@1", "uart@1", "uart@2", "uart@2",
217 };
218
219 static const struct hw_port_descriptor bfin_dmac1_538_ports[] = {
220 { "sport@2_rx", 0, 0, input_port, },
221 { "sport@2_tx", 1, 0, input_port, },
222 { "sport@3_rx", 2, 0, input_port, },
223 { "sport@3_tx", 3, 0, input_port, },
224 { "spi@1", 6, 0, input_port, },
225 { "spi@2", 7, 0, input_port, },
226 { "uart@1_rx", 8, 0, input_port, },
227 { "uart@1_tx", 9, 0, input_port, },
228 { "uart@2_rx", 10, 0, input_port, },
229 { "uart@2_tx", 11, 0, input_port, },
230 { NULL, 0, 0, 0, },
231 };
232
233 static const char *bfin_dmac0_54x_pmap[] = {
234 "sport@0", "sport@0", "sport@1", "sport@1", "spi@0", "spi@1",
235 "uart2@0", "uart2@0", "uart2@1", "uart2@1", "atapi", "atapi",
236 };
237
238 static const struct hw_port_descriptor bfin_dmac0_54x_ports[] = {
239 { "sport@0_rx", 0, 0, input_port, },
240 { "sport@0_tx", 1, 0, input_port, },
241 { "sport@1_rx", 2, 0, input_port, },
242 { "sport@1_tx", 3, 0, input_port, },
243 { "spi@0", 4, 0, input_port, },
244 { "spi@1", 5, 0, input_port, },
245 { "uart2@0_rx", 6, 0, input_port, },
246 { "uart2@0_tx", 7, 0, input_port, },
247 { "uart2@1_rx", 8, 0, input_port, },
248 { "uart2@1_tx", 9, 0, input_port, },
249 { "atapi", 10, 0, input_port, },
250 { "atapi", 11, 0, input_port, },
251 { NULL, 0, 0, 0, },
252 };
253
254 static const char *bfin_dmac1_54x_pmap[] = {
255 "eppi@0", "eppi@1", "eppi@2", "pixc", "pixc", "pixc",
256 "sport@2", "sport@2", "sport@3", "sport@3", "sdh",
257 "spi@2", "uart2@2", "uart2@2", "uart2@3", "uart2@3",
258 };
259
260 static const struct hw_port_descriptor bfin_dmac1_54x_ports[] = {
261 { "eppi@0", 0, 0, input_port, },
262 { "eppi@1", 1, 0, input_port, },
263 { "eppi@2", 2, 0, input_port, },
264 { "pixc", 3, 0, input_port, },
265 { "pixc", 4, 0, input_port, },
266 { "pixc", 5, 0, input_port, },
267 { "sport@2_rx", 6, 0, input_port, },
268 { "sport@2_tx", 7, 0, input_port, },
269 { "sport@3_rx", 8, 0, input_port, },
270 { "sport@3_tx", 9, 0, input_port, },
271 { "sdh", 10, 0, input_port, },
272 /*{ "nfc", 10, 0, input_port, },*/
273 { "spi@2", 11, 0, input_port, },
274 { "uart2@2_rx", 12, 0, input_port, },
275 { "uart2@2_tx", 13, 0, input_port, },
276 { "uart2@3_rx", 14, 0, input_port, },
277 { "uart2@3_tx", 15, 0, input_port, },
278 { NULL, 0, 0, 0, },
279 };
280
281 static const char *bfin_dmac0_561_pmap[] = {
282 "sport@0", "sport@0", "sport@1", "sport@1", "spi", "uart@0", "uart@0",
283 };
284
285 static const struct hw_port_descriptor bfin_dmac0_561_ports[] = {
286 { "sport@0_rx", 0, 0, input_port, },
287 { "sport@0_tx", 1, 0, input_port, },
288 { "sport@1_rx", 2, 0, input_port, },
289 { "sport@1_tx", 3, 0, input_port, },
290 { "spi@0", 4, 0, input_port, },
291 { "uart@0_rx", 5, 0, input_port, },
292 { "uart@0_tx", 6, 0, input_port, },
293 { NULL, 0, 0, 0, },
294 };
295
296 static const char *bfin_dmac1_561_pmap[] = {
297 "ppi@0", "ppi@1",
298 };
299
300 static const struct hw_port_descriptor bfin_dmac1_561_ports[] = {
301 { "ppi@0", 0, 0, input_port, },
302 { "ppi@1", 1, 0, input_port, },
303 { NULL, 0, 0, 0, },
304 };
305
306 static const char *bfin_dmac_59x_pmap[] = {
307 "ppi@0", "sport@0", "sport@0", "sport@1", "sport@1", "spi@0",
308 "spi@1", "uart@0", "uart@0",
309 };
310
311 static const struct hw_port_descriptor bfin_dmac_59x_ports[] = {
312 { "ppi@0", 0, 0, input_port, },
313 { "sport@0_tx", 1, 0, input_port, },
314 { "sport@0_rx", 2, 0, input_port, },
315 { "sport@1_tx", 3, 0, input_port, },
316 { "sport@1_rx", 4, 0, input_port, },
317 { "spi@0", 5, 0, input_port, },
318 { "spi@1", 6, 0, input_port, },
319 { "uart@0_rx", 7, 0, input_port, },
320 { "uart@0_tx", 8, 0, input_port, },
321 { NULL, 0, 0, 0, },
322 };
323
324 static void
325 bfin_dmac_port_event (struct hw *me, int my_port, struct hw *source,
326 int source_port, int level)
327 {
328 SIM_DESC sd = hw_system (me);
329 struct bfin_dmac *dmac = hw_data (me);
330 struct hw *dma = hw_child (me);
331
332 while (dma)
333 {
334 bu16 pmap;
335 sim_hw_io_read_buffer (sd, dma, &pmap, 0, 0x2c, sizeof (pmap));
336 pmap >>= 12;
337 if (pmap == my_port)
338 break;
339 dma = hw_sibling (dma);
340 }
341
342 if (!dma)
343 hw_abort (me, "no valid dma mapping found for %s", dmac->pmap[my_port]);
344
345 /* Have the DMA channel raise its interrupt to the SIC. */
346 hw_port_event (dma, 0, 1);
347 }
348
349 static void
350 bfin_dmac_finish (struct hw *me)
351 {
352 struct bfin_dmac *dmac;
353 unsigned int dmac_num = dv_get_bus_num (me);
354
355 dmac = HW_ZALLOC (me, struct bfin_dmac);
356
357 set_hw_data (me, dmac);
358 set_hw_port_event (me, bfin_dmac_port_event);
359
360 /* Initialize the DMA Controller. */
361 if (hw_find_property (me, "type") == NULL)
362 hw_abort (me, "Missing \"type\" property");
363
364 switch (hw_find_integer_property (me, "type"))
365 {
366 case 500 ... 509:
367 if (dmac_num != 0)
368 hw_abort (me, "this Blackfin only has a DMAC0");
369 dmac->pmap = bfin_dmac_50x_pmap;
370 dmac->pmap_count = ARRAY_SIZE (bfin_dmac_50x_pmap);
371 set_hw_ports (me, bfin_dmac_50x_ports);
372 break;
373 case 510 ... 519:
374 if (dmac_num != 0)
375 hw_abort (me, "this Blackfin only has a DMAC0");
376 dmac->pmap = bfin_dmac_51x_pmap;
377 dmac->pmap_count = ARRAY_SIZE (bfin_dmac_51x_pmap);
378 set_hw_ports (me, bfin_dmac_51x_ports);
379 break;
380 case 522 ... 527:
381 if (dmac_num != 0)
382 hw_abort (me, "this Blackfin only has a DMAC0");
383 dmac->pmap = bfin_dmac_52x_pmap;
384 dmac->pmap_count = ARRAY_SIZE (bfin_dmac_52x_pmap);
385 set_hw_ports (me, bfin_dmac_52x_ports);
386 break;
387 case 531 ... 533:
388 if (dmac_num != 0)
389 hw_abort (me, "this Blackfin only has a DMAC0");
390 dmac->pmap = bfin_dmac_533_pmap;
391 dmac->pmap_count = ARRAY_SIZE (bfin_dmac_533_pmap);
392 set_hw_ports (me, bfin_dmac_533_ports);
393 break;
394 case 534:
395 case 536:
396 case 537:
397 if (dmac_num != 0)
398 hw_abort (me, "this Blackfin only has a DMAC0");
399 dmac->pmap = bfin_dmac_537_pmap;
400 dmac->pmap_count = ARRAY_SIZE (bfin_dmac_537_pmap);
401 set_hw_ports (me, bfin_dmac_537_ports);
402 break;
403 case 538 ... 539:
404 switch (dmac_num)
405 {
406 case 0:
407 dmac->pmap = bfin_dmac0_538_pmap;
408 dmac->pmap_count = ARRAY_SIZE (bfin_dmac0_538_pmap);
409 set_hw_ports (me, bfin_dmac0_538_ports);
410 break;
411 case 1:
412 dmac->pmap = bfin_dmac1_538_pmap;
413 dmac->pmap_count = ARRAY_SIZE (bfin_dmac1_538_pmap);
414 set_hw_ports (me, bfin_dmac1_538_ports);
415 break;
416 default:
417 hw_abort (me, "this Blackfin only has a DMAC0 & DMAC1");
418 }
419 break;
420 case 540 ... 549:
421 switch (dmac_num)
422 {
423 case 0:
424 dmac->pmap = bfin_dmac0_54x_pmap;
425 dmac->pmap_count = ARRAY_SIZE (bfin_dmac0_54x_pmap);
426 set_hw_ports (me, bfin_dmac0_54x_ports);
427 break;
428 case 1:
429 dmac->pmap = bfin_dmac1_54x_pmap;
430 dmac->pmap_count = ARRAY_SIZE (bfin_dmac1_54x_pmap);
431 set_hw_ports (me, bfin_dmac1_54x_ports);
432 break;
433 default:
434 hw_abort (me, "this Blackfin only has a DMAC0 & DMAC1");
435 }
436 break;
437 case 561:
438 switch (dmac_num)
439 {
440 case 0:
441 dmac->pmap = bfin_dmac0_561_pmap;
442 dmac->pmap_count = ARRAY_SIZE (bfin_dmac0_561_pmap);
443 set_hw_ports (me, bfin_dmac0_561_ports);
444 break;
445 case 1:
446 dmac->pmap = bfin_dmac1_561_pmap;
447 dmac->pmap_count = ARRAY_SIZE (bfin_dmac1_561_pmap);
448 set_hw_ports (me, bfin_dmac1_561_ports);
449 break;
450 default:
451 hw_abort (me, "this Blackfin only has a DMAC0 & DMAC1");
452 }
453 break;
454 case 590 ... 599:
455 if (dmac_num != 0)
456 hw_abort (me, "this Blackfin only has a DMAC0");
457 dmac->pmap = bfin_dmac_59x_pmap;
458 dmac->pmap_count = ARRAY_SIZE (bfin_dmac_59x_pmap);
459 set_hw_ports (me, bfin_dmac_59x_ports);
460 break;
461 default:
462 hw_abort (me, "no support for DMAC on this Blackfin model yet");
463 }
464 }
465
466 const struct hw_descriptor dv_bfin_dmac_descriptor[] = {
467 {"bfin_dmac", bfin_dmac_finish,},
468 {NULL, NULL},
469 };
This page took 0.047676 seconds and 4 git commands to generate.