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