mirror of
https://github.com/torvalds/linux.git
synced 2024-11-10 14:11:52 +00:00
LoongArch: Add FDT booting support from efi system table
Since commit 40cd01a9c324("efi/loongarch: libstub: remove dependency on flattened DT"), we can parse the FDT from efi system table. And now, LoongArch is coming to support booting with FDT, so we add the relevant booting support as well as parameter parsing. Signed-off-by: Binbin Zhou <zhoubinbin@loongson.cn> Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
This commit is contained in:
parent
a275a82dcd
commit
88d4d957ed
@ -111,6 +111,8 @@ config LOONGARCH
|
|||||||
select MODULES_USE_ELF_RELA if MODULES
|
select MODULES_USE_ELF_RELA if MODULES
|
||||||
select NEED_PER_CPU_EMBED_FIRST_CHUNK
|
select NEED_PER_CPU_EMBED_FIRST_CHUNK
|
||||||
select NEED_PER_CPU_PAGE_FIRST_CHUNK
|
select NEED_PER_CPU_PAGE_FIRST_CHUNK
|
||||||
|
select OF
|
||||||
|
select OF_EARLY_FLATTREE
|
||||||
select PCI
|
select PCI
|
||||||
select PCI_DOMAINS_GENERIC
|
select PCI_DOMAINS_GENERIC
|
||||||
select PCI_ECAM if ACPI
|
select PCI_ECAM if ACPI
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
void __init efi_init(void);
|
void __init efi_init(void);
|
||||||
void __init efi_runtime_init(void);
|
void __init efi_runtime_init(void);
|
||||||
|
void __init *efi_fdt_pointer(void);
|
||||||
void efifb_setup_from_dmi(struct screen_info *si, const char *opt);
|
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_IRQ_FLAGS_MASK 0x00000004 /* Bit 2: CSR.CRMD.IE */
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
extern unsigned long eentry;
|
extern unsigned long eentry;
|
||||||
extern unsigned long tlbrentry;
|
extern unsigned long tlbrentry;
|
||||||
|
extern char init_command_line[COMMAND_LINE_SIZE];
|
||||||
extern void tlb_init(int cpu);
|
extern void tlb_init(int cpu);
|
||||||
extern void cpu_cache_init(void);
|
extern void cpu_cache_init(void);
|
||||||
extern void cache_error_setup(void);
|
extern void cache_error_setup(void);
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
#include <linux/irq.h>
|
#include <linux/irq.h>
|
||||||
#include <linux/irqdomain.h>
|
#include <linux/irqdomain.h>
|
||||||
#include <linux/memblock.h>
|
#include <linux/memblock.h>
|
||||||
|
#include <linux/of_fdt.h>
|
||||||
#include <linux/serial_core.h>
|
#include <linux/serial_core.h>
|
||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
#include <asm/numa.h>
|
#include <asm/numa.h>
|
||||||
@ -145,14 +146,14 @@ void __init acpi_boot_table_init(void)
|
|||||||
* If acpi_disabled, bail out
|
* If acpi_disabled, bail out
|
||||||
*/
|
*/
|
||||||
if (acpi_disabled)
|
if (acpi_disabled)
|
||||||
return;
|
goto fdt_earlycon;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initialize the ACPI boot-time table parser.
|
* Initialize the ACPI boot-time table parser.
|
||||||
*/
|
*/
|
||||||
if (acpi_table_init()) {
|
if (acpi_table_init()) {
|
||||||
disable_acpi();
|
disable_acpi();
|
||||||
return;
|
goto fdt_earlycon;
|
||||||
}
|
}
|
||||||
|
|
||||||
loongson_sysconf.boot_cpu_id = read_csr_cpuid();
|
loongson_sysconf.boot_cpu_id = read_csr_cpuid();
|
||||||
@ -164,6 +165,12 @@ void __init acpi_boot_table_init(void)
|
|||||||
|
|
||||||
/* Do not enable ACPI SPCR console by default */
|
/* Do not enable ACPI SPCR console by default */
|
||||||
acpi_parse_spcr(earlycon_acpi_spcr_enable, false);
|
acpi_parse_spcr(earlycon_acpi_spcr_enable, false);
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
fdt_earlycon:
|
||||||
|
if (earlycon_acpi_spcr_enable)
|
||||||
|
early_init_dt_scan_chosen_stdout();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_ACPI_NUMA
|
#ifdef CONFIG_ACPI_NUMA
|
||||||
|
@ -28,16 +28,29 @@ static unsigned long efi_nr_tables;
|
|||||||
static unsigned long efi_config_table;
|
static unsigned long efi_config_table;
|
||||||
|
|
||||||
static unsigned long __initdata boot_memmap = EFI_INVALID_TABLE_ADDR;
|
static unsigned long __initdata boot_memmap = EFI_INVALID_TABLE_ADDR;
|
||||||
|
static unsigned long __initdata fdt_pointer = EFI_INVALID_TABLE_ADDR;
|
||||||
|
|
||||||
static efi_system_table_t *efi_systab;
|
static efi_system_table_t *efi_systab;
|
||||||
static efi_config_table_type_t arch_tables[] __initdata = {
|
static efi_config_table_type_t arch_tables[] __initdata = {
|
||||||
{LINUX_EFI_BOOT_MEMMAP_GUID, &boot_memmap, "MEMMAP" },
|
{LINUX_EFI_BOOT_MEMMAP_GUID, &boot_memmap, "MEMMAP" },
|
||||||
|
{DEVICE_TREE_GUID, &fdt_pointer, "FDTPTR" },
|
||||||
{},
|
{},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void __init *efi_fdt_pointer(void)
|
||||||
|
{
|
||||||
|
if (!efi_systab)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (fdt_pointer == EFI_INVALID_TABLE_ADDR)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return early_memremap_ro(fdt_pointer, SZ_64K);
|
||||||
|
}
|
||||||
|
|
||||||
void __init efi_runtime_init(void)
|
void __init efi_runtime_init(void)
|
||||||
{
|
{
|
||||||
if (!efi_enabled(EFI_BOOT))
|
if (!efi_enabled(EFI_BOOT) || !efi_systab->runtime)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (efi_runtime_disabled()) {
|
if (efi_runtime_disabled()) {
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#include <asm/early_ioremap.h>
|
#include <asm/early_ioremap.h>
|
||||||
#include <asm/bootinfo.h>
|
#include <asm/bootinfo.h>
|
||||||
#include <asm/loongson.h>
|
#include <asm/loongson.h>
|
||||||
|
#include <asm/setup.h>
|
||||||
|
|
||||||
u64 efi_system_table;
|
u64 efi_system_table;
|
||||||
struct loongson_system_configuration loongson_sysconf;
|
struct loongson_system_configuration loongson_sysconf;
|
||||||
@ -27,6 +28,7 @@ void __init init_environ(void)
|
|||||||
clear_bit(EFI_BOOT, &efi.flags);
|
clear_bit(EFI_BOOT, &efi.flags);
|
||||||
|
|
||||||
strscpy(boot_command_line, cmdline, COMMAND_LINE_SIZE);
|
strscpy(boot_command_line, cmdline, COMMAND_LINE_SIZE);
|
||||||
|
strscpy(init_command_line, cmdline, COMMAND_LINE_SIZE);
|
||||||
early_memunmap(cmdline, COMMAND_LINE_SIZE);
|
early_memunmap(cmdline, COMMAND_LINE_SIZE);
|
||||||
|
|
||||||
efi_system_table = fw_arg2;
|
efi_system_table = fw_arg2;
|
||||||
|
@ -388,6 +388,21 @@ static void __init numa_default_distance(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* fake_numa_init() - For Non-ACPI systems
|
||||||
|
* Return: 0 on success, -errno on failure.
|
||||||
|
*/
|
||||||
|
static int __init fake_numa_init(void)
|
||||||
|
{
|
||||||
|
phys_addr_t start = memblock_start_of_DRAM();
|
||||||
|
phys_addr_t end = memblock_end_of_DRAM() - 1;
|
||||||
|
|
||||||
|
node_set(0, numa_nodes_parsed);
|
||||||
|
pr_info("Faking a node at [mem %pap-%pap]\n", &start, &end);
|
||||||
|
|
||||||
|
return numa_add_memblk(0, start, end + 1);
|
||||||
|
}
|
||||||
|
|
||||||
int __init init_numa_memory(void)
|
int __init init_numa_memory(void)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@ -404,7 +419,7 @@ int __init init_numa_memory(void)
|
|||||||
memset(&numa_meminfo, 0, sizeof(numa_meminfo));
|
memset(&numa_meminfo, 0, sizeof(numa_meminfo));
|
||||||
|
|
||||||
/* Parse SRAT and SLIT if provided by firmware. */
|
/* Parse SRAT and SLIT if provided by firmware. */
|
||||||
ret = acpi_numa_init();
|
ret = acpi_disabled ? fake_numa_init() : acpi_numa_init();
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
@ -28,6 +28,9 @@
|
|||||||
#include <linux/sizes.h>
|
#include <linux/sizes.h>
|
||||||
#include <linux/device.h>
|
#include <linux/device.h>
|
||||||
#include <linux/dma-map-ops.h>
|
#include <linux/dma-map-ops.h>
|
||||||
|
#include <linux/libfdt.h>
|
||||||
|
#include <linux/of_fdt.h>
|
||||||
|
#include <linux/of_address.h>
|
||||||
#include <linux/swiotlb.h>
|
#include <linux/swiotlb.h>
|
||||||
|
|
||||||
#include <asm/addrspace.h>
|
#include <asm/addrspace.h>
|
||||||
@ -69,6 +72,7 @@ static const char dmi_empty_string[] = " ";
|
|||||||
*
|
*
|
||||||
* These are initialized so they are in the .data section
|
* These are initialized so they are in the .data section
|
||||||
*/
|
*/
|
||||||
|
char init_command_line[COMMAND_LINE_SIZE] __initdata;
|
||||||
|
|
||||||
static int num_standard_resources;
|
static int num_standard_resources;
|
||||||
static struct resource *standard_resources;
|
static struct resource *standard_resources;
|
||||||
@ -253,6 +257,58 @@ static void __init arch_parse_crashkernel(void)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void __init fdt_setup(void)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_OF_EARLY_FLATTREE
|
||||||
|
void *fdt_pointer;
|
||||||
|
|
||||||
|
/* ACPI-based systems do not require parsing fdt */
|
||||||
|
if (acpi_os_get_root_pointer())
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Look for a device tree configuration table entry */
|
||||||
|
fdt_pointer = efi_fdt_pointer();
|
||||||
|
if (!fdt_pointer || fdt_check_header(fdt_pointer))
|
||||||
|
return;
|
||||||
|
|
||||||
|
early_init_dt_scan(fdt_pointer);
|
||||||
|
early_init_fdt_reserve_self();
|
||||||
|
|
||||||
|
max_low_pfn = PFN_PHYS(memblock_end_of_DRAM());
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __init bootcmdline_init(char **cmdline_p)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* If CONFIG_CMDLINE_FORCE is enabled then initializing the command line
|
||||||
|
* is trivial - we simply use the built-in command line unconditionally &
|
||||||
|
* unmodified.
|
||||||
|
*/
|
||||||
|
if (IS_ENABLED(CONFIG_CMDLINE_FORCE)) {
|
||||||
|
strscpy(boot_command_line, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_OF_FLATTREE
|
||||||
|
/*
|
||||||
|
* If CONFIG_CMDLINE_BOOTLOADER is enabled and we are in FDT-based system,
|
||||||
|
* the boot_command_line will be overwritten by early_init_dt_scan_chosen().
|
||||||
|
* So we need to append init_command_line (the original copy of boot_command_line)
|
||||||
|
* to boot_command_line.
|
||||||
|
*/
|
||||||
|
if (initial_boot_params) {
|
||||||
|
if (boot_command_line[0])
|
||||||
|
strlcat(boot_command_line, " ", COMMAND_LINE_SIZE);
|
||||||
|
|
||||||
|
strlcat(boot_command_line, init_command_line, COMMAND_LINE_SIZE);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
out:
|
||||||
|
*cmdline_p = boot_command_line;
|
||||||
|
}
|
||||||
|
|
||||||
void __init platform_init(void)
|
void __init platform_init(void)
|
||||||
{
|
{
|
||||||
arch_reserve_vmcore();
|
arch_reserve_vmcore();
|
||||||
@ -265,6 +321,7 @@ void __init platform_init(void)
|
|||||||
acpi_gbl_use_default_register_widths = false;
|
acpi_gbl_use_default_register_widths = false;
|
||||||
acpi_boot_table_init();
|
acpi_boot_table_init();
|
||||||
#endif
|
#endif
|
||||||
|
unflatten_and_copy_device_tree();
|
||||||
|
|
||||||
#ifdef CONFIG_NUMA
|
#ifdef CONFIG_NUMA
|
||||||
init_numa_memory();
|
init_numa_memory();
|
||||||
@ -297,6 +354,8 @@ static void __init arch_mem_init(char **cmdline_p)
|
|||||||
|
|
||||||
check_kernel_sections_mem();
|
check_kernel_sections_mem();
|
||||||
|
|
||||||
|
early_init_fdt_scan_reserved_mem();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* In order to reduce the possibility of kernel panic when failed to
|
* In order to reduce the possibility of kernel panic when failed to
|
||||||
* get IO TLB memory under CONFIG_SWIOTLB, it is better to allocate
|
* get IO TLB memory under CONFIG_SWIOTLB, it is better to allocate
|
||||||
@ -422,12 +481,13 @@ static void __init prefill_possible_map(void)
|
|||||||
void __init setup_arch(char **cmdline_p)
|
void __init setup_arch(char **cmdline_p)
|
||||||
{
|
{
|
||||||
cpu_probe();
|
cpu_probe();
|
||||||
*cmdline_p = boot_command_line;
|
|
||||||
|
|
||||||
init_environ();
|
init_environ();
|
||||||
efi_init();
|
efi_init();
|
||||||
|
fdt_setup();
|
||||||
memblock_init();
|
memblock_init();
|
||||||
pagetable_init();
|
pagetable_init();
|
||||||
|
bootcmdline_init(cmdline_p);
|
||||||
parse_early_param();
|
parse_early_param();
|
||||||
reserve_initrd_mem();
|
reserve_initrd_mem();
|
||||||
|
|
||||||
|
@ -180,8 +180,42 @@ irqreturn_t loongson_ipi_interrupt(int irq, void *dev)
|
|||||||
return IRQ_HANDLED;
|
return IRQ_HANDLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void __init fdt_smp_setup(void)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_OF
|
||||||
|
unsigned int cpu, cpuid;
|
||||||
|
struct device_node *node = NULL;
|
||||||
|
|
||||||
|
for_each_of_cpu_node(node) {
|
||||||
|
if (!of_device_is_available(node))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
cpuid = of_get_cpu_hwid(node, 0);
|
||||||
|
if (cpuid >= nr_cpu_ids)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (cpuid == loongson_sysconf.boot_cpu_id) {
|
||||||
|
cpu = 0;
|
||||||
|
numa_add_cpu(cpu);
|
||||||
|
} else {
|
||||||
|
cpu = cpumask_next_zero(-1, cpu_present_mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
num_processors++;
|
||||||
|
set_cpu_possible(cpu, true);
|
||||||
|
set_cpu_present(cpu, true);
|
||||||
|
__cpu_number_map[cpuid] = cpu;
|
||||||
|
__cpu_logical_map[cpu] = cpuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
loongson_sysconf.nr_cpus = num_processors;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void __init loongson_smp_setup(void)
|
void __init loongson_smp_setup(void)
|
||||||
{
|
{
|
||||||
|
fdt_smp_setup();
|
||||||
|
|
||||||
cpu_data[0].core = cpu_logical_map(0) % loongson_sysconf.cores_per_package;
|
cpu_data[0].core = cpu_logical_map(0) % loongson_sysconf.cores_per_package;
|
||||||
cpu_data[0].package = cpu_logical_map(0) / loongson_sysconf.cores_per_package;
|
cpu_data[0].package = cpu_logical_map(0) / loongson_sysconf.cores_per_package;
|
||||||
|
|
||||||
|
@ -26,9 +26,12 @@ void pcibios_add_bus(struct pci_bus *bus)
|
|||||||
|
|
||||||
int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
|
int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
|
||||||
{
|
{
|
||||||
struct pci_config_window *cfg = bridge->bus->sysdata;
|
struct acpi_device *adev = NULL;
|
||||||
struct acpi_device *adev = to_acpi_device(cfg->parent);
|
|
||||||
struct device *bus_dev = &bridge->bus->dev;
|
struct device *bus_dev = &bridge->bus->dev;
|
||||||
|
struct pci_config_window *cfg = bridge->bus->sysdata;
|
||||||
|
|
||||||
|
if (!acpi_disabled)
|
||||||
|
adev = to_acpi_device(cfg->parent);
|
||||||
|
|
||||||
ACPI_COMPANION_SET(&bridge->dev, adev);
|
ACPI_COMPANION_SET(&bridge->dev, adev);
|
||||||
set_dev_node(bus_dev, pa_to_nid(cfg->res.start));
|
set_dev_node(bus_dev, pa_to_nid(cfg->res.start));
|
||||||
|
Loading…
Reference in New Issue
Block a user