xref: /openbmc/linux/arch/loongarch/kernel/acpi.c (revision 628c3bb40e9a8cefc0a6fde28b7b66bfe46d1dc2)
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