-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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: linux-efi@vger.kernel.org Cc: Ard Biesheuvel <ardb@kernel.org> Reviewed-by: WANG Xuerui <git@xen0n.name> Reviewed-by: Jiaxun Yang <jiaxun.yang@flygoat.com> Co-developed-by: Yun Liu <liuyun@loongson.cn> Signed-off-by: Yun Liu <liuyun@loongson.cn> Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
- Loading branch information
Huacai Chen
committed
Jun 3, 2022
1 parent
b738c10
commit 628c3bb
Showing
18 changed files
with
1,738 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
/* SPDX-License-Identifier: GPL-2.0 */ | ||
/* | ||
* LoongArch specific ACPICA environments and implementation | ||
* | ||
* Author: Jianmin Lv <lvjianmin@loongson.cn> | ||
* Huacai Chen <chenhuacai@loongson.cn> | ||
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited | ||
*/ | ||
|
||
#ifndef _ASM_LOONGARCH_ACENV_H | ||
#define _ASM_LOONGARCH_ACENV_H | ||
|
||
/* | ||
* This header is required by ACPI core, but we have nothing to fill in | ||
* right now. Will be updated later when needed. | ||
*/ | ||
|
||
#endif /* _ASM_LOONGARCH_ACENV_H */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
/* SPDX-License-Identifier: GPL-2.0 */ | ||
/* | ||
* Author: Jianmin Lv <lvjianmin@loongson.cn> | ||
* Huacai Chen <chenhuacai@loongson.cn> | ||
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited | ||
*/ | ||
|
||
#ifndef _ASM_LOONGARCH_ACPI_H | ||
#define _ASM_LOONGARCH_ACPI_H | ||
|
||
#ifdef CONFIG_ACPI | ||
extern int acpi_strict; | ||
extern int acpi_disabled; | ||
extern int acpi_pci_disabled; | ||
extern int acpi_noirq; | ||
|
||
#define acpi_os_ioremap acpi_os_ioremap | ||
void __init __iomem *acpi_os_ioremap(acpi_physical_address phys, acpi_size size); | ||
|
||
static inline void disable_acpi(void) | ||
{ | ||
acpi_disabled = 1; | ||
acpi_pci_disabled = 1; | ||
acpi_noirq = 1; | ||
} | ||
|
||
static inline bool acpi_has_cpu_in_madt(void) | ||
{ | ||
return true; | ||
} | ||
|
||
extern struct list_head acpi_wakeup_device_list; | ||
|
||
#endif /* !CONFIG_ACPI */ | ||
|
||
#define ACPI_TABLE_UPGRADE_MAX_PHYS ARCH_LOW_ADDRESS_LIMIT | ||
|
||
#endif /* _ASM_LOONGARCH_ACPI_H */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
/* SPDX-License-Identifier: GPL-2.0 */ | ||
/* | ||
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited | ||
*/ | ||
#ifndef _ASM_BOOTINFO_H | ||
#define _ASM_BOOTINFO_H | ||
|
||
#include <linux/types.h> | ||
#include <asm/setup.h> | ||
|
||
const char *get_system_type(void); | ||
|
||
extern void init_environ(void); | ||
extern void memblock_init(void); | ||
extern void platform_init(void); | ||
|
||
struct loongson_board_info { | ||
int bios_size; | ||
const char *bios_vendor; | ||
const char *bios_version; | ||
const char *bios_release_date; | ||
const char *board_name; | ||
const char *board_vendor; | ||
}; | ||
|
||
struct loongson_system_configuration { | ||
int nr_cpus; | ||
int nr_nodes; | ||
int nr_io_pics; | ||
int boot_cpu_id; | ||
int cores_per_node; | ||
int cores_per_package; | ||
const char *cpuname; | ||
}; | ||
|
||
extern u64 efi_system_table; | ||
extern unsigned long fw_arg0, fw_arg1; | ||
extern struct loongson_board_info b_info; | ||
extern struct loongson_system_configuration loongson_sysconf; | ||
|
||
#endif /* _ASM_BOOTINFO_H */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
/* SPDX-License-Identifier: GPL-2.0 */ | ||
/* | ||
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited | ||
*/ | ||
#ifndef _ASM_DMI_H | ||
#define _ASM_DMI_H | ||
|
||
#include <linux/io.h> | ||
#include <linux/memblock.h> | ||
|
||
#define dmi_early_remap(x, l) dmi_remap(x, l) | ||
#define dmi_early_unmap(x, l) dmi_unmap(x) | ||
#define dmi_alloc(l) memblock_alloc(l, PAGE_SIZE) | ||
|
||
static inline void *dmi_remap(u64 phys_addr, unsigned long size) | ||
{ | ||
return ((void *)TO_CACHE(phys_addr)); | ||
} | ||
|
||
static inline void dmi_unmap(void *addr) | ||
{ | ||
} | ||
|
||
#endif /* _ASM_DMI_H */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
/* SPDX-License-Identifier: GPL-2.0 */ | ||
/* | ||
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited | ||
*/ | ||
#ifndef _ASM_LOONGARCH_EFI_H | ||
#define _ASM_LOONGARCH_EFI_H | ||
|
||
#include <linux/efi.h> | ||
|
||
void __init efi_init(void); | ||
void __init efi_runtime_init(void); | ||
void efifb_setup_from_dmi(struct screen_info *si, const char *opt); | ||
|
||
#define ARCH_EFI_IRQ_FLAGS_MASK 0x00000004 /* Bit 2: CSR.CRMD.IE */ | ||
|
||
#define arch_efi_call_virt_setup() \ | ||
({ \ | ||
}) | ||
|
||
#define arch_efi_call_virt(p, f, args...) \ | ||
({ \ | ||
efi_##f##_t * __f; \ | ||
__f = p->f; \ | ||
__f(args); \ | ||
}) | ||
|
||
#define arch_efi_call_virt_teardown() \ | ||
({ \ | ||
}) | ||
|
||
#define EFI_ALLOC_ALIGN SZ_64K | ||
|
||
struct screen_info *alloc_screen_info(void); | ||
void free_screen_info(struct screen_info *si); | ||
|
||
static inline unsigned long efi_get_max_initrd_addr(unsigned long image_addr) | ||
{ | ||
return ULONG_MAX; | ||
} | ||
|
||
#endif /* _ASM_LOONGARCH_EFI_H */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
/* SPDX-License-Identifier: GPL-2.0 */ | ||
/* | ||
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited | ||
*/ | ||
#ifndef _ASM_REBOOT_H | ||
#define _ASM_REBOOT_H | ||
|
||
extern void (*pm_restart)(void); | ||
|
||
#endif /* _ASM_REBOOT_H */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
/* SPDX-License-Identifier: GPL-2.0 */ | ||
/* | ||
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited | ||
*/ | ||
|
||
#ifndef _LOONGARCH_SETUP_H | ||
#define _LOONGARCH_SETUP_H | ||
|
||
#include <linux/types.h> | ||
#include <uapi/asm/setup.h> | ||
|
||
#define VECSIZE 0x200 | ||
|
||
extern unsigned long eentry; | ||
extern unsigned long tlbrentry; | ||
extern void cpu_cache_init(void); | ||
extern void per_cpu_trap_init(int cpu); | ||
extern void set_handler(unsigned long offset, void *addr, unsigned long len); | ||
extern void set_merr_handler(unsigned long offset, void *addr, unsigned long len); | ||
|
||
#endif /* __SETUP_H */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,169 @@ | ||
// SPDX-License-Identifier: GPL-2.0 | ||
/* | ||
* acpi.c - Architecture-Specific Low-Level ACPI Boot Support | ||
* | ||
* Author: Jianmin Lv <lvjianmin@loongson.cn> | ||
* Huacai Chen <chenhuacai@loongson.cn> | ||
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited | ||
*/ | ||
|
||
#include <linux/init.h> | ||
#include <linux/acpi.h> | ||
#include <linux/irq.h> | ||
#include <linux/irqdomain.h> | ||
#include <linux/memblock.h> | ||
#include <linux/serial_core.h> | ||
#include <asm/io.h> | ||
#include <asm/loongson.h> | ||
|
||
int acpi_disabled; | ||
EXPORT_SYMBOL(acpi_disabled); | ||
int acpi_noirq; | ||
int acpi_pci_disabled; | ||
EXPORT_SYMBOL(acpi_pci_disabled); | ||
int acpi_strict = 1; /* We have no workarounds on LoongArch */ | ||
int num_processors; | ||
int disabled_cpus; | ||
enum acpi_irq_model_id acpi_irq_model = ACPI_IRQ_MODEL_PLATFORM; | ||
|
||
u64 acpi_saved_sp; | ||
|
||
#define MAX_CORE_PIC 256 | ||
|
||
#define PREFIX "ACPI: " | ||
|
||
int acpi_gsi_to_irq(u32 gsi, unsigned int *irqp) | ||
{ | ||
if (irqp != NULL) | ||
*irqp = acpi_register_gsi(NULL, gsi, -1, -1); | ||
return (*irqp >= 0) ? 0 : -EINVAL; | ||
} | ||
EXPORT_SYMBOL_GPL(acpi_gsi_to_irq); | ||
|
||
int acpi_isa_irq_to_gsi(unsigned int isa_irq, u32 *gsi) | ||
{ | ||
if (gsi) | ||
*gsi = isa_irq; | ||
return 0; | ||
} | ||
|
||
/* | ||
* success: return IRQ number (>=0) | ||
* failure: return < 0 | ||
*/ | ||
int acpi_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity) | ||
{ | ||
struct irq_fwspec fwspec; | ||
|
||
switch (gsi) { | ||
case GSI_MIN_CPU_IRQ ... GSI_MAX_CPU_IRQ: | ||
fwspec.fwnode = liointc_domain->fwnode; | ||
fwspec.param[0] = gsi - GSI_MIN_CPU_IRQ; | ||
fwspec.param_count = 1; | ||
|
||
return irq_create_fwspec_mapping(&fwspec); | ||
|
||
case GSI_MIN_LPC_IRQ ... GSI_MAX_LPC_IRQ: | ||
if (!pch_lpc_domain) | ||
return -EINVAL; | ||
|
||
fwspec.fwnode = pch_lpc_domain->fwnode; | ||
fwspec.param[0] = gsi - GSI_MIN_LPC_IRQ; | ||
fwspec.param[1] = acpi_dev_get_irq_type(trigger, polarity); | ||
fwspec.param_count = 2; | ||
|
||
return irq_create_fwspec_mapping(&fwspec); | ||
|
||
case GSI_MIN_PCH_IRQ ... GSI_MAX_PCH_IRQ: | ||
if (!pch_pic_domain[0]) | ||
return -EINVAL; | ||
|
||
fwspec.fwnode = pch_pic_domain[0]->fwnode; | ||
fwspec.param[0] = gsi - GSI_MIN_PCH_IRQ; | ||
fwspec.param[1] = IRQ_TYPE_LEVEL_HIGH; | ||
fwspec.param_count = 2; | ||
|
||
return irq_create_fwspec_mapping(&fwspec); | ||
} | ||
|
||
return -EINVAL; | ||
} | ||
EXPORT_SYMBOL_GPL(acpi_register_gsi); | ||
|
||
void acpi_unregister_gsi(u32 gsi) | ||
{ | ||
|
||
} | ||
EXPORT_SYMBOL_GPL(acpi_unregister_gsi); | ||
|
||
void __init __iomem * __acpi_map_table(unsigned long phys, unsigned long size) | ||
{ | ||
|
||
if (!phys || !size) | ||
return NULL; | ||
|
||
return early_memremap(phys, size); | ||
} | ||
void __init __acpi_unmap_table(void __iomem *map, unsigned long size) | ||
{ | ||
if (!map || !size) | ||
return; | ||
|
||
early_memunmap(map, size); | ||
} | ||
|
||
void __init __iomem *acpi_os_ioremap(acpi_physical_address phys, acpi_size size) | ||
{ | ||
if (!memblock_is_memory(phys)) | ||
return ioremap(phys, size); | ||
else | ||
return ioremap_cache(phys, size); | ||
} | ||
|
||
void __init acpi_boot_table_init(void) | ||
{ | ||
/* | ||
* If acpi_disabled, bail out | ||
*/ | ||
if (acpi_disabled) | ||
return; | ||
|
||
/* | ||
* Initialize the ACPI boot-time table parser. | ||
*/ | ||
if (acpi_table_init()) { | ||
disable_acpi(); | ||
return; | ||
} | ||
} | ||
|
||
static void __init acpi_process_madt(void) | ||
{ | ||
loongson_sysconf.nr_cpus = num_processors; | ||
} | ||
|
||
int __init acpi_boot_init(void) | ||
{ | ||
/* | ||
* If acpi_disabled, bail out | ||
*/ | ||
if (acpi_disabled) | ||
return -1; | ||
|
||
loongson_sysconf.boot_cpu_id = read_csr_cpuid(); | ||
|
||
/* | ||
* Process the Multiple APIC Description Table (MADT), if present | ||
*/ | ||
acpi_process_madt(); | ||
|
||
/* Do not enable ACPI SPCR console by default */ | ||
acpi_parse_spcr(earlycon_acpi_spcr_enable, false); | ||
|
||
return 0; | ||
} | ||
|
||
void __init arch_reserve_mem_area(acpi_physical_address addr, size_t size) | ||
{ | ||
memblock_reserve(addr, size); | ||
} |
Oops, something went wrong.