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