xref: /openbmc/qemu/hw/mips/loongson3_bootp.c (revision d2245e2de0201d7dfaff66c6851934af2d23bbfc)
1*d2245e2dSHuacai Chen /*
2*d2245e2dSHuacai Chen  * LEFI (a UEFI-like interface for BIOS-Kernel boot parameters) helpers
3*d2245e2dSHuacai Chen  *
4*d2245e2dSHuacai Chen  * Copyright (c) 2018-2020 Huacai Chen (chenhc@lemote.com)
5*d2245e2dSHuacai Chen  * Copyright (c) 2018-2020 Jiaxun Yang <jiaxun.yang@flygoat.com>
6*d2245e2dSHuacai Chen  *
7*d2245e2dSHuacai Chen  * This program is free software: you can redistribute it and/or modify
8*d2245e2dSHuacai Chen  * it under the terms of the GNU General Public License as published by
9*d2245e2dSHuacai Chen  * the Free Software Foundation, either version 2 of the License, or
10*d2245e2dSHuacai Chen  * (at your option) any later version.
11*d2245e2dSHuacai Chen  *
12*d2245e2dSHuacai Chen  * This program is distributed in the hope that it will be useful,
13*d2245e2dSHuacai Chen  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14*d2245e2dSHuacai Chen  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15*d2245e2dSHuacai Chen  * GNU General Public License for more details.
16*d2245e2dSHuacai Chen  *
17*d2245e2dSHuacai Chen  * You should have received a copy of the GNU General Public License
18*d2245e2dSHuacai Chen  * along with this program. If not, see <https://www.gnu.org/licenses/>.
19*d2245e2dSHuacai Chen  */
20*d2245e2dSHuacai Chen 
21*d2245e2dSHuacai Chen #include "qemu/osdep.h"
22*d2245e2dSHuacai Chen #include "qemu/units.h"
23*d2245e2dSHuacai Chen #include "qemu/cutils.h"
24*d2245e2dSHuacai Chen #include "cpu.h"
25*d2245e2dSHuacai Chen #include "hw/boards.h"
26*d2245e2dSHuacai Chen #include "hw/mips/loongson3_bootp.h"
27*d2245e2dSHuacai Chen 
28*d2245e2dSHuacai Chen #define LOONGSON3_CORE_PER_NODE 4
29*d2245e2dSHuacai Chen 
30*d2245e2dSHuacai Chen static void init_cpu_info(void *g_cpuinfo, uint64_t cpu_freq)
31*d2245e2dSHuacai Chen {
32*d2245e2dSHuacai Chen     struct efi_cpuinfo_loongson *c = g_cpuinfo;
33*d2245e2dSHuacai Chen 
34*d2245e2dSHuacai Chen     c->cputype = cpu_to_le32(Loongson_3A);
35*d2245e2dSHuacai Chen     c->processor_id = cpu_to_le32(MIPS_CPU(first_cpu)->env.CP0_PRid);
36*d2245e2dSHuacai Chen     if (cpu_freq > UINT_MAX) {
37*d2245e2dSHuacai Chen         c->cpu_clock_freq = cpu_to_le32(UINT_MAX);
38*d2245e2dSHuacai Chen     } else {
39*d2245e2dSHuacai Chen         c->cpu_clock_freq = cpu_to_le32(cpu_freq);
40*d2245e2dSHuacai Chen     }
41*d2245e2dSHuacai Chen 
42*d2245e2dSHuacai Chen     c->cpu_startup_core_id = cpu_to_le16(0);
43*d2245e2dSHuacai Chen     c->nr_cpus = cpu_to_le32(current_machine->smp.cpus);
44*d2245e2dSHuacai Chen     c->total_node = cpu_to_le32(DIV_ROUND_UP(current_machine->smp.cpus,
45*d2245e2dSHuacai Chen                                              LOONGSON3_CORE_PER_NODE));
46*d2245e2dSHuacai Chen }
47*d2245e2dSHuacai Chen 
48*d2245e2dSHuacai Chen static void init_memory_map(void *g_map, uint64_t ram_size)
49*d2245e2dSHuacai Chen {
50*d2245e2dSHuacai Chen     struct efi_memory_map_loongson *emap = g_map;
51*d2245e2dSHuacai Chen 
52*d2245e2dSHuacai Chen     emap->nr_map = cpu_to_le32(2);
53*d2245e2dSHuacai Chen     emap->mem_freq = cpu_to_le32(300000000);
54*d2245e2dSHuacai Chen 
55*d2245e2dSHuacai Chen     emap->map[0].node_id = cpu_to_le32(0);
56*d2245e2dSHuacai Chen     emap->map[0].mem_type = cpu_to_le32(1);
57*d2245e2dSHuacai Chen     emap->map[0].mem_start = cpu_to_le64(0x0);
58*d2245e2dSHuacai Chen     emap->map[0].mem_size = cpu_to_le32(240);
59*d2245e2dSHuacai Chen 
60*d2245e2dSHuacai Chen     emap->map[1].node_id = cpu_to_le32(0);
61*d2245e2dSHuacai Chen     emap->map[1].mem_type = cpu_to_le32(2);
62*d2245e2dSHuacai Chen     emap->map[1].mem_start = cpu_to_le64(0x90000000);
63*d2245e2dSHuacai Chen     emap->map[1].mem_size = cpu_to_le32((ram_size / MiB) - 256);
64*d2245e2dSHuacai Chen }
65*d2245e2dSHuacai Chen 
66*d2245e2dSHuacai Chen static void init_system_loongson(void *g_system)
67*d2245e2dSHuacai Chen {
68*d2245e2dSHuacai Chen     struct system_loongson *s = g_system;
69*d2245e2dSHuacai Chen 
70*d2245e2dSHuacai Chen     s->ccnuma_smp = cpu_to_le32(0);
71*d2245e2dSHuacai Chen     s->sing_double_channel = cpu_to_le32(1);
72*d2245e2dSHuacai Chen     s->nr_uarts = cpu_to_le32(1);
73*d2245e2dSHuacai Chen     s->uarts[0].iotype = cpu_to_le32(2);
74*d2245e2dSHuacai Chen     s->uarts[0].int_offset = cpu_to_le32(2);
75*d2245e2dSHuacai Chen     s->uarts[0].uartclk = cpu_to_le32(25000000); /* Random value */
76*d2245e2dSHuacai Chen     s->uarts[0].uart_base = cpu_to_le64(virt_memmap[VIRT_UART].base);
77*d2245e2dSHuacai Chen }
78*d2245e2dSHuacai Chen 
79*d2245e2dSHuacai Chen static void init_irq_source(void *g_irq_source)
80*d2245e2dSHuacai Chen {
81*d2245e2dSHuacai Chen     struct irq_source_routing_table *irq_info = g_irq_source;
82*d2245e2dSHuacai Chen 
83*d2245e2dSHuacai Chen     irq_info->node_id = cpu_to_le32(0);
84*d2245e2dSHuacai Chen     irq_info->PIC_type = cpu_to_le32(0);
85*d2245e2dSHuacai Chen     irq_info->dma_mask_bits = cpu_to_le16(64);
86*d2245e2dSHuacai Chen     irq_info->pci_mem_start_addr = cpu_to_le64(virt_memmap[VIRT_PCIE_MMIO].base);
87*d2245e2dSHuacai Chen     irq_info->pci_mem_end_addr = cpu_to_le64(virt_memmap[VIRT_PCIE_MMIO].base +
88*d2245e2dSHuacai Chen                                              virt_memmap[VIRT_PCIE_MMIO].size - 1);
89*d2245e2dSHuacai Chen     irq_info->pci_io_start_addr = cpu_to_le64(virt_memmap[VIRT_PCIE_PIO].base);
90*d2245e2dSHuacai Chen }
91*d2245e2dSHuacai Chen 
92*d2245e2dSHuacai Chen static void init_interface_info(void *g_interface)
93*d2245e2dSHuacai Chen {
94*d2245e2dSHuacai Chen     struct interface_info *interface = g_interface;
95*d2245e2dSHuacai Chen 
96*d2245e2dSHuacai Chen     interface->vers = cpu_to_le16(0x01);
97*d2245e2dSHuacai Chen     strpadcpy(interface->description, 64, "UEFI_Version_v1.0", '\0');
98*d2245e2dSHuacai Chen }
99*d2245e2dSHuacai Chen 
100*d2245e2dSHuacai Chen static void board_devices_info(void *g_board)
101*d2245e2dSHuacai Chen {
102*d2245e2dSHuacai Chen     struct board_devices *bd = g_board;
103*d2245e2dSHuacai Chen 
104*d2245e2dSHuacai Chen     strpadcpy(bd->name, 64, "Loongson-3A-VIRT-1w-V1.00-demo", '\0');
105*d2245e2dSHuacai Chen }
106*d2245e2dSHuacai Chen 
107*d2245e2dSHuacai Chen static void init_special_info(void *g_special)
108*d2245e2dSHuacai Chen {
109*d2245e2dSHuacai Chen     struct loongson_special_attribute *special = g_special;
110*d2245e2dSHuacai Chen 
111*d2245e2dSHuacai Chen     strpadcpy(special->special_name, 64, "2018-05-01", '\0');
112*d2245e2dSHuacai Chen }
113*d2245e2dSHuacai Chen 
114*d2245e2dSHuacai Chen void init_loongson_params(struct loongson_params *lp, void *p,
115*d2245e2dSHuacai Chen                           uint64_t cpu_freq, uint64_t ram_size)
116*d2245e2dSHuacai Chen {
117*d2245e2dSHuacai Chen     init_cpu_info(p, cpu_freq);
118*d2245e2dSHuacai Chen     lp->cpu_offset = cpu_to_le64((uintptr_t)p - (uintptr_t)lp);
119*d2245e2dSHuacai Chen     p += ROUND_UP(sizeof(struct efi_cpuinfo_loongson), 64);
120*d2245e2dSHuacai Chen 
121*d2245e2dSHuacai Chen     init_memory_map(p, ram_size);
122*d2245e2dSHuacai Chen     lp->memory_offset = cpu_to_le64((uintptr_t)p - (uintptr_t)lp);
123*d2245e2dSHuacai Chen     p += ROUND_UP(sizeof(struct efi_memory_map_loongson), 64);
124*d2245e2dSHuacai Chen 
125*d2245e2dSHuacai Chen     init_system_loongson(p);
126*d2245e2dSHuacai Chen     lp->system_offset = cpu_to_le64((uintptr_t)p - (uintptr_t)lp);
127*d2245e2dSHuacai Chen     p += ROUND_UP(sizeof(struct system_loongson), 64);
128*d2245e2dSHuacai Chen 
129*d2245e2dSHuacai Chen     init_irq_source(p);
130*d2245e2dSHuacai Chen     lp->irq_offset = cpu_to_le64((uintptr_t)p - (uintptr_t)lp);
131*d2245e2dSHuacai Chen     p += ROUND_UP(sizeof(struct irq_source_routing_table), 64);
132*d2245e2dSHuacai Chen 
133*d2245e2dSHuacai Chen     init_interface_info(p);
134*d2245e2dSHuacai Chen     lp->interface_offset = cpu_to_le64((uintptr_t)p - (uintptr_t)lp);
135*d2245e2dSHuacai Chen     p += ROUND_UP(sizeof(struct interface_info), 64);
136*d2245e2dSHuacai Chen 
137*d2245e2dSHuacai Chen     board_devices_info(p);
138*d2245e2dSHuacai Chen     lp->boarddev_table_offset = cpu_to_le64((uintptr_t)p - (uintptr_t)lp);
139*d2245e2dSHuacai Chen     p += ROUND_UP(sizeof(struct board_devices), 64);
140*d2245e2dSHuacai Chen 
141*d2245e2dSHuacai Chen     init_special_info(p);
142*d2245e2dSHuacai Chen     lp->special_offset = cpu_to_le64((uintptr_t)p - (uintptr_t)lp);
143*d2245e2dSHuacai Chen     p += ROUND_UP(sizeof(struct loongson_special_attribute), 64);
144*d2245e2dSHuacai Chen }
145*d2245e2dSHuacai Chen 
146*d2245e2dSHuacai Chen void init_reset_system(struct efi_reset_system_t *reset)
147*d2245e2dSHuacai Chen {
148*d2245e2dSHuacai Chen     reset->Shutdown = cpu_to_le64(0xffffffffbfc000a8);
149*d2245e2dSHuacai Chen     reset->ResetCold = cpu_to_le64(0xffffffffbfc00080);
150*d2245e2dSHuacai Chen     reset->ResetWarm = cpu_to_le64(0xffffffffbfc00080);
151*d2245e2dSHuacai Chen }
152