Revision e0dfe5b1

b/hw/openpic.c
56 56
        } \
57 57
    } while (0)
58 58

  
59
#define MAX_CPU     15
59
#define MAX_CPU     32
60 60
#define MAX_SRC     256
61 61
#define MAX_TMR     4
62 62
#define MAX_IPI     4
......
66 66

  
67 67
/* OpenPIC capability flags */
68 68
#define OPENPIC_FLAG_IDR_CRIT     (1 << 0)
69
#define OPENPIC_FLAG_ILR          (2 << 0)
69 70

  
70 71
/* OpenPIC address map */
71 72
#define OPENPIC_GLB_REG_START        0x0
......
74 75
#define OPENPIC_TMR_REG_SIZE         0x220
75 76
#define OPENPIC_MSI_REG_START        0x1600
76 77
#define OPENPIC_MSI_REG_SIZE         0x200
78
#define OPENPIC_SUMMARY_REG_START   0x3800
79
#define OPENPIC_SUMMARY_REG_SIZE    0x800
77 80
#define OPENPIC_SRC_REG_START        0x10000
78 81
#define OPENPIC_SRC_REG_SIZE         (MAX_SRC * 0x20)
79 82
#define OPENPIC_CPU_REG_START        0x20000
......
94 97
/* First doorbell IRQ */
95 98
#define RAVEN_DBL_IRQ    (RAVEN_IPI_IRQ + (RAVEN_MAX_CPU * RAVEN_MAX_IPI))
96 99

  
97
/* FSL_MPIC_20 */
98
#define FSL_MPIC_20_MAX_CPU      1
99
#define FSL_MPIC_20_MAX_EXT     12
100
#define FSL_MPIC_20_MAX_INT     64
101
#define FSL_MPIC_20_MAX_IRQ     MAX_IRQ
100
typedef struct FslMpicInfo {
101
    int max_ext;
102
} FslMpicInfo;
102 103

  
103
/* Interrupt definitions */
104
/* IRQs, accessible through the IRQ region */
105
#define FSL_MPIC_20_EXT_IRQ      0x00
106
#define FSL_MPIC_20_INT_IRQ      0x10
107
#define FSL_MPIC_20_MSG_IRQ      0xb0
108
#define FSL_MPIC_20_MSI_IRQ      0xe0
109
/* These are available through separate regions, but
110
   for simplicity's sake mapped into the same number space */
111
#define FSL_MPIC_20_TMR_IRQ      0x100
112
#define FSL_MPIC_20_IPI_IRQ      0x104
104
static FslMpicInfo fsl_mpic_20 = {
105
    .max_ext = 12,
106
};
113 107

  
114
/*
115
 * Block Revision Register1 (BRR1): QEMU does not fully emulate
116
 * any version on MPIC. So to start with, set the IP version to 0.
117
 *
118
 * NOTE: This is Freescale MPIC specific register. Keep it here till
119
 * this code is refactored for different variants of OPENPIC and MPIC.
120
 */
121
#define FSL_BRR1_IPID (0x0040 << 16) /* 16 bit IP-block ID */
122
#define FSL_BRR1_IPMJ (0x00 << 8) /* 8 bit IP major number */
123
#define FSL_BRR1_IPMN 0x00 /* 8 bit IP minor number */
108
static FslMpicInfo fsl_mpic_42 = {
109
    .max_ext = 12,
110
};
124 111

  
125 112
#define FRR_NIRQ_SHIFT    16
126 113
#define FRR_NCPU_SHIFT     8
......
146 133
#define IDR_P1_SHIFT      1
147 134
#define IDR_P0_SHIFT      0
148 135

  
136
#define ILR_INTTGT_MASK   0x000000ff
137
#define ILR_INTTGT_INT    0x00
138
#define ILR_INTTGT_CINT   0x01 /* critical */
139
#define ILR_INTTGT_MCP    0x02 /* machine check */
140

  
141
/* The currently supported INTTGT values happen to be the same as QEMU's
142
 * openpic output codes, but don't depend on this.  The output codes
143
 * could change (unlikely, but...) or support could be added for
144
 * more INTTGT values.
145
 */
