]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
arm64: FFH: Move ACPI specific code into drivers/acpi/arm64/
authorSudeep Holla <sudeep.holla@arm.com>
Wed, 5 Jun 2024 13:14:58 +0000 (14:14 +0100)
committerCatalin Marinas <catalin.marinas@arm.com>
Thu, 13 Jun 2024 09:18:40 +0000 (10:18 +0100)
The ACPI FFH Opregion code can be moved out of arm64 arch code as
it just uses SMCCC. Move all the ACPI FFH Opregion code into
drivers/acpi/arm64/ffh.c

Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
Acked-by: Catalin Marinas <catalin.marinas@arm.com>
Acked-by: Hanjun Guo <guohanjun@huawei.com>
Link: https://lore.kernel.org/r/20240605131458.3341095-4-sudeep.holla@arm.com
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
arch/arm64/kernel/acpi.c
drivers/acpi/arm64/Makefile
drivers/acpi/arm64/ffh.c [new file with mode: 0644]

index e0e7b93c16cc430f5e60be3ebc23f58818c89d48..fd1917336d3ab857d0ed9c751abbc2298467f33d 100644 (file)
@@ -422,108 +422,3 @@ void arch_reserve_mem_area(acpi_physical_address addr, size_t size)
 {
        memblock_mark_nomap(addr, size);
 }
-
-#ifdef CONFIG_ACPI_FFH
-/*
- * Implements ARM64 specific callbacks to support ACPI FFH Operation Region as
- * specified in https://developer.arm.com/docs/den0048/latest
- */
-struct acpi_ffh_data {
-       struct acpi_ffh_info info;
-       void (*invoke_ffh_fn)(unsigned long a0, unsigned long a1,
-                             unsigned long a2, unsigned long a3,
-                             unsigned long a4, unsigned long a5,
-                             unsigned long a6, unsigned long a7,
-                             struct arm_smccc_res *args,
-                             struct arm_smccc_quirk *res);
-       void (*invoke_ffh64_fn)(const struct arm_smccc_1_2_regs *args,
-                               struct arm_smccc_1_2_regs *res);
-};
-
-int acpi_ffh_address_space_arch_setup(void *handler_ctxt, void **region_ctxt)
-{
-       enum arm_smccc_conduit conduit;
-       struct acpi_ffh_data *ffh_ctxt;
-
-       if (arm_smccc_get_version() < ARM_SMCCC_VERSION_1_2)
-               return -EOPNOTSUPP;
-
-       conduit = arm_smccc_1_1_get_conduit();
-       if (conduit == SMCCC_CONDUIT_NONE) {
-               pr_err("%s: invalid SMCCC conduit\n", __func__);
-               return -EOPNOTSUPP;
-       }
-
-       ffh_ctxt = kzalloc(sizeof(*ffh_ctxt), GFP_KERNEL);
-       if (!ffh_ctxt)
-               return -ENOMEM;
-
-       if (conduit == SMCCC_CONDUIT_SMC) {
-               ffh_ctxt->invoke_ffh_fn = __arm_smccc_smc;
-               ffh_ctxt->invoke_ffh64_fn = arm_smccc_1_2_smc;
-       } else {
-               ffh_ctxt->invoke_ffh_fn = __arm_smccc_hvc;
-               ffh_ctxt->invoke_ffh64_fn = arm_smccc_1_2_hvc;
-       }
-
-       memcpy(ffh_ctxt, handler_ctxt, sizeof(ffh_ctxt->info));
-
-       *region_ctxt = ffh_ctxt;
-       return AE_OK;
-}
-
-static bool acpi_ffh_smccc_owner_allowed(u32 fid)
-{
-       int owner = ARM_SMCCC_OWNER_NUM(fid);
-
-       if (owner == ARM_SMCCC_OWNER_STANDARD ||
-           owner == ARM_SMCCC_OWNER_SIP || owner == ARM_SMCCC_OWNER_OEM)
-               return true;
-
-       return false;
-}
-
-int acpi_ffh_address_space_arch_handler(acpi_integer *value, void *region_context)
-{
-       int ret = 0;
-       struct acpi_ffh_data *ffh_ctxt = region_context;
-
-       if (ffh_ctxt->info.offset == 0) {
-               /* SMC/HVC 32bit call */
-               struct arm_smccc_res res;
-               u32 a[8] = { 0 }, *ptr = (u32 *)value;
-
-               if (!ARM_SMCCC_IS_FAST_CALL(*ptr) || ARM_SMCCC_IS_64(*ptr) ||
-                   !acpi_ffh_smccc_owner_allowed(*ptr) ||
-                   ffh_ctxt->info.length > 32) {
-                       ret = AE_ERROR;
-               } else {
-                       int idx, len = ffh_ctxt->info.length >> 2;
-
-                       for (idx = 0; idx < len; idx++)
-                               a[idx] = *(ptr + idx);
-
-                       ffh_ctxt->invoke_ffh_fn(a[0], a[1], a[2], a[3], a[4],
-                                               a[5], a[6], a[7], &res, NULL);
-                       memcpy(value, &res, sizeof(res));
-               }
-
-       } else if (ffh_ctxt->info.offset == 1) {
-               /* SMC/HVC 64bit call */
-               struct arm_smccc_1_2_regs *r = (struct arm_smccc_1_2_regs *)value;
-
-               if (!ARM_SMCCC_IS_FAST_CALL(r->a0) || !ARM_SMCCC_IS_64(r->a0) ||
-                   !acpi_ffh_smccc_owner_allowed(r->a0) ||
-                   ffh_ctxt->info.length > sizeof(*r)) {
-                       ret = AE_ERROR;
-               } else {
-                       ffh_ctxt->invoke_ffh64_fn(r, r);
-                       memcpy(value, r, ffh_ctxt->info.length);
-               }
-       } else {
-               ret = AE_ERROR;
-       }
-
-       return ret;
-}
-#endif /* CONFIG_ACPI_FFH */
index 2efee23f00b4dbe57d8b247bb2926de9f6452b3f..05ecde9eaabe954cf5ebb5a8fb64ced34791a790 100644 (file)
@@ -1,6 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0-only
 obj-$(CONFIG_ACPI_AGDI)        += agdi.o
 obj-$(CONFIG_ACPI_APMT)        += apmt.o
