1
2
3
4
5
6
7
8
9
10
11
12
13
14#include "qemu/osdep.h"
15#include "qemu-common.h"
16#include "qemu/cutils.h"
17#include "qemu/error-report.h"
18#include "qapi/error.h"
19#include "hw/hw.h"
20#include "sysemu/blockdev.h"
21#include "hw/boards.h"
22#include "sysemu/kvm.h"
23#include "kvm_ppc.h"
24#include "sysemu/device_tree.h"
25#include "sysemu/block-backend.h"
26#include "hw/loader.h"
27#include "elf.h"
28#include "exec/address-spaces.h"
29#include "exec/memory.h"
30#include "hw/ppc/ppc440.h"
31#include "hw/ppc/ppc405.h"
32#include "hw/block/flash.h"
33#include "sysemu/sysemu.h"
34#include "sysemu/qtest.h"
35#include "hw/sysbus.h"
36#include "hw/char/serial.h"
37#include "hw/i2c/ppc4xx_i2c.h"
38#include "hw/i2c/smbus.h"
39#include "hw/usb/hcd-ehci.h"
40
41#define BINARY_DEVICE_TREE_FILE "canyonlands.dtb"
42#define UBOOT_FILENAME "u-boot-sam460-20100605.bin"
43
44
45
46
47
48#define FLASH_BASE 0xfff00000
49#define FLASH_BASE_H 0x4
50#define FLASH_SIZE (1 << 20)
51#define UBOOT_LOAD_BASE 0xfff80000
52#define UBOOT_SIZE 0x00080000
53#define UBOOT_ENTRY 0xfffffffc
54
55
56#define EPAPR_MAGIC (0x45504150)
57#define KERNEL_ADDR 0x1000000
58#define FDT_ADDR 0x1800000
59#define RAMDISK_ADDR 0x1900000
60
61
62
63
64
65
66
67
68
69
70#define CPU_FREQ 1150000000
71#define SDRAM_NR_BANKS 4
72
73
74static const unsigned int ppc460ex_sdram_bank_sizes[] = {
75 1024 << 20, 512 << 20, 256 << 20, 128 << 20, 64 << 20, 32 << 20, 0
76};
77
78struct boot_info {
79 uint32_t dt_base;
80 uint32_t dt_size;
81 uint32_t entry;
82};
83
84
85
86
87struct _eeprom24c0x_t {
88 uint8_t tick;
89 uint8_t address;
90 uint8_t command;
91 uint8_t ack;
92 uint8_t scl;
93 uint8_t sda;
94 uint8_t data;
95 uint8_t contents[256];
96};
97
98typedef struct _eeprom24c0x_t eeprom24c0x_t;
99
100static eeprom24c0x_t spd_eeprom = {
101 .contents = {
102 0x80, 0x08, 0xFF, 0x0D, 0x0A, 0xFF, 0x40, 0x00,
103 0x04, 0x75, 0x54, 0x00, 0x82, 0x08, 0x00, 0x01,
104 0x8F, 0x04, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00,
105 0x00, 0x00, 0x00, 0x14, 0x0F, 0x14, 0x2D, 0xFF,
106 0x15, 0x08, 0x15, 0x08, 0x00, 0x00, 0x00, 0x00,
107 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
108 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
109 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0xD0,
110 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
111 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
112 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
113 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
114 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
115 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
116 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
117 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0xF4,
118 },
119};
120
121static void generate_eeprom_spd(uint8_t *eeprom, ram_addr_t ram_size)
122{
123 enum { SDR = 0x4, DDR1 = 0x7, DDR2 = 0x8 } type;
124 uint8_t *spd = spd_eeprom.contents;
125 uint8_t nbanks = 0;
126 uint16_t density = 0;
127 int i;
128
129
130 ram_size >>= 20;
131
132 while ((ram_size >= 4) && (nbanks <= 2)) {
133 int sz_log2 = MIN(31 - clz32(ram_size), 14);
134 nbanks++;
135 density |= 1 << (sz_log2 - 2);
136 ram_size -= 1 << sz_log2;
137 }
138
139
140 if ((nbanks == 1) && (density > 1)) {
141 nbanks++;
142 density >>= 1;
143 }
144
145 if (density & 0xff00) {
146 density = (density & 0xe0) | ((density >> 8) & 0x1f);
147 type = DDR2;
148 } else if (!(density & 0x1f)) {
149 type = DDR2;
150 } else {
151 type = SDR;
152 }
153
154 if (ram_size) {
155 warn_report("SPD cannot represent final " RAM_ADDR_FMT "MB"
156 " of SDRAM", ram_size);
157 }
158
159
160 spd[2] = type;
161 spd[5] = nbanks;
162 spd[31] = density;
163
164
165 spd[9] = 0x10;
166 spd[18] = 0x20;
167 spd[23] = 0x10;
168 spd[25] = 0x10;
169
170
171 spd[63] = 0;
172 for (i = 0; i < 63; i++) {
173 spd[63] += spd[i];
174 }
175
176
177 memcpy(eeprom, spd, sizeof(spd_eeprom.contents));
178}
179
180static void generate_eeprom_serial(uint8_t *eeprom)
181{
182 int i, pos = 0;
183 uint8_t mac[6] = { 0x00 };
184 uint8_t sn[5] = { 0x01, 0x23, 0x45, 0x67, 0x89 };
185
186
187 eeprom[pos++] = 0x01;
188
189
190 eeprom[pos++] = 0x02;
191
192
193 eeprom[pos++] = 0x01;
194 eeprom[pos++] = 0x06;
195 memcpy(&eeprom[pos], mac, sizeof(mac));
196 pos += sizeof(mac);
197
198
199 eeprom[pos++] = 0x02;
200 eeprom[pos++] = 0x05;
201 memcpy(&eeprom[pos], sn, sizeof(sn));
202 pos += sizeof(sn);
203
204
205 eeprom[pos] = 0;
206 for (i = 0; i < pos; i++) {
207 eeprom[pos] += eeprom[i];
208 }
209}
210
211
212
213static int sam460ex_load_uboot(void)
214{
215 DriveInfo *dinfo;
216 BlockBackend *blk = NULL;
217 hwaddr base = FLASH_BASE | ((hwaddr)FLASH_BASE_H << 32);
218 long bios_size = FLASH_SIZE;
219 int fl_sectors;
220
221 dinfo = drive_get(IF_PFLASH, 0, 0);
222 if (dinfo) {
223 blk = blk_by_legacy_dinfo(dinfo);
224 bios_size = blk_getlength(blk);
225 }
226 fl_sectors = (bios_size + 65535) >> 16;
227
228 if (!pflash_cfi01_register(base, NULL, "sam460ex.flash", bios_size,
229 blk, (64 * 1024), fl_sectors,
230 1, 0x89, 0x18, 0x0000, 0x0, 1)) {
231 error_report("qemu: Error registering flash memory.");
232
233 exit(1);
234 }
235
236 if (!blk) {
237
238
239 base = UBOOT_LOAD_BASE | ((hwaddr)FLASH_BASE_H << 32);
240 rom_add_file_fixed(UBOOT_FILENAME, base, -1);
241 }
242
243 return 0;
244}
245
246static int sam460ex_load_device_tree(hwaddr addr,
247 uint32_t ramsize,
248 hwaddr initrd_base,
249 hwaddr initrd_size,
250 const char *kernel_cmdline)
251{
252 int ret = -1;
253 uint32_t mem_reg_property[] = { 0, 0, cpu_to_be32(ramsize) };
254 char *filename;
255 int fdt_size;
256 void *fdt;
257 uint32_t tb_freq = CPU_FREQ;
258 uint32_t clock_freq = CPU_FREQ;
259
260 filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, BINARY_DEVICE_TREE_FILE);
261 if (!filename) {
262 goto out;
263 }
264 fdt = load_device_tree(filename, &fdt_size);
265 g_free(filename);
266 if (fdt == NULL) {
267 goto out;
268 }
269
270
271
272 ret = qemu_fdt_setprop(fdt, "/memory", "reg", mem_reg_property,
273 sizeof(mem_reg_property));
274 if (ret < 0) {
275 error_report("couldn't set /memory/reg");
276 }
277
278
279 qemu_fdt_add_subnode(fdt, "/chosen");
280
281 ret = qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-start",
282 initrd_base);
283 if (ret < 0) {
284 error_report("couldn't set /chosen/linux,initrd-start");
285 }
286
287 ret = qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-end",
288 (initrd_base + initrd_size));
289 if (ret < 0) {
290 error_report("couldn't set /chosen/linux,initrd-end");
291 }
292
293 ret = qemu_fdt_setprop_string(fdt, "/chosen", "bootargs",
294 kernel_cmdline);
295 if (ret < 0) {
296 error_report("couldn't set /chosen/bootargs");
297 }
298
299
300
301
302 if (kvm_enabled()) {
303 tb_freq = kvmppc_get_tbfreq();
304 clock_freq = kvmppc_get_clockfreq();
305 }
306
307 qemu_fdt_setprop_cell(fdt, "/cpus/cpu@0", "clock-frequency",
308 clock_freq);
309 qemu_fdt_setprop_cell(fdt, "/cpus/cpu@0", "timebase-frequency",
310 tb_freq);
311
312 rom_add_blob_fixed(BINARY_DEVICE_TREE_FILE, fdt, fdt_size, addr);
313 g_free(fdt);
314 ret = fdt_size;
315
316out:
317
318 return ret;
319}
320
321
322static void mmubooke_create_initial_mapping_uboot(CPUPPCState *env)
323{
324 ppcemb_tlb_t *tlb = &env->tlb.tlbe[0];
325
326
327
328
329
330 tlb->attr = 0;
331 tlb->prot = PAGE_VALID | ((PAGE_READ | PAGE_WRITE | PAGE_EXEC) << 4);
332 tlb->size = 0x10000000;
333 tlb->EPN = 0xf0000000 & TARGET_PAGE_MASK;
334 tlb->RPN = (0xf0000000 & TARGET_PAGE_MASK) | 0x4;
335 tlb->PID = 0;
336}
337
338
339static void mmubooke_create_initial_mapping(CPUPPCState *env,
340 target_ulong va,
341 hwaddr pa)
342{
343 ppcemb_tlb_t *tlb = &env->tlb.tlbe[0];
344
345 tlb->attr = 0;
346 tlb->prot = PAGE_VALID | ((PAGE_READ | PAGE_WRITE | PAGE_EXEC) << 4);
347 tlb->size = 1 << 31;
348 tlb->EPN = va & TARGET_PAGE_MASK;
349 tlb->RPN = pa & TARGET_PAGE_MASK;
350 tlb->PID = 0;
351}
352
353static void main_cpu_reset(void *opaque)
354{
355 PowerPCCPU *cpu = opaque;
356 CPUPPCState *env = &cpu->env;
357 struct boot_info *bi = env->load_info;
358
359 cpu_reset(CPU(cpu));
360
361
362 if (bi->entry != UBOOT_ENTRY) {
363 env->gpr[1] = (16 << 20) - 8;
364 env->gpr[3] = FDT_ADDR;
365 env->nip = bi->entry;
366
367
368 mmubooke_create_initial_mapping(env, 0, 0);
369 env->gpr[6] = tswap32(EPAPR_MAGIC);
370 env->gpr[7] = (16 << 20) - 8;
371
372 } else {
373 env->nip = UBOOT_ENTRY;
374 mmubooke_create_initial_mapping_uboot(env);
375 }
376}
377
378static void sam460ex_init(MachineState *machine)
379{
380 MemoryRegion *address_space_mem = get_system_memory();
381 MemoryRegion *isa = g_new(MemoryRegion, 1);
382 MemoryRegion *ram_memories = g_new(MemoryRegion, SDRAM_NR_BANKS);
383 hwaddr ram_bases[SDRAM_NR_BANKS];
384 hwaddr ram_sizes[SDRAM_NR_BANKS];
385 MemoryRegion *l2cache_ram = g_new(MemoryRegion, 1);
386 qemu_irq *irqs, *uic[4];
387 PCIBus *pci_bus;
388 PowerPCCPU *cpu;
389 CPUPPCState *env;
390 PPC4xxI2CState *i2c[2];
391 hwaddr entry = UBOOT_ENTRY;
392 hwaddr loadaddr = 0;
393 target_long initrd_size = 0;
394 DeviceState *dev;
395 SysBusDevice *sbdev;
396 int success;
397 int i;
398 struct boot_info *boot_info;
399 const size_t smbus_eeprom_size = 8 * 256;
400 uint8_t *smbus_eeprom_buf = g_malloc0(smbus_eeprom_size);
401
402 cpu = POWERPC_CPU(cpu_create(machine->cpu_type));
403 env = &cpu->env;
404 if (env->mmu_model != POWERPC_MMU_BOOKE) {
405 error_report("Only MMU model BookE is supported by this machine.");
406 exit(1);
407 }
408
409#ifdef TARGET_PPCEMB
410 if (!qtest_enabled()) {
411 warn_report("qemu-system-ppcemb is deprecated, "
412 "please use qemu-system-ppc instead.");
413 }
414#endif
415
416 qemu_register_reset(main_cpu_reset, cpu);
417 boot_info = g_malloc0(sizeof(*boot_info));
418 env->load_info = boot_info;
419
420 ppc_booke_timers_init(cpu, CPU_FREQ, 0);
421 ppc_dcr_init(env, NULL, NULL);
422
423
424 ppc4xx_plb_init(env);
425
426
427 irqs = g_malloc0(sizeof(*irqs) * PPCUIC_OUTPUT_NB);
428 irqs[PPCUIC_OUTPUT_INT] = ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_INT];
429 irqs[PPCUIC_OUTPUT_CINT] = ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_CINT];
430 uic[0] = ppcuic_init(env, irqs, 0xc0, 0, 1);
431 uic[1] = ppcuic_init(env, &uic[0][30], 0xd0, 0, 1);
432 uic[2] = ppcuic_init(env, &uic[0][10], 0xe0, 0, 1);
433 uic[3] = ppcuic_init(env, &uic[0][16], 0xf0, 0, 1);
434
435
436 memset(ram_bases, 0, sizeof(ram_bases));
437 memset(ram_sizes, 0, sizeof(ram_sizes));
438
439
440 machine->ram_size = ppc4xx_sdram_adjust(machine->ram_size, 1,
441 ram_memories, ram_bases, ram_sizes,
442 ppc460ex_sdram_bank_sizes);
443
444
445 ppc440_sdram_init(env, SDRAM_NR_BANKS, ram_memories,
446 ram_bases, ram_sizes, 1);
447
448
449 for (i = 0; i < SDRAM_NR_BANKS; i++) {
450 generate_eeprom_spd(&smbus_eeprom_buf[i * 256], ram_sizes[i]);
451 }
452 generate_eeprom_serial(&smbus_eeprom_buf[4 * 256]);
453 generate_eeprom_serial(&smbus_eeprom_buf[6 * 256]);
454
455
456 dev = sysbus_create_simple(TYPE_PPC4xx_I2C, 0x4ef600700, uic[0][2]);
457 i2c[0] = PPC4xx_I2C(dev);
458 object_property_set_bool(OBJECT(dev), true, "realized", NULL);
459 smbus_eeprom_init(i2c[0]->bus, 8, smbus_eeprom_buf, smbus_eeprom_size);
460 g_free(smbus_eeprom_buf);
461
462 dev = sysbus_create_simple(TYPE_PPC4xx_I2C, 0x4ef600800, uic[0][3]);
463 i2c[1] = PPC4xx_I2C(dev);
464
465
466 ppc405_ebc_init(env);
467
468
469 ppc4xx_cpr_init(env);
470
471
472 ppc4xx_ahb_init(env);
473
474
475 ppc4xx_sdr_init(env);
476
477
478 ppc4xx_mal_init(env, 4, 16, &uic[2][3]);
479
480
481 ppc4xx_l2sram_init(env);
482
483 memory_region_init_ram(l2cache_ram, NULL, "ppc440.l2cache_ram", 256 << 10,
484 &error_abort);
485 memory_region_add_subregion(address_space_mem, 0x400000000LL, l2cache_ram);
486
487
488 sysbus_create_simple(TYPE_PPC4xx_EHCI, 0x4bffd0400, uic[2][29]);
489 dev = qdev_create(NULL, "sysbus-ohci");
490 qdev_prop_set_string(dev, "masterbus", "usb-bus.0");
491 qdev_prop_set_uint32(dev, "num-ports", 6);
492 qdev_init_nofail(dev);
493 sbdev = SYS_BUS_DEVICE(dev);
494 sysbus_mmio_map(sbdev, 0, 0x4bffd0000);
495 sysbus_connect_irq(sbdev, 0, uic[2][30]);
496 usb_create_simple(usb_bus_find(-1), "usb-kbd");
497 usb_create_simple(usb_bus_find(-1), "usb-mouse");
498
499
500 ppc460ex_pcie_init(env);
501
502 dev = sysbus_create_varargs("ppc440-pcix-host", 0xc0ec00000,
503 uic[1][0], uic[1][20], uic[1][21], uic[1][22],
504 NULL);
505 pci_bus = (PCIBus *)qdev_get_child_bus(dev, "pci.0");
506 if (!pci_bus) {
507 error_report("couldn't create PCI controller!");
508 exit(1);
509 }
510 memory_region_init_alias(isa, NULL, "isa_mmio", get_system_io(),
511 0, 0x10000);
512 memory_region_add_subregion(get_system_memory(), 0xc08000000, isa);
513
514
515 pci_create_simple(pci_bus, PCI_DEVFN(6, 0), "sm501");
516
517
518
519 if (defaults_enabled()) {
520 pci_create_simple(pci_bus, -1, "sii3112");
521 }
522
523
524
525 if (serial_hds[0] != NULL) {
526 serial_mm_init(address_space_mem, 0x4ef600300, 0, uic[1][1],
527 PPC_SERIAL_MM_BAUDBASE, serial_hds[0],
528 DEVICE_BIG_ENDIAN);
529 }
530 if (serial_hds[1] != NULL) {
531 serial_mm_init(address_space_mem, 0x4ef600400, 0, uic[0][1],
532 PPC_SERIAL_MM_BAUDBASE, serial_hds[1],
533 DEVICE_BIG_ENDIAN);
534 }
535
536
537 if (!machine->kernel_filename) {
538 success = sam460ex_load_uboot();
539 if (success < 0) {
540 error_report("qemu: could not load firmware");
541 exit(1);
542 }
543 }
544
545
546 if (machine->kernel_filename) {
547 success = load_uimage(machine->kernel_filename, &entry, &loadaddr,
548 NULL, NULL, NULL);
549 if (success < 0) {
550 uint64_t elf_entry, elf_lowaddr;
551
552 success = load_elf(machine->kernel_filename, NULL, NULL, &elf_entry,
553 &elf_lowaddr, NULL, 1, PPC_ELF_MACHINE, 0, 0);
554 entry = elf_entry;
555 loadaddr = elf_lowaddr;
556 }
557
558 if (success < 0) {
559 error_report("qemu: could not load kernel '%s'",
560 machine->kernel_filename);
561 exit(1);
562 }
563 }
564
565
566 if (machine->initrd_filename) {
567 initrd_size = load_image_targphys(machine->initrd_filename,
568 RAMDISK_ADDR,
569 machine->ram_size - RAMDISK_ADDR);
570 if (initrd_size < 0) {
571 error_report("qemu: could not load ram disk '%s' at %x",
572 machine->initrd_filename, RAMDISK_ADDR);
573 exit(1);
574 }
575 }
576
577
578 if (machine->kernel_filename) {
579 int dt_size;
580
581 dt_size = sam460ex_load_device_tree(FDT_ADDR, machine->ram_size,
582 RAMDISK_ADDR, initrd_size,
583 machine->kernel_cmdline);
584 if (dt_size < 0) {
585 error_report("couldn't load device tree");
586 exit(1);
587 }
588
589 boot_info->dt_base = FDT_ADDR;
590 boot_info->dt_size = dt_size;
591 }
592
593 boot_info->entry = entry;
594}
595
596static void sam460ex_machine_init(MachineClass *mc)
597{
598 mc->desc = "aCube Sam460ex";
599 mc->init = sam460ex_init;
600 mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("460exb");
601 mc->default_ram_size = 512 * M_BYTE;
602}
603
604DEFINE_MACHINE("sam460ex", sam460ex_machine_init)
605