xref: /openbmc/qemu/hw/rx/rx62n.c (revision 2df1eb27)
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 
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 
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 
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 
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 
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 
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 
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 
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