xref: /openbmc/qemu/hw/rx/rx62n.c (revision 4011a686)
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/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"
32 #include "cpu.h"
33 #include "qom/object.h"
34 
35 /*
36  * RX62N Internal Memory
37  */
38 #define RX62N_IRAM_BASE     0x00000000
39 #define RX62N_DFLASH_BASE   0x00100000
40 #define RX62N_CFLASH_BASE   0xfff80000
41 
42 /*
43  * RX62N Peripheral Address
44  * See users manual section 5
45  */
46 #define RX62N_ICU_BASE  0x00087000
47 #define RX62N_TMR_BASE  0x00088200
48 #define RX62N_CMT_BASE  0x00088000
49 #define RX62N_SCI_BASE  0x00088240
50 
51 /*
52  * RX62N Peripheral IRQ
53  * See users manual section 11
54  */
55 #define RX62N_TMR_IRQ   174
56 #define RX62N_CMT_IRQ   28
57 #define RX62N_SCI_IRQ   214
58 
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)
62 
63 struct RX62NClass {
64     /*< private >*/
65     DeviceClass parent_class;
66     /*< public >*/
67     const char *name;
68     uint64_t ram_size;
69     uint64_t rom_flash_size;
70     uint64_t data_flash_size;
71 };
72 typedef struct RX62NClass RX62NClass;
73 
74 DECLARE_CLASS_CHECKERS(RX62NClass, RX62N_MCU,
75                        TYPE_RX62N_MCU)
76 
77 /*
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.
82  */
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 */
116 };
117 
118 /*
119  * Level triggerd IRQ list
120  * Not listed IRQ is Edge trigger.
121  * See "11.3.1 Interrupt Vector Table" in hardware manual.
122  */
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,
129 };
130 
131 static void register_icu(RX62NState *s)
132 {
133     int i;
134     SysBusDevice *icu;
135 
136     object_initialize_child(OBJECT(s), "icu", &s->icu, TYPE_RX_ICU);
137     icu = SYS_BUS_DEVICE(&s->icu);
138     qdev_prop_set_uint32(DEVICE(icu), "len-ipr-map", NR_IRQS);
139     for (i = 0; i < NR_IRQS; i++) {
140         char propname[32];
141         snprintf(propname, sizeof(propname), "ipr-map[%d]", i);
142         qdev_prop_set_uint32(DEVICE(icu), propname, ipr_table[i]);
143     }
144     qdev_prop_set_uint32(DEVICE(icu), "len-trigger-level",
145                          ARRAY_SIZE(levelirq));
146     for (i = 0; i < ARRAY_SIZE(levelirq); i++) {
147         char propname[32];
148         snprintf(propname, sizeof(propname), "trigger-level[%d]", i);
149         qdev_prop_set_uint32(DEVICE(icu), propname, levelirq[i]);
150     }
151 
152     for (i = 0; i < NR_IRQS; i++) {
153         s->irq[i] = qdev_get_gpio_in(DEVICE(icu), i);
154     }
155     sysbus_realize(icu, &error_abort);
156     sysbus_connect_irq(icu, 0, qdev_get_gpio_in(DEVICE(&s->cpu), RX_CPU_IRQ));
157     sysbus_connect_irq(icu, 1, qdev_get_gpio_in(DEVICE(&s->cpu), RX_CPU_FIR));
158     sysbus_connect_irq(icu, 2, s->irq[SWI]);
159     sysbus_mmio_map(SYS_BUS_DEVICE(icu), 0, RX62N_ICU_BASE);
160 }
161 
162 static void register_tmr(RX62NState *s, int unit)
163 {
164     SysBusDevice *tmr;
165     int i, irqbase;
166 
167     object_initialize_child(OBJECT(s), "tmr[*]",
168                             &s->tmr[unit], TYPE_RENESAS_TMR);
169     tmr = SYS_BUS_DEVICE(&s->tmr[unit]);
170     qdev_prop_set_uint64(DEVICE(tmr), "input-freq", s->pclk_freq_hz);
171     sysbus_realize(tmr, &error_abort);
172 
173     irqbase = RX62N_TMR_IRQ + TMR_NR_IRQ * unit;
174     for (i = 0; i < TMR_NR_IRQ; i++) {
175         sysbus_connect_irq(tmr, i, s->irq[irqbase + i]);
176     }
177     sysbus_mmio_map(tmr, 0, RX62N_TMR_BASE + unit * 0x10);
178 }
179 
180 static void register_cmt(RX62NState *s, int unit)
181 {
182     SysBusDevice *cmt;
183     int i, irqbase;
184 
185     object_initialize_child(OBJECT(s), "cmt[*]",
186                             &s->cmt[unit], TYPE_RENESAS_CMT);
187     cmt = SYS_BUS_DEVICE(&s->cmt[unit]);
188     qdev_prop_set_uint64(DEVICE(cmt), "input-freq", s->pclk_freq_hz);
189     sysbus_realize(cmt, &error_abort);
190 
191     irqbase = RX62N_CMT_IRQ + CMT_NR_IRQ * unit;
192     for (i = 0; i < CMT_NR_IRQ; i++) {
193         sysbus_connect_irq(cmt, i, s->irq[irqbase + i]);
194     }
195     sysbus_mmio_map(cmt, 0, RX62N_CMT_BASE + unit * 0x10);
196 }
197 
198 static void register_sci(RX62NState *s, int unit)
199 {
200     SysBusDevice *sci;
201     int i, irqbase;
202 
203     object_initialize_child(OBJECT(s), "sci[*]",
204                             &s->sci[unit], TYPE_RENESAS_SCI);
205     sci = SYS_BUS_DEVICE(&s->sci[unit]);
206     qdev_prop_set_chr(DEVICE(sci), "chardev", serial_hd(unit));
207     qdev_prop_set_uint64(DEVICE(sci), "input-freq", s->pclk_freq_hz);
208     sysbus_realize(sci, &error_abort);
209 
210     irqbase = RX62N_SCI_IRQ + SCI_NR_IRQ * unit;
211     for (i = 0; i < SCI_NR_IRQ; i++) {
212         sysbus_connect_irq(sci, i, s->irq[irqbase + i]);
213     }
214     sysbus_mmio_map(sci, 0, RX62N_SCI_BASE + unit * 0x08);
215 }
216 
217 static void rx62n_realize(DeviceState *dev, Error **errp)
218 {
219     RX62NState *s = RX62N_MCU(dev);
220     RX62NClass *rxc = RX62N_MCU_GET_CLASS(dev);
221 
222     if (s->xtal_freq_hz == 0) {
223         error_setg(errp, "\"xtal-frequency-hz\" property must be provided.");
224         return;
225     }
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.");
230         return;
231     }
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);
236 
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);
246 
247     /* Initialize CPU */
248     object_initialize_child(OBJECT(s), "cpu", &s->cpu, TYPE_RX62N_CPU);
249     qdev_realize(DEVICE(&s->cpu), NULL, &error_abort);
250 
251     register_icu(s);
252     s->cpu.env.ack = qdev_get_gpio_in_named(DEVICE(&s->icu), "ack", 0);
253     register_tmr(s, 0);
254     register_tmr(s, 1);
255     register_cmt(s, 0);
256     register_cmt(s, 1);
257     register_sci(s, 0);
258 }
259 
260 static Property rx62n_properties[] = {
261     DEFINE_PROP_LINK("main-bus", RX62NState, sysmem, TYPE_MEMORY_REGION,
262                      MemoryRegion *),
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(),
266 };
267 
268 static void rx62n_class_init(ObjectClass *klass, void *data)
269 {
270     DeviceClass *dc = DEVICE_CLASS(klass);
271 
272     dc->realize = rx62n_realize;
273     device_class_set_props(dc, rx62n_properties);
274 }
275 
276 static void r5f562n7_class_init(ObjectClass *oc, void *data)
277 {
278     RX62NClass *rxc = RX62N_MCU_CLASS(oc);
279 
280     rxc->ram_size = 64 * KiB;
281     rxc->rom_flash_size = 384 * KiB;
282     rxc->data_flash_size = 32 * KiB;
283 };
284 
285 static void r5f562n8_class_init(ObjectClass *oc, void *data)
286 {
287     RX62NClass *rxc = RX62N_MCU_CLASS(oc);
288 
289     rxc->ram_size = 96 * KiB;
290     rxc->rom_flash_size = 512 * KiB;
291     rxc->data_flash_size = 32 * KiB;
292 };
293 
294 static const TypeInfo rx62n_types[] = {
295     {
296         .name           = TYPE_R5F562N7_MCU,
297         .parent         = TYPE_RX62N_MCU,
298         .class_init     = r5f562n7_class_init,
299     }, {
300         .name           = TYPE_R5F562N8_MCU,
301         .parent         = TYPE_RX62N_MCU,
302         .class_init     = r5f562n8_class_init,
303     }, {
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,
309         .abstract       = true,
310      }
311 };
312 
313 DEFINE_TYPES(rx62n_types)
314