qemu

Форк
0
/
arm_sysctl.c 
662 строки · 20.1 Кб
1
/*
2
 * Status and system control registers for ARM RealView/Versatile boards.
3
 *
4
 * Copyright (c) 2006-2007 CodeSourcery.
5
 * Written by Paul Brook
6
 *
7
 * This code is licensed under the GPL.
8
 */
9

10
#include "qemu/osdep.h"
11
#include "hw/irq.h"
12
#include "hw/qdev-properties.h"
13
#include "qemu/timer.h"
14
#include "sysemu/runstate.h"
15
#include "qemu/bitops.h"
16
#include "hw/sysbus.h"
17
#include "migration/vmstate.h"
18
#include "hw/arm/primecell.h"
19
#include "qemu/log.h"
20
#include "qemu/module.h"
21
#include "qom/object.h"
22

23
#define LOCK_VALUE 0xa05f
24

25
#define TYPE_ARM_SYSCTL "realview_sysctl"
26
OBJECT_DECLARE_SIMPLE_TYPE(arm_sysctl_state, ARM_SYSCTL)
27

28
struct arm_sysctl_state {
29
    SysBusDevice parent_obj;
30

31
    MemoryRegion iomem;
32
    qemu_irq pl110_mux_ctrl;
33

34
    uint32_t sys_id;
35
    uint32_t leds;
36
    uint16_t lockval;
37
    uint32_t cfgdata1;
38
    uint32_t cfgdata2;
39
    uint32_t flags;
40
    uint32_t nvflags;
41
    uint32_t resetlevel;
42
    uint32_t proc_id;
43
    uint32_t sys_mci;
44
    uint32_t sys_cfgdata;
45
    uint32_t sys_cfgctrl;
46
    uint32_t sys_cfgstat;
47
    uint32_t sys_clcd;
48
    uint32_t mb_clock[6];
49
    uint32_t *db_clock;
50
    uint32_t db_num_vsensors;
51
    uint32_t *db_voltage;
52
    uint32_t db_num_clocks;
53
    uint32_t *db_clock_reset;
54
};
55

56
static const VMStateDescription vmstate_arm_sysctl = {
57
    .name = "realview_sysctl",
58
    .version_id = 4,
59
    .minimum_version_id = 1,
60
    .fields = (const VMStateField[]) {
61
        VMSTATE_UINT32(leds, arm_sysctl_state),
62
        VMSTATE_UINT16(lockval, arm_sysctl_state),
63
        VMSTATE_UINT32(cfgdata1, arm_sysctl_state),
64
        VMSTATE_UINT32(cfgdata2, arm_sysctl_state),
65
        VMSTATE_UINT32(flags, arm_sysctl_state),
66
        VMSTATE_UINT32(nvflags, arm_sysctl_state),
67
        VMSTATE_UINT32(resetlevel, arm_sysctl_state),
68
        VMSTATE_UINT32_V(sys_mci, arm_sysctl_state, 2),
69
        VMSTATE_UINT32_V(sys_cfgdata, arm_sysctl_state, 2),
70
        VMSTATE_UINT32_V(sys_cfgctrl, arm_sysctl_state, 2),
71
        VMSTATE_UINT32_V(sys_cfgstat, arm_sysctl_state, 2),
72
        VMSTATE_UINT32_V(sys_clcd, arm_sysctl_state, 3),
73
        VMSTATE_UINT32_ARRAY_V(mb_clock, arm_sysctl_state, 6, 4),
74
        VMSTATE_VARRAY_UINT32(db_clock, arm_sysctl_state, db_num_clocks,
75
                              4, vmstate_info_uint32, uint32_t),
76
        VMSTATE_END_OF_LIST()
77
    }
78
};
79

80
/* The PB926 actually uses a different format for
81
 * its SYS_ID register. Fortunately the bits which are
82
 * board type on later boards are distinct.
83
 */
