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