146
static const int inttgt_output[][2] = {
147
    { ILR_INTTGT_INT, OPENPIC_OUTPUT_INT },
148
    { ILR_INTTGT_CINT, OPENPIC_OUTPUT_CINT },
149
    { ILR_INTTGT_MCP, OPENPIC_OUTPUT_MCK },
150
};
151

  
152
static int inttgt_to_output(int inttgt)
153
{
154
    int i;
155

  
156
    for (i = 0; i < ARRAY_SIZE(inttgt_output); i++) {
157
        if (inttgt_output[i][0] == inttgt) {
158
            return inttgt_output[i][1];
159
        }
160
    }
161

  
162
    fprintf(stderr, "%s: unsupported inttgt %d\n", __func__, inttgt);
163
    return OPENPIC_OUTPUT_INT;
164
}
165

  
166
static int output_to_inttgt(int output)
167
{
168
    int i;
169

  
170
    for (i = 0; i < ARRAY_SIZE(inttgt_output); i++) {
171
        if (inttgt_output[i][1] == output) {
172
            return inttgt_output[i][0];
173
        }
174
    }
175

  
176
    abort();
177
}
178

  
149 179
#define MSIIR_OFFSET       0x140
150 180
#define MSIIR_SRS_SHIFT    29
151 181
#define MSIIR_SRS_MASK     (0x7 << MSIIR_SRS_SHIFT)
......
230 260
    MemoryRegion mem;
231 261

  
232 262
    /* Behavior control */
263
    FslMpicInfo *fsl;
233 264
    uint32_t model;
234 265
    uint32_t flags;
235 266
    uint32_t nb_irqs;
......
243 274
    uint32_t mpic_mode_mask;
244 275

  
245 276
    /* Sub-regions */
246
    MemoryRegion sub_io_mem[5];
277
    MemoryRegion sub_io_mem[6];
247 278

  
248 279
    /* Global registers */
249 280
    uint32_t frr; /* Feature reporting register */
......
558 589
    return opp->src[n_IRQ].idr;
559 590
}
560 591

  
592
static inline uint32_t read_IRQreg_ilr(OpenPICState *opp, int n_IRQ)
593
{
594
    if (opp->flags & OPENPIC_FLAG_ILR) {
595
        return output_to_inttgt(opp->src[n_IRQ].output);
596
    }
597

  
598
    return 0xffffffff;
599
}
600

  
561 601
static inline uint32_t read_IRQreg_ivpr(OpenPICState *opp, int n_IRQ)
562 602
{
563 603
    return opp->src[n_IRQ].ivpr;
......
608 648
    }
609 649
}
610 650

  
651
static inline void write_IRQreg_ilr(OpenPICState *opp, int n_IRQ, uint32_t val)
652
{
653
    if (opp->flags & OPENPIC_FLAG_ILR) {
654
        IRQSource *src = &opp->src[n_IRQ];
655

  
656
        src->output = inttgt_to_output(val & ILR_INTTGT_MASK);
657
        DPRINTF("Set ILR %d to 0x%08x, output %d\n", n_IRQ, src->idr,
658
                src->output);
659

  
660
        /* TODO: on MPIC v4.0 only, set nomask for non-INT */
661
    }
662
}
663

  
611 664
static inline void write_IRQreg_ivpr(OpenPICState *opp, int n_IRQ, uint32_t val)
612 665
{
613 666
    uint32_t mask;
......
874 927

  
875 928
    DPRINTF("%s: addr %#" HWADDR_PRIx " <= %08" PRIx64 "\n",
876 929
            __func__, addr, val);
877
    if (addr & 0xF) {
878
        return;
879
    }
880
    addr = addr & 0xFFF0;
930

  
931
    addr = addr & 0xffff;
881 932
    idx = addr >> 5;
882
    if (addr & 0x10) {
883
        /* EXDE / IFEDE / IEEDE */
884
        write_IRQreg_idr(opp, idx, val);
885
    } else {
886
        /* EXVP / IFEVP / IEEVP */
933

  
934
    switch (addr & 0x1f) {
935
    case 0x00:
887 936
        write_IRQreg_ivpr(opp, idx, val);
937
        break;
938
    case 0x10:
939
        write_IRQreg_idr(opp, idx, val);
940
        break;
941
    case 0x18:
942
        write_IRQreg_ilr(opp, idx, val);
943
        break;
888 944
    }
889 945
}
890 946

  
......
896 952

  
897 953
    DPRINTF("%s: addr %#" HWADDR_PRIx "\n", __func__, addr);
898 954
    retval = 0xFFFFFFFF;
899
    if (addr & 0xF) {
900
        return retval;
901
    }
902
    addr = addr & 0xFFF0;
955

  
956
    addr = addr & 0xffff;
903 957
    idx = addr >> 5;
904
    if (addr & 0x10) {
905
        /* EXDE / IFEDE / IEEDE */
906
        retval = read_IRQreg_idr(opp, idx);
907
    } else {
908
        /* EXVP / IFEVP / IEEVP */
958

  
959
    switch (addr & 0x1f) {
960
    case 0x00:
909 961
        retval = read_IRQreg_ivpr(opp, idx);
962
        break;
963
    case 0x10:
964
        retval = read_IRQreg_idr(opp, idx);
965
        break;
966
    case 0x18:
967
        retval = read_IRQreg_ilr(opp, idx);
968
        break;
910 969
    }
911
    DPRINTF("%s: => 0x%08x\n", __func__, retval);
912 970

  
971
    DPRINTF("%s: => 0x%08x\n", __func__, retval);
913 972
    return retval;
914 973
}
915 974

  
......
977 1036
    return r;
978 1037
}
979 1038

  
1039
static uint64_t openpic_summary_read(void *opaque, hwaddr addr, unsigned size)
1040
{
1041
    uint64_t r = 0;
1042

  
1043
    DPRINTF("%s: addr %#" HWADDR_PRIx "\n", __func__, addr);
1044

  
1045
    /* TODO: EISR/EIMR */
1046

  
1047
    return r;
1048
}
1049

  
1050
static void openpic_summary_write(void *opaque, hwaddr addr, uint64_t val,
1051
                                  unsigned size)
