Skip to content

Commit 628c3bb

Browse files
committed
LoongArch: Add boot and setup routines
Add basic boot, setup and reset routines for LoongArch. Now, LoongArch machines use UEFI-based firmware. The firmware passes configuration information to the kernel via ACPI and DMI/SMBIOS. Currently an existing interface between the kernel and the bootloader is implemented. Kernel gets 2 values from the bootloader, passed in registers a0 and a1; a0 is an "EFI boot flag" distinguishing UEFI and non-UEFI firmware, while a1 is a pointer to an FDT with systable, memmap, cmdline and initrd information. The standard UEFI boot protocol (EFISTUB) will be added later. Cc: [email protected] Cc: Ard Biesheuvel <[email protected]> Reviewed-by: WANG Xuerui <[email protected]> Reviewed-by: Jiaxun Yang <[email protected]> Co-developed-by: Yun Liu <[email protected]> Signed-off-by: Yun Liu <[email protected]> Signed-off-by: Huacai Chen <[email protected]>
1 parent b738c10 commit 628c3bb

File tree

18 files changed

+1738
-0
lines changed

18 files changed

+1738
-0
lines changed

arch/loongarch/include/asm/acenv.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
/*
3+
* LoongArch specific ACPICA environments and implementation
4+
*
5+
* Author: Jianmin Lv <[email protected]>
6+
* Huacai Chen <[email protected]>
7+
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
8+
*/
9+
10+
#ifndef _ASM_LOONGARCH_ACENV_H
11+
#define _ASM_LOONGARCH_ACENV_H
12+
13+
/*
14+
* This header is required by ACPI core, but we have nothing to fill in
15+
* right now. Will be updated later when needed.
16+
*/
17+
18+
#endif /* _ASM_LOONGARCH_ACENV_H */

arch/loongarch/include/asm/acpi.h

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
/*
3+
* Author: Jianmin Lv <[email protected]>
4+
* Huacai Chen <[email protected]>
5+
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
6+
*/
7+
8+
#ifndef _ASM_LOONGARCH_ACPI_H
9+
#define _ASM_LOONGARCH_ACPI_H
10+
11+
#ifdef CONFIG_ACPI
12+
extern int acpi_strict;
13+
extern int acpi_disabled;
14+
extern int acpi_pci_disabled;
15+
extern int acpi_noirq;
16+
17+
#define acpi_os_ioremap acpi_os_ioremap
18+
void __init __iomem *acpi_os_ioremap(acpi_physical_address phys, acpi_size size);
19+
20+
static inline void disable_acpi(void)
21+
{
22+
acpi_disabled = 1;
23+
acpi_pci_disabled = 1;
24+
acpi_noirq = 1;
25+
}
26+
27+
static inline bool acpi_has_cpu_in_madt(void)
28+
{
29+
return true;
30+
}
31+
32+
extern struct list_head acpi_wakeup_device_list;
33+
34+
#endif /* !CONFIG_ACPI */
35+
36+
#define ACPI_TABLE_UPGRADE_MAX_PHYS ARCH_LOW_ADDRESS_LIMIT
37+
38+
#endif /* _ASM_LOONGARCH_ACPI_H */

arch/loongarch/include/asm/bootinfo.h

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
/*
3+
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
4+
*/
5+
#ifndef _ASM_BOOTINFO_H
6+
#define _ASM_BOOTINFO_H
7+
8+
#include <linux/types.h>
9+
#include <asm/setup.h>
10+
11+
const char *get_system_type(void);
12+
13+
extern void init_environ(void);
14+
extern void memblock_init(void);
15+
extern void platform_init(void);
16+
17+
struct loongson_board_info {
18+
int bios_size;
19+
const char *bios_vendor;
20+
const char *bios_version;
21+
const char *bios_release_date;
22+
const char *board_name;
23+
const char *board_vendor;
24+
};
25+
26+
struct loongson_system_configuration {
27+
int nr_cpus;
28+
int nr_nodes;
29+
int nr_io_pics;
30+
int boot_cpu_id;
31+
int cores_per_node;
32+
int cores_per_package;
33+
const char *cpuname;
34+
};
35+
36+
extern u64 efi_system_table;
37+
extern unsigned long fw_arg0, fw_arg1;
38+
extern struct loongson_board_info b_info;
39+
extern struct loongson_system_configuration loongson_sysconf;
40+
41+
#endif /* _ASM_BOOTINFO_H */

