xref: /openbmc/qemu/hw/mips/boston.c (revision 7f6c3d1a)
1 /*
2  * MIPS Boston development board emulation.
3  *
4  * Copyright (c) 2016 Imagination Technologies
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #include "qemu/osdep.h"
21 #include "qemu/units.h"
22 
23 #include "exec/address-spaces.h"
24 #include "hw/boards.h"
25 #include "hw/char/serial.h"
26 #include "hw/ide/pci.h"
27 #include "hw/ide/ahci.h"
28 #include "hw/loader.h"
29 #include "hw/loader-fit.h"
30 #include "hw/mips/cps.h"
31 #include "hw/mips/cpudevs.h"
32 #include "hw/pci-host/xilinx-pcie.h"
33 #include "hw/qdev-properties.h"
34 #include "qapi/error.h"
35 #include "qemu/error-report.h"
36 #include "qemu/log.h"
37 #include "chardev/char.h"
38 #include "sysemu/device_tree.h"
39 #include "sysemu/sysemu.h"
40 #include "sysemu/qtest.h"
41 #include "sysemu/runstate.h"
42 
43 #include <libfdt.h>
44 #include "qom/object.h"
45 
46 #define TYPE_MIPS_BOSTON "mips-boston"
47 typedef struct BostonState BostonState;
48 DECLARE_INSTANCE_CHECKER(BostonState, BOSTON,
49                          TYPE_MIPS_BOSTON)
50 
51 struct BostonState {
52     SysBusDevice parent_obj;
53 
54     MachineState *mach;
55     MIPSCPSState cps;
56     SerialMM *uart;
57 
58     CharBackend lcd_display;
59     char lcd_content[8];
60     bool lcd_inited;
61 
62     hwaddr kernel_entry;
63     hwaddr fdt_base;
64 };
65 
66 enum boston_plat_reg {
67     PLAT_FPGA_BUILD     = 0x00,
68     PLAT_CORE_CL        = 0x04,
69     PLAT_WRAPPER_CL     = 0x08,
70     PLAT_SYSCLK_STATUS  = 0x0c,
71     PLAT_SOFTRST_CTL    = 0x10,
72 #define PLAT_SOFTRST_CTL_SYSRESET       (1 << 4)
73     PLAT_DDR3_STATUS    = 0x14,
74 #define PLAT_DDR3_STATUS_LOCKED         (1 << 0)
75 #define PLAT_DDR3_STATUS_CALIBRATED     (1 << 2)
76     PLAT_PCIE_STATUS    = 0x18,
77 #define PLAT_PCIE_STATUS_PCIE0_LOCKED   (1 << 0)
78 #define PLAT_PCIE_STATUS_PCIE1_LOCKED   (1 << 8)
79 #define PLAT_PCIE_STATUS_PCIE2_LOCKED   (1 << 16)
80     PLAT_FLASH_CTL      = 0x1c,
81     PLAT_SPARE0         = 0x20,
82     PLAT_SPARE1         = 0x24,
83     PLAT_SPARE2         = 0x28,
84     PLAT_SPARE3         = 0x2c,
85     PLAT_MMCM_DIV       = 0x30,
86 #define PLAT_MMCM_DIV_CLK0DIV_SHIFT     0
87 #define PLAT_MMCM_DIV_INPUT_SHIFT       8
88 #define PLAT_MMCM_DIV_MUL_SHIFT         16
89 #define PLAT_MMCM_DIV_CLK1DIV_SHIFT     24
90     PLAT_BUILD_CFG      = 0x34,
91 #define PLAT_BUILD_CFG_IOCU_EN          (1 << 0)
92 #define PLAT_BUILD_CFG_PCIE0_EN         (1 << 1)
93 #define PLAT_BUILD_CFG_PCIE1_EN         (1 << 2)
94 #define PLAT_BUILD_CFG_PCIE2_EN         (1 << 3)
95     PLAT_DDR_CFG        = 0x38,
96 #define PLAT_DDR_CFG_SIZE               (0xf << 0)
97 #define PLAT_DDR_CFG_MHZ                (0xfff << 4)
98     PLAT_NOC_PCIE0_ADDR = 0x3c,
99     PLAT_NOC_PCIE1_ADDR = 0x40,
100     PLAT_NOC_PCIE2_ADDR = 0x44,
101     PLAT_SYS_CTL        = 0x48,
102 };
103 
104 static void boston_lcd_event(void *opaque, QEMUChrEvent event)
105 {
106     BostonState *s = opaque;
107     if (event == CHR_EVENT_OPENED && !s->lcd_inited) {
108         qemu_chr_fe_printf(&s->lcd_display, "        ");
109         s->lcd_inited = true;
110     }
111 }
112 
113 static uint64_t boston_lcd_read(void *opaque, hwaddr addr,
114                                 unsigned size)
115 {
116     BostonState *s = opaque;
117     uint64_t val = 0;
118 
119     switch (size) {
120     case 8:
121         val |= (uint64_t)s->lcd_content[(addr + 7) & 0x7] << 56;
122         val |= (uint64_t)s->lcd_content[(addr + 6) & 0x7] << 48;
123         val |= (uint64_t)s->lcd_content[(addr + 5) & 0x7] << 40;
124         val |= (uint64_t)s->lcd_content[(addr + 4) & 0x7] << 32;
125         /* fall through */
126     case 4:
127         val |= (uint64_t)s->lcd_content[(addr + 3) & 0x7] << 24;
128         val |= (uint64_t)s->lcd_content[(addr + 2) & 0x7] << 16;
129         /* fall through */
130     case 2:
131         val |= (uint64_t)s->lcd_content[(addr + 1) & 0x7] << 8;
132         /* fall through */
133     case 1:
134         val |= (uint64_t)s->lcd_content[(addr + 0) & 0x7];
135         break;
136     }
137 
138     return val;
139 }
140 
141 static void boston_lcd_write(void *opaque, hwaddr addr,
142                              uint64_t val, unsigned size)
143 {
144     BostonState *s = opaque;
145 
146     switch (size) {
147     case 8:
148         s->lcd_content[(addr + 7) & 0x7] = val >> 56;
149         s->lcd_content[(addr + 6) & 0x7] = val >> 48;
150         s->lcd_content[(addr + 5) & 0x7] = val >> 40;
151         s->lcd_content[(addr + 4) & 0x7] = val >> 32;
152         /* fall through */
153     case 4:
154         s->lcd_content[(addr + 3) & 0x7] = val >> 24;
155         s->lcd_content[(addr + 2) & 0x7] = val >> 16;
156         /* fall through */
157     case 2:
158         s->lcd_content[(addr + 1) & 0x7] = val >> 8;
159         /* fall through */
160     case 1:
161         s->lcd_content[(addr + 0) & 0x7] = val;
162         break;
163     }
164 
165     qemu_chr_fe_printf(&s->lcd_display,
166                        "\r%-8.8s", s->lcd_content);
167 }
168 
169 static const MemoryRegionOps boston_lcd_ops = {
170     .read = boston_lcd_read,
171     .write = boston_lcd_write,
172     .endianness = DEVICE_NATIVE_ENDIAN,
173 };
174 
175 static uint64_t boston_platreg_read(void *opaque, hwaddr addr,
176                                     unsigned size)
177 {
178     BostonState *s = opaque;
179     uint32_t gic_freq, val;
180 
181     if (size != 4) {
182         qemu_log_mask(LOG_UNIMP, "%uB platform register read\n", size);
183         return 0;
184     }
185 
186     switch (addr & 0xffff) {
187     case PLAT_FPGA_BUILD:
188     case PLAT_CORE_CL:
189     case PLAT_WRAPPER_CL:
190         return 0;
191     case PLAT_DDR3_STATUS:
192         return PLAT_DDR3_STATUS_LOCKED | PLAT_DDR3_STATUS_CALIBRATED;
193     case PLAT_MMCM_DIV:
194         gic_freq = mips_gictimer_get_freq(s->cps.gic.gic_timer) / 1000000;
195         val = gic_freq << PLAT_MMCM_DIV_INPUT_SHIFT;
196         val |= 1 << PLAT_MMCM_DIV_MUL_SHIFT;
197         val |= 1 << PLAT_MMCM_DIV_CLK0DIV_SHIFT;
198         val |= 1 << PLAT_MMCM_DIV_CLK1DIV_SHIFT;
199         return val;
200     case PLAT_BUILD_CFG:
201         val = PLAT_BUILD_CFG_PCIE0_EN;
202         val |= PLAT_BUILD_CFG_PCIE1_EN;
203         val |= PLAT_BUILD_CFG_PCIE2_EN;
204         return val;
205     case PLAT_DDR_CFG:
206         val = s->mach->ram_size / GiB;
207         assert(!(val & ~PLAT_DDR_CFG_SIZE));
208         val |= PLAT_DDR_CFG_MHZ;
209         return val;
210     default:
211         qemu_log_mask(LOG_UNIMP, "Read platform register 0x%" HWADDR_PRIx "\n",
212                       addr & 0xffff);
213         return 0;
214     }
215 }
216 
217 static void boston_platreg_write(void *opaque, hwaddr addr,
218                                  uint64_t val, unsigned size)
219 {
220     if (size != 4) {
221         qemu_log_mask(LOG_UNIMP, "%uB platform register write\n", size);
222         return;
223     }
224 
225     switch (addr & 0xffff) {
226     case PLAT_FPGA_BUILD:
227     case PLAT_CORE_CL:
228     case PLAT_WRAPPER_CL:
229     case PLAT_DDR3_STATUS:
230     case PLAT_PCIE_STATUS:
231     case PLAT_MMCM_DIV:
232     case PLAT_BUILD_CFG:
233     case PLAT_DDR_CFG:
234         /* read only */
235         break;
236     case PLAT_SOFTRST_CTL:
237         if (val & PLAT_SOFTRST_CTL_SYSRESET) {
238             qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
239         }
240         break;
241     default:
242         qemu_log_mask(LOG_UNIMP, "Write platform register 0x%" HWADDR_PRIx
243                       " = 0x%" PRIx64 "\n", addr & 0xffff, val);
244         break;
245     }
246 }
247 
248 static const MemoryRegionOps boston_platreg_ops = {
249     .read = boston_platreg_read,
250     .write = boston_platreg_write,
251     .endianness = DEVICE_NATIVE_ENDIAN,
252 };
253 
254 static const TypeInfo boston_device = {
255     .name          = TYPE_MIPS_BOSTON,
256     .parent        = TYPE_SYS_BUS_DEVICE,
257     .instance_size = sizeof(BostonState),
258 };
259 
260 static void boston_register_types(void)
261 {
262     type_register_static(&boston_device);
263 }
264 type_init(boston_register_types)
265 
266 static void gen_firmware(uint32_t *p, hwaddr kernel_entry, hwaddr fdt_addr,
267                          bool is_64b)
268 {
269     const uint32_t cm_base = 0x16100000;
270     const uint32_t gic_base = 0x16120000;
271     const uint32_t cpc_base = 0x16200000;
272 
273     /* Move CM GCRs */
274     if (is_64b) {
275         stl_p(p++, 0x40287803);                 /* dmfc0 $8, CMGCRBase */
276         stl_p(p++, 0x00084138);                 /* dsll $8, $8, 4 */
277     } else {
278         stl_p(p++, 0x40087803);                 /* mfc0 $8, CMGCRBase */
279         stl_p(p++, 0x00084100);                 /* sll  $8, $8, 4 */
280     }
281     stl_p(p++, 0x3c09a000);                     /* lui  $9, 0xa000 */
282     stl_p(p++, 0x01094025);                     /* or   $8, $9 */
283     stl_p(p++, 0x3c0a0000 | (cm_base >> 16));   /* lui  $10, cm_base >> 16 */
284     if (is_64b) {
285         stl_p(p++, 0xfd0a0008);                 /* sd   $10, 0x8($8) */
286     } else {
287         stl_p(p++, 0xad0a0008);                 /* sw   $10, 0x8($8) */
288     }
289     stl_p(p++, 0x012a4025);                     /* or   $8, $10 */
290 
291     /* Move & enable GIC GCRs */
292     stl_p(p++, 0x3c090000 | (gic_base >> 16));  /* lui  $9, gic_base >> 16 */
293     stl_p(p++, 0x35290001);                     /* ori  $9, 0x1 */
294     if (is_64b) {
295         stl_p(p++, 0xfd090080);                 /* sd   $9, 0x80($8) */
296     } else {
297         stl_p(p++, 0xad090080);                 /* sw   $9, 0x80($8) */
298     }
299 
300     /* Move & enable CPC GCRs */
301     stl_p(p++, 0x3c090000 | (cpc_base >> 16));  /* lui  $9, cpc_base >> 16 */
302     stl_p(p++, 0x35290001);                     /* ori  $9, 0x1 */
303     if (is_64b) {
304         stl_p(p++, 0xfd090088);                 /* sd   $9, 0x88($8) */
305     } else {
306         stl_p(p++, 0xad090088);                 /* sw   $9, 0x88($8) */
307     }
308 
309     /*
310      * Setup argument registers to follow the UHI boot protocol:
311      *
312      * a0/$4 = -2
313      * a1/$5 = virtual address of FDT
314      * a2/$6 = 0
315      * a3/$7 = 0
316      */
317     stl_p(p++, 0x2404fffe);                     /* li   $4, -2 */
318                                                 /* lui  $5, hi(fdt_addr) */
319     stl_p(p++, 0x3c050000 | ((fdt_addr >> 16) & 0xffff));
320     if (fdt_addr & 0xffff) {                    /* ori  $5, lo(fdt_addr) */
321         stl_p(p++, 0x34a50000 | (fdt_addr & 0xffff));
322     }
323     stl_p(p++, 0x34060000);                     /* li   $6, 0 */
324     stl_p(p++, 0x34070000);                     /* li   $7, 0 */
325 
326     /* Load kernel entry address & jump to it */
327                                                 /* lui  $25, hi(kernel_entry) */
328     stl_p(p++, 0x3c190000 | ((kernel_entry >> 16) & 0xffff));
329                                                 /* ori  $25, lo(kernel_entry) */
330     stl_p(p++, 0x37390000 | (kernel_entry & 0xffff));
331     stl_p(p++, 0x03200009);                     /* jr   $25 */
332 }
333 
334 static const void *boston_fdt_filter(void *opaque, const void *fdt_orig,
335                                      const void *match_data, hwaddr *load_addr)
336 {
337     BostonState *s = BOSTON(opaque);
338     MachineState *machine = s->mach;
339     const char *cmdline;
340     int err;
341     void *fdt;
342     size_t fdt_sz, ram_low_sz, ram_high_sz;
343 
344     fdt_sz = fdt_totalsize(fdt_orig) * 2;
345     fdt = g_malloc0(fdt_sz);
346 
347     err = fdt_open_into(fdt_orig, fdt, fdt_sz);
348     if (err) {
349         fprintf(stderr, "unable to open FDT\n");
350         return NULL;
351     }
352 
353     cmdline = (machine->kernel_cmdline && machine->kernel_cmdline[0])
354             ? machine->kernel_cmdline : " ";
355     err = qemu_fdt_setprop_string(fdt, "/chosen", "bootargs", cmdline);
356     if (err < 0) {
357         fprintf(stderr, "couldn't set /chosen/bootargs\n");
358         return NULL;
359     }
360 
361     ram_low_sz = MIN(256 * MiB, machine->ram_size);
362     ram_high_sz = machine->ram_size - ram_low_sz;
363     qemu_fdt_setprop_sized_cells(fdt, "/memory@0", "reg",
364                                  1, 0x00000000, 1, ram_low_sz,
365                                  1, 0x90000000, 1, ram_high_sz);
366 
367     fdt = g_realloc(fdt, fdt_totalsize(fdt));
368     qemu_fdt_dumpdtb(fdt, fdt_sz);
369 
370     s->fdt_base = *load_addr;
371 
372     return fdt;
373 }
374 
375 static const void *boston_kernel_filter(void *opaque, const void *kernel,
376                                         hwaddr *load_addr, hwaddr *entry_addr)
377 {
378     BostonState *s = BOSTON(opaque);
379 
380     s->kernel_entry = *entry_addr;
381 
382     return kernel;
383 }
384 
385 static const struct fit_loader_match boston_matches[] = {
386     { "img,boston" },
387     { NULL },
388 };
389 
390 static const struct fit_loader boston_fit_loader = {
391     .matches = boston_matches,
392     .addr_to_phys = cpu_mips_kseg0_to_phys,
393     .fdt_filter = boston_fdt_filter,
394     .kernel_filter = boston_kernel_filter,
395 };
396 
397 static inline XilinxPCIEHost *
398 xilinx_pcie_init(MemoryRegion *sys_mem, uint32_t bus_nr,
399                  hwaddr cfg_base, uint64_t cfg_size,
400                  hwaddr mmio_base, uint64_t mmio_size,
401                  qemu_irq irq, bool link_up)
402 {
403     DeviceState *dev;
404     MemoryRegion *cfg, *mmio;
405 
406     dev = qdev_new(TYPE_XILINX_PCIE_HOST);
407 
408     qdev_prop_set_uint32(dev, "bus_nr", bus_nr);
409     qdev_prop_set_uint64(dev, "cfg_base", cfg_base);
410     qdev_prop_set_uint64(dev, "cfg_size", cfg_size);
411     qdev_prop_set_uint64(dev, "mmio_base", mmio_base);
412     qdev_prop_set_uint64(dev, "mmio_size", mmio_size);
413     qdev_prop_set_bit(dev, "link_up", link_up);
414 
415     sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
416 
417     cfg = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0);
418     memory_region_add_subregion_overlap(sys_mem, cfg_base, cfg, 0);
419 
420     mmio = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 1);
421     memory_region_add_subregion_overlap(sys_mem, 0, mmio, 0);
422 
423     qdev_connect_gpio_out_named(dev, "interrupt_out", 0, irq);
424 
425     return XILINX_PCIE_HOST(dev);
426 }
427 
428 static void boston_mach_init(MachineState *machine)
429 {
430     DeviceState *dev;
431     BostonState *s;
432     MemoryRegion *flash, *ddr_low_alias, *lcd, *platreg;
433     MemoryRegion *sys_mem = get_system_memory();
434     XilinxPCIEHost *pcie2;
435     PCIDevice *ahci;
436     DriveInfo *hd[6];
437     Chardev *chr;
438     int fw_size, fit_err;
439     bool is_64b;
440 
441     if ((machine->ram_size % GiB) ||
442         (machine->ram_size > (2 * GiB))) {
443         error_report("Memory size must be 1GB or 2GB");
444         exit(1);
445     }
446 
447     dev = qdev_new(TYPE_MIPS_BOSTON);
448     sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
449 
450     s = BOSTON(dev);
451     s->mach = machine;
452 
453     if (!cpu_supports_cps_smp(machine->cpu_type)) {
454         error_report("Boston requires CPUs which support CPS");
455         exit(1);
456     }
457 
458     is_64b = cpu_supports_isa(machine->cpu_type, ISA_MIPS64);
459 
460     object_initialize_child(OBJECT(machine), "cps", &s->cps, TYPE_MIPS_CPS);
461     object_property_set_str(OBJECT(&s->cps), "cpu-type", machine->cpu_type,
462                             &error_fatal);
463     object_property_set_int(OBJECT(&s->cps), "num-vp", machine->smp.cpus,
464                             &error_fatal);
465     sysbus_realize(SYS_BUS_DEVICE(&s->cps), &error_fatal);
466 
467     sysbus_mmio_map_overlap(SYS_BUS_DEVICE(&s->cps), 0, 0, 1);
468 
469     flash =  g_new(MemoryRegion, 1);
470     memory_region_init_rom(flash, NULL, "boston.flash", 128 * MiB,
471                            &error_fatal);
472     memory_region_add_subregion_overlap(sys_mem, 0x18000000, flash, 0);
473 
474     memory_region_add_subregion_overlap(sys_mem, 0x80000000, machine->ram, 0);
475 
476     ddr_low_alias = g_new(MemoryRegion, 1);
477     memory_region_init_alias(ddr_low_alias, NULL, "boston_low.ddr",
478                              machine->ram, 0,
479                              MIN(machine->ram_size, (256 * MiB)));
480     memory_region_add_subregion_overlap(sys_mem, 0, ddr_low_alias, 0);
481 
482     xilinx_pcie_init(sys_mem, 0,
483                      0x10000000, 32 * MiB,
484                      0x40000000, 1 * GiB,
485                      get_cps_irq(&s->cps, 2), false);
486 
487     xilinx_pcie_init(sys_mem, 1,
488                      0x12000000, 32 * MiB,
489                      0x20000000, 512 * MiB,
490                      get_cps_irq(&s->cps, 1), false);
491 
492     pcie2 = xilinx_pcie_init(sys_mem, 2,
493                              0x14000000, 32 * MiB,
494                              0x16000000, 1 * MiB,
495                              get_cps_irq(&s->cps, 0), true);
496 
497     platreg = g_new(MemoryRegion, 1);
498     memory_region_init_io(platreg, NULL, &boston_platreg_ops, s,
499                           "boston-platregs", 0x1000);
500     memory_region_add_subregion_overlap(sys_mem, 0x17ffd000, platreg, 0);
501 
502     s->uart = serial_mm_init(sys_mem, 0x17ffe000, 2,
503                              get_cps_irq(&s->cps, 3), 10000000,
504                              serial_hd(0), DEVICE_NATIVE_ENDIAN);
505 
506     lcd = g_new(MemoryRegion, 1);
507     memory_region_init_io(lcd, NULL, &boston_lcd_ops, s, "boston-lcd", 0x8);
508     memory_region_add_subregion_overlap(sys_mem, 0x17fff000, lcd, 0);
509 
510     chr = qemu_chr_new("lcd", "vc:320x240", NULL);
511     qemu_chr_fe_init(&s->lcd_display, chr, NULL);
512     qemu_chr_fe_set_handlers(&s->lcd_display, NULL, NULL,
513                              boston_lcd_event, NULL, s, NULL, true);
514 
515     ahci = pci_create_simple_multifunction(&PCI_BRIDGE(&pcie2->root)->sec_bus,
516                                            PCI_DEVFN(0, 0),
517                                            true, TYPE_ICH9_AHCI);
518     g_assert(ARRAY_SIZE(hd) == ahci_get_num_ports(ahci));
519     ide_drive_get(hd, ahci_get_num_ports(ahci));
520     ahci_ide_create_devs(ahci, hd);
521 
522     if (machine->firmware) {
523         fw_size = load_image_targphys(machine->firmware,
524                                       0x1fc00000, 4 * MiB);
525         if (fw_size == -1) {
526             error_report("unable to load firmware image '%s'",
527                           machine->firmware);
528             exit(1);
529         }
530     } else if (machine->kernel_filename) {
531         fit_err = load_fit(&boston_fit_loader, machine->kernel_filename, s);
532         if (fit_err) {
533             error_report("unable to load FIT image");
534             exit(1);
535         }
536 
537         gen_firmware(memory_region_get_ram_ptr(flash) + 0x7c00000,
538                      s->kernel_entry, s->fdt_base, is_64b);
539     } else if (!qtest_enabled()) {
540         error_report("Please provide either a -kernel or -bios argument");
541         exit(1);
542     }
543 }
544 
545 static void boston_mach_class_init(MachineClass *mc)
546 {
547     mc->desc = "MIPS Boston";
548     mc->init = boston_mach_init;
549     mc->block_default_type = IF_IDE;
550     mc->default_ram_size = 1 * GiB;
551     mc->default_ram_id = "boston.ddr";
552     mc->max_cpus = 16;
553     mc->default_cpu_type = MIPS_CPU_TYPE_NAME("I6400");
554 }
555 
556 DEFINE_MACHINE("boston", boston_mach_class_init)
557