xref: /qemu/hw/rx/rx62n.c (revision 7d272cb43d64e44d476e83c89dc61f5b54a658e9)
10c80f50fSYoshinori Sato /*
20c80f50fSYoshinori Sato  * RX62N Microcontroller
30c80f50fSYoshinori Sato  *
40c80f50fSYoshinori Sato  * Datasheet: RX62N Group, RX621 Group User's Manual: Hardware
50c80f50fSYoshinori Sato  * (Rev.1.40 R01UH0033EJ0140)
60c80f50fSYoshinori Sato  *
70c80f50fSYoshinori Sato  * Copyright (c) 2019 Yoshinori Sato
80c80f50fSYoshinori Sato  *
90c80f50fSYoshinori Sato  * This program is free software; you can redistribute it and/or modify it
100c80f50fSYoshinori Sato  * under the terms and conditions of the GNU General Public License,
110c80f50fSYoshinori Sato  * version 2 or later, as published by the Free Software Foundation.
120c80f50fSYoshinori Sato  *
130c80f50fSYoshinori Sato  * This program is distributed in the hope it will be useful, but WITHOUT
140c80f50fSYoshinori Sato  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
150c80f50fSYoshinori Sato  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
160c80f50fSYoshinori Sato  * more details.
170c80f50fSYoshinori Sato  *
180c80f50fSYoshinori Sato  * You should have received a copy of the GNU General Public License along with
190c80f50fSYoshinori Sato  * this program.  If not, see <http://www.gnu.org/licenses/>.
200c80f50fSYoshinori Sato  */
210c80f50fSYoshinori Sato 
220c80f50fSYoshinori Sato #include "qemu/osdep.h"
230c80f50fSYoshinori Sato #include "qapi/error.h"
24*7d272cb4SRichard Henderson #include "qemu/error-report.h"
250c80f50fSYoshinori Sato #include "hw/hw.h"
260c80f50fSYoshinori Sato #include "hw/rx/rx62n.h"
270c80f50fSYoshinori Sato #include "hw/loader.h"
280c80f50fSYoshinori Sato #include "hw/sysbus.h"
290c80f50fSYoshinori Sato #include "hw/qdev-properties.h"
300c80f50fSYoshinori Sato #include "sysemu/sysemu.h"
31*7d272cb4SRichard Henderson #include "sysemu/qtest.h"
320c80f50fSYoshinori Sato #include "cpu.h"
330c80f50fSYoshinori Sato 
340c80f50fSYoshinori Sato /*
350c80f50fSYoshinori Sato  * RX62N Internal Memory
360c80f50fSYoshinori Sato  */
370c80f50fSYoshinori Sato #define RX62N_IRAM_BASE     0x00000000
380c80f50fSYoshinori Sato #define RX62N_DFLASH_BASE   0x00100000
390c80f50fSYoshinori Sato #define RX62N_CFLASH_BASE   0xfff80000
400c80f50fSYoshinori Sato 
410c80f50fSYoshinori Sato /*
420c80f50fSYoshinori Sato  * RX62N Peripheral Address
430c80f50fSYoshinori Sato  * See users manual section 5
440c80f50fSYoshinori Sato  */
450c80f50fSYoshinori Sato #define RX62N_ICU_BASE  0x00087000
460c80f50fSYoshinori Sato #define RX62N_TMR_BASE  0x00088200
470c80f50fSYoshinori Sato #define RX62N_CMT_BASE  0x00088000
480c80f50fSYoshinori Sato #define RX62N_SCI_BASE  0x00088240
490c80f50fSYoshinori Sato 
500c80f50fSYoshinori Sato /*
510c80f50fSYoshinori Sato  * RX62N Peripheral IRQ
520c80f50fSYoshinori Sato  * See users manual section 11
530c80f50fSYoshinori Sato  */
540c80f50fSYoshinori Sato #define RX62N_TMR_IRQ   174
550c80f50fSYoshinori Sato #define RX62N_CMT_IRQ   28
560c80f50fSYoshinori Sato #define RX62N_SCI_IRQ   214
570c80f50fSYoshinori Sato 
580c80f50fSYoshinori Sato /*
590c80f50fSYoshinori Sato  * IRQ -> IPR mapping table
600c80f50fSYoshinori Sato  * 0x00 - 0x91: IPR no (IPR00 to IPR91)
610c80f50fSYoshinori Sato  * 0xff: IPR not assigned
620c80f50fSYoshinori Sato  * See "11.3.1 Interrupt Vector Table" in hardware manual.
630c80f50fSYoshinori Sato  */
640c80f50fSYoshinori Sato static const uint8_t ipr_table[NR_IRQS] = {
650c80f50fSYoshinori Sato     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
660c80f50fSYoshinori Sato     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 15 */
670c80f50fSYoshinori Sato     0x00, 0xff, 0xff, 0xff, 0xff, 0x01, 0xff, 0x02,
680c80f50fSYoshinori Sato     0xff, 0xff, 0xff, 0x03, 0x04, 0x05, 0x06, 0x07, /* 31 */
690c80f50fSYoshinori Sato     0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
700c80f50fSYoshinori Sato     0x10, 0x11, 0x12, 0x13, 0x14, 0x14, 0x14, 0x14, /* 47 */
710c80f50fSYoshinori Sato     0x15, 0x15, 0x15, 0x15, 0xff, 0xff, 0xff, 0xff,
720c80f50fSYoshinori Sato     0x18, 0x18, 0x18, 0x18, 0x18, 0x1d, 0x1e, 0x1f, /* 63 */
730c80f50fSYoshinori Sato     0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
740c80f50fSYoshinori Sato     0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 79 */
750c80f50fSYoshinori Sato     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
760c80f50fSYoshinori Sato     0xff, 0xff, 0x3a, 0x3b, 0x3c, 0xff, 0xff, 0xff, /* 95 */
770c80f50fSYoshinori Sato     0x40, 0xff, 0x44, 0x45, 0xff, 0xff, 0x48, 0xff,
780c80f50fSYoshinori Sato     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 111 */
790c80f50fSYoshinori Sato     0xff, 0xff, 0x51, 0x51, 0x51, 0x51, 0x52, 0x52,
800c80f50fSYoshinori Sato     0x52, 0x53, 0x53, 0x54, 0x54, 0x55, 0x55, 0x56, /* 127 */
810c80f50fSYoshinori Sato     0x56, 0x57, 0x57, 0x57, 0x57, 0x58, 0x59, 0x59,
820c80f50fSYoshinori Sato     0x59, 0x59, 0x5a, 0x5b, 0x5b, 0x5b, 0x5c, 0x5c, /* 143 */
830c80f50fSYoshinori Sato     0x5c, 0x5c, 0x5d, 0x5d, 0x5d, 0x5e, 0x5e, 0x5f,
840c80f50fSYoshinori Sato     0x5f, 0x60, 0x60, 0x61, 0x61, 0x62, 0x62, 0x62, /* 159 */
850c80f50fSYoshinori Sato     0x62, 0x63, 0x64, 0x64, 0x64, 0x64, 0x65, 0x66,
860c80f50fSYoshinori Sato     0x66, 0x66, 0x67, 0x67, 0x67, 0x67, 0x68, 0x68, /* 175 */
870c80f50fSYoshinori Sato     0x68, 0x69, 0x69, 0x69, 0x6a, 0x6a, 0x6a, 0x6b,
880c80f50fSYoshinori Sato     0x6b, 0x6b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 191 */
890c80f50fSYoshinori Sato     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x70, 0x71,
900c80f50fSYoshinori Sato     0x72, 0x73, 0x74, 0x75, 0xff, 0xff, 0xff, 0xff, /* 207 */
910c80f50fSYoshinori Sato     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x80,
920c80f50fSYoshinori Sato     0x80, 0x80, 0x81, 0x81, 0x81, 0x81, 0x82, 0x82, /* 223 */
930c80f50fSYoshinori Sato     0x82, 0x82, 0x83, 0x83, 0x83, 0x83, 0xff, 0xff,
940c80f50fSYoshinori Sato     0xff, 0xff, 0x85, 0x85, 0x85, 0x85, 0x86, 0x86, /* 239 */
950c80f50fSYoshinori Sato     0x86, 0x86, 0xff, 0xff, 0xff, 0xff, 0x88, 0x89,
960c80f50fSYoshinori Sato     0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, /* 255 */
970c80f50fSYoshinori Sato };
980c80f50fSYoshinori Sato 
990c80f50fSYoshinori Sato /*
1000c80f50fSYoshinori Sato  * Level triggerd IRQ list
1010c80f50fSYoshinori Sato  * Not listed IRQ is Edge trigger.
1020c80f50fSYoshinori Sato  * See "11.3.1 Interrupt Vector Table" in hardware manual.
1030c80f50fSYoshinori Sato  */
1040c80f50fSYoshinori Sato static const uint8_t levelirq[] = {
1050c80f50fSYoshinori Sato      16,  21,  32,  44,  47,  48,  51,  64,  65,  66,
1060c80f50fSYoshinori Sato      67,  68,  69,  70,  71,  72,  73,  74,  75,  76,
1070c80f50fSYoshinori Sato      77,  78,  79,  90,  91, 170, 171, 172, 173, 214,
1080c80f50fSYoshinori Sato     217, 218, 221, 222, 225, 226, 229, 234, 237, 238,
1090c80f50fSYoshinori Sato     241, 246, 249, 250, 253,
1100c80f50fSYoshinori Sato };
1110c80f50fSYoshinori Sato 
1120c80f50fSYoshinori Sato static void register_icu(RX62NState *s)
1130c80f50fSYoshinori Sato {
1140c80f50fSYoshinori Sato     int i;
1150c80f50fSYoshinori Sato     SysBusDevice *icu;
1160c80f50fSYoshinori Sato 
1170c80f50fSYoshinori Sato     object_initialize_child(OBJECT(s), "icu", &s->icu, TYPE_RX_ICU);
1180c80f50fSYoshinori Sato     icu = SYS_BUS_DEVICE(&s->icu);
1190c80f50fSYoshinori Sato     qdev_prop_set_uint32(DEVICE(icu), "len-ipr-map", NR_IRQS);
1200c80f50fSYoshinori Sato     for (i = 0; i < NR_IRQS; i++) {
1210c80f50fSYoshinori Sato         char propname[32];
1220c80f50fSYoshinori Sato         snprintf(propname, sizeof(propname), "ipr-map[%d]", i);
1230c80f50fSYoshinori Sato         qdev_prop_set_uint32(DEVICE(icu), propname, ipr_table[i]);
1240c80f50fSYoshinori Sato     }
1250c80f50fSYoshinori Sato     qdev_prop_set_uint32(DEVICE(icu), "len-trigger-level",
1260c80f50fSYoshinori Sato                          ARRAY_SIZE(levelirq));
1270c80f50fSYoshinori Sato     for (i = 0; i < ARRAY_SIZE(levelirq); i++) {
1280c80f50fSYoshinori Sato         char propname[32];
1290c80f50fSYoshinori Sato         snprintf(propname, sizeof(propname), "trigger-level[%d]", i);
1300c80f50fSYoshinori Sato         qdev_prop_set_uint32(DEVICE(icu), propname, levelirq[i]);
1310c80f50fSYoshinori Sato     }
1320c80f50fSYoshinori Sato 
1330c80f50fSYoshinori Sato     for (i = 0; i < NR_IRQS; i++) {
1340c80f50fSYoshinori Sato         s->irq[i] = qdev_get_gpio_in(DEVICE(icu), i);
1350c80f50fSYoshinori Sato     }
1360c80f50fSYoshinori Sato     sysbus_realize(icu, &error_abort);
1370c80f50fSYoshinori Sato     sysbus_connect_irq(icu, 0, qdev_get_gpio_in(DEVICE(&s->cpu), RX_CPU_IRQ));
1380c80f50fSYoshinori Sato     sysbus_connect_irq(icu, 1, qdev_get_gpio_in(DEVICE(&s->cpu), RX_CPU_FIR));
1390c80f50fSYoshinori Sato     sysbus_connect_irq(icu, 2, s->irq[SWI]);
1400c80f50fSYoshinori Sato     sysbus_mmio_map(SYS_BUS_DEVICE(icu), 0, RX62N_ICU_BASE);
1410c80f50fSYoshinori Sato }
1420c80f50fSYoshinori Sato 
1430c80f50fSYoshinori Sato static void register_tmr(RX62NState *s, int unit)
1440c80f50fSYoshinori Sato {
1450c80f50fSYoshinori Sato     SysBusDevice *tmr;
1460c80f50fSYoshinori Sato     int i, irqbase;
1470c80f50fSYoshinori Sato 
1480c80f50fSYoshinori Sato     object_initialize_child(OBJECT(s), "tmr[*]",
1490c80f50fSYoshinori Sato                             &s->tmr[unit], TYPE_RENESAS_TMR);
1500c80f50fSYoshinori Sato     tmr = SYS_BUS_DEVICE(&s->tmr[unit]);
1510c80f50fSYoshinori Sato     qdev_prop_set_uint64(DEVICE(tmr), "input-freq", RX62N_PCLK);
1520c80f50fSYoshinori Sato     sysbus_realize(tmr, &error_abort);
1530c80f50fSYoshinori Sato 
1540c80f50fSYoshinori Sato     irqbase = RX62N_TMR_IRQ + TMR_NR_IRQ * unit;
1550c80f50fSYoshinori Sato     for (i = 0; i < TMR_NR_IRQ; i++) {
1560c80f50fSYoshinori Sato         sysbus_connect_irq(tmr, i, s->irq[irqbase + i]);
1570c80f50fSYoshinori Sato     }
1580c80f50fSYoshinori Sato     sysbus_mmio_map(tmr, 0, RX62N_TMR_BASE + unit * 0x10);
1590c80f50fSYoshinori Sato }
1600c80f50fSYoshinori Sato 
1610c80f50fSYoshinori Sato static void register_cmt(RX62NState *s, int unit)
1620c80f50fSYoshinori Sato {
1630c80f50fSYoshinori Sato     SysBusDevice *cmt;
1640c80f50fSYoshinori Sato     int i, irqbase;
1650c80f50fSYoshinori Sato 
1660c80f50fSYoshinori Sato     object_initialize_child(OBJECT(s), "cmt[*]",
1670c80f50fSYoshinori Sato                             &s->cmt[unit], TYPE_RENESAS_CMT);
1680c80f50fSYoshinori Sato     cmt = SYS_BUS_DEVICE(&s->cmt[unit]);
1690c80f50fSYoshinori Sato     qdev_prop_set_uint64(DEVICE(cmt), "input-freq", RX62N_PCLK);
1700c80f50fSYoshinori Sato     sysbus_realize(cmt, &error_abort);
1710c80f50fSYoshinori Sato 
1720c80f50fSYoshinori Sato     irqbase = RX62N_CMT_IRQ + CMT_NR_IRQ * unit;
1730c80f50fSYoshinori Sato     for (i = 0; i < CMT_NR_IRQ; i++) {
1740c80f50fSYoshinori Sato         sysbus_connect_irq(cmt, i, s->irq[irqbase + i]);
1750c80f50fSYoshinori Sato     }
1760c80f50fSYoshinori Sato     sysbus_mmio_map(cmt, 0, RX62N_CMT_BASE + unit * 0x10);
1770c80f50fSYoshinori Sato }
1780c80f50fSYoshinori Sato 
1790c80f50fSYoshinori Sato static void register_sci(RX62NState *s, int unit)
1800c80f50fSYoshinori Sato {
1810c80f50fSYoshinori Sato     SysBusDevice *sci;
1820c80f50fSYoshinori Sato     int i, irqbase;
1830c80f50fSYoshinori Sato 
1840c80f50fSYoshinori Sato     object_initialize_child(OBJECT(s), "sci[*]",
1850c80f50fSYoshinori Sato                             &s->sci[unit], TYPE_RENESAS_SCI);
1860c80f50fSYoshinori Sato     sci = SYS_BUS_DEVICE(&s->sci[unit]);
1870c80f50fSYoshinori Sato     qdev_prop_set_chr(DEVICE(sci), "chardev", serial_hd(unit));
1880c80f50fSYoshinori Sato     qdev_prop_set_uint64(DEVICE(sci), "input-freq", RX62N_PCLK);
1890c80f50fSYoshinori Sato     sysbus_realize(sci, &error_abort);
1900c80f50fSYoshinori Sato 
1910c80f50fSYoshinori Sato     irqbase = RX62N_SCI_IRQ + SCI_NR_IRQ * unit;
1920c80f50fSYoshinori Sato     for (i = 0; i < SCI_NR_IRQ; i++) {
1930c80f50fSYoshinori Sato         sysbus_connect_irq(sci, i, s->irq[irqbase + i]);
1940c80f50fSYoshinori Sato     }
1950c80f50fSYoshinori Sato     sysbus_mmio_map(sci, 0, RX62N_SCI_BASE + unit * 0x08);
1960c80f50fSYoshinori Sato }
1970c80f50fSYoshinori Sato 
1980c80f50fSYoshinori Sato static void rx62n_realize(DeviceState *dev, Error **errp)
1990c80f50fSYoshinori Sato {
2000c80f50fSYoshinori Sato     RX62NState *s = RX62N_MCU(dev);
2010c80f50fSYoshinori Sato 
2020c80f50fSYoshinori Sato     memory_region_init_ram(&s->iram, OBJECT(dev), "iram",
2030c80f50fSYoshinori Sato                            RX62N_IRAM_SIZE, &error_abort);
2040c80f50fSYoshinori Sato     memory_region_add_subregion(s->sysmem, RX62N_IRAM_BASE, &s->iram);
2050c80f50fSYoshinori Sato     memory_region_init_rom(&s->d_flash, OBJECT(dev), "flash-data",
2060c80f50fSYoshinori Sato                            RX62N_DFLASH_SIZE, &error_abort);
2070c80f50fSYoshinori Sato     memory_region_add_subregion(s->sysmem, RX62N_DFLASH_BASE, &s->d_flash);
2080c80f50fSYoshinori Sato     memory_region_init_rom(&s->c_flash, OBJECT(dev), "flash-code",
2090c80f50fSYoshinori Sato                            RX62N_CFLASH_SIZE, &error_abort);
2100c80f50fSYoshinori Sato     memory_region_add_subregion(s->sysmem, RX62N_CFLASH_BASE, &s->c_flash);
2110c80f50fSYoshinori Sato 
2120c80f50fSYoshinori Sato     if (!s->kernel) {
213*7d272cb4SRichard Henderson         if (bios_name) {
2140c80f50fSYoshinori Sato             rom_add_file_fixed(bios_name, RX62N_CFLASH_BASE, 0);
215*7d272cb4SRichard Henderson         }  else if (!qtest_enabled()) {
216*7d272cb4SRichard Henderson             error_report("No bios or kernel specified");
217*7d272cb4SRichard Henderson             exit(1);
218*7d272cb4SRichard Henderson         }
2190c80f50fSYoshinori Sato     }
2200c80f50fSYoshinori Sato 
2210c80f50fSYoshinori Sato     /* Initialize CPU */
2220c80f50fSYoshinori Sato     object_initialize_child(OBJECT(s), "cpu", &s->cpu, TYPE_RX62N_CPU);
2230c80f50fSYoshinori Sato     qdev_realize(DEVICE(&s->cpu), NULL, &error_abort);
2240c80f50fSYoshinori Sato 
2250c80f50fSYoshinori Sato     register_icu(s);
2260c80f50fSYoshinori Sato     s->cpu.env.ack = qdev_get_gpio_in_named(DEVICE(&s->icu), "ack", 0);
2270c80f50fSYoshinori Sato     register_tmr(s, 0);
2280c80f50fSYoshinori Sato     register_tmr(s, 1);
2290c80f50fSYoshinori Sato     register_cmt(s, 0);
2300c80f50fSYoshinori Sato     register_cmt(s, 1);
2310c80f50fSYoshinori Sato     register_sci(s, 0);
2320c80f50fSYoshinori Sato }
2330c80f50fSYoshinori Sato 
2340c80f50fSYoshinori Sato static Property rx62n_properties[] = {
2350c80f50fSYoshinori Sato     DEFINE_PROP_LINK("main-bus", RX62NState, sysmem, TYPE_MEMORY_REGION,
2360c80f50fSYoshinori Sato                      MemoryRegion *),
2370c80f50fSYoshinori Sato     DEFINE_PROP_BOOL("load-kernel", RX62NState, kernel, false),
2380c80f50fSYoshinori Sato     DEFINE_PROP_END_OF_LIST(),
2390c80f50fSYoshinori Sato };
2400c80f50fSYoshinori Sato 
2410c80f50fSYoshinori Sato static void rx62n_class_init(ObjectClass *klass, void *data)
2420c80f50fSYoshinori Sato {
2430c80f50fSYoshinori Sato     DeviceClass *dc = DEVICE_CLASS(klass);
2440c80f50fSYoshinori Sato 
2450c80f50fSYoshinori Sato     dc->realize = rx62n_realize;
2460c80f50fSYoshinori Sato     device_class_set_props(dc, rx62n_properties);
2470c80f50fSYoshinori Sato }
2480c80f50fSYoshinori Sato 
2490c80f50fSYoshinori Sato static const TypeInfo rx62n_info = {
2500c80f50fSYoshinori Sato     .name = TYPE_RX62N_MCU,
2510c80f50fSYoshinori Sato     .parent = TYPE_DEVICE,
2520c80f50fSYoshinori Sato     .instance_size = sizeof(RX62NState),
2530c80f50fSYoshinori Sato     .class_init = rx62n_class_init,
2540c80f50fSYoshinori Sato };
2550c80f50fSYoshinori Sato 
2560c80f50fSYoshinori Sato static void rx62n_register_types(void)
2570c80f50fSYoshinori Sato {
2580c80f50fSYoshinori Sato     type_register_static(&rx62n_info);
2590c80f50fSYoshinori Sato }
2600c80f50fSYoshinori Sato 
2610c80f50fSYoshinori Sato type_init(rx62n_register_types)
262