xref: /openbmc/qemu/hw/rx/rx62n.c (revision 0c80f50f1e047535f76cffcf9629ebf6d4542c4d)
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  *
9  * This program is free software; you can redistribute it and/or modify it
10  * under the terms and conditions of the GNU General Public License,
11  * version 2 or later, as published by the Free Software Foundation.
12  *
13  * This program is distributed in the hope it will be useful, but WITHOUT
14  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
16  * more details.
17  *
18  * You should have received a copy of the GNU General Public License along with
19  * this program.  If not, see <http://www.gnu.org/licenses/>.
20  */
21 
22 #include "qemu/osdep.h"
23 #include "qapi/error.h"
24 #include "hw/hw.h"
25 #include "hw/rx/rx62n.h"
26 #include "hw/loader.h"
27 #include "hw/sysbus.h"
28 #include "hw/qdev-properties.h"
29 #include "sysemu/sysemu.h"
30 #include "cpu.h"
31 
32 /*
33  * RX62N Internal Memory
34  */
35 #define RX62N_IRAM_BASE     0x00000000
36 #define RX62N_DFLASH_BASE   0x00100000
37 #define RX62N_CFLASH_BASE   0xfff80000
38 
39 /*
40  * RX62N Peripheral Address
41  * See users manual section 5
42  */
43 #define RX62N_ICU_BASE  0x00087000
44 #define RX62N_TMR_BASE  0x00088200
45 #define RX62N_CMT_BASE  0x00088000
46 #define RX62N_SCI_BASE  0x00088240
47 
48 /*
49  * RX62N Peripheral IRQ
50  * See users manual section 11
51  */
52 #define RX62N_TMR_IRQ   174
53 #define RX62N_CMT_IRQ   28
54 #define RX62N_SCI_IRQ   214
55 
56 /*
57  * IRQ -> IPR mapping table
58  * 0x00 - 0x91: IPR no (IPR00 to IPR91)
59  * 0xff: IPR not assigned
60  * See "11.3.1 Interrupt Vector Table" in hardware manual.
61  */
62 static const uint8_t ipr_table[NR_IRQS] = {
63     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
64     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 15 */
65     0x00, 0xff, 0xff, 0xff, 0xff, 0x01, 0xff, 0x02,
66     0xff, 0xff, 0xff, 0x03, 0x04, 0x05, 0x06, 0x07, /* 31 */
67     0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
68     0x10, 0x11, 0x12, 0x13, 0x14, 0x14, 0x14, 0x14, /* 47 */
69     0x15, 0x15, 0x15, 0x15, 0xff, 0xff, 0xff, 0xff,
70     0x18, 0x18, 0x18, 0x18, 0x18, 0x1d, 0x1e, 0x1f, /* 63 */
71     0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
72     0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 79 */
73     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
74     0xff, 0xff, 0x3a, 0x3b, 0x3c, 0xff, 0xff, 0xff, /* 95 */
75     0x40, 0xff, 0x44, 0x45, 0xff, 0xff, 0x48, 0xff,
76     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 111 */
77     0xff, 0xff, 0x51, 0x51, 0x51, 0x51, 0x52, 0x52,
78     0x52, 0x53, 0x53, 0x54, 0x54, 0x55, 0x55, 0x56, /* 127 */
79     0x56, 0x57, 0x57, 0x57, 0x57, 0x58, 0x59, 0x59,
80     0x59, 0x59, 0x5a, 0x5b, 0x5b, 0x5b, 0x5c, 0x5c, /* 143 */
81     0x5c, 0x5c, 0x5d, 0x5d, 0x5d, 0x5e, 0x5e, 0x5f,
82     0x5f, 0x60, 0x60, 0x61, 0x61, 0x62, 0x62, 0x62, /* 159 */
83     0x62, 0x63, 0x64, 0x64, 0x64, 0x64, 0x65, 0x66,
84     0x66, 0x66, 0x67, 0x67, 0x67, 0x67, 0x68, 0x68, /* 175 */
85     0x68, 0x69, 0x69, 0x69, 0x6a, 0x6a, 0x6a, 0x6b,
86     0x6b, 0x6b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 191 */
87     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x70, 0x71,
88     0x72, 0x73, 0x74, 0x75, 0xff, 0xff, 0xff, 0xff, /* 207 */
89     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x80,
90     0x80, 0x80, 0x81, 0x81, 0x81, 0x81, 0x82, 0x82, /* 223 */
91     0x82, 0x82, 0x83, 0x83, 0x83, 0x83, 0xff, 0xff,
92     0xff, 0xff, 0x85, 0x85, 0x85, 0x85, 0x86, 0x86, /* 239 */
93     0x86, 0x86, 0xff, 0xff, 0xff, 0xff, 0x88, 0x89,
94     0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, /* 255 */
95 };
96 
97 /*
98  * Level triggerd IRQ list
99  * Not listed IRQ is Edge trigger.
100  * See "11.3.1 Interrupt Vector Table" in hardware manual.
101  */
102 static const uint8_t levelirq[] = {
103      16,  21,  32,  44,  47,  48,  51,  64,  65,  66,
104      67,  68,  69,  70,  71,  72,  73,  74,  75,  76,
105      77,  78,  79,  90,  91, 170, 171, 172, 173, 214,
106     217, 218, 221, 222, 225, 226, 229, 234, 237, 238,
107     241, 246, 249, 250, 253,
108 };
109 
110 static void register_icu(RX62NState *s)
111 {
112     int i;
113     SysBusDevice *icu;
114 
115     object_initialize_child(OBJECT(s), "icu", &s->icu, TYPE_RX_ICU);
116     icu = SYS_BUS_DEVICE(&s->icu);
117     qdev_prop_set_uint32(DEVICE(icu), "len-ipr-map", NR_IRQS);
118     for (i = 0; i < NR_IRQS; i++) {
119         char propname[32];
120         snprintf(propname, sizeof(propname), "ipr-map[%d]", i);
121         qdev_prop_set_uint32(DEVICE(icu), propname, ipr_table[i]);
122     }
123     qdev_prop_set_uint32(DEVICE(icu), "len-trigger-level",
124                          ARRAY_SIZE(levelirq));
125     for (i = 0; i < ARRAY_SIZE(levelirq); i++) {
126         char propname[32];
127         snprintf(propname, sizeof(propname), "trigger-level[%d]", i);
128         qdev_prop_set_uint32(DEVICE(icu), propname, levelirq[i]);
129     }
130 
131     for (i = 0; i < NR_IRQS; i++) {
132         s->irq[i] = qdev_get_gpio_in(DEVICE(icu), i);
133     }
134     sysbus_realize(icu, &error_abort);
135     sysbus_connect_irq(icu, 0, qdev_get_gpio_in(DEVICE(&s->cpu), RX_CPU_IRQ));
136     sysbus_connect_irq(icu, 1, qdev_get_gpio_in(DEVICE(&s->cpu), RX_CPU_FIR));
137     sysbus_connect_irq(icu, 2, s->irq[SWI]);
138     sysbus_mmio_map(SYS_BUS_DEVICE(icu), 0, RX62N_ICU_BASE);
139 }
140 
141 static void register_tmr(RX62NState *s, int unit)
142 {
143     SysBusDevice *tmr;
144     int i, irqbase;
145 
146     object_initialize_child(OBJECT(s), "tmr[*]",
147                             &s->tmr[unit], TYPE_RENESAS_TMR);
148     tmr = SYS_BUS_DEVICE(&s->tmr[unit]);
149     qdev_prop_set_uint64(DEVICE(tmr), "input-freq", RX62N_PCLK);
150     sysbus_realize(tmr, &error_abort);
151 
152     irqbase = RX62N_TMR_IRQ + TMR_NR_IRQ * unit;
153     for (i = 0; i < TMR_NR_IRQ; i++) {
154         sysbus_connect_irq(tmr, i, s->irq[irqbase + i]);
155     }
156     sysbus_mmio_map(tmr, 0, RX62N_TMR_BASE + unit * 0x10);
157 }
158 
159 static void register_cmt(RX62NState *s, int unit)
160 {
161     SysBusDevice *cmt;
162     int i, irqbase;
163 
164     object_initialize_child(OBJECT(s), "cmt[*]",
165                             &s->cmt[unit], TYPE_RENESAS_CMT);
166     cmt = SYS_BUS_DEVICE(&s->cmt[unit]);
167     qdev_prop_set_uint64(DEVICE(cmt), "input-freq", RX62N_PCLK);
168     sysbus_realize(cmt, &error_abort);
169 
170     irqbase = RX62N_CMT_IRQ + CMT_NR_IRQ * unit;
171     for (i = 0; i < CMT_NR_IRQ; i++) {
172         sysbus_connect_irq(cmt, i, s->irq[irqbase + i]);
173     }
174     sysbus_mmio_map(cmt, 0, RX62N_CMT_BASE + unit * 0x10);
175 }
176 
177 static void register_sci(RX62NState *s, int unit)
178 {
179     SysBusDevice *sci;
180     int i, irqbase;
181 
182     object_initialize_child(OBJECT(s), "sci[*]",
183                             &s->sci[unit], TYPE_RENESAS_SCI);
184     sci = SYS_BUS_DEVICE(&s->sci[unit]);
185     qdev_prop_set_chr(DEVICE(sci), "chardev", serial_hd(unit));
186     qdev_prop_set_uint64(DEVICE(sci), "input-freq", RX62N_PCLK);
187     sysbus_realize(sci, &error_abort);
188 
189     irqbase = RX62N_SCI_IRQ + SCI_NR_IRQ * unit;
190     for (i = 0; i < SCI_NR_IRQ; i++) {
191         sysbus_connect_irq(sci, i, s->irq[irqbase + i]);
192     }
193     sysbus_mmio_map(sci, 0, RX62N_SCI_BASE + unit * 0x08);
194 }
195 
196 static void rx62n_realize(DeviceState *dev, Error **errp)
197 {
198     RX62NState *s = RX62N_MCU(dev);
199 
200     memory_region_init_ram(&s->iram, OBJECT(dev), "iram",
201                            RX62N_IRAM_SIZE, &error_abort);
202     memory_region_add_subregion(s->sysmem, RX62N_IRAM_BASE, &s->iram);
203     memory_region_init_rom(&s->d_flash, OBJECT(dev), "flash-data",
204                            RX62N_DFLASH_SIZE, &error_abort);
205     memory_region_add_subregion(s->sysmem, RX62N_DFLASH_BASE, &s->d_flash);
206     memory_region_init_rom(&s->c_flash, OBJECT(dev), "flash-code",
207                            RX62N_CFLASH_SIZE, &error_abort);
208     memory_region_add_subregion(s->sysmem, RX62N_CFLASH_BASE, &s->c_flash);
209 
210     if (!s->kernel) {
211         rom_add_file_fixed(bios_name, RX62N_CFLASH_BASE, 0);
212     }
213 
214     /* Initialize CPU */
215     object_initialize_child(OBJECT(s), "cpu", &s->cpu, TYPE_RX62N_CPU);
216     qdev_realize(DEVICE(&s->cpu), NULL, &error_abort);
217 
218     register_icu(s);
219     s->cpu.env.ack = qdev_get_gpio_in_named(DEVICE(&s->icu), "ack", 0);
220     register_tmr(s, 0);
221     register_tmr(s, 1);
222     register_cmt(s, 0);
223     register_cmt(s, 1);
224     register_sci(s, 0);
225 }
226 
227 static Property rx62n_properties[] = {
228     DEFINE_PROP_LINK("main-bus", RX62NState, sysmem, TYPE_MEMORY_REGION,
229                      MemoryRegion *),
230     DEFINE_PROP_BOOL("load-kernel", RX62NState, kernel, false),
231     DEFINE_PROP_END_OF_LIST(),
232 };
233 
234 static void rx62n_class_init(ObjectClass *klass, void *data)
235 {
236     DeviceClass *dc = DEVICE_CLASS(klass);
237 
238     dc->realize = rx62n_realize;
239     device_class_set_props(dc, rx62n_properties);
240 }
241 
242 static const TypeInfo rx62n_info = {
243     .name = TYPE_RX62N_MCU,
244     .parent = TYPE_DEVICE,
245     .instance_size = sizeof(RX62NState),
246     .class_init = rx62n_class_init,
247 };
248 
249 static void rx62n_register_types(void)
250 {
251     type_register_static(&rx62n_info);
252 }
253 
254 type_init(rx62n_register_types)
255