2 * RX Interrupt Control Unit
4 * Warning: Only ICUa is supported.
6 * Datasheet: RX62N Group, RX621 Group User's Manual: Hardware
7 * (Rev.1.40 R01UH0033EJ0140)
9 * Copyright (c) 2019 Yoshinori Sato
11 * SPDX-License-Identifier: GPL-2.0-or-later
13 * This program is free software; you can redistribute it and/or modify it
14 * under the terms and conditions of the GNU General Public License,
15 * version 2 or later, as published by the Free Software Foundation.
17 * This program is distributed in the hope it will be useful, but WITHOUT
18 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
22 * You should have received a copy of the GNU General Public License along with
23 * this program. If not, see <http://www.gnu.org/licenses/>.
26 #include "qemu/osdep.h"
28 #include "qemu/error-report.h"
30 #include "hw/registerfields.h"
31 #include "hw/qdev-properties.h"
32 #include "hw/intc/rx_icu.h"
33 #include "migration/vmstate.h"
38 FIELD(DTCER
, DTCE
, 0, 1)
41 FIELD(SWINTR
, SWINT
, 0, 1)
43 FIELD(FIR
, FVCT
, 0, 8)
44 FIELD(FIR
, FIEN
, 15, 1)
49 FIELD(IRQCR
, IRQMD
, 2, 2)
51 FIELD(NMISR
, NMIST
, 0, 1)
52 FIELD(NMISR
, LVDST
, 1, 1)
53 FIELD(NMISR
, OSTST
, 2, 1)
55 FIELD(NMIER
, NMIEN
, 0, 1)
56 FIELD(NMIER
, LVDEN
, 1, 1)
57 FIELD(NMIER
, OSTEN
, 2, 1)
59 FIELD(NMICLR
, NMICLR
, 0, 1)
60 FIELD(NMICLR
, OSTCLR
, 2, 1)
62 FIELD(NMICR
, NMIMD
, 3, 1)
64 static void set_irq(RXICUState
*icu
, int n_IRQ
, int req
)
66 if ((icu
->fir
& R_FIR_FIEN_MASK
) &&
67 (icu
->fir
& R_FIR_FVCT_MASK
) == n_IRQ
) {
68 qemu_set_irq(icu
->_fir
, req
);
70 qemu_set_irq(icu
->_irq
, req
);
74 static uint16_t rxicu_level(RXICUState
*icu
, unsigned n
)
76 return (icu
->ipr
[icu
->map
[n
]] << 8) | n
;
79 static void rxicu_request(RXICUState
*icu
, int n_IRQ
)
83 enable
= icu
->ier
[n_IRQ
/ 8] & (1 << (n_IRQ
& 7));
84 if (n_IRQ
> 0 && enable
!= 0 && atomic_read(&icu
->req_irq
) < 0) {
85 atomic_set(&icu
->req_irq
, n_IRQ
);
86 set_irq(icu
, n_IRQ
, rxicu_level(icu
, n_IRQ
));
90 static void rxicu_set_irq(void *opaque
, int n_IRQ
, int level
)
92 RXICUState
*icu
= opaque
;
93 struct IRQSource
*src
;
96 if (n_IRQ
>= NR_IRQS
) {
97 error_report("%s: IRQ %d out of range", __func__
, n_IRQ
);
101 src
= &icu
->src
[n_IRQ
];
103 level
= (level
!= 0);
104 switch (src
->sense
) {
106 /* level-sensitive irq */
111 issue
= (level
== 0 && src
->level
== 1);
115 issue
= (level
== 1 && src
->level
== 0);
119 issue
= ((level
^ src
->level
) & 1);
123 g_assert_not_reached();
125 if (issue
== 0 && src
->sense
== TRG_LEVEL
) {
127 if (atomic_read(&icu
->req_irq
) == n_IRQ
) {
129 set_irq(icu
, n_IRQ
, 0);
130 atomic_set(&icu
->req_irq
, -1);
136 rxicu_request(icu
, n_IRQ
);
140 static void rxicu_ack_irq(void *opaque
, int no
, int level
)
142 RXICUState
*icu
= opaque
;
147 n_IRQ
= atomic_read(&icu
->req_irq
);
151 atomic_set(&icu
->req_irq
, -1);
152 if (icu
->src
[n_IRQ
].sense
!= TRG_LEVEL
) {
158 for (i
= 0; i
< NR_IRQS
; i
++) {
160 if (max_pri
< icu
->ipr
[icu
->map
[i
]]) {
162 max_pri
= icu
->ipr
[icu
->map
[i
]];
168 rxicu_request(icu
, n_IRQ
);
172 static uint64_t icu_read(void *opaque
, hwaddr addr
, unsigned size
)
174 RXICUState
*icu
= opaque
;
175 int reg
= addr
& 0xff;
177 if ((addr
!= A_FIR
&& size
!= 1) ||
178 (addr
== A_FIR
&& size
!= 2)) {
179 qemu_log_mask(LOG_GUEST_ERROR
, "rx_icu: Invalid read size 0x%"
185 case A_IR
... A_IR
+ 0xff:
186 return icu
->ir
[reg
] & R_IR_IR_MASK
;
187 case A_DTCER
... A_DTCER
+ 0xff:
188 return icu
->dtcer
[reg
] & R_DTCER_DTCE_MASK
;
189 case A_IER
... A_IER
+ 0x1f:
190 return icu
->ier
[reg
];
194 return icu
->fir
& (R_FIR_FIEN_MASK
| R_FIR_FVCT_MASK
);
195 case A_IPR
... A_IPR
+ 0x8f:
196 return icu
->ipr
[reg
] & R_IPR_IPR_MASK
;
201 return icu
->dmasr
[reg
>> 2];
202 case A_IRQCR
... A_IRQCR
+ 0x1f:
203 return icu
->src
[64 + reg
].sense
<< R_IRQCR_IRQMD_SHIFT
;
212 qemu_log_mask(LOG_UNIMP
, "rx_icu: Register 0x%" HWADDR_PRIX
" "
213 "not implemented.\n",
220 static void icu_write(void *opaque
, hwaddr addr
, uint64_t val
, unsigned size
)
222 RXICUState
*icu
= opaque
;
223 int reg
= addr
& 0xff;
225 if ((addr
!= A_FIR
&& size
!= 1) ||
226 (addr
== A_FIR
&& size
!= 2)) {
227 qemu_log_mask(LOG_GUEST_ERROR
, "rx_icu: Invalid write size at "
228 "0x%" HWADDR_PRIX
"\n",
233 case A_IR
... A_IR
+ 0xff:
234 if (icu
->src
[reg
].sense
!= TRG_LEVEL
&& val
== 0) {
238 case A_DTCER
... A_DTCER
+ 0xff:
239 icu
->dtcer
[reg
] = val
& R_DTCER_DTCE_MASK
;
240 qemu_log_mask(LOG_UNIMP
, "rx_icu: DTC not implemented\n");
242 case A_IER
... A_IER
+ 0x1f:
246 if (val
& R_SWINTR_SWINT_MASK
) {
247 qemu_irq_pulse(icu
->_swi
);
251 icu
->fir
= val
& (R_FIR_FIEN_MASK
| R_FIR_FVCT_MASK
);
253 case A_IPR
... A_IPR
+ 0x8f:
254 icu
->ipr
[reg
] = val
& R_IPR_IPR_MASK
;
260 icu
->dmasr
[reg
>> 2] = val
;
261 qemu_log_mask(LOG_UNIMP
, "rx_icu: DMAC not implemented\n");
263 case A_IRQCR
... A_IRQCR
+ 0x1f:
264 icu
->src
[64 + reg
].sense
= val
>> R_IRQCR_IRQMD_SHIFT
;
269 icu
->nmier
|= val
& (R_NMIER_NMIEN_MASK
|
274 if ((icu
->nmier
& R_NMIER_NMIEN_MASK
) == 0) {
275 icu
->nmicr
= val
& R_NMICR_NMIMD_MASK
;
279 qemu_log_mask(LOG_UNIMP
, "rx_icu: Register 0x%" HWADDR_PRIX
" "
286 static const MemoryRegionOps icu_ops
= {
289 .endianness
= DEVICE_LITTLE_ENDIAN
,
291 .min_access_size
= 1,
292 .max_access_size
= 2,
295 .min_access_size
= 1,
296 .max_access_size
= 2,
300 static void rxicu_realize(DeviceState
*dev
, Error
**errp
)
302 RXICUState
*icu
= RX_ICU(dev
);
305 if (icu
->init_sense
== NULL
) {
306 qemu_log_mask(LOG_GUEST_ERROR
,
307 "rx_icu: trigger-level property must be set.");
310 for (i
= j
= 0; i
< NR_IRQS
; i
++) {
311 if (icu
->init_sense
[j
] == i
) {
312 icu
->src
[i
].sense
= TRG_LEVEL
;
313 if (j
< icu
->nr_sense
) {
317 icu
->src
[i
].sense
= TRG_PEDGE
;
323 static void rxicu_init(Object
*obj
)
325 SysBusDevice
*d
= SYS_BUS_DEVICE(obj
);
326 RXICUState
*icu
= RX_ICU(obj
);
328 memory_region_init_io(&icu
->memory
, OBJECT(icu
), &icu_ops
,
329 icu
, "rx-icu", 0x600);
330 sysbus_init_mmio(d
, &icu
->memory
);
332 qdev_init_gpio_in(DEVICE(d
), rxicu_set_irq
, NR_IRQS
);
333 qdev_init_gpio_in_named(DEVICE(d
), rxicu_ack_irq
, "ack", 1);
334 sysbus_init_irq(d
, &icu
->_irq
);
335 sysbus_init_irq(d
, &icu
->_fir
);
336 sysbus_init_irq(d
, &icu
->_swi
);
339 static void rxicu_fini(Object
*obj
)
341 RXICUState
*icu
= RX_ICU(obj
);
343 g_free(icu
->init_sense
);
346 static const VMStateDescription vmstate_rxicu
= {
349 .minimum_version_id
= 1,
350 .fields
= (VMStateField
[]) {
351 VMSTATE_UINT8_ARRAY(ir
, RXICUState
, NR_IRQS
),
352 VMSTATE_UINT8_ARRAY(dtcer
, RXICUState
, NR_IRQS
),
353 VMSTATE_UINT8_ARRAY(ier
, RXICUState
, NR_IRQS
/ 8),
354 VMSTATE_UINT8_ARRAY(ipr
, RXICUState
, 142),
355 VMSTATE_UINT8_ARRAY(dmasr
, RXICUState
, 4),
356 VMSTATE_UINT16(fir
, RXICUState
),
357 VMSTATE_UINT8(nmisr
, RXICUState
),
358 VMSTATE_UINT8(nmier
, RXICUState
),
359 VMSTATE_UINT8(nmiclr
, RXICUState
),
360 VMSTATE_UINT8(nmicr
, RXICUState
),
361 VMSTATE_INT16(req_irq
, RXICUState
),
362 VMSTATE_END_OF_LIST()
366 static Property rxicu_properties
[] = {
367 DEFINE_PROP_ARRAY("ipr-map", RXICUState
, nr_irqs
, map
,
368 qdev_prop_uint8
, uint8_t),
369 DEFINE_PROP_ARRAY("trigger-level", RXICUState
, nr_sense
, init_sense
,
370 qdev_prop_uint8
, uint8_t),
371 DEFINE_PROP_END_OF_LIST(),
374 static void rxicu_class_init(ObjectClass
*klass
, void *data
)
376 DeviceClass
*dc
= DEVICE_CLASS(klass
);
378 dc
->realize
= rxicu_realize
;
379 dc
->vmsd
= &vmstate_rxicu
;
380 device_class_set_props(dc
, rxicu_properties
);
383 static const TypeInfo rxicu_info
= {
385 .parent
= TYPE_SYS_BUS_DEVICE
,
386 .instance_size
= sizeof(RXICUState
),
387 .instance_init
= rxicu_init
,
388 .instance_finalize
= rxicu_fini
,
389 .class_init
= rxicu_class_init
,
392 static void rxicu_register_types(void)
394 type_register_static(&rxicu_info
);
397 type_init(rxicu_register_types
)