xref: /qemu/hw/ppc/ppc4xx_devs.c (revision 70ce076fa6dff60585c229a4b641b13e64bf03cf)
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 "cpu.h"
27 #include "hw/ppc/ppc4xx.h"
28 #include "hw/qdev-properties.h"
29 #include "qapi/error.h"
30 
31 /*****************************************************************************/
32 /* MAL */
33 
34 enum {
35     MAL0_CFG      = 0x180,
36     MAL0_ESR      = 0x181,
37     MAL0_IER      = 0x182,
38     MAL0_TXCASR   = 0x184,
39     MAL0_TXCARR   = 0x185,
40     MAL0_TXEOBISR = 0x186,
41     MAL0_TXDEIR   = 0x187,
42     MAL0_RXCASR   = 0x190,
43     MAL0_RXCARR   = 0x191,
44     MAL0_RXEOBISR = 0x192,
45     MAL0_RXDEIR   = 0x193,
46     MAL0_TXCTP0R  = 0x1A0,
47     MAL0_RXCTP0R  = 0x1C0,
48     MAL0_RCBS0    = 0x1E0,
49     MAL0_RCBS1    = 0x1E1,
50 };
51 
52 static void ppc4xx_mal_reset(DeviceState *dev)
53 {
54     Ppc4xxMalState *mal = PPC4xx_MAL(dev);
55 
56     mal->cfg = 0x0007C000;
57     mal->esr = 0x00000000;
58     mal->ier = 0x00000000;
59     mal->rxcasr = 0x00000000;
60     mal->rxdeir = 0x00000000;
61     mal->rxeobisr = 0x00000000;
62     mal->txcasr = 0x00000000;
63     mal->txdeir = 0x00000000;
64     mal->txeobisr = 0x00000000;
65 }
66 
67 static uint32_t dcr_read_mal(void *opaque, int dcrn)
68 {
69     Ppc4xxMalState *mal = opaque;
70     uint32_t ret;
71 
72     switch (dcrn) {
73     case MAL0_CFG:
74         ret = mal->cfg;
75         break;
76     case MAL0_ESR:
77         ret = mal->esr;
78         break;
79     case MAL0_IER:
80         ret = mal->ier;
81         break;
82     case MAL0_TXCASR:
83         ret = mal->txcasr;
84         break;
85     case MAL0_TXCARR:
86         ret = mal->txcarr;
87         break;
88     case MAL0_TXEOBISR:
89         ret = mal->txeobisr;
90         break;
91     case MAL0_TXDEIR:
92         ret = mal->txdeir;
93         break;
94     case MAL0_RXCASR:
95         ret = mal->rxcasr;
96         break;
97     case MAL0_RXCARR:
98         ret = mal->rxcarr;
99         break;
100     case MAL0_RXEOBISR:
101         ret = mal->rxeobisr;
102         break;
103     case MAL0_RXDEIR:
104         ret = mal->rxdeir;
105         break;
106     default:
107         ret = 0;
108         break;
109     }
110     if (dcrn >= MAL0_TXCTP0R && dcrn < MAL0_TXCTP0R + mal->txcnum) {
111         ret = mal->txctpr[dcrn - MAL0_TXCTP0R];
112     }
113     if (dcrn >= MAL0_RXCTP0R && dcrn < MAL0_RXCTP0R + mal->rxcnum) {
114         ret = mal->rxctpr[dcrn - MAL0_RXCTP0R];
115     }
116     if (dcrn >= MAL0_RCBS0 && dcrn < MAL0_RCBS0 + mal->rxcnum) {
117         ret = mal->rcbs[dcrn - MAL0_RCBS0];
118     }
119 
120     return ret;
121 }
122 
123 static void dcr_write_mal(void *opaque, int dcrn, uint32_t val)
124 {
125     Ppc4xxMalState *mal = opaque;
126 
127     switch (dcrn) {
128     case MAL0_CFG:
129         if (val & 0x80000000) {
130             ppc4xx_mal_reset(DEVICE(mal));
131         }
132         mal->cfg = val & 0x00FFC087;
133         break;
134     case MAL0_ESR:
135         /* Read/clear */
136         mal->esr &= ~val;
137         break;
138     case MAL0_IER:
139         mal->ier = val & 0x0000001F;
140         break;
141     case MAL0_TXCASR:
142         mal->txcasr = val & 0xF0000000;
143         break;
144     case MAL0_TXCARR:
145         mal->txcarr = val & 0xF0000000;
146         break;
147     case MAL0_TXEOBISR:
148         /* Read/clear */
149         mal->txeobisr &= ~val;
150         break;
151     case MAL0_TXDEIR:
152         /* Read/clear */
153         mal->txdeir &= ~val;
154         break;
155     case MAL0_RXCASR:
156         mal->rxcasr = val & 0xC0000000;
157         break;
158     case MAL0_RXCARR:
159         mal->rxcarr = val & 0xC0000000;
160         break;
161     case MAL0_RXEOBISR:
162         /* Read/clear */
163         mal->rxeobisr &= ~val;
164         break;
165     case MAL0_RXDEIR:
166         /* Read/clear */
167         mal->rxdeir &= ~val;
168         break;
169     }
170     if (dcrn >= MAL0_TXCTP0R && dcrn < MAL0_TXCTP0R + mal->txcnum) {
171         mal->txctpr[dcrn - MAL0_TXCTP0R] = val;
172     }
173     if (dcrn >= MAL0_RXCTP0R && dcrn < MAL0_RXCTP0R + mal->rxcnum) {
174         mal->rxctpr[dcrn - MAL0_RXCTP0R] = val;
175     }
176     if (dcrn >= MAL0_RCBS0 && dcrn < MAL0_RCBS0 + mal->rxcnum) {
177         mal->rcbs[dcrn - MAL0_RCBS0] = val & 0x000000FF;
178     }
179 }
180 
181 static void ppc4xx_mal_realize(DeviceState *dev, Error **errp)
182 {
183     Ppc4xxMalState *mal = PPC4xx_MAL(dev);
184     Ppc4xxDcrDeviceState *dcr = PPC4xx_DCR_DEVICE(dev);
185     int i;
186 
187     if (mal->txcnum > 32 || mal->rxcnum > 32) {
188         error_setg(errp, "invalid TXC/RXC number");
189         return;
190     }
191 
192     mal->txctpr = g_new0(uint32_t, mal->txcnum);
193     mal->rxctpr = g_new0(uint32_t, mal->rxcnum);
194     mal->rcbs = g_new0(uint32_t, mal->rxcnum);
195 
196     for (i = 0; i < ARRAY_SIZE(mal->irqs); i++) {
197         sysbus_init_irq(SYS_BUS_DEVICE(dev), &mal->irqs[i]);
198     }
199 
200     ppc4xx_dcr_register(dcr, MAL0_CFG, mal, &dcr_read_mal, &dcr_write_mal);
201     ppc4xx_dcr_register(dcr, MAL0_ESR, mal, &dcr_read_mal, &dcr_write_mal);
202     ppc4xx_dcr_register(dcr, MAL0_IER, mal, &dcr_read_mal, &dcr_write_mal);
203     ppc4xx_dcr_register(dcr, MAL0_TXCASR, mal, &dcr_read_mal, &dcr_write_mal);
204     ppc4xx_dcr_register(dcr, MAL0_TXCARR, mal, &dcr_read_mal, &dcr_write_mal);
205     ppc4xx_dcr_register(dcr, MAL0_TXEOBISR, mal, &dcr_read_mal, &dcr_write_mal);
206     ppc4xx_dcr_register(dcr, MAL0_TXDEIR, mal, &dcr_read_mal, &dcr_write_mal);
207     ppc4xx_dcr_register(dcr, MAL0_RXCASR, mal, &dcr_read_mal, &dcr_write_mal);
208     ppc4xx_dcr_register(dcr, MAL0_RXCARR, mal, &dcr_read_mal, &dcr_write_mal);
209     ppc4xx_dcr_register(dcr, MAL0_RXEOBISR, mal, &dcr_read_mal, &dcr_write_mal);
210     ppc4xx_dcr_register(dcr, MAL0_RXDEIR, mal, &dcr_read_mal, &dcr_write_mal);
211     for (i = 0; i < mal->txcnum; i++) {
212         ppc4xx_dcr_register(dcr, MAL0_TXCTP0R + i,
213                             mal, &dcr_read_mal, &dcr_write_mal);
214     }
215     for (i = 0; i < mal->rxcnum; i++) {
216         ppc4xx_dcr_register(dcr, MAL0_RXCTP0R + i,
217                             mal, &dcr_read_mal, &dcr_write_mal);
218     }
219     for (i = 0; i < mal->rxcnum; i++) {
220         ppc4xx_dcr_register(dcr, MAL0_RCBS0 + i,
221                             mal, &dcr_read_mal, &dcr_write_mal);
222     }
223 }
224 
225 static void ppc4xx_mal_finalize(Object *obj)
226 {
227     Ppc4xxMalState *mal = PPC4xx_MAL(obj);
228 
229     g_free(mal->rcbs);
230     g_free(mal->rxctpr);
231     g_free(mal->txctpr);
232 }
233 
234 static const Property ppc4xx_mal_properties[] = {
235     DEFINE_PROP_UINT8("txc-num", Ppc4xxMalState, txcnum, 0),
236     DEFINE_PROP_UINT8("rxc-num", Ppc4xxMalState, rxcnum, 0),
237 };
238 
239 static void ppc4xx_mal_class_init(ObjectClass *oc, void *data)
240 {
241     DeviceClass *dc = DEVICE_CLASS(oc);
242 
243     dc->realize = ppc4xx_mal_realize;
244     device_class_set_legacy_reset(dc, ppc4xx_mal_reset);
245     /* Reason: only works as function of a ppc4xx SoC */
246     dc->user_creatable = false;
247     device_class_set_props(dc, ppc4xx_mal_properties);
248 }
249 
250 /*****************************************************************************/
251 /* Peripheral local bus arbitrer */
252 enum {
253     PLB3A0_ACR = 0x077,
254     PLB4A0_ACR = 0x081,
255     PLB0_BESR  = 0x084,
256     PLB0_BEAR  = 0x086,
257     PLB0_ACR   = 0x087,
258     PLB4A1_ACR = 0x089,
259 };
260 
261 static uint32_t dcr_read_plb(void *opaque, int dcrn)
262 {
263     Ppc4xxPlbState *plb = opaque;
264     uint32_t ret;
265 
266     switch (dcrn) {
267     case PLB0_ACR:
268         ret = plb->acr;
269         break;
270     case PLB0_BEAR:
271         ret = plb->bear;
272         break;
273     case PLB0_BESR:
274         ret = plb->besr;
275         break;
276     default:
277         /* Avoid gcc warning */
278         ret = 0;
279         break;
280     }
281 
282     return ret;
283 }
284 
285 static void dcr_write_plb(void *opaque, int dcrn, uint32_t val)
286 {
287     Ppc4xxPlbState *plb = opaque;
288 
289     switch (dcrn) {
290     case PLB0_ACR:
291         /*
292          * We don't care about the actual parameters written as
293          * we don't manage any priorities on the bus
294          */
295         plb->acr = val & 0xF8000000;
296         break;
297     case PLB0_BEAR:
298         /* Read only */
299         break;
300     case PLB0_BESR:
301         /* Write-clear */
302         plb->besr &= ~val;
303         break;
304     }
305 }
306 
307 static void ppc405_plb_reset(DeviceState *dev)
308 {
309     Ppc4xxPlbState *plb = PPC4xx_PLB(dev);
310 
311     plb->acr = 0x00000000;
312     plb->bear = 0x00000000;
313     plb->besr = 0x00000000;
314 }
315 
316 static void ppc405_plb_realize(DeviceState *dev, Error **errp)
317 {
318     Ppc4xxPlbState *plb = PPC4xx_PLB(dev);
319     Ppc4xxDcrDeviceState *dcr = PPC4xx_DCR_DEVICE(dev);
320 
321     ppc4xx_dcr_register(dcr, PLB3A0_ACR, plb, &dcr_read_plb, &dcr_write_plb);
322     ppc4xx_dcr_register(dcr, PLB4A0_ACR, plb, &dcr_read_plb, &dcr_write_plb);
323     ppc4xx_dcr_register(dcr, PLB0_ACR, plb, &dcr_read_plb, &dcr_write_plb);
324     ppc4xx_dcr_register(dcr, PLB0_BEAR, plb, &dcr_read_plb, &dcr_write_plb);
325     ppc4xx_dcr_register(dcr, PLB0_BESR, plb, &dcr_read_plb, &dcr_write_plb);
326     ppc4xx_dcr_register(dcr, PLB4A1_ACR, plb, &dcr_read_plb, &dcr_write_plb);
327 }
328 
329 static void ppc405_plb_class_init(ObjectClass *oc, void *data)
330 {
331     DeviceClass *dc = DEVICE_CLASS(oc);
332 
333     dc->realize = ppc405_plb_realize;
334     device_class_set_legacy_reset(dc, ppc405_plb_reset);
335     /* Reason: only works as function of a ppc4xx SoC */
336     dc->user_creatable = false;
337 }
338 
339 /*****************************************************************************/
340 /* Peripheral controller */
341 enum {
342     EBC0_CFGADDR = 0x012,
343     EBC0_CFGDATA = 0x013,
344 };
345 
346 static uint32_t dcr_read_ebc(void *opaque, int dcrn)
347 {
348     Ppc4xxEbcState *ebc = opaque;
349     uint32_t ret;
350 
351     switch (dcrn) {
352     case EBC0_CFGADDR:
353         ret = ebc->addr;
354         break;
355     case EBC0_CFGDATA:
356         switch (ebc->addr) {
357         case 0x00: /* B0CR */
358             ret = ebc->bcr[0];
359             break;
360         case 0x01: /* B1CR */
361             ret = ebc->bcr[1];
362             break;
363         case 0x02: /* B2CR */
364             ret = ebc->bcr[2];
365             break;
366         case 0x03: /* B3CR */
367             ret = ebc->bcr[3];
368             break;
369         case 0x04: /* B4CR */
370             ret = ebc->bcr[4];
371             break;
372         case 0x05: /* B5CR */
373             ret = ebc->bcr[5];
374             break;
375         case 0x06: /* B6CR */
376             ret = ebc->bcr[6];
377             break;
378         case 0x07: /* B7CR */
379             ret = ebc->bcr[7];
380             break;
381         case 0x10: /* B0AP */
382             ret = ebc->bap[0];
383             break;
384         case 0x11: /* B1AP */
385             ret = ebc->bap[1];
386             break;
387         case 0x12: /* B2AP */
388             ret = ebc->bap[2];
389             break;
390         case 0x13: /* B3AP */
391             ret = ebc->bap[3];
392             break;
393         case 0x14: /* B4AP */
394             ret = ebc->bap[4];
395             break;
396         case 0x15: /* B5AP */
397             ret = ebc->bap[5];
398             break;
399         case 0x16: /* B6AP */
400             ret = ebc->bap[6];
401             break;
402         case 0x17: /* B7AP */
403             ret = ebc->bap[7];
404             break;
405         case 0x20: /* BEAR */
406             ret = ebc->bear;
407             break;
408         case 0x21: /* BESR0 */
409             ret = ebc->besr0;
410             break;
411         case 0x22: /* BESR1 */
412             ret = ebc->besr1;
413             break;
414         case 0x23: /* CFG */
415             ret = ebc->cfg;
416             break;
417         default:
418             ret = 0x00000000;
419             break;
420         }
421         break;
422     default:
423         ret = 0x00000000;
424         break;
425     }
426 
427     return ret;
428 }
429 
430 static void dcr_write_ebc(void *opaque, int dcrn, uint32_t val)
431 {
432     Ppc4xxEbcState *ebc = opaque;
433 
434     switch (dcrn) {
435     case EBC0_CFGADDR:
436         ebc->addr = val;
437         break;
438     case EBC0_CFGDATA:
439         switch (ebc->addr) {
440         case 0x00: /* B0CR */
441             break;
442         case 0x01: /* B1CR */
443             break;
444         case 0x02: /* B2CR */
445             break;
446         case 0x03: /* B3CR */
447             break;
448         case 0x04: /* B4CR */
449             break;
450         case 0x05: /* B5CR */
451             break;
452         case 0x06: /* B6CR */
453             break;
454         case 0x07: /* B7CR */
455             break;
456         case 0x10: /* B0AP */
457             break;
458         case 0x11: /* B1AP */
459             break;
460         case 0x12: /* B2AP */
461             break;
462         case 0x13: /* B3AP */
463             break;
464         case 0x14: /* B4AP */
465             break;
466         case 0x15: /* B5AP */
467             break;
468         case 0x16: /* B6AP */
469             break;
470         case 0x17: /* B7AP */
471             break;
472         case 0x20: /* BEAR */
473             break;
474         case 0x21: /* BESR0 */
475             break;
476         case 0x22: /* BESR1 */
477             break;
478         case 0x23: /* CFG */
479             break;
480         default:
481             break;
482         }
483         break;
484     default:
485         break;
486     }
487 }
488 
489 static void ppc405_ebc_reset(DeviceState *dev)
490 {
491     Ppc4xxEbcState *ebc = PPC4xx_EBC(dev);
492     int i;
493 
494     ebc->addr = 0x00000000;
495     ebc->bap[0] = 0x7F8FFE80;
496     ebc->bcr[0] = 0xFFE28000;
497     for (i = 0; i < 8; i++) {
498         ebc->bap[i] = 0x00000000;
499         ebc->bcr[i] = 0x00000000;
500     }
501     ebc->besr0 = 0x00000000;
502     ebc->besr1 = 0x00000000;
503     ebc->cfg = 0x80400000;
504 }
505 
506 static void ppc405_ebc_realize(DeviceState *dev, Error **errp)
507 {
508     Ppc4xxEbcState *ebc = PPC4xx_EBC(dev);
509     Ppc4xxDcrDeviceState *dcr = PPC4xx_DCR_DEVICE(dev);
510 
511     ppc4xx_dcr_register(dcr, EBC0_CFGADDR, ebc, &dcr_read_ebc, &dcr_write_ebc);
512     ppc4xx_dcr_register(dcr, EBC0_CFGDATA, ebc, &dcr_read_ebc, &dcr_write_ebc);
513 }
514 
515 static void ppc405_ebc_class_init(ObjectClass *oc, void *data)
516 {
517     DeviceClass *dc = DEVICE_CLASS(oc);
518 
519     dc->realize = ppc405_ebc_realize;
520     device_class_set_legacy_reset(dc, ppc405_ebc_reset);
521     /* Reason: only works as function of a ppc4xx SoC */
522     dc->user_creatable = false;
523 }
524 
525 /* PPC4xx_DCR_DEVICE */
526 
527 void ppc4xx_dcr_register(Ppc4xxDcrDeviceState *dev, int dcrn, void *opaque,
528                          dcr_read_cb dcr_read, dcr_write_cb dcr_write)
529 {
530     assert(dev->cpu);
531     ppc_dcr_register(&dev->cpu->env, dcrn, opaque, dcr_read, dcr_write);
532 }
533 
534 bool ppc4xx_dcr_realize(Ppc4xxDcrDeviceState *dev, PowerPCCPU *cpu,
535                         Error **errp)
536 {
537     object_property_set_link(OBJECT(dev), "cpu", OBJECT(cpu), &error_abort);
538     return sysbus_realize(SYS_BUS_DEVICE(dev), errp);
539 }
540 
541 static const Property ppc4xx_dcr_properties[] = {
542     DEFINE_PROP_LINK("cpu", Ppc4xxDcrDeviceState, cpu, TYPE_POWERPC_CPU,
543                      PowerPCCPU *),
544 };
545 
546 static void ppc4xx_dcr_class_init(ObjectClass *oc, void *data)
547 {
548     DeviceClass *dc = DEVICE_CLASS(oc);
549 
550     device_class_set_props(dc, ppc4xx_dcr_properties);
551 }
552 
553 static const TypeInfo ppc4xx_types[] = {
554     {
555         .name           = TYPE_PPC4xx_MAL,
556         .parent         = TYPE_PPC4xx_DCR_DEVICE,
557         .instance_size  = sizeof(Ppc4xxMalState),
558         .instance_finalize = ppc4xx_mal_finalize,
559         .class_init     = ppc4xx_mal_class_init,
560     }, {
561         .name           = TYPE_PPC4xx_PLB,
562         .parent         = TYPE_PPC4xx_DCR_DEVICE,
563         .instance_size  = sizeof(Ppc4xxPlbState),
564         .class_init     = ppc405_plb_class_init,
565     }, {
566         .name           = TYPE_PPC4xx_EBC,
567         .parent         = TYPE_PPC4xx_DCR_DEVICE,
568         .instance_size  = sizeof(Ppc4xxEbcState),
569         .class_init     = ppc405_ebc_class_init,
570     }, {
571         .name           = TYPE_PPC4xx_DCR_DEVICE,
572         .parent         = TYPE_SYS_BUS_DEVICE,
573         .instance_size  = sizeof(Ppc4xxDcrDeviceState),
574         .class_init     = ppc4xx_dcr_class_init,
575         .abstract       = true,
576     }
577 };
578 
579 DEFINE_TYPES(ppc4xx_types)
580