Statistics
| Branch: | Revision:

root / hw / integratorcp.c @ 61074e46

History | View | Annotate | Download (15.6 kB)

1
/*
2
 * ARM Integrator CP System emulation.
3
 *
4
 * Copyright (c) 2005-2007 CodeSourcery.
5
 * Written by Paul Brook
6
 *
7
 * This code is licensed under the GPL
8
 */
9

    
10
#include "sysbus.h"
11
#include "primecell.h"
12
#include "devices.h"
13
#include "boards.h"
14
#include "arm-misc.h"
15
#include "net.h"
16
#include "exec-memory.h"
17
#include "sysemu.h"
18

    
19
typedef struct {
20
    SysBusDevice busdev;
21
    MemoryRegion iomem;
22
    uint32_t memsz;
23
    MemoryRegion flash;
24
    bool flash_mapped;
25
    uint32_t cm_osc;
26
    uint32_t cm_ctrl;
27
    uint32_t cm_lock;
28
    uint32_t cm_auxosc;
29
    uint32_t cm_sdram;
30
    uint32_t cm_init;
31
    uint32_t cm_flags;
32
    uint32_t cm_nvflags;
33
    uint32_t int_level;
34
    uint32_t irq_enabled;
35
    uint32_t fiq_enabled;
36
} integratorcm_state;
37

    
38
static uint8_t integrator_spd[128] = {
39
   128, 8, 4, 11, 9, 1, 64, 0,  2, 0xa0, 0xa0, 0, 0, 8, 0, 1,
40
   0xe, 4, 0x1c, 1, 2, 0x20, 0xc0, 0, 0, 0, 0, 0x30, 0x28, 0x30, 0x28, 0x40
41
};
42

    
43
static uint64_t integratorcm_read(void *opaque, target_phys_addr_t offset,
44
                                  unsigned size)
45
{
46
    integratorcm_state *s = (integratorcm_state *)opaque;
47
    if (offset >= 0x100 && offset < 0x200) {
48
        /* CM_SPD */
49
        if (offset >= 0x180)
50
            return 0;
51
        return integrator_spd[offset >> 2];
52
    }
53
    switch (offset >> 2) {
54
    case 0: /* CM_ID */
55
        return 0x411a3001;
56
    case 1: /* CM_PROC */
57
        return 0;
58
    case 2: /* CM_OSC */
59
        return s->cm_osc;
60
    case 3: /* CM_CTRL */
61
        return s->cm_ctrl;
62
    case 4: /* CM_STAT */
63
        return 0x00100000;
64
    case 5: /* CM_LOCK */
65
        if (s->cm_lock == 0xa05f) {
66
            return 0x1a05f;
67
        } else {
68
            return s->cm_lock;
69
        }
70
    case 6: /* CM_LMBUSCNT */
71
        /* ??? High frequency timer.  */
72
        hw_error("integratorcm_read: CM_LMBUSCNT");
73
    case 7: /* CM_AUXOSC */
74
        return s->cm_auxosc;
75
    case 8: /* CM_SDRAM */
76
        return s->cm_sdram;
77
    case 9: /* CM_INIT */
78
        return s->cm_init;
79
    case 10: /* CM_REFCT */
80
        /* ??? High frequency timer.  */
81
        hw_error("integratorcm_read: CM_REFCT");
82
    case 12: /* CM_FLAGS */
83
        return s->cm_flags;
84
    case 14: /* CM_NVFLAGS */
85
        return s->cm_nvflags;
86
    case 16: /* CM_IRQ_STAT */
87
        return s->int_level & s->irq_enabled;
88
    case 17: /* CM_IRQ_RSTAT */
89
        return s->int_level;
90
    case 18: /* CM_IRQ_ENSET */
91
        return s->irq_enabled;
92
    case 20: /* CM_SOFT_INTSET */
93
        return s->int_level & 1;
94
    case 24: /* CM_FIQ_STAT */
95
        return s->int_level & s->fiq_enabled;
96
    case 25: /* CM_FIQ_RSTAT */
97
        return s->int_level;
98
    case 26: /* CM_FIQ_ENSET */
99
        return s->fiq_enabled;
100
    case 32: /* CM_VOLTAGE_CTL0 */
101
    case 33: /* CM_VOLTAGE_CTL1 */
102
    case 34: /* CM_VOLTAGE_CTL2 */
103
    case 35: /* CM_VOLTAGE_CTL3 */
104
        /* ??? Voltage control unimplemented.  */
105
        return 0;
106
    default:
107
        hw_error("integratorcm_read: Unimplemented offset 0x%x\n",
108
                 (int)offset);
109
        return 0;
110
    }
111
}
112

    
113
static void integratorcm_do_remap(integratorcm_state *s, int flash)
114
{
115
    if (flash) {
116
        if (s->flash_mapped) {
117
            sysbus_del_memory(&s->busdev, &s->flash);
118
            s->flash_mapped = false;
119
        }
120
    } else {
121
        if (!s->flash_mapped) {
122
            sysbus_add_memory_overlap(&s->busdev, 0, &s->flash, 1);
123
            s->flash_mapped = true;
124
        }
125
    }
126
    //??? tlb_flush (cpu_single_env, 1);
127
}
128

    
129
static void integratorcm_set_ctrl(integratorcm_state *s, uint32_t value)
130
{
131
    if (value & 8) {
132
        qemu_system_reset_request();
133
    }
134
    if ((s->cm_ctrl ^ value) & 4) {
135
        integratorcm_do_remap(s, (value & 4) == 0);
136
    }
137
    if ((s->cm_ctrl ^ value) & 1) {
138
        /* (value & 1) != 0 means the green "MISC LED" is lit.
139
         * We don't have any nice place to display LEDs. printf is a bad
140
         * idea because Linux uses the LED as a heartbeat and the output
141
         * will swamp anything else on the terminal.
142
         */
143
    }
144
    /* Note that the RESET bit [3] always reads as zero */
145
    s->cm_ctrl = (s->cm_ctrl & ~5) | (value & 5);
146
}
147

    
148
static void integratorcm_update(integratorcm_state *s)
149
{
150
    /* ??? The CPU irq/fiq is raised when either the core module or base PIC
151
       are active.  */
152
    if (s->int_level & (s->irq_enabled | s->fiq_enabled))
153
        hw_error("Core module interrupt\n");
154
}
155

    
156
static void integratorcm_write(void *opaque, target_phys_addr_t offset,
157
                               uint64_t value, unsigned size)
