qemu

Форк
0
/
grlib_ahb_apb_pnp.c 
303 строки · 10.4 Кб
1
/*
2
 * GRLIB AHB APB PNP
3
 *
4
 *  Copyright (C) 2019 AdaCore
5
 *
6
 *  Developed by :
7
 *  Frederic Konrad   <frederic.konrad@adacore.com>
8
 *
9
 * This program is free software; you can redistribute it and/or modify
10
 * it under the terms of the GNU General Public License as published by
11
 * the Free Software Foundation, either version 2 of the License, or
12
 * (at your option) any later version.
13
 *
14
 * This program is distributed in the hope that it will be useful,
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 * GNU General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU General Public License along
20
 * with this program; if not, see <http://www.gnu.org/licenses/>.
21
 *
22
 */
23

24
#include "qemu/osdep.h"
25
#include "qemu/log.h"
26
#include "hw/sysbus.h"
27
#include "hw/misc/grlib_ahb_apb_pnp.h"
28
#include "trace.h"
29

30
#define GRLIB_PNP_VENDOR_SHIFT (24)
31
#define GRLIB_PNP_VENDOR_SIZE   (8)
32
#define GRLIB_PNP_DEV_SHIFT    (12)
33
#define GRLIB_PNP_DEV_SIZE     (12)
34
#define GRLIB_PNP_VER_SHIFT     (5)
35
#define GRLIB_PNP_VER_SIZE      (5)
36
#define GRLIB_PNP_IRQ_SHIFT     (0)
37
#define GRLIB_PNP_IRQ_SIZE      (5)
38
#define GRLIB_PNP_ADDR_SHIFT   (20)
39
#define GRLIB_PNP_ADDR_SIZE    (12)
40
#define GRLIB_PNP_MASK_SHIFT    (4)
41
#define GRLIB_PNP_MASK_SIZE    (12)
42

43
#define GRLIB_AHB_DEV_ADDR_SHIFT   (20)
44
#define GRLIB_AHB_DEV_ADDR_SIZE    (12)
45
#define GRLIB_AHB_ENTRY_SIZE       (0x20)
46
#define GRLIB_AHB_MAX_DEV          (64)
47
#define GRLIB_AHB_SLAVE_OFFSET     (0x800)
48

49
#define GRLIB_APB_DEV_ADDR_SHIFT   (8)
50
#define GRLIB_APB_DEV_ADDR_SIZE    (12)
51
#define GRLIB_APB_ENTRY_SIZE       (0x08)
52
#define GRLIB_APB_MAX_DEV          (512)
53

54
#define GRLIB_PNP_MAX_REGS         (0x1000)
55

56
typedef struct AHBPnp {
57
    SysBusDevice parent_obj;
58
    MemoryRegion iomem;
59

60
    uint32_t regs[GRLIB_PNP_MAX_REGS >> 2];
61
    uint8_t master_count;
62
    uint8_t slave_count;
63
} AHBPnp;
64

65
void grlib_ahb_pnp_add_entry(AHBPnp *dev, uint32_t address, uint32_t mask,
66
                             uint8_t vendor, uint16_t device, int slave,
67
                             int type)