84
#define BOARD_ID_PB926 0x100
85
#define BOARD_ID_EB 0x140
86
#define BOARD_ID_PBA8 0x178
87
#define BOARD_ID_PBX 0x182
88
#define BOARD_ID_VEXPRESS 0x190
89

90
static int board_id(arm_sysctl_state *s)
91
{
92
    /* Extract the board ID field from the SYS_ID register value */
93
    return (s->sys_id >> 16) & 0xfff;
94
}
95

96
static void arm_sysctl_reset(DeviceState *d)
97
{
98
    arm_sysctl_state *s = ARM_SYSCTL(d);
99
    int i;
100

101
    s->leds = 0;
102
    s->lockval = 0;
103
    s->cfgdata1 = 0;
104
    s->cfgdata2 = 0;
105
    s->flags = 0;
106
    s->resetlevel = 0;
107
    /* Motherboard oscillators (in Hz) */
108
    s->mb_clock[0] = 50000000; /* Static memory clock: 50MHz */
109
    s->mb_clock[1] = 23750000; /* motherboard CLCD clock: 23.75MHz */
110
    s->mb_clock[2] = 24000000; /* IO FPGA peripheral clock: 24MHz */
111
    s->mb_clock[3] = 24000000; /* IO FPGA reserved clock: 24MHz */
112
    s->mb_clock[4] = 24000000; /* System bus global clock: 24MHz */
113
    s->mb_clock[5] = 24000000; /* IO FPGA reserved clock: 24MHz */
114
    /* Daughterboard oscillators: reset from property values */
115
    for (i = 0; i < s->db_num_clocks; i++) {
116
        s->db_clock[i] = s->db_clock_reset[i];
117
    }
118
    if (board_id(s) == BOARD_ID_VEXPRESS) {
119
        /* On VExpress this register will RAZ/WI */
120
        s->sys_clcd = 0;
121
    } else {
122
        /* All others: CLCDID 0x1f, indicating VGA */
123
        s->sys_clcd = 0x1f00;
124
    }
125
}
126

127
static uint64_t arm_sysctl_read(void *opaque, hwaddr offset,
128
                                unsigned size)
129
{
130
    arm_sysctl_state *s = (arm_sysctl_state *)opaque;
131

132
    switch (offset) {
133
    case 0x00: /* ID */
134
        return s->sys_id;
135
    case 0x04: /* SW */
136
        /* General purpose hardware switches.
137
           We don't have a useful way of exposing these to the user.  */
138
        return 0;
139
    case 0x08: /* LED */
140
        return s->leds;
141
    case 0x20: /* LOCK */
142
        return s->lockval;
143
    case 0x0c: /* OSC0 */
144
    case 0x10: /* OSC1 */
145
    case 0x14: /* OSC2 */
146
    case 0x18: /* OSC3 */
147
    case 0x1c: /* OSC4 */
148
    case 0x24: /* 100HZ */
149
        /* ??? Implement these.  */
150
        return 0;
151
    case 0x28: /* CFGDATA1 */
152
        return s->cfgdata1;
153
    case 0x2c: /* CFGDATA2 */
154
        return s->cfgdata2;
155
    case 0x30: /* FLAGS */
156
        return s->flags;
157
    case 0x38: /* NVFLAGS */
158
        return s->nvflags;
159
    case 0x40: /* RESETCTL */
160
        if (board_id(s) == BOARD_ID_VEXPRESS) {
161
            /* reserved: RAZ/WI */
162
            return 0;
163
        }
164
        return s->resetlevel;
165
    case 0x44: /* PCICTL */
166
        return 1;
167
    case 0x48: /* MCI */
168
        return s->sys_mci;
169
    case 0x4c: /* FLASH */
170
        return 0;
171
    case 0x50: /* CLCD */
172
        return s->sys_clcd;
173
    case 0x54: /* CLCDSER */
174
        return 0;
175
    case 0x58: /* BOOTCS */
176
        return 0;
177
    case 0x5c: /* 24MHz */
178
        return muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), 24000000,
179
                        NANOSECONDS_PER_SECOND);