158
{
159
    integratorcm_state *s = (integratorcm_state *)opaque;
160
    switch (offset >> 2) {
161
    case 2: /* CM_OSC */
162
        if (s->cm_lock == 0xa05f)
163
            s->cm_osc = value;
164
        break;
165
    case 3: /* CM_CTRL */
166
        integratorcm_set_ctrl(s, value);
167
        break;
168
    case 5: /* CM_LOCK */
169
        s->cm_lock = value & 0xffff;
170
        break;
171
    case 7: /* CM_AUXOSC */
172
        if (s->cm_lock == 0xa05f)
173
            s->cm_auxosc = value;
174
        break;
175
    case 8: /* CM_SDRAM */
176
        s->cm_sdram = value;
177
        break;
178
    case 9: /* CM_INIT */
179
        /* ??? This can change the memory bus frequency.  */
180
        s->cm_init = value;
181
        break;
182
    case 12: /* CM_FLAGSS */
183
        s->cm_flags |= value;
184
        break;
185
    case 13: /* CM_FLAGSC */
186
        s->cm_flags &= ~value;
187
        break;
188
    case 14: /* CM_NVFLAGSS */
189
        s->cm_nvflags |= value;
190
        break;
191
    case 15: /* CM_NVFLAGSS */
192
        s->cm_nvflags &= ~value;
193
        break;
194
    case 18: /* CM_IRQ_ENSET */
195
        s->irq_enabled |= value;
196
        integratorcm_update(s);
197
        break;
198
    case 19: /* CM_IRQ_ENCLR */
199
        s->irq_enabled &= ~value;
200
        integratorcm_update(s);
201
        break;
202
    case 20: /* CM_SOFT_INTSET */
203
        s->int_level |= (value & 1);
204
        integratorcm_update(s);
205
        break;
206
    case 21: /* CM_SOFT_INTCLR */
207
        s->int_level &= ~(value & 1);
208
        integratorcm_update(s);
209
        break;
210
    case 26: /* CM_FIQ_ENSET */
211
        s->fiq_enabled |= value;
212
        integratorcm_update(s);
213
        break;
214
    case 27: /* CM_FIQ_ENCLR */
215
        s->fiq_enabled &= ~value;
216
        integratorcm_update(s);
217
        break;
218
    case 32: /* CM_VOLTAGE_CTL0 */
219
    case 33: /* CM_VOLTAGE_CTL1 */
220
    case 34: /* CM_VOLTAGE_CTL2 */
221
    case 35: /* CM_VOLTAGE_CTL3 */
222
        /* ??? Voltage control unimplemented.  */
223
        break;
224
    default:
225
        hw_error("integratorcm_write: Unimplemented offset 0x%x\n",
226
                 (int)offset);
227
        break;
228
    }
229
}
230

    
231
/* Integrator/CM control registers.  */
232

    
233
static const MemoryRegionOps integratorcm_ops = {
234
    .read = integratorcm_read,
235
    .write = integratorcm_write,
236
    .endianness = DEVICE_NATIVE_ENDIAN,
237
};
238

    
239
static int integratorcm_init(SysBusDevice *dev)
240
{
241
    integratorcm_state *s = FROM_SYSBUS(integratorcm_state, dev);
242

    
243
    s->cm_osc = 0x01000048;
244
    /* ??? What should the high bits of this value be?  */
245
    s->cm_auxosc = 0x0007feff;
246
    s->cm_sdram = 0x00011122;
247
    if (s->memsz >= 256) {
248
        integrator_spd[31] = 64;
249
        s->cm_sdram |= 0x10;
250
    } else if (s->memsz >= 128) {
251
        integrator_spd[31] = 32;
252
        s->cm_sdram |= 0x0c;
253
    } else if (s->memsz >= 64) {
254
        integrator_spd[31] = 16;
255
        s->cm_sdram |= 0x08;
256
    } else if (s->memsz >= 32) {
257
        integrator_spd[31] = 4;
258
        s->cm_sdram |= 0x04;
259
    } else {
260
        integrator_spd[31] = 2;
261
    }
262
    memcpy(integrator_spd + 73, "QEMU-MEMORY", 11);
263
    s->cm_init = 0x00000112;
264
    memory_region_init_ram(&s->flash, NULL, "integrator.flash", 0x100000);
265
    s->flash_mapped = false;
266

    
267
    memory_region_init_io(&s->iomem, &integratorcm_ops, s,
268
                          "integratorcm", 0x00800000);
269
    sysbus_init_mmio_region(dev, &s->iomem);
270

    
271
    integratorcm_do_remap(s, 1);
272
    /* ??? Save/restore.  */
273
    return 0;
274
}
275

    
276
/* Integrator/CP hardware emulation.  */
277
/* Primary interrupt controller.  */
278

    
279
typedef struct icp_pic_state
280
{
281
  SysBusDevice busdev;
282
  MemoryRegion iomem;
283
  uint32_t level;
284
  uint32_t irq_enabled;
285
  uint32_t fiq_enabled;
286
  qemu_irq parent_irq;
287
  qemu_irq parent_fiq;
288
} icp_pic_state;
289

    
290
static void icp_pic_update(icp_pic_state *s)
291
{
292
    uint32_t flags;
293

    
294
    flags = (s->level & s->irq_enabled);
295
    qemu_set_irq(s->parent_irq, flags != 0);
296
    flags = (s->level & s->fiq_enabled);
297
    qemu_set_irq(s->parent_fiq, flags != 0);
298
}
299

    
300
static void icp_pic_set_irq(void *opaque, int irq, int level)
301
{
302
    icp_pic_state *s = (icp_pic_state *)opaque;
303
    if (level)
304
        s->level |= 1 << irq;
305
    else
306
        s->level &= ~(1 << irq);
307
    icp_pic_update(s);
308
}
309

    
310
static uint64_t icp_pic_read(void *opaque, target_phys_addr_t offset,
311
                             unsigned size)
