^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * CPU kernel entry/exit control
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2013 ARM Ltd.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/acpi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/cache.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <asm/acpi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <asm/cpu_ops.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <asm/smp_plat.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) extern const struct cpu_operations smp_spin_table_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #ifdef CONFIG_ARM64_ACPI_PARKING_PROTOCOL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) extern const struct cpu_operations acpi_parking_protocol_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) extern const struct cpu_operations cpu_psci_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) static const struct cpu_operations *cpu_ops[NR_CPUS] __ro_after_init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) static const struct cpu_operations *const dt_supported_cpu_ops[] __initconst = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) &smp_spin_table_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) &cpu_psci_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) static const struct cpu_operations *const acpi_supported_cpu_ops[] __initconst = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #ifdef CONFIG_ARM64_ACPI_PARKING_PROTOCOL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) &acpi_parking_protocol_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) &cpu_psci_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) static const struct cpu_operations * __init cpu_get_ops(const char *name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) const struct cpu_operations *const *ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) ops = acpi_disabled ? dt_supported_cpu_ops : acpi_supported_cpu_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) while (*ops) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) if (!strcmp(name, (*ops)->name))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) return *ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) ops++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) static const char *__init cpu_read_enable_method(int cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) const char *enable_method;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) if (acpi_disabled) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) struct device_node *dn = of_get_cpu_node(cpu, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) if (!dn) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) if (!cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) pr_err("Failed to find device node for boot cpu\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) enable_method = of_get_property(dn, "enable-method", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) if (!enable_method) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) * The boot CPU may not have an enable method (e.g.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) * when spin-table is used for secondaries).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) * Don't warn spuriously.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) if (cpu != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) pr_err("%pOF: missing enable-method property\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) dn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) of_node_put(dn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) enable_method = acpi_get_enable_method(cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) if (!enable_method) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) * In ACPI systems the boot CPU does not require
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) * checking the enable method since for some
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) * boot protocol (ie parking protocol) it need not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) * be initialized. Don't warn spuriously.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) if (cpu != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) pr_err("Unsupported ACPI enable-method\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) return enable_method;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) * Read a cpu's enable method and record it in cpu_ops.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) int __init init_cpu_ops(int cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) const char *enable_method = cpu_read_enable_method(cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) if (!enable_method)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) cpu_ops[cpu] = cpu_get_ops(enable_method);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) if (!cpu_ops[cpu]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) pr_warn("Unsupported enable-method: %s\n", enable_method);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) const struct cpu_operations *get_cpu_ops(int cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) return cpu_ops[cpu];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) }