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