312
{
313
    icp_pic_state *s = (icp_pic_state *)opaque;
314

    
315
    switch (offset >> 2) {
316
    case 0: /* IRQ_STATUS */
317
        return s->level & s->irq_enabled;
318
    case 1: /* IRQ_RAWSTAT */
319
        return s->level;
320
    case 2: /* IRQ_ENABLESET */
321
        return s->irq_enabled;
322
    case 4: /* INT_SOFTSET */
323
        return s->level & 1;
324
    case 8: /* FRQ_STATUS */
325
        return s->level & s->fiq_enabled;
326
    case 9: /* FRQ_RAWSTAT */
327
        return s->level;
328
    case 10: /* FRQ_ENABLESET */
329
        return s->fiq_enabled;
330
    case 3: /* IRQ_ENABLECLR */
331
    case 5: /* INT_SOFTCLR */
332
    case 11: /* FRQ_ENABLECLR */
333
    default:
334
        printf ("icp_pic_read: Bad register offset 0x%x\n", (int)offset);
335
        return 0;
336
    }
337
}
338

    
339
static void icp_pic_write(void *opaque, target_phys_addr_t offset,
340
                          uint64_t value, unsigned size)
341
{
342
    icp_pic_state *s = (icp_pic_state *)opaque;
343

    
344
    switch (offset >> 2) {
345
    case 2: /* IRQ_ENABLESET */
346
        s->irq_enabled |= value;
347
        break;
348
    case 3: /* IRQ_ENABLECLR */
349
        s->irq_enabled &= ~value;
350
        break;
351
    case 4: /* INT_SOFTSET */
352
        if (value & 1)
353
            icp_pic_set_irq(s, 0, 1);
354
        break;
355
    case 5: /* INT_SOFTCLR */
356
        if (value & 1)
357
            icp_pic_set_irq(s, 0, 0);
358
        break;
359
    case 10: /* FRQ_ENABLESET */
360
        s->fiq_enabled |= value;
361
        break;
362
    case 11: /* FRQ_ENABLECLR */
363
        s->fiq_enabled &= ~value;
364
        break;
365
    case 0: /* IRQ_STATUS */
366
    case 1: /* IRQ_RAWSTAT */
367
    case 8: /* FRQ_STATUS */
368
    case 9: /* FRQ_RAWSTAT */
369
    default:
370
        printf ("icp_pic_write: Bad register offset 0x%x\n", (int)offset);
371
        return;
372
    }
373
    icp_pic_update(s);
374
}
375

    
376
static const MemoryRegionOps icp_pic_ops = {
377
    .read = icp_pic_read,
378
    .write = icp_pic_write,
379
    .endianness = DEVICE_NATIVE_ENDIAN,
380
};
381

    
382
static int icp_pic_init(SysBusDevice *dev)
383
{
384
    icp_pic_state *s = FROM_SYSBUS(icp_pic_state, dev);
385

    
386
    qdev_init_gpio_in(&dev->qdev, icp_pic_set_irq, 32);
387
    sysbus_init_irq(dev, &s->parent_irq);
388
    sysbus_init_irq(dev, &s->parent_fiq);
389
    memory_region_init_io(&s->iomem, &icp_pic_ops, s, "icp-pic", 0x00800000);
390
    sysbus_init_mmio_region(dev, &s->iomem);
391
    return 0;
392
}
393

    
394
/* CP control registers.  */
395
static uint32_t icp_control_read(void *opaque, target_phys_addr_t offset)
396
{
397
    switch (offset >> 2) {
398
    case 0: /* CP_IDFIELD */
399
        return 0x41034003;
400
    case 1: /* CP_FLASHPROG */
401
        return 0;
402
    case 2: /* CP_INTREG */
403
        return 0;
404
    case 3: /* CP_DECODE */
405
        return 0x11;
406
    default:
407
        hw_error("icp_control_read: Bad offset %x\n", (int)offset);
408
        return 0;
409
    }
410
}
411

    
412
static void icp_control_write(void *opaque, target_phys_addr_t offset,
413
                          uint32_t value)
