2 * RX62N Microcontroller
4 * Datasheet: RX62N Group, RX621 Group User's Manual: Hardware
5 * (Rev.1.40 R01UH0033EJ0140)
7 * Copyright (c) 2019 Yoshinori Sato
8 * Copyright (c) 2020 Philippe Mathieu-Daudé
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.
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
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/>.
23 #include "qemu/osdep.h"
24 #include "qapi/error.h"
25 #include "qemu/error-report.h"
26 #include "qemu/units.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 "qapi/qmp/qlist.h"
33 #include "qom/object.h"
36 * RX62N Internal Memory
38 #define RX62N_IRAM_BASE 0x00000000
39 #define RX62N_DFLASH_BASE 0x00100000
40 #define RX62N_CFLASH_BASE 0xfff80000
43 * RX62N Peripheral Address
44 * See users manual section 5
46 #define RX62N_ICU_BASE 0x00087000
47 #define RX62N_TMR_BASE 0x00088200
48 #define RX62N_CMT_BASE 0x00088000
49 #define RX62N_SCI_BASE 0x00088240
52 * RX62N Peripheral IRQ
53 * See users manual section 11
55 #define RX62N_TMR_IRQ 174
56 #define RX62N_CMT_IRQ 28
57 #define RX62N_SCI_IRQ 214
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)
65 DeviceClass parent_class
;
69 uint64_t rom_flash_size
;
70 uint64_t data_flash_size
;
72 typedef struct RX62NClass RX62NClass
;
74 DECLARE_CLASS_CHECKERS(RX62NClass
, RX62N_MCU
,
78 * IRQ -> IPR mapping table
79 * 0x00 - 0x91: IPR no (IPR00 to IPR91)
80 * 0xff: IPR not assigned
81 * See "11.3.1 Interrupt Vector Table" in hardware manual.
83 static 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, /* 15 */
86 0x00, 0xff, 0xff, 0xff, 0xff, 0x01, 0xff, 0x02,
87 0xff, 0xff, 0xff, 0x03, 0x04, 0x05, 0x06, 0x07, /* 31 */
88 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
89 0x10, 0x11, 0x12, 0x13, 0x14, 0x14, 0x14, 0x14, /* 47 */
90 0x15, 0x15, 0x15, 0x15, 0xff, 0xff, 0xff, 0xff,
91 0x18, 0x18, 0x18, 0x18, 0x18, 0x1d, 0x1e, 0x1f, /* 63 */
92 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
93 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 79 */
94 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
95 0xff, 0xff, 0x3a, 0x3b, 0x3c, 0xff, 0xff, 0xff, /* 95 */
96 0x40, 0xff, 0x44, 0x45, 0xff, 0xff, 0x48, 0xff,
97 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 111 */
98 0xff, 0xff, 0x51, 0x51, 0x51, 0x51, 0x52, 0x52,
99 0x52, 0x53, 0x53, 0x54, 0x54, 0x55, 0x55, 0x56, /* 127 */
100 0x56, 0x57, 0x57, 0x57, 0x57, 0x58, 0x59, 0x59,
101 0x59, 0x59, 0x5a, 0x5b, 0x5b, 0x5b, 0x5c, 0x5c, /* 143 */
102 0x5c, 0x5c, 0x5d, 0x5d, 0x5d, 0x5e, 0x5e, 0x5f,
103 0x5f, 0x60, 0x60, 0x61, 0x61, 0x62, 0x62, 0x62, /* 159 */
104 0x62, 0x63, 0x64, 0x64, 0x64, 0x64, 0x65, 0x66,
105 0x66, 0x66, 0x67, 0x67, 0x67, 0x67, 0x68, 0x68, /* 175 */
106 0x68, 0x69, 0x69, 0x69, 0x6a, 0x6a, 0x6a, 0x6b,
107 0x6b, 0x6b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 191 */
108 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x70, 0x71,
109 0x72, 0x73, 0x74, 0x75, 0xff, 0xff, 0xff, 0xff, /* 207 */
110 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x80,
111 0x80, 0x80, 0x81, 0x81, 0x81, 0x81, 0x82, 0x82, /* 223 */
112 0x82, 0x82, 0x83, 0x83, 0x83, 0x83, 0xff, 0xff,
113 0xff, 0xff, 0x85, 0x85, 0x85, 0x85, 0x86, 0x86, /* 239 */
114 0x86, 0x86, 0xff, 0xff, 0xff, 0xff, 0x88, 0x89,
115 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, /* 255 */
119 * Level triggered IRQ list
120 * Not listed IRQ is Edge trigger.
121 * See "11.3.1 Interrupt Vector Table" in hardware manual.
123 static 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,
131 static void register_icu(RX62NState
*s
)
135 QList
*ipr_map
, *trigger_level
;
137 object_initialize_child(OBJECT(s
), "icu", &s
->icu
, TYPE_RX_ICU
);
138 icu
= SYS_BUS_DEVICE(&s
->icu
);
140 ipr_map
= qlist_new();
141 for (i
= 0; i
< NR_IRQS
; i
++) {
142 qlist_append_int(ipr_map
, ipr_table
[i
]);
144 qdev_prop_set_array(DEVICE(icu
), "ipr-map", ipr_map
);
146 trigger_level
= qlist_new();
147 for (i
= 0; i
< ARRAY_SIZE(levelirq
); i
++) {
148 qlist_append_int(trigger_level
, levelirq
[i
]);
150 qdev_prop_set_array(DEVICE(icu
), "trigger-level", trigger_level
);
151 sysbus_realize(icu
, &error_abort
);
153 sysbus_connect_irq(icu
, 0, qdev_get_gpio_in(DEVICE(&s
->cpu
), RX_CPU_IRQ
));
154 sysbus_connect_irq(icu
, 1, qdev_get_gpio_in(DEVICE(&s
->cpu
), RX_CPU_FIR
));
155 sysbus_connect_irq(icu
, 2, qdev_get_gpio_in(DEVICE(&s
->icu
), SWI
));
156 sysbus_mmio_map(icu
, 0, RX62N_ICU_BASE
);
159 static void register_tmr(RX62NState
*s
, int unit
)
164 object_initialize_child(OBJECT(s
), "tmr[*]",
165 &s
->tmr
[unit
], TYPE_RENESAS_TMR
);
166 tmr
= SYS_BUS_DEVICE(&s
->tmr
[unit
]);
167 qdev_prop_set_uint64(DEVICE(tmr
), "input-freq", s
->pclk_freq_hz
);
168 sysbus_realize(tmr
, &error_abort
);
170 irqbase
= RX62N_TMR_IRQ
+ TMR_NR_IRQ
* unit
;
171 for (i
= 0; i
< TMR_NR_IRQ
; i
++) {
172 sysbus_connect_irq(tmr
, i
,
173 qdev_get_gpio_in(DEVICE(&s
->icu
), irqbase
+ i
));
175 sysbus_mmio_map(tmr
, 0, RX62N_TMR_BASE
+ unit
* 0x10);
178 static void register_cmt(RX62NState
*s
, int unit
)
183 object_initialize_child(OBJECT(s
), "cmt[*]",
184 &s
->cmt
[unit
], TYPE_RENESAS_CMT
);
185 cmt
= SYS_BUS_DEVICE(&s
->cmt
[unit
]);
186 qdev_prop_set_uint64(DEVICE(cmt
), "input-freq", s
->pclk_freq_hz
);
187 sysbus_realize(cmt
, &error_abort
);
189 irqbase
= RX62N_CMT_IRQ
+ CMT_NR_IRQ
* unit
;
190 for (i
= 0; i
< CMT_NR_IRQ
; i
++) {
191 sysbus_connect_irq(cmt
, i
,
192 qdev_get_gpio_in(DEVICE(&s
->icu
), irqbase
+ i
));
194 sysbus_mmio_map(cmt
, 0, RX62N_CMT_BASE
+ unit
* 0x10);
197 static void register_sci(RX62NState
*s
, int unit
)
202 object_initialize_child(OBJECT(s
), "sci[*]",
203 &s
->sci
[unit
], TYPE_RENESAS_SCI
);
204 sci
= SYS_BUS_DEVICE(&s
->sci
[unit
]);
205 qdev_prop_set_chr(DEVICE(sci
), "chardev", serial_hd(unit
));
206 qdev_prop_set_uint64(DEVICE(sci
), "input-freq", s
->pclk_freq_hz
);
207 sysbus_realize(sci
, &error_abort
);
209 irqbase
= RX62N_SCI_IRQ
+ SCI_NR_IRQ
* unit
;
210 for (i
= 0; i
< SCI_NR_IRQ
; i
++) {
211 sysbus_connect_irq(sci
, i
,
212 qdev_get_gpio_in(DEVICE(&s
->icu
), irqbase
+ i
));
214 sysbus_mmio_map(sci
, 0, RX62N_SCI_BASE
+ unit
* 0x08);
217 static void rx62n_realize(DeviceState
*dev
, Error
**errp
)
219 RX62NState
*s
= RX62N_MCU(dev
);
220 RX62NClass
*rxc
= RX62N_MCU_GET_CLASS(dev
);
222 if (s
->xtal_freq_hz
== 0) {
223 error_setg(errp
, "\"xtal-frequency-hz\" property must be provided.");
226 /* XTAL range: 8-14 MHz */
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.");
232 /* Use a 4x fixed multiplier */
233 s
->pclk_freq_hz
= 4 * s
->xtal_freq_hz
;
234 /* PCLK range: 8-50 MHz */
235 assert(s
->pclk_freq_hz
<= RX62N_PCLK_MAX_HZ
);
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
);
248 object_initialize_child(OBJECT(s
), "cpu", &s
->cpu
, TYPE_RX62N_CPU
);
249 qdev_realize(DEVICE(&s
->cpu
), NULL
, &error_abort
);
252 s
->cpu
.env
.ack
= qdev_get_gpio_in_named(DEVICE(&s
->icu
), "ack", 0);
260 static Property rx62n_properties
[] = {
261 DEFINE_PROP_LINK("main-bus", RX62NState
, sysmem
, TYPE_MEMORY_REGION
,
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(),
268 static void rx62n_class_init(ObjectClass
*klass
, void *data
)
270 DeviceClass
*dc
= DEVICE_CLASS(klass
);
272 dc
->realize
= rx62n_realize
;
273 device_class_set_props(dc
, rx62n_properties
);
276 static void r5f562n7_class_init(ObjectClass
*oc
, void *data
)
278 RX62NClass
*rxc
= RX62N_MCU_CLASS(oc
);
280 rxc
->ram_size
= 64 * KiB
;
281 rxc
->rom_flash_size
= 384 * KiB
;
282 rxc
->data_flash_size
= 32 * KiB
;
285 static void r5f562n8_class_init(ObjectClass
*oc
, void *data
)
287 RX62NClass
*rxc
= RX62N_MCU_CLASS(oc
);
289 rxc
->ram_size
= 96 * KiB
;
290 rxc
->rom_flash_size
= 512 * KiB
;
291 rxc
->data_flash_size
= 32 * KiB
;
294 static const TypeInfo rx62n_types
[] = {
296 .name
= TYPE_R5F562N7_MCU
,
297 .parent
= TYPE_RX62N_MCU
,
298 .class_init
= r5f562n7_class_init
,
300 .name
= TYPE_R5F562N8_MCU
,
301 .parent
= TYPE_RX62N_MCU
,
302 .class_init
= r5f562n8_class_init
,
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
,
313 DEFINE_TYPES(rx62n_types
)