180
    case 0x60: /* MISC */
181
        return 0;
182
    case 0x84: /* PROCID0 */
183
        return s->proc_id;
184
    case 0x88: /* PROCID1 */
185
        return 0xff000000;
186
    case 0x64: /* DMAPSR0 */
187
    case 0x68: /* DMAPSR1 */
188
    case 0x6c: /* DMAPSR2 */
189
    case 0x70: /* IOSEL */
190
    case 0x74: /* PLDCTL */
191
    case 0x80: /* BUSID */
192
    case 0x8c: /* OSCRESET0 */
193
    case 0x90: /* OSCRESET1 */
194
    case 0x94: /* OSCRESET2 */
195
    case 0x98: /* OSCRESET3 */
196
    case 0x9c: /* OSCRESET4 */
197
    case 0xc0: /* SYS_TEST_OSC0 */
198
    case 0xc4: /* SYS_TEST_OSC1 */
199
    case 0xc8: /* SYS_TEST_OSC2 */
200
    case 0xcc: /* SYS_TEST_OSC3 */
201
    case 0xd0: /* SYS_TEST_OSC4 */
202
        return 0;
203
    case 0xa0: /* SYS_CFGDATA */
204
        if (board_id(s) != BOARD_ID_VEXPRESS) {
205
            goto bad_reg;
206
        }
207
        return s->sys_cfgdata;
208
    case 0xa4: /* SYS_CFGCTRL */
209
        if (board_id(s) != BOARD_ID_VEXPRESS) {
210
            goto bad_reg;
211
        }
212
        return s->sys_cfgctrl;
213
    case 0xa8: /* SYS_CFGSTAT */
214
        if (board_id(s) != BOARD_ID_VEXPRESS) {
215
            goto bad_reg;
216
        }
217
        return s->sys_cfgstat;
218
    default:
219
    bad_reg:
220
        qemu_log_mask(LOG_GUEST_ERROR,
221
                      "arm_sysctl_read: Bad register offset 0x%x\n",
222
                      (int)offset);
223
        return 0;
224
    }
225
}
226

227
/* SYS_CFGCTRL functions */
228
#define SYS_CFG_OSC 1
229
#define SYS_CFG_VOLT 2
230
#define SYS_CFG_AMP 3
231
#define SYS_CFG_TEMP 4
232
#define SYS_CFG_RESET 5
233
#define SYS_CFG_SCC 6
234
#define SYS_CFG_MUXFPGA 7
235
#define SYS_CFG_SHUTDOWN 8
236
#define SYS_CFG_REBOOT 9
237
#define SYS_CFG_DVIMODE 11
238
#define SYS_CFG_POWER 12
239
#define SYS_CFG_ENERGY 13
240

241
/* SYS_CFGCTRL site field values */
242
#define SYS_CFG_SITE_MB 0
243
#define SYS_CFG_SITE_DB1 1
244
#define SYS_CFG_SITE_DB2 2
245

246
/**
247
 * vexpress_cfgctrl_read:
248
 * @s: arm_sysctl_state pointer
249
 * @dcc, @function, @site, @position, @device: split out values from
250
 * SYS_CFGCTRL register
251
 * @val: pointer to where to put the read data on success
252
 *
253
 * Handle a VExpress SYS_CFGCTRL register read. On success, return true and
254
 * write the read value to *val. On failure, return false (and val may
255
 * or may not be written to).
256
 */
257
static bool vexpress_cfgctrl_read(arm_sysctl_state *s, unsigned int dcc,
258
                                  unsigned int function, unsigned int site,
259
                                  unsigned int position, unsigned int device,
260
                                  uint32_t *val)