68
{
69
    unsigned int reg_start;
70

71
    /*
72
     * AHB entries look like this:
73
     *
74
     * 31 -------- 23 -------- 11 ----- 9 -------- 4 --- 0
75
     *  | VENDOR ID | DEVICE ID | IRQ ? | VERSION  | IRQ |
76
     *  --------------------------------------------------
77
     *  |                      USER                      |
78
     *  --------------------------------------------------
79
     *  |                      USER                      |
80
     *  --------------------------------------------------
81
     *  |                      USER                      |
82
     *  --------------------------------------------------
83
     *  |                      USER                      |
84
     *  --------------------------------------------------
85
     * 31 ----------- 20 --- 15 ----------------- 3 ---- 0
86
     *  | ADDR[31..12] | 00PC |        MASK       | TYPE |
87
     *  --------------------------------------------------
88
     * 31 ----------- 20 --- 15 ----------------- 3 ---- 0
89
     *  | ADDR[31..12] | 00PC |        MASK       | TYPE |
90
     *  --------------------------------------------------
91
     * 31 ----------- 20 --- 15 ----------------- 3 ---- 0
92
     *  | ADDR[31..12] | 00PC |        MASK       | TYPE |
93
     *  --------------------------------------------------
94
     * 31 ----------- 20 --- 15 ----------------- 3 ---- 0
95
     *  | ADDR[31..12] | 00PC |        MASK       | TYPE |
96
     *  --------------------------------------------------
97
     */
98

99
    if (slave) {
100
        assert(dev->slave_count < GRLIB_AHB_MAX_DEV);
101
        reg_start = (GRLIB_AHB_SLAVE_OFFSET
102
                  + (dev->slave_count * GRLIB_AHB_ENTRY_SIZE)) >> 2;
103
        dev->slave_count++;
104
    } else {
105
        assert(dev->master_count < GRLIB_AHB_MAX_DEV);
106
        reg_start = (dev->master_count * GRLIB_AHB_ENTRY_SIZE) >> 2;
107
        dev->master_count++;
108
    }
109

110
    dev->regs[reg_start] = deposit32(dev->regs[reg_start],
111
                                     GRLIB_PNP_VENDOR_SHIFT,
112
                                     GRLIB_PNP_VENDOR_SIZE,
113
                                     vendor);
114
    dev->regs[reg_start] = deposit32(dev->regs[reg_start],
115
                                     GRLIB_PNP_DEV_SHIFT,
116
                                     GRLIB_PNP_DEV_SIZE,
117
                                     device);
118
    reg_start += 4;
119
    /* AHB Memory Space */
120
    dev->regs[reg_start] = type;
121
    dev->regs[reg_start] = deposit32(dev->regs[reg_start],
122
                                     GRLIB_PNP_ADDR_SHIFT,
123
                                     GRLIB_PNP_ADDR_SIZE,
124
                                     extract32(address,
125
                                               GRLIB_AHB_DEV_ADDR_SHIFT,
126
                                               GRLIB_AHB_DEV_ADDR_SIZE));
127
    dev->regs[reg_start] = deposit32(dev->regs[reg_start],
128
                                     GRLIB_PNP_MASK_SHIFT,
129
                                     GRLIB_PNP_MASK_SIZE,
130
                                     mask);
131
}
132

133
static uint64_t grlib_ahb_pnp_read(void *opaque, hwaddr offset, unsigned size)
134
{
135
    AHBPnp *ahb_pnp = GRLIB_AHB_PNP(opaque);
136
    uint32_t val;
137

138
    val = ahb_pnp->regs[offset >> 2];
139
    val = extract32(val, (4 - (offset & 3) - size) * 8, size * 8);
140
    trace_grlib_ahb_pnp_read(offset, size, val);
141

142
    return val;
143
}
144

145
static void grlib_ahb_pnp_write(void *opaque, hwaddr addr,
146
                                uint64_t val, unsigned size)
147
{
148
    qemu_log_mask(LOG_UNIMP, "%s not implemented\n", __func__);
149
}
150

151
static const MemoryRegionOps grlib_ahb_pnp_ops = {
152
    .read       = grlib_ahb_pnp_read,
153
    .write      = grlib_ahb_pnp_write,
154
    .endianness = DEVICE_BIG_ENDIAN,
155
    .impl = {
156
        .min_access_size = 1,
157
        .max_access_size = 4,
158
    },
159
};
160

161
static void grlib_ahb_pnp_realize(DeviceState *dev, Error **errp)
162
{
163
    AHBPnp *ahb_pnp = GRLIB_AHB_PNP(dev);
164
    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
165

166
    memory_region_init_io(&ahb_pnp->iomem, OBJECT(dev), &grlib_ahb_pnp_ops,
167
                          ahb_pnp, TYPE_GRLIB_AHB_PNP, GRLIB_PNP_MAX_REGS);
168
    sysbus_init_mmio(sbd, &ahb_pnp->iomem);
169
}
170

171
static void grlib_ahb_pnp_class_init(ObjectClass *klass, void *data)
172
{
173
    DeviceClass *dc = DEVICE_CLASS(klass);
174

175
    dc->realize = grlib_ahb_pnp_realize;
176
}
177

178
static const TypeInfo grlib_ahb_pnp_info = {
179
    .name          = TYPE_GRLIB_AHB_PNP,
180
    .parent        = TYPE_SYS_BUS_DEVICE,
181
    .instance_size = sizeof(AHBPnp),
182
    .class_init    = grlib_ahb_pnp_class_init,
183
};
184

185
/* APBPnp */
186

187
typedef struct APBPnp {
188
    SysBusDevice parent_obj;
189
    MemoryRegion iomem;
190

191
    uint32_t regs[GRLIB_PNP_MAX_REGS >> 2];
192
    uint32_t entry_count;
193
} APBPnp;
194

195
void grlib_apb_pnp_add_entry(APBPnp *dev, uint32_t address, uint32_t mask,
196
                             uint8_t vendor, uint16_t device, uint8_t version,
197
                             uint8_t irq, int type)
