1 /* 2 * ARM64 Specific Low-Level ACPI Boot Support 3 * 4 * Copyright (C) 2013-2014, Linaro Ltd. 5 * Author: Al Stone <al.stone@linaro.org> 6 * Author: Graeme Gregory <graeme.gregory@linaro.org> 7 * Author: Hanjun Guo <hanjun.guo@linaro.org> 8 * Author: Tomasz Nowicki <tomasz.nowicki@linaro.org> 9 * Author: Naresh Bhat <naresh.bhat@linaro.org> 10 * 11 * This program is free software; you can redistribute it and/or modify 12 * it under the terms of the GNU General Public License version 2 as 13 * published by the Free Software Foundation. 14 */ 15 16 #define pr_fmt(fmt) "ACPI: " fmt 17 18 #include <linux/acpi.h> 19 #include <linux/bootmem.h> 20 #include <linux/cpumask.h> 21 #include <linux/init.h> 22 #include <linux/irq.h> 23 #include <linux/irqdomain.h> 24 #include <linux/memblock.h> 25 #include <linux/of_fdt.h> 26 #include <linux/smp.h> 27 28 #include <asm/cputype.h> 29 #include <asm/cpu_ops.h> 30 #include <asm/smp_plat.h> 31 32 int acpi_noirq = 1; /* skip ACPI IRQ initialization */ 33 int acpi_disabled = 1; 34 EXPORT_SYMBOL(acpi_disabled); 35 36 int acpi_pci_disabled = 1; /* skip ACPI PCI scan and IRQ initialization */ 37 EXPORT_SYMBOL(acpi_pci_disabled); 38 39 static bool param_acpi_off __initdata; 40 static bool param_acpi_force __initdata; 41 42 static int __init parse_acpi(char *arg) 43 { 44 if (!arg) 45 return -EINVAL; 46 47 /* "acpi=off" disables both ACPI table parsing and interpreter */ 48 if (strcmp(arg, "off") == 0) 49 param_acpi_off = true; 50 else if (strcmp(arg, "force") == 0) /* force ACPI to be enabled */ 51 param_acpi_force = true; 52 else 53 return -EINVAL; /* Core will print when we return error */ 54 55 return 0; 56 } 57 early_param("acpi", parse_acpi); 58 59 static int __init dt_scan_depth1_nodes(unsigned long node, 60 const char *uname, int depth, 61 void *data) 62 { 63 /* 64 * Return 1 as soon as we encounter a node at depth 1 that is 65 * not the /chosen node. 66 */ 67 if (depth == 1 && (strcmp(uname, "chosen") != 0)) 68 return 1; 69 return 0; 70 } 71 72 /* 73 * __acpi_map_table() will be called before page_init(), so early_ioremap() 74 * or early_memremap() should be called here to for ACPI table mapping. 75 */ 76 char *__init __acpi_map_table(unsigned long phys, unsigned long size) 77 { 78 if (!size) 79 return NULL; 80 81 return early_memremap(phys, size); 82 } 83 84 void __init __acpi_unmap_table(char *map, unsigned long size) 85 { 86 if (!map || !size) 87 return; 88 89 early_memunmap(map, size); 90 } 91 92 bool __init acpi_psci_present(void) 93 { 94 return acpi_gbl_FADT.arm_boot_flags & ACPI_FADT_PSCI_COMPLIANT; 95 } 96 97 /* Whether HVC must be used instead of SMC as the PSCI conduit */ 98 bool __init acpi_psci_use_hvc(void) 99 { 100 return acpi_gbl_FADT.arm_boot_flags & ACPI_FADT_PSCI_USE_HVC; 101 } 102 103 /* 104 * acpi_fadt_sanity_check() - Check FADT presence and carry out sanity 105 * checks on it 106 * 107 * Return 0 on success, <0 on failure 108 */ 109 static int __init acpi_fadt_sanity_check(void) 110 { 111 struct acpi_table_header *table; 112 struct acpi_table_fadt *fadt; 113 acpi_status status; 114 acpi_size tbl_size; 115 int ret = 0; 116 117 /* 118 * FADT is required on arm64; retrieve it to check its presence 119 * and carry out revision and ACPI HW reduced compliancy tests 120 */ 121 status = acpi_get_table_with_size(ACPI_SIG_FADT, 0, &table, &tbl_size); 122 if (ACPI_FAILURE(status)) { 123 const char *msg = acpi_format_exception(status); 124 125 pr_err("Failed to get FADT table, %s\n", msg); 126 return -ENODEV; 127 } 128 129 fadt = (struct acpi_table_fadt *)table; 130 131 /* 132 * Revision in table header is the FADT Major revision, and there 133 * is a minor revision of FADT which was introduced by ACPI 5.1, 134 * we only deal with ACPI 5.1 or newer revision to get GIC and SMP 135 * boot protocol configuration data. 136 */ 137 if (table->revision < 5 || 138 (table->revision == 5 && fadt->minor_revision < 1)) { 139 pr_err("Unsupported FADT revision %d.%d, should be 5.1+\n", 140 table->revision, fadt->minor_revision); 141 ret = -EINVAL; 142 goto out; 143 } 144 145 if (!(fadt->flags & ACPI_FADT_HW_REDUCED)) { 146 pr_err("FADT not ACPI hardware reduced compliant\n"); 147 ret = -EINVAL; 148 } 149 150 out: 151 /* 152 * acpi_get_table_with_size() creates FADT table mapping that 153 * should be released after parsing and before resuming boot 154 */ 155 early_acpi_os_unmap_memory(table, tbl_size); 156 return ret; 157 } 158 159 /* 160 * acpi_boot_table_init() called from setup_arch(), always. 161 * 1. find RSDP and get its address, and then find XSDT 162 * 2. extract all tables and checksums them all 163 * 3. check ACPI FADT revision 164 * 4. check ACPI FADT HW reduced flag 165 * 166 * We can parse ACPI boot-time tables such as MADT after 167 * this function is called. 168 * 169 * On return ACPI is enabled if either: 170 * 171 * - ACPI tables are initialized and sanity checks passed 172 * - acpi=force was passed in the command line and ACPI was not disabled 173 * explicitly through acpi=off command line parameter 174 * 175 * ACPI is disabled on function return otherwise 176 */ 177 void __init acpi_boot_table_init(void) 178 { 179 /* 180 * Enable ACPI instead of device tree unless 181 * - ACPI has been disabled explicitly (acpi=off), or 182 * - the device tree is not empty (it has more than just a /chosen node) 183 * and ACPI has not been force enabled (acpi=force) 184 */ 185 if (param_acpi_off || 186 (!param_acpi_force && of_scan_flat_dt(dt_scan_depth1_nodes, NULL))) 187 return; 188 189 /* 190 * ACPI is disabled at this point. Enable it in order to parse 191 * the ACPI tables and carry out sanity checks 192 */ 193 enable_acpi(); 194 195 /* 196 * If ACPI tables are initialized and FADT sanity checks passed, 197 * leave ACPI enabled and carry on booting; otherwise disable ACPI 198 * on initialization error. 199 * If acpi=force was passed on the command line it forces ACPI 200 * to be enabled even if its initialization failed. 201 */ 202 if (acpi_table_init() || acpi_fadt_sanity_check()) { 203 pr_err("Failed to init ACPI tables\n"); 204 if (!param_acpi_force) 205 disable_acpi(); 206 } 207 } 208 209 void __init acpi_gic_init(void) 210 { 211 struct acpi_table_header *table; 212 acpi_status status; 213 acpi_size tbl_size; 214 int err; 215 216 if (acpi_disabled) 217 return; 218 219 status = acpi_get_table_with_size(ACPI_SIG_MADT, 0, &table, &tbl_size); 220 if (ACPI_FAILURE(status)) { 221 const char *msg = acpi_format_exception(status); 222 223 pr_err("Failed to get MADT table, %s\n", msg); 224 return; 225 } 226 227 err = gic_v2_acpi_init(table); 228 if (err) 229 pr_err("Failed to initialize GIC IRQ controller"); 230 231 early_acpi_os_unmap_memory((char *)table, tbl_size); 232 } 233