261
{
262
    /* We don't support anything other than DCC 0, board stack position 0
263
     * or sites other than motherboard/daughterboard:
264
     */
265
    if (dcc != 0 || position != 0 ||
266
        (site != SYS_CFG_SITE_MB && site != SYS_CFG_SITE_DB1)) {
267
        goto cfgctrl_unimp;
268
    }
269

270
    switch (function) {
271
    case SYS_CFG_VOLT:
272
        if (site == SYS_CFG_SITE_DB1 && device < s->db_num_vsensors) {
273
            *val = s->db_voltage[device];
274
            return true;
275
        }
276
        if (site == SYS_CFG_SITE_MB && device == 0) {
277
            /* There is only one motherboard voltage sensor:
278
             * VIO : 3.3V : bus voltage between mother and daughterboard
279
             */
280
            *val = 3300000;
281
            return true;
282
        }
283
        break;
284
    case SYS_CFG_OSC:
285
        if (site == SYS_CFG_SITE_MB && device < ARRAY_SIZE(s->mb_clock)) {
286
            /* motherboard clock */
287
            *val = s->mb_clock[device];
288
            return true;
289
        }
290
        if (site == SYS_CFG_SITE_DB1 && device < s->db_num_clocks) {
291
            /* daughterboard clock */
292
            *val = s->db_clock[device];
293
            return true;
294
        }
295
        break;
296
    default:
297
        break;
298
    }
299

300
cfgctrl_unimp:
301
    qemu_log_mask(LOG_UNIMP,
302
                  "arm_sysctl: Unimplemented SYS_CFGCTRL read of function "
303
                  "0x%x DCC 0x%x site 0x%x position 0x%x device 0x%x\n",
304
                  function, dcc, site, position, device);
305
    return false;
306
}
307

308
/**
309
 * vexpress_cfgctrl_write:
310
 * @s: arm_sysctl_state pointer
311
 * @dcc, @function, @site, @position, @device: split out values from
312
 * SYS_CFGCTRL register
313
 * @val: data to write
314
 *
315
 * Handle a VExpress SYS_CFGCTRL register write. On success, return true.
316
 * On failure, return false.
317
 */
318
static bool vexpress_cfgctrl_write(arm_sysctl_state *s, unsigned int dcc,
319
                                   unsigned int function, unsigned int site,
320
                                   unsigned int position, unsigned int device,
321
                                   uint32_t val)
322
{
323
    /* We don't support anything other than DCC 0, board stack position 0
324
     * or sites other than motherboard/daughterboard:
325
     */
326
    if (dcc != 0 || position != 0 ||
327
        (site != SYS_CFG_SITE_MB && site != SYS_CFG_SITE_DB1)) {
328
        goto cfgctrl_unimp;
329
    }
330

331
    switch (function) {
332
    case SYS_CFG_OSC:
333
        if (site == SYS_CFG_SITE_MB && device < ARRAY_SIZE(s->mb_clock)) {
334
            /* motherboard clock */
335
            s->mb_clock[device] = val;
336
            return true;
337
        }
338
        if (site == SYS_CFG_SITE_DB1 && device < s->db_num_clocks) {
339
            /* daughterboard clock */
340
            s->db_clock[device] = val;
341
            return true;
342
        }
343
        break;
344
    case SYS_CFG_MUXFPGA:
345
        if (site == SYS_CFG_SITE_MB && device == 0) {
346
            /* Select whether video output comes from motherboard
347
             * or daughterboard: log and ignore as QEMU doesn't
348
             * support this.
349
             */
350
            qemu_log_mask(LOG_UNIMP, "arm_sysctl: selection of video output "
351
                          "not supported, ignoring\n");
352
            return true;
353
        }
354
        break;
355
    case SYS_CFG_SHUTDOWN:
356
        if (site == SYS_CFG_SITE_MB && device == 0) {
357
            qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
358
            return true;
359
        }
360
        break;
361
    case SYS_CFG_REBOOT:
362
        if (site == SYS_CFG_SITE_MB && device == 0) {
363
            qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
364
            return true;
365
        }
366
        break;
367
    case SYS_CFG_DVIMODE:
368
        if (site == SYS_CFG_SITE_MB && device == 0) {
369
            /* Selecting DVI mode is meaningless for QEMU: we will
370
             * always display the output correctly according to the
371
             * pixel height/width programmed into the CLCD controller.
372
             */
373
            return true;
374
        }
375
    default:
376
        break;
377
    }
378

379
cfgctrl_unimp:
380
    qemu_log_mask(LOG_UNIMP,
381
                  "arm_sysctl: Unimplemented SYS_CFGCTRL write of function "
382
                  "0x%x DCC 0x%x site 0x%x position 0x%x device 0x%x\n",
383
                  function, dcc, site, position, device);
384
    return false;
385
}
386