198
{
199
    unsigned int reg_start;
200

201
    /*
202
     * APB entries look like this:
203
     *
204
     * 31 -------- 23 -------- 11 ----- 9 ------- 4 --- 0
205
     *  | VENDOR ID | DEVICE ID | IRQ ? | VERSION | IRQ |
206
     *
207
     * 31 ---------- 20 --- 15 ----------------- 3 ---- 0
208
     *  | ADDR[20..8] | 0000 |        MASK       | TYPE |
209
     */
210

211
    assert(dev->entry_count < GRLIB_APB_MAX_DEV);
212
    reg_start = (dev->entry_count * GRLIB_APB_ENTRY_SIZE) >> 2;
213
    dev->entry_count++;
214

215
    dev->regs[reg_start] = deposit32(dev->regs[reg_start],
216
                                     GRLIB_PNP_VENDOR_SHIFT,
217
                                     GRLIB_PNP_VENDOR_SIZE,
218
                                     vendor);
219
    dev->regs[reg_start] = deposit32(dev->regs[reg_start],
220
                                     GRLIB_PNP_DEV_SHIFT,
221
                                     GRLIB_PNP_DEV_SIZE,
222
                                     device);
223
    dev->regs[reg_start] = deposit32(dev->regs[reg_start],
224
                                     GRLIB_PNP_VER_SHIFT,
225
                                     GRLIB_PNP_VER_SIZE,
226
                                     version);
227
    dev->regs[reg_start] = deposit32(dev->regs[reg_start],
228
                                     GRLIB_PNP_IRQ_SHIFT,
229
                                     GRLIB_PNP_IRQ_SIZE,
230
                                     irq);
231
    reg_start += 1;
232
    dev->regs[reg_start] = type;
233
    dev->regs[reg_start] = deposit32(dev->regs[reg_start],
234
                                     GRLIB_PNP_ADDR_SHIFT,
235
                                     GRLIB_PNP_ADDR_SIZE,
236
                                     extract32(address,
237
                                               GRLIB_APB_DEV_ADDR_SHIFT,
238
                                               GRLIB_APB_DEV_ADDR_SIZE));
239
    dev->regs[reg_start] = deposit32(dev->regs[reg_start],
240
                                     GRLIB_PNP_MASK_SHIFT,
241
                                     GRLIB_PNP_MASK_SIZE,
242
                                     mask);
243
}
244

245
static uint64_t grlib_apb_pnp_read(void *opaque, hwaddr offset, unsigned size)
246
{
247
    APBPnp *apb_pnp = GRLIB_APB_PNP(opaque);
248
    uint32_t val;
249

250
    val = apb_pnp->regs[offset >> 2];
251
    val = extract32(val, (4 - (offset & 3) - size) * 8, size * 8);
252
    trace_grlib_apb_pnp_read(offset, size, val);
253

254
    return val;
255
}
256

257
static void grlib_apb_pnp_write(void *opaque, hwaddr addr,
258
                                uint64_t val, unsigned size)
259
{
260
    qemu_log_mask(LOG_UNIMP, "%s not implemented\n", __func__);
261
}
262

263
static const MemoryRegionOps grlib_apb_pnp_ops = {
264
    .read       = grlib_apb_pnp_read,
265
    .write      = grlib_apb_pnp_write,
266
    .endianness = DEVICE_BIG_ENDIAN,
267
    .impl = {
268
        .min_access_size = 1,
269
        .max_access_size = 4,
270
    },
271
};
272

273
static void grlib_apb_pnp_realize(DeviceState *dev, Error **errp)
274
{
275
    APBPnp *apb_pnp = GRLIB_APB_PNP(dev);
276
    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
277

278
    memory_region_init_io(&apb_pnp->iomem, OBJECT(dev), &grlib_apb_pnp_ops,
279
                          apb_pnp, TYPE_GRLIB_APB_PNP, GRLIB_PNP_MAX_REGS);
280
    sysbus_init_mmio(sbd, &apb_pnp->iomem);
281
}
282

283
static void grlib_apb_pnp_class_init(ObjectClass *klass, void *data)
284
{
285
    DeviceClass *dc = DEVICE_CLASS(klass);
286

287
    dc->realize = grlib_apb_pnp_realize;
288
}
289

290
static const TypeInfo grlib_apb_pnp_info = {
291
    .name          = TYPE_GRLIB_APB_PNP,
292
    .parent        = TYPE_SYS_BUS_DEVICE,
293
    .instance_size = sizeof(APBPnp),
294
    .class_init    = grlib_apb_pnp_class_init,
295
};
296

297
static void grlib_ahb_apb_pnp_register_types(void)
298
{
299
    type_register_static(&grlib_ahb_pnp_info);
300
    type_register_static(&grlib_apb_pnp_info);
301
}
302

303
type_init(grlib_ahb_apb_pnp_register_types)
304

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

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

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

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