1052
{
1053
    DPRINTF("%s: addr %#" HWADDR_PRIx " <= 0x%08" PRIx64 "\n",
1054
            __func__, addr, val);
1055

  
1056
    /* TODO: EISR/EIMR */
1057
}
1058

  
980 1059
static void openpic_cpu_write_internal(void *opaque, hwaddr addr,
981 1060
                                       uint32_t val, int idx)
982 1061
{
......
1242 1321
    },
1243 1322
};
1244 1323

  
1245
static const MemoryRegionOps openpic_msi_ops_le = {
1324
static const MemoryRegionOps openpic_msi_ops_be = {
1246 1325
    .read = openpic_msi_read,
1247 1326
    .write = openpic_msi_write,
1248
    .endianness = DEVICE_LITTLE_ENDIAN,
1327
    .endianness = DEVICE_BIG_ENDIAN,
1249 1328
    .impl = {
1250 1329
        .min_access_size = 4,
1251 1330
        .max_access_size = 4,
1252 1331
    },
1253 1332
};
1254 1333

  
1255
static const MemoryRegionOps openpic_msi_ops_be = {
1256
    .read = openpic_msi_read,
1257
    .write = openpic_msi_write,
1334
static const MemoryRegionOps openpic_summary_ops_be = {
1335
    .read = openpic_summary_read,
1336
    .write = openpic_summary_write,
1258 1337
    .endianness = DEVICE_BIG_ENDIAN,
1259 1338
    .impl = {
1260 1339
        .min_access_size = 4,
......
1387 1466
typedef struct MemReg {
1388 1467
    const char             *name;
1389 1468
    MemoryRegionOps const  *ops;
1390
    bool                   map;
1391 1469
    hwaddr      start_addr;
1392 1470
    ram_addr_t              size;
1393 1471
} MemReg;
1394 1472

  
1473
static void fsl_common_init(OpenPICState *opp)
1474
{
1475
    int i;
1476
    int virq = MAX_SRC;
1477

  
1478
    opp->vid = VID_REVISION_1_2;
1479
    opp->vir = VIR_GENERIC;
1480
    opp->vector_mask = 0xFFFF;
1481
    opp->tfrr_reset = 0;
1482
    opp->ivpr_reset = IVPR_MASK_MASK;
1483
    opp->idr_reset = 1 << 0;
1484
    opp->max_irq = MAX_IRQ;
1485

  
1486
    opp->irq_ipi0 = virq;
1487
    virq += MAX_IPI;
1488
    opp->irq_tim0 = virq;
1489
    virq += MAX_TMR;
1490

  
1491
    assert(virq <= MAX_IRQ);
1492

  
1493
    opp->irq_msi = 224;
1494

  
1495
    msi_supported = true;
1496
    for (i = 0; i < opp->fsl->max_ext; i++) {
1497
        opp->src[i].level = false;
1498
    }
1499

  
1500
    /* Internal interrupts, including message and MSI */
1501
    for (i = 16; i < MAX_SRC; i++) {
1502
        opp->src[i].type = IRQ_TYPE_FSLINT;
1503
        opp->src[i].level = true;
1504
    }
1505

  
1506
    /* timers and IPIs */
1507
    for (i = MAX_SRC; i < virq; i++) {
1508
        opp->src[i].type = IRQ_TYPE_FSLSPECIAL;
1509
        opp->src[i].level = false;
1510
    }
1511
}
1512

  
1513
static void map_list(OpenPICState *opp, const MemReg *list, int *count)
1514
{
1515
    while (list->name) {
1516
        assert(*count < ARRAY_SIZE(opp->sub_io_mem));
1517

  
1518
        memory_region_init_io(&opp->sub_io_mem[*count], list->ops, opp,
1519
                              list->name, list->size);
1520

  
1521
        memory_region_add_subregion(&opp->mem, list->start_addr,
1522
                                    &opp->sub_io_mem[*count]);
1523

  
1524
        (*count)++;
1525
        list++;
1526
    }
1527
}
1528

  
1395 1529
static int openpic_init(SysBusDevice *dev)
1396 1530
{
1397 1531
    OpenPICState *opp = FROM_SYSBUS(typeof (*opp), dev);
1398 1532
    int i, j;
1399
    MemReg list_le[] = {
1400
        {"glb", &openpic_glb_ops_le, true,
1533
    int list_count = 0;
1534
    static const MemReg list_le[] = {
1535
        {"glb", &openpic_glb_ops_le,
1401 1536
                OPENPIC_GLB_REG_START, OPENPIC_GLB_REG_SIZE},
1402
        {"tmr", &openpic_tmr_ops_le, true,
1537
        {"tmr", &openpic_tmr_ops_le,
1403 1538
                OPENPIC_TMR_REG_START, OPENPIC_TMR_REG_SIZE},
1404
        {"msi", &openpic_msi_ops_le, true,
1405
                OPENPIC_MSI_REG_START, OPENPIC_MSI_REG_SIZE},
1406
        {"src", &openpic_src_ops_le, true,
1539
        {"src", &openpic_src_ops_le,
1407 1540
                OPENPIC_SRC_REG_START, OPENPIC_SRC_REG_SIZE},
1408
        {"cpu", &openpic_cpu_ops_le, true,
1541
        {"cpu", &openpic_cpu_ops_le,
1409 1542
                OPENPIC_CPU_REG_START, OPENPIC_CPU_REG_SIZE},
1543
        {NULL}
1410 1544
    };
1411
    MemReg list_be[] = {
1412
        {"glb", &openpic_glb_ops_be, true,
1545
    static const MemReg list_be[] = {
1546
        {"glb", &openpic_glb_ops_be,
1413 1547
                OPENPIC_GLB_REG_START, OPENPIC_GLB_REG_SIZE},
1414
        {"tmr", &openpic_tmr_ops_be, true,
1548
        {"tmr", &openpic_tmr_ops_be,
1415 1549
                OPENPIC_TMR_REG_START, OPENPIC_TMR_REG_SIZE},
1416
        {"msi", &openpic_msi_ops_be, true,
1417
                OPENPIC_MSI_REG_START, OPENPIC_MSI_REG_SIZE},
1418
        {"src", &openpic_src_ops_be, true,
1550
        {"src", &openpic_src_ops_be,
1419 1551
                OPENPIC_SRC_REG_START, OPENPIC_SRC_REG_SIZE},
1420
        {"cpu", &openpic_cpu_ops_be, true,
1552
        {"cpu", &openpic_cpu_ops_be,
1421 1553
                OPENPIC_CPU_REG_START, OPENPIC_CPU_REG_SIZE},
1554
        {NULL}
1422 1555
    };
1423
    MemReg *list;
1556
    static const MemReg list_fsl[] = {
1557
        {"msi", &openpic_msi_ops_be,
1558
                OPENPIC_MSI_REG_START, OPENPIC_MSI_REG_SIZE},
1559
        {"summary", &openpic_summary_ops_be,
1560
                OPENPIC_SUMMARY_REG_START, OPENPIC_SUMMARY_REG_SIZE},
1561
        {NULL}
1562
    };
1563

  
1564
    memory_region_init(&opp->mem, "openpic", 0x40000);
1424 1565

  
1425 1566
    switch (opp->model) {
1426 1567
    case OPENPIC_MODEL_FSL_MPIC_20:
1427 1568
    default:
1569
        opp->fsl = &fsl_mpic_20;
1570
        opp->brr1 = 0x00400200;
1428 1571
        opp->flags |= OPENPIC_FLAG_IDR_CRIT;
1429 1572
        opp->nb_irqs = 80;
1430
        opp->vid = VID_REVISION_1_2;
1431
        opp->vir = VIR_GENERIC;
1432
        opp->vector_mask = 0xFFFF;
1433
        opp->tfrr_reset = 0;
1434
        opp->ivpr_reset = IVPR_MASK_MASK;
1435
        opp->idr_reset = 1 << 0;
1436
        opp->max_irq = FSL_MPIC_20_MAX_IRQ;
1437
        opp->irq_ipi0 = FSL_MPIC_20_IPI_IRQ;
1438
        opp->irq_tim0 = FSL_MPIC_20_TMR_IRQ;
1439
        opp->irq_msi = FSL_MPIC_20_MSI_IRQ;
1440
        opp->brr1 = FSL_BRR1_IPID | FSL_BRR1_IPMJ | FSL_BRR1_IPMN;
1441
        /* XXX really only available as of MPIC 4.0 */
1442
        opp->mpic_mode_mask = GCR_MODE_PROXY;
1573
        opp->mpic_mode_mask = GCR_MODE_MIXED;
1443 1574

  
1444
        msi_supported = true;
1445
        list = list_be;
1575
        fsl_common_init(opp);
1576
        map_list(opp, list_be, &list_count);
1577
        map_list(opp, list_fsl, &list_count);
1446 1578

  
1447
        for (i = 0; i < FSL_MPIC_20_MAX_EXT; i++) {
1448
            opp->src[i].level = false;
1449
        }
1579
        break;
1450 1580

  
1451
        /* Internal interrupts, including message and MSI */
1452
        for (i = 16; i < MAX_SRC; i++) {
1453
            opp->src[i].type = IRQ_TYPE_FSLINT;
1454
            opp->src[i].level = true;
1455
        }
1581
    case OPENPIC_MODEL_FSL_MPIC_42:
1582
        opp->fsl = &fsl_mpic_42;
1583
        opp->brr1 = 0x00400402;
1584
        opp->flags |= OPENPIC_FLAG_ILR;
1585
        opp->nb_irqs = 196;
1586
        opp->mpic_mode_mask = GCR_MODE_PROXY;
1456 1587

  
1457
        /* timers and IPIs */
1458
        for (i = MAX_SRC; i < MAX_IRQ; i++) {
1459
            opp->src[i].type = IRQ_TYPE_FSLSPECIAL;
1460
            opp->src[i].level = false;
1461
        }
1588
        fsl_common_init(opp);
1589
        map_list(opp, list_be, &list_count);
1590
        map_list(opp, list_fsl, &list_count);
1462 1591

  
1463 1592
        break;
1464 1593

  
......
1475 1604
        opp->irq_tim0 = RAVEN_TMR_IRQ;
1476 1605
        opp->brr1 = -1;
1477 1606
        opp->mpic_mode_mask = GCR_MODE_MIXED;
1478
        list = list_le;
1479
        /* Don't map MSI region */
1480
        list[2].map = false;
1481 1607

  
1482 1608
        /* Only UP supported today */
1483 1609
        if (opp->nb_cpus != 1) {
1484 1610
            return -EINVAL;
1485 1611
        }
1486
        break;
1487
    }
1488

  
1489
    memory_region_init(&opp->mem, "openpic", 0x40000);
1490 1612

  
1491
    for (i = 0; i < ARRAY_SIZE(list_le); i++) {
1492
        if (!list[i].map) {
1493
            continue;
1494
        }
1495

  
1496
        memory_region_init_io(&opp->sub_io_mem[i], list[i].ops, opp,
1497
                              list[i].name, list[i].size);
1498

  
1499
        memory_region_add_subregion(&opp->mem, list[i].start_addr,
1500
                                    &opp->sub_io_mem[i]);
1613
        map_list(opp, list_le, &list_count);
1614
        break;
1501 1615
    }
1502 1616

  
1503 1617
    for (i = 0; i < opp->nb_cpus; i++) {
b/hw/openpic.h
13 13

  
14 14
#define OPENPIC_MODEL_RAVEN       0
15 15
#define OPENPIC_MODEL_FSL_MPIC_20 1
16
#define OPENPIC_MODEL_FSL_MPIC_42 2
16 17

  
17 18
#endif /* __OPENPIC_H__ */

Also available in: Unified diff