qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

ppc4xx_devs.c (16099B)


      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     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);
    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     dc->reset = 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     dc->reset = 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)