414
{
415
    switch (offset >> 2) {
416
    case 1: /* CP_FLASHPROG */
417
    case 2: /* CP_INTREG */
418
    case 3: /* CP_DECODE */
419
        /* Nothing interesting implemented yet.  */
420
        break;
421
    default:
422
        hw_error("icp_control_write: Bad offset %x\n", (int)offset);
423
    }
424
}
425
static CPUReadMemoryFunc * const icp_control_readfn[] = {
426
   icp_control_read,
427
   icp_control_read,
428
   icp_control_read
429
};
430

    
431
static CPUWriteMemoryFunc * const icp_control_writefn[] = {
432
   icp_control_write,
433
   icp_control_write,
434
   icp_control_write
435
};
436

    
437
static void icp_control_init(uint32_t base)
438
{
439
    int iomemtype;
440

    
441
    iomemtype = cpu_register_io_memory(icp_control_readfn,
442
                                       icp_control_writefn, NULL,
443
                                       DEVICE_NATIVE_ENDIAN);
444
    cpu_register_physical_memory(base, 0x00800000, iomemtype);
445
    /* ??? Save/restore.  */
446
}
447

    
448

    
449
/* Board init.  */
450

    
451
static struct arm_boot_info integrator_binfo = {
452
    .loader_start = 0x0,
453
    .board_id = 0x113,
454
};
455

    
456
static void integratorcp_init(ram_addr_t ram_size,
457
                     const char *boot_device,
458
                     const char *kernel_filename, const char *kernel_cmdline,
459
                     const char *initrd_filename, const char *cpu_model)
