aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/arm64/arm64/machdep.c71
-rw-r--r--sys/arm64/arm64/mp_machdep.c34
-rw-r--r--sys/arm64/arm64/nexus.c5
-rw-r--r--sys/arm64/include/machdep.h8
4 files changed, 97 insertions, 21 deletions
diff --git a/sys/arm64/arm64/machdep.c b/sys/arm64/arm64/machdep.c
index 19d398192924..90b5f3d47e05 100644
--- a/sys/arm64/arm64/machdep.c
+++ b/sys/arm64/arm64/machdep.c
@@ -25,6 +25,7 @@
*
*/
+#include "opt_acpi.h"
#include "opt_platform.h"
#include "opt_ddb.h"
@@ -82,11 +83,19 @@ __FBSDID("$FreeBSD$");
#include <machine/vfp.h>
#endif
+#ifdef DEV_ACPI
+#include <contrib/dev/acpica/include/acpi.h>
+#include <machine/acpica_machdep.h>
+#endif
+
#ifdef FDT
#include <dev/fdt/fdt_common.h>
#include <dev/ofw/openfirm.h>
#endif
+
+enum arm64_bus arm64_bus_method = ARM64_BUS_NONE;
+
struct pcpu __pcpu[MAXCPU];
static struct trapframe proc0_tf;
@@ -802,6 +811,61 @@ try_load_dtb(caddr_t kmdp)
}
#endif
+static bool
+bus_probe(void)
+{
+ bool has_acpi, has_fdt;
+ char *order, *env;
+
+ has_acpi = has_fdt = false;
+
+#ifdef FDT
+ has_fdt = (OF_peer(0) != 0);
+#endif
+#ifdef DEV_ACPI
+ has_acpi = (acpi_find_table(ACPI_SIG_SPCR) != 0);
+#endif
+
+ env = kern_getenv("kern.cfg.order");
+ if (env != NULL) {
+ order = env;
+ while (order != NULL) {
+ if (has_acpi &&
+ strncmp(order, "acpi", 4) == 0 &&
+ (order[4] == ',' || order[4] == '\0')) {
+ arm64_bus_method = ARM64_BUS_ACPI;
+ break;
+ }
+ if (has_fdt &&
+ strncmp(order, "fdt", 3) == 0 &&
+ (order[3] == ',' || order[3] == '\0')) {
+ arm64_bus_method = ARM64_BUS_FDT;
+ break;
+ }
+ order = strchr(order, ',');
+ }
+ freeenv(env);
+
+ /* If we set the bus method it is valid */
+ if (arm64_bus_method != ARM64_BUS_NONE)
+ return (true);
+ }
+ /* If no order or an invalid order was set use the default */
+ if (arm64_bus_method == ARM64_BUS_NONE) {
+ if (has_fdt)
+ arm64_bus_method = ARM64_BUS_FDT;
+ else if (has_acpi)
+ arm64_bus_method = ARM64_BUS_ACPI;
+ }
+
+ /*
+ * If no option was set the default is valid, otherwise we are
+ * setting one to get cninit() working, then calling panic to tell
+ * the user about the invalid bus setup.
+ */
+ return (env == NULL);
+}
+
static void
cache_setup(void)
{
@@ -849,6 +913,7 @@ initarm(struct arm64_bootparams *abp)
vm_offset_t lastaddr;
caddr_t kmdp;
vm_paddr_t mem_len;
+ bool valid;
int i;
/* Set the module data location */
@@ -921,8 +986,14 @@ initarm(struct arm64_bootparams *abp)
devmap_bootstrap(0, NULL);
+ valid = bus_probe();
+
cninit();
+ if (!valid)
+ panic("Invalid bus configuration: %s",
+ kern_getenv("kern.cfg.order"));
+
init_proc0(abp->kern_stack);
msgbufinit(msgbufp, msgbufsize);
mutex_init();
diff --git a/sys/arm64/arm64/mp_machdep.c b/sys/arm64/arm64/mp_machdep.c
index b8e0394d2611..b0e182796461 100644
--- a/sys/arm64/arm64/mp_machdep.c
+++ b/sys/arm64/arm64/mp_machdep.c
@@ -52,6 +52,7 @@ __FBSDID("$FreeBSD$");
#include <vm/vm_kern.h>
#include <machine/debug_monitor.h>
+#include <machine/machdep.h>
#include <machine/intr.h>
#include <machine/smp.h>
#ifdef VFP
@@ -90,13 +91,6 @@ boolean_t ofw_cpu_reg(phandle_t node, u_int, cell_t *);
extern struct pcpu __pcpu[];
-static enum {
- CPUS_UNKNOWN,
-#ifdef FDT
- CPUS_FDT,
-#endif
-} cpu_enum_method;
-
static device_identify_t arm64_cpu_identify;
static device_probe_t arm64_cpu_probe;
static device_attach_t arm64_cpu_attach;
@@ -499,14 +493,14 @@ cpu_mp_start(void)
CPU_SET(0, &all_cpus);
- switch(cpu_enum_method) {
+ switch(arm64_bus_method) {
#ifdef FDT
- case CPUS_FDT:
+ case ARM64_BUS_FDT:
KASSERT(cpu0 >= 0, ("Current CPU was not found"));
ofw_cpu_early_foreach(cpu_init_fdt, true);
break;
#endif
- case CPUS_UNKNOWN:
+ default:
break;
}
}
@@ -544,15 +538,17 @@ cpu_mp_setmaxid(void)
#ifdef FDT
int cores;
- cores = ofw_cpu_early_foreach(cpu_find_cpu0_fdt, false);
- if (cores > 0) {
- cores = MIN(cores, MAXCPU);
- if (bootverbose)
- printf("Found %d CPUs in the device tree\n", cores);
- mp_ncpus = cores;
- mp_maxid = cores - 1;
- cpu_enum_method = CPUS_FDT;
- return;
+ if (arm64_bus_method == ARM64_BUS_FDT) {
+ cores = ofw_cpu_early_foreach(cpu_find_cpu0_fdt, false);
+ if (cores > 0) {
+ cores = MIN(cores, MAXCPU);
+ if (bootverbose)
+ printf("Found %d CPUs in the device tree\n",
+ cores);
+ mp_ncpus = cores;
+ mp_maxid = cores - 1;
+ return;
+ }
}
#endif
diff --git a/sys/arm64/arm64/nexus.c b/sys/arm64/arm64/nexus.c
index 2cd36ad68006..2495c4d91eff 100644
--- a/sys/arm64/arm64/nexus.c
+++ b/sys/arm64/arm64/nexus.c
@@ -55,6 +55,7 @@ __FBSDID("$FreeBSD$");
#include <sys/rman.h>
#include <sys/interrupt.h>
+#include <machine/machdep.h>
#include <machine/vmparam.h>
#include <machine/pcb.h>
#include <vm/vm.h>
@@ -411,7 +412,7 @@ static int
nexus_fdt_probe(device_t dev)
{
- if (OF_peer(0) == 0)
+ if (arm64_bus_method != ARM64_BUS_FDT)
return (ENXIO);
device_quiet(dev);
@@ -455,7 +456,7 @@ static int
nexus_acpi_probe(device_t dev)
{
- if (acpi_identify() != 0)
+ if (arm64_bus_method != ARM64_BUS_ACPI || acpi_identify() != 0)
return (ENXIO);
device_quiet(dev);
diff --git a/sys/arm64/include/machdep.h b/sys/arm64/include/machdep.h
index 0b1feaeab46e..b1554e98a921 100644
--- a/sys/arm64/include/machdep.h
+++ b/sys/arm64/include/machdep.h
@@ -37,6 +37,14 @@ struct arm64_bootparams {
vm_offset_t kern_l0pt; /* L1 page table for the kernel */
};
+enum arm64_bus {
+ ARM64_BUS_NONE,
+ ARM64_BUS_FDT,
+ ARM64_BUS_ACPI,
+};
+
+extern enum arm64_bus arm64_bus_method;
+
extern vm_paddr_t physmap[];
extern u_int physmap_idx;