arch/loongarch/include/asm/dmi.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
/*
3+
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
4+
*/
5+
#ifndef _ASM_DMI_H
6+
#define _ASM_DMI_H
7+
8+
#include <linux/io.h>
9+
#include <linux/memblock.h>
10+
11+
#define dmi_early_remap(x, l) dmi_remap(x, l)
12+
#define dmi_early_unmap(x, l) dmi_unmap(x)
13+
#define dmi_alloc(l) memblock_alloc(l, PAGE_SIZE)
14+
15+
static inline void *dmi_remap(u64 phys_addr, unsigned long size)
16+
{
17+
return ((void *)TO_CACHE(phys_addr));
18+
}
19+
20+
static inline void dmi_unmap(void *addr)
21+
{
22+
}
23+
24+
#endif /* _ASM_DMI_H */

arch/loongarch/include/asm/efi.h

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
/*
3+
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
4+
*/
5+
#ifndef _ASM_LOONGARCH_EFI_H
6+
#define _ASM_LOONGARCH_EFI_H
7+
8+
#include <linux/efi.h>
9+
10+
void __init efi_init(void);
11+
void __init efi_runtime_init(void);
12+
void efifb_setup_from_dmi(struct screen_info *si, const char *opt);
13+
14+
#define ARCH_EFI_IRQ_FLAGS_MASK 0x00000004 /* Bit 2: CSR.CRMD.IE */
15+
16+
#define arch_efi_call_virt_setup() \
17+
({ \
18+
})
19+
20+
#define arch_efi_call_virt(p, f, args...) \
21+
({ \
22+
efi_##f##_t * __f; \
23+
__f = p->f; \
24+
__f(args); \
25+
})
26+
27+
#define arch_efi_call_virt_teardown() \
28+
({ \
29+
})
30+
31+
#define EFI_ALLOC_ALIGN SZ_64K
32+
33+
struct screen_info *alloc_screen_info(void);
34+
void free_screen_info(struct screen_info *si);
35+
36+
static inline unsigned long efi_get_max_initrd_addr(unsigned long image_addr)
37+
{
38+
return ULONG_MAX;
39+
}
40+
41+
#endif /* _ASM_LOONGARCH_EFI_H */

arch/loongarch/include/asm/reboot.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
/*
3+
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
4+
*/
5+
#ifndef _ASM_REBOOT_H
6+
#define _ASM_REBOOT_H
7+
8+
extern void (*pm_restart)(void);
9+
10+
#endif /* _ASM_REBOOT_H */

arch/loongarch/include/asm/setup.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
/*
3+
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
4+
*/
5+
6+
#ifndef _LOONGARCH_SETUP_H
7+
#define _LOONGARCH_SETUP_H
8+
9+
#include <linux/types.h>
10+
#include <uapi/asm/setup.h>
11+
12+
#define VECSIZE 0x200
13+
14+
extern unsigned long eentry;
15+
extern unsigned long tlbrentry;
16+
extern void cpu_cache_init(void);
17+
extern void per_cpu_trap_init(int cpu);
18+
extern void set_handler(unsigned long offset, void *addr, unsigned long len);
19+
extern void set_merr_handler(unsigned long offset, void *addr, unsigned long len);
20+
21+
#endif /* __SETUP_H */

