1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23#include "qemu/osdep.h"
24#include "qapi/error.h"
25#include "qemu/error-report.h"
26#include "hw/hw.h"
27#include "hw/rx/rx62n.h"
28#include "hw/loader.h"
29#include "hw/sysbus.h"
30#include "hw/qdev-properties.h"
31#include "sysemu/sysemu.h"
32#include "cpu.h"
33#include "qom/object.h"
34
35
36
37
38#define RX62N_IRAM_BASE 0x00000000
39#define RX62N_DFLASH_BASE 0x00100000
40#define RX62N_CFLASH_BASE 0xfff80000
41
42
43
44
45
46#define RX62N_ICU_BASE 0x00087000
47#define RX62N_TMR_BASE 0x00088200
48#define RX62N_CMT_BASE 0x00088000
49#define RX62N_SCI_BASE 0x00088240
50
51
52
53
54
55#define RX62N_TMR_IRQ 174
56#define RX62N_CMT_IRQ 28
57#define RX62N_SCI_IRQ 214
58
59#define RX62N_XTAL_MIN_HZ (8 * 1000 * 1000)
60#define RX62N_XTAL_MAX_HZ (14 * 1000 * 1000)
61#define RX62N_PCLK_MAX_HZ (50 * 1000 * 1000)
62
63struct RX62NClass {
64
65 DeviceClass parent_class;
66
67 const char *name;
68 uint64_t ram_size;
69 uint64_t rom_flash_size;
70 uint64_t data_flash_size;
71};
72typedef struct RX62NClass RX62NClass;
73
74DECLARE_CLASS_CHECKERS(RX62NClass, RX62N_MCU,
75 TYPE_RX62N_MCU)
76
77
78
79
80
81
82
83static const uint8_t ipr_table[NR_IRQS] = {
84 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
85 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
86 0x00, 0xff, 0xff, 0xff, 0xff, 0x01, 0xff, 0x02,
87 0xff, 0xff, 0xff, 0x03, 0x04, 0x05, 0x06, 0x07,
88 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
89 0x10, 0x11, 0x12, 0x13, 0x14, 0x14, 0x14, 0x14,
90 0x15, 0x15, 0x15, 0x15, 0xff, 0xff, 0xff, 0xff,
91 0x18, 0x18, 0x18, 0x18, 0x18, 0x1d, 0x1e, 0x1f,
92 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
93 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
94 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
95 0xff, 0xff, 0x3a, 0x3b, 0x3c, 0xff, 0xff, 0xff,
96 0x40, 0xff, 0x44, 0x45, 0xff, 0xff, 0x48, 0xff,
97 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
98 0xff, 0xff, 0x51, 0x51, 0x51, 0x51, 0x52, 0x52,
99 0x52, 0x53, 0x53, 0x54, 0x54, 0x55, 0x55, 0x56,
100 0x56, 0x57, 0x57, 0x57, 0x57, 0x58, 0x59, 0x59,
101 0x59, 0x59, 0x5a, 0x5b, 0x5b, 0x5b, 0x5c, 0x5c,
102 0x5c, 0x5c, 0x5d, 0x5d, 0x5d, 0x5e, 0x5e, 0x5f,
103 0x5f, 0x60, 0x60, 0x61, 0x61, 0x62, 0x62, 0x62,
104 0x62, 0x63, 0x64, 0x64, 0x64, 0x64, 0x65, 0x66,
105 0x66, 0x66, 0x67, 0x67, 0x67, 0x67, 0x68, 0x68,
106 0x68, 0x69, 0x69, 0x69, 0x6a, 0x6a, 0x6a, 0x6b,
107 0x6b, 0x6b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
108 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x70, 0x71,
109 0x72, 0x73, 0x74, 0x75, 0xff, 0xff, 0xff, 0xff,
110 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x80,
111 0x80, 0x80, 0x81, 0x81, 0x81, 0x81, 0x82, 0x82,
112 0x82, 0x82, 0x83, 0x83, 0x83, 0x83, 0xff, 0xff,
113 0xff, 0xff, 0x85, 0x85, 0x85, 0x85, 0x86, 0x86,
114 0x86, 0x86, 0xff, 0xff, 0xff, 0xff, 0x88, 0x89,
115 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91,
116};
117
118
119
120
121
122
123static const uint8_t levelirq[] = {
124 16, 21, 32, 44, 47, 48, 51, 64, 65, 66,
125 67, 68, 69, 70, 71, 72, 73, 74, 75, 76,
126 77, 78, 79, 90, 91, 170, 171, 172, 173, 214,
127 217, 218, 221, 222, 225, 226, 229, 234, 237, 238,
128 241, 246, 249, 250, 253,
129};
130
131static void register_icu(RX62NState *s)
132{
133 int i;
134 SysBusDevice *icu;
135
136 object_initialize_child(OBJECT(s), "icu", &s->icu, TYPE_RX_ICU);
137 icu = SYS_BUS_DEVICE(&s->icu);
138 qdev_prop_set_uint32(DEVICE(icu), "len-ipr-map", NR_IRQS);
139 for (i = 0; i < NR_IRQS; i++) {
140 char propname[32];
141 snprintf(propname, sizeof(propname), "ipr-map[%d]", i);
142 qdev_prop_set_uint32(DEVICE(icu), propname, ipr_table[i]);
143 }
144 qdev_prop_set_uint32(DEVICE(icu), "len-trigger-level",
145 ARRAY_SIZE(levelirq));
146 for (i = 0; i < ARRAY_SIZE(levelirq); i++) {
147 char propname[32];
148 snprintf(propname, sizeof(propname), "trigger-level[%d]", i);
149 qdev_prop_set_uint32(DEVICE(icu), propname, levelirq[i]);
150 }
151
152 for (i = 0; i < NR_IRQS; i++) {
153 s->irq[i] = qdev_get_gpio_in(DEVICE(icu), i);
154 }
155 sysbus_realize(icu, &error_abort);
156 sysbus_connect_irq(icu, 0, qdev_get_gpio_in(DEVICE(&s->cpu), RX_CPU_IRQ));
157 sysbus_connect_irq(icu, 1, qdev_get_gpio_in(DEVICE(&s->cpu), RX_CPU_FIR));
158 sysbus_connect_irq(icu, 2, s->irq[SWI]);
159 sysbus_mmio_map(SYS_BUS_DEVICE(icu), 0, RX62N_ICU_BASE);
160}
161
162static void register_tmr(RX62NState *s, int unit)
163{
164 SysBusDevice *tmr;
165 int i, irqbase;
166
167 object_initialize_child(OBJECT(s), "tmr[*]",
168 &s->tmr[unit], TYPE_RENESAS_TMR);
169 tmr = SYS_BUS_DEVICE(&s->tmr[unit]);
170 qdev_prop_set_uint64(DEVICE(tmr), "input-freq", s->pclk_freq_hz);
171 sysbus_realize(tmr, &error_abort);
172
173 irqbase = RX62N_TMR_IRQ + TMR_NR_IRQ * unit;
174 for (i = 0; i < TMR_NR_IRQ; i++) {
175 sysbus_connect_irq(tmr, i, s->irq[irqbase + i]);
176 }
177 sysbus_mmio_map(tmr, 0, RX62N_TMR_BASE + unit * 0x10);
178}
179
180static void register_cmt(RX62NState *s, int unit)
181{
182 SysBusDevice *cmt;
183 int i, irqbase;
184
185 object_initialize_child(OBJECT(s), "cmt[*]",
186 &s->cmt[unit], TYPE_RENESAS_CMT);
187 cmt = SYS_BUS_DEVICE(&s->cmt[unit]);
188 qdev_prop_set_uint64(DEVICE(cmt), "input-freq", s->pclk_freq_hz);
189 sysbus_realize(cmt, &error_abort);
190
191 irqbase = RX62N_CMT_IRQ + CMT_NR_IRQ * unit;
192 for (i = 0; i < CMT_NR_IRQ; i++) {
193 sysbus_connect_irq(cmt, i, s->irq[irqbase + i]);
194 }
195 sysbus_mmio_map(cmt, 0, RX62N_CMT_BASE + unit * 0x10);
196}
197
198static void register_sci(RX62NState *s, int unit)
199{
200 SysBusDevice *sci;
201 int i, irqbase;
202
203 object_initialize_child(OBJECT(s), "sci[*]",
204 &s->sci[unit], TYPE_RENESAS_SCI);
205 sci = SYS_BUS_DEVICE(&s->sci[unit]);
206 qdev_prop_set_chr(DEVICE(sci), "chardev", serial_hd(unit));
207 qdev_prop_set_uint64(DEVICE(sci), "input-freq", s->pclk_freq_hz);
208 sysbus_realize(sci, &error_abort);
209
210 irqbase = RX62N_SCI_IRQ + SCI_NR_IRQ * unit;
211 for (i = 0; i < SCI_NR_IRQ; i++) {
212 sysbus_connect_irq(sci, i, s->irq[irqbase + i]);
213 }
214 sysbus_mmio_map(sci, 0, RX62N_SCI_BASE + unit * 0x08);
215}
216
217static void rx62n_realize(DeviceState *dev, Error **errp)
218{
219 RX62NState *s = RX62N_MCU(dev);
220 RX62NClass *rxc = RX62N_MCU_GET_CLASS(dev);
221
222 if (s->xtal_freq_hz == 0) {
223 error_setg(errp, "\"xtal-frequency-hz\" property must be provided.");
224 return;
225 }
226
227 if (s->xtal_freq_hz < RX62N_XTAL_MIN_HZ
228 || s->xtal_freq_hz > RX62N_XTAL_MAX_HZ) {
229 error_setg(errp, "\"xtal-frequency-hz\" property in incorrect range.");
230 return;
231 }
232
233 s->pclk_freq_hz = 4 * s->xtal_freq_hz;
234
235 assert(s->pclk_freq_hz <= RX62N_PCLK_MAX_HZ);
236
237 memory_region_init_ram(&s->iram, OBJECT(dev), "iram",
238 rxc->ram_size, &error_abort);
239 memory_region_add_subregion(s->sysmem, RX62N_IRAM_BASE, &s->iram);
240 memory_region_init_rom(&s->d_flash, OBJECT(dev), "flash-data",
241 rxc->data_flash_size, &error_abort);
242 memory_region_add_subregion(s->sysmem, RX62N_DFLASH_BASE, &s->d_flash);
243 memory_region_init_rom(&s->c_flash, OBJECT(dev), "flash-code",
244 rxc->rom_flash_size, &error_abort);
245 memory_region_add_subregion(s->sysmem, RX62N_CFLASH_BASE, &s->c_flash);
246
247
248 object_initialize_child(OBJECT(s), "cpu", &s->cpu, TYPE_RX62N_CPU);
249 qdev_realize(DEVICE(&s->cpu), NULL, &error_abort);
250
251 register_icu(s);
252 s->cpu.env.ack = qdev_get_gpio_in_named(DEVICE(&s->icu), "ack", 0);
253 register_tmr(s, 0);
254 register_tmr(s, 1);
255 register_cmt(s, 0);
256 register_cmt(s, 1);
257 register_sci(s, 0);
258}
259
260static Property rx62n_properties[] = {
261 DEFINE_PROP_LINK("main-bus", RX62NState, sysmem, TYPE_MEMORY_REGION,
262 MemoryRegion *),
263 DEFINE_PROP_BOOL("load-kernel", RX62NState, kernel, false),
264 DEFINE_PROP_UINT32("xtal-frequency-hz", RX62NState, xtal_freq_hz, 0),
265 DEFINE_PROP_END_OF_LIST(),
266};
267
268static void rx62n_class_init(ObjectClass *klass, void *data)
269{
270 DeviceClass *dc = DEVICE_CLASS(klass);
271
272 dc->realize = rx62n_realize;
273 device_class_set_props(dc, rx62n_properties);
274}
275
276static void r5f562n7_class_init(ObjectClass *oc, void *data)
277{
278 RX62NClass *rxc = RX62N_MCU_CLASS(oc);
279
280 rxc->ram_size = 64 * KiB;
281 rxc->rom_flash_size = 384 * KiB;
282 rxc->data_flash_size = 32 * KiB;
283};
284
285static void r5f562n8_class_init(ObjectClass *oc, void *data)
286{
287 RX62NClass *rxc = RX62N_MCU_CLASS(oc);
288
289 rxc->ram_size = 96 * KiB;
290 rxc->rom_flash_size = 512 * KiB;
291 rxc->data_flash_size = 32 * KiB;
292};
293
294static const TypeInfo rx62n_types[] = {
295 {
296 .name = TYPE_R5F562N7_MCU,
297 .parent = TYPE_RX62N_MCU,
298 .class_init = r5f562n7_class_init,
299 }, {
300 .name = TYPE_R5F562N8_MCU,
301 .parent = TYPE_RX62N_MCU,
302 .class_init = r5f562n8_class_init,
303 }, {
304 .name = TYPE_RX62N_MCU,
305 .parent = TYPE_DEVICE,
306 .instance_size = sizeof(RX62NState),
307 .class_size = sizeof(RX62NClass),
308 .class_init = rx62n_class_init,
309 .abstract = true,
310 }
311};
312
313DEFINE_TYPES(rx62n_types)
314