387
static void arm_sysctl_write(void *opaque, hwaddr offset,
388
                             uint64_t val, unsigned size)
389
{
390
    arm_sysctl_state *s = (arm_sysctl_state *)opaque;
391

392
    switch (offset) {
393
    case 0x08: /* LED */
394
        s->leds = val;
395
        break;
396
    case 0x0c: /* OSC0 */
397
    case 0x10: /* OSC1 */
398
    case 0x14: /* OSC2 */
399
    case 0x18: /* OSC3 */
400
    case 0x1c: /* OSC4 */
401
        /* ??? */
402
        break;
403
    case 0x20: /* LOCK */
404
        if (val == LOCK_VALUE)
405
            s->lockval = val;
406
        else
407
            s->lockval = val & 0x7fff;
408
        break;
409
    case 0x28: /* CFGDATA1 */
410
        /* ??? Need to implement this.  */
411
        s->cfgdata1 = val;
412
        break;
413
    case 0x2c: /* CFGDATA2 */
414
        /* ??? Need to implement this.  */
415
        s->cfgdata2 = val;
416
        break;
417
    case 0x30: /* FLAGSSET */
418
        s->flags |= val;
419
        break;
420
    case 0x34: /* FLAGSCLR */
421
        s->flags &= ~val;
422
        break;
423
    case 0x38: /* NVFLAGSSET */
424
        s->nvflags |= val;
425
        break;
426
    case 0x3c: /* NVFLAGSCLR */
427
        s->nvflags &= ~val;
428
        break;
429
    case 0x40: /* RESETCTL */
430
        switch (board_id(s)) {
431
        case BOARD_ID_PB926:
432
            if (s->lockval == LOCK_VALUE) {
433
                s->resetlevel = val;
434
                if (val & 0x100) {
435
                    qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
436
                }
437
            }
438
            break;
439
        case BOARD_ID_PBX:
440
        case BOARD_ID_PBA8:
441
            if (s->lockval == LOCK_VALUE) {
442
                s->resetlevel = val;
443
                if (val & 0x04) {
444
                    qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
445
                }
446
            }
447
            break;
448
        case BOARD_ID_VEXPRESS:
449
        case BOARD_ID_EB:
450
        default:
451
            /* reserved: RAZ/WI */
452
            break;
453
        }
454
        break;
455
    case 0x44: /* PCICTL */
456
        /* nothing to do.  */
457
        break;
458
    case 0x4c: /* FLASH */
459
        break;
460
    case 0x50: /* CLCD */
461
        switch (board_id(s)) {
462
        case BOARD_ID_PB926:
463
            /* On 926 bits 13:8 are R/O, bits 1:0 control
464
             * the mux that defines how to interpret the PL110
465
             * graphics format, and other bits are r/w but we
466
             * don't implement them to do anything.
467
             */
468
            s->sys_clcd &= 0x3f00;
469
            s->sys_clcd |= val & ~0x3f00;
470
            qemu_set_irq(s->pl110_mux_ctrl, val & 3);
471
            break;
472
        case BOARD_ID_EB:
473
            /* The EB is the same except that there is no mux since
474
             * the EB has a PL111.
475
             */
476
            s->sys_clcd &= 0x3f00;
477
            s->sys_clcd |= val & ~0x3f00;
478
            break;
479
        case BOARD_ID_PBA8:
480
        case BOARD_ID_PBX:
481
            /* On PBA8 and PBX bit 7 is r/w and all other bits
482
             * are either r/o or RAZ/WI.
483
             */
484
            s->sys_clcd &= (1 << 7);
485
            s->sys_clcd |= val & ~(1 << 7);
486
            break;
487
        case BOARD_ID_VEXPRESS:
488
        default:
489
            /* On VExpress this register is unimplemented and will RAZ/WI */
490
            break;
491
        }
492
        break;
493
    case 0x54: /* CLCDSER */
494
    case 0x64: /* DMAPSR0 */
495
    case 0x68: /* DMAPSR1 */
496
    case 0x6c: /* DMAPSR2 */
497
    case 0x70: /* IOSEL */
498
    case 0x74: /* PLDCTL */
499
    case 0x80: /* BUSID */
500
    case 0x84: /* PROCID0 */
501
    case 0x88: /* PROCID1 */
502
    case 0x8c: /* OSCRESET0 */
503
    case 0x90: /* OSCRESET1 */
504
    case 0x94: /* OSCRESET2 */
505
    case 0x98: /* OSCRESET3 */
506
    case 0x9c: /* OSCRESET4 */
507
        break;
508
    case 0xa0: /* SYS_CFGDATA */
509
        if (board_id(s) != BOARD_ID_VEXPRESS) {
510
            goto bad_reg;
511
        }
512
        s->sys_cfgdata = val;
513
        return;
514
    case 0xa4: /* SYS_CFGCTRL */
515
        if (board_id(s) != BOARD_ID_VEXPRESS) {
516
            goto bad_reg;
517
        }
518
        /* Undefined bits [19:18] are RAZ/WI, and writing to
519
         * the start bit just triggers the action; it always reads
520
         * as zero.
521
         */
522
        s->sys_cfgctrl = val & ~((3 << 18) | (1 << 31));
523
        if (val & (1 << 31)) {
524
            /* Start bit set -- actually do something */
525
            unsigned int dcc = extract32(s->sys_cfgctrl, 26, 4);
526
            unsigned int function = extract32(s->sys_cfgctrl, 20, 6);
527
            unsigned int site = extract32(s->sys_cfgctrl, 16, 2);
528
            unsigned int position = extract32(s->sys_cfgctrl, 12, 4);
529
            unsigned int device = extract32(s->sys_cfgctrl, 0, 12);
530
            s->sys_cfgstat = 1;            /* complete */
531
            if (s->sys_cfgctrl & (1 << 30)) {
532
                if (!vexpress_cfgctrl_write(s, dcc, function, site, position,
533
                                            device, s->sys_cfgdata)) {
534
                    s->sys_cfgstat |= 2;        /* error */
535
                }
536
            } else {
537
                uint32_t data;
538
                if (!vexpress_cfgctrl_read(s, dcc, function, site, position,
539
                                           device, &data)) {
540
                    s->sys_cfgstat |= 2;        /* error */
541
                } else {
542
                    s->sys_cfgdata = data;
543
                }
544
            }
545
        }
546
        s->sys_cfgctrl &= ~(1 << 31);
547
        return;
548
    case 0xa8: /* SYS_CFGSTAT */
549
        if (board_id(s) != BOARD_ID_VEXPRESS) {
550
            goto bad_reg;
551
        }
552
        s->sys_cfgstat = val & 3;
553
        return;
554
    default:
555
    bad_reg:
556
        qemu_log_mask(LOG_GUEST_ERROR,
557
                      "arm_sysctl_write: Bad register offset 0x%x\n",
558
                      (int)offset);
559
        return;
560
    }
561
}
562

