qemu

Форк
0
/
rx62n.c 
313 строк · 10.3 Кб
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 "qemu/units.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 "qapi/qmp/qlist.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 triggered 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
    QList *ipr_map, *trigger_level;
136

137
    object_initialize_child(OBJECT(s), "icu", &s->icu, TYPE_RX_ICU);
138
    icu = SYS_BUS_DEVICE(&s->icu);
139

140
    ipr_map = qlist_new();
141
    for (i = 0; i < NR_IRQS; i++) {
142
        qlist_append_int(ipr_map, ipr_table[i]);
143
    }
144
    qdev_prop_set_array(DEVICE(icu), "ipr-map", ipr_map);
145

146
    trigger_level = qlist_new();
147
    for (i = 0; i < ARRAY_SIZE(levelirq); i++) {
148
        qlist_append_int(trigger_level, levelirq[i]);
149
    }
150
    qdev_prop_set_array(DEVICE(icu), "trigger-level", trigger_level);
151
    sysbus_realize(icu, &error_abort);
152

153
    sysbus_connect_irq(icu, 0, qdev_get_gpio_in(DEVICE(&s->cpu), RX_CPU_IRQ));
154
    sysbus_connect_irq(icu, 1, qdev_get_gpio_in(DEVICE(&s->cpu), RX_CPU_FIR));
155
    sysbus_connect_irq(icu, 2, qdev_get_gpio_in(DEVICE(&s->icu), SWI));
156
    sysbus_mmio_map(icu, 0, RX62N_ICU_BASE);
157
}
158

159
static void register_tmr(RX62NState *s, int unit)
160
{
161
    SysBusDevice *tmr;
162
    int i, irqbase;
163

164
    object_initialize_child(OBJECT(s), "tmr[*]",
165
                            &s->tmr[unit], TYPE_RENESAS_TMR);
166
    tmr = SYS_BUS_DEVICE(&s->tmr[unit]);
167
    qdev_prop_set_uint64(DEVICE(tmr), "input-freq", s->pclk_freq_hz);
168
    sysbus_realize(tmr, &error_abort);
169

170
    irqbase = RX62N_TMR_IRQ + TMR_NR_IRQ * unit;
171
    for (i = 0; i < TMR_NR_IRQ; i++) {
172
        sysbus_connect_irq(tmr, i,
173
                           qdev_get_gpio_in(DEVICE(&s->icu), irqbase + i));
174
    }
175
    sysbus_mmio_map(tmr, 0, RX62N_TMR_BASE + unit * 0x10);
176
}
177

178
static void register_cmt(RX62NState *s, int unit)
179
{
180
    SysBusDevice *cmt;
181
    int i, irqbase;
182

183
    object_initialize_child(OBJECT(s), "cmt[*]",
184
                            &s->cmt[unit], TYPE_RENESAS_CMT);
185
    cmt = SYS_BUS_DEVICE(&s->cmt[unit]);
186
    qdev_prop_set_uint64(DEVICE(cmt), "input-freq", s->pclk_freq_hz);
187
    sysbus_realize(cmt, &error_abort);
188

189
    irqbase = RX62N_CMT_IRQ + CMT_NR_IRQ * unit;
190
    for (i = 0; i < CMT_NR_IRQ; i++) {
191
        sysbus_connect_irq(cmt, i,
192
                           qdev_get_gpio_in(DEVICE(&s->icu), irqbase + i));
193
    }
194
    sysbus_mmio_map(cmt, 0, RX62N_CMT_BASE + unit * 0x10);
195
}
196

197
static void register_sci(RX62NState *s, int unit)
198
{
199
    SysBusDevice *sci;
200
    int i, irqbase;
201

202
    object_initialize_child(OBJECT(s), "sci[*]",
203
                            &s->sci[unit], TYPE_RENESAS_SCI);
204
    sci = SYS_BUS_DEVICE(&s->sci[unit]);
205
    qdev_prop_set_chr(DEVICE(sci), "chardev", serial_hd(unit));
206
    qdev_prop_set_uint64(DEVICE(sci), "input-freq", s->pclk_freq_hz);
207
    sysbus_realize(sci, &error_abort);
208

209
    irqbase = RX62N_SCI_IRQ + SCI_NR_IRQ * unit;
210
    for (i = 0; i < SCI_NR_IRQ; i++) {
211
        sysbus_connect_irq(sci, i,
212
                           qdev_get_gpio_in(DEVICE(&s->icu), 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

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.