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