xref: /openbmc/qemu/hw/ppc/ppc4xx_devs.c (revision 629cae617039e03d5bfdc0120ade69135a009d33)
1 /*
2  * QEMU PowerPC 4xx embedded processors shared devices emulation
3  *
4  * Copyright (c) 2007 Jocelyn Mayer
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  */
24 
25 #include "qemu/osdep.h"
26 #include "qemu/units.h"
27 #include "sysemu/reset.h"
28 #include "cpu.h"
29 #include "hw/irq.h"
30 #include "hw/ppc/ppc.h"
31 #include "hw/ppc/ppc4xx.h"
32 #include "hw/intc/ppc-uic.h"
33 #include "hw/qdev-properties.h"
34 #include "qemu/log.h"
35 #include "exec/address-spaces.h"
36 #include "qemu/error-report.h"
37 #include "qapi/error.h"
38 #include "trace.h"
39 
40 /*****************************************************************************/
41 /* SDRAM controller */
42 typedef struct ppc4xx_sdram_t ppc4xx_sdram_t;
43 struct ppc4xx_sdram_t {
44     uint32_t addr;
45     int nbanks;
46     MemoryRegion containers[4]; /* used for clipping */
47     MemoryRegion *ram_memories;
48     hwaddr ram_bases[4];
49     hwaddr ram_sizes[4];
50     uint32_t besr0;
51     uint32_t besr1;
52     uint32_t bear;
53     uint32_t cfg;
54     uint32_t status;
55     uint32_t rtr;
56     uint32_t pmit;
57     uint32_t bcr[4];
58     uint32_t tr;
59     uint32_t ecccfg;
60     uint32_t eccesr;
61     qemu_irq irq;
62 };
63 
64 enum {
65     SDRAM0_CFGADDR = 0x010,
66     SDRAM0_CFGDATA = 0x011,
67 };
68 
69 /* XXX: TOFIX: some patches have made this code become inconsistent:
70  *      there are type inconsistencies, mixing hwaddr, target_ulong
71  *      and uint32_t
72  */
73 static uint32_t sdram_bcr (hwaddr ram_base,
74                            hwaddr ram_size)
75 {
76     uint32_t bcr;
77 
78     switch (ram_size) {
79     case 4 * MiB:
80         bcr = 0x00000000;
81         break;
82     case 8 * MiB:
83         bcr = 0x00020000;
84         break;
85     case 16 * MiB:
86         bcr = 0x00040000;
87         break;
88     case 32 * MiB:
89         bcr = 0x00060000;
90         break;
91     case 64 * MiB:
92         bcr = 0x00080000;
93         break;
94     case 128 * MiB:
95         bcr = 0x000A0000;
96         break;
97     case 256 * MiB:
98         bcr = 0x000C0000;
99         break;
100     default:
101         qemu_log_mask(LOG_GUEST_ERROR,
102                       "%s: invalid RAM size 0x%" HWADDR_PRIx "\n", __func__,
103                       ram_size);
104         return 0x00000000;
105     }
106     bcr |= ram_base & 0xFF800000;
107     bcr |= 1;
108 
109     return bcr;
110 }
111 
112 static inline hwaddr sdram_base(uint32_t bcr)
113 {
114     return bcr & 0xFF800000;
115 }
116 
117 static target_ulong sdram_size (uint32_t bcr)
118 {
119     target_ulong size;
120     int sh;
121 
122     sh = (bcr >> 17) & 0x7;
123     if (sh == 7)
124         size = -1;
125     else
126         size = (4 * MiB) << sh;
127 
128     return size;
129 }
130 
131 static void sdram_set_bcr(ppc4xx_sdram_t *sdram, int i,
132                           uint32_t bcr, int enabled)
133 {
134     if (sdram->bcr[i] & 0x00000001) {
135         /* Unmap RAM */
136         trace_ppc4xx_sdram_unmap(sdram_base(sdram->bcr[i]),
137                                  sdram_size(sdram->bcr[i]));
138         memory_region_del_subregion(get_system_memory(),
139                                     &sdram->containers[i]);
140         memory_region_del_subregion(&sdram->containers[i],
141                                     &sdram->ram_memories[i]);
142         object_unparent(OBJECT(&sdram->containers[i]));
143     }
144     sdram->bcr[i] = bcr & 0xFFDEE001;
145     if (enabled && (bcr & 0x00000001)) {
146         trace_ppc4xx_sdram_unmap(sdram_base(bcr), sdram_size(bcr));
147         memory_region_init(&sdram->containers[i], NULL, "sdram-containers",
148                            sdram_size(bcr));
149         memory_region_add_subregion(&sdram->containers[i], 0,
150                                     &sdram->ram_memories[i]);
151         memory_region_add_subregion(get_system_memory(),
152                                     sdram_base(bcr),
153                                     &sdram->containers[i]);
154     }
155 }
156 
157 static void sdram_map_bcr (ppc4xx_sdram_t *sdram)
158 {
159     int i;
160 
161     for (i = 0; i < sdram->nbanks; i++) {
162         if (sdram->ram_sizes[i] != 0) {
163             sdram_set_bcr(sdram, i, sdram_bcr(sdram->ram_bases[i],
164                                               sdram->ram_sizes[i]), 1);
165         } else {
166             sdram_set_bcr(sdram, i, 0x00000000, 0);
167         }
168     }
169 }
170 
171 static void sdram_unmap_bcr (ppc4xx_sdram_t *sdram)
172 {
173     int i;
174 
175     for (i = 0; i < sdram->nbanks; i++) {
176         trace_ppc4xx_sdram_unmap(sdram_base(sdram->bcr[i]),
177                                  sdram_size(sdram->bcr[i]));
178         memory_region_del_subregion(get_system_memory(),
179                                     &sdram->ram_memories[i]);
180     }
181 }
182 
183 static uint32_t dcr_read_sdram (void *opaque, int dcrn)
184 {
185     ppc4xx_sdram_t *sdram;
186     uint32_t ret;
187 
188     sdram = opaque;
189     switch (dcrn) {
190     case SDRAM0_CFGADDR:
191         ret = sdram->addr;
192         break;
193     case SDRAM0_CFGDATA:
194         switch (sdram->addr) {
195         case 0x00: /* SDRAM_BESR0 */
196             ret = sdram->besr0;
197             break;
198         case 0x08: /* SDRAM_BESR1 */
199             ret = sdram->besr1;
200             break;
201         case 0x10: /* SDRAM_BEAR */
202             ret = sdram->bear;
203             break;
204         case 0x20: /* SDRAM_CFG */
205             ret = sdram->cfg;
206             break;
207         case 0x24: /* SDRAM_STATUS */
208             ret = sdram->status;
209             break;
210         case 0x30: /* SDRAM_RTR */
211             ret = sdram->rtr;
212             break;
213         case 0x34: /* SDRAM_PMIT */
214             ret = sdram->pmit;
215             break;
216         case 0x40: /* SDRAM_B0CR */
217             ret = sdram->bcr[0];
218             break;
219         case 0x44: /* SDRAM_B1CR */
220             ret = sdram->bcr[1];
221             break;
222         case 0x48: /* SDRAM_B2CR */
223             ret = sdram->bcr[2];
224             break;
225         case 0x4C: /* SDRAM_B3CR */
226             ret = sdram->bcr[3];
227             break;
228         case 0x80: /* SDRAM_TR */
229             ret = -1; /* ? */
230             break;
231         case 0x94: /* SDRAM_ECCCFG */
232             ret = sdram->ecccfg;
233             break;
234         case 0x98: /* SDRAM_ECCESR */
235             ret = sdram->eccesr;
236             break;
237         default: /* Error */
238             ret = -1;
239             break;
240         }
241         break;
242     default:
243         /* Avoid gcc warning */
244         ret = 0x00000000;
245         break;
246     }
247 
248     return ret;
249 }
250 
251 static void dcr_write_sdram (void *opaque, int dcrn, uint32_t val)
252 {
253     ppc4xx_sdram_t *sdram;
254 
255     sdram = opaque;
256     switch (dcrn) {
257     case SDRAM0_CFGADDR:
258         sdram->addr = val;
259         break;
260     case SDRAM0_CFGDATA:
261         switch (sdram->addr) {
262         case 0x00: /* SDRAM_BESR0 */
263             sdram->besr0 &= ~val;
264             break;
265         case 0x08: /* SDRAM_BESR1 */
266             sdram->besr1 &= ~val;
267             break;
268         case 0x10: /* SDRAM_BEAR */
269             sdram->bear = val;
270             break;
271         case 0x20: /* SDRAM_CFG */
272             val &= 0xFFE00000;
273             if (!(sdram->cfg & 0x80000000) && (val & 0x80000000)) {
274                 trace_ppc4xx_sdram_enable("enable");
275                 /* validate all RAM mappings */
276                 sdram_map_bcr(sdram);
277                 sdram->status &= ~0x80000000;
278             } else if ((sdram->cfg & 0x80000000) && !(val & 0x80000000)) {
279                 trace_ppc4xx_sdram_enable("disable");
280                 /* invalidate all RAM mappings */
281                 sdram_unmap_bcr(sdram);
282                 sdram->status |= 0x80000000;
283             }
284             if (!(sdram->cfg & 0x40000000) && (val & 0x40000000))
285                 sdram->status |= 0x40000000;
286             else if ((sdram->cfg & 0x40000000) && !(val & 0x40000000))
287                 sdram->status &= ~0x40000000;
288             sdram->cfg = val;
289             break;
290         case 0x24: /* SDRAM_STATUS */
291             /* Read-only register */
292             break;
293         case 0x30: /* SDRAM_RTR */
294             sdram->rtr = val & 0x3FF80000;
295             break;
296         case 0x34: /* SDRAM_PMIT */
297             sdram->pmit = (val & 0xF8000000) | 0x07C00000;
298             break;
299         case 0x40: /* SDRAM_B0CR */
300             sdram_set_bcr(sdram, 0, val, sdram->cfg & 0x80000000);
301             break;
302         case 0x44: /* SDRAM_B1CR */
303             sdram_set_bcr(sdram, 1, val, sdram->cfg & 0x80000000);
304             break;
305         case 0x48: /* SDRAM_B2CR */
306             sdram_set_bcr(sdram, 2, val, sdram->cfg & 0x80000000);
307             break;
308         case 0x4C: /* SDRAM_B3CR */
309             sdram_set_bcr(sdram, 3, val, sdram->cfg & 0x80000000);
310             break;
311         case 0x80: /* SDRAM_TR */
312             sdram->tr = val & 0x018FC01F;
313             break;
314         case 0x94: /* SDRAM_ECCCFG */
315             sdram->ecccfg = val & 0x00F00000;
316             break;
317         case 0x98: /* SDRAM_ECCESR */
318             val &= 0xFFF0F000;
319             if (sdram->eccesr == 0 && val != 0)
320                 qemu_irq_raise(sdram->irq);
321             else if (sdram->eccesr != 0 && val == 0)
322                 qemu_irq_lower(sdram->irq);
323             sdram->eccesr = val;
324             break;
325         default: /* Error */
326             break;
327         }
328         break;
329     }
330 }
331 
332 static void sdram_reset (void *opaque)
333 {
334     ppc4xx_sdram_t *sdram;
335 
336     sdram = opaque;
337     sdram->addr = 0x00000000;
338     sdram->bear = 0x00000000;
339     sdram->besr0 = 0x00000000; /* No error */
340     sdram->besr1 = 0x00000000; /* No error */
341     sdram->cfg = 0x00000000;
342     sdram->ecccfg = 0x00000000; /* No ECC */
343     sdram->eccesr = 0x00000000; /* No error */
344     sdram->pmit = 0x07C00000;
345     sdram->rtr = 0x05F00000;
346     sdram->tr = 0x00854009;
347     /* We pre-initialize RAM banks */
348     sdram->status = 0x00000000;
349     sdram->cfg = 0x00800000;
350 }
351 
352 void ppc4xx_sdram_init (CPUPPCState *env, qemu_irq irq, int nbanks,
353                         MemoryRegion *ram_memories,
354                         hwaddr *ram_bases,
355                         hwaddr *ram_sizes,
356                         int do_init)
357 {
358     ppc4xx_sdram_t *sdram;
359 
360     sdram = g_new0(ppc4xx_sdram_t, 1);
361     sdram->irq = irq;
362     sdram->nbanks = nbanks;
363     sdram->ram_memories = ram_memories;
364     memset(sdram->ram_bases, 0, 4 * sizeof(hwaddr));
365     memcpy(sdram->ram_bases, ram_bases,
366            nbanks * sizeof(hwaddr));
367     memset(sdram->ram_sizes, 0, 4 * sizeof(hwaddr));
368     memcpy(sdram->ram_sizes, ram_sizes,
369            nbanks * sizeof(hwaddr));
370     qemu_register_reset(&sdram_reset, sdram);
371     ppc_dcr_register(env, SDRAM0_CFGADDR,
372                      sdram, &dcr_read_sdram, &dcr_write_sdram);
373     ppc_dcr_register(env, SDRAM0_CFGDATA,
374                      sdram, &dcr_read_sdram, &dcr_write_sdram);
375     if (do_init)
376         sdram_map_bcr(sdram);
377 }
378 
379 /*
380  * Split RAM between SDRAM banks.
381  *
382  * sdram_bank_sizes[] must be in descending order, that is sizes[i] > sizes[i+1]
383  * and must be 0-terminated.
384  *
385  * The 4xx SDRAM controller supports a small number of banks, and each bank
386  * must be one of a small set of sizes. The number of banks and the supported
387  * sizes varies by SoC.
388  */
389 void ppc4xx_sdram_banks(MemoryRegion *ram, int nr_banks,
390                         MemoryRegion ram_memories[],
391                         hwaddr ram_bases[], hwaddr ram_sizes[],
392                         const ram_addr_t sdram_bank_sizes[])
393 {
394     ram_addr_t size_left = memory_region_size(ram);
395     ram_addr_t base = 0;
396     ram_addr_t bank_size;
397     int i;
398     int j;
399 
400     for (i = 0; i < nr_banks; i++) {
401         for (j = 0; sdram_bank_sizes[j] != 0; j++) {
402             bank_size = sdram_bank_sizes[j];
403             if (bank_size <= size_left) {
404                 char name[32];
405 
406                 ram_bases[i] = base;
407                 ram_sizes[i] = bank_size;
408                 base += bank_size;
409                 size_left -= bank_size;
410                 snprintf(name, sizeof(name), "ppc4xx.sdram%d", i);
411                 memory_region_init_alias(&ram_memories[i], NULL, name, ram,
412                                          ram_bases[i], ram_sizes[i]);
413                 break;
414             }
415         }
416         if (!size_left) {
417             /* No need to use the remaining banks. */
418             break;
419         }
420     }
421 
422     if (size_left) {
423         ram_addr_t used_size = memory_region_size(ram) - size_left;
424         GString *s = g_string_new(NULL);
425 
426         for (i = 0; sdram_bank_sizes[i]; i++) {
427             g_string_append_printf(s, "%" PRIi64 "%s",
428                                    sdram_bank_sizes[i] / MiB,
429                                    sdram_bank_sizes[i + 1] ? ", " : "");
430         }
431         error_report("at most %d bank%s of %s MiB each supported",
432                      nr_banks, nr_banks == 1 ? "" : "s", s->str);
433         error_printf("Possible valid RAM size: %" PRIi64 " MiB \n",
434             used_size ? used_size / MiB : sdram_bank_sizes[i - 1] / MiB);
435 
436         g_string_free(s, true);
437         exit(EXIT_FAILURE);
438     }
439 }
440 
441 /*****************************************************************************/
442 /* MAL */
443 
444 enum {
445     MAL0_CFG      = 0x180,
446     MAL0_ESR      = 0x181,
447     MAL0_IER      = 0x182,
448     MAL0_TXCASR   = 0x184,
449     MAL0_TXCARR   = 0x185,
450     MAL0_TXEOBISR = 0x186,
451     MAL0_TXDEIR   = 0x187,
452     MAL0_RXCASR   = 0x190,
453     MAL0_RXCARR   = 0x191,
454     MAL0_RXEOBISR = 0x192,
455     MAL0_RXDEIR   = 0x193,
456     MAL0_TXCTP0R  = 0x1A0,
457     MAL0_RXCTP0R  = 0x1C0,
458     MAL0_RCBS0    = 0x1E0,
459     MAL0_RCBS1    = 0x1E1,
460 };
461 
462 typedef struct ppc4xx_mal_t ppc4xx_mal_t;
463 struct ppc4xx_mal_t {
464     qemu_irq irqs[4];
465     uint32_t cfg;
466     uint32_t esr;
467     uint32_t ier;
468     uint32_t txcasr;
469     uint32_t txcarr;
470     uint32_t txeobisr;
471     uint32_t txdeir;
472     uint32_t rxcasr;
473     uint32_t rxcarr;
474     uint32_t rxeobisr;
475     uint32_t rxdeir;
476     uint32_t *txctpr;
477     uint32_t *rxctpr;
478     uint32_t *rcbs;
479     uint8_t  txcnum;
480     uint8_t  rxcnum;
481 };
482 
483 static void ppc4xx_mal_reset(void *opaque)
484 {
485     ppc4xx_mal_t *mal;
486 
487     mal = opaque;
488     mal->cfg = 0x0007C000;
489     mal->esr = 0x00000000;
490     mal->ier = 0x00000000;
491     mal->rxcasr = 0x00000000;
492     mal->rxdeir = 0x00000000;
493     mal->rxeobisr = 0x00000000;
494     mal->txcasr = 0x00000000;
495     mal->txdeir = 0x00000000;
496     mal->txeobisr = 0x00000000;
497 }
498 
499 static uint32_t dcr_read_mal(void *opaque, int dcrn)
500 {
501     ppc4xx_mal_t *mal;
502     uint32_t ret;
503 
504     mal = opaque;
505     switch (dcrn) {
506     case MAL0_CFG:
507         ret = mal->cfg;
508         break;
509     case MAL0_ESR:
510         ret = mal->esr;
511         break;
512     case MAL0_IER:
513         ret = mal->ier;
514         break;
515     case MAL0_TXCASR:
516         ret = mal->txcasr;
517         break;
518     case MAL0_TXCARR:
519         ret = mal->txcarr;
520         break;
521     case MAL0_TXEOBISR:
522         ret = mal->txeobisr;
523         break;
524     case MAL0_TXDEIR:
525         ret = mal->txdeir;
526         break;
527     case MAL0_RXCASR:
528         ret = mal->rxcasr;
529         break;
530     case MAL0_RXCARR:
531         ret = mal->rxcarr;
532         break;
533     case MAL0_RXEOBISR:
534         ret = mal->rxeobisr;
535         break;
536     case MAL0_RXDEIR:
537         ret = mal->rxdeir;
538         break;
539     default:
540         ret = 0;
541         break;
542     }
543     if (dcrn >= MAL0_TXCTP0R && dcrn < MAL0_TXCTP0R + mal->txcnum) {
544         ret = mal->txctpr[dcrn - MAL0_TXCTP0R];
545     }
546     if (dcrn >= MAL0_RXCTP0R && dcrn < MAL0_RXCTP0R + mal->rxcnum) {
547         ret = mal->rxctpr[dcrn - MAL0_RXCTP0R];
548     }
549     if (dcrn >= MAL0_RCBS0 && dcrn < MAL0_RCBS0 + mal->rxcnum) {
550         ret = mal->rcbs[dcrn - MAL0_RCBS0];
551     }
552 
553     return ret;
554 }
555 
556 static void dcr_write_mal(void *opaque, int dcrn, uint32_t val)
557 {
558     ppc4xx_mal_t *mal;
559 
560     mal = opaque;
561     switch (dcrn) {
562     case MAL0_CFG:
563         if (val & 0x80000000) {
564             ppc4xx_mal_reset(mal);
565         }
566         mal->cfg = val & 0x00FFC087;
567         break;
568     case MAL0_ESR:
569         /* Read/clear */
570         mal->esr &= ~val;
571         break;
572     case MAL0_IER:
573         mal->ier = val & 0x0000001F;
574         break;
575     case MAL0_TXCASR:
576         mal->txcasr = val & 0xF0000000;
577         break;
578     case MAL0_TXCARR:
579         mal->txcarr = val & 0xF0000000;
580         break;
581     case MAL0_TXEOBISR:
582         /* Read/clear */
583         mal->txeobisr &= ~val;
584         break;
585     case MAL0_TXDEIR:
586         /* Read/clear */
587         mal->txdeir &= ~val;
588         break;
589     case MAL0_RXCASR:
590         mal->rxcasr = val & 0xC0000000;
591         break;
592     case MAL0_RXCARR:
593         mal->rxcarr = val & 0xC0000000;
594         break;
595     case MAL0_RXEOBISR:
596         /* Read/clear */
597         mal->rxeobisr &= ~val;
598         break;
599     case MAL0_RXDEIR:
600         /* Read/clear */
601         mal->rxdeir &= ~val;
602         break;
603     }
604     if (dcrn >= MAL0_TXCTP0R && dcrn < MAL0_TXCTP0R + mal->txcnum) {
605         mal->txctpr[dcrn - MAL0_TXCTP0R] = val;
606     }
607     if (dcrn >= MAL0_RXCTP0R && dcrn < MAL0_RXCTP0R + mal->rxcnum) {
608         mal->rxctpr[dcrn - MAL0_RXCTP0R] = val;
609     }
610     if (dcrn >= MAL0_RCBS0 && dcrn < MAL0_RCBS0 + mal->rxcnum) {
611         mal->rcbs[dcrn - MAL0_RCBS0] = val & 0x000000FF;
612     }
613 }
614 
615 void ppc4xx_mal_init(CPUPPCState *env, uint8_t txcnum, uint8_t rxcnum,
616                      qemu_irq irqs[4])
617 {
618     ppc4xx_mal_t *mal;
619     int i;
620 
621     assert(txcnum <= 32 && rxcnum <= 32);
622     mal = g_malloc0(sizeof(*mal));
623     mal->txcnum = txcnum;
624     mal->rxcnum = rxcnum;
625     mal->txctpr = g_new0(uint32_t, txcnum);
626     mal->rxctpr = g_new0(uint32_t, rxcnum);
627     mal->rcbs = g_new0(uint32_t, rxcnum);
628     for (i = 0; i < 4; i++) {
629         mal->irqs[i] = irqs[i];
630     }
631     qemu_register_reset(&ppc4xx_mal_reset, mal);
632     ppc_dcr_register(env, MAL0_CFG,
633                      mal, &dcr_read_mal, &dcr_write_mal);
634     ppc_dcr_register(env, MAL0_ESR,
635                      mal, &dcr_read_mal, &dcr_write_mal);
636     ppc_dcr_register(env, MAL0_IER,
637                      mal, &dcr_read_mal, &dcr_write_mal);
638     ppc_dcr_register(env, MAL0_TXCASR,
639                      mal, &dcr_read_mal, &dcr_write_mal);
640     ppc_dcr_register(env, MAL0_TXCARR,
641                      mal, &dcr_read_mal, &dcr_write_mal);
642     ppc_dcr_register(env, MAL0_TXEOBISR,
643                      mal, &dcr_read_mal, &dcr_write_mal);
644     ppc_dcr_register(env, MAL0_TXDEIR,
645                      mal, &dcr_read_mal, &dcr_write_mal);
646     ppc_dcr_register(env, MAL0_RXCASR,
647                      mal, &dcr_read_mal, &dcr_write_mal);
648     ppc_dcr_register(env, MAL0_RXCARR,
649                      mal, &dcr_read_mal, &dcr_write_mal);
650     ppc_dcr_register(env, MAL0_RXEOBISR,
651                      mal, &dcr_read_mal, &dcr_write_mal);
652     ppc_dcr_register(env, MAL0_RXDEIR,
653                      mal, &dcr_read_mal, &dcr_write_mal);
654     for (i = 0; i < txcnum; i++) {
655         ppc_dcr_register(env, MAL0_TXCTP0R + i,
656                          mal, &dcr_read_mal, &dcr_write_mal);
657     }
658     for (i = 0; i < rxcnum; i++) {
659         ppc_dcr_register(env, MAL0_RXCTP0R + i,
660                          mal, &dcr_read_mal, &dcr_write_mal);
661     }
662     for (i = 0; i < rxcnum; i++) {
663         ppc_dcr_register(env, MAL0_RCBS0 + i,
664                          mal, &dcr_read_mal, &dcr_write_mal);
665     }
666 }
667 
668 /* PPC4xx_DCR_DEVICE */
669 
670 void ppc4xx_dcr_register(Ppc4xxDcrDeviceState *dev, int dcrn, void *opaque,
671                          dcr_read_cb dcr_read, dcr_write_cb dcr_write)
672 {
673     assert(dev->cpu);
674     ppc_dcr_register(&dev->cpu->env, dcrn, opaque, dcr_read, dcr_write);
675 }
676 
677 bool ppc4xx_dcr_realize(Ppc4xxDcrDeviceState *dev, PowerPCCPU *cpu,
678                         Error **errp)
679 {
680     object_property_set_link(OBJECT(dev), "cpu", OBJECT(cpu), &error_abort);
681     return sysbus_realize(SYS_BUS_DEVICE(dev), errp);
682 }
683 
684 static Property ppc4xx_dcr_properties[] = {
685     DEFINE_PROP_LINK("cpu", Ppc4xxDcrDeviceState, cpu, TYPE_POWERPC_CPU,
686                      PowerPCCPU *),
687     DEFINE_PROP_END_OF_LIST(),
688 };
689 
690 static void ppc4xx_dcr_class_init(ObjectClass *oc, void *data)
691 {
692     DeviceClass *dc = DEVICE_CLASS(oc);
693 
694     device_class_set_props(dc, ppc4xx_dcr_properties);
695 }
696 
697 static const TypeInfo ppc4xx_types[] = {
698     {
699         .name           = TYPE_PPC4xx_DCR_DEVICE,
700         .parent         = TYPE_SYS_BUS_DEVICE,
701         .instance_size  = sizeof(Ppc4xxDcrDeviceState),
702         .class_init     = ppc4xx_dcr_class_init,
703         .abstract       = true,
704     }
705 };
706 
707 DEFINE_TYPES(ppc4xx_types)
708