+obj-$(CONFIG_ACPI_FFH)         += ffh.o
 obj-$(CONFIG_ACPI_GTDT)        += gtdt.o
 obj-$(CONFIG_ACPI_IORT)        += iort.o
 obj-$(CONFIG_ACPI_PROCESSOR_IDLE) += cpuidle.o
diff --git a/drivers/acpi/arm64/ffh.c b/drivers/acpi/arm64/ffh.c
new file mode 100644 (file)
index 0000000..877edc6
--- /dev/null
@@ -0,0 +1,107 @@
+// SPDX-License-Identifier: GPL-2.0-only
+#include <linux/acpi.h>
+#include <linux/arm-smccc.h>
+#include <linux/slab.h>
+
+/*
+ * Implements ARM64 specific callbacks to support ACPI FFH Operation Region as
+ * specified in https://developer.arm.com/docs/den0048/latest
+ */
+struct acpi_ffh_data {
+       struct acpi_ffh_info info;
+       void (*invoke_ffh_fn)(unsigned long a0, unsigned long a1,
+                             unsigned long a2, unsigned long a3,
+                             unsigned long a4, unsigned long a5,
+                             unsigned long a6, unsigned long a7,
+                             struct arm_smccc_res *args,
+                             struct arm_smccc_quirk *res);
+       void (*invoke_ffh64_fn)(const struct arm_smccc_1_2_regs *args,
+                               struct arm_smccc_1_2_regs *res);
+};
+
+int acpi_ffh_address_space_arch_setup(void *handler_ctxt, void **region_ctxt)
+{
+       enum arm_smccc_conduit conduit;
+       struct acpi_ffh_data *ffh_ctxt;
+
+       if (arm_smccc_get_version() < ARM_SMCCC_VERSION_1_2)
+               return -EOPNOTSUPP;
+
+       conduit = arm_smccc_1_1_get_conduit();
+       if (conduit == SMCCC_CONDUIT_NONE) {
+               pr_err("%s: invalid SMCCC conduit\n", __func__);
+               return -EOPNOTSUPP;
+       }
+
+       ffh_ctxt = kzalloc(sizeof(*ffh_ctxt), GFP_KERNEL);
+       if (!ffh_ctxt)
+               return -ENOMEM;
+
+       if (conduit == SMCCC_CONDUIT_SMC) {
+               ffh_ctxt->invoke_ffh_fn = __arm_smccc_smc;
+               ffh_ctxt->invoke_ffh64_fn = arm_smccc_1_2_smc;
+       } else {
+               ffh_ctxt->invoke_ffh_fn = __arm_smccc_hvc;
+               ffh_ctxt->invoke_ffh64_fn = arm_smccc_1_2_hvc;
+       }
+
+       memcpy(ffh_ctxt, handler_ctxt, sizeof(ffh_ctxt->info));
+
+       *region_ctxt = ffh_ctxt;
+       return AE_OK;
+}
+
+static bool acpi_ffh_smccc_owner_allowed(u32 fid)
+{
+       int owner = ARM_SMCCC_OWNER_NUM(fid);
+
+       if (owner == ARM_SMCCC_OWNER_STANDARD ||
+           owner == ARM_SMCCC_OWNER_SIP || owner == ARM_SMCCC_OWNER_OEM)
+               return true;
+
+       return false;
+}
+
+int acpi_ffh_address_space_arch_handler(acpi_integer *value, void *region_context)
+{
+       int ret = 0;
+       struct acpi_ffh_data *ffh_ctxt = region_context;
+
+       if (ffh_ctxt->info.offset == 0) {
+               /* SMC/HVC 32bit call */
+               struct arm_smccc_res res;
+               u32 a[8] = { 0 }, *ptr = (u32 *)value;
+
+               if (!ARM_SMCCC_IS_FAST_CALL(*ptr) || ARM_SMCCC_IS_64(*ptr) ||
+                   !acpi_ffh_smccc_owner_allowed(*ptr) ||
+                   ffh_ctxt->info.length > 32) {
+                       ret = AE_ERROR;
+               } else {
+                       int idx, len = ffh_ctxt->info.length >> 2;
+
+                       for (idx = 0; idx < len; idx++)
+                               a[idx] = *(ptr + idx);
+
+                       ffh_ctxt->invoke_ffh_fn(a[0], a[1], a[2], a[3], a[4],
+                                               a[5], a[6], a[7], &res, NULL);
+                       memcpy(value, &res, sizeof(res));
+               }
+
+       } else if (ffh_ctxt->info.offset == 1) {
+               /* SMC/HVC 64bit call */
+               struct arm_smccc_1_2_regs *r = (struct arm_smccc_1_2_regs *)value;
+
+               if (!ARM_SMCCC_IS_FAST_CALL(r->a0) || !ARM_SMCCC_IS_64(r->a0) ||
+                   !acpi_ffh_smccc_owner_allowed(r->a0) ||
+                   ffh_ctxt->info.length > sizeof(*r)) {
+                       ret = AE_ERROR;
+               } else {
+                       ffh_ctxt->invoke_ffh64_fn(r, r);
+                       memcpy(value, r, ffh_ctxt->info.length);
+               }
+       } else {
+               ret = AE_ERROR;
+       }
+
+       return ret;
+}