• R/O
  • HTTP
  • SSH
  • HTTPS

Commit

Tags
Aucun tag

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

Commit MetaInfo

Révisionfde34f3869f25f5bf77868ba0cabccf4853cb7c0 (tree)
l'heure2020-03-16 00:12:48
AuteurYoshinori Sato <ysato@user...>
CommiterYoshinori Sato

Message de Log

hw/intc: RX62N interrupt controller (ICUa)

This implementation supported only ICUa.
Hardware manual.
https://www.renesas.com/us/en/doc/products/mpumcu/doc/rx_family/r01uh0033ej0140_rx62n.pdf

Signed-off-by: Yoshinori Sato <ysato@users.sourceforge.jp>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Message-Id: <20190607091116.49044-6-ysato@users.sourceforge.jp>
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

Change Summary

Modification

--- a/hw/intc/Kconfig
+++ b/hw/intc/Kconfig
@@ -61,3 +61,6 @@ config S390_FLIC_KVM
6161
6262 config OMPIC
6363 bool
64+
65+config RX_ICU
66+ bool
--- a/hw/intc/Makefile.objs
+++ b/hw/intc/Makefile.objs
@@ -49,3 +49,4 @@ obj-$(CONFIG_ARM_GIC) += arm_gicv3_cpuif.o
4949 obj-$(CONFIG_MIPS_CPS) += mips_gic.o
5050 obj-$(CONFIG_NIOS2) += nios2_iic.o
5151 obj-$(CONFIG_OMPIC) += ompic.o
52+obj-$(CONFIG_RX) += rx_icu.o
--- /dev/null
+++ b/hw/intc/rx_icu.c
@@ -0,0 +1,379 @@
1+/*
2+ * RX Interrupt Control Unit
3+ *
4+ * Warning: Only ICUa is supported.
5+ *
6+ * Datasheet: RX62N Group, RX621 Group User's Manual: Hardware
7+ * (Rev.1.40 R01UH0033EJ0140)
8+ *
9+ * Copyright (c) 2019 Yoshinori Sato
10+ *
11+ * This program is free software; you can redistribute it and/or modify it
12+ * under the terms and conditions of the GNU General Public License,
13+ * version 2 or later, as published by the Free Software Foundation.
14+ *
15+ * This program is distributed in the hope it will be useful, but WITHOUT
16+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
18+ * more details.
19+ *
20+ * You should have received a copy of the GNU General Public License along with
21+ * this program. If not, see <http://www.gnu.org/licenses/>.
22+ */
23+
24+#include "qemu/osdep.h"
25+#include "qemu-common.h"
26+#include "qemu/log.h"
27+#include "qapi/error.h"
28+#include "cpu.h"
29+#include "hw/hw.h"
30+#include "hw/irq.h"
31+#include "hw/sysbus.h"
32+#include "hw/registerfields.h"
33+#include "hw/qdev-properties.h"
34+#include "hw/intc/rx_icu.h"
35+#include "migration/vmstate.h"
36+#include "qemu/error-report.h"
37+
38+REG8(IR, 0)
39+ FIELD(IR, IR, 0, 1)
40+REG8(DTCER, 0x100)
41+ FIELD(DTCER, DTCE, 0, 1)
42+REG8(IER, 0x200)
43+REG8(SWINTR, 0x2e0)
44+ FIELD(SWINTR, SWINT, 0, 1)
45+REG16(FIR, 0x2f0)
46+ FIELD(FIR, FVCT, 0, 8)
47+ FIELD(FIR, FIEN, 15, 1)
48+REG8(IPR, 0x300)
49+ FIELD(IPR, IPR, 0, 4)
50+REG8(DMRSR, 0x400)
51+REG8(IRQCR, 0x500)
52+ FIELD(IRQCR, IRQMD, 2, 2)
53+REG8(NMISR, 0x580)
54+ FIELD(NMISR, NMIST, 0, 1)
55+ FIELD(NMISR, LVDST, 1, 1)
56+ FIELD(NMISR, OSTST, 2, 1)
57+REG8(NMIER, 0x581)
58+ FIELD(NMIER, NMIEN, 0, 1)
59+ FIELD(NMIER, LVDEN, 1, 1)
60+ FIELD(NMIER, OSTEN, 2, 1)
61+REG8(NMICLR, 0x582)
62+ FIELD(NMICLR, NMICLR, 0, 1)
63+ FIELD(NMICLR, OSTCLR, 2, 1)
64+REG8(NMICR, 0x583)
65+ FIELD(NMICR, NMIMD, 3, 1)
66+
67+#define request(icu, n) (icu->ipr[icu->map[n]] << 8 | n)
68+
69+static void set_irq(RXICUState *icu, int n_IRQ, int req)
70+{
71+ if ((icu->fir & R_FIR_FIEN_MASK) &&
72+ (icu->fir & R_FIR_FVCT_MASK) == n_IRQ) {
73+ qemu_set_irq(icu->_fir, req);
74+ } else {
75+ qemu_set_irq(icu->_irq, req);
76+ }
77+}
78+
79+static void rxicu_request(RXICUState *icu, int n_IRQ)
80+{
81+ int enable;
82+
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, request(icu, n_IRQ));
87+ }
88+}
89+
90+static void rxicu_set_irq(void *opaque, int n_IRQ, int level)
91+{
92+ RXICUState *icu = opaque;
93+ struct IRQSource *src;
94+ int issue;
95+
96+ if (n_IRQ >= NR_IRQS) {
97+ error_report("%s: IRQ %d out of range", __func__, n_IRQ);
98+ return;
99+ }
100+
101+ src = &icu->src[n_IRQ];
102+
103+ level = (level != 0);
104+ switch (src->sense) {
105+ case TRG_LEVEL:
106+ /* level-sensitive irq */
107+ issue = level;
108+ src->level = level;
109+ break;
110+ case TRG_NEDGE:
111+ issue = (level == 0 && src->level == 1);
112+ src->level = level;
113+ break;
114+ case TRG_PEDGE:
115+ issue = (level == 1 && src->level == 0);
116+ src->level = level;
117+ break;
118+ case TRG_BEDGE:
119+ issue = ((level ^ src->level) & 1);
120+ src->level = level;
121+ break;
122+ default:
123+ g_assert_not_reached();
124+ }
125+ if (issue == 0 && src->sense == TRG_LEVEL) {
126+ icu->ir[n_IRQ] = 0;
127+ if (atomic_read(&icu->req_irq) == n_IRQ) {
128+ /* clear request */
129+ set_irq(icu, n_IRQ, 0);
130+ atomic_set(&icu->req_irq, -1);
131+ }
132+ return;
133+ }
134+ if (issue) {
135+ icu->ir[n_IRQ] = 1;
136+ rxicu_request(icu, n_IRQ);
137+ }
138+}
139+
140+static void rxicu_ack_irq(void *opaque, int no, int level)
141+{
142+ RXICUState *icu = opaque;
143+ int i;
144+ int n_IRQ;
145+ int max_pri;
146+
147+ n_IRQ = atomic_read(&icu->req_irq);
148+ if (n_IRQ < 0) {
149+ return;
150+ }
151+ atomic_set(&icu->req_irq, -1);
152+ if (icu->src[n_IRQ].sense != TRG_LEVEL) {
153+ icu->ir[n_IRQ] = 0;
154+ }
155+
156+ max_pri = 0;
157+ n_IRQ = -1;
158+ for (i = 0; i < NR_IRQS; i++) {
159+ if (icu->ir[i]) {
160+ if (max_pri < icu->ipr[icu->map[i]]) {
161+ n_IRQ = i;
162+ max_pri = icu->ipr[icu->map[i]];
163+ }
164+ }
165+ }
166+
167+ if (n_IRQ >= 0) {
168+ rxicu_request(icu, n_IRQ);
169+ }
170+}
171+
172+static uint64_t icu_read(void *opaque, hwaddr addr, unsigned size)
173+{
174+ RXICUState *icu = opaque;
175+ int reg = addr & 0xff;
176+
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%"
180+ HWADDR_PRIX "\n", addr);
181+ return UINT64_MAX;
182+ }
183+ switch (addr) {
184+ case A_IR ... A_IR + 0xff:
185+ return icu->ir[reg] & R_IR_IR_MASK;
186+ case A_DTCER ... A_DTCER + 0xff:
187+ return icu->dtcer[reg] & R_DTCER_DTCE_MASK;
188+ case A_IER ... A_IER + 0x1f:
189+ return icu->ier[reg];
190+ case A_SWINTR:
191+ return 0;
192+ case A_FIR:
193+ return icu->fir & (R_FIR_FIEN_MASK | R_FIR_FVCT_MASK);
194+ case A_IPR ... A_IPR + 0x8f:
195+ return icu->ipr[reg] & R_IPR_IPR_MASK;
196+ case A_DMRSR:
197+ case A_DMRSR + 4:
198+ case A_DMRSR + 8:
199+ case A_DMRSR + 12:
200+ return icu->dmasr[reg >> 2];
201+ case A_IRQCR ... A_IRQCR + 0x1f:
202+ return icu->src[64 + reg].sense << R_IRQCR_IRQMD_SHIFT;
203+ case A_NMISR:
204+ case A_NMICLR:
205+ return 0;
206+ case A_NMIER:
207+ return icu->nmier;
208+ case A_NMICR:
209+ return icu->nmicr;
210+ default:
211+ qemu_log_mask(LOG_UNIMP, "rx_icu: Register 0x%" HWADDR_PRIX
212+ " not implemented.\n", addr);
213+ break;
214+ }
215+ return UINT64_MAX;
216+}
217+
218+static void icu_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
219+{
220+ RXICUState *icu = opaque;
221+ int reg = addr & 0xff;
222+
223+ if ((addr != A_FIR && size != 1) ||
224+ (addr == A_FIR && size != 2)) {
225+ qemu_log_mask(LOG_GUEST_ERROR, "rx_icu: Invalid write size at 0x%"
226+ HWADDR_PRIX "\n", addr);
227+ return;
228+ }
229+ switch (addr) {
230+ case A_IR ... A_IR + 0xff:
231+ if (icu->src[reg].sense != TRG_LEVEL && val == 0) {
232+ icu->ir[reg] = 0;
233+ }
234+ break;
235+ case A_DTCER ... A_DTCER + 0xff:
236+ icu->dtcer[reg] = val & R_DTCER_DTCE_MASK;
237+ qemu_log_mask(LOG_UNIMP,
238+ "rx_icu: DTC not implemented\n");
239+ break;
240+ case A_IER ... A_IER + 0x1f:
241+ icu->ier[reg] = val;
242+ break;
243+ case A_SWINTR:
244+ if (val & R_SWINTR_SWINT_MASK) {
245+ qemu_irq_pulse(icu->_swi);
246+ }
247+ break;
248+ case A_FIR:
249+ icu->fir = val & (R_FIR_FIEN_MASK | R_FIR_FVCT_MASK);
250+ break;
251+ case A_IPR ... A_IPR + 0x8f:
252+ icu->ipr[reg] = val & R_IPR_IPR_MASK;
253+ break;
254+ case A_DMRSR:
255+ case A_DMRSR + 4:
256+ case A_DMRSR + 8:
257+ case A_DMRSR + 12:
258+ icu->dmasr[reg >> 2] = val;
259+ qemu_log_mask(LOG_UNIMP,
260+ "rx_icu: DMAC not implemented\n");
261+ break;
262+ case A_IRQCR ... A_IRQCR + 0x1f:
263+ icu->src[64 + reg].sense = val >> R_IRQCR_IRQMD_SHIFT;
264+ break;
265+ case A_NMICLR:
266+ break;
267+ case A_NMIER:
268+ icu->nmier |= val & (R_NMIER_NMIEN_MASK |
269+ R_NMIER_LVDEN_MASK |
270+ R_NMIER_OSTEN_MASK);
271+ break;
272+ case A_NMICR:
273+ if ((icu->nmier & R_NMIER_NMIEN_MASK) == 0) {
274+ icu->nmicr = val & R_NMICR_NMIMD_MASK;
275+ }
276+ break;
277+ default:
278+ qemu_log_mask(LOG_UNIMP, "rx_icu: Register 0x%" HWADDR_PRIX
279+ " not implemented\n", addr);
280+ break;
281+ }
282+}
283+
284+static const MemoryRegionOps icu_ops = {
285+ .write = icu_write,
286+ .read = icu_read,
287+ .endianness = DEVICE_LITTLE_ENDIAN,
288+ .impl = {
289+ .max_access_size = 2,
290+ },
291+};
292+
293+static void rxicu_realize(DeviceState *dev, Error **errp)
294+{
295+ RXICUState *icu = RXICU(dev);
296+ int i, j;
297+
298+ if (icu->init_sense == NULL) {
299+ qemu_log_mask(LOG_GUEST_ERROR,
300+ "rx_icu: trigger-level property must be set.");
301+ return;
302+ }
303+ for (i = j = 0; i < NR_IRQS; i++) {
304+ if (icu->init_sense[j] == i) {
305+ icu->src[i].sense = TRG_LEVEL;
306+ if (j < icu->nr_sense) {
307+ j++;
308+ }
309+ } else {
310+ icu->src[i].sense = TRG_PEDGE;
311+ }
312+ }
313+ icu->req_irq = -1;
314+}
315+
316+static void rxicu_init(Object *obj)
317+{
318+ SysBusDevice *d = SYS_BUS_DEVICE(obj);
319+ RXICUState *icu = RXICU(obj);
320+
321+ memory_region_init_io(&icu->memory, OBJECT(icu), &icu_ops,
322+ icu, "rx-icu", 0x600);
323+ sysbus_init_mmio(d, &icu->memory);
324+
325+ qdev_init_gpio_in(DEVICE(d), rxicu_set_irq, NR_IRQS);
326+ qdev_init_gpio_in_named(DEVICE(d), rxicu_ack_irq, "ack", 1);
327+ sysbus_init_irq(d, &icu->_irq);
328+ sysbus_init_irq(d, &icu->_fir);
329+ sysbus_init_irq(d, &icu->_swi);
330+}
331+
332+static void rxicu_fini(Object *obj)
333+{
334+ RXICUState *icu = RXICU(obj);
335+ g_free(icu->map);
336+ g_free(icu->init_sense);
337+}
338+
339+static const VMStateDescription vmstate_rxicu = {
340+ .name = "rx-icu",
341+ .version_id = 1,
342+ .minimum_version_id = 1,
343+ .fields = (VMStateField[]) {
344+ VMSTATE_END_OF_LIST()
345+ }
346+};
347+
348+static Property rxicu_properties[] = {
349+ DEFINE_PROP_ARRAY("ipr-map", RXICUState, nr_irqs, map,
350+ qdev_prop_uint32, uint32_t),
351+ DEFINE_PROP_ARRAY("trigger-level", RXICUState, nr_sense, init_sense,
352+ qdev_prop_uint32, uint32_t),
353+ DEFINE_PROP_END_OF_LIST(),
354+};
355+
356+static void rxicu_class_init(ObjectClass *klass, void *data)
357+{
358+ DeviceClass *dc = DEVICE_CLASS(klass);
359+
360+ dc->realize = rxicu_realize;
361+ dc->vmsd = &vmstate_rxicu;
362+ device_class_set_props(dc, rxicu_properties);
363+}
364+
365+static const TypeInfo rxicu_info = {
366+ .name = TYPE_RXICU,
367+ .parent = TYPE_SYS_BUS_DEVICE,
368+ .instance_size = sizeof(RXICUState),
369+ .instance_init = rxicu_init,
370+ .instance_finalize = rxicu_fini,
371+ .class_init = rxicu_class_init,
372+};
373+
374+static void rxicu_register_types(void)
375+{
376+ type_register_static(&rxicu_info);
377+}
378+
379+type_init(rxicu_register_types)
--- /dev/null
+++ b/include/hw/intc/rx_icu.h
@@ -0,0 +1,56 @@
1+#ifndef RX_ICU_H
2+#define RX_ICU_H
3+
4+#include "qemu-common.h"
5+#include "hw/irq.h"
6+
7+enum TRG_MODE {
8+ TRG_LEVEL = 0,
9+ TRG_NEDGE = 1, /* Falling */
10+ TRG_PEDGE = 2, /* Raising */
11+ TRG_BEDGE = 3, /* Both */
12+};
13+
14+struct IRQSource {
15+ enum TRG_MODE sense;
16+ int level;
17+};
18+
19+enum {
20+ /* Software interrupt request */
21+ SWI = 27,
22+ NR_IRQS = 256,
23+};
24+
25+struct RXICUState {
26+ SysBusDevice parent_obj;
27+
28+ MemoryRegion memory;
29+ struct IRQSource src[NR_IRQS];
30+ char *icutype;
31+ uint32_t nr_irqs;
32+ uint32_t *map;
33+ uint32_t nr_sense;
34+ uint32_t *init_sense;
35+
36+ uint8_t ir[NR_IRQS];
37+ uint8_t dtcer[NR_IRQS];
38+ uint8_t ier[NR_IRQS / 8];
39+ uint8_t ipr[142];
40+ uint8_t dmasr[4];
41+ uint16_t fir;
42+ uint8_t nmisr;
43+ uint8_t nmier;
44+ uint8_t nmiclr;
45+ uint8_t nmicr;
46+ int req_irq;
47+ qemu_irq _irq;
48+ qemu_irq _fir;
49+ qemu_irq _swi;
50+};
51+typedef struct RXICUState RXICUState;
52+
53+#define TYPE_RXICU "rx-icu"
54+#define RXICU(obj) OBJECT_CHECK(RXICUState, (obj), TYPE_RXICU)
55+
56+#endif /* RX_ICU_H */