563
static const MemoryRegionOps arm_sysctl_ops = {
564
    .read = arm_sysctl_read,
565
    .write = arm_sysctl_write,
566
    .endianness = DEVICE_NATIVE_ENDIAN,
567
};
568

569
static void arm_sysctl_gpio_set(void *opaque, int line, int level)
570
{
571
    arm_sysctl_state *s = (arm_sysctl_state *)opaque;
572
    switch (line) {
573
    case ARM_SYSCTL_GPIO_MMC_WPROT:
574
    {
575
        /* For PB926 and EB write-protect is bit 2 of SYS_MCI;
576
         * for all later boards it is bit 1.
577
         */
578
        int bit = 2;
579
        if ((board_id(s) == BOARD_ID_PB926) || (board_id(s) == BOARD_ID_EB)) {
580
            bit = 4;
581
        }
582
        s->sys_mci &= ~bit;
583
        if (level) {
584
            s->sys_mci |= bit;
585
        }
586
        break;
587
    }
588
    case ARM_SYSCTL_GPIO_MMC_CARDIN:
589
        s->sys_mci &= ~1;
590
        if (level) {
591
            s->sys_mci |= 1;
592
        }
593
        break;
594
    }
595
}
596

597
static void arm_sysctl_init(Object *obj)
598
{
599
    DeviceState *dev = DEVICE(obj);
600
    SysBusDevice *sd = SYS_BUS_DEVICE(obj);
601
    arm_sysctl_state *s = ARM_SYSCTL(obj);
602

603
    memory_region_init_io(&s->iomem, OBJECT(dev), &arm_sysctl_ops, s,
604
                          "arm-sysctl", 0x1000);
605
    sysbus_init_mmio(sd, &s->iomem);
606
    qdev_init_gpio_in(dev, arm_sysctl_gpio_set, 2);
607
    qdev_init_gpio_out(dev, &s->pl110_mux_ctrl, 1);
608
}
609

