xref: /qemu/hw/ppc/ppc4xx_devs.c (revision 90f5755e8a6a791fa67fa860a947770326b54961)
1008ff9d7Sj_mayer /*
2008ff9d7Sj_mayer  * QEMU PowerPC 4xx embedded processors shared devices emulation
3008ff9d7Sj_mayer  *
4008ff9d7Sj_mayer  * Copyright (c) 2007 Jocelyn Mayer
5008ff9d7Sj_mayer  *
6008ff9d7Sj_mayer  * Permission is hereby granted, free of charge, to any person obtaining a copy
7008ff9d7Sj_mayer  * of this software and associated documentation files (the "Software"), to deal
8008ff9d7Sj_mayer  * in the Software without restriction, including without limitation the rights
9008ff9d7Sj_mayer  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10008ff9d7Sj_mayer  * copies of the Software, and to permit persons to whom the Software is
11008ff9d7Sj_mayer  * furnished to do so, subject to the following conditions:
12008ff9d7Sj_mayer  *
13008ff9d7Sj_mayer  * The above copyright notice and this permission notice shall be included in
14008ff9d7Sj_mayer  * all copies or substantial portions of the Software.
15008ff9d7Sj_mayer  *
16008ff9d7Sj_mayer  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17008ff9d7Sj_mayer  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18008ff9d7Sj_mayer  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19008ff9d7Sj_mayer  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20008ff9d7Sj_mayer  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21008ff9d7Sj_mayer  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22008ff9d7Sj_mayer  * THE SOFTWARE.
23008ff9d7Sj_mayer  */
2471e8a915SMarkus Armbruster 
250d75590dSPeter Maydell #include "qemu/osdep.h"
2633c11879SPaolo Bonzini #include "cpu.h"
270d09e41aSPaolo Bonzini #include "hw/ppc/ppc4xx.h"
2834d0831fSPeter Maydell #include "hw/qdev-properties.h"
2934d0831fSPeter Maydell #include "qapi/error.h"
30b7da58fdSaurel32 
31517284a7SBALATON Zoltan /*****************************************************************************/
32517284a7SBALATON Zoltan /* MAL */
3304534280SBALATON Zoltan 
34517284a7SBALATON Zoltan enum {
35517284a7SBALATON Zoltan     MAL0_CFG      = 0x180,
36517284a7SBALATON Zoltan     MAL0_ESR      = 0x181,
37517284a7SBALATON Zoltan     MAL0_IER      = 0x182,
38517284a7SBALATON Zoltan     MAL0_TXCASR   = 0x184,
39517284a7SBALATON Zoltan     MAL0_TXCARR   = 0x185,
40517284a7SBALATON Zoltan     MAL0_TXEOBISR = 0x186,
41517284a7SBALATON Zoltan     MAL0_TXDEIR   = 0x187,
42517284a7SBALATON Zoltan     MAL0_RXCASR   = 0x190,
43517284a7SBALATON Zoltan     MAL0_RXCARR   = 0x191,
44517284a7SBALATON Zoltan     MAL0_RXEOBISR = 0x192,
45517284a7SBALATON Zoltan     MAL0_RXDEIR   = 0x193,
46517284a7SBALATON Zoltan     MAL0_TXCTP0R  = 0x1A0,
47517284a7SBALATON Zoltan     MAL0_RXCTP0R  = 0x1C0,
48517284a7SBALATON Zoltan     MAL0_RCBS0    = 0x1E0,
49517284a7SBALATON Zoltan     MAL0_RCBS1    = 0x1E1,
50517284a7SBALATON Zoltan };
51517284a7SBALATON Zoltan 
52da116a8aSCédric Le Goater static void ppc4xx_mal_reset(DeviceState *dev)
5304534280SBALATON Zoltan {
54da116a8aSCédric Le Goater     Ppc4xxMalState *mal = PPC4xx_MAL(dev);
5504534280SBALATON Zoltan 
5604534280SBALATON Zoltan     mal->cfg = 0x0007C000;
5704534280SBALATON Zoltan     mal->esr = 0x00000000;
5804534280SBALATON Zoltan     mal->ier = 0x00000000;
5904534280SBALATON Zoltan     mal->rxcasr = 0x00000000;
6004534280SBALATON Zoltan     mal->rxdeir = 0x00000000;
6104534280SBALATON Zoltan     mal->rxeobisr = 0x00000000;
6204534280SBALATON Zoltan     mal->txcasr = 0x00000000;
6304534280SBALATON Zoltan     mal->txdeir = 0x00000000;
6404534280SBALATON Zoltan     mal->txeobisr = 0x00000000;
6504534280SBALATON Zoltan }
66517284a7SBALATON Zoltan 
67517284a7SBALATON Zoltan static uint32_t dcr_read_mal(void *opaque, int dcrn)
68517284a7SBALATON Zoltan {
69da116a8aSCédric Le Goater     Ppc4xxMalState *mal = opaque;
70517284a7SBALATON Zoltan     uint32_t ret;
71517284a7SBALATON Zoltan 
72517284a7SBALATON Zoltan     switch (dcrn) {
73517284a7SBALATON Zoltan     case MAL0_CFG:
74517284a7SBALATON Zoltan         ret = mal->cfg;
75517284a7SBALATON Zoltan         break;
76517284a7SBALATON Zoltan     case MAL0_ESR:
77517284a7SBALATON Zoltan         ret = mal->esr;
78517284a7SBALATON Zoltan         break;
79517284a7SBALATON Zoltan     case MAL0_IER:
80517284a7SBALATON Zoltan         ret = mal->ier;
81517284a7SBALATON Zoltan         break;
82517284a7SBALATON Zoltan     case MAL0_TXCASR:
83517284a7SBALATON Zoltan         ret = mal->txcasr;
84517284a7SBALATON Zoltan         break;
85517284a7SBALATON Zoltan     case MAL0_TXCARR:
86517284a7SBALATON Zoltan         ret = mal->txcarr;
87517284a7SBALATON Zoltan         break;
88517284a7SBALATON Zoltan     case MAL0_TXEOBISR:
89517284a7SBALATON Zoltan         ret = mal->txeobisr;
90517284a7SBALATON Zoltan         break;
91517284a7SBALATON Zoltan     case MAL0_TXDEIR:
92517284a7SBALATON Zoltan         ret = mal->txdeir;
93517284a7SBALATON Zoltan         break;
94517284a7SBALATON Zoltan     case MAL0_RXCASR:
95517284a7SBALATON Zoltan         ret = mal->rxcasr;
96517284a7SBALATON Zoltan         break;
97517284a7SBALATON Zoltan     case MAL0_RXCARR:
98517284a7SBALATON Zoltan         ret = mal->rxcarr;
99517284a7SBALATON Zoltan         break;
100517284a7SBALATON Zoltan     case MAL0_RXEOBISR:
101517284a7SBALATON Zoltan         ret = mal->rxeobisr;
102517284a7SBALATON Zoltan         break;
103517284a7SBALATON Zoltan     case MAL0_RXDEIR:
104517284a7SBALATON Zoltan         ret = mal->rxdeir;
105517284a7SBALATON Zoltan         break;
106517284a7SBALATON Zoltan     default:
107517284a7SBALATON Zoltan         ret = 0;
108517284a7SBALATON Zoltan         break;
109517284a7SBALATON Zoltan     }
11004534280SBALATON Zoltan     if (dcrn >= MAL0_TXCTP0R && dcrn < MAL0_TXCTP0R + mal->txcnum) {
11104534280SBALATON Zoltan         ret = mal->txctpr[dcrn - MAL0_TXCTP0R];
11204534280SBALATON Zoltan     }
11304534280SBALATON Zoltan     if (dcrn >= MAL0_RXCTP0R && dcrn < MAL0_RXCTP0R + mal->rxcnum) {
11404534280SBALATON Zoltan         ret = mal->rxctpr[dcrn - MAL0_RXCTP0R];
11504534280SBALATON Zoltan     }
11604534280SBALATON Zoltan     if (dcrn >= MAL0_RCBS0 && dcrn < MAL0_RCBS0 + mal->rxcnum) {
11704534280SBALATON Zoltan         ret = mal->rcbs[dcrn - MAL0_RCBS0];
11804534280SBALATON Zoltan     }
119517284a7SBALATON Zoltan 
120517284a7SBALATON Zoltan     return ret;
121517284a7SBALATON Zoltan }
122517284a7SBALATON Zoltan 
123517284a7SBALATON Zoltan static void dcr_write_mal(void *opaque, int dcrn, uint32_t val)
124517284a7SBALATON Zoltan {
125da116a8aSCédric Le Goater     Ppc4xxMalState *mal = opaque;
126517284a7SBALATON Zoltan 
127517284a7SBALATON Zoltan     switch (dcrn) {
128517284a7SBALATON Zoltan     case MAL0_CFG:
129517284a7SBALATON Zoltan         if (val & 0x80000000) {
130da116a8aSCédric Le Goater             ppc4xx_mal_reset(DEVICE(mal));
131517284a7SBALATON Zoltan         }
132517284a7SBALATON Zoltan         mal->cfg = val & 0x00FFC087;
133517284a7SBALATON Zoltan         break;
134517284a7SBALATON Zoltan     case MAL0_ESR:
135517284a7SBALATON Zoltan         /* Read/clear */
136517284a7SBALATON Zoltan         mal->esr &= ~val;
137517284a7SBALATON Zoltan         break;
138517284a7SBALATON Zoltan     case MAL0_IER:
139517284a7SBALATON Zoltan         mal->ier = val & 0x0000001F;
140517284a7SBALATON Zoltan         break;
141517284a7SBALATON Zoltan     case MAL0_TXCASR:
142517284a7SBALATON Zoltan         mal->txcasr = val & 0xF0000000;
143517284a7SBALATON Zoltan         break;
144517284a7SBALATON Zoltan     case MAL0_TXCARR:
145517284a7SBALATON Zoltan         mal->txcarr = val & 0xF0000000;
146517284a7SBALATON Zoltan         break;
147517284a7SBALATON Zoltan     case MAL0_TXEOBISR:
148517284a7SBALATON Zoltan         /* Read/clear */
149517284a7SBALATON Zoltan         mal->txeobisr &= ~val;
150517284a7SBALATON Zoltan         break;
151517284a7SBALATON Zoltan     case MAL0_TXDEIR:
152517284a7SBALATON Zoltan         /* Read/clear */
153517284a7SBALATON Zoltan         mal->txdeir &= ~val;
154517284a7SBALATON Zoltan         break;
155517284a7SBALATON Zoltan     case MAL0_RXCASR:
156517284a7SBALATON Zoltan         mal->rxcasr = val & 0xC0000000;
157517284a7SBALATON Zoltan         break;
158517284a7SBALATON Zoltan     case MAL0_RXCARR:
159517284a7SBALATON Zoltan         mal->rxcarr = val & 0xC0000000;
160517284a7SBALATON Zoltan         break;
161517284a7SBALATON Zoltan     case MAL0_RXEOBISR:
162517284a7SBALATON Zoltan         /* Read/clear */
163517284a7SBALATON Zoltan         mal->rxeobisr &= ~val;
164517284a7SBALATON Zoltan         break;
165517284a7SBALATON Zoltan     case MAL0_RXDEIR:
166517284a7SBALATON Zoltan         /* Read/clear */
167517284a7SBALATON Zoltan         mal->rxdeir &= ~val;
168517284a7SBALATON Zoltan         break;
16904534280SBALATON Zoltan     }
17004534280SBALATON Zoltan     if (dcrn >= MAL0_TXCTP0R && dcrn < MAL0_TXCTP0R + mal->txcnum) {
17104534280SBALATON Zoltan         mal->txctpr[dcrn - MAL0_TXCTP0R] = val;
17204534280SBALATON Zoltan     }
17304534280SBALATON Zoltan     if (dcrn >= MAL0_RXCTP0R && dcrn < MAL0_RXCTP0R + mal->rxcnum) {
17404534280SBALATON Zoltan         mal->rxctpr[dcrn - MAL0_RXCTP0R] = val;
17504534280SBALATON Zoltan     }
17604534280SBALATON Zoltan     if (dcrn >= MAL0_RCBS0 && dcrn < MAL0_RCBS0 + mal->rxcnum) {
17704534280SBALATON Zoltan         mal->rcbs[dcrn - MAL0_RCBS0] = val & 0x000000FF;
178517284a7SBALATON Zoltan     }
179517284a7SBALATON Zoltan }
180517284a7SBALATON Zoltan 
181da116a8aSCédric Le Goater static void ppc4xx_mal_realize(DeviceState *dev, Error **errp)
182517284a7SBALATON Zoltan {
183da116a8aSCédric Le Goater     Ppc4xxMalState *mal = PPC4xx_MAL(dev);
184da116a8aSCédric Le Goater     Ppc4xxDcrDeviceState *dcr = PPC4xx_DCR_DEVICE(dev);
185517284a7SBALATON Zoltan     int i;
186517284a7SBALATON Zoltan 
187da116a8aSCédric Le Goater     if (mal->txcnum > 32 || mal->rxcnum > 32) {
188da116a8aSCédric Le Goater         error_setg(errp, "invalid TXC/RXC number");
189da116a8aSCédric Le Goater         return;
190517284a7SBALATON Zoltan     }
191da116a8aSCédric Le Goater 
192da116a8aSCédric Le Goater     mal->txctpr = g_new0(uint32_t, mal->txcnum);
193da116a8aSCédric Le Goater     mal->rxctpr = g_new0(uint32_t, mal->rxcnum);
194da116a8aSCédric Le Goater     mal->rcbs = g_new0(uint32_t, mal->rxcnum);
195da116a8aSCédric Le Goater 
196da116a8aSCédric Le Goater     for (i = 0; i < ARRAY_SIZE(mal->irqs); i++) {
197da116a8aSCédric Le Goater         sysbus_init_irq(SYS_BUS_DEVICE(dev), &mal->irqs[i]);
198da116a8aSCédric Le Goater     }
199da116a8aSCédric Le Goater 
200da116a8aSCédric Le Goater     ppc4xx_dcr_register(dcr, MAL0_CFG, mal, &dcr_read_mal, &dcr_write_mal);
201da116a8aSCédric Le Goater     ppc4xx_dcr_register(dcr, MAL0_ESR, mal, &dcr_read_mal, &dcr_write_mal);
202da116a8aSCédric Le Goater     ppc4xx_dcr_register(dcr, MAL0_IER, mal, &dcr_read_mal, &dcr_write_mal);
203da116a8aSCédric Le Goater     ppc4xx_dcr_register(dcr, MAL0_TXCASR, mal, &dcr_read_mal, &dcr_write_mal);
204da116a8aSCédric Le Goater     ppc4xx_dcr_register(dcr, MAL0_TXCARR, mal, &dcr_read_mal, &dcr_write_mal);
205da116a8aSCédric Le Goater     ppc4xx_dcr_register(dcr, MAL0_TXEOBISR, mal, &dcr_read_mal, &dcr_write_mal);
206da116a8aSCédric Le Goater     ppc4xx_dcr_register(dcr, MAL0_TXDEIR, mal, &dcr_read_mal, &dcr_write_mal);
207da116a8aSCédric Le Goater     ppc4xx_dcr_register(dcr, MAL0_RXCASR, mal, &dcr_read_mal, &dcr_write_mal);
208da116a8aSCédric Le Goater     ppc4xx_dcr_register(dcr, MAL0_RXCARR, mal, &dcr_read_mal, &dcr_write_mal);
209da116a8aSCédric Le Goater     ppc4xx_dcr_register(dcr, MAL0_RXEOBISR, mal, &dcr_read_mal, &dcr_write_mal);
210da116a8aSCédric Le Goater     ppc4xx_dcr_register(dcr, MAL0_RXDEIR, mal, &dcr_read_mal, &dcr_write_mal);
211da116a8aSCédric Le Goater     for (i = 0; i < mal->txcnum; i++) {
212da116a8aSCédric Le Goater         ppc4xx_dcr_register(dcr, MAL0_TXCTP0R + i,
213517284a7SBALATON Zoltan                             mal, &dcr_read_mal, &dcr_write_mal);
21404534280SBALATON Zoltan     }
215da116a8aSCédric Le Goater     for (i = 0; i < mal->rxcnum; i++) {
216da116a8aSCédric Le Goater         ppc4xx_dcr_register(dcr, MAL0_RXCTP0R + i,
217517284a7SBALATON Zoltan                             mal, &dcr_read_mal, &dcr_write_mal);
21804534280SBALATON Zoltan     }
219da116a8aSCédric Le Goater     for (i = 0; i < mal->rxcnum; i++) {
220da116a8aSCédric Le Goater         ppc4xx_dcr_register(dcr, MAL0_RCBS0 + i,
221517284a7SBALATON Zoltan                             mal, &dcr_read_mal, &dcr_write_mal);
22204534280SBALATON Zoltan     }
223517284a7SBALATON Zoltan }
224629cae61SCédric Le Goater 
225da116a8aSCédric Le Goater static void ppc4xx_mal_finalize(Object *obj)
226da116a8aSCédric Le Goater {
227da116a8aSCédric Le Goater     Ppc4xxMalState *mal = PPC4xx_MAL(obj);
228da116a8aSCédric Le Goater 
229da116a8aSCédric Le Goater     g_free(mal->rcbs);
230da116a8aSCédric Le Goater     g_free(mal->rxctpr);
231da116a8aSCédric Le Goater     g_free(mal->txctpr);
232da116a8aSCédric Le Goater }
233da116a8aSCédric Le Goater 
234*90f5755eSRichard Henderson static const Property ppc4xx_mal_properties[] = {
235da116a8aSCédric Le Goater     DEFINE_PROP_UINT8("txc-num", Ppc4xxMalState, txcnum, 0),
236da116a8aSCédric Le Goater     DEFINE_PROP_UINT8("rxc-num", Ppc4xxMalState, rxcnum, 0),
237da116a8aSCédric Le Goater     DEFINE_PROP_END_OF_LIST(),
238da116a8aSCédric Le Goater };
239da116a8aSCédric Le Goater 
240da116a8aSCédric Le Goater static void ppc4xx_mal_class_init(ObjectClass *oc, void *data)
241da116a8aSCédric Le Goater {
242da116a8aSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(oc);
243da116a8aSCédric Le Goater 
244da116a8aSCédric Le Goater     dc->realize = ppc4xx_mal_realize;
245e3d08143SPeter Maydell     device_class_set_legacy_reset(dc, ppc4xx_mal_reset);
246da116a8aSCédric Le Goater     /* Reason: only works as function of a ppc4xx SoC */
247da116a8aSCédric Le Goater     dc->user_creatable = false;
248da116a8aSCédric Le Goater     device_class_set_props(dc, ppc4xx_mal_properties);
249da116a8aSCédric Le Goater }
250da116a8aSCédric Le Goater 
2512d54aaf1SBALATON Zoltan /*****************************************************************************/
2522d54aaf1SBALATON Zoltan /* Peripheral local bus arbitrer */
2532d54aaf1SBALATON Zoltan enum {
2542d54aaf1SBALATON Zoltan     PLB3A0_ACR = 0x077,
2552d54aaf1SBALATON Zoltan     PLB4A0_ACR = 0x081,
2562d54aaf1SBALATON Zoltan     PLB0_BESR  = 0x084,
2572d54aaf1SBALATON Zoltan     PLB0_BEAR  = 0x086,
2582d54aaf1SBALATON Zoltan     PLB0_ACR   = 0x087,
2592d54aaf1SBALATON Zoltan     PLB4A1_ACR = 0x089,
2602d54aaf1SBALATON Zoltan };
2612d54aaf1SBALATON Zoltan 
2622d54aaf1SBALATON Zoltan static uint32_t dcr_read_plb(void *opaque, int dcrn)
2632d54aaf1SBALATON Zoltan {
264052c779bSBALATON Zoltan     Ppc4xxPlbState *plb = opaque;
2652d54aaf1SBALATON Zoltan     uint32_t ret;
2662d54aaf1SBALATON Zoltan 
2672d54aaf1SBALATON Zoltan     switch (dcrn) {
2682d54aaf1SBALATON Zoltan     case PLB0_ACR:
2692d54aaf1SBALATON Zoltan         ret = plb->acr;
2702d54aaf1SBALATON Zoltan         break;
2712d54aaf1SBALATON Zoltan     case PLB0_BEAR:
2722d54aaf1SBALATON Zoltan         ret = plb->bear;
2732d54aaf1SBALATON Zoltan         break;
2742d54aaf1SBALATON Zoltan     case PLB0_BESR:
2752d54aaf1SBALATON Zoltan         ret = plb->besr;
2762d54aaf1SBALATON Zoltan         break;
2772d54aaf1SBALATON Zoltan     default:
2782d54aaf1SBALATON Zoltan         /* Avoid gcc warning */
2792d54aaf1SBALATON Zoltan         ret = 0;
2802d54aaf1SBALATON Zoltan         break;
2812d54aaf1SBALATON Zoltan     }
2822d54aaf1SBALATON Zoltan 
2832d54aaf1SBALATON Zoltan     return ret;
2842d54aaf1SBALATON Zoltan }
2852d54aaf1SBALATON Zoltan 
2862d54aaf1SBALATON Zoltan static void dcr_write_plb(void *opaque, int dcrn, uint32_t val)
2872d54aaf1SBALATON Zoltan {
288052c779bSBALATON Zoltan     Ppc4xxPlbState *plb = opaque;
2892d54aaf1SBALATON Zoltan 
2902d54aaf1SBALATON Zoltan     switch (dcrn) {
2912d54aaf1SBALATON Zoltan     case PLB0_ACR:
2922d54aaf1SBALATON Zoltan         /*
2932d54aaf1SBALATON Zoltan          * We don't care about the actual parameters written as
2942d54aaf1SBALATON Zoltan          * we don't manage any priorities on the bus
2952d54aaf1SBALATON Zoltan          */
2962d54aaf1SBALATON Zoltan         plb->acr = val & 0xF8000000;
2972d54aaf1SBALATON Zoltan         break;
2982d54aaf1SBALATON Zoltan     case PLB0_BEAR:
2992d54aaf1SBALATON Zoltan         /* Read only */
3002d54aaf1SBALATON Zoltan         break;
3012d54aaf1SBALATON Zoltan     case PLB0_BESR:
3022d54aaf1SBALATON Zoltan         /* Write-clear */
3032d54aaf1SBALATON Zoltan         plb->besr &= ~val;
3042d54aaf1SBALATON Zoltan         break;
3052d54aaf1SBALATON Zoltan     }
3062d54aaf1SBALATON Zoltan }
3072d54aaf1SBALATON Zoltan 
3082d54aaf1SBALATON Zoltan static void ppc405_plb_reset(DeviceState *dev)
3092d54aaf1SBALATON Zoltan {
310052c779bSBALATON Zoltan     Ppc4xxPlbState *plb = PPC4xx_PLB(dev);
3112d54aaf1SBALATON Zoltan 
3122d54aaf1SBALATON Zoltan     plb->acr = 0x00000000;
3132d54aaf1SBALATON Zoltan     plb->bear = 0x00000000;
3142d54aaf1SBALATON Zoltan     plb->besr = 0x00000000;
3152d54aaf1SBALATON Zoltan }
3162d54aaf1SBALATON Zoltan 
3172d54aaf1SBALATON Zoltan static void ppc405_plb_realize(DeviceState *dev, Error **errp)
3182d54aaf1SBALATON Zoltan {
319052c779bSBALATON Zoltan     Ppc4xxPlbState *plb = PPC4xx_PLB(dev);
3202d54aaf1SBALATON Zoltan     Ppc4xxDcrDeviceState *dcr = PPC4xx_DCR_DEVICE(dev);
3212d54aaf1SBALATON Zoltan 
3222d54aaf1SBALATON Zoltan     ppc4xx_dcr_register(dcr, PLB3A0_ACR, plb, &dcr_read_plb, &dcr_write_plb);
3232d54aaf1SBALATON Zoltan     ppc4xx_dcr_register(dcr, PLB4A0_ACR, plb, &dcr_read_plb, &dcr_write_plb);
3242d54aaf1SBALATON Zoltan     ppc4xx_dcr_register(dcr, PLB0_ACR, plb, &dcr_read_plb, &dcr_write_plb);
3252d54aaf1SBALATON Zoltan     ppc4xx_dcr_register(dcr, PLB0_BEAR, plb, &dcr_read_plb, &dcr_write_plb);
3262d54aaf1SBALATON Zoltan     ppc4xx_dcr_register(dcr, PLB0_BESR, plb, &dcr_read_plb, &dcr_write_plb);
3272d54aaf1SBALATON Zoltan     ppc4xx_dcr_register(dcr, PLB4A1_ACR, plb, &dcr_read_plb, &dcr_write_plb);
3282d54aaf1SBALATON Zoltan }
3292d54aaf1SBALATON Zoltan 
3302d54aaf1SBALATON Zoltan static void ppc405_plb_class_init(ObjectClass *oc, void *data)
3312d54aaf1SBALATON Zoltan {
3322d54aaf1SBALATON Zoltan     DeviceClass *dc = DEVICE_CLASS(oc);
3332d54aaf1SBALATON Zoltan 
3342d54aaf1SBALATON Zoltan     dc->realize = ppc405_plb_realize;
335e3d08143SPeter Maydell     device_class_set_legacy_reset(dc, ppc405_plb_reset);
3362d54aaf1SBALATON Zoltan     /* Reason: only works as function of a ppc4xx SoC */
3372d54aaf1SBALATON Zoltan     dc->user_creatable = false;
3382d54aaf1SBALATON Zoltan }
3392d54aaf1SBALATON Zoltan 
340127ba8d0SBALATON Zoltan /*****************************************************************************/
341127ba8d0SBALATON Zoltan /* Peripheral controller */
342127ba8d0SBALATON Zoltan enum {
343127ba8d0SBALATON Zoltan     EBC0_CFGADDR = 0x012,
344127ba8d0SBALATON Zoltan     EBC0_CFGDATA = 0x013,
345127ba8d0SBALATON Zoltan };
346127ba8d0SBALATON Zoltan 
347127ba8d0SBALATON Zoltan static uint32_t dcr_read_ebc(void *opaque, int dcrn)
348127ba8d0SBALATON Zoltan {
349cba58aa7SBALATON Zoltan     Ppc4xxEbcState *ebc = opaque;
350127ba8d0SBALATON Zoltan     uint32_t ret;
351127ba8d0SBALATON Zoltan 
352127ba8d0SBALATON Zoltan     switch (dcrn) {
353127ba8d0SBALATON Zoltan     case EBC0_CFGADDR:
354127ba8d0SBALATON Zoltan         ret = ebc->addr;
355127ba8d0SBALATON Zoltan         break;
356127ba8d0SBALATON Zoltan     case EBC0_CFGDATA:
357127ba8d0SBALATON Zoltan         switch (ebc->addr) {
358127ba8d0SBALATON Zoltan         case 0x00: /* B0CR */
359127ba8d0SBALATON Zoltan             ret = ebc->bcr[0];
360127ba8d0SBALATON Zoltan             break;
361127ba8d0SBALATON Zoltan         case 0x01: /* B1CR */
362127ba8d0SBALATON Zoltan             ret = ebc->bcr[1];
363127ba8d0SBALATON Zoltan             break;
364127ba8d0SBALATON Zoltan         case 0x02: /* B2CR */
365127ba8d0SBALATON Zoltan             ret = ebc->bcr[2];
366127ba8d0SBALATON Zoltan             break;
367127ba8d0SBALATON Zoltan         case 0x03: /* B3CR */
368127ba8d0SBALATON Zoltan             ret = ebc->bcr[3];
369127ba8d0SBALATON Zoltan             break;
370127ba8d0SBALATON Zoltan         case 0x04: /* B4CR */
371127ba8d0SBALATON Zoltan             ret = ebc->bcr[4];
372127ba8d0SBALATON Zoltan             break;
373127ba8d0SBALATON Zoltan         case 0x05: /* B5CR */
374127ba8d0SBALATON Zoltan             ret = ebc->bcr[5];
375127ba8d0SBALATON Zoltan             break;
376127ba8d0SBALATON Zoltan         case 0x06: /* B6CR */
377127ba8d0SBALATON Zoltan             ret = ebc->bcr[6];
378127ba8d0SBALATON Zoltan             break;
379127ba8d0SBALATON Zoltan         case 0x07: /* B7CR */
380127ba8d0SBALATON Zoltan             ret = ebc->bcr[7];
381127ba8d0SBALATON Zoltan             break;
382127ba8d0SBALATON Zoltan         case 0x10: /* B0AP */
383127ba8d0SBALATON Zoltan             ret = ebc->bap[0];
384127ba8d0SBALATON Zoltan             break;
385127ba8d0SBALATON Zoltan         case 0x11: /* B1AP */
386127ba8d0SBALATON Zoltan             ret = ebc->bap[1];
387127ba8d0SBALATON Zoltan             break;
388127ba8d0SBALATON Zoltan         case 0x12: /* B2AP */
389127ba8d0SBALATON Zoltan             ret = ebc->bap[2];
390127ba8d0SBALATON Zoltan             break;
391127ba8d0SBALATON Zoltan         case 0x13: /* B3AP */
392127ba8d0SBALATON Zoltan             ret = ebc->bap[3];
393127ba8d0SBALATON Zoltan             break;
394127ba8d0SBALATON Zoltan         case 0x14: /* B4AP */
395127ba8d0SBALATON Zoltan             ret = ebc->bap[4];
396127ba8d0SBALATON Zoltan             break;
397127ba8d0SBALATON Zoltan         case 0x15: /* B5AP */
398127ba8d0SBALATON Zoltan             ret = ebc->bap[5];
399127ba8d0SBALATON Zoltan             break;
400127ba8d0SBALATON Zoltan         case 0x16: /* B6AP */
401127ba8d0SBALATON Zoltan             ret = ebc->bap[6];
402127ba8d0SBALATON Zoltan             break;
403127ba8d0SBALATON Zoltan         case 0x17: /* B7AP */
404127ba8d0SBALATON Zoltan             ret = ebc->bap[7];
405127ba8d0SBALATON Zoltan             break;
406127ba8d0SBALATON Zoltan         case 0x20: /* BEAR */
407127ba8d0SBALATON Zoltan             ret = ebc->bear;
408127ba8d0SBALATON Zoltan             break;
409127ba8d0SBALATON Zoltan         case 0x21: /* BESR0 */
410127ba8d0SBALATON Zoltan             ret = ebc->besr0;
411127ba8d0SBALATON Zoltan             break;
412127ba8d0SBALATON Zoltan         case 0x22: /* BESR1 */
413127ba8d0SBALATON Zoltan             ret = ebc->besr1;
414127ba8d0SBALATON Zoltan             break;
415127ba8d0SBALATON Zoltan         case 0x23: /* CFG */
416127ba8d0SBALATON Zoltan             ret = ebc->cfg;
417127ba8d0SBALATON Zoltan             break;
418127ba8d0SBALATON Zoltan         default:
419127ba8d0SBALATON Zoltan             ret = 0x00000000;
420127ba8d0SBALATON Zoltan             break;
421127ba8d0SBALATON Zoltan         }
422127ba8d0SBALATON Zoltan         break;
423127ba8d0SBALATON Zoltan     default:
424127ba8d0SBALATON Zoltan         ret = 0x00000000;
425127ba8d0SBALATON Zoltan         break;
426127ba8d0SBALATON Zoltan     }
427127ba8d0SBALATON Zoltan 
428127ba8d0SBALATON Zoltan     return ret;
429127ba8d0SBALATON Zoltan }
430127ba8d0SBALATON Zoltan 
431127ba8d0SBALATON Zoltan static void dcr_write_ebc(void *opaque, int dcrn, uint32_t val)
432127ba8d0SBALATON Zoltan {
433cba58aa7SBALATON Zoltan     Ppc4xxEbcState *ebc = opaque;
434127ba8d0SBALATON Zoltan 
435127ba8d0SBALATON Zoltan     switch (dcrn) {
436127ba8d0SBALATON Zoltan     case EBC0_CFGADDR:
437127ba8d0SBALATON Zoltan         ebc->addr = val;
438127ba8d0SBALATON Zoltan         break;
439127ba8d0SBALATON Zoltan     case EBC0_CFGDATA:
440127ba8d0SBALATON Zoltan         switch (ebc->addr) {
441127ba8d0SBALATON Zoltan         case 0x00: /* B0CR */
442127ba8d0SBALATON Zoltan             break;
443127ba8d0SBALATON Zoltan         case 0x01: /* B1CR */
444127ba8d0SBALATON Zoltan             break;
445127ba8d0SBALATON Zoltan         case 0x02: /* B2CR */
446127ba8d0SBALATON Zoltan             break;
447127ba8d0SBALATON Zoltan         case 0x03: /* B3CR */
448127ba8d0SBALATON Zoltan             break;
449127ba8d0SBALATON Zoltan         case 0x04: /* B4CR */
450127ba8d0SBALATON Zoltan             break;
451127ba8d0SBALATON Zoltan         case 0x05: /* B5CR */
452127ba8d0SBALATON Zoltan             break;
453127ba8d0SBALATON Zoltan         case 0x06: /* B6CR */
454127ba8d0SBALATON Zoltan             break;
455127ba8d0SBALATON Zoltan         case 0x07: /* B7CR */
456127ba8d0SBALATON Zoltan             break;
457127ba8d0SBALATON Zoltan         case 0x10: /* B0AP */
458127ba8d0SBALATON Zoltan             break;
459127ba8d0SBALATON Zoltan         case 0x11: /* B1AP */
460127ba8d0SBALATON Zoltan             break;
461127ba8d0SBALATON Zoltan         case 0x12: /* B2AP */
462127ba8d0SBALATON Zoltan             break;
463127ba8d0SBALATON Zoltan         case 0x13: /* B3AP */
464127ba8d0SBALATON Zoltan             break;
465127ba8d0SBALATON Zoltan         case 0x14: /* B4AP */
466127ba8d0SBALATON Zoltan             break;
467127ba8d0SBALATON Zoltan         case 0x15: /* B5AP */
468127ba8d0SBALATON Zoltan             break;
469127ba8d0SBALATON Zoltan         case 0x16: /* B6AP */
470127ba8d0SBALATON Zoltan             break;
471127ba8d0SBALATON Zoltan         case 0x17: /* B7AP */
472127ba8d0SBALATON Zoltan             break;
473127ba8d0SBALATON Zoltan         case 0x20: /* BEAR */
474127ba8d0SBALATON Zoltan             break;
475127ba8d0SBALATON Zoltan         case 0x21: /* BESR0 */
476127ba8d0SBALATON Zoltan             break;
477127ba8d0SBALATON Zoltan         case 0x22: /* BESR1 */
478127ba8d0SBALATON Zoltan             break;
479127ba8d0SBALATON Zoltan         case 0x23: /* CFG */
480127ba8d0SBALATON Zoltan             break;
481127ba8d0SBALATON Zoltan         default:
482127ba8d0SBALATON Zoltan             break;
483127ba8d0SBALATON Zoltan         }
484127ba8d0SBALATON Zoltan         break;
485127ba8d0SBALATON Zoltan     default:
486127ba8d0SBALATON Zoltan         break;
487127ba8d0SBALATON Zoltan     }
488127ba8d0SBALATON Zoltan }
489127ba8d0SBALATON Zoltan 
490127ba8d0SBALATON Zoltan static void ppc405_ebc_reset(DeviceState *dev)
491127ba8d0SBALATON Zoltan {
492cba58aa7SBALATON Zoltan     Ppc4xxEbcState *ebc = PPC4xx_EBC(dev);
493127ba8d0SBALATON Zoltan     int i;
494127ba8d0SBALATON Zoltan 
495127ba8d0SBALATON Zoltan     ebc->addr = 0x00000000;
496127ba8d0SBALATON Zoltan     ebc->bap[0] = 0x7F8FFE80;
497127ba8d0SBALATON Zoltan     ebc->bcr[0] = 0xFFE28000;
498127ba8d0SBALATON Zoltan     for (i = 0; i < 8; i++) {
499127ba8d0SBALATON Zoltan         ebc->bap[i] = 0x00000000;
500127ba8d0SBALATON Zoltan         ebc->bcr[i] = 0x00000000;
501127ba8d0SBALATON Zoltan     }
502127ba8d0SBALATON Zoltan     ebc->besr0 = 0x00000000;
503127ba8d0SBALATON Zoltan     ebc->besr1 = 0x00000000;
504127ba8d0SBALATON Zoltan     ebc->cfg = 0x80400000;
505127ba8d0SBALATON Zoltan }
506127ba8d0SBALATON Zoltan 
507127ba8d0SBALATON Zoltan static void ppc405_ebc_realize(DeviceState *dev, Error **errp)
508127ba8d0SBALATON Zoltan {
509cba58aa7SBALATON Zoltan     Ppc4xxEbcState *ebc = PPC4xx_EBC(dev);
510127ba8d0SBALATON Zoltan     Ppc4xxDcrDeviceState *dcr = PPC4xx_DCR_DEVICE(dev);
511127ba8d0SBALATON Zoltan 
512127ba8d0SBALATON Zoltan     ppc4xx_dcr_register(dcr, EBC0_CFGADDR, ebc, &dcr_read_ebc, &dcr_write_ebc);
513127ba8d0SBALATON Zoltan     ppc4xx_dcr_register(dcr, EBC0_CFGDATA, ebc, &dcr_read_ebc, &dcr_write_ebc);
514127ba8d0SBALATON Zoltan }
515127ba8d0SBALATON Zoltan 
516127ba8d0SBALATON Zoltan static void ppc405_ebc_class_init(ObjectClass *oc, void *data)
517127ba8d0SBALATON Zoltan {
518127ba8d0SBALATON Zoltan     DeviceClass *dc = DEVICE_CLASS(oc);
519127ba8d0SBALATON Zoltan 
520127ba8d0SBALATON Zoltan     dc->realize = ppc405_ebc_realize;
521e3d08143SPeter Maydell     device_class_set_legacy_reset(dc, ppc405_ebc_reset);
522127ba8d0SBALATON Zoltan     /* Reason: only works as function of a ppc4xx SoC */
523127ba8d0SBALATON Zoltan     dc->user_creatable = false;
524127ba8d0SBALATON Zoltan }
525127ba8d0SBALATON Zoltan 
526629cae61SCédric Le Goater /* PPC4xx_DCR_DEVICE */
527629cae61SCédric Le Goater 
528629cae61SCédric Le Goater void ppc4xx_dcr_register(Ppc4xxDcrDeviceState *dev, int dcrn, void *opaque,
529629cae61SCédric Le Goater                          dcr_read_cb dcr_read, dcr_write_cb dcr_write)
530629cae61SCédric Le Goater {
531629cae61SCédric Le Goater     assert(dev->cpu);
532629cae61SCédric Le Goater     ppc_dcr_register(&dev->cpu->env, dcrn, opaque, dcr_read, dcr_write);
533629cae61SCédric Le Goater }
534629cae61SCédric Le Goater 
535629cae61SCédric Le Goater bool ppc4xx_dcr_realize(Ppc4xxDcrDeviceState *dev, PowerPCCPU *cpu,
536629cae61SCédric Le Goater                         Error **errp)
537629cae61SCédric Le Goater {
538629cae61SCédric Le Goater     object_property_set_link(OBJECT(dev), "cpu", OBJECT(cpu), &error_abort);
539629cae61SCédric Le Goater     return sysbus_realize(SYS_BUS_DEVICE(dev), errp);
540629cae61SCédric Le Goater }
541629cae61SCédric Le Goater 
542*90f5755eSRichard Henderson static const Property ppc4xx_dcr_properties[] = {
543629cae61SCédric Le Goater     DEFINE_PROP_LINK("cpu", Ppc4xxDcrDeviceState, cpu, TYPE_POWERPC_CPU,
544629cae61SCédric Le Goater                      PowerPCCPU *),
545629cae61SCédric Le Goater     DEFINE_PROP_END_OF_LIST(),
546629cae61SCédric Le Goater };
547629cae61SCédric Le Goater 
548629cae61SCédric Le Goater static void ppc4xx_dcr_class_init(ObjectClass *oc, void *data)
549629cae61SCédric Le Goater {
550629cae61SCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(oc);
551629cae61SCédric Le Goater 
552629cae61SCédric Le Goater     device_class_set_props(dc, ppc4xx_dcr_properties);
553629cae61SCédric Le Goater }
554629cae61SCédric Le Goater 
555629cae61SCédric Le Goater static const TypeInfo ppc4xx_types[] = {
556629cae61SCédric Le Goater     {
557da116a8aSCédric Le Goater         .name           = TYPE_PPC4xx_MAL,
558da116a8aSCédric Le Goater         .parent         = TYPE_PPC4xx_DCR_DEVICE,
559da116a8aSCédric Le Goater         .instance_size  = sizeof(Ppc4xxMalState),
560da116a8aSCédric Le Goater         .instance_finalize = ppc4xx_mal_finalize,
561da116a8aSCédric Le Goater         .class_init     = ppc4xx_mal_class_init,
562da116a8aSCédric Le Goater     }, {
563052c779bSBALATON Zoltan         .name           = TYPE_PPC4xx_PLB,
5642d54aaf1SBALATON Zoltan         .parent         = TYPE_PPC4xx_DCR_DEVICE,
565052c779bSBALATON Zoltan         .instance_size  = sizeof(Ppc4xxPlbState),
5662d54aaf1SBALATON Zoltan         .class_init     = ppc405_plb_class_init,
5672d54aaf1SBALATON Zoltan     }, {
568cba58aa7SBALATON Zoltan         .name           = TYPE_PPC4xx_EBC,
569127ba8d0SBALATON Zoltan         .parent         = TYPE_PPC4xx_DCR_DEVICE,
570cba58aa7SBALATON Zoltan         .instance_size  = sizeof(Ppc4xxEbcState),
571127ba8d0SBALATON Zoltan         .class_init     = ppc405_ebc_class_init,
572127ba8d0SBALATON Zoltan     }, {
573629cae61SCédric Le Goater         .name           = TYPE_PPC4xx_DCR_DEVICE,
574629cae61SCédric Le Goater         .parent         = TYPE_SYS_BUS_DEVICE,
575629cae61SCédric Le Goater         .instance_size  = sizeof(Ppc4xxDcrDeviceState),
576629cae61SCédric Le Goater         .class_init     = ppc4xx_dcr_class_init,
577629cae61SCédric Le Goater         .abstract       = true,
578629cae61SCédric Le Goater     }
579629cae61SCédric Le Goater };
580629cae61SCédric Le Goater 
581629cae61SCédric Le Goater DEFINE_TYPES(ppc4xx_types)
582