xref: /openbmc/qemu/hw/ppc/ppc405_boards.c (revision 096b778f)
1 /*
2  * QEMU PowerPC 405 evaluation boards emulation
3  *
4  * Copyright (c) 2007 Jocelyn Mayer
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  */
24 
25 #include "qemu/osdep.h"
26 #include "qemu/units.h"
27 #include "qapi/error.h"
28 #include "qemu/datadir.h"
29 #include "cpu.h"
30 #include "hw/ppc/ppc.h"
31 #include "hw/qdev-properties.h"
32 #include "hw/sysbus.h"
33 #include "ppc405.h"
34 #include "hw/rtc/m48t59.h"
35 #include "hw/block/flash.h"
36 #include "sysemu/qtest.h"
37 #include "sysemu/reset.h"
38 #include "sysemu/block-backend.h"
39 #include "hw/boards.h"
40 #include "qemu/error-report.h"
41 #include "hw/loader.h"
42 #include "qemu/cutils.h"
43 #include "elf.h"
44 
45 #define BIOS_FILENAME "ppc405_rom.bin"
46 #define BIOS_SIZE (2 * MiB)
47 
48 #define KERNEL_LOAD_ADDR 0x01000000
49 #define INITRD_LOAD_ADDR 0x01800000
50 
51 #define USE_FLASH_BIOS
52 
53 /*****************************************************************************/
54 /* PPC405EP reference board (IBM) */
55 /* Standalone board with:
56  * - PowerPC 405EP CPU
57  * - SDRAM (0x00000000)
58  * - Flash (0xFFF80000)
59  * - SRAM  (0xFFF00000)
60  * - NVRAM (0xF0000000)
61  * - FPGA  (0xF0300000)
62  */
63 typedef struct ref405ep_fpga_t ref405ep_fpga_t;
64 struct ref405ep_fpga_t {
65     uint8_t reg0;
66     uint8_t reg1;
67 };
68 
69 static uint64_t ref405ep_fpga_readb(void *opaque, hwaddr addr, unsigned size)
70 {
71     ref405ep_fpga_t *fpga;
72     uint32_t ret;
73 
74     fpga = opaque;
75     switch (addr) {
76     case 0x0:
77         ret = fpga->reg0;
78         break;
79     case 0x1:
80         ret = fpga->reg1;
81         break;
82     default:
83         ret = 0;
84         break;
85     }
86 
87     return ret;
88 }
89 
90 static void ref405ep_fpga_writeb(void *opaque, hwaddr addr, uint64_t value,
91                                  unsigned size)
92 {
93     ref405ep_fpga_t *fpga;
94 
95     fpga = opaque;
96     switch (addr) {
97     case 0x0:
98         /* Read only */
99         break;
100     case 0x1:
101         fpga->reg1 = value;
102         break;
103     default:
104         break;
105     }
106 }
107 
108 static const MemoryRegionOps ref405ep_fpga_ops = {
109     .read = ref405ep_fpga_readb,
110     .write = ref405ep_fpga_writeb,
111     .impl.min_access_size = 1,
112     .impl.max_access_size = 1,
113     .valid.min_access_size = 1,
114     .valid.max_access_size = 4,
115     .endianness = DEVICE_BIG_ENDIAN,
116 };
117 
118 static void ref405ep_fpga_reset (void *opaque)
119 {
120     ref405ep_fpga_t *fpga;
121 
122     fpga = opaque;
123     fpga->reg0 = 0x00;
124     fpga->reg1 = 0x0F;
125 }
126 
127 static void ref405ep_fpga_init(MemoryRegion *sysmem, uint32_t base)
128 {
129     ref405ep_fpga_t *fpga;
130     MemoryRegion *fpga_memory = g_new(MemoryRegion, 1);
131 
132     fpga = g_new0(ref405ep_fpga_t, 1);
133     memory_region_init_io(fpga_memory, NULL, &ref405ep_fpga_ops, fpga,
134                           "fpga", 0x00000100);
135     memory_region_add_subregion(sysmem, base, fpga_memory);
136     qemu_register_reset(&ref405ep_fpga_reset, fpga);
137 }
138 
139 /*
140  * CPU reset handler when booting directly from a loaded kernel
141  */
142 static struct boot_info {
143     uint32_t entry;
144     uint32_t bdloc;
145     uint32_t initrd_base;
146     uint32_t initrd_size;
147     uint32_t cmdline_base;
148     uint32_t cmdline_size;
149 } boot_info;
150 
151 static void main_cpu_reset(void *opaque)
152 {
153     PowerPCCPU *cpu = opaque;
154     CPUPPCState *env = &cpu->env;
155     struct boot_info *bi = env->load_info;
156 
157     cpu_reset(CPU(cpu));
158 
159     /* stack: top of sram */
160     env->gpr[1] = PPC405EP_SRAM_BASE + PPC405EP_SRAM_SIZE - 8;
161 
162     /* Tune our boot state */
163     env->gpr[3] = bi->bdloc;
164     env->gpr[4] = bi->initrd_base;
165     env->gpr[5] = bi->initrd_base + bi->initrd_size;
166     env->gpr[6] = bi->cmdline_base;
167     env->gpr[7] = bi->cmdline_size;
168 
169     env->nip = bi->entry;
170 }
171 
172 static void boot_from_kernel(MachineState *machine, PowerPCCPU *cpu)
173 {
174     CPUPPCState *env = &cpu->env;
175     hwaddr boot_entry;
176     hwaddr kernel_base;
177     int kernel_size;
178     hwaddr initrd_base;
179     int initrd_size;
180     ram_addr_t bdloc;
181     int len;
182 
183     bdloc = ppc405_set_bootinfo(env, machine->ram_size);
184     boot_info.bdloc = bdloc;
185 
186     kernel_size = load_elf(machine->kernel_filename, NULL, NULL, NULL,
187                            &boot_entry, &kernel_base, NULL, NULL,
188                            1, PPC_ELF_MACHINE, 0, 0);
189     if (kernel_size < 0) {
190         error_report("Could not load kernel '%s' : %s",
191                      machine->kernel_filename, load_elf_strerror(kernel_size));
192         exit(1);
193     }
194     boot_info.entry = boot_entry;
195 
196     /* load initrd */
197     if (machine->initrd_filename) {
198         initrd_base = INITRD_LOAD_ADDR;
199         initrd_size = load_image_targphys(machine->initrd_filename, initrd_base,
200                                           machine->ram_size - initrd_base);
201         if (initrd_size < 0) {
202             error_report("could not load initial ram disk '%s'",
203                          machine->initrd_filename);
204             exit(1);
205         }
206 
207         boot_info.initrd_base = initrd_base;
208         boot_info.initrd_size = initrd_size;
209     }
210 
211     if (machine->kernel_cmdline) {
212         len = strlen(machine->kernel_cmdline);
213         bdloc -= ((len + 255) & ~255);
214         cpu_physical_memory_write(bdloc, machine->kernel_cmdline, len + 1);
215         boot_info.cmdline_base = bdloc;
216         boot_info.cmdline_size = bdloc + len;
217     }
218 
219     /* Install our custom reset handler to start from Linux */
220     qemu_register_reset(main_cpu_reset, cpu);
221     env->load_info = &boot_info;
222 }
223 
224 static void ref405ep_init(MachineState *machine)
225 {
226     MachineClass *mc = MACHINE_GET_CLASS(machine);
227     const char *kernel_filename = machine->kernel_filename;
228     PowerPCCPU *cpu;
229     DeviceState *dev;
230     SysBusDevice *s;
231     MemoryRegion *sram = g_new(MemoryRegion, 1);
232     MemoryRegion *ram_memories = g_new(MemoryRegion, 2);
233     hwaddr ram_bases[2], ram_sizes[2];
234     MemoryRegion *sysmem = get_system_memory();
235     DeviceState *uicdev;
236 
237     if (machine->ram_size != mc->default_ram_size) {
238         char *sz = size_to_str(mc->default_ram_size);
239         error_report("Invalid RAM size, should be %s", sz);
240         g_free(sz);
241         exit(EXIT_FAILURE);
242     }
243 
244     /* XXX: fix this */
245     memory_region_init_alias(&ram_memories[0], NULL, "ef405ep.ram.alias",
246                              machine->ram, 0, machine->ram_size);
247     ram_bases[0] = 0;
248     ram_sizes[0] = machine->ram_size;
249     memory_region_init(&ram_memories[1], NULL, "ef405ep.ram1", 0);
250     ram_bases[1] = 0x00000000;
251     ram_sizes[1] = 0x00000000;
252 
253     cpu = ppc405ep_init(sysmem, ram_memories, ram_bases, ram_sizes,
254                         33333333, &uicdev, kernel_filename == NULL ? 0 : 1);
255 
256     /* allocate SRAM */
257     memory_region_init_ram(sram, NULL, "ef405ep.sram", PPC405EP_SRAM_SIZE,
258                            &error_fatal);
259     memory_region_add_subregion(sysmem, PPC405EP_SRAM_BASE, sram);
260 
261     /* allocate and load BIOS */
262     if (machine->firmware) {
263         MemoryRegion *bios = g_new(MemoryRegion, 1);
264         g_autofree char *filename;
265         long bios_size;
266 
267         memory_region_init_rom(bios, NULL, "ef405ep.bios", BIOS_SIZE,
268                                &error_fatal);
269 
270         filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, machine->firmware);
271         if (!filename) {
272             error_report("Could not find firmware '%s'", machine->firmware);
273             exit(1);
274         }
275 
276         bios_size = load_image_size(filename,
277                                     memory_region_get_ram_ptr(bios),
278                                     BIOS_SIZE);
279         if (bios_size < 0) {
280             error_report("Could not load PowerPC BIOS '%s'", machine->firmware);
281             exit(1);
282         }
283 
284         bios_size = (bios_size + 0xfff) & ~0xfff;
285         memory_region_add_subregion(sysmem, (uint32_t)(-bios_size), bios);
286     }
287 
288     /* Register FPGA */
289     ref405ep_fpga_init(sysmem, PPC405EP_FPGA_BASE);
290     /* Register NVRAM */
291     dev = qdev_new("sysbus-m48t08");
292     qdev_prop_set_int32(dev, "base-year", 1968);
293     s = SYS_BUS_DEVICE(dev);
294     sysbus_realize_and_unref(s, &error_fatal);
295     sysbus_mmio_map(s, 0, PPC405EP_NVRAM_BASE);
296 
297     /* Load kernel and initrd using U-Boot images */
298     if (kernel_filename && machine->firmware) {
299         target_ulong kernel_base, initrd_base;
300         long kernel_size, initrd_size;
301 
302         kernel_base = KERNEL_LOAD_ADDR;
303         kernel_size = load_image_targphys(kernel_filename, kernel_base,
304                                           machine->ram_size - kernel_base);
305         if (kernel_size < 0) {
306             error_report("could not load kernel '%s'", kernel_filename);
307             exit(1);
308         }
309 
310         /* load initrd */
311         if (machine->initrd_filename) {
312             initrd_base = INITRD_LOAD_ADDR;
313             initrd_size = load_image_targphys(machine->initrd_filename,
314                                               initrd_base,
315                                               machine->ram_size - initrd_base);
316             if (initrd_size < 0) {
317                 error_report("could not load initial ram disk '%s'",
318                              machine->initrd_filename);
319                 exit(1);
320             }
321         }
322 
323     /* Load ELF kernel and rootfs.cpio */
324     } else if (kernel_filename && !machine->firmware) {
325         boot_from_kernel(machine, cpu);
326     }
327 }
328 
329 static void ref405ep_class_init(ObjectClass *oc, void *data)
330 {
331     MachineClass *mc = MACHINE_CLASS(oc);
332 
333     mc->desc = "ref405ep";
334     mc->init = ref405ep_init;
335     mc->default_ram_size = 0x08000000;
336     mc->default_ram_id = "ef405ep.ram";
337 }
338 
339 static const TypeInfo ref405ep_type = {
340     .name = MACHINE_TYPE_NAME("ref405ep"),
341     .parent = TYPE_MACHINE,
342     .class_init = ref405ep_class_init,
343 };
344 
345 /*****************************************************************************/
346 /* AMCC Taihu evaluation board */
347 /* - PowerPC 405EP processor
348  * - SDRAM               128 MB at 0x00000000
349  * - Boot flash          2 MB   at 0xFFE00000
350  * - Application flash   32 MB  at 0xFC000000
351  * - 2 serial ports
352  * - 2 ethernet PHY
353  * - 1 USB 1.1 device    0x50000000
354  * - 1 LCD display       0x50100000
355  * - 1 CPLD              0x50100000
356  * - 1 I2C EEPROM
357  * - 1 I2C thermal sensor
358  * - a set of LEDs
359  * - bit-bang SPI port using GPIOs
360  * - 1 EBC interface connector 0 0x50200000
361  * - 1 cardbus controller + expansion slot.
362  * - 1 PCI expansion slot.
363  */
364 typedef struct taihu_cpld_t taihu_cpld_t;
365 struct taihu_cpld_t {
366     uint8_t reg0;
367     uint8_t reg1;
368 };
369 
370 static uint64_t taihu_cpld_read(void *opaque, hwaddr addr, unsigned size)
371 {
372     taihu_cpld_t *cpld;
373     uint32_t ret;
374 
375     cpld = opaque;
376     switch (addr) {
377     case 0x0:
378         ret = cpld->reg0;
379         break;
380     case 0x1:
381         ret = cpld->reg1;
382         break;
383     default:
384         ret = 0;
385         break;
386     }
387 
388     return ret;
389 }
390 
391 static void taihu_cpld_write(void *opaque, hwaddr addr,
392                              uint64_t value, unsigned size)
393 {
394     taihu_cpld_t *cpld;
395 
396     cpld = opaque;
397     switch (addr) {
398     case 0x0:
399         /* Read only */
400         break;
401     case 0x1:
402         cpld->reg1 = value;
403         break;
404     default:
405         break;
406     }
407 }
408 
409 static const MemoryRegionOps taihu_cpld_ops = {
410     .read = taihu_cpld_read,
411     .write = taihu_cpld_write,
412     .impl = {
413         .min_access_size = 1,
414         .max_access_size = 1,
415     },
416     .endianness = DEVICE_NATIVE_ENDIAN,
417 };
418 
419 static void taihu_cpld_reset (void *opaque)
420 {
421     taihu_cpld_t *cpld;
422 
423     cpld = opaque;
424     cpld->reg0 = 0x01;
425     cpld->reg1 = 0x80;
426 }
427 
428 static void taihu_cpld_init(MemoryRegion *sysmem, uint32_t base)
429 {
430     taihu_cpld_t *cpld;
431     MemoryRegion *cpld_memory = g_new(MemoryRegion, 1);
432 
433     cpld = g_new0(taihu_cpld_t, 1);
434     memory_region_init_io(cpld_memory, NULL, &taihu_cpld_ops, cpld, "cpld", 0x100);
435     memory_region_add_subregion(sysmem, base, cpld_memory);
436     qemu_register_reset(&taihu_cpld_reset, cpld);
437 }
438 
439 static void taihu_405ep_init(MachineState *machine)
440 {
441     MachineClass *mc = MACHINE_GET_CLASS(machine);
442     const char *bios_name = machine->firmware ?: BIOS_FILENAME;
443     const char *kernel_filename = machine->kernel_filename;
444     const char *initrd_filename = machine->initrd_filename;
445     char *filename;
446     MemoryRegion *sysmem = get_system_memory();
447     MemoryRegion *bios;
448     MemoryRegion *ram_memories = g_new(MemoryRegion, 2);
449     hwaddr ram_bases[2], ram_sizes[2];
450     long bios_size;
451     target_ulong kernel_base, initrd_base;
452     long kernel_size, initrd_size;
453     int linux_boot;
454     int fl_idx;
455     DriveInfo *dinfo;
456     DeviceState *uicdev;
457 
458     if (machine->ram_size != mc->default_ram_size) {
459         char *sz = size_to_str(mc->default_ram_size);
460         error_report("Invalid RAM size, should be %s", sz);
461         g_free(sz);
462         exit(EXIT_FAILURE);
463     }
464 
465     ram_bases[0] = 0;
466     ram_sizes[0] = 0x04000000;
467     memory_region_init_alias(&ram_memories[0], NULL,
468                              "taihu_405ep.ram-0", machine->ram, ram_bases[0],
469                              ram_sizes[0]);
470     ram_bases[1] = 0x04000000;
471     ram_sizes[1] = 0x04000000;
472     memory_region_init_alias(&ram_memories[1], NULL,
473                              "taihu_405ep.ram-1", machine->ram, ram_bases[1],
474                              ram_sizes[1]);
475     ppc405ep_init(sysmem, ram_memories, ram_bases, ram_sizes,
476                   33333333, &uicdev, kernel_filename == NULL ? 0 : 1);
477     /* allocate and load BIOS */
478     fl_idx = 0;
479 #if defined(USE_FLASH_BIOS)
480     dinfo = drive_get(IF_PFLASH, 0, fl_idx);
481     if (dinfo) {
482         bios_size = 2 * MiB;
483         pflash_cfi02_register(0xFFE00000,
484                               "taihu_405ep.bios", bios_size,
485                               blk_by_legacy_dinfo(dinfo),
486                               64 * KiB, 1,
487                               4, 0x0001, 0x22DA, 0x0000, 0x0000, 0x555, 0x2AA,
488                               1);
489         fl_idx++;
490     } else
491 #endif
492     {
493         bios = g_new(MemoryRegion, 1);
494         memory_region_init_rom(bios, NULL, "taihu_405ep.bios", BIOS_SIZE,
495                                &error_fatal);
496         filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
497         if (filename) {
498             bios_size = load_image_size(filename,
499                                         memory_region_get_ram_ptr(bios),
500                                         BIOS_SIZE);
501             g_free(filename);
502             if (bios_size < 0) {
503                 error_report("Could not load PowerPC BIOS '%s'", bios_name);
504                 exit(1);
505             }
506             bios_size = (bios_size + 0xfff) & ~0xfff;
507             memory_region_add_subregion(sysmem, (uint32_t)(-bios_size), bios);
508         } else if (!qtest_enabled()) {
509             error_report("Could not load PowerPC BIOS '%s'", bios_name);
510             exit(1);
511         }
512     }
513     /* Register Linux flash */
514     dinfo = drive_get(IF_PFLASH, 0, fl_idx);
515     if (dinfo) {
516         bios_size = 32 * MiB;
517         pflash_cfi02_register(0xfc000000, "taihu_405ep.flash", bios_size,
518                               blk_by_legacy_dinfo(dinfo),
519                               64 * KiB, 1,
520                               4, 0x0001, 0x22DA, 0x0000, 0x0000, 0x555, 0x2AA,
521                               1);
522         fl_idx++;
523     }
524     /* Register CLPD & LCD display */
525     taihu_cpld_init(sysmem, 0x50100000);
526     /* Load kernel */
527     linux_boot = (kernel_filename != NULL);
528     if (linux_boot) {
529         kernel_base = KERNEL_LOAD_ADDR;
530         /* now we can load the kernel */
531         kernel_size = load_image_targphys(kernel_filename, kernel_base,
532                                           machine->ram_size - kernel_base);
533         if (kernel_size < 0) {
534             error_report("could not load kernel '%s'", kernel_filename);
535             exit(1);
536         }
537         /* load initrd */
538         if (initrd_filename) {
539             initrd_base = INITRD_LOAD_ADDR;
540             initrd_size = load_image_targphys(initrd_filename, initrd_base,
541                                               machine->ram_size - initrd_base);
542             if (initrd_size < 0) {
543                 error_report("could not load initial ram disk '%s'",
544                              initrd_filename);
545                 exit(1);
546             }
547         } else {
548             initrd_base = 0;
549             initrd_size = 0;
550         }
551     } else {
552         kernel_base = 0;
553         kernel_size = 0;
554         initrd_base = 0;
555         initrd_size = 0;
556     }
557 }
558 
559 static void taihu_class_init(ObjectClass *oc, void *data)
560 {
561     MachineClass *mc = MACHINE_CLASS(oc);
562 
563     mc->desc = "taihu";
564     mc->init = taihu_405ep_init;
565     mc->default_ram_size = 0x08000000;
566     mc->default_ram_id = "taihu_405ep.ram";
567     mc->deprecation_reason = "incomplete, use 'ref405ep' instead";
568 }
569 
570 static const TypeInfo taihu_type = {
571     .name = MACHINE_TYPE_NAME("taihu"),
572     .parent = TYPE_MACHINE,
573     .class_init = taihu_class_init,
574 };
575 
576 static void ppc405_machine_init(void)
577 {
578     type_register_static(&ref405ep_type);
579     type_register_static(&taihu_type);
580 }
581 
582 type_init(ppc405_machine_init)
583