2 * QEMU PowerPC 4xx embedded processors shared devices emulation
4 * Copyright (c) 2007 Jocelyn Mayer
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:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
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
25 #include "qemu/osdep.h"
27 #include "hw/ppc/ppc4xx.h"
28 #include "hw/qdev-properties.h"
29 #include "qapi/error.h"
31 /*****************************************************************************/
40 MAL0_TXEOBISR
= 0x186,
44 MAL0_RXEOBISR
= 0x192,
52 static void ppc4xx_mal_reset(DeviceState
*dev
)
54 Ppc4xxMalState
*mal
= PPC4xx_MAL(dev
);
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;
67 static uint32_t dcr_read_mal(void *opaque
, int dcrn
)
69 Ppc4xxMalState
*mal
= opaque
;
110 if (dcrn
>= MAL0_TXCTP0R
&& dcrn
< MAL0_TXCTP0R
+ mal
->txcnum
) {
111 ret
= mal
->txctpr
[dcrn
- MAL0_TXCTP0R
];
113 if (dcrn
>= MAL0_RXCTP0R
&& dcrn
< MAL0_RXCTP0R
+ mal
->rxcnum
) {
114 ret
= mal
->rxctpr
[dcrn
- MAL0_RXCTP0R
];
116 if (dcrn
>= MAL0_RCBS0
&& dcrn
< MAL0_RCBS0
+ mal
->rxcnum
) {
117 ret
= mal
->rcbs
[dcrn
- MAL0_RCBS0
];
123 static void dcr_write_mal(void *opaque
, int dcrn
, uint32_t val
)
125 Ppc4xxMalState
*mal
= opaque
;
129 if (val
& 0x80000000) {
130 ppc4xx_mal_reset(DEVICE(mal
));
132 mal
->cfg
= val
& 0x00FFC087;
139 mal
->ier
= val
& 0x0000001F;
142 mal
->txcasr
= val
& 0xF0000000;
145 mal
->txcarr
= val
& 0xF0000000;
149 mal
->txeobisr
&= ~val
;
156 mal
->rxcasr
= val
& 0xC0000000;
159 mal
->rxcarr
= val
& 0xC0000000;
163 mal
->rxeobisr
&= ~val
;
170 if (dcrn
>= MAL0_TXCTP0R
&& dcrn
< MAL0_TXCTP0R
+ mal
->txcnum
) {
171 mal
->txctpr
[dcrn
- MAL0_TXCTP0R
] = val
;
173 if (dcrn
>= MAL0_RXCTP0R
&& dcrn
< MAL0_RXCTP0R
+ mal
->rxcnum
) {
174 mal
->rxctpr
[dcrn
- MAL0_RXCTP0R
] = val
;
176 if (dcrn
>= MAL0_RCBS0
&& dcrn
< MAL0_RCBS0
+ mal
->rxcnum
) {
177 mal
->rcbs
[dcrn
- MAL0_RCBS0
] = val
& 0x000000FF;
181 static void ppc4xx_mal_realize(DeviceState
*dev
, Error
**errp
)
183 Ppc4xxMalState
*mal
= PPC4xx_MAL(dev
);
184 Ppc4xxDcrDeviceState
*dcr
= PPC4xx_DCR_DEVICE(dev
);
187 if (mal
->txcnum
> 32 || mal
->rxcnum
> 32) {
188 error_setg(errp
, "invalid TXC/RXC number");
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
);
196 for (i
= 0; i
< ARRAY_SIZE(mal
->irqs
); i
++) {
197 sysbus_init_irq(SYS_BUS_DEVICE(dev
), &mal
->irqs
[i
]);
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
);
215 for (i
= 0; i
< mal
->rxcnum
; i
++) {
216 ppc4xx_dcr_register(dcr
, MAL0_RXCTP0R
+ i
,
217 mal
, &dcr_read_mal
, &dcr_write_mal
);
219 for (i
= 0; i
< mal
->rxcnum
; i
++) {
220 ppc4xx_dcr_register(dcr
, MAL0_RCBS0
+ i
,
221 mal
, &dcr_read_mal
, &dcr_write_mal
);
225 static void ppc4xx_mal_finalize(Object
*obj
)
227 Ppc4xxMalState
*mal
= PPC4xx_MAL(obj
);
234 static Property ppc4xx_mal_properties
[] = {
235 DEFINE_PROP_UINT8("txc-num", Ppc4xxMalState
, txcnum
, 0),
236 DEFINE_PROP_UINT8("rxc-num", Ppc4xxMalState
, rxcnum
, 0),
237 DEFINE_PROP_END_OF_LIST(),
240 static void ppc4xx_mal_class_init(ObjectClass
*oc
, void *data
)
242 DeviceClass
*dc
= DEVICE_CLASS(oc
);
244 dc
->realize
= ppc4xx_mal_realize
;
245 dc
->reset
= ppc4xx_mal_reset
;
246 /* Reason: only works as function of a ppc4xx SoC */
247 dc
->user_creatable
= false;
248 device_class_set_props(dc
, ppc4xx_mal_properties
);
251 /*****************************************************************************/
252 /* Peripheral local bus arbitrer */
262 static uint32_t dcr_read_plb(void *opaque
, int dcrn
)
264 Ppc4xxPlbState
*plb
= opaque
;
278 /* Avoid gcc warning */
286 static void dcr_write_plb(void *opaque
, int dcrn
, uint32_t val
)
288 Ppc4xxPlbState
*plb
= opaque
;
293 * We don't care about the actual parameters written as
294 * we don't manage any priorities on the bus
296 plb
->acr
= val
& 0xF8000000;
308 static void ppc405_plb_reset(DeviceState
*dev
)
310 Ppc4xxPlbState
*plb
= PPC4xx_PLB(dev
);
312 plb
->acr
= 0x00000000;
313 plb
->bear
= 0x00000000;
314 plb
->besr
= 0x00000000;
317 static void ppc405_plb_realize(DeviceState
*dev
, Error
**errp
)
319 Ppc4xxPlbState
*plb
= PPC4xx_PLB(dev
);
320 Ppc4xxDcrDeviceState
*dcr
= PPC4xx_DCR_DEVICE(dev
);
322 ppc4xx_dcr_register(dcr
, PLB3A0_ACR
, plb
, &dcr_read_plb
, &dcr_write_plb
);
323 ppc4xx_dcr_register(dcr
, PLB4A0_ACR
, plb
, &dcr_read_plb
, &dcr_write_plb
);
324 ppc4xx_dcr_register(dcr
, PLB0_ACR
, plb
, &dcr_read_plb
, &dcr_write_plb
);
325 ppc4xx_dcr_register(dcr
, PLB0_BEAR
, plb
, &dcr_read_plb
, &dcr_write_plb
);
326 ppc4xx_dcr_register(dcr
, PLB0_BESR
, plb
, &dcr_read_plb
, &dcr_write_plb
);
327 ppc4xx_dcr_register(dcr
, PLB4A1_ACR
, plb
, &dcr_read_plb
, &dcr_write_plb
);
330 static void ppc405_plb_class_init(ObjectClass
*oc
, void *data
)
332 DeviceClass
*dc
= DEVICE_CLASS(oc
);
334 dc
->realize
= ppc405_plb_realize
;
335 dc
->reset
= ppc405_plb_reset
;
336 /* Reason: only works as function of a ppc4xx SoC */
337 dc
->user_creatable
= false;
340 /*****************************************************************************/
341 /* Peripheral controller */
343 EBC0_CFGADDR
= 0x012,
344 EBC0_CFGDATA
= 0x013,
347 static uint32_t dcr_read_ebc(void *opaque
, int dcrn
)
349 Ppc4xxEbcState
*ebc
= opaque
;
358 case 0x00: /* B0CR */
361 case 0x01: /* B1CR */
364 case 0x02: /* B2CR */
367 case 0x03: /* B3CR */
370 case 0x04: /* B4CR */
373 case 0x05: /* B5CR */
376 case 0x06: /* B6CR */
379 case 0x07: /* B7CR */
382 case 0x10: /* B0AP */
385 case 0x11: /* B1AP */
388 case 0x12: /* B2AP */
391 case 0x13: /* B3AP */
394 case 0x14: /* B4AP */
397 case 0x15: /* B5AP */
400 case 0x16: /* B6AP */
403 case 0x17: /* B7AP */
406 case 0x20: /* BEAR */
409 case 0x21: /* BESR0 */
412 case 0x22: /* BESR1 */
431 static void dcr_write_ebc(void *opaque
, int dcrn
, uint32_t val
)
433 Ppc4xxEbcState
*ebc
= opaque
;
441 case 0x00: /* B0CR */
443 case 0x01: /* B1CR */
445 case 0x02: /* B2CR */
447 case 0x03: /* B3CR */
449 case 0x04: /* B4CR */
451 case 0x05: /* B5CR */
453 case 0x06: /* B6CR */
455 case 0x07: /* B7CR */
457 case 0x10: /* B0AP */
459 case 0x11: /* B1AP */
461 case 0x12: /* B2AP */
463 case 0x13: /* B3AP */
465 case 0x14: /* B4AP */
467 case 0x15: /* B5AP */
469 case 0x16: /* B6AP */
471 case 0x17: /* B7AP */
473 case 0x20: /* BEAR */
475 case 0x21: /* BESR0 */
477 case 0x22: /* BESR1 */
490 static void ppc405_ebc_reset(DeviceState
*dev
)
492 Ppc4xxEbcState
*ebc
= PPC4xx_EBC(dev
);
495 ebc
->addr
= 0x00000000;
496 ebc
->bap
[0] = 0x7F8FFE80;
497 ebc
->bcr
[0] = 0xFFE28000;
498 for (i
= 0; i
< 8; i
++) {
499 ebc
->bap
[i
] = 0x00000000;
500 ebc
->bcr
[i
] = 0x00000000;
502 ebc
->besr0
= 0x00000000;
503 ebc
->besr1
= 0x00000000;
504 ebc
->cfg
= 0x80400000;
507 static void ppc405_ebc_realize(DeviceState
*dev
, Error
**errp
)
509 Ppc4xxEbcState
*ebc
= PPC4xx_EBC(dev
);
510 Ppc4xxDcrDeviceState
*dcr
= PPC4xx_DCR_DEVICE(dev
);
512 ppc4xx_dcr_register(dcr
, EBC0_CFGADDR
, ebc
, &dcr_read_ebc
, &dcr_write_ebc
);
513 ppc4xx_dcr_register(dcr
, EBC0_CFGDATA
, ebc
, &dcr_read_ebc
, &dcr_write_ebc
);
516 static void ppc405_ebc_class_init(ObjectClass
*oc
, void *data
)
518 DeviceClass
*dc
= DEVICE_CLASS(oc
);
520 dc
->realize
= ppc405_ebc_realize
;
521 dc
->reset
= ppc405_ebc_reset
;
522 /* Reason: only works as function of a ppc4xx SoC */
523 dc
->user_creatable
= false;
526 /* PPC4xx_DCR_DEVICE */
528 void ppc4xx_dcr_register(Ppc4xxDcrDeviceState
*dev
, int dcrn
, void *opaque
,
529 dcr_read_cb dcr_read
, dcr_write_cb dcr_write
)
532 ppc_dcr_register(&dev
->cpu
->env
, dcrn
, opaque
, dcr_read
, dcr_write
);
535 bool ppc4xx_dcr_realize(Ppc4xxDcrDeviceState
*dev
, PowerPCCPU
*cpu
,
538 object_property_set_link(OBJECT(dev
), "cpu", OBJECT(cpu
), &error_abort
);
539 return sysbus_realize(SYS_BUS_DEVICE(dev
), errp
);
542 static Property ppc4xx_dcr_properties
[] = {
543 DEFINE_PROP_LINK("cpu", Ppc4xxDcrDeviceState
, cpu
, TYPE_POWERPC_CPU
,
545 DEFINE_PROP_END_OF_LIST(),
548 static void ppc4xx_dcr_class_init(ObjectClass
*oc
, void *data
)
550 DeviceClass
*dc
= DEVICE_CLASS(oc
);
552 device_class_set_props(dc
, ppc4xx_dcr_properties
);
555 static const TypeInfo ppc4xx_types
[] = {
557 .name
= TYPE_PPC4xx_MAL
,
558 .parent
= TYPE_PPC4xx_DCR_DEVICE
,
559 .instance_size
= sizeof(Ppc4xxMalState
),
560 .instance_finalize
= ppc4xx_mal_finalize
,
561 .class_init
= ppc4xx_mal_class_init
,
563 .name
= TYPE_PPC4xx_PLB
,
564 .parent
= TYPE_PPC4xx_DCR_DEVICE
,
565 .instance_size
= sizeof(Ppc4xxPlbState
),
566 .class_init
= ppc405_plb_class_init
,
568 .name
= TYPE_PPC4xx_EBC
,
569 .parent
= TYPE_PPC4xx_DCR_DEVICE
,
570 .instance_size
= sizeof(Ppc4xxEbcState
),
571 .class_init
= ppc405_ebc_class_init
,
573 .name
= TYPE_PPC4xx_DCR_DEVICE
,
574 .parent
= TYPE_SYS_BUS_DEVICE
,
575 .instance_size
= sizeof(Ppc4xxDcrDeviceState
),
576 .class_init
= ppc4xx_dcr_class_init
,
581 DEFINE_TYPES(ppc4xx_types
)