balrog | c171313 | 2007-04-30 01:26:42 +0000 | [diff] [blame] | 1 | /* |
| 2 | * Intel XScale PXA Programmable Interrupt Controller. |
| 3 | * |
| 4 | * Copyright (c) 2006 Openedhand Ltd. |
| 5 | * Copyright (c) 2006 Thorsten Zitterell |
| 6 | * Written by Andrzej Zaborowski <balrog@zabor.org> |
| 7 | * |
Matthew Fernandez | 8e31bf3 | 2011-06-26 12:21:35 +1000 | [diff] [blame] | 8 | * This code is licensed under the GPL. |
balrog | c171313 | 2007-04-30 01:26:42 +0000 | [diff] [blame] | 9 | */ |
| 10 | |
Peter Maydell | 12b1672 | 2015-12-07 16:23:45 +0000 | [diff] [blame] | 11 | #include "qemu/osdep.h" |
Markus Armbruster | 3e80f69 | 2020-06-10 07:31:58 +0200 | [diff] [blame] | 12 | #include "qapi/error.h" |
Markus Armbruster | 0b8fa32 | 2019-05-23 16:35:07 +0200 | [diff] [blame] | 13 | #include "qemu/module.h" |
Peter Maydell | e53652e | 2020-07-03 16:59:45 +0100 | [diff] [blame] | 14 | #include "qemu/log.h" |
Paolo Bonzini | 4771d75 | 2016-01-19 21:51:44 +0100 | [diff] [blame] | 15 | #include "cpu.h" |
Paolo Bonzini | 0d09e41 | 2013-02-05 17:06:20 +0100 | [diff] [blame] | 16 | #include "hw/arm/pxa.h" |
Paolo Bonzini | 83c9f4c | 2013-02-04 15:40:22 +0100 | [diff] [blame] | 17 | #include "hw/sysbus.h" |
Markus Armbruster | d645427 | 2019-08-12 07:23:45 +0200 | [diff] [blame] | 18 | #include "migration/vmstate.h" |
Eduardo Habkost | db1015e | 2020-09-03 16:43:22 -0400 | [diff] [blame] | 19 | #include "qom/object.h" |
balrog | c171313 | 2007-04-30 01:26:42 +0000 | [diff] [blame] | 20 | |
| 21 | #define ICIP 0x00 /* Interrupt Controller IRQ Pending register */ |
| 22 | #define ICMR 0x04 /* Interrupt Controller Mask register */ |
| 23 | #define ICLR 0x08 /* Interrupt Controller Level register */ |
| 24 | #define ICFP 0x0c /* Interrupt Controller FIQ Pending register */ |
| 25 | #define ICPR 0x10 /* Interrupt Controller Pending register */ |
| 26 | #define ICCR 0x14 /* Interrupt Controller Control register */ |
| 27 | #define ICHP 0x18 /* Interrupt Controller Highest Priority register */ |
| 28 | #define IPR0 0x1c /* Interrupt Controller Priority register 0 */ |
| 29 | #define IPR31 0x98 /* Interrupt Controller Priority register 31 */ |
| 30 | #define ICIP2 0x9c /* Interrupt Controller IRQ Pending register 2 */ |
| 31 | #define ICMR2 0xa0 /* Interrupt Controller Mask register 2 */ |
| 32 | #define ICLR2 0xa4 /* Interrupt Controller Level register 2 */ |
| 33 | #define ICFP2 0xa8 /* Interrupt Controller FIQ Pending register 2 */ |
| 34 | #define ICPR2 0xac /* Interrupt Controller Pending register 2 */ |
| 35 | #define IPR32 0xb0 /* Interrupt Controller Priority register 32 */ |
| 36 | #define IPR39 0xcc /* Interrupt Controller Priority register 39 */ |
| 37 | |
| 38 | #define PXA2XX_PIC_SRCS 40 |
| 39 | |
Andreas Färber | 6050ed5 | 2013-07-24 02:08:09 +0200 | [diff] [blame] | 40 | #define TYPE_PXA2XX_PIC "pxa2xx_pic" |
Eduardo Habkost | 8063396 | 2020-09-16 14:25:19 -0400 | [diff] [blame] | 41 | OBJECT_DECLARE_SIMPLE_TYPE(PXA2xxPICState, PXA2XX_PIC) |
Andreas Färber | 6050ed5 | 2013-07-24 02:08:09 +0200 | [diff] [blame] | 42 | |
Eduardo Habkost | db1015e | 2020-09-03 16:43:22 -0400 | [diff] [blame] | 43 | struct PXA2xxPICState { |
Andreas Färber | 6050ed5 | 2013-07-24 02:08:09 +0200 | [diff] [blame] | 44 | /*< private >*/ |
| 45 | SysBusDevice parent_obj; |
| 46 | /*< public >*/ |
| 47 | |
Benoît Canet | 90e8e5a | 2011-10-30 14:50:17 +0100 | [diff] [blame] | 48 | MemoryRegion iomem; |
Andreas Färber | e9d872c | 2012-05-04 00:05:29 +0200 | [diff] [blame] | 49 | ARMCPU *cpu; |
balrog | c171313 | 2007-04-30 01:26:42 +0000 | [diff] [blame] | 50 | uint32_t int_enabled[2]; |
| 51 | uint32_t int_pending[2]; |
| 52 | uint32_t is_fiq[2]; |
| 53 | uint32_t int_idle; |
| 54 | uint32_t priority[PXA2XX_PIC_SRCS]; |
Eduardo Habkost | db1015e | 2020-09-03 16:43:22 -0400 | [diff] [blame] | 55 | }; |
balrog | c171313 | 2007-04-30 01:26:42 +0000 | [diff] [blame] | 56 | |
| 57 | static void pxa2xx_pic_update(void *opaque) |
| 58 | { |
| 59 | uint32_t mask[2]; |
Paul Brook | bc24a22 | 2009-05-10 01:44:56 +0100 | [diff] [blame] | 60 | PXA2xxPICState *s = (PXA2xxPICState *) opaque; |
Andreas Färber | 259186a | 2013-01-17 18:51:17 +0100 | [diff] [blame] | 61 | CPUState *cpu = CPU(s->cpu); |
balrog | c171313 | 2007-04-30 01:26:42 +0000 | [diff] [blame] | 62 | |
Andreas Färber | 259186a | 2013-01-17 18:51:17 +0100 | [diff] [blame] | 63 | if (cpu->halted) { |
balrog | c171313 | 2007-04-30 01:26:42 +0000 | [diff] [blame] | 64 | mask[0] = s->int_pending[0] & (s->int_enabled[0] | s->int_idle); |
| 65 | mask[1] = s->int_pending[1] & (s->int_enabled[1] | s->int_idle); |
Andreas Färber | e9d872c | 2012-05-04 00:05:29 +0200 | [diff] [blame] | 66 | if (mask[0] || mask[1]) { |
Andreas Färber | c3affe5 | 2013-01-18 15:03:43 +0100 | [diff] [blame] | 67 | cpu_interrupt(cpu, CPU_INTERRUPT_EXITTB); |
Andreas Färber | e9d872c | 2012-05-04 00:05:29 +0200 | [diff] [blame] | 68 | } |
balrog | c171313 | 2007-04-30 01:26:42 +0000 | [diff] [blame] | 69 | } |
| 70 | |
| 71 | mask[0] = s->int_pending[0] & s->int_enabled[0]; |
| 72 | mask[1] = s->int_pending[1] & s->int_enabled[1]; |
| 73 | |
Andreas Färber | e9d872c | 2012-05-04 00:05:29 +0200 | [diff] [blame] | 74 | if ((mask[0] & s->is_fiq[0]) || (mask[1] & s->is_fiq[1])) { |
Andreas Färber | c3affe5 | 2013-01-18 15:03:43 +0100 | [diff] [blame] | 75 | cpu_interrupt(cpu, CPU_INTERRUPT_FIQ); |
Andreas Färber | e9d872c | 2012-05-04 00:05:29 +0200 | [diff] [blame] | 76 | } else { |
Andreas Färber | d8ed887 | 2013-01-17 22:30:20 +0100 | [diff] [blame] | 77 | cpu_reset_interrupt(cpu, CPU_INTERRUPT_FIQ); |
Andreas Färber | e9d872c | 2012-05-04 00:05:29 +0200 | [diff] [blame] | 78 | } |
balrog | c171313 | 2007-04-30 01:26:42 +0000 | [diff] [blame] | 79 | |
Andreas Färber | e9d872c | 2012-05-04 00:05:29 +0200 | [diff] [blame] | 80 | if ((mask[0] & ~s->is_fiq[0]) || (mask[1] & ~s->is_fiq[1])) { |
Andreas Färber | c3affe5 | 2013-01-18 15:03:43 +0100 | [diff] [blame] | 81 | cpu_interrupt(cpu, CPU_INTERRUPT_HARD); |
Andreas Färber | e9d872c | 2012-05-04 00:05:29 +0200 | [diff] [blame] | 82 | } else { |
Andreas Färber | d8ed887 | 2013-01-17 22:30:20 +0100 | [diff] [blame] | 83 | cpu_reset_interrupt(cpu, CPU_INTERRUPT_HARD); |
Andreas Färber | e9d872c | 2012-05-04 00:05:29 +0200 | [diff] [blame] | 84 | } |
balrog | c171313 | 2007-04-30 01:26:42 +0000 | [diff] [blame] | 85 | } |
| 86 | |
| 87 | /* Note: Here level means state of the signal on a pin, not |
| 88 | * IRQ/FIQ distinction as in PXA Developer Manual. */ |
| 89 | static void pxa2xx_pic_set_irq(void *opaque, int irq, int level) |
| 90 | { |
Paul Brook | bc24a22 | 2009-05-10 01:44:56 +0100 | [diff] [blame] | 91 | PXA2xxPICState *s = (PXA2xxPICState *) opaque; |
balrog | c171313 | 2007-04-30 01:26:42 +0000 | [diff] [blame] | 92 | int int_set = (irq >= 32); |
| 93 | irq &= 31; |
| 94 | |
| 95 | if (level) |
| 96 | s->int_pending[int_set] |= 1 << irq; |
| 97 | else |
| 98 | s->int_pending[int_set] &= ~(1 << irq); |
| 99 | |
| 100 | pxa2xx_pic_update(opaque); |
| 101 | } |
| 102 | |
Paul Brook | bc24a22 | 2009-05-10 01:44:56 +0100 | [diff] [blame] | 103 | static inline uint32_t pxa2xx_pic_highest(PXA2xxPICState *s) { |
balrog | c171313 | 2007-04-30 01:26:42 +0000 | [diff] [blame] | 104 | int i, int_set, irq; |
| 105 | uint32_t bit, mask[2]; |
| 106 | uint32_t ichp = 0x003f003f; /* Both IDs invalid */ |
| 107 | |
| 108 | mask[0] = s->int_pending[0] & s->int_enabled[0]; |
| 109 | mask[1] = s->int_pending[1] & s->int_enabled[1]; |
| 110 | |
| 111 | for (i = PXA2XX_PIC_SRCS - 1; i >= 0; i --) { |
| 112 | irq = s->priority[i] & 0x3f; |
Peter Maydell | 43a32ed | 2014-03-10 14:56:29 +0000 | [diff] [blame] | 113 | if ((s->priority[i] & (1U << 31)) && irq < PXA2XX_PIC_SRCS) { |
balrog | c171313 | 2007-04-30 01:26:42 +0000 | [diff] [blame] | 114 | /* Source peripheral ID is valid. */ |
| 115 | bit = 1 << (irq & 31); |
| 116 | int_set = (irq >= 32); |
| 117 | |
| 118 | if (mask[int_set] & bit & s->is_fiq[int_set]) { |
| 119 | /* FIQ asserted */ |
| 120 | ichp &= 0xffff0000; |
| 121 | ichp |= (1 << 15) | irq; |
| 122 | } |
| 123 | |
| 124 | if (mask[int_set] & bit & ~s->is_fiq[int_set]) { |
| 125 | /* IRQ asserted */ |
| 126 | ichp &= 0x0000ffff; |
Peter Maydell | 43a32ed | 2014-03-10 14:56:29 +0000 | [diff] [blame] | 127 | ichp |= (1U << 31) | (irq << 16); |
balrog | c171313 | 2007-04-30 01:26:42 +0000 | [diff] [blame] | 128 | } |
| 129 | } |
| 130 | } |
| 131 | |
| 132 | return ichp; |
| 133 | } |
| 134 | |
Avi Kivity | a8170e5 | 2012-10-23 12:30:10 +0200 | [diff] [blame] | 135 | static uint64_t pxa2xx_pic_mem_read(void *opaque, hwaddr offset, |
Benoît Canet | 90e8e5a | 2011-10-30 14:50:17 +0100 | [diff] [blame] | 136 | unsigned size) |
balrog | c171313 | 2007-04-30 01:26:42 +0000 | [diff] [blame] | 137 | { |
Paul Brook | bc24a22 | 2009-05-10 01:44:56 +0100 | [diff] [blame] | 138 | PXA2xxPICState *s = (PXA2xxPICState *) opaque; |
balrog | c171313 | 2007-04-30 01:26:42 +0000 | [diff] [blame] | 139 | |
| 140 | switch (offset) { |
| 141 | case ICIP: /* IRQ Pending register */ |
| 142 | return s->int_pending[0] & ~s->is_fiq[0] & s->int_enabled[0]; |
| 143 | case ICIP2: /* IRQ Pending register 2 */ |
| 144 | return s->int_pending[1] & ~s->is_fiq[1] & s->int_enabled[1]; |
| 145 | case ICMR: /* Mask register */ |
| 146 | return s->int_enabled[0]; |
| 147 | case ICMR2: /* Mask register 2 */ |
| 148 | return s->int_enabled[1]; |
| 149 | case ICLR: /* Level register */ |
| 150 | return s->is_fiq[0]; |
| 151 | case ICLR2: /* Level register 2 */ |
| 152 | return s->is_fiq[1]; |
| 153 | case ICCR: /* Idle mask */ |
| 154 | return (s->int_idle == 0); |
| 155 | case ICFP: /* FIQ Pending register */ |
| 156 | return s->int_pending[0] & s->is_fiq[0] & s->int_enabled[0]; |
| 157 | case ICFP2: /* FIQ Pending register 2 */ |
| 158 | return s->int_pending[1] & s->is_fiq[1] & s->int_enabled[1]; |
| 159 | case ICPR: /* Pending register */ |
| 160 | return s->int_pending[0]; |
| 161 | case ICPR2: /* Pending register 2 */ |
| 162 | return s->int_pending[1]; |
| 163 | case IPR0 ... IPR31: |
| 164 | return s->priority[0 + ((offset - IPR0 ) >> 2)]; |
| 165 | case IPR32 ... IPR39: |
| 166 | return s->priority[32 + ((offset - IPR32) >> 2)]; |
| 167 | case ICHP: /* Highest Priority register */ |
| 168 | return pxa2xx_pic_highest(s); |
| 169 | default: |
Peter Maydell | e53652e | 2020-07-03 16:59:45 +0100 | [diff] [blame] | 170 | qemu_log_mask(LOG_GUEST_ERROR, |
| 171 | "pxa2xx_pic_mem_read: bad register offset 0x%" HWADDR_PRIx |
| 172 | "\n", offset); |
balrog | c171313 | 2007-04-30 01:26:42 +0000 | [diff] [blame] | 173 | return 0; |
| 174 | } |
| 175 | } |
| 176 | |
Avi Kivity | a8170e5 | 2012-10-23 12:30:10 +0200 | [diff] [blame] | 177 | static void pxa2xx_pic_mem_write(void *opaque, hwaddr offset, |
Benoît Canet | 90e8e5a | 2011-10-30 14:50:17 +0100 | [diff] [blame] | 178 | uint64_t value, unsigned size) |
balrog | c171313 | 2007-04-30 01:26:42 +0000 | [diff] [blame] | 179 | { |
Paul Brook | bc24a22 | 2009-05-10 01:44:56 +0100 | [diff] [blame] | 180 | PXA2xxPICState *s = (PXA2xxPICState *) opaque; |
balrog | c171313 | 2007-04-30 01:26:42 +0000 | [diff] [blame] | 181 | |
| 182 | switch (offset) { |
| 183 | case ICMR: /* Mask register */ |
| 184 | s->int_enabled[0] = value; |
| 185 | break; |
| 186 | case ICMR2: /* Mask register 2 */ |
| 187 | s->int_enabled[1] = value; |
| 188 | break; |
| 189 | case ICLR: /* Level register */ |
| 190 | s->is_fiq[0] = value; |
| 191 | break; |
| 192 | case ICLR2: /* Level register 2 */ |
| 193 | s->is_fiq[1] = value; |
| 194 | break; |
| 195 | case ICCR: /* Idle mask */ |
| 196 | s->int_idle = (value & 1) ? 0 : ~0; |
| 197 | break; |
| 198 | case IPR0 ... IPR31: |
| 199 | s->priority[0 + ((offset - IPR0 ) >> 2)] = value & 0x8000003f; |
| 200 | break; |
| 201 | case IPR32 ... IPR39: |
| 202 | s->priority[32 + ((offset - IPR32) >> 2)] = value & 0x8000003f; |
| 203 | break; |
| 204 | default: |
Peter Maydell | e53652e | 2020-07-03 16:59:45 +0100 | [diff] [blame] | 205 | qemu_log_mask(LOG_GUEST_ERROR, |
| 206 | "pxa2xx_pic_mem_write: bad register offset 0x%" |
| 207 | HWADDR_PRIx "\n", offset); |
balrog | c171313 | 2007-04-30 01:26:42 +0000 | [diff] [blame] | 208 | return; |
| 209 | } |
| 210 | pxa2xx_pic_update(opaque); |
| 211 | } |
| 212 | |
| 213 | /* Interrupt Controller Coprocessor Space Register Mapping */ |
| 214 | static const int pxa2xx_cp_reg_map[0x10] = { |
| 215 | [0x0 ... 0xf] = -1, |
| 216 | [0x0] = ICIP, |
| 217 | [0x1] = ICMR, |
| 218 | [0x2] = ICLR, |
| 219 | [0x3] = ICFP, |
| 220 | [0x4] = ICPR, |
| 221 | [0x5] = ICHP, |
| 222 | [0x6] = ICIP2, |
| 223 | [0x7] = ICMR2, |
| 224 | [0x8] = ICLR2, |
| 225 | [0x9] = ICFP2, |
| 226 | [0xa] = ICPR2, |
| 227 | }; |
| 228 | |
Peter Maydell | c4241c7 | 2014-02-20 10:35:54 +0000 | [diff] [blame] | 229 | static uint64_t pxa2xx_pic_cp_read(CPUARMState *env, const ARMCPRegInfo *ri) |
balrog | c171313 | 2007-04-30 01:26:42 +0000 | [diff] [blame] | 230 | { |
Peter Maydell | 9ee703b | 2012-06-20 11:57:08 +0000 | [diff] [blame] | 231 | int offset = pxa2xx_cp_reg_map[ri->crn]; |
Peter Maydell | c4241c7 | 2014-02-20 10:35:54 +0000 | [diff] [blame] | 232 | return pxa2xx_pic_mem_read(ri->opaque, offset, 4); |
balrog | c171313 | 2007-04-30 01:26:42 +0000 | [diff] [blame] | 233 | } |
| 234 | |
Peter Maydell | c4241c7 | 2014-02-20 10:35:54 +0000 | [diff] [blame] | 235 | static void pxa2xx_pic_cp_write(CPUARMState *env, const ARMCPRegInfo *ri, |
| 236 | uint64_t value) |
balrog | c171313 | 2007-04-30 01:26:42 +0000 | [diff] [blame] | 237 | { |
Peter Maydell | 9ee703b | 2012-06-20 11:57:08 +0000 | [diff] [blame] | 238 | int offset = pxa2xx_cp_reg_map[ri->crn]; |
| 239 | pxa2xx_pic_mem_write(ri->opaque, offset, value, 4); |
balrog | c171313 | 2007-04-30 01:26:42 +0000 | [diff] [blame] | 240 | } |
| 241 | |
Peter Maydell | 9ee703b | 2012-06-20 11:57:08 +0000 | [diff] [blame] | 242 | #define REGINFO_FOR_PIC_CP(NAME, CRN) \ |
| 243 | { .name = NAME, .cp = 6, .crn = CRN, .crm = 0, .opc1 = 0, .opc2 = 0, \ |
Peter Maydell | 14c3032 | 2015-06-15 18:06:09 +0100 | [diff] [blame] | 244 | .access = PL1_RW, .type = ARM_CP_IO, \ |
Peter Maydell | 9ee703b | 2012-06-20 11:57:08 +0000 | [diff] [blame] | 245 | .readfn = pxa2xx_pic_cp_read, .writefn = pxa2xx_pic_cp_write } |
| 246 | |
| 247 | static const ARMCPRegInfo pxa_pic_cp_reginfo[] = { |
| 248 | REGINFO_FOR_PIC_CP("ICIP", 0), |
| 249 | REGINFO_FOR_PIC_CP("ICMR", 1), |
| 250 | REGINFO_FOR_PIC_CP("ICLR", 2), |
| 251 | REGINFO_FOR_PIC_CP("ICFP", 3), |
| 252 | REGINFO_FOR_PIC_CP("ICPR", 4), |
| 253 | REGINFO_FOR_PIC_CP("ICHP", 5), |
| 254 | REGINFO_FOR_PIC_CP("ICIP2", 6), |
| 255 | REGINFO_FOR_PIC_CP("ICMR2", 7), |
| 256 | REGINFO_FOR_PIC_CP("ICLR2", 8), |
| 257 | REGINFO_FOR_PIC_CP("ICFP2", 9), |
| 258 | REGINFO_FOR_PIC_CP("ICPR2", 0xa), |
| 259 | REGINFO_SENTINEL |
| 260 | }; |
| 261 | |
Benoît Canet | 90e8e5a | 2011-10-30 14:50:17 +0100 | [diff] [blame] | 262 | static const MemoryRegionOps pxa2xx_pic_ops = { |
| 263 | .read = pxa2xx_pic_mem_read, |
| 264 | .write = pxa2xx_pic_mem_write, |
| 265 | .endianness = DEVICE_NATIVE_ENDIAN, |
balrog | c171313 | 2007-04-30 01:26:42 +0000 | [diff] [blame] | 266 | }; |
| 267 | |
Dmitry Eremin-Solenikov | e1f8c72 | 2011-02-25 12:13:38 +0100 | [diff] [blame] | 268 | static int pxa2xx_pic_post_load(void *opaque, int version_id) |
balrog | aa941b9 | 2007-05-24 18:50:09 +0000 | [diff] [blame] | 269 | { |
balrog | aa941b9 | 2007-05-24 18:50:09 +0000 | [diff] [blame] | 270 | pxa2xx_pic_update(opaque); |
| 271 | return 0; |
| 272 | } |
| 273 | |
Avi Kivity | a8170e5 | 2012-10-23 12:30:10 +0200 | [diff] [blame] | 274 | DeviceState *pxa2xx_pic_init(hwaddr base, ARMCPU *cpu) |
balrog | c171313 | 2007-04-30 01:26:42 +0000 | [diff] [blame] | 275 | { |
Markus Armbruster | 3e80f69 | 2020-06-10 07:31:58 +0200 | [diff] [blame] | 276 | DeviceState *dev = qdev_new(TYPE_PXA2XX_PIC); |
Andreas Färber | 6050ed5 | 2013-07-24 02:08:09 +0200 | [diff] [blame] | 277 | PXA2xxPICState *s = PXA2XX_PIC(dev); |
balrog | c171313 | 2007-04-30 01:26:42 +0000 | [diff] [blame] | 278 | |
Andreas Färber | e9d872c | 2012-05-04 00:05:29 +0200 | [diff] [blame] | 279 | s->cpu = cpu; |
balrog | c171313 | 2007-04-30 01:26:42 +0000 | [diff] [blame] | 280 | |
| 281 | s->int_pending[0] = 0; |
| 282 | s->int_pending[1] = 0; |
| 283 | s->int_enabled[0] = 0; |
| 284 | s->int_enabled[1] = 0; |
| 285 | s->is_fiq[0] = 0; |
| 286 | s->is_fiq[1] = 0; |
| 287 | |
Markus Armbruster | 3c6ef47 | 2020-06-10 07:32:34 +0200 | [diff] [blame] | 288 | sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); |
Dmitry Eremin-Solenikov | e1f8c72 | 2011-02-25 12:13:38 +0100 | [diff] [blame] | 289 | |
| 290 | qdev_init_gpio_in(dev, pxa2xx_pic_set_irq, PXA2XX_PIC_SRCS); |
balrog | c171313 | 2007-04-30 01:26:42 +0000 | [diff] [blame] | 291 | |
| 292 | /* Enable IC memory-mapped registers access. */ |
Paolo Bonzini | 64bde0f | 2013-06-06 21:25:08 -0400 | [diff] [blame] | 293 | memory_region_init_io(&s->iomem, OBJECT(s), &pxa2xx_pic_ops, s, |
Benoît Canet | 90e8e5a | 2011-10-30 14:50:17 +0100 | [diff] [blame] | 294 | "pxa2xx-pic", 0x00100000); |
Andreas Färber | 1356b98 | 2013-01-20 02:47:33 +0100 | [diff] [blame] | 295 | sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem); |
| 296 | sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base); |
balrog | c171313 | 2007-04-30 01:26:42 +0000 | [diff] [blame] | 297 | |
| 298 | /* Enable IC coprocessor access. */ |
Andreas Färber | 6050ed5 | 2013-07-24 02:08:09 +0200 | [diff] [blame] | 299 | define_arm_cp_regs_with_opaque(cpu, pxa_pic_cp_reginfo, s); |
balrog | c171313 | 2007-04-30 01:26:42 +0000 | [diff] [blame] | 300 | |
Dmitry Eremin-Solenikov | e1f8c72 | 2011-02-25 12:13:38 +0100 | [diff] [blame] | 301 | return dev; |
balrog | c171313 | 2007-04-30 01:26:42 +0000 | [diff] [blame] | 302 | } |
Dmitry Eremin-Solenikov | e1f8c72 | 2011-02-25 12:13:38 +0100 | [diff] [blame] | 303 | |
Philippe Mathieu-Daudé | cfa52e0 | 2021-03-13 18:11:48 +0100 | [diff] [blame] | 304 | static const VMStateDescription vmstate_pxa2xx_pic_regs = { |
Dmitry Eremin-Solenikov | e1f8c72 | 2011-02-25 12:13:38 +0100 | [diff] [blame] | 305 | .name = "pxa2xx_pic", |
| 306 | .version_id = 0, |
| 307 | .minimum_version_id = 0, |
Dmitry Eremin-Solenikov | e1f8c72 | 2011-02-25 12:13:38 +0100 | [diff] [blame] | 308 | .post_load = pxa2xx_pic_post_load, |
| 309 | .fields = (VMStateField[]) { |
| 310 | VMSTATE_UINT32_ARRAY(int_enabled, PXA2xxPICState, 2), |
| 311 | VMSTATE_UINT32_ARRAY(int_pending, PXA2xxPICState, 2), |
| 312 | VMSTATE_UINT32_ARRAY(is_fiq, PXA2xxPICState, 2), |
| 313 | VMSTATE_UINT32(int_idle, PXA2xxPICState), |
| 314 | VMSTATE_UINT32_ARRAY(priority, PXA2xxPICState, PXA2XX_PIC_SRCS), |
| 315 | VMSTATE_END_OF_LIST(), |
| 316 | }, |
| 317 | }; |
| 318 | |
Anthony Liguori | 999e12b | 2012-01-24 13:12:29 -0600 | [diff] [blame] | 319 | static void pxa2xx_pic_class_init(ObjectClass *klass, void *data) |
| 320 | { |
Anthony Liguori | 39bffca | 2011-12-07 21:34:16 -0600 | [diff] [blame] | 321 | DeviceClass *dc = DEVICE_CLASS(klass); |
Anthony Liguori | 999e12b | 2012-01-24 13:12:29 -0600 | [diff] [blame] | 322 | |
Anthony Liguori | 39bffca | 2011-12-07 21:34:16 -0600 | [diff] [blame] | 323 | dc->desc = "PXA2xx PIC"; |
| 324 | dc->vmsd = &vmstate_pxa2xx_pic_regs; |
Anthony Liguori | 999e12b | 2012-01-24 13:12:29 -0600 | [diff] [blame] | 325 | } |
| 326 | |
Andreas Färber | 8c43a6f | 2013-01-10 16:19:07 +0100 | [diff] [blame] | 327 | static const TypeInfo pxa2xx_pic_info = { |
Andreas Färber | 6050ed5 | 2013-07-24 02:08:09 +0200 | [diff] [blame] | 328 | .name = TYPE_PXA2XX_PIC, |
Anthony Liguori | 39bffca | 2011-12-07 21:34:16 -0600 | [diff] [blame] | 329 | .parent = TYPE_SYS_BUS_DEVICE, |
| 330 | .instance_size = sizeof(PXA2xxPICState), |
| 331 | .class_init = pxa2xx_pic_class_init, |
Dmitry Eremin-Solenikov | e1f8c72 | 2011-02-25 12:13:38 +0100 | [diff] [blame] | 332 | }; |
| 333 | |
Andreas Färber | 83f7d43 | 2012-02-09 15:20:55 +0100 | [diff] [blame] | 334 | static void pxa2xx_pic_register_types(void) |
Dmitry Eremin-Solenikov | e1f8c72 | 2011-02-25 12:13:38 +0100 | [diff] [blame] | 335 | { |
Anthony Liguori | 39bffca | 2011-12-07 21:34:16 -0600 | [diff] [blame] | 336 | type_register_static(&pxa2xx_pic_info); |
Dmitry Eremin-Solenikov | e1f8c72 | 2011-02-25 12:13:38 +0100 | [diff] [blame] | 337 | } |
Andreas Färber | 83f7d43 | 2012-02-09 15:20:55 +0100 | [diff] [blame] | 338 | |
| 339 | type_init(pxa2xx_pic_register_types) |