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