forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-05-10 23fa18eaa71266feff7ba8d83022d9e1cc83c65a
kernel/arch/arm64/kernel/cpuidle.c
....@@ -1,12 +1,9 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * ARM64 CPU idle arch support
34 *
45 * Copyright (C) 2014 ARM Ltd.
56 * Author: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
6
- *
7
- * This program is free software; you can redistribute it and/or modify
8
- * it under the terms of the GNU General Public License version 2 as
9
- * published by the Free Software Foundation.
107 */
118
129 #include <linux/acpi.h>
....@@ -14,17 +11,18 @@
1411 #include <linux/cpu_pm.h>
1512 #include <linux/of.h>
1613 #include <linux/of_device.h>
14
+#include <linux/psci.h>
1715
1816 #include <asm/cpuidle.h>
1917 #include <asm/cpu_ops.h>
2018
2119 int arm_cpuidle_init(unsigned int cpu)
2220 {
21
+ const struct cpu_operations *ops = get_cpu_ops(cpu);
2322 int ret = -EOPNOTSUPP;
2423
25
- if (cpu_ops[cpu] && cpu_ops[cpu]->cpu_suspend &&
26
- cpu_ops[cpu]->cpu_init_idle)
27
- ret = cpu_ops[cpu]->cpu_init_idle(cpu);
24
+ if (ops && ops->cpu_suspend && ops->cpu_init_idle)
25
+ ret = ops->cpu_init_idle(cpu);
2826
2927 return ret;
3028 }
....@@ -39,10 +37,10 @@
3937 int arm_cpuidle_suspend(int index)
4038 {
4139 int cpu = smp_processor_id();
40
+ const struct cpu_operations *ops = get_cpu_ops(cpu);
4241
43
- return cpu_ops[cpu]->cpu_suspend(index);
42
+ return ops->cpu_suspend(index);
4443 }
45
-EXPORT_SYMBOL_GPL(arm_cpuidle_suspend);
4644
4745 #ifdef CONFIG_ACPI
4846
....@@ -50,17 +48,58 @@
5048
5149 #define ARM64_LPI_IS_RETENTION_STATE(arch_flags) (!(arch_flags))
5250
51
+static int psci_acpi_cpu_init_idle(unsigned int cpu)
52
+{
53
+ int i, count;
54
+ struct acpi_lpi_state *lpi;
55
+ struct acpi_processor *pr = per_cpu(processors, cpu);
56
+
57
+ if (unlikely(!pr || !pr->flags.has_lpi))
58
+ return -EINVAL;
59
+
60
+ /*
61
+ * If the PSCI cpu_suspend function hook has not been initialized
62
+ * idle states must not be enabled, so bail out
63
+ */
64
+ if (!psci_ops.cpu_suspend)
65
+ return -EOPNOTSUPP;
66
+
67
+ count = pr->power.count - 1;
68
+ if (count <= 0)
69
+ return -ENODEV;
70
+
71
+ for (i = 0; i < count; i++) {
72
+ u32 state;
73
+
74
+ lpi = &pr->power.lpi_states[i + 1];
75
+ /*
76
+ * Only bits[31:0] represent a PSCI power_state while
77
+ * bits[63:32] must be 0x0 as per ARM ACPI FFH Specification
78
+ */
79
+ state = lpi->address;
80
+ if (!psci_power_state_is_valid(state)) {
81
+ pr_warn("Invalid PSCI power state %#x\n", state);
82
+ return -EINVAL;
83
+ }
84
+ }
85
+
86
+ return 0;
87
+}
88
+
5389 int acpi_processor_ffh_lpi_probe(unsigned int cpu)
5490 {
55
- return arm_cpuidle_init(cpu);
91
+ return psci_acpi_cpu_init_idle(cpu);
5692 }
5793
5894 int acpi_processor_ffh_lpi_enter(struct acpi_lpi_state *lpi)
5995 {
96
+ u32 state = lpi->address;
97
+
6098 if (ARM64_LPI_IS_RETENTION_STATE(lpi->arch_flags))
61
- return CPU_PM_CPU_IDLE_ENTER_RETENTION(arm_cpuidle_suspend,
62
- lpi->index);
99
+ return CPU_PM_CPU_IDLE_ENTER_RETENTION_PARAM(psci_cpu_suspend_enter,
100
+ lpi->index, state);
63101 else
64
- return CPU_PM_CPU_IDLE_ENTER(arm_cpuidle_suspend, lpi->index);
102
+ return CPU_PM_CPU_IDLE_ENTER_PARAM(psci_cpu_suspend_enter,
103
+ lpi->index, state);
65104 }
66105 #endif