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