xref: /openbmc/qemu/hw/ppc/ppc405_boards.c (revision 64552b6b)
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-common.h"
29 #include "cpu.h"
30 #include "hw/hw.h"
31 #include "hw/ppc/ppc.h"
32 #include "ppc405.h"
33 #include "hw/timer/m48t59.h"
34 #include "hw/block/flash.h"
35 #include "sysemu/sysemu.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/log.h"
41 #include "qemu/error-report.h"
42 #include "hw/loader.h"
43 #include "exec/address-spaces.h"
44 
45 #define BIOS_FILENAME "ppc405_rom.bin"
46 #define BIOS_SIZE (2 * MiB)
47 
48 #define KERNEL_LOAD_ADDR 0x00000000
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_malloc0(sizeof(ref405ep_fpga_t));
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 static void ref405ep_init(MachineState *machine)
140 {
141     ram_addr_t ram_size = machine->ram_size;
142     const char *kernel_filename = machine->kernel_filename;
143     const char *kernel_cmdline = machine->kernel_cmdline;
144     const char *initrd_filename = machine->initrd_filename;
145     char *filename;
146     ppc4xx_bd_info_t bd;
147     CPUPPCState *env;
148     qemu_irq *pic;
149     MemoryRegion *bios;
150     MemoryRegion *sram = g_new(MemoryRegion, 1);
151     ram_addr_t bdloc;
152     MemoryRegion *ram_memories = g_new(MemoryRegion, 2);
153     hwaddr ram_bases[2], ram_sizes[2];
154     target_ulong sram_size;
155     long bios_size;
156     //int phy_addr = 0;
157     //static int phy_addr = 1;
158     target_ulong kernel_base, initrd_base;
159     long kernel_size, initrd_size;
160     int linux_boot;
161     int len;
162     DriveInfo *dinfo;
163     MemoryRegion *sysmem = get_system_memory();
164 
165     /* XXX: fix this */
166     memory_region_allocate_system_memory(&ram_memories[0], NULL, "ef405ep.ram",
167                                          0x08000000);
168     ram_bases[0] = 0;
169     ram_sizes[0] = 0x08000000;
170     memory_region_init(&ram_memories[1], NULL, "ef405ep.ram1", 0);
171     ram_bases[1] = 0x00000000;
172     ram_sizes[1] = 0x00000000;
173     ram_size = 128 * MiB;
174     env = ppc405ep_init(sysmem, ram_memories, ram_bases, ram_sizes,
175                         33333333, &pic, kernel_filename == NULL ? 0 : 1);
176     /* allocate SRAM */
177     sram_size = 512 * KiB;
178     memory_region_init_ram(sram, NULL, "ef405ep.sram", sram_size,
179                            &error_fatal);
180     memory_region_add_subregion(sysmem, 0xFFF00000, sram);
181     /* allocate and load BIOS */
182 #ifdef USE_FLASH_BIOS
183     dinfo = drive_get(IF_PFLASH, 0, 0);
184     if (dinfo) {
185         bios_size = 8 * MiB;
186         pflash_cfi02_register((uint32_t)(-bios_size),
187                               "ef405ep.bios", bios_size,
188                               dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
189                               64 * KiB, 1,
190                               2, 0x0001, 0x22DA, 0x0000, 0x0000, 0x555, 0x2AA,
191                               1);
192     } else
193 #endif
194     {
195         bios = g_new(MemoryRegion, 1);
196         memory_region_init_ram(bios, NULL, "ef405ep.bios", BIOS_SIZE,
197                                &error_fatal);
198 
199         if (bios_name == NULL)
200             bios_name = BIOS_FILENAME;
201         filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
202         if (filename) {
203             bios_size = load_image_size(filename,
204                                         memory_region_get_ram_ptr(bios),
205                                         BIOS_SIZE);
206             g_free(filename);
207             if (bios_size < 0) {
208                 error_report("Could not load PowerPC BIOS '%s'", bios_name);
209                 exit(1);
210             }
211             bios_size = (bios_size + 0xfff) & ~0xfff;
212             memory_region_add_subregion(sysmem, (uint32_t)(-bios_size), bios);
213         } else if (!qtest_enabled() || kernel_filename != NULL) {
214             error_report("Could not load PowerPC BIOS '%s'", bios_name);
215             exit(1);
216         } else {
217             /* Avoid an uninitialized variable warning */
218             bios_size = -1;
219         }
220         memory_region_set_readonly(bios, true);
221     }
222     /* Register FPGA */
223     ref405ep_fpga_init(sysmem, 0xF0300000);
224     /* Register NVRAM */
225     m48t59_init(NULL, 0xF0000000, 0, 8192, 1968, 8);
226     /* Load kernel */
227     linux_boot = (kernel_filename != NULL);
228     if (linux_boot) {
229         memset(&bd, 0, sizeof(bd));
230         bd.bi_memstart = 0x00000000;
231         bd.bi_memsize = ram_size;
232         bd.bi_flashstart = -bios_size;
233         bd.bi_flashsize = -bios_size;
234         bd.bi_flashoffset = 0;
235         bd.bi_sramstart = 0xFFF00000;
236         bd.bi_sramsize = sram_size;
237         bd.bi_bootflags = 0;
238         bd.bi_intfreq = 133333333;
239         bd.bi_busfreq = 33333333;
240         bd.bi_baudrate = 115200;
241         bd.bi_s_version[0] = 'Q';
242         bd.bi_s_version[1] = 'M';
243         bd.bi_s_version[2] = 'U';
244         bd.bi_s_version[3] = '\0';
245         bd.bi_r_version[0] = 'Q';
246         bd.bi_r_version[1] = 'E';
247         bd.bi_r_version[2] = 'M';
248         bd.bi_r_version[3] = 'U';
249         bd.bi_r_version[4] = '\0';
250         bd.bi_procfreq = 133333333;
251         bd.bi_plb_busfreq = 33333333;
252         bd.bi_pci_busfreq = 33333333;
253         bd.bi_opbfreq = 33333333;
254         bdloc = ppc405_set_bootinfo(env, &bd, 0x00000001);
255         env->gpr[3] = bdloc;
256         kernel_base = KERNEL_LOAD_ADDR;
257         /* now we can load the kernel */
258         kernel_size = load_image_targphys(kernel_filename, kernel_base,
259                                           ram_size - kernel_base);
260         if (kernel_size < 0) {
261             error_report("could not load kernel '%s'", kernel_filename);
262             exit(1);
263         }
264         printf("Load kernel size %ld at " TARGET_FMT_lx,
265                kernel_size, kernel_base);
266         /* load initrd */
267         if (initrd_filename) {
268             initrd_base = INITRD_LOAD_ADDR;
269             initrd_size = load_image_targphys(initrd_filename, initrd_base,
270                                               ram_size - initrd_base);
271             if (initrd_size < 0) {
272                 error_report("could not load initial ram disk '%s'",
273                              initrd_filename);
274                 exit(1);
275             }
276         } else {
277             initrd_base = 0;
278             initrd_size = 0;
279         }
280         env->gpr[4] = initrd_base;
281         env->gpr[5] = initrd_size;
282         if (kernel_cmdline != NULL) {
283             len = strlen(kernel_cmdline);
284             bdloc -= ((len + 255) & ~255);
285             cpu_physical_memory_write(bdloc, kernel_cmdline, len + 1);
286             env->gpr[6] = bdloc;
287             env->gpr[7] = bdloc + len;
288         } else {
289             env->gpr[6] = 0;
290             env->gpr[7] = 0;
291         }
292         env->nip = KERNEL_LOAD_ADDR;
293     } else {
294         kernel_base = 0;
295         kernel_size = 0;
296         initrd_base = 0;
297         initrd_size = 0;
298         bdloc = 0;
299     }
300 }
301 
302 static void ref405ep_class_init(ObjectClass *oc, void *data)
303 {
304     MachineClass *mc = MACHINE_CLASS(oc);
305 
306     mc->desc = "ref405ep";
307     mc->init = ref405ep_init;
308 }
309 
310 static const TypeInfo ref405ep_type = {
311     .name = MACHINE_TYPE_NAME("ref405ep"),
312     .parent = TYPE_MACHINE,
313     .class_init = ref405ep_class_init,
314 };
315 
316 /*****************************************************************************/
317 /* AMCC Taihu evaluation board */
318 /* - PowerPC 405EP processor
319  * - SDRAM               128 MB at 0x00000000
320  * - Boot flash          2 MB   at 0xFFE00000
321  * - Application flash   32 MB  at 0xFC000000
322  * - 2 serial ports
323  * - 2 ethernet PHY
324  * - 1 USB 1.1 device    0x50000000
325  * - 1 LCD display       0x50100000
326  * - 1 CPLD              0x50100000
327  * - 1 I2C EEPROM
328  * - 1 I2C thermal sensor
329  * - a set of LEDs
330  * - bit-bang SPI port using GPIOs
331  * - 1 EBC interface connector 0 0x50200000
332  * - 1 cardbus controller + expansion slot.
333  * - 1 PCI expansion slot.
334  */
335 typedef struct taihu_cpld_t taihu_cpld_t;
336 struct taihu_cpld_t {
337     uint8_t reg0;
338     uint8_t reg1;
339 };
340 
341 static uint64_t taihu_cpld_read(void *opaque, hwaddr addr, unsigned size)
342 {
343     taihu_cpld_t *cpld;
344     uint32_t ret;
345 
346     cpld = opaque;
347     switch (addr) {
348     case 0x0:
349         ret = cpld->reg0;
350         break;
351     case 0x1:
352         ret = cpld->reg1;
353         break;
354     default:
355         ret = 0;
356         break;
357     }
358 
359     return ret;
360 }
361 
362 static void taihu_cpld_write(void *opaque, hwaddr addr,
363                              uint64_t value, unsigned size)
364 {
365     taihu_cpld_t *cpld;
366 
367     cpld = opaque;
368     switch (addr) {
369     case 0x0:
370         /* Read only */
371         break;
372     case 0x1:
373         cpld->reg1 = value;
374         break;
375     default:
376         break;
377     }
378 }
379 
380 static const MemoryRegionOps taihu_cpld_ops = {
381     .read = taihu_cpld_read,
382     .write = taihu_cpld_write,
383     .impl = {
384         .min_access_size = 1,
385         .max_access_size = 1,
386     },
387     .endianness = DEVICE_NATIVE_ENDIAN,
388 };
389 
390 static void taihu_cpld_reset (void *opaque)
391 {
392     taihu_cpld_t *cpld;
393 
394     cpld = opaque;
395     cpld->reg0 = 0x01;
396     cpld->reg1 = 0x80;
397 }
398 
399 static void taihu_cpld_init(MemoryRegion *sysmem, uint32_t base)
400 {
401     taihu_cpld_t *cpld;
402     MemoryRegion *cpld_memory = g_new(MemoryRegion, 1);
403 
404     cpld = g_malloc0(sizeof(taihu_cpld_t));
405     memory_region_init_io(cpld_memory, NULL, &taihu_cpld_ops, cpld, "cpld", 0x100);
406     memory_region_add_subregion(sysmem, base, cpld_memory);
407     qemu_register_reset(&taihu_cpld_reset, cpld);
408 }
409 
410 static void taihu_405ep_init(MachineState *machine)
411 {
412     ram_addr_t ram_size = machine->ram_size;
413     const char *kernel_filename = machine->kernel_filename;
414     const char *initrd_filename = machine->initrd_filename;
415     char *filename;
416     qemu_irq *pic;
417     MemoryRegion *sysmem = get_system_memory();
418     MemoryRegion *bios;
419     MemoryRegion *ram_memories = g_new(MemoryRegion, 2);
420     MemoryRegion *ram = g_malloc0(sizeof(*ram));
421     hwaddr ram_bases[2], ram_sizes[2];
422     long bios_size;
423     target_ulong kernel_base, initrd_base;
424     long kernel_size, initrd_size;
425     int linux_boot;
426     int fl_idx;
427     DriveInfo *dinfo;
428 
429     /* RAM is soldered to the board so the size cannot be changed */
430     ram_size = 0x08000000;
431     memory_region_allocate_system_memory(ram, NULL, "taihu_405ep.ram",
432                                          ram_size);
433 
434     ram_bases[0] = 0;
435     ram_sizes[0] = 0x04000000;
436     memory_region_init_alias(&ram_memories[0], NULL,
437                              "taihu_405ep.ram-0", ram, ram_bases[0],
438                              ram_sizes[0]);
439     ram_bases[1] = 0x04000000;
440     ram_sizes[1] = 0x04000000;
441     memory_region_init_alias(&ram_memories[1], NULL,
442                              "taihu_405ep.ram-1", ram, ram_bases[1],
443                              ram_sizes[1]);
444     ppc405ep_init(sysmem, ram_memories, ram_bases, ram_sizes,
445                   33333333, &pic, kernel_filename == NULL ? 0 : 1);
446     /* allocate and load BIOS */
447     fl_idx = 0;
448 #if defined(USE_FLASH_BIOS)
449     dinfo = drive_get(IF_PFLASH, 0, fl_idx);
450     if (dinfo) {
451         bios_size = 2 * MiB;
452         pflash_cfi02_register(0xFFE00000,
453                               "taihu_405ep.bios", bios_size,
454                               dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
455                               64 * KiB, 1,
456                               4, 0x0001, 0x22DA, 0x0000, 0x0000, 0x555, 0x2AA,
457                               1);
458         fl_idx++;
459     } else
460 #endif
461     {
462         if (bios_name == NULL)
463             bios_name = BIOS_FILENAME;
464         bios = g_new(MemoryRegion, 1);
465         memory_region_init_ram(bios, NULL, "taihu_405ep.bios", BIOS_SIZE,
466                                &error_fatal);
467         filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
468         if (filename) {
469             bios_size = load_image_size(filename,
470                                         memory_region_get_ram_ptr(bios),
471                                         BIOS_SIZE);
472             g_free(filename);
473             if (bios_size < 0) {
474                 error_report("Could not load PowerPC BIOS '%s'", bios_name);
475                 exit(1);
476             }
477             bios_size = (bios_size + 0xfff) & ~0xfff;
478             memory_region_add_subregion(sysmem, (uint32_t)(-bios_size), bios);
479         } else if (!qtest_enabled()) {
480             error_report("Could not load PowerPC BIOS '%s'", bios_name);
481             exit(1);
482         }
483         memory_region_set_readonly(bios, true);
484     }
485     /* Register Linux flash */
486     dinfo = drive_get(IF_PFLASH, 0, fl_idx);
487     if (dinfo) {
488         bios_size = 32 * MiB;
489         pflash_cfi02_register(0xfc000000, "taihu_405ep.flash", bios_size,
490                               dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
491                               64 * KiB, 1,
492                               4, 0x0001, 0x22DA, 0x0000, 0x0000, 0x555, 0x2AA,
493                               1);
494         fl_idx++;
495     }
496     /* Register CLPD & LCD display */
497     taihu_cpld_init(sysmem, 0x50100000);
498     /* Load kernel */
499     linux_boot = (kernel_filename != NULL);
500     if (linux_boot) {
501         kernel_base = KERNEL_LOAD_ADDR;
502         /* now we can load the kernel */
503         kernel_size = load_image_targphys(kernel_filename, kernel_base,
504                                           ram_size - kernel_base);
505         if (kernel_size < 0) {
506             error_report("could not load kernel '%s'", kernel_filename);
507             exit(1);
508         }
509         /* load initrd */
510         if (initrd_filename) {
511             initrd_base = INITRD_LOAD_ADDR;
512             initrd_size = load_image_targphys(initrd_filename, initrd_base,
513                                               ram_size - initrd_base);
514             if (initrd_size < 0) {
515                 error_report("could not load initial ram disk '%s'",
516                              initrd_filename);
517                 exit(1);
518             }
519         } else {
520             initrd_base = 0;
521             initrd_size = 0;
522         }
523     } else {
524         kernel_base = 0;
525         kernel_size = 0;
526         initrd_base = 0;
527         initrd_size = 0;
528     }
529 }
530 
531 static void taihu_class_init(ObjectClass *oc, void *data)
532 {
533     MachineClass *mc = MACHINE_CLASS(oc);
534 
535     mc->desc = "taihu";
536     mc->init = taihu_405ep_init;
537 }
538 
539 static const TypeInfo taihu_type = {
540     .name = MACHINE_TYPE_NAME("taihu"),
541     .parent = TYPE_MACHINE,
542     .class_init = taihu_class_init,
543 };
544 
545 static void ppc405_machine_init(void)
546 {
547     type_register_static(&ref405ep_type);
548     type_register_static(&taihu_type);
549 }
550 
551 type_init(ppc405_machine_init)
552