arch/loongarch/kernel/acpi.c

Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/*
3+
* acpi.c - Architecture-Specific Low-Level ACPI Boot Support
4+
*
5+
* Author: Jianmin Lv <[email protected]>
6+
* Huacai Chen <[email protected]>
7+
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
8+
*/
9+
10+
#include <linux/init.h>
11+
#include <linux/acpi.h>
12+
#include <linux/irq.h>
13+
#include <linux/irqdomain.h>
14+
#include <linux/memblock.h>
15+
#include <linux/serial_core.h>
16+
#include <asm/io.h>
17+
#include <asm/loongson.h>
18+
19+
int acpi_disabled;
20+
EXPORT_SYMBOL(acpi_disabled);
21+
int acpi_noirq;
22+
int acpi_pci_disabled;
23+
EXPORT_SYMBOL(acpi_pci_disabled);
24+
int acpi_strict = 1; /* We have no workarounds on LoongArch */
25+
int num_processors;
26+
int disabled_cpus;
27+
enum acpi_irq_model_id acpi_irq_model = ACPI_IRQ_MODEL_PLATFORM;
28+
29+
u64 acpi_saved_sp;
30+
31+
#define MAX_CORE_PIC 256
32+
33+
#define PREFIX "ACPI: "
34+
35+
int acpi_gsi_to_irq(u32 gsi, unsigned int *irqp)
36+
{
37+
if (irqp != NULL)
38+
*irqp = acpi_register_gsi(NULL, gsi, -1, -1);
39+
return (*irqp >= 0) ? 0 : -EINVAL;
40+
}
41+
EXPORT_SYMBOL_GPL(acpi_gsi_to_irq);
42+
43+
int acpi_isa_irq_to_gsi(unsigned int isa_irq, u32 *gsi)
44+
{
45+
if (gsi)
46+
*gsi = isa_irq;
47+
return 0;
48+
}
49+
50+
/*
51+
* success: return IRQ number (>=0)
52+
* failure: return < 0
53+
*/
54+
int acpi_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity)
55+
{
56+
struct irq_fwspec fwspec;
57+
58+
switch (gsi) {
59+
case GSI_MIN_CPU_IRQ ... GSI_MAX_CPU_IRQ:
60+
fwspec.fwnode = liointc_domain->fwnode;
61+
fwspec.param[0] = gsi - GSI_MIN_CPU_IRQ;
62+
fwspec.param_count = 1;
63+
64+
return irq_create_fwspec_mapping(&fwspec);
65+
66+
case GSI_MIN_LPC_IRQ ... GSI_MAX_LPC_IRQ:
67+
if (!pch_lpc_domain)
68+
return -EINVAL;
69+
70+
fwspec.fwnode = pch_lpc_domain->fwnode;
71+
fwspec.param[0] = gsi - GSI_MIN_LPC_IRQ;
72+
fwspec.param[1] = acpi_dev_get_irq_type(trigger, polarity);
73+
fwspec.param_count = 2;
74+
75+
return irq_create_fwspec_mapping(&fwspec);
76+
77+
case GSI_MIN_PCH_IRQ ... GSI_MAX_PCH_IRQ:
78+
if (!pch_pic_domain[0])
79+
return -EINVAL;
80+
81+
fwspec.fwnode = pch_pic_domain[0]->fwnode;
82+
fwspec.param[0] = gsi - GSI_MIN_PCH_IRQ;
83+
fwspec.param[1] = IRQ_TYPE_LEVEL_HIGH;
84+
fwspec.param_count = 2;
85+
86+
return irq_create_fwspec_mapping(&fwspec);
87+
}
88+
89+
return -EINVAL;
90+
}
91+
EXPORT_SYMBOL_GPL(acpi_register_gsi);
92+
93+
void acpi_unregister_gsi(u32 gsi)
94+
{
95+
96+
}
97+
EXPORT_SYMBOL_GPL(acpi_unregister_gsi);
98+
99+
void __init __iomem * __acpi_map_table(unsigned long phys, unsigned long size)
100+
{
101+
102+
if (!phys || !size)
103+
return NULL;
104+
105+
return early_memremap(phys, size);
106+
}
107+
void __init __acpi_unmap_table(void __iomem *map, unsigned long size)
108+
{
109+
if (!map || !size)
110+
return;
111+
112+
early_memunmap(map, size);
113+
}
114+
115+
void __init __iomem *acpi_os_ioremap(acpi_physical_address phys, acpi_size size)
116+
{
117+
if (!memblock_is_memory(phys))
118+
return ioremap(phys, size);
119+
else
120+
return ioremap_cache(phys, size);
121+
}
122+
123+
void __init acpi_boot_table_init(void)
124+
{
125+
/*
126+
* If acpi_disabled, bail out
127+
*/
128+
if (acpi_disabled)
129+
return;
130+
131+
/*
132+
* Initialize the ACPI boot-time table parser.
133+
*/
134+
if (acpi_table_init()) {
135+
disable_acpi();
136+
return;
137+
}
138+
}
139+
140+
static void __init acpi_process_madt(void)
141+
{
142+
loongson_sysconf.nr_cpus = num_processors;
143+
}
144+
145+
int __init acpi_boot_init(void)
146+
{
147+
/*
148+
* If acpi_disabled, bail out
149+
*/
150+
if (acpi_disabled)
151+
return -1;
152+
153+
loongson_sysconf.boot_cpu_id = read_csr_cpuid();
154+
155+
/*
156+
* Process the Multiple APIC Description Table (MADT), if present
157+
*/
158+
acpi_process_madt();
159+
160+
/* Do not enable ACPI SPCR console by default */
161+
acpi_parse_spcr(earlycon_acpi_spcr_enable, false);
162+
163+
return 0;
164+
}
165+
166+
void __init arch_reserve_mem_area(acpi_physical_address addr, size_t size)
167+
{
168+
memblock_reserve(addr, size);
169+
}

0 commit comments

Comments
 (0)