Imported Upstream version 7.9
[platform/upstream/gdb.git] / sim / bfin / dv-bfin_dmac.c
1 /* Blackfin Direct Memory Access (DMA) Controller model.
2
3    Copyright (C) 2010-2015 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 * const *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 * const bfin_dmac_50x_pmap[] =
88 {
89   "ppi@0", "rsi", "sport@0", "sport@0", "sport@1", "sport@1",
90   "spi@0", "spi@1", "uart2@0", "uart2@0", "uart2@1", "uart2@1",
91 };
92
93 /* XXX: Need to figure out how to handle portmuxed DMA channels.  */
94 static const struct hw_port_descriptor bfin_dmac_50x_ports[] =
95 {
96   { "ppi@0",       0, 0, input_port, },
97   { "rsi",         1, 0, input_port, },
98   { "sport@0_rx",  2, 0, input_port, },
99   { "sport@0_tx",  3, 0, input_port, },
100   { "sport@1_tx",  4, 0, input_port, },
101   { "sport@1_rx",  5, 0, input_port, },
102   { "spi@0",       6, 0, input_port, },
103   { "spi@1",       7, 0, input_port, },
104   { "uart2@0_rx",  8, 0, input_port, },
105   { "uart2@0_tx",  9, 0, input_port, },
106   { "uart2@1_rx", 10, 0, input_port, },
107   { "uart2@1_tx", 11, 0, input_port, },
108   { NULL, 0, 0, 0, },
109 };
110
111 static const char * const bfin_dmac_51x_pmap[] =
112 {
113   "ppi@0", "emac", "emac", "sport@0", "sport@0", "sport@1",
114   "sport@1", "spi@0", "uart@0", "uart@0", "uart@1", "uart@1",
115 };
116
117 /* XXX: Need to figure out how to handle portmuxed DMA channels.  */
118 static const struct hw_port_descriptor bfin_dmac_51x_ports[] =
119 {
120   { "ppi@0",       0, 0, input_port, },
121   { "emac_rx",     1, 0, input_port, },
122   { "emac_tx",     2, 0, input_port, },
123   { "sport@0_rx",  3, 0, input_port, },
124   { "sport@0_tx",  4, 0, input_port, },
125 /*{ "rsi",         4, 0, input_port, },*/
126   { "sport@1_tx",  5, 0, input_port, },
127 /*{ "spi@1",       5, 0, input_port, },*/
128   { "sport@1_rx",  6, 0, input_port, },
129   { "spi@0",       7, 0, input_port, },
130   { "uart@0_rx",   8, 0, input_port, },
131   { "uart@0_tx",   9, 0, input_port, },
132   { "uart@1_rx",  10, 0, input_port, },
133   { "uart@1_tx",  11, 0, input_port, },
134   { NULL, 0, 0, 0, },
135 };
136
137 static const char * const bfin_dmac_52x_pmap[] =
138 {
139   "ppi@0", "emac", "emac", "sport@0", "sport@0", "sport@1",
140   "sport@1", "spi", "uart@0", "uart@0", "uart@1", "uart@1",
141 };
142
143 /* XXX: Need to figure out how to handle portmuxed DMA channels
144         like PPI/NFC here which share DMA0.  */
145 static const struct hw_port_descriptor bfin_dmac_52x_ports[] =
146 {
147   { "ppi@0",       0, 0, input_port, },
148 /*{ "nfc",         0, 0, input_port, },*/
149   { "emac_rx",     1, 0, input_port, },
150 /*{ "hostdp",      1, 0, input_port, },*/
151   { "emac_tx",     2, 0, input_port, },
152 /*{ "nfc",         2, 0, input_port, },*/
153   { "sport@0_tx",  3, 0, input_port, },
154   { "sport@0_rx",  4, 0, input_port, },
155   { "sport@1_tx",  5, 0, input_port, },
156   { "sport@1_rx",  6, 0, input_port, },
157   { "spi",         7, 0, input_port, },
158   { "uart@0_tx",   8, 0, input_port, },
159   { "uart@0_rx",   9, 0, input_port, },
160   { "uart@1_tx",  10, 0, input_port, },
161   { "uart@1_rx",  11, 0, input_port, },
162   { NULL, 0, 0, 0, },
163 };
164
165 static const char * const bfin_dmac_533_pmap[] =
166 {
167   "ppi@0", "sport@0", "sport@0", "sport@1", "sport@1", "spi",
168   "uart@0", "uart@0",
169 };
170
171 static const struct hw_port_descriptor bfin_dmac_533_ports[] =
172 {
173   { "ppi@0",       0, 0, input_port, },
174   { "sport@0_tx",  1, 0, input_port, },
175   { "sport@0_rx",  2, 0, input_port, },
176   { "sport@1_tx",  3, 0, input_port, },
177   { "sport@1_rx",  4, 0, input_port, },
178   { "spi",         5, 0, input_port, },
179   { "uart@0_tx",   6, 0, input_port, },
180   { "uart@0_rx",   7, 0, input_port, },
181   { NULL, 0, 0, 0, },
182 };
183
184 static const char * const bfin_dmac_537_pmap[] =
185 {
186   "ppi@0", "emac", "emac", "sport@0", "sport@0", "sport@1",
187   "sport@1", "spi", "uart@0", "uart@0", "uart@1", "uart@1",
188 };
189
190 static const struct hw_port_descriptor bfin_dmac_537_ports[] =
191 {
192   { "ppi@0",       0, 0, input_port, },
193   { "emac_rx",     1, 0, input_port, },
194   { "emac_tx",     2, 0, input_port, },
195   { "sport@0_tx",  3, 0, input_port, },
196   { "sport@0_rx",  4, 0, input_port, },
197   { "sport@1_tx",  5, 0, input_port, },
198   { "sport@1_rx",  6, 0, input_port, },
199   { "spi",         7, 0, input_port, },
200   { "uart@0_tx",   8, 0, input_port, },
201   { "uart@0_rx",   9, 0, input_port, },
202   { "uart@1_tx",  10, 0, input_port, },
203   { "uart@1_rx",  11, 0, input_port, },
204   { NULL, 0, 0, 0, },
205 };
206
207 static const char * const bfin_dmac0_538_pmap[] =
208 {
209   "ppi@0", "sport@0", "sport@0", "sport@1", "sport@1", "spi@0",
210   "uart@0", "uart@0",
211 };
212
213 static const struct hw_port_descriptor bfin_dmac0_538_ports[] =
214 {
215   { "ppi@0",       0, 0, input_port, },
216   { "sport@0_rx",  1, 0, input_port, },
217   { "sport@0_tx",  2, 0, input_port, },
218   { "sport@1_rx",  3, 0, input_port, },
219   { "sport@1_tx",  4, 0, input_port, },
220   { "spi@0",       5, 0, input_port, },
221   { "uart@0_rx",   6, 0, input_port, },
222   { "uart@0_tx",   7, 0, input_port, },
223   { NULL, 0, 0, 0, },
224 };
225
226 static const char * const bfin_dmac1_538_pmap[] =
227 {
228   "sport@2", "sport@2", "sport@3", "sport@3", NULL, NULL,
229   "spi@1", "spi@2", "uart@1", "uart@1", "uart@2", "uart@2",
230 };
231
232 static const struct hw_port_descriptor bfin_dmac1_538_ports[] =
233 {
234   { "sport@2_rx",  0, 0, input_port, },
235   { "sport@2_tx",  1, 0, input_port, },
236   { "sport@3_rx",  2, 0, input_port, },
237   { "sport@3_tx",  3, 0, input_port, },
238   { "spi@1",       6, 0, input_port, },
239   { "spi@2",       7, 0, input_port, },
240   { "uart@1_rx",   8, 0, input_port, },
241   { "uart@1_tx",   9, 0, input_port, },
242   { "uart@2_rx",  10, 0, input_port, },
243   { "uart@2_tx",  11, 0, input_port, },
244   { NULL, 0, 0, 0, },
245 };
246
247 static const char * const bfin_dmac0_54x_pmap[] =
248 {
249   "sport@0", "sport@0", "sport@1", "sport@1", "spi@0", "spi@1",
250   "uart2@0", "uart2@0", "uart2@1", "uart2@1", "atapi", "atapi",
251 };
252
253 static const struct hw_port_descriptor bfin_dmac0_54x_ports[] =
254 {
255   { "sport@0_rx",  0, 0, input_port, },
256   { "sport@0_tx",  1, 0, input_port, },
257   { "sport@1_rx",  2, 0, input_port, },
258   { "sport@1_tx",  3, 0, input_port, },
259   { "spi@0",       4, 0, input_port, },
260   { "spi@1",       5, 0, input_port, },
261   { "uart2@0_rx",  6, 0, input_port, },
262   { "uart2@0_tx",  7, 0, input_port, },
263   { "uart2@1_rx",  8, 0, input_port, },
264   { "uart2@1_tx",  9, 0, input_port, },
265   { "atapi",      10, 0, input_port, },
266   { "atapi",      11, 0, input_port, },
267   { NULL, 0, 0, 0, },
268 };
269
270 static const char * const bfin_dmac1_54x_pmap[] =
271 {
272   "eppi@0", "eppi@1", "eppi@2", "pixc", "pixc", "pixc",
273   "sport@2", "sport@2", "sport@3", "sport@3", "sdh",
274   "spi@2", "uart2@2", "uart2@2", "uart2@3", "uart2@3",
275 };
276
277 static const struct hw_port_descriptor bfin_dmac1_54x_ports[] =
278 {
279   { "eppi@0",      0, 0, input_port, },
280   { "eppi@1",      1, 0, input_port, },
281   { "eppi@2",      2, 0, input_port, },
282   { "pixc",        3, 0, input_port, },
283   { "pixc",        4, 0, input_port, },
284   { "pixc",        5, 0, input_port, },
285   { "sport@2_rx",  6, 0, input_port, },
286   { "sport@2_tx",  7, 0, input_port, },
287   { "sport@3_rx",  8, 0, input_port, },
288   { "sport@3_tx",  9, 0, input_port, },
289   { "sdh",        10, 0, input_port, },
290 /*{ "nfc",        10, 0, input_port, },*/
291   { "spi@2",      11, 0, input_port, },
292   { "uart2@2_rx", 12, 0, input_port, },
293   { "uart2@2_tx", 13, 0, input_port, },
294   { "uart2@3_rx", 14, 0, input_port, },
295   { "uart2@3_tx", 15, 0, input_port, },
296   { NULL, 0, 0, 0, },
297 };
298
299 static const char * const bfin_dmac0_561_pmap[] =
300 {
301   "sport@0", "sport@0", "sport@1", "sport@1", "spi", "uart@0", "uart@0",
302 };
303
304 static const struct hw_port_descriptor bfin_dmac0_561_ports[] =
305 {
306   { "sport@0_rx",  0, 0, input_port, },
307   { "sport@0_tx",  1, 0, input_port, },
308   { "sport@1_rx",  2, 0, input_port, },
309   { "sport@1_tx",  3, 0, input_port, },
310   { "spi@0",       4, 0, input_port, },
311   { "uart@0_rx",   5, 0, input_port, },
312   { "uart@0_tx",   6, 0, input_port, },
313   { NULL, 0, 0, 0, },
314 };
315
316 static const char * const bfin_dmac1_561_pmap[] =
317 {
318   "ppi@0", "ppi@1",
319 };
320
321 static const struct hw_port_descriptor bfin_dmac1_561_ports[] =
322 {
323   { "ppi@0",       0, 0, input_port, },
324   { "ppi@1",       1, 0, input_port, },
325   { NULL, 0, 0, 0, },
326 };
327
328 static const char * const bfin_dmac_59x_pmap[] =
329 {
330   "ppi@0", "sport@0", "sport@0", "sport@1", "sport@1", "spi@0",
331   "spi@1", "uart@0", "uart@0",
332 };
333
334 static const struct hw_port_descriptor bfin_dmac_59x_ports[] =
335 {
336   { "ppi@0",       0, 0, input_port, },
337   { "sport@0_tx",  1, 0, input_port, },
338   { "sport@0_rx",  2, 0, input_port, },
339   { "sport@1_tx",  3, 0, input_port, },
340   { "sport@1_rx",  4, 0, input_port, },
341   { "spi@0",       5, 0, input_port, },
342   { "spi@1",       6, 0, input_port, },
343   { "uart@0_rx",   7, 0, input_port, },
344   { "uart@0_tx",   8, 0, input_port, },
345   { NULL, 0, 0, 0, },
346 };
347
348 static void
349 bfin_dmac_port_event (struct hw *me, int my_port, struct hw *source,
350                       int source_port, int level)
351 {
352   SIM_DESC sd = hw_system (me);
353   struct bfin_dmac *dmac = hw_data (me);
354   struct hw *dma = hw_child (me);
355
356   while (dma)
357     {
358       bu16 pmap;
359       sim_hw_io_read_buffer (sd, dma, &pmap, 0, 0x2c, sizeof (pmap));
360       pmap >>= 12;
361       if (pmap == my_port)
362         break;
363       dma = hw_sibling (dma);
364     }
365
366   if (!dma)
367     hw_abort (me, "no valid dma mapping found for %s", dmac->pmap[my_port]);
368
369   /* Have the DMA channel raise its interrupt to the SIC.  */
370   hw_port_event (dma, 0, 1);
371 }
372
373 static void
374 bfin_dmac_finish (struct hw *me)
375 {
376   struct bfin_dmac *dmac;
377   unsigned int dmac_num = dv_get_bus_num (me);
378
379   dmac = HW_ZALLOC (me, struct bfin_dmac);
380
381   set_hw_data (me, dmac);
382   set_hw_port_event (me, bfin_dmac_port_event);
383
384   /* Initialize the DMA Controller.  */
385   if (hw_find_property (me, "type") == NULL)
386     hw_abort (me, "Missing \"type\" property");
387
388   switch (hw_find_integer_property (me, "type"))
389     {
390     case 500 ... 509:
391       if (dmac_num != 0)
392         hw_abort (me, "this Blackfin only has a DMAC0");
393       dmac->pmap = bfin_dmac_50x_pmap;
394       dmac->pmap_count = ARRAY_SIZE (bfin_dmac_50x_pmap);
395       set_hw_ports (me, bfin_dmac_50x_ports);
396       break;
397     case 510 ... 519:
398       if (dmac_num != 0)
399         hw_abort (me, "this Blackfin only has a DMAC0");
400       dmac->pmap = bfin_dmac_51x_pmap;
401       dmac->pmap_count = ARRAY_SIZE (bfin_dmac_51x_pmap);
402       set_hw_ports (me, bfin_dmac_51x_ports);
403       break;
404     case 522 ... 527:
405       if (dmac_num != 0)
406         hw_abort (me, "this Blackfin only has a DMAC0");
407       dmac->pmap = bfin_dmac_52x_pmap;
408       dmac->pmap_count = ARRAY_SIZE (bfin_dmac_52x_pmap);
409       set_hw_ports (me, bfin_dmac_52x_ports);
410       break;
411     case 531 ... 533:
412       if (dmac_num != 0)
413         hw_abort (me, "this Blackfin only has a DMAC0");
414       dmac->pmap = bfin_dmac_533_pmap;
415       dmac->pmap_count = ARRAY_SIZE (bfin_dmac_533_pmap);
416       set_hw_ports (me, bfin_dmac_533_ports);
417       break;
418     case 534:
419     case 536:
420     case 537:
421       if (dmac_num != 0)
422         hw_abort (me, "this Blackfin only has a DMAC0");
423       dmac->pmap = bfin_dmac_537_pmap;
424       dmac->pmap_count = ARRAY_SIZE (bfin_dmac_537_pmap);
425       set_hw_ports (me, bfin_dmac_537_ports);
426       break;
427     case 538 ... 539:
428       switch (dmac_num)
429         {
430         case 0:
431           dmac->pmap = bfin_dmac0_538_pmap;
432           dmac->pmap_count = ARRAY_SIZE (bfin_dmac0_538_pmap);
433           set_hw_ports (me, bfin_dmac0_538_ports);
434           break;
435         case 1:
436           dmac->pmap = bfin_dmac1_538_pmap;
437           dmac->pmap_count = ARRAY_SIZE (bfin_dmac1_538_pmap);
438           set_hw_ports (me, bfin_dmac1_538_ports);
439           break;
440         default:
441           hw_abort (me, "this Blackfin only has a DMAC0 & DMAC1");
442         }
443       break;
444     case 540 ... 549:
445       switch (dmac_num)
446         {
447         case 0:
448           dmac->pmap = bfin_dmac0_54x_pmap;
449           dmac->pmap_count = ARRAY_SIZE (bfin_dmac0_54x_pmap);
450           set_hw_ports (me, bfin_dmac0_54x_ports);
451           break;
452         case 1:
453           dmac->pmap = bfin_dmac1_54x_pmap;
454           dmac->pmap_count = ARRAY_SIZE (bfin_dmac1_54x_pmap);
455           set_hw_ports (me, bfin_dmac1_54x_ports);
456           break;
457         default:
458           hw_abort (me, "this Blackfin only has a DMAC0 & DMAC1");
459         }
460       break;
461     case 561:
462       switch (dmac_num)
463         {
464         case 0:
465           dmac->pmap = bfin_dmac0_561_pmap;
466           dmac->pmap_count = ARRAY_SIZE (bfin_dmac0_561_pmap);
467           set_hw_ports (me, bfin_dmac0_561_ports);
468           break;
469         case 1:
470           dmac->pmap = bfin_dmac1_561_pmap;
471           dmac->pmap_count = ARRAY_SIZE (bfin_dmac1_561_pmap);
472           set_hw_ports (me, bfin_dmac1_561_ports);
473           break;
474         default:
475           hw_abort (me, "this Blackfin only has a DMAC0 & DMAC1");
476         }
477       break;
478     case 590 ... 599:
479       if (dmac_num != 0)
480         hw_abort (me, "this Blackfin only has a DMAC0");
481       dmac->pmap = bfin_dmac_59x_pmap;
482       dmac->pmap_count = ARRAY_SIZE (bfin_dmac_59x_pmap);
483       set_hw_ports (me, bfin_dmac_59x_ports);
484       break;
485     default:
486       hw_abort (me, "no support for DMAC on this Blackfin model yet");
487     }
488 }
489
490 const struct hw_descriptor dv_bfin_dmac_descriptor[] =
491 {
492   {"bfin_dmac", bfin_dmac_finish,},
493   {NULL, NULL},
494 };