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