610
static void arm_sysctl_realize(DeviceState *d, Error **errp)
611
{
612
    arm_sysctl_state *s = ARM_SYSCTL(d);
613

614
    s->db_clock = g_new0(uint32_t, s->db_num_clocks);
615
}
616

617
static void arm_sysctl_finalize(Object *obj)
618
{
619
    arm_sysctl_state *s = ARM_SYSCTL(obj);
620

621
    g_free(s->db_voltage);
622
    g_free(s->db_clock);
623
    g_free(s->db_clock_reset);
624
}
625

626
static Property arm_sysctl_properties[] = {
627
    DEFINE_PROP_UINT32("sys_id", arm_sysctl_state, sys_id, 0),
628
    DEFINE_PROP_UINT32("proc_id", arm_sysctl_state, proc_id, 0),
629
    /* Daughterboard power supply voltages (as reported via SYS_CFG) */
630
    DEFINE_PROP_ARRAY("db-voltage", arm_sysctl_state, db_num_vsensors,
631
                      db_voltage, qdev_prop_uint32, uint32_t),
632
    /* Daughterboard clock reset values (as reported via SYS_CFG) */
633
    DEFINE_PROP_ARRAY("db-clock", arm_sysctl_state, db_num_clocks,
634
                      db_clock_reset, qdev_prop_uint32, uint32_t),
635
    DEFINE_PROP_END_OF_LIST(),
636
};
637

638
static void arm_sysctl_class_init(ObjectClass *klass, void *data)
639
{
640
    DeviceClass *dc = DEVICE_CLASS(klass);
641

642
    dc->realize = arm_sysctl_realize;
643
    dc->reset = arm_sysctl_reset;
644
    dc->vmsd = &vmstate_arm_sysctl;
645
    device_class_set_props(dc, arm_sysctl_properties);
646
}
647

648
static const TypeInfo arm_sysctl_info = {
649
    .name          = TYPE_ARM_SYSCTL,
650
    .parent        = TYPE_SYS_BUS_DEVICE,
651
    .instance_size = sizeof(arm_sysctl_state),
652
    .instance_init = arm_sysctl_init,
653
    .instance_finalize = arm_sysctl_finalize,
654
    .class_init    = arm_sysctl_class_init,
655
};
656

657
static void arm_sysctl_register_types(void)
658
{
659
    type_register_static(&arm_sysctl_info);
660
}
661

662
type_init(arm_sysctl_register_types)
663

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

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

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

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