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
init_cpu_info(void * g_cpuinfo,uint64_t cpu_freq)28d2245e2dSHuacai Chen static void init_cpu_info(void *g_cpuinfo, uint64_t cpu_freq)
29d2245e2dSHuacai Chen {
30d2245e2dSHuacai Chen struct efi_cpuinfo_loongson *c = g_cpuinfo;
31d2245e2dSHuacai Chen
32d2245e2dSHuacai Chen c->cputype = cpu_to_le32(Loongson_3A);
33d2245e2dSHuacai Chen c->processor_id = cpu_to_le32(MIPS_CPU(first_cpu)->env.CP0_PRid);
34d2245e2dSHuacai Chen if (cpu_freq > UINT_MAX) {
35d2245e2dSHuacai Chen c->cpu_clock_freq = cpu_to_le32(UINT_MAX);
36d2245e2dSHuacai Chen } else {
37d2245e2dSHuacai Chen c->cpu_clock_freq = cpu_to_le32(cpu_freq);
38d2245e2dSHuacai Chen }
39d2245e2dSHuacai Chen
40d2245e2dSHuacai Chen c->cpu_startup_core_id = cpu_to_le16(0);
41d2245e2dSHuacai Chen c->nr_cpus = cpu_to_le32(current_machine->smp.cpus);
42d2245e2dSHuacai Chen c->total_node = cpu_to_le32(DIV_ROUND_UP(current_machine->smp.cpus,
43d2245e2dSHuacai Chen LOONGSON3_CORE_PER_NODE));
44d2245e2dSHuacai Chen }
45d2245e2dSHuacai Chen
init_memory_map(void * g_map,uint64_t ram_size)46d2245e2dSHuacai Chen static void init_memory_map(void *g_map, uint64_t ram_size)
47d2245e2dSHuacai Chen {
48d2245e2dSHuacai Chen struct efi_memory_map_loongson *emap = g_map;
49d2245e2dSHuacai Chen
50d2245e2dSHuacai Chen emap->nr_map = cpu_to_le32(2);
51d2245e2dSHuacai Chen emap->mem_freq = cpu_to_le32(300000000);
52d2245e2dSHuacai Chen
53d2245e2dSHuacai Chen emap->map[0].node_id = cpu_to_le32(0);
54d2245e2dSHuacai Chen emap->map[0].mem_type = cpu_to_le32(1);
55d2245e2dSHuacai Chen emap->map[0].mem_start = cpu_to_le64(0x0);
56d2245e2dSHuacai Chen emap->map[0].mem_size = cpu_to_le32(240);
57d2245e2dSHuacai Chen
58d2245e2dSHuacai Chen emap->map[1].node_id = cpu_to_le32(0);
59d2245e2dSHuacai Chen emap->map[1].mem_type = cpu_to_le32(2);
60d2245e2dSHuacai Chen emap->map[1].mem_start = cpu_to_le64(0x90000000);
61d2245e2dSHuacai Chen emap->map[1].mem_size = cpu_to_le32((ram_size / MiB) - 256);
62d2245e2dSHuacai Chen }
63d2245e2dSHuacai Chen
init_system_loongson(void * g_system)64d2245e2dSHuacai Chen static void init_system_loongson(void *g_system)
65d2245e2dSHuacai Chen {
66d2245e2dSHuacai Chen struct system_loongson *s = g_system;
67d2245e2dSHuacai Chen
68d2245e2dSHuacai Chen s->ccnuma_smp = cpu_to_le32(0);
69d2245e2dSHuacai Chen s->sing_double_channel = cpu_to_le32(1);
70d2245e2dSHuacai Chen s->nr_uarts = cpu_to_le32(1);
71d2245e2dSHuacai Chen s->uarts[0].iotype = cpu_to_le32(2);
72d2245e2dSHuacai Chen s->uarts[0].int_offset = cpu_to_le32(2);
73d2245e2dSHuacai Chen s->uarts[0].uartclk = cpu_to_le32(25000000); /* Random value */
74d2245e2dSHuacai Chen s->uarts[0].uart_base = cpu_to_le64(virt_memmap[VIRT_UART].base);
75d2245e2dSHuacai Chen }
76d2245e2dSHuacai Chen
init_irq_source(void * g_irq_source)77d2245e2dSHuacai Chen static void init_irq_source(void *g_irq_source)
78d2245e2dSHuacai Chen {
79d2245e2dSHuacai Chen struct irq_source_routing_table *irq_info = g_irq_source;
80d2245e2dSHuacai Chen
81d2245e2dSHuacai Chen irq_info->node_id = cpu_to_le32(0);
82d2245e2dSHuacai Chen irq_info->PIC_type = cpu_to_le32(0);
83d2245e2dSHuacai Chen irq_info->dma_mask_bits = cpu_to_le16(64);
84d2245e2dSHuacai Chen irq_info->pci_mem_start_addr = cpu_to_le64(virt_memmap[VIRT_PCIE_MMIO].base);
85d2245e2dSHuacai Chen irq_info->pci_mem_end_addr = cpu_to_le64(virt_memmap[VIRT_PCIE_MMIO].base +
86d2245e2dSHuacai Chen virt_memmap[VIRT_PCIE_MMIO].size - 1);
87d2245e2dSHuacai Chen irq_info->pci_io_start_addr = cpu_to_le64(virt_memmap[VIRT_PCIE_PIO].base);
88d2245e2dSHuacai Chen }
89d2245e2dSHuacai Chen
init_interface_info(void * g_interface)90d2245e2dSHuacai Chen static void init_interface_info(void *g_interface)
91d2245e2dSHuacai Chen {
92d2245e2dSHuacai Chen struct interface_info *interface = g_interface;
93d2245e2dSHuacai Chen
94d2245e2dSHuacai Chen interface->vers = cpu_to_le16(0x01);
95d2245e2dSHuacai Chen strpadcpy(interface->description, 64, "UEFI_Version_v1.0", '\0');
96d2245e2dSHuacai Chen }
97d2245e2dSHuacai Chen
board_devices_info(void * g_board)98d2245e2dSHuacai Chen static void board_devices_info(void *g_board)
99d2245e2dSHuacai Chen {
100d2245e2dSHuacai Chen struct board_devices *bd = g_board;
101d2245e2dSHuacai Chen
102d2245e2dSHuacai Chen strpadcpy(bd->name, 64, "Loongson-3A-VIRT-1w-V1.00-demo", '\0');
103d2245e2dSHuacai Chen }
104d2245e2dSHuacai Chen
init_special_info(void * g_special)105d2245e2dSHuacai Chen static void init_special_info(void *g_special)
106d2245e2dSHuacai Chen {
107d2245e2dSHuacai Chen struct loongson_special_attribute *special = g_special;
108d2245e2dSHuacai Chen
109d2245e2dSHuacai Chen strpadcpy(special->special_name, 64, "2018-05-01", '\0');
110d2245e2dSHuacai Chen }
111d2245e2dSHuacai Chen
init_loongson_params(struct loongson_params * lp,void * p,uint64_t cpu_freq,uint64_t ram_size)112d2245e2dSHuacai Chen void init_loongson_params(struct loongson_params *lp, void *p,
113d2245e2dSHuacai Chen uint64_t cpu_freq, uint64_t ram_size)
114d2245e2dSHuacai Chen {
115d2245e2dSHuacai Chen init_cpu_info(p, cpu_freq);
116d2245e2dSHuacai Chen lp->cpu_offset = cpu_to_le64((uintptr_t)p - (uintptr_t)lp);
117d2245e2dSHuacai Chen p += ROUND_UP(sizeof(struct efi_cpuinfo_loongson), 64);
118d2245e2dSHuacai Chen
119d2245e2dSHuacai Chen init_memory_map(p, ram_size);
120d2245e2dSHuacai Chen lp->memory_offset = cpu_to_le64((uintptr_t)p - (uintptr_t)lp);
121d2245e2dSHuacai Chen p += ROUND_UP(sizeof(struct efi_memory_map_loongson), 64);
122d2245e2dSHuacai Chen
123d2245e2dSHuacai Chen init_system_loongson(p);
124d2245e2dSHuacai Chen lp->system_offset = cpu_to_le64((uintptr_t)p - (uintptr_t)lp);
125d2245e2dSHuacai Chen p += ROUND_UP(sizeof(struct system_loongson), 64);
126d2245e2dSHuacai Chen
127d2245e2dSHuacai Chen init_irq_source(p);
128d2245e2dSHuacai Chen lp->irq_offset = cpu_to_le64((uintptr_t)p - (uintptr_t)lp);
129d2245e2dSHuacai Chen p += ROUND_UP(sizeof(struct irq_source_routing_table), 64);
130d2245e2dSHuacai Chen
131d2245e2dSHuacai Chen init_interface_info(p);
132d2245e2dSHuacai Chen lp->interface_offset = cpu_to_le64((uintptr_t)p - (uintptr_t)lp);
133d2245e2dSHuacai Chen p += ROUND_UP(sizeof(struct interface_info), 64);
134d2245e2dSHuacai Chen
135d2245e2dSHuacai Chen board_devices_info(p);
136d2245e2dSHuacai Chen lp->boarddev_table_offset = cpu_to_le64((uintptr_t)p - (uintptr_t)lp);
137d2245e2dSHuacai Chen p += ROUND_UP(sizeof(struct board_devices), 64);
138d2245e2dSHuacai Chen
139d2245e2dSHuacai Chen init_special_info(p);
140d2245e2dSHuacai Chen lp->special_offset = cpu_to_le64((uintptr_t)p - (uintptr_t)lp);
141d2245e2dSHuacai Chen p += ROUND_UP(sizeof(struct loongson_special_attribute), 64);
142d2245e2dSHuacai Chen }
143d2245e2dSHuacai Chen
init_reset_system(struct efi_reset_system_t * reset)144d2245e2dSHuacai Chen void init_reset_system(struct efi_reset_system_t *reset)
145d2245e2dSHuacai Chen {
146d2245e2dSHuacai Chen reset->Shutdown = cpu_to_le64(0xffffffffbfc000a8);
147d2245e2dSHuacai Chen reset->ResetCold = cpu_to_le64(0xffffffffbfc00080);
148d2245e2dSHuacai Chen reset->ResetWarm = cpu_to_le64(0xffffffffbfc00080);
149*5b1a3b9fSJiaxun Yang reset->DoSuspend = cpu_to_le64(0xffffffffbfc000d0);
150d2245e2dSHuacai Chen }
151