Commit 7afc5395 authored by Rafael J. Wysocki's avatar Rafael J. Wysocki

Merge branches 'pm-docs' and 'pm-misc'

* pm-docs:
  Documentation: PM: Unify copyright notices
  Documentation: PM: Add SPDX license tags to multiple files
  cpufreq: intel_pstate: Documentation: Add references sections

* pm-misc:
  firmware/psci: add support for SYSTEM_RESET2
  drivers: firmware: psci: Announce support for OS initiated suspend mode
  drivers: firmware: psci: Simplify error path of psci_dt_init()
  drivers: firmware: psci: Split psci_dt_cpu_init_idle()
  MAINTAINERS: Update files for PSCI
  drivers: firmware: psci: Move psci to separate directory
.. SPDX-License-Identifier: GPL-2.0
.. include:: <isonum.txt>
.. |struct cpufreq_policy| replace:: :c:type:`struct cpufreq_policy <cpufreq_policy>` .. |struct cpufreq_policy| replace:: :c:type:`struct cpufreq_policy <cpufreq_policy>`
.. |intel_pstate| replace:: :doc:`intel_pstate <intel_pstate>` .. |intel_pstate| replace:: :doc:`intel_pstate <intel_pstate>`
...@@ -5,9 +8,10 @@ ...@@ -5,9 +8,10 @@
CPU Performance Scaling CPU Performance Scaling
======================= =======================
:: :Copyright: |copy| 2017 Intel Corporation
:Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Copyright (c) 2017 Intel Corp., Rafael J. Wysocki <rafael.j.wysocki@intel.com>
The Concept of CPU Performance Scaling The Concept of CPU Performance Scaling
====================================== ======================================
...@@ -396,8 +400,8 @@ RT or deadline scheduling classes, the governor will increase the frequency to ...@@ -396,8 +400,8 @@ RT or deadline scheduling classes, the governor will increase the frequency to
the allowed maximum (that is, the ``scaling_max_freq`` policy limit). In turn, the allowed maximum (that is, the ``scaling_max_freq`` policy limit). In turn,
if it is invoked by the CFS scheduling class, the governor will use the if it is invoked by the CFS scheduling class, the governor will use the
Per-Entity Load Tracking (PELT) metric for the root control group of the Per-Entity Load Tracking (PELT) metric for the root control group of the
given CPU as the CPU utilization estimate (see the `Per-entity load tracking`_ given CPU as the CPU utilization estimate (see the *Per-entity load tracking*
LWN.net article for a description of the PELT mechanism). Then, the new LWN.net article [1]_ for a description of the PELT mechanism). Then, the new
CPU frequency to apply is computed in accordance with the formula CPU frequency to apply is computed in accordance with the formula
f = 1.25 * ``f_0`` * ``util`` / ``max`` f = 1.25 * ``f_0`` * ``util`` / ``max``
...@@ -698,4 +702,8 @@ hardware feature (e.g. all Intel ones), even if the ...@@ -698,4 +702,8 @@ hardware feature (e.g. all Intel ones), even if the
:c:macro:`CONFIG_X86_ACPI_CPUFREQ_CPB` configuration option is set. :c:macro:`CONFIG_X86_ACPI_CPUFREQ_CPB` configuration option is set.
.. _Per-entity load tracking: https://lwn.net/Articles/531853/ References
==========
.. [1] Jonathan Corbet, *Per-entity load tracking*,
https://lwn.net/Articles/531853/
.. SPDX-License-Identifier: GPL-2.0
.. include:: <isonum.txt>
.. |struct cpuidle_state| replace:: :c:type:`struct cpuidle_state <cpuidle_state>` .. |struct cpuidle_state| replace:: :c:type:`struct cpuidle_state <cpuidle_state>`
.. |cpufreq| replace:: :doc:`CPU Performance Scaling <cpufreq>` .. |cpufreq| replace:: :doc:`CPU Performance Scaling <cpufreq>`
...@@ -5,9 +8,10 @@ ...@@ -5,9 +8,10 @@
CPU Idle Time Management CPU Idle Time Management
======================== ========================
:: :Copyright: |copy| 2018 Intel Corporation
:Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Copyright (c) 2018 Intel Corp., Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Concepts Concepts
======== ========
......
.. SPDX-License-Identifier: GPL-2.0
================ ================
Power Management Power Management
================ ================
......
.. SPDX-License-Identifier: GPL-2.0
.. include:: <isonum.txt>
=============================================== ===============================================
``intel_pstate`` CPU Performance Scaling Driver ``intel_pstate`` CPU Performance Scaling Driver
=============================================== ===============================================
:: :Copyright: |copy| 2017 Intel Corporation
Copyright (c) 2017 Intel Corp., Rafael J. Wysocki <rafael.j.wysocki@intel.com> :Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
General Information General Information
...@@ -20,11 +23,10 @@ you have not done that yet.] ...@@ -20,11 +23,10 @@ you have not done that yet.]
For the processors supported by ``intel_pstate``, the P-state concept is broader For the processors supported by ``intel_pstate``, the P-state concept is broader
than just an operating frequency or an operating performance point (see the than just an operating frequency or an operating performance point (see the
`LinuxCon Europe 2015 presentation by Kristen Accardi <LCEU2015_>`_ for more LinuxCon Europe 2015 presentation by Kristen Accardi [1]_ for more
information about that). For this reason, the representation of P-states used information about that). For this reason, the representation of P-states used
by ``intel_pstate`` internally follows the hardware specification (for details by ``intel_pstate`` internally follows the hardware specification (for details
refer to `Intel® 64 and IA-32 Architectures Software Developers Manual refer to Intel Software Developers Manual [2]_). However, the ``CPUFreq`` core
Volume 3: System Programming Guide <SDM_>`_). However, the ``CPUFreq`` core
uses frequencies for identifying operating performance points of CPUs and uses frequencies for identifying operating performance points of CPUs and
frequencies are involved in the user space interface exposed by it, so frequencies are involved in the user space interface exposed by it, so
``intel_pstate`` maps its internal representation of P-states to frequencies too ``intel_pstate`` maps its internal representation of P-states to frequencies too
...@@ -561,9 +563,9 @@ or to pin every task potentially sensitive to them to a specific CPU.] ...@@ -561,9 +563,9 @@ or to pin every task potentially sensitive to them to a specific CPU.]
On the majority of systems supported by ``intel_pstate``, the ACPI tables On the majority of systems supported by ``intel_pstate``, the ACPI tables
provided by the platform firmware contain ``_PSS`` objects returning information provided by the platform firmware contain ``_PSS`` objects returning information
that can be used for CPU performance scaling (refer to the `ACPI specification`_ that can be used for CPU performance scaling (refer to the ACPI specification
for details on the ``_PSS`` objects and the format of the information returned [3]_ for details on the ``_PSS`` objects and the format of the information
by them). returned by them).
The information returned by the ACPI ``_PSS`` objects is used by the The information returned by the ACPI ``_PSS`` objects is used by the
``acpi-cpufreq`` scaling driver. On systems supported by ``intel_pstate`` ``acpi-cpufreq`` scaling driver. On systems supported by ``intel_pstate``
...@@ -728,6 +730,14 @@ P-state is called, the ``ftrace`` filter can be set to to ...@@ -728,6 +730,14 @@ P-state is called, the ``ftrace`` filter can be set to to
<idle>-0 [000] ..s. 2537.654843: intel_pstate_set_pstate <-intel_pstate_timer_func <idle>-0 [000] ..s. 2537.654843: intel_pstate_set_pstate <-intel_pstate_timer_func
.. _LCEU2015: http://events.linuxfoundation.org/sites/events/files/slides/LinuxConEurope_2015.pdf References
.. _SDM: http://www.intel.com/content/www/us/en/architecture-and-technology/64-ia-32-architectures-software-developer-system-programming-manual-325384.html ==========
.. _ACPI specification: http://www.uefi.org/sites/default/files/resources/ACPI_6_1.pdf
.. [1] Kristen Accardi, *Balancing Power and Performance in the Linux Kernel*,
http://events.linuxfoundation.org/sites/events/files/slides/LinuxConEurope_2015.pdf
.. [2] *Intel® 64 and IA-32 Architectures Software Developers Manual Volume 3: System Programming Guide*,
http://www.intel.com/content/www/us/en/architecture-and-technology/64-ia-32-architectures-software-developer-system-programming-manual-325384.html
.. [3] *Advanced Configuration and Power Interface Specification*,
https://uefi.org/sites/default/files/resources/ACPI_6_3_final_Jan30.pdf
.. SPDX-License-Identifier: GPL-2.0
.. include:: <isonum.txt>
=================== ===================
System Sleep States System Sleep States
=================== ===================
:: :Copyright: |copy| 2017 Intel Corporation
:Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Copyright (c) 2017 Intel Corp., Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Sleep states are global low-power states of the entire system in which user Sleep states are global low-power states of the entire system in which user
space code cannot be executed and the overall system activity is significantly space code cannot be executed and the overall system activity is significantly
......
.. SPDX-License-Identifier: GPL-2.0
.. include:: <isonum.txt>
=========================== ===========================
Power Management Strategies Power Management Strategies
=========================== ===========================
:: :Copyright: |copy| 2017 Intel Corporation
:Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Copyright (c) 2017 Intel Corp., Rafael J. Wysocki <rafael.j.wysocki@intel.com>
The Linux kernel supports two major high-level power management strategies. The Linux kernel supports two major high-level power management strategies.
......
.. SPDX-License-Identifier: GPL-2.0
============================ ============================
System-Wide Power Management System-Wide Power Management
============================ ============================
......
.. SPDX-License-Identifier: GPL-2.0
============================== ==============================
Working-State Power Management Working-State Power Management
============================== ==============================
......
.. SPDX-License-Identifier: GPL-2.0
.. include:: <isonum.txt>
.. |struct cpuidle_governor| replace:: :c:type:`struct cpuidle_governor <cpuidle_governor>` .. |struct cpuidle_governor| replace:: :c:type:`struct cpuidle_governor <cpuidle_governor>`
.. |struct cpuidle_device| replace:: :c:type:`struct cpuidle_device <cpuidle_device>` .. |struct cpuidle_device| replace:: :c:type:`struct cpuidle_device <cpuidle_device>`
.. |struct cpuidle_driver| replace:: :c:type:`struct cpuidle_driver <cpuidle_driver>` .. |struct cpuidle_driver| replace:: :c:type:`struct cpuidle_driver <cpuidle_driver>`
...@@ -7,9 +10,9 @@ ...@@ -7,9 +10,9 @@
CPU Idle Time Management CPU Idle Time Management
======================== ========================
:: :Copyright: |copy| 2019 Intel Corporation
Copyright (c) 2019 Intel Corp., Rafael J. Wysocki <rafael.j.wysocki@intel.com> :Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
CPU Idle Time Management Subsystem CPU Idle Time Management Subsystem
......
.. SPDX-License-Identifier: GPL-2.0
.. include:: <isonum.txt>
.. |struct dev_pm_ops| replace:: :c:type:`struct dev_pm_ops <dev_pm_ops>` .. |struct dev_pm_ops| replace:: :c:type:`struct dev_pm_ops <dev_pm_ops>`
.. |struct dev_pm_domain| replace:: :c:type:`struct dev_pm_domain <dev_pm_domain>` .. |struct dev_pm_domain| replace:: :c:type:`struct dev_pm_domain <dev_pm_domain>`
.. |struct bus_type| replace:: :c:type:`struct bus_type <bus_type>` .. |struct bus_type| replace:: :c:type:`struct bus_type <bus_type>`
...@@ -12,11 +15,12 @@ ...@@ -12,11 +15,12 @@
Device Power Management Basics Device Power Management Basics
============================== ==============================
:: :Copyright: |copy| 2010-2011 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc.
:Copyright: |copy| 2010 Alan Stern <stern@rowland.harvard.edu>
:Copyright: |copy| 2016 Intel Corporation
:Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Copyright (c) 2010-2011 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc.
Copyright (c) 2010 Alan Stern <stern@rowland.harvard.edu>
Copyright (c) 2016 Intel Corp., Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Most of the code in Linux is device drivers, so most of the Linux power Most of the code in Linux is device drivers, so most of the Linux power
management (PM) code is also driver-specific. Most drivers will do very management (PM) code is also driver-specific. Most drivers will do very
......
.. SPDX-License-Identifier: GPL-2.0
=============================== ===============================
CPU and Device Power Management CPU and Device Power Management
=============================== ===============================
......
.. SPDX-License-Identifier: GPL-2.0
.. include:: <isonum.txt>
============================= =============================
Suspend/Hibernation Notifiers Suspend/Hibernation Notifiers
============================= =============================
:: :Copyright: |copy| 2016 Intel Corporation
:Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Copyright (c) 2016 Intel Corp., Rafael J. Wysocki <rafael.j.wysocki@intel.com>
There are some operations that subsystems or drivers may want to carry out There are some operations that subsystems or drivers may want to carry out
before hibernation/suspend or after restore/resume, but they require the system before hibernation/suspend or after restore/resume, but they require the system
......
.. SPDX-License-Identifier: GPL-2.0
================================== ==================================
Device Power Management Data Types Device Power Management Data Types
================================== ==================================
......
...@@ -12416,7 +12416,7 @@ M: Mark Rutland <mark.rutland@arm.com> ...@@ -12416,7 +12416,7 @@ M: Mark Rutland <mark.rutland@arm.com>
M: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> M: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
L: linux-arm-kernel@lists.infradead.org L: linux-arm-kernel@lists.infradead.org
S: Maintained S: Maintained
F: drivers/firmware/psci*.c F: drivers/firmware/psci/
F: include/linux/psci.h F: include/linux/psci.h
F: include/uapi/linux/psci.h F: include/uapi/linux/psci.h
......
...@@ -5,20 +5,6 @@ ...@@ -5,20 +5,6 @@
menu "Firmware Drivers" menu "Firmware Drivers"
config ARM_PSCI_FW
bool
config ARM_PSCI_CHECKER
bool "ARM PSCI checker"
depends on ARM_PSCI_FW && HOTPLUG_CPU && CPU_IDLE && !TORTURE_TEST
help
Run the PSCI checker during startup. This checks that hotplug and
suspend operations work correctly when using PSCI.
The torture tests may interfere with the PSCI checker by turning CPUs
on and off through hotplug, so for now torture tests and PSCI checker
are mutually exclusive.
config ARM_SCMI_PROTOCOL config ARM_SCMI_PROTOCOL
bool "ARM System Control and Management Interface (SCMI) Message Protocol" bool "ARM System Control and Management Interface (SCMI) Message Protocol"
depends on ARM || ARM64 || COMPILE_TEST depends on ARM || ARM64 || COMPILE_TEST
...@@ -270,6 +256,7 @@ config TI_SCI_PROTOCOL ...@@ -270,6 +256,7 @@ config TI_SCI_PROTOCOL
config HAVE_ARM_SMCCC config HAVE_ARM_SMCCC
bool bool
source "drivers/firmware/psci/Kconfig"
source "drivers/firmware/broadcom/Kconfig" source "drivers/firmware/broadcom/Kconfig"
source "drivers/firmware/google/Kconfig" source "drivers/firmware/google/Kconfig"
source "drivers/firmware/efi/Kconfig" source "drivers/firmware/efi/Kconfig"
......
...@@ -2,8 +2,6 @@ ...@@ -2,8 +2,6 @@
# #
# Makefile for the linux kernel. # Makefile for the linux kernel.
# #
obj-$(CONFIG_ARM_PSCI_FW) += psci.o
obj-$(CONFIG_ARM_PSCI_CHECKER) += psci_checker.o
obj-$(CONFIG_ARM_SCPI_PROTOCOL) += arm_scpi.o obj-$(CONFIG_ARM_SCPI_PROTOCOL) += arm_scpi.o
obj-$(CONFIG_ARM_SCPI_POWER_DOMAIN) += scpi_pm_domain.o obj-$(CONFIG_ARM_SCPI_POWER_DOMAIN) += scpi_pm_domain.o
obj-$(CONFIG_ARM_SDE_INTERFACE) += arm_sdei.o obj-$(CONFIG_ARM_SDE_INTERFACE) += arm_sdei.o
...@@ -25,6 +23,7 @@ CFLAGS_qcom_scm-32.o :=$(call as-instr,.arch armv7-a\n.arch_extension sec,-DREQU ...@@ -25,6 +23,7 @@ CFLAGS_qcom_scm-32.o :=$(call as-instr,.arch armv7-a\n.arch_extension sec,-DREQU
obj-$(CONFIG_TI_SCI_PROTOCOL) += ti_sci.o obj-$(CONFIG_TI_SCI_PROTOCOL) += ti_sci.o
obj-$(CONFIG_ARM_SCMI_PROTOCOL) += arm_scmi/ obj-$(CONFIG_ARM_SCMI_PROTOCOL) += arm_scmi/
obj-y += psci/
obj-y += broadcom/ obj-y += broadcom/
obj-y += meson/ obj-y += meson/
obj-$(CONFIG_GOOGLE_FIRMWARE) += google/ obj-$(CONFIG_GOOGLE_FIRMWARE) += google/
......
config ARM_PSCI_FW
bool
config ARM_PSCI_CHECKER
bool "ARM PSCI checker"
depends on ARM_PSCI_FW && HOTPLUG_CPU && CPU_IDLE && !TORTURE_TEST
help
Run the PSCI checker during startup. This checks that hotplug and
suspend operations work correctly when using PSCI.
The torture tests may interfere with the PSCI checker by turning CPUs
on and off through hotplug, so for now torture tests and PSCI checker
are mutually exclusive.
# SPDX-License-Identifier: GPL-2.0
#
obj-$(CONFIG_ARM_PSCI_FW) += psci.o
obj-$(CONFIG_ARM_PSCI_CHECKER) += psci_checker.o
...@@ -88,6 +88,7 @@ static u32 psci_function_id[PSCI_FN_MAX]; ...@@ -88,6 +88,7 @@ static u32 psci_function_id[PSCI_FN_MAX];
PSCI_1_0_EXT_POWER_STATE_TYPE_MASK) PSCI_1_0_EXT_POWER_STATE_TYPE_MASK)
static u32 psci_cpu_suspend_feature; static u32 psci_cpu_suspend_feature;
static bool psci_system_reset2_supported;
static inline bool psci_has_ext_power_state(void) static inline bool psci_has_ext_power_state(void)
{ {
...@@ -95,6 +96,11 @@ static inline bool psci_has_ext_power_state(void) ...@@ -95,6 +96,11 @@ static inline bool psci_has_ext_power_state(void)
PSCI_1_0_FEATURES_CPU_SUSPEND_PF_MASK; PSCI_1_0_FEATURES_CPU_SUSPEND_PF_MASK;
} }
static inline bool psci_has_osi_support(void)
{
return psci_cpu_suspend_feature & PSCI_1_0_OS_INITIATED;
}
static inline bool psci_power_state_loses_context(u32 state) static inline bool psci_power_state_loses_context(u32 state)
{ {
const u32 mask = psci_has_ext_power_state() ? const u32 mask = psci_has_ext_power_state() ?
...@@ -253,7 +259,17 @@ static int get_set_conduit_method(struct device_node *np) ...@@ -253,7 +259,17 @@ static int get_set_conduit_method(struct device_node *np)
static void psci_sys_reset(enum reboot_mode reboot_mode, const char *cmd) static void psci_sys_reset(enum reboot_mode reboot_mode, const char *cmd)
{ {
if ((reboot_mode == REBOOT_WARM || reboot_mode == REBOOT_SOFT) &&
psci_system_reset2_supported) {
/*
* reset_type[31] = 0 (architectural)
* reset_type[30:0] = 0 (SYSTEM_WARM_RESET)
* cookie = 0 (ignored by the implementation)
*/
invoke_psci_fn(PSCI_FN_NATIVE(1_1, SYSTEM_RESET2), 0, 0, 0);
} else {
invoke_psci_fn(PSCI_0_2_FN_SYSTEM_RESET, 0, 0, 0); invoke_psci_fn(PSCI_0_2_FN_SYSTEM_RESET, 0, 0, 0);
}
} }
static void psci_sys_poweroff(void) static void psci_sys_poweroff(void)
...@@ -270,9 +286,26 @@ static int __init psci_features(u32 psci_func_id) ...@@ -270,9 +286,26 @@ static int __init psci_features(u32 psci_func_id)
#ifdef CONFIG_CPU_IDLE #ifdef CONFIG_CPU_IDLE
static DEFINE_PER_CPU_READ_MOSTLY(u32 *, psci_power_state); static DEFINE_PER_CPU_READ_MOSTLY(u32 *, psci_power_state);
static int psci_dt_parse_state_node(struct device_node *np, u32 *state)
{
int err = of_property_read_u32(np, "arm,psci-suspend-param", state);
if (err) {
pr_warn("%pOF missing arm,psci-suspend-param property\n", np);
return err;
}
if (!psci_power_state_is_valid(*state)) {
pr_warn("Invalid PSCI power state %#x\n", *state);
return -EINVAL;
}
return 0;
}
static int psci_dt_cpu_init_idle(struct device_node *cpu_node, int cpu) static int psci_dt_cpu_init_idle(struct device_node *cpu_node, int cpu)
{ {
int i, ret, count = 0; int i, ret = 0, count = 0;
u32 *psci_states; u32 *psci_states;
struct device_node *state_node; struct device_node *state_node;
...@@ -291,29 +324,16 @@ static int psci_dt_cpu_init_idle(struct device_node *cpu_node, int cpu) ...@@ -291,29 +324,16 @@ static int psci_dt_cpu_init_idle(struct device_node *cpu_node, int cpu)
return -ENOMEM; return -ENOMEM;
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
u32 state;
state_node = of_parse_phandle(cpu_node, "cpu-idle-states", i); state_node = of_parse_phandle(cpu_node, "cpu-idle-states", i);
ret = psci_dt_parse_state_node(state_node, &psci_states[i]);
ret = of_property_read_u32(state_node,
"arm,psci-suspend-param",
&state);
if (ret) {
pr_warn(" * %pOF missing arm,psci-suspend-param property\n",
state_node);
of_node_put(state_node); of_node_put(state_node);
goto free_mem;
}
of_node_put(state_node); if (ret)
pr_debug("psci-power-state %#x index %d\n", state, i);
if (!psci_power_state_is_valid(state)) {
pr_warn("Invalid PSCI power state %#x\n", state);
ret = -EINVAL;
goto free_mem; goto free_mem;
pr_debug("psci-power-state %#x index %d\n", psci_states[i], i);
} }
psci_states[i] = state;
}
/* Idle states parsed correctly, initialize per-cpu pointer */ /* Idle states parsed correctly, initialize per-cpu pointer */
per_cpu(psci_power_state, cpu) = psci_states; per_cpu(psci_power_state, cpu) = psci_states;
return 0; return 0;
...@@ -451,6 +471,16 @@ static const struct platform_suspend_ops psci_suspend_ops = { ...@@ -451,6 +471,16 @@ static const struct platform_suspend_ops psci_suspend_ops = {
.enter = psci_system_suspend_enter, .enter = psci_system_suspend_enter,
}; };
static void __init psci_init_system_reset2(void)
{
int ret;
ret = psci_features(PSCI_FN_NATIVE(1_1, SYSTEM_RESET2));
if (ret != PSCI_RET_NOT_SUPPORTED)
psci_system_reset2_supported = true;
}
static void __init psci_init_system_suspend(void) static void __init psci_init_system_suspend(void)
{ {
int ret; int ret;
...@@ -588,6 +618,7 @@ static int __init psci_probe(void) ...@@ -588,6 +618,7 @@ static int __init psci_probe(void)
psci_init_smccc(); psci_init_smccc();
psci_init_cpu_suspend(); psci_init_cpu_suspend();
psci_init_system_suspend(); psci_init_system_suspend();
psci_init_system_reset2();
} }
return 0; return 0;
...@@ -605,9 +636,9 @@ static int __init psci_0_2_init(struct device_node *np) ...@@ -605,9 +636,9 @@ static int __init psci_0_2_init(struct device_node *np)
int err; int err;
err = get_set_conduit_method(np); err = get_set_conduit_method(np);
if (err) if (err)
goto out_put_node; return err;
/* /*
* Starting with v0.2, the PSCI specification introduced a call * Starting with v0.2, the PSCI specification introduced a call
* (PSCI_VERSION) that allows probing the firmware version, so * (PSCI_VERSION) that allows probing the firmware version, so
...@@ -615,11 +646,7 @@ static int __init psci_0_2_init(struct device_node *np) ...@@ -615,11 +646,7 @@ static int __init psci_0_2_init(struct device_node *np)
* can be carried out according to the specific version reported * can be carried out according to the specific version reported
* by firmware * by firmware
*/ */
err = psci_probe(); return psci_probe();
out_put_node:
of_node_put(np);
return err;
} }
/* /*
...@@ -631,9 +658,8 @@ static int __init psci_0_1_init(struct device_node *np) ...@@ -631,9 +658,8 @@ static int __init psci_0_1_init(struct device_node *np)
int err; int err;
err = get_set_conduit_method(np); err = get_set_conduit_method(np);
if (err) if (err)
goto out_put_node; return err;
pr_info("Using PSCI v0.1 Function IDs from DT\n"); pr_info("Using PSCI v0.1 Function IDs from DT\n");
...@@ -657,15 +683,27 @@ static int __init psci_0_1_init(struct device_node *np) ...@@ -657,15 +683,27 @@ static int __init psci_0_1_init(struct device_node *np)
psci_ops.migrate = psci_migrate; psci_ops.migrate = psci_migrate;
} }
out_put_node: return 0;
of_node_put(np); }
static int __init psci_1_0_init(struct device_node *np)
{
int err;
err = psci_0_2_init(np);
if (err)
return err; return err;
if (psci_has_osi_support())
pr_info("OSI mode supported.\n");
return 0;
} }
static const struct of_device_id psci_of_match[] __initconst = { static const struct of_device_id psci_of_match[] __initconst = {
{ .compatible = "arm,psci", .data = psci_0_1_init}, { .compatible = "arm,psci", .data = psci_0_1_init},
{ .compatible = "arm,psci-0.2", .data = psci_0_2_init}, { .compatible = "arm,psci-0.2", .data = psci_0_2_init},
{ .compatible = "arm,psci-1.0", .data = psci_0_2_init}, { .compatible = "arm,psci-1.0", .data = psci_1_0_init},
{}, {},
}; };
...@@ -674,6 +712,7 @@ int __init psci_dt_init(void) ...@@ -674,6 +712,7 @@ int __init psci_dt_init(void)
struct device_node *np; struct device_node *np;
const struct of_device_id *matched_np; const struct of_device_id *matched_np;
psci_initcall_t init_fn; psci_initcall_t init_fn;
int ret;
np = of_find_matching_node_and_match(NULL, psci_of_match, &matched_np); np = of_find_matching_node_and_match(NULL, psci_of_match, &matched_np);
...@@ -681,7 +720,10 @@ int __init psci_dt_init(void) ...@@ -681,7 +720,10 @@ int __init psci_dt_init(void)
return -ENODEV; return -ENODEV;
init_fn = (psci_initcall_t)matched_np->data; init_fn = (psci_initcall_t)matched_np->data;
return init_fn(np); ret = init_fn(np);
of_node_put(np);
return ret;
} }
#ifdef CONFIG_ACPI #ifdef CONFIG_ACPI
......
...@@ -49,8 +49,11 @@ ...@@ -49,8 +49,11 @@
#define PSCI_1_0_FN_PSCI_FEATURES PSCI_0_2_FN(10) #define PSCI_1_0_FN_PSCI_FEATURES PSCI_0_2_FN(10)
#define PSCI_1_0_FN_SYSTEM_SUSPEND PSCI_0_2_FN(14) #define PSCI_1_0_FN_SYSTEM_SUSPEND PSCI_0_2_FN(14)
#define PSCI_1_0_FN_SET_SUSPEND_MODE PSCI_0_2_FN(15)
#define PSCI_1_1_FN_SYSTEM_RESET2 PSCI_0_2_FN(18)
#define PSCI_1_0_FN64_SYSTEM_SUSPEND PSCI_0_2_FN64(14) #define PSCI_1_0_FN64_SYSTEM_SUSPEND PSCI_0_2_FN64(14)
#define PSCI_1_1_FN64_SYSTEM_RESET2 PSCI_0_2_FN64(18)
/* PSCI v0.2 power state encoding for CPU_SUSPEND function */ /* PSCI v0.2 power state encoding for CPU_SUSPEND function */
#define PSCI_0_2_POWER_STATE_ID_MASK 0xffff #define PSCI_0_2_POWER_STATE_ID_MASK 0xffff
...@@ -97,6 +100,10 @@ ...@@ -97,6 +100,10 @@
#define PSCI_1_0_FEATURES_CPU_SUSPEND_PF_MASK \ #define PSCI_1_0_FEATURES_CPU_SUSPEND_PF_MASK \
(0x1 << PSCI_1_0_FEATURES_CPU_SUSPEND_PF_SHIFT) (0x1 << PSCI_1_0_FEATURES_CPU_SUSPEND_PF_SHIFT)
#define PSCI_1_0_OS_INITIATED BIT(0)
#define PSCI_1_0_SUSPEND_MODE_PC 0
#define PSCI_1_0_SUSPEND_MODE_OSI 1
/* PSCI return values (inclusive of all PSCI versions) */ /* PSCI return values (inclusive of all PSCI versions) */
#define PSCI_RET_SUCCESS 0 #define PSCI_RET_SUCCESS 0
#define PSCI_RET_NOT_SUPPORTED -1 #define PSCI_RET_NOT_SUPPORTED -1
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment