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