]> git.proxmox.com Git - mirror_qemu.git/blame - hw/rx/rx62n.c
Use DECLARE_*CHECKER* macros
[mirror_qemu.git] / hw / rx / rx62n.c
CommitLineData
0c80f50f
YS
1/*
2 * RX62N Microcontroller
3 *
4 * Datasheet: RX62N Group, RX621 Group User's Manual: Hardware
5 * (Rev.1.40 R01UH0033EJ0140)
6 *
7 * Copyright (c) 2019 Yoshinori Sato
1db2086e 8 * Copyright (c) 2020 Philippe Mathieu-Daudé
0c80f50f
YS
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms and conditions of the GNU General Public License,
12 * version 2 or later, as published by the Free Software Foundation.
13 *
14 * This program is distributed in the hope it will be useful, but WITHOUT
15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17 * more details.
18 *
19 * You should have received a copy of the GNU General Public License along with
20 * this program. If not, see <http://www.gnu.org/licenses/>.
21 */
22
23#include "qemu/osdep.h"
24#include "qapi/error.h"
7d272cb4 25#include "qemu/error-report.h"
0c80f50f
YS
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"
7d272cb4 32#include "sysemu/qtest.h"
0c80f50f 33#include "cpu.h"
db1015e9 34#include "qom/object.h"
0c80f50f
YS
35
36/*
37 * RX62N Internal Memory
38 */
39#define RX62N_IRAM_BASE 0x00000000
40#define RX62N_DFLASH_BASE 0x00100000
41#define RX62N_CFLASH_BASE 0xfff80000
42
43/*
44 * RX62N Peripheral Address
45 * See users manual section 5
46 */
47#define RX62N_ICU_BASE 0x00087000
48#define RX62N_TMR_BASE 0x00088200
49#define RX62N_CMT_BASE 0x00088000
50#define RX62N_SCI_BASE 0x00088240
51
52/*
53 * RX62N Peripheral IRQ
54 * See users manual section 11
55 */
56#define RX62N_TMR_IRQ 174
57#define RX62N_CMT_IRQ 28
58#define RX62N_SCI_IRQ 214
59
1db2086e
PMD
60#define RX62N_XTAL_MIN_HZ (8 * 1000 * 1000)
61#define RX62N_XTAL_MAX_HZ (14 * 1000 * 1000)
62#define RX62N_PCLK_MAX_HZ (50 * 1000 * 1000)
63
db1015e9 64struct RX62NClass {
1db2086e
PMD
65 /*< private >*/
66 DeviceClass parent_class;
67 /*< public >*/
68 const char *name;
69 uint64_t ram_size;
70 uint64_t rom_flash_size;
71 uint64_t data_flash_size;
db1015e9
EH
72};
73typedef struct RX62NClass RX62NClass;
1db2086e 74
8110fa1d
EH
75DECLARE_CLASS_CHECKERS(RX62NClass, RX62N_MCU,
76 TYPE_RX62N_MCU)
1db2086e 77
0c80f50f
YS
78/*
79 * IRQ -> IPR mapping table
80 * 0x00 - 0x91: IPR no (IPR00 to IPR91)
81 * 0xff: IPR not assigned
82 * See "11.3.1 Interrupt Vector Table" in hardware manual.
83 */
84static const uint8_t ipr_table[NR_IRQS] = {
85 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
86 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 15 */
87 0x00, 0xff, 0xff, 0xff, 0xff, 0x01, 0xff, 0x02,
88 0xff, 0xff, 0xff, 0x03, 0x04, 0x05, 0x06, 0x07, /* 31 */
89 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
90 0x10, 0x11, 0x12, 0x13, 0x14, 0x14, 0x14, 0x14, /* 47 */
91 0x15, 0x15, 0x15, 0x15, 0xff, 0xff, 0xff, 0xff,
92 0x18, 0x18, 0x18, 0x18, 0x18, 0x1d, 0x1e, 0x1f, /* 63 */
93 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
94 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 79 */
95 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
96 0xff, 0xff, 0x3a, 0x3b, 0x3c, 0xff, 0xff, 0xff, /* 95 */
97 0x40, 0xff, 0x44, 0x45, 0xff, 0xff, 0x48, 0xff,
98 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 111 */
99 0xff, 0xff, 0x51, 0x51, 0x51, 0x51, 0x52, 0x52,
100 0x52, 0x53, 0x53, 0x54, 0x54, 0x55, 0x55, 0x56, /* 127 */
101 0x56, 0x57, 0x57, 0x57, 0x57, 0x58, 0x59, 0x59,
102 0x59, 0x59, 0x5a, 0x5b, 0x5b, 0x5b, 0x5c, 0x5c, /* 143 */
103 0x5c, 0x5c, 0x5d, 0x5d, 0x5d, 0x5e, 0x5e, 0x5f,
104 0x5f, 0x60, 0x60, 0x61, 0x61, 0x62, 0x62, 0x62, /* 159 */
105 0x62, 0x63, 0x64, 0x64, 0x64, 0x64, 0x65, 0x66,
106 0x66, 0x66, 0x67, 0x67, 0x67, 0x67, 0x68, 0x68, /* 175 */
107 0x68, 0x69, 0x69, 0x69, 0x6a, 0x6a, 0x6a, 0x6b,
108 0x6b, 0x6b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 191 */
109 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x70, 0x71,
110 0x72, 0x73, 0x74, 0x75, 0xff, 0xff, 0xff, 0xff, /* 207 */
111 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x80,
112 0x80, 0x80, 0x81, 0x81, 0x81, 0x81, 0x82, 0x82, /* 223 */
113 0x82, 0x82, 0x83, 0x83, 0x83, 0x83, 0xff, 0xff,
114 0xff, 0xff, 0x85, 0x85, 0x85, 0x85, 0x86, 0x86, /* 239 */
115 0x86, 0x86, 0xff, 0xff, 0xff, 0xff, 0x88, 0x89,
116 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, /* 255 */
117};
118
119/*
120 * Level triggerd IRQ list
121 * Not listed IRQ is Edge trigger.
122 * See "11.3.1 Interrupt Vector Table" in hardware manual.
123 */
124static const uint8_t levelirq[] = {
125 16, 21, 32, 44, 47, 48, 51, 64, 65, 66,
126 67, 68, 69, 70, 71, 72, 73, 74, 75, 76,
127 77, 78, 79, 90, 91, 170, 171, 172, 173, 214,
128 217, 218, 221, 222, 225, 226, 229, 234, 237, 238,
129 241, 246, 249, 250, 253,
130};
131
132static void register_icu(RX62NState *s)
133{
134 int i;
135 SysBusDevice *icu;
136
137 object_initialize_child(OBJECT(s), "icu", &s->icu, TYPE_RX_ICU);
138 icu = SYS_BUS_DEVICE(&s->icu);
139 qdev_prop_set_uint32(DEVICE(icu), "len-ipr-map", NR_IRQS);
140 for (i = 0; i < NR_IRQS; i++) {
141 char propname[32];
142 snprintf(propname, sizeof(propname), "ipr-map[%d]", i);
143 qdev_prop_set_uint32(DEVICE(icu), propname, ipr_table[i]);
144 }
145 qdev_prop_set_uint32(DEVICE(icu), "len-trigger-level",
146 ARRAY_SIZE(levelirq));
147 for (i = 0; i < ARRAY_SIZE(levelirq); i++) {
148 char propname[32];
149 snprintf(propname, sizeof(propname), "trigger-level[%d]", i);
150 qdev_prop_set_uint32(DEVICE(icu), propname, levelirq[i]);
151 }
152
153 for (i = 0; i < NR_IRQS; i++) {
154 s->irq[i] = qdev_get_gpio_in(DEVICE(icu), i);
155 }
156 sysbus_realize(icu, &error_abort);
157 sysbus_connect_irq(icu, 0, qdev_get_gpio_in(DEVICE(&s->cpu), RX_CPU_IRQ));
158 sysbus_connect_irq(icu, 1, qdev_get_gpio_in(DEVICE(&s->cpu), RX_CPU_FIR));
159 sysbus_connect_irq(icu, 2, s->irq[SWI]);
160 sysbus_mmio_map(SYS_BUS_DEVICE(icu), 0, RX62N_ICU_BASE);
161}
162
163static void register_tmr(RX62NState *s, int unit)
164{
165 SysBusDevice *tmr;
166 int i, irqbase;
167
168 object_initialize_child(OBJECT(s), "tmr[*]",
169 &s->tmr[unit], TYPE_RENESAS_TMR);
170 tmr = SYS_BUS_DEVICE(&s->tmr[unit]);
1db2086e 171 qdev_prop_set_uint64(DEVICE(tmr), "input-freq", s->pclk_freq_hz);
0c80f50f
YS
172 sysbus_realize(tmr, &error_abort);
173
174 irqbase = RX62N_TMR_IRQ + TMR_NR_IRQ * unit;
175 for (i = 0; i < TMR_NR_IRQ; i++) {
176 sysbus_connect_irq(tmr, i, s->irq[irqbase + i]);
177 }
178 sysbus_mmio_map(tmr, 0, RX62N_TMR_BASE + unit * 0x10);
179}
180
181static void register_cmt(RX62NState *s, int unit)
182{
183 SysBusDevice *cmt;
184 int i, irqbase;
185
186 object_initialize_child(OBJECT(s), "cmt[*]",
187 &s->cmt[unit], TYPE_RENESAS_CMT);
188 cmt = SYS_BUS_DEVICE(&s->cmt[unit]);
1db2086e 189 qdev_prop_set_uint64(DEVICE(cmt), "input-freq", s->pclk_freq_hz);
0c80f50f
YS
190 sysbus_realize(cmt, &error_abort);
191
192 irqbase = RX62N_CMT_IRQ + CMT_NR_IRQ * unit;
193 for (i = 0; i < CMT_NR_IRQ; i++) {
194 sysbus_connect_irq(cmt, i, s->irq[irqbase + i]);
195 }
196 sysbus_mmio_map(cmt, 0, RX62N_CMT_BASE + unit * 0x10);
197}
198
199static void register_sci(RX62NState *s, int unit)
200{
201 SysBusDevice *sci;
202 int i, irqbase;
203
204 object_initialize_child(OBJECT(s), "sci[*]",
205 &s->sci[unit], TYPE_RENESAS_SCI);
206 sci = SYS_BUS_DEVICE(&s->sci[unit]);
207 qdev_prop_set_chr(DEVICE(sci), "chardev", serial_hd(unit));
1db2086e 208 qdev_prop_set_uint64(DEVICE(sci), "input-freq", s->pclk_freq_hz);
0c80f50f
YS
209 sysbus_realize(sci, &error_abort);
210
211 irqbase = RX62N_SCI_IRQ + SCI_NR_IRQ * unit;
212 for (i = 0; i < SCI_NR_IRQ; i++) {
213 sysbus_connect_irq(sci, i, s->irq[irqbase + i]);
214 }
215 sysbus_mmio_map(sci, 0, RX62N_SCI_BASE + unit * 0x08);
216}
217
218static void rx62n_realize(DeviceState *dev, Error **errp)
219{
220 RX62NState *s = RX62N_MCU(dev);
1db2086e
PMD
221 RX62NClass *rxc = RX62N_MCU_GET_CLASS(dev);
222
223 if (s->xtal_freq_hz == 0) {
224 error_setg(errp, "\"xtal-frequency-hz\" property must be provided.");
225 return;
226 }
227 /* XTAL range: 8-14 MHz */
228 if (s->xtal_freq_hz < RX62N_XTAL_MIN_HZ
229 || s->xtal_freq_hz > RX62N_XTAL_MAX_HZ) {
230 error_setg(errp, "\"xtal-frequency-hz\" property in incorrect range.");
231 return;
232 }
233 /* Use a 4x fixed multiplier */
234 s->pclk_freq_hz = 4 * s->xtal_freq_hz;
235 /* PCLK range: 8-50 MHz */
236 assert(s->pclk_freq_hz <= RX62N_PCLK_MAX_HZ);
0c80f50f
YS
237
238 memory_region_init_ram(&s->iram, OBJECT(dev), "iram",
1db2086e 239 rxc->ram_size, &error_abort);
0c80f50f
YS
240 memory_region_add_subregion(s->sysmem, RX62N_IRAM_BASE, &s->iram);
241 memory_region_init_rom(&s->d_flash, OBJECT(dev), "flash-data",
1db2086e 242 rxc->data_flash_size, &error_abort);
0c80f50f
YS
243 memory_region_add_subregion(s->sysmem, RX62N_DFLASH_BASE, &s->d_flash);
244 memory_region_init_rom(&s->c_flash, OBJECT(dev), "flash-code",
1db2086e 245 rxc->rom_flash_size, &error_abort);
0c80f50f
YS
246 memory_region_add_subregion(s->sysmem, RX62N_CFLASH_BASE, &s->c_flash);
247
248 if (!s->kernel) {
7d272cb4
RH
249 if (bios_name) {
250 rom_add_file_fixed(bios_name, RX62N_CFLASH_BASE, 0);
251 } else if (!qtest_enabled()) {
252 error_report("No bios or kernel specified");
253 exit(1);
254 }
0c80f50f
YS
255 }
256
257 /* Initialize CPU */
258 object_initialize_child(OBJECT(s), "cpu", &s->cpu, TYPE_RX62N_CPU);
259 qdev_realize(DEVICE(&s->cpu), NULL, &error_abort);
260
261 register_icu(s);
262 s->cpu.env.ack = qdev_get_gpio_in_named(DEVICE(&s->icu), "ack", 0);
263 register_tmr(s, 0);
264 register_tmr(s, 1);
265 register_cmt(s, 0);
266 register_cmt(s, 1);
267 register_sci(s, 0);
268}
269
270static Property rx62n_properties[] = {
271 DEFINE_PROP_LINK("main-bus", RX62NState, sysmem, TYPE_MEMORY_REGION,
272 MemoryRegion *),
273 DEFINE_PROP_BOOL("load-kernel", RX62NState, kernel, false),
1db2086e 274 DEFINE_PROP_UINT32("xtal-frequency-hz", RX62NState, xtal_freq_hz, 0),
0c80f50f
YS
275 DEFINE_PROP_END_OF_LIST(),
276};
277
278static void rx62n_class_init(ObjectClass *klass, void *data)
279{
280 DeviceClass *dc = DEVICE_CLASS(klass);
281
282 dc->realize = rx62n_realize;
283 device_class_set_props(dc, rx62n_properties);
284}
285
1db2086e
PMD
286static void r5f562n7_class_init(ObjectClass *oc, void *data)
287{
288 RX62NClass *rxc = RX62N_MCU_CLASS(oc);
289
290 rxc->ram_size = 64 * KiB;
291 rxc->rom_flash_size = 384 * KiB;
292 rxc->data_flash_size = 32 * KiB;
0c80f50f
YS
293};
294
1db2086e 295static void r5f562n8_class_init(ObjectClass *oc, void *data)
0c80f50f 296{
1db2086e
PMD
297 RX62NClass *rxc = RX62N_MCU_CLASS(oc);
298
299 rxc->ram_size = 96 * KiB;
300 rxc->rom_flash_size = 512 * KiB;
301 rxc->data_flash_size = 32 * KiB;
302};
303
304static const TypeInfo rx62n_types[] = {
305 {
306 .name = TYPE_R5F562N7_MCU,
307 .parent = TYPE_RX62N_MCU,
308 .class_init = r5f562n7_class_init,
309 }, {
310 .name = TYPE_R5F562N8_MCU,
311 .parent = TYPE_RX62N_MCU,
312 .class_init = r5f562n8_class_init,
313 }, {
314 .name = TYPE_RX62N_MCU,
315 .parent = TYPE_DEVICE,
316 .instance_size = sizeof(RX62NState),
317 .class_size = sizeof(RX62NClass),
318 .class_init = rx62n_class_init,
319 .abstract = true,
320 }
321};
0c80f50f 322
1db2086e 323DEFINE_TYPES(rx62n_types)