460
{
461
    CPUState *env;
462
    MemoryRegion *address_space_mem = get_system_memory();
463
    MemoryRegion *ram = g_new(MemoryRegion, 1);
464
    MemoryRegion *ram_alias = g_new(MemoryRegion, 1);
465
    qemu_irq pic[32];
466
    qemu_irq *cpu_pic;
467
    DeviceState *dev;
468
    int i;
469

    
470
    if (!cpu_model)
471
        cpu_model = "arm926";
472
    env = cpu_init(cpu_model);
473
    if (!env) {
474
        fprintf(stderr, "Unable to find CPU definition\n");
475
        exit(1);
476
    }
477
    memory_region_init_ram(ram, NULL, "integrator.ram", ram_size);
478
    /* ??? On a real system the first 1Mb is mapped as SSRAM or boot flash.  */
479
    /* ??? RAM should repeat to fill physical memory space.  */
480
    /* SDRAM at address zero*/
481
    memory_region_add_subregion(address_space_mem, 0, ram);
482
    /* And again at address 0x80000000 */
483
    memory_region_init_alias(ram_alias, "ram.alias", ram, 0, ram_size);
484
    memory_region_add_subregion(address_space_mem, 0x80000000, ram_alias);
485

    
486
    dev = qdev_create(NULL, "integrator_core");
487
    qdev_prop_set_uint32(dev, "memsz", ram_size >> 20);
488
    qdev_init_nofail(dev);
489
    sysbus_mmio_map((SysBusDevice *)dev, 0, 0x10000000);
490

    
491
    cpu_pic = arm_pic_init_cpu(env);
492
    dev = sysbus_create_varargs("integrator_pic", 0x14000000,
493
                                cpu_pic[ARM_PIC_CPU_IRQ],
494
                                cpu_pic[ARM_PIC_CPU_FIQ], NULL);
495
    for (i = 0; i < 32; i++) {
496
        pic[i] = qdev_get_gpio_in(dev, i);
497
    }
498
    sysbus_create_simple("integrator_pic", 0xca000000, pic[26]);
499
    sysbus_create_varargs("integrator_pit", 0x13000000,
500
                          pic[5], pic[6], pic[7], NULL);
501
    sysbus_create_simple("pl031", 0x15000000, pic[8]);
502
    sysbus_create_simple("pl011", 0x16000000, pic[1]);
503
    sysbus_create_simple("pl011", 0x17000000, pic[2]);
504
    icp_control_init(0xcb000000);
505
    sysbus_create_simple("pl050_keyboard", 0x18000000, pic[3]);
506
    sysbus_create_simple("pl050_mouse", 0x19000000, pic[4]);
507
    sysbus_create_varargs("pl181", 0x1c000000, pic[23], pic[24], NULL);
508
    if (nd_table[0].vlan)
509
        smc91c111_init(&nd_table[0], 0xc8000000, pic[27]);
510

    
511
    sysbus_create_simple("pl110", 0xc0000000, pic[22]);
512

    
513
    integrator_binfo.ram_size = ram_size;
514
    integrator_binfo.kernel_filename = kernel_filename;
515
    integrator_binfo.kernel_cmdline = kernel_cmdline;
516
    integrator_binfo.initrd_filename = initrd_filename;
517
    arm_load_kernel(env, &integrator_binfo);
518
}
519

    
520
static QEMUMachine integratorcp_machine = {
521
    .name = "integratorcp",
522
    .desc = "ARM Integrator/CP (ARM926EJ-S)",
523
    .init = integratorcp_init,
524
    .is_default = 1,
525
};
526

    
527
static void integratorcp_machine_init(void)
528
{
529
    qemu_register_machine(&integratorcp_machine);
530
}
531

    
532
machine_init(integratorcp_machine_init);
533

    
534
static SysBusDeviceInfo core_info = {
535
    .init = integratorcm_init,
536
    .qdev.name  = "integrator_core",
537
    .qdev.size  = sizeof(integratorcm_state),
538
    .qdev.props = (Property[]) {
539
        DEFINE_PROP_UINT32("memsz", integratorcm_state, memsz, 0),
540
        DEFINE_PROP_END_OF_LIST(),
541
    }
542
};
543

    
544
static void integratorcp_register_devices(void)
545
{
546
    sysbus_register_dev("integrator_pic", sizeof(icp_pic_state), icp_pic_init);
547
    sysbus_register_withprop(&core_info);
548
}
549

    
550
device_init(integratorcp_register_devices)