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 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(), 238 }; 239 240 static void ppc4xx_mal_class_init(ObjectClass *oc, void *data) 241 { 242 DeviceClass *dc = DEVICE_CLASS(oc); 243 244 dc->realize = ppc4xx_mal_realize; 245 device_class_set_legacy_reset(dc, 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); 249 } 250 251 /*****************************************************************************/ 252 /* Peripheral local bus arbitrer */ 253 enum { 254 PLB3A0_ACR = 0x077, 255 PLB4A0_ACR = 0x081, 256 PLB0_BESR = 0x084, 257 PLB0_BEAR = 0x086, 258 PLB0_ACR = 0x087, 259 PLB4A1_ACR = 0x089, 260 }; 261 262 static uint32_t dcr_read_plb(void *opaque, int dcrn) 263 { 264 Ppc4xxPlbState *plb = opaque; 265 uint32_t ret; 266 267 switch (dcrn) { 268 case PLB0_ACR: 269 ret = plb->acr; 270 break; 271 case PLB0_BEAR: 272 ret = plb->bear; 273 break; 274 case PLB0_BESR: 275 ret = plb->besr; 276 break; 277 default: 278 /* Avoid gcc warning */ 279 ret = 0; 280 break; 281 } 282 283 return ret; 284 } 285 286 static void dcr_write_plb(void *opaque, int dcrn, uint32_t val) 287 { 288 Ppc4xxPlbState *plb = opaque; 289 290 switch (dcrn) { 291 case PLB0_ACR: 292 /* 293 * We don't care about the actual parameters written as 294 * we don't manage any priorities on the bus 295 */ 296 plb->acr = val & 0xF8000000; 297 break; 298 case PLB0_BEAR: 299 /* Read only */ 300 break; 301 case PLB0_BESR: 302 /* Write-clear */ 303 plb->besr &= ~val; 304 break; 305 } 306 } 307 308 static void ppc405_plb_reset(DeviceState *dev) 309 { 310 Ppc4xxPlbState *plb = PPC4xx_PLB(dev); 311 312 plb->acr = 0x00000000; 313 plb->bear = 0x00000000; 314 plb->besr = 0x00000000; 315 } 316 317 static void ppc405_plb_realize(DeviceState *dev, Error **errp) 318 { 319 Ppc4xxPlbState *plb = PPC4xx_PLB(dev); 320 Ppc4xxDcrDeviceState *dcr = PPC4xx_DCR_DEVICE(dev); 321 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); 328 } 329 330 static void ppc405_plb_class_init(ObjectClass *oc, void *data) 331 { 332 DeviceClass *dc = DEVICE_CLASS(oc); 333 334 dc->realize = ppc405_plb_realize; 335 device_class_set_legacy_reset(dc, ppc405_plb_reset); 336 /* Reason: only works as function of a ppc4xx SoC */ 337 dc->user_creatable = false; 338 } 339 340 /*****************************************************************************/ 341 /* Peripheral controller */ 342 enum { 343 EBC0_CFGADDR = 0x012, 344 EBC0_CFGDATA = 0x013, 345 }; 346 347 static uint32_t dcr_read_ebc(void *opaque, int dcrn) 348 { 349 Ppc4xxEbcState *ebc = opaque; 350 uint32_t ret; 351 352 switch (dcrn) { 353 case EBC0_CFGADDR: 354 ret = ebc->addr; 355 break; 356 case EBC0_CFGDATA: 357 switch (ebc->addr) { 358 case 0x00: /* B0CR */ 359 ret = ebc->bcr[0]; 360 break; 361 case 0x01: /* B1CR */ 362 ret = ebc->bcr[1]; 363 break; 364 case 0x02: /* B2CR */ 365 ret = ebc->bcr[2]; 366 break; 367 case 0x03: /* B3CR */ 368 ret = ebc->bcr[3]; 369 break; 370 case 0x04: /* B4CR */ 371 ret = ebc->bcr[4]; 372 break; 373 case 0x05: /* B5CR */ 374 ret = ebc->bcr[5]; 375 break; 376 case 0x06: /* B6CR */ 377 ret = ebc->bcr[6]; 378 break; 379 case 0x07: /* B7CR */ 380 ret = ebc->bcr[7]; 381 break; 382 case 0x10: /* B0AP */ 383 ret = ebc->bap[0]; 384 break; 385 case 0x11: /* B1AP */ 386 ret = ebc->bap[1]; 387 break; 388 case 0x12: /* B2AP */ 389 ret = ebc->bap[2]; 390 break; 391 case 0x13: /* B3AP */ 392 ret = ebc->bap[3]; 393 break; 394 case 0x14: /* B4AP */ 395 ret = ebc->bap[4]; 396 break; 397 case 0x15: /* B5AP */ 398 ret = ebc->bap[5]; 399 break; 400 case 0x16: /* B6AP */ 401 ret = ebc->bap[6]; 402 break; 403 case 0x17: /* B7AP */ 404 ret = ebc->bap[7]; 405 break; 406 case 0x20: /* BEAR */ 407 ret = ebc->bear; 408 break; 409 case 0x21: /* BESR0 */ 410 ret = ebc->besr0; 411 break; 412 case 0x22: /* BESR1 */ 413 ret = ebc->besr1; 414 break; 415 case 0x23: /* CFG */ 416 ret = ebc->cfg; 417 break; 418 default: 419 ret = 0x00000000; 420 break; 421 } 422 break; 423 default: 424 ret = 0x00000000; 425 break; 426 } 427 428 return ret; 429 } 430 431 static void dcr_write_ebc(void *opaque, int dcrn, uint32_t val) 432 { 433 Ppc4xxEbcState *ebc = opaque; 434 435 switch (dcrn) { 436 case EBC0_CFGADDR: 437 ebc->addr = val; 438 break; 439 case EBC0_CFGDATA: 440 switch (ebc->addr) { 441 case 0x00: /* B0CR */ 442 break; 443 case 0x01: /* B1CR */ 444 break; 445 case 0x02: /* B2CR */ 446 break; 447 case 0x03: /* B3CR */ 448 break; 449 case 0x04: /* B4CR */ 450 break; 451 case 0x05: /* B5CR */ 452 break; 453 case 0x06: /* B6CR */ 454 break; 455 case 0x07: /* B7CR */ 456 break; 457 case 0x10: /* B0AP */ 458 break; 459 case 0x11: /* B1AP */ 460 break; 461 case 0x12: /* B2AP */ 462 break; 463 case 0x13: /* B3AP */ 464 break; 465 case 0x14: /* B4AP */ 466 break; 467 case 0x15: /* B5AP */ 468 break; 469 case 0x16: /* B6AP */ 470 break; 471 case 0x17: /* B7AP */ 472 break; 473 case 0x20: /* BEAR */ 474 break; 475 case 0x21: /* BESR0 */ 476 break; 477 case 0x22: /* BESR1 */ 478 break; 479 case 0x23: /* CFG */ 480 break; 481 default: 482 break; 483 } 484 break; 485 default: 486 break; 487 } 488 } 489 490 static void ppc405_ebc_reset(DeviceState *dev) 491 { 492 Ppc4xxEbcState *ebc = PPC4xx_EBC(dev); 493 int i; 494 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; 501 } 502 ebc->besr0 = 0x00000000; 503 ebc->besr1 = 0x00000000; 504 ebc->cfg = 0x80400000; 505 } 506 507 static void ppc405_ebc_realize(DeviceState *dev, Error **errp) 508 { 509 Ppc4xxEbcState *ebc = PPC4xx_EBC(dev); 510 Ppc4xxDcrDeviceState *dcr = PPC4xx_DCR_DEVICE(dev); 511 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); 514 } 515 516 static void ppc405_ebc_class_init(ObjectClass *oc, void *data) 517 { 518 DeviceClass *dc = DEVICE_CLASS(oc); 519 520 dc->realize = ppc405_ebc_realize; 521 device_class_set_legacy_reset(dc, ppc405_ebc_reset); 522 /* Reason: only works as function of a ppc4xx SoC */ 523 dc->user_creatable = false; 524 } 525 526 /* PPC4xx_DCR_DEVICE */ 527 528 void ppc4xx_dcr_register(Ppc4xxDcrDeviceState *dev, int dcrn, void *opaque, 529 dcr_read_cb dcr_read, dcr_write_cb dcr_write) 530 { 531 assert(dev->cpu); 532 ppc_dcr_register(&dev->cpu->env, dcrn, opaque, dcr_read, dcr_write); 533 } 534 535 bool ppc4xx_dcr_realize(Ppc4xxDcrDeviceState *dev, PowerPCCPU *cpu, 536 Error **errp) 537 { 538 object_property_set_link(OBJECT(dev), "cpu", OBJECT(cpu), &error_abort); 539 return sysbus_realize(SYS_BUS_DEVICE(dev), errp); 540 } 541 542 static Property ppc4xx_dcr_properties[] = { 543 DEFINE_PROP_LINK("cpu", Ppc4xxDcrDeviceState, cpu, TYPE_POWERPC_CPU, 544 PowerPCCPU *), 545 DEFINE_PROP_END_OF_LIST(), 546 }; 547 548 static void ppc4xx_dcr_class_init(ObjectClass *oc, void *data) 549 { 550 DeviceClass *dc = DEVICE_CLASS(oc); 551 552 device_class_set_props(dc, ppc4xx_dcr_properties); 553 } 554 555 static const TypeInfo ppc4xx_types[] = { 556 { 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, 562 }, { 563 .name = TYPE_PPC4xx_PLB, 564 .parent = TYPE_PPC4xx_DCR_DEVICE, 565 .instance_size = sizeof(Ppc4xxPlbState), 566 .class_init = ppc405_plb_class_init, 567 }, { 568 .name = TYPE_PPC4xx_EBC, 569 .parent = TYPE_PPC4xx_DCR_DEVICE, 570 .instance_size = sizeof(Ppc4xxEbcState), 571 .class_init = ppc405_ebc_class_init, 572 }, { 573 .name = TYPE_PPC4xx_DCR_DEVICE, 574 .parent = TYPE_SYS_BUS_DEVICE, 575 .instance_size = sizeof(Ppc4xxDcrDeviceState), 576 .class_init = ppc4xx_dcr_class_init, 577 .abstract = true, 578 } 579 }; 580 581 DEFINE_TYPES(ppc4xx_types) 582