xref: /openbmc/qemu/hw/xtensa/mx_pic.c (revision c6f3f334)
110df8ff1SMax Filippov /*
210df8ff1SMax Filippov  * Copyright (c) 2013 - 2019, Max Filippov, Open Source and Linux Lab.
310df8ff1SMax Filippov  * All rights reserved.
410df8ff1SMax Filippov  *
510df8ff1SMax Filippov  * Redistribution and use in source and binary forms, with or without
610df8ff1SMax Filippov  * modification, are permitted provided that the following conditions are met:
710df8ff1SMax Filippov  *     * Redistributions of source code must retain the above copyright
810df8ff1SMax Filippov  *       notice, this list of conditions and the following disclaimer.
910df8ff1SMax Filippov  *     * Redistributions in binary form must reproduce the above copyright
1010df8ff1SMax Filippov  *       notice, this list of conditions and the following disclaimer in the
1110df8ff1SMax Filippov  *       documentation and/or other materials provided with the distribution.
1210df8ff1SMax Filippov  *     * Neither the name of the Open Source and Linux Lab nor the
1310df8ff1SMax Filippov  *       names of its contributors may be used to endorse or promote products
1410df8ff1SMax Filippov  *       derived from this software without specific prior written permission.
1510df8ff1SMax Filippov  *
1610df8ff1SMax Filippov  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
1710df8ff1SMax Filippov  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1810df8ff1SMax Filippov  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1910df8ff1SMax Filippov  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
2010df8ff1SMax Filippov  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
2110df8ff1SMax Filippov  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
2210df8ff1SMax Filippov  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
2310df8ff1SMax Filippov  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2410df8ff1SMax Filippov  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
2510df8ff1SMax Filippov  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2610df8ff1SMax Filippov  */
2710df8ff1SMax Filippov 
2810df8ff1SMax Filippov #include "qemu/osdep.h"
2964552b6bSMarkus Armbruster #include "hw/irq.h"
3010df8ff1SMax Filippov #include "hw/xtensa/mx_pic.h"
3110df8ff1SMax Filippov #include "qemu/log.h"
3210df8ff1SMax Filippov 
3310df8ff1SMax Filippov #define MX_MAX_CPU 32
3410df8ff1SMax Filippov #define MX_MAX_IRQ 32
3510df8ff1SMax Filippov 
3610df8ff1SMax Filippov #define MIROUT 0x0
3710df8ff1SMax Filippov #define MIPICAUSE 0x100
3810df8ff1SMax Filippov #define MIPISET 0x140
3910df8ff1SMax Filippov #define MIENG 0x180
4010df8ff1SMax Filippov #define MIENGSET 0x184
4110df8ff1SMax Filippov #define MIASG 0x188
4210df8ff1SMax Filippov #define MIASGSET 0x18c
4310df8ff1SMax Filippov #define MIPIPART 0x190
4410df8ff1SMax Filippov #define SYSCFGID 0x1a0
4510df8ff1SMax Filippov #define MPSCORE 0x200
4610df8ff1SMax Filippov #define CCON 0x220
4710df8ff1SMax Filippov 
4810df8ff1SMax Filippov struct XtensaMxPic {
4910df8ff1SMax Filippov     unsigned n_cpu;
5010df8ff1SMax Filippov     unsigned n_irq;
5110df8ff1SMax Filippov 
5210df8ff1SMax Filippov     uint32_t ext_irq_state;
5310df8ff1SMax Filippov     uint32_t mieng;
5410df8ff1SMax Filippov     uint32_t miasg;
5510df8ff1SMax Filippov     uint32_t mirout[MX_MAX_IRQ];
5610df8ff1SMax Filippov     uint32_t mipipart;
5710df8ff1SMax Filippov     uint32_t runstall;
5810df8ff1SMax Filippov 
5910df8ff1SMax Filippov     qemu_irq *irq_inputs;
6010df8ff1SMax Filippov     struct XtensaMxPicCpu {
6110df8ff1SMax Filippov         XtensaMxPic *mx;
6210df8ff1SMax Filippov         qemu_irq *irq;
6310df8ff1SMax Filippov         qemu_irq runstall;
6410df8ff1SMax Filippov         uint32_t mipicause;
6510df8ff1SMax Filippov         uint32_t mirout_cache;
6610df8ff1SMax Filippov         uint32_t irq_state_cache;
6710df8ff1SMax Filippov         uint32_t ccon;
6810df8ff1SMax Filippov         MemoryRegion reg;
6910df8ff1SMax Filippov     } cpu[MX_MAX_CPU];
7010df8ff1SMax Filippov };
7110df8ff1SMax Filippov 
xtensa_mx_pic_ext_reg_read(void * opaque,hwaddr offset,unsigned size)7210df8ff1SMax Filippov static uint64_t xtensa_mx_pic_ext_reg_read(void *opaque, hwaddr offset,
7310df8ff1SMax Filippov                                            unsigned size)
7410df8ff1SMax Filippov {
7510df8ff1SMax Filippov     struct XtensaMxPicCpu *mx_cpu = opaque;
7610df8ff1SMax Filippov     struct XtensaMxPic *mx = mx_cpu->mx;
7710df8ff1SMax Filippov 
7810df8ff1SMax Filippov     if (offset < MIROUT + MX_MAX_IRQ) {
7910df8ff1SMax Filippov         return mx->mirout[offset - MIROUT];
8010df8ff1SMax Filippov     } else if (offset >= MIPICAUSE && offset < MIPICAUSE + MX_MAX_CPU) {
8110df8ff1SMax Filippov         return mx->cpu[offset - MIPICAUSE].mipicause;
8210df8ff1SMax Filippov     } else {
8310df8ff1SMax Filippov         switch (offset) {
8410df8ff1SMax Filippov         case MIENG:
8510df8ff1SMax Filippov             return mx->mieng;
8610df8ff1SMax Filippov 
8710df8ff1SMax Filippov         case MIASG:
8810df8ff1SMax Filippov             return mx->miasg;
8910df8ff1SMax Filippov 
9010df8ff1SMax Filippov         case MIPIPART:
9110df8ff1SMax Filippov             return mx->mipipart;
9210df8ff1SMax Filippov 
9310df8ff1SMax Filippov         case SYSCFGID:
9410df8ff1SMax Filippov             return ((mx->n_cpu - 1) << 18) | (mx_cpu - mx->cpu);
9510df8ff1SMax Filippov 
9610df8ff1SMax Filippov         case MPSCORE:
9710df8ff1SMax Filippov             return mx->runstall;
9810df8ff1SMax Filippov 
9910df8ff1SMax Filippov         case CCON:
10010df8ff1SMax Filippov             return mx_cpu->ccon;
10110df8ff1SMax Filippov 
10210df8ff1SMax Filippov         default:
10310df8ff1SMax Filippov             qemu_log_mask(LOG_GUEST_ERROR,
10410df8ff1SMax Filippov                           "unknown RER in MX PIC range: 0x%08x\n",
10510df8ff1SMax Filippov                           (uint32_t)offset);
10610df8ff1SMax Filippov             return 0;
10710df8ff1SMax Filippov         }
10810df8ff1SMax Filippov     }
10910df8ff1SMax Filippov }
11010df8ff1SMax Filippov 
xtensa_mx_pic_get_ipi_for_cpu(const XtensaMxPic * mx,unsigned cpu)11110df8ff1SMax Filippov static uint32_t xtensa_mx_pic_get_ipi_for_cpu(const XtensaMxPic *mx,
11210df8ff1SMax Filippov                                               unsigned cpu)
11310df8ff1SMax Filippov {
11410df8ff1SMax Filippov     uint32_t mipicause = mx->cpu[cpu].mipicause;
11510df8ff1SMax Filippov     uint32_t mipipart = mx->mipipart;
11610df8ff1SMax Filippov 
11710df8ff1SMax Filippov     return (((mipicause & 1) << (mipipart & 3)) |
11810df8ff1SMax Filippov             ((mipicause & 0x000e) != 0) << ((mipipart >> 2) & 3) |
11910df8ff1SMax Filippov             ((mipicause & 0x00f0) != 0) << ((mipipart >> 4) & 3) |
12010df8ff1SMax Filippov             ((mipicause & 0xff00) != 0) << ((mipipart >> 6) & 3)) & 0x7;
12110df8ff1SMax Filippov }
12210df8ff1SMax Filippov 
xtensa_mx_pic_get_ext_irq_for_cpu(const XtensaMxPic * mx,unsigned cpu)12310df8ff1SMax Filippov static uint32_t xtensa_mx_pic_get_ext_irq_for_cpu(const XtensaMxPic *mx,
12410df8ff1SMax Filippov                                                   unsigned cpu)
12510df8ff1SMax Filippov {
12610df8ff1SMax Filippov     return ((((mx->ext_irq_state & mx->mieng) | mx->miasg) &
12710df8ff1SMax Filippov              mx->cpu[cpu].mirout_cache) << 2) |
12810df8ff1SMax Filippov         xtensa_mx_pic_get_ipi_for_cpu(mx, cpu);
12910df8ff1SMax Filippov }
13010df8ff1SMax Filippov 
xtensa_mx_pic_update_cpu(XtensaMxPic * mx,unsigned cpu)13110df8ff1SMax Filippov static void xtensa_mx_pic_update_cpu(XtensaMxPic *mx, unsigned cpu)
13210df8ff1SMax Filippov {
13310df8ff1SMax Filippov     uint32_t irq = xtensa_mx_pic_get_ext_irq_for_cpu(mx, cpu);
13410df8ff1SMax Filippov     uint32_t changed_irq = mx->cpu[cpu].irq_state_cache ^ irq;
13510df8ff1SMax Filippov     unsigned i;
13610df8ff1SMax Filippov 
13710df8ff1SMax Filippov     qemu_log_mask(CPU_LOG_INT, "%s: CPU %d, irq: %08x, changed_irq: %08x\n",
13810df8ff1SMax Filippov                   __func__, cpu, irq, changed_irq);
13910df8ff1SMax Filippov     mx->cpu[cpu].irq_state_cache = irq;
14010df8ff1SMax Filippov     for (i = 0; changed_irq; ++i) {
14110df8ff1SMax Filippov         uint32_t mask = 1u << i;
14210df8ff1SMax Filippov 
14310df8ff1SMax Filippov         if (changed_irq & mask) {
14410df8ff1SMax Filippov             changed_irq ^= mask;
14510df8ff1SMax Filippov             qemu_set_irq(mx->cpu[cpu].irq[i], irq & mask);
14610df8ff1SMax Filippov         }
14710df8ff1SMax Filippov     }
14810df8ff1SMax Filippov }
14910df8ff1SMax Filippov 
xtensa_mx_pic_update_all(XtensaMxPic * mx)15010df8ff1SMax Filippov static void xtensa_mx_pic_update_all(XtensaMxPic *mx)
15110df8ff1SMax Filippov {
15210df8ff1SMax Filippov     unsigned cpu;
15310df8ff1SMax Filippov 
15410df8ff1SMax Filippov     for (cpu = 0; cpu < mx->n_cpu; ++cpu) {
15510df8ff1SMax Filippov         xtensa_mx_pic_update_cpu(mx, cpu);
15610df8ff1SMax Filippov     }
15710df8ff1SMax Filippov }
15810df8ff1SMax Filippov 
xtensa_mx_pic_ext_reg_write(void * opaque,hwaddr offset,uint64_t v,unsigned size)15910df8ff1SMax Filippov static void xtensa_mx_pic_ext_reg_write(void *opaque, hwaddr offset,
16010df8ff1SMax Filippov                                         uint64_t v, unsigned size)
16110df8ff1SMax Filippov {
16210df8ff1SMax Filippov     struct XtensaMxPicCpu *mx_cpu = opaque;
16310df8ff1SMax Filippov     struct XtensaMxPic *mx = mx_cpu->mx;
16410df8ff1SMax Filippov     unsigned cpu;
16510df8ff1SMax Filippov 
16610df8ff1SMax Filippov     if (offset < MIROUT + mx->n_irq) {
16710df8ff1SMax Filippov         mx->mirout[offset - MIROUT] = v;
16810df8ff1SMax Filippov         for (cpu = 0; cpu < mx->n_cpu; ++cpu) {
16910df8ff1SMax Filippov             uint32_t mask = 1u << (offset - MIROUT);
17010df8ff1SMax Filippov 
17110df8ff1SMax Filippov             if (!(mx->cpu[cpu].mirout_cache & mask) != !(v & (1u << cpu))) {
17210df8ff1SMax Filippov                 mx->cpu[cpu].mirout_cache ^= mask;
17310df8ff1SMax Filippov                 xtensa_mx_pic_update_cpu(mx, cpu);
17410df8ff1SMax Filippov             }
17510df8ff1SMax Filippov         }
17610df8ff1SMax Filippov     } else if (offset >= MIPICAUSE && offset < MIPICAUSE + mx->n_cpu) {
17710df8ff1SMax Filippov         cpu = offset - MIPICAUSE;
17810df8ff1SMax Filippov         mx->cpu[cpu].mipicause &= ~v;
17910df8ff1SMax Filippov         xtensa_mx_pic_update_cpu(mx, cpu);
18010df8ff1SMax Filippov     } else if (offset >= MIPISET && offset < MIPISET + 16) {
18110df8ff1SMax Filippov         for (cpu = 0; cpu < mx->n_cpu; ++cpu) {
18210df8ff1SMax Filippov             if (v & (1u << cpu)) {
18310df8ff1SMax Filippov                 mx->cpu[cpu].mipicause |= 1u << (offset - MIPISET);
18410df8ff1SMax Filippov                 xtensa_mx_pic_update_cpu(mx, cpu);
18510df8ff1SMax Filippov             }
18610df8ff1SMax Filippov         }
18710df8ff1SMax Filippov     } else {
18810df8ff1SMax Filippov         uint32_t change = 0;
18910df8ff1SMax Filippov         uint32_t oldv, newv;
19010df8ff1SMax Filippov         const char *name = "???";
19110df8ff1SMax Filippov 
19210df8ff1SMax Filippov         switch (offset) {
19310df8ff1SMax Filippov         case MIENG:
19410df8ff1SMax Filippov             change = mx->mieng & v;
19510df8ff1SMax Filippov             oldv = mx->mieng;
19610df8ff1SMax Filippov             mx->mieng &= ~v;
19710df8ff1SMax Filippov             newv = mx->mieng;
19810df8ff1SMax Filippov             name = "MIENG";
19910df8ff1SMax Filippov             break;
20010df8ff1SMax Filippov 
20110df8ff1SMax Filippov         case MIENGSET:
20210df8ff1SMax Filippov             change = ~mx->mieng & v;
20310df8ff1SMax Filippov             oldv = mx->mieng;
20410df8ff1SMax Filippov             mx->mieng |= v;
20510df8ff1SMax Filippov             newv = mx->mieng;
20610df8ff1SMax Filippov             name = "MIENG";
20710df8ff1SMax Filippov             break;
20810df8ff1SMax Filippov 
20910df8ff1SMax Filippov         case MIASG:
21010df8ff1SMax Filippov             change = mx->miasg & v;
21110df8ff1SMax Filippov             oldv = mx->miasg;
21210df8ff1SMax Filippov             mx->miasg &= ~v;
21310df8ff1SMax Filippov             newv = mx->miasg;
21410df8ff1SMax Filippov             name = "MIASG";
21510df8ff1SMax Filippov             break;
21610df8ff1SMax Filippov 
21710df8ff1SMax Filippov         case MIASGSET:
21810df8ff1SMax Filippov             change = ~mx->miasg & v;
21910df8ff1SMax Filippov             oldv = mx->miasg;
22010df8ff1SMax Filippov             mx->miasg |= v;
22110df8ff1SMax Filippov             newv = mx->miasg;
22210df8ff1SMax Filippov             name = "MIASG";
22310df8ff1SMax Filippov             break;
22410df8ff1SMax Filippov 
22510df8ff1SMax Filippov         case MIPIPART:
22610df8ff1SMax Filippov             change = mx->mipipart ^ v;
22710df8ff1SMax Filippov             oldv = mx->mipipart;
22810df8ff1SMax Filippov             mx->mipipart = v;
22910df8ff1SMax Filippov             newv = mx->mipipart;
23010df8ff1SMax Filippov             name = "MIPIPART";
23110df8ff1SMax Filippov             break;
23210df8ff1SMax Filippov 
23310df8ff1SMax Filippov         case MPSCORE:
23410df8ff1SMax Filippov             change = mx->runstall ^ v;
23510df8ff1SMax Filippov             oldv = mx->runstall;
23610df8ff1SMax Filippov             mx->runstall = v;
23710df8ff1SMax Filippov             newv = mx->runstall;
23810df8ff1SMax Filippov             name = "RUNSTALL";
23910df8ff1SMax Filippov             for (cpu = 0; cpu < mx->n_cpu; ++cpu) {
24010df8ff1SMax Filippov                 if (change & (1u << cpu)) {
24110df8ff1SMax Filippov                     qemu_set_irq(mx->cpu[cpu].runstall, v & (1u << cpu));
24210df8ff1SMax Filippov                 }
24310df8ff1SMax Filippov             }
24410df8ff1SMax Filippov             break;
24510df8ff1SMax Filippov 
24610df8ff1SMax Filippov         case CCON:
24710df8ff1SMax Filippov             mx_cpu->ccon = v & 0x1;
24810df8ff1SMax Filippov             break;
24910df8ff1SMax Filippov 
25010df8ff1SMax Filippov         default:
25110df8ff1SMax Filippov             qemu_log_mask(LOG_GUEST_ERROR,
25210df8ff1SMax Filippov                           "unknown WER in MX PIC range: 0x%08x = 0x%08x\n",
25310df8ff1SMax Filippov                           (uint32_t)offset, (uint32_t)v);
25410df8ff1SMax Filippov             break;
25510df8ff1SMax Filippov         }
25610df8ff1SMax Filippov         if (change) {
25710df8ff1SMax Filippov             qemu_log_mask(CPU_LOG_INT,
25810df8ff1SMax Filippov                           "%s: %s changed by CPU %d: %08x -> %08x\n",
25910df8ff1SMax Filippov                           __func__, name, (int)(mx_cpu - mx->cpu),
26010df8ff1SMax Filippov                           oldv, newv);
26110df8ff1SMax Filippov             xtensa_mx_pic_update_all(mx);
26210df8ff1SMax Filippov         }
26310df8ff1SMax Filippov     }
26410df8ff1SMax Filippov }
26510df8ff1SMax Filippov 
26610df8ff1SMax Filippov static const MemoryRegionOps xtensa_mx_pic_ops = {
26710df8ff1SMax Filippov     .read = xtensa_mx_pic_ext_reg_read,
26810df8ff1SMax Filippov     .write = xtensa_mx_pic_ext_reg_write,
26910df8ff1SMax Filippov     .endianness = DEVICE_NATIVE_ENDIAN,
27010df8ff1SMax Filippov     .valid = {
27110df8ff1SMax Filippov         .unaligned = true,
27210df8ff1SMax Filippov     },
27310df8ff1SMax Filippov };
27410df8ff1SMax Filippov 
xtensa_mx_pic_register_cpu(XtensaMxPic * mx,qemu_irq * irq,qemu_irq runstall)27510df8ff1SMax Filippov MemoryRegion *xtensa_mx_pic_register_cpu(XtensaMxPic *mx,
27610df8ff1SMax Filippov                                          qemu_irq *irq,
27710df8ff1SMax Filippov                                          qemu_irq runstall)
27810df8ff1SMax Filippov {
27910df8ff1SMax Filippov     struct XtensaMxPicCpu *mx_cpu = mx->cpu + mx->n_cpu;
28010df8ff1SMax Filippov 
28110df8ff1SMax Filippov     mx_cpu->mx = mx;
28210df8ff1SMax Filippov     mx_cpu->irq = irq;
28310df8ff1SMax Filippov     mx_cpu->runstall = runstall;
28410df8ff1SMax Filippov 
28510df8ff1SMax Filippov     memory_region_init_io(&mx_cpu->reg, NULL, &xtensa_mx_pic_ops, mx_cpu,
28610df8ff1SMax Filippov                           "mx_pic", 0x280);
28710df8ff1SMax Filippov 
28810df8ff1SMax Filippov     ++mx->n_cpu;
28910df8ff1SMax Filippov     return &mx_cpu->reg;
29010df8ff1SMax Filippov }
29110df8ff1SMax Filippov 
xtensa_mx_pic_set_irq(void * opaque,int irq,int active)29210df8ff1SMax Filippov static void xtensa_mx_pic_set_irq(void *opaque, int irq, int active)
29310df8ff1SMax Filippov {
29410df8ff1SMax Filippov     XtensaMxPic *mx = opaque;
29510df8ff1SMax Filippov 
29610df8ff1SMax Filippov     if (irq < mx->n_irq) {
29710df8ff1SMax Filippov         uint32_t old_irq_state = mx->ext_irq_state;
29810df8ff1SMax Filippov 
29910df8ff1SMax Filippov         if (active) {
30010df8ff1SMax Filippov             mx->ext_irq_state |= 1u << irq;
30110df8ff1SMax Filippov         } else {
30210df8ff1SMax Filippov             mx->ext_irq_state &= ~(1u << irq);
30310df8ff1SMax Filippov         }
30410df8ff1SMax Filippov         if (old_irq_state != mx->ext_irq_state) {
30510df8ff1SMax Filippov             qemu_log_mask(CPU_LOG_INT,
30610df8ff1SMax Filippov                           "%s: IRQ %d, active: %d, ext_irq_state: %08x -> %08x\n",
30710df8ff1SMax Filippov                           __func__, irq, active,
30810df8ff1SMax Filippov                           old_irq_state, mx->ext_irq_state);
30910df8ff1SMax Filippov             xtensa_mx_pic_update_all(mx);
31010df8ff1SMax Filippov         }
31110df8ff1SMax Filippov     } else {
31210df8ff1SMax Filippov         qemu_log_mask(LOG_GUEST_ERROR, "%s: IRQ %d out of range\n",
31310df8ff1SMax Filippov                       __func__, irq);
31410df8ff1SMax Filippov     }
31510df8ff1SMax Filippov }
31610df8ff1SMax Filippov 
xtensa_mx_pic_init(unsigned n_irq)31710df8ff1SMax Filippov XtensaMxPic *xtensa_mx_pic_init(unsigned n_irq)
31810df8ff1SMax Filippov {
31910df8ff1SMax Filippov     XtensaMxPic *mx = calloc(1, sizeof(XtensaMxPic));
32010df8ff1SMax Filippov 
32110df8ff1SMax Filippov     mx->n_irq = n_irq + 1;
32210df8ff1SMax Filippov     mx->irq_inputs = qemu_allocate_irqs(xtensa_mx_pic_set_irq, mx,
32310df8ff1SMax Filippov                                         mx->n_irq);
32410df8ff1SMax Filippov     return mx;
32510df8ff1SMax Filippov }
32610df8ff1SMax Filippov 
xtensa_mx_pic_reset(void * opaque)32710df8ff1SMax Filippov void xtensa_mx_pic_reset(void *opaque)
32810df8ff1SMax Filippov {
32910df8ff1SMax Filippov     XtensaMxPic *mx = opaque;
33010df8ff1SMax Filippov     unsigned i;
33110df8ff1SMax Filippov 
33210df8ff1SMax Filippov     mx->ext_irq_state = 0;
33310df8ff1SMax Filippov     mx->mieng = mx->n_irq < 32 ? (1u << mx->n_irq) - 1 : ~0u;
33410df8ff1SMax Filippov     mx->miasg = 0;
33510df8ff1SMax Filippov     mx->mipipart = 0;
33610df8ff1SMax Filippov     for (i = 0; i < mx->n_irq; ++i) {
337*c6f3f334SMax Filippov         mx->mirout[i] = 0;
33810df8ff1SMax Filippov     }
33910df8ff1SMax Filippov     for (i = 0; i < mx->n_cpu; ++i) {
34010df8ff1SMax Filippov         mx->cpu[i].mipicause = 0;
34110df8ff1SMax Filippov         mx->cpu[i].mirout_cache = i ? 0 : mx->mieng;
34210df8ff1SMax Filippov         mx->cpu[i].irq_state_cache = 0;
34310df8ff1SMax Filippov         mx->cpu[i].ccon = 0;
34410df8ff1SMax Filippov     }
34510df8ff1SMax Filippov     mx->runstall = (1u << mx->n_cpu) - 2;
34610df8ff1SMax Filippov     for (i = 0; i < mx->n_cpu; ++i) {
34710df8ff1SMax Filippov         qemu_set_irq(mx->cpu[i].runstall, i > 0);
34810df8ff1SMax Filippov     }
34910df8ff1SMax Filippov }
35010df8ff1SMax Filippov 
xtensa_mx_pic_get_extints(XtensaMxPic * mx)35110df8ff1SMax Filippov qemu_irq *xtensa_mx_pic_get_extints(XtensaMxPic *mx)
35210df8ff1SMax Filippov {
35310df8ff1SMax Filippov     return mx->irq_inputs + 1;
35410df8ff1SMax Filippov }
355