mirror of
https://github.com/t2linux/kernel.git
synced 2026-04-30 13:48:59 -07:00
Merge tag 'pm-5.6-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
Pull power management updates from Rafael Wysocki:
"These add ACPI support to the intel_idle driver along with an admin
guide document for it, add support for CPR (Core Power Reduction) to
the AVS (Adaptive Voltage Scaling) subsystem, add new hardware support
in a few places, add some new sysfs attributes, debugfs files and
tracepoints, fix bugs and clean up a bunch of things all over.
Specifics:
- Update the ACPI processor driver in order to export
acpi_processor_evaluate_cst() to the code outside of it, add ACPI
support to the intel_idle driver based on that and clean up that
driver somewhat (Rafael Wysocki).
- Add an admin guide document for the intel_idle driver (Rafael
Wysocki).
- Clean up cpuidle core and drivers, enable compilation testing for
some of them (Benjamin Gaignard, Krzysztof Kozlowski, Rafael
Wysocki, Yangtao Li).
- Fix reference counting of OPP (operating performance points) table
structures (Viresh Kumar).
- Add support for CPR (Core Power Reduction) to the AVS (Adaptive
Voltage Scaling) subsystem (Niklas Cassel, Colin Ian King,
YueHaibing).
- Add support for TigerLake Mobile and JasperLake to the Intel RAPL
power capping driver (Zhang Rui).
- Update cpufreq drivers:
- Add i.MX8MP support to imx-cpufreq-dt (Anson Huang).
- Fix usage of a macro in loongson2_cpufreq (Alexandre Oliva).
- Fix cpufreq policy reference counting issues in s3c and
brcmstb-avs (chenqiwu).
- Fix ACPI table reference counting issue and HiSilicon quirk
handling in the CPPC driver (Hanjun Guo).
- Clean up spelling mistake in intel_pstate (Harry Pan).
- Convert the kirkwood and tegra186 drivers to using
devm_platform_ioremap_resource() (Yangtao Li).
- Update devfreq core:
- Add 'name' sysfs attribute for devfreq devices (Chanwoo Choi).
- Clean up the handing of transition statistics and allow them to
be reset by writing 0 to the 'trans_stat' devfreq device
attribute in sysfs (Kamil Konieczny).
- Add 'devfreq_summary' to debugfs (Chanwoo Choi).
- Clean up kerneldoc comments and Kconfig indentation (Krzysztof
Kozlowski, Randy Dunlap).
- Update devfreq drivers:
- Add dynamic scaling for the imx8m DDR controller and clean up
imx8m-ddrc (Leonard Crestez, YueHaibing).
- Fix DT node reference counting and nitialization error code path
in rk3399_dmc and add COMPILE_TEST and HAVE_ARM_SMCCC dependency
for it (Chanwoo Choi, Yangtao Li).
- Fix DT node reference counting in rockchip-dfi and make it use
devm_platform_ioremap_resource() (Yangtao Li).
- Fix excessive stack usage in exynos-ppmu (Arnd Bergmann).
- Fix initialization error code paths in exynos-bus (Yangtao Li).
- Clean up exynos-bus and exynos somewhat (Artur Świgoń, Krzysztof
Kozlowski).
- Add tracepoints for tracking usage_count updates unrelated to
status changes in PM-runtime (Michał Mirosław).
- Add sysfs attribute to control the "sync on suspend" behavior
during system-wide suspend (Jonas Meurer).
- Switch system-wide suspend tests over to 64-bit time (Alexandre
Belloni).
- Make wakeup sources statistics in debugfs cover deleted ones which
used to be the case some time ago (zhuguangqing).
- Clean up computations carried out during hibernation, update
messages related to hibernation and fix a spelling mistake in one
of them (Wen Yang, Luigi Semenzato, Colin Ian King).
- Add mailmap entry for maintainer e-mail address that has not been
functional for several years (Rafael Wysocki)"
* tag 'pm-5.6-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: (83 commits)
cpufreq: loongson2_cpufreq: adjust cpufreq uses of LOONGSON_CHIPCFG
intel_idle: Clean up irtl_2_usec()
intel_idle: Move 3 functions closer to their callers
intel_idle: Annotate initialization code and data structures
intel_idle: Move and clean up intel_idle_cpuidle_devices_uninit()
intel_idle: Rearrange intel_idle_cpuidle_driver_init()
intel_idle: Clean up NULL pointer check in intel_idle_init()
intel_idle: Fold intel_idle_probe() into intel_idle_init()
intel_idle: Eliminate __setup_broadcast_timer()
cpuidle: fix cpuidle_find_deepest_state() kerneldoc warnings
cpuidle: sysfs: fix warnings when compiling with W=1
cpuidle: coupled: fix warnings when compiling with W=1
cpufreq: brcmstb-avs: fix imbalance of cpufreq policy refcount
PM: suspend: Add sysfs attribute to control the "sync on suspend" behavior
PM / devfreq: Add debugfs support with devfreq_summary file
Documentation: admin-guide: PM: Add intel_idle document
cpuidle: arm: Enable compile testing for some of drivers
PM-runtime: add tracepoints for usage_count changes
cpufreq: intel_pstate: fix spelling mistake: "Whethet" -> "Whether"
PM: hibernate: fix spelling mistake "shapshot" -> "snapshot"
...
This commit is contained in:
@@ -217,6 +217,7 @@ Praveen BP <praveenbp@ti.com>
|
||||
Punit Agrawal <punitagrawal@gmail.com> <punit.agrawal@arm.com>
|
||||
Qais Yousef <qsyousef@gmail.com> <qais.yousef@imgtec.com>
|
||||
Quentin Perret <qperret@qperret.net> <quentin.perret@arm.com>
|
||||
Rafael J. Wysocki <rjw@rjwysocki.net> <rjw@sisk.pl>
|
||||
Rajesh Shah <rajesh.shah@intel.com>
|
||||
Ralf Baechle <ralf@linux-mips.org>
|
||||
Ralf Wildenhues <Ralf.Wildenhues@gmx.de>
|
||||
|
||||
@@ -7,6 +7,13 @@ Description:
|
||||
The name of devfreq object denoted as ... is same as the
|
||||
name of device using devfreq.
|
||||
|
||||
What: /sys/class/devfreq/.../name
|
||||
Date: November 2019
|
||||
Contact: Chanwoo Choi <cw00.choi@samsung.com>
|
||||
Description:
|
||||
The /sys/class/devfreq/.../name shows the name of device
|
||||
of the corresponding devfreq object.
|
||||
|
||||
What: /sys/class/devfreq/.../governor
|
||||
Date: September 2011
|
||||
Contact: MyungJoo Ham <myungjoo.ham@samsung.com>
|
||||
@@ -48,12 +55,15 @@ What: /sys/class/devfreq/.../trans_stat
|
||||
Date: October 2012
|
||||
Contact: MyungJoo Ham <myungjoo.ham@samsung.com>
|
||||
Description:
|
||||
This ABI shows the statistics of devfreq behavior on a
|
||||
specific device. It shows the time spent in each state and
|
||||
the number of transitions between states.
|
||||
This ABI shows or clears the statistics of devfreq behavior
|
||||
on a specific device. It shows the time spent in each state
|
||||
and the number of transitions between states.
|
||||
In order to activate this ABI, the devfreq target device
|
||||
driver should provide the list of available frequencies
|
||||
with its profile.
|
||||
with its profile. If need to reset the statistics of devfreq
|
||||
behavior on a specific device, enter 0(zero) to 'trans_stat'
|
||||
as following:
|
||||
echo 0 > /sys/class/devfreq/.../trans_stat
|
||||
|
||||
What: /sys/class/devfreq/.../userspace/set_freq
|
||||
Date: September 2011
|
||||
|
||||
@@ -196,6 +196,12 @@ Description:
|
||||
does not reflect it. Likewise, if one enables a deep state but a
|
||||
lighter state still is disabled, then this has no effect.
|
||||
|
||||
What: /sys/devices/system/cpu/cpuX/cpuidle/stateN/default_status
|
||||
Date: December 2019
|
||||
KernelVersion: v5.6
|
||||
Contact: Linux power management list <linux-pm@vger.kernel.org>
|
||||
Description:
|
||||
(RO) The default status of this state, "enabled" or "disabled".
|
||||
|
||||
What: /sys/devices/system/cpu/cpuX/cpuidle/stateN/residency
|
||||
Date: March 2014
|
||||
|
||||
@@ -407,3 +407,16 @@ Contact: Kalesh Singh <kaleshsingh96@gmail.com>
|
||||
Description:
|
||||
The /sys/power/suspend_stats/last_failed_step file contains
|
||||
the last failed step in the suspend/resume path.
|
||||
|
||||
What: /sys/power/sync_on_suspend
|
||||
Date: October 2019
|
||||
Contact: Jonas Meurer <jonas@freesources.org>
|
||||
Description:
|
||||
This file controls whether or not the kernel will sync()
|
||||
filesystems during system suspend (after freezing user space
|
||||
and before suspending devices).
|
||||
|
||||
Writing a "1" to this file enables the sync() and writing a "0"
|
||||
disables it. Reads from the file return the current value.
|
||||
The default is "1" if the build-time "SUSPEND_SKIP_SYNC" config
|
||||
flag is unset, or "0" otherwise.
|
||||
|
||||
@@ -506,6 +506,9 @@ object corresponding to it, as follows:
|
||||
``disable``
|
||||
Whether or not this idle state is disabled.
|
||||
|
||||
``default_status``
|
||||
The default status of this state, "enabled" or "disabled".
|
||||
|
||||
``latency``
|
||||
Exit latency of the idle state in microseconds.
|
||||
|
||||
|
||||
@@ -0,0 +1,246 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
.. include:: <isonum.txt>
|
||||
|
||||
==============================================
|
||||
``intel_idle`` CPU Idle Time Management Driver
|
||||
==============================================
|
||||
|
||||
:Copyright: |copy| 2020 Intel Corporation
|
||||
|
||||
:Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
|
||||
|
||||
|
||||
General Information
|
||||
===================
|
||||
|
||||
``intel_idle`` is a part of the
|
||||
:doc:`CPU idle time management subsystem <cpuidle>` in the Linux kernel
|
||||
(``CPUIdle``). It is the default CPU idle time management driver for the
|
||||
Nehalem and later generations of Intel processors, but the level of support for
|
||||
a particular processor model in it depends on whether or not it recognizes that
|
||||
processor model and may also depend on information coming from the platform
|
||||
firmware. [To understand ``intel_idle`` it is necessary to know how ``CPUIdle``
|
||||
works in general, so this is the time to get familiar with :doc:`cpuidle` if you
|
||||
have not done that yet.]
|
||||
|
||||
``intel_idle`` uses the ``MWAIT`` instruction to inform the processor that the
|
||||
logical CPU executing it is idle and so it may be possible to put some of the
|
||||
processor's functional blocks into low-power states. That instruction takes two
|
||||
arguments (passed in the ``EAX`` and ``ECX`` registers of the target CPU), the
|
||||
first of which, referred to as a *hint*, can be used by the processor to
|
||||
determine what can be done (for details refer to Intel Software Developer’s
|
||||
Manual [1]_). Accordingly, ``intel_idle`` refuses to work with processors in
|
||||
which the support for the ``MWAIT`` instruction has been disabled (for example,
|
||||
via the platform firmware configuration menu) or which do not support that
|
||||
instruction at all.
|
||||
|
||||
``intel_idle`` is not modular, so it cannot be unloaded, which means that the
|
||||
only way to pass early-configuration-time parameters to it is via the kernel
|
||||
command line.
|
||||
|
||||
|
||||
.. _intel-idle-enumeration-of-states:
|
||||
|
||||
Enumeration of Idle States
|
||||
==========================
|
||||
|
||||
Each ``MWAIT`` hint value is interpreted by the processor as a license to
|
||||
reconfigure itself in a certain way in order to save energy. The processor
|
||||
configurations (with reduced power draw) resulting from that are referred to
|
||||
as C-states (in the ACPI terminology) or idle states. The list of meaningful
|
||||
``MWAIT`` hint values and idle states (i.e. low-power configurations of the
|
||||
processor) corresponding to them depends on the processor model and it may also
|
||||
depend on the configuration of the platform.
|
||||
|
||||
In order to create a list of available idle states required by the ``CPUIdle``
|
||||
subsystem (see :ref:`idle-states-representation` in :doc:`cpuidle`),
|
||||
``intel_idle`` can use two sources of information: static tables of idle states
|
||||
for different processor models included in the driver itself and the ACPI tables
|
||||
of the system. The former are always used if the processor model at hand is
|
||||
recognized by ``intel_idle`` and the latter are used if that is required for
|
||||
the given processor model (which is the case for all server processor models
|
||||
recognized by ``intel_idle``) or if the processor model is not recognized.
|
||||
|
||||
If the ACPI tables are going to be used for building the list of available idle
|
||||
states, ``intel_idle`` first looks for a ``_CST`` object under one of the ACPI
|
||||
objects corresponding to the CPUs in the system (refer to the ACPI specification
|
||||
[2]_ for the description of ``_CST`` and its output package). Because the
|
||||
``CPUIdle`` subsystem expects that the list of idle states supplied by the
|
||||
driver will be suitable for all of the CPUs handled by it and ``intel_idle`` is
|
||||
registered as the ``CPUIdle`` driver for all of the CPUs in the system, the
|
||||
driver looks for the first ``_CST`` object returning at least one valid idle
|
||||
state description and such that all of the idle states included in its return
|
||||
package are of the FFH (Functional Fixed Hardware) type, which means that the
|
||||
``MWAIT`` instruction is expected to be used to tell the processor that it can
|
||||
enter one of them. The return package of that ``_CST`` is then assumed to be
|
||||
applicable to all of the other CPUs in the system and the idle state
|
||||
descriptions extracted from it are stored in a preliminary list of idle states
|
||||
coming from the ACPI tables. [This step is skipped if ``intel_idle`` is
|
||||
configured to ignore the ACPI tables; see `below <intel-idle-parameters_>`_.]
|
||||
|
||||
Next, the first (index 0) entry in the list of available idle states is
|
||||
initialized to represent a "polling idle state" (a pseudo-idle state in which
|
||||
the target CPU continuously fetches and executes instructions), and the
|
||||
subsequent (real) idle state entries are populated as follows.
|
||||
|
||||
If the processor model at hand is recognized by ``intel_idle``, there is a
|
||||
(static) table of idle state descriptions for it in the driver. In that case,
|
||||
the "internal" table is the primary source of information on idle states and the
|
||||
information from it is copied to the final list of available idle states. If
|
||||
using the ACPI tables for the enumeration of idle states is not required
|
||||
(depending on the processor model), all of the listed idle state are enabled by
|
||||
default (so all of them will be taken into consideration by ``CPUIdle``
|
||||
governors during CPU idle state selection). Otherwise, some of the listed idle
|
||||
states may not be enabled by default if there are no matching entries in the
|
||||
preliminary list of idle states coming from the ACPI tables. In that case user
|
||||
space still can enable them later (on a per-CPU basis) with the help of
|
||||
the ``disable`` idle state attribute in ``sysfs`` (see
|
||||
:ref:`idle-states-representation` in :doc:`cpuidle`). This basically means that
|
||||
the idle states "known" to the driver may not be enabled by default if they have
|
||||
not been exposed by the platform firmware (through the ACPI tables).
|
||||
|
||||
If the given processor model is not recognized by ``intel_idle``, but it
|
||||
supports ``MWAIT``, the preliminary list of idle states coming from the ACPI
|
||||
tables is used for building the final list that will be supplied to the
|
||||
``CPUIdle`` core during driver registration. For each idle state in that list,
|
||||
the description, ``MWAIT`` hint and exit latency are copied to the corresponding
|
||||
entry in the final list of idle states. The name of the idle state represented
|
||||
by it (to be returned by the ``name`` idle state attribute in ``sysfs``) is
|
||||
"CX_ACPI", where X is the index of that idle state in the final list (note that
|
||||
the minimum value of X is 1, because 0 is reserved for the "polling" state), and
|
||||
its target residency is based on the exit latency value. Specifically, for
|
||||
C1-type idle states the exit latency value is also used as the target residency
|
||||
(for compatibility with the majority of the "internal" tables of idle states for
|
||||
various processor models recognized by ``intel_idle``) and for the other idle
|
||||
state types (C2 and C3) the target residency value is 3 times the exit latency
|
||||
(again, that is because it reflects the target residency to exit latency ratio
|
||||
in the majority of cases for the processor models recognized by ``intel_idle``).
|
||||
All of the idle states in the final list are enabled by default in this case.
|
||||
|
||||
|
||||
.. _intel-idle-initialization:
|
||||
|
||||
Initialization
|
||||
==============
|
||||
|
||||
The initialization of ``intel_idle`` starts with checking if the kernel command
|
||||
line options forbid the use of the ``MWAIT`` instruction. If that is the case,
|
||||
an error code is returned right away.
|
||||
|
||||
The next step is to check whether or not the processor model is known to the
|
||||
driver, which determines the idle states enumeration method (see
|
||||
`above <intel-idle-enumeration-of-states_>`_), and whether or not the processor
|
||||
supports ``MWAIT`` (the initialization fails if that is not the case). Then,
|
||||
the ``MWAIT`` support in the processor is enumerated through ``CPUID`` and the
|
||||
driver initialization fails if the level of support is not as expected (for
|
||||
example, if the total number of ``MWAIT`` substates returned is 0).
|
||||
|
||||
Next, if the driver is not configured to ignore the ACPI tables (see
|
||||
`below <intel-idle-parameters_>`_), the idle states information provided by the
|
||||
platform firmware is extracted from them.
|
||||
|
||||
Then, ``CPUIdle`` device objects are allocated for all CPUs and the list of
|
||||
available idle states is created as explained
|
||||
`above <intel-idle-enumeration-of-states_>`_.
|
||||
|
||||
Finally, ``intel_idle`` is registered with the help of cpuidle_register_driver()
|
||||
as the ``CPUIdle`` driver for all CPUs in the system and a CPU online callback
|
||||
for configuring individual CPUs is registered via cpuhp_setup_state(), which
|
||||
(among other things) causes the callback routine to be invoked for all of the
|
||||
CPUs present in the system at that time (each CPU executes its own instance of
|
||||
the callback routine). That routine registers a ``CPUIdle`` device for the CPU
|
||||
running it (which enables the ``CPUIdle`` subsystem to operate that CPU) and
|
||||
optionally performs some CPU-specific initialization actions that may be
|
||||
required for the given processor model.
|
||||
|
||||
|
||||
.. _intel-idle-parameters:
|
||||
|
||||
Kernel Command Line Options and Module Parameters
|
||||
=================================================
|
||||
|
||||
The *x86* architecture support code recognizes three kernel command line
|
||||
options related to CPU idle time management: ``idle=poll``, ``idle=halt``,
|
||||
and ``idle=nomwait``. If any of them is present in the kernel command line, the
|
||||
``MWAIT`` instruction is not allowed to be used, so the initialization of
|
||||
``intel_idle`` will fail.
|
||||
|
||||
Apart from that there are two module parameters recognized by ``intel_idle``
|
||||
itself that can be set via the kernel command line (they cannot be updated via
|
||||
sysfs, so that is the only way to change their values).
|
||||
|
||||
The ``max_cstate`` parameter value is the maximum idle state index in the list
|
||||
of idle states supplied to the ``CPUIdle`` core during the registration of the
|
||||
driver. It is also the maximum number of regular (non-polling) idle states that
|
||||
can be used by ``intel_idle``, so the enumeration of idle states is terminated
|
||||
after finding that number of usable idle states (the other idle states that
|
||||
potentially might have been used if ``max_cstate`` had been greater are not
|
||||
taken into consideration at all). Setting ``max_cstate`` can prevent
|
||||
``intel_idle`` from exposing idle states that are regarded as "too deep" for
|
||||
some reason to the ``CPUIdle`` core, but it does so by making them effectively
|
||||
invisible until the system is shut down and started again which may not always
|
||||
be desirable. In practice, it is only really necessary to do that if the idle
|
||||
states in question cannot be enabled during system startup, because in the
|
||||
working state of the system the CPU power management quality of service (PM
|
||||
QoS) feature can be used to prevent ``CPUIdle`` from touching those idle states
|
||||
even if they have been enumerated (see :ref:`cpu-pm-qos` in :doc:`cpuidle`).
|
||||
Setting ``max_cstate`` to 0 causes the ``intel_idle`` initialization to fail.
|
||||
|
||||
The ``noacpi`` module parameter (which is recognized by ``intel_idle`` if the
|
||||
kernel has been configured with ACPI support), can be set to make the driver
|
||||
ignore the system's ACPI tables entirely (it is unset by default).
|
||||
|
||||
|
||||
.. _intel-idle-core-and-package-idle-states:
|
||||
|
||||
Core and Package Levels of Idle States
|
||||
======================================
|
||||
|
||||
Typically, in a processor supporting the ``MWAIT`` instruction there are (at
|
||||
least) two levels of idle states (or C-states). One level, referred to as
|
||||
"core C-states", covers individual cores in the processor, whereas the other
|
||||
level, referred to as "package C-states", covers the entire processor package
|
||||
and it may also involve other components of the system (GPUs, memory
|
||||
controllers, I/O hubs etc.).
|
||||
|
||||
Some of the ``MWAIT`` hint values allow the processor to use core C-states only
|
||||
(most importantly, that is the case for the ``MWAIT`` hint value corresponding
|
||||
to the ``C1`` idle state), but the majority of them give it a license to put
|
||||
the target core (i.e. the core containing the logical CPU executing ``MWAIT``
|
||||
with the given hint value) into a specific core C-state and then (if possible)
|
||||
to enter a specific package C-state at the deeper level. For example, the
|
||||
``MWAIT`` hint value representing the ``C3`` idle state allows the processor to
|
||||
put the target core into the low-power state referred to as "core ``C3``" (or
|
||||
``CC3``), which happens if all of the logical CPUs (SMT siblings) in that core
|
||||
have executed ``MWAIT`` with the ``C3`` hint value (or with a hint value
|
||||
representing a deeper idle state), and in addition to that (in the majority of
|
||||
cases) it gives the processor a license to put the entire package (possibly
|
||||
including some non-CPU components such as a GPU or a memory controller) into the
|
||||
low-power state referred to as "package ``C3``" (or ``PC3``), which happens if
|
||||
all of the cores have gone into the ``CC3`` state and (possibly) some additional
|
||||
conditions are satisfied (for instance, if the GPU is covered by ``PC3``, it may
|
||||
be required to be in a certain GPU-specific low-power state for ``PC3`` to be
|
||||
reachable).
|
||||
|
||||
As a rule, there is no simple way to make the processor use core C-states only
|
||||
if the conditions for entering the corresponding package C-states are met, so
|
||||
the logical CPU executing ``MWAIT`` with a hint value that is not core-level
|
||||
only (like for ``C1``) must always assume that this may cause the processor to
|
||||
enter a package C-state. [That is why the exit latency and target residency
|
||||
values corresponding to the majority of ``MWAIT`` hint values in the "internal"
|
||||
tables of idle states in ``intel_idle`` reflect the properties of package
|
||||
C-states.] If using package C-states is not desirable at all, either
|
||||
:ref:`PM QoS <cpu-pm-qos>` or the ``max_cstate`` module parameter of
|
||||
``intel_idle`` described `above <intel-idle-parameters_>`_ must be used to
|
||||
restrict the range of permissible idle states to the ones with core-level only
|
||||
``MWAIT`` hint values (like ``C1``).
|
||||
|
||||
|
||||
References
|
||||
==========
|
||||
|
||||
.. [1] *Intel® 64 and IA-32 Architectures Software Developer’s Manual Volume 2B*,
|
||||
https://www.intel.com/content/www/us/en/architecture-and-technology/64-ia-32-architectures-software-developer-vol-2b-manual.html
|
||||
|
||||
.. [2] *Advanced Configuration and Power Interface (ACPI) Specification*,
|
||||
https://uefi.org/specifications
|
||||
@@ -8,6 +8,7 @@ Working-State Power Management
|
||||
:maxdepth: 2
|
||||
|
||||
cpuidle
|
||||
intel_idle
|
||||
cpufreq
|
||||
intel_pstate
|
||||
intel_epb
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/memory-controllers/fsl/imx8m-ddrc.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: i.MX8M DDR Controller
|
||||
|
||||
maintainers:
|
||||
- Leonard Crestez <leonard.crestez@nxp.com>
|
||||
|
||||
description:
|
||||
The DDRC block is integrated in i.MX8M for interfacing with DDR based
|
||||
memories.
|
||||
|
||||
It supports switching between different frequencies at runtime but during
|
||||
this process RAM itself becomes briefly inaccessible so actual frequency
|
||||
switching is implemented by TF-A code which runs from a SRAM area.
|
||||
|
||||
The Linux driver for the DDRC doesn't even map registers (they're included
|
||||
for the sake of "describing hardware"), it mostly just exposes firmware
|
||||
capabilities through standard Linux mechanism like devfreq and OPP tables.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
items:
|
||||
- enum:
|
||||
- fsl,imx8mn-ddrc
|
||||
- fsl,imx8mm-ddrc
|
||||
- fsl,imx8mq-ddrc
|
||||
- const: fsl,imx8m-ddrc
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
description:
|
||||
Base address and size of DDRC CTL area.
|
||||
This is not currently mapped by the imx8m-ddrc driver.
|
||||
|
||||
clocks:
|
||||
maxItems: 4
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: core
|
||||
- const: pll
|
||||
- const: alt
|
||||
- const: apb
|
||||
|
||||
operating-points-v2: true
|
||||
opp-table: true
|
||||
|
||||
required:
|
||||
- reg
|
||||
- compatible
|
||||
- clocks
|
||||
- clock-names
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/imx8mm-clock.h>
|
||||
ddrc: memory-controller@3d400000 {
|
||||
compatible = "fsl,imx8mm-ddrc", "fsl,imx8m-ddrc";
|
||||
reg = <0x3d400000 0x400000>;
|
||||
clock-names = "core", "pll", "alt", "apb";
|
||||
clocks = <&clk IMX8MM_CLK_DRAM_CORE>,
|
||||
<&clk IMX8MM_DRAM_PLL>,
|
||||
<&clk IMX8MM_CLK_DRAM_ALT>,
|
||||
<&clk IMX8MM_CLK_DRAM_APB>;
|
||||
operating-points-v2 = <&ddrc_opp_table>;
|
||||
};
|
||||
@@ -0,0 +1,130 @@
|
||||
QCOM CPR (Core Power Reduction)
|
||||
|
||||
CPR (Core Power Reduction) is a technology to reduce core power on a CPU
|
||||
or other device. Each OPP of a device corresponds to a "corner" that has
|
||||
a range of valid voltages for a particular frequency. While the device is
|
||||
running at a particular frequency, CPR monitors dynamic factors such as
|
||||
temperature, etc. and suggests adjustments to the voltage to save power
|
||||
and meet silicon characteristic requirements.
|
||||
|
||||
- compatible:
|
||||
Usage: required
|
||||
Value type: <string>
|
||||
Definition: should be "qcom,qcs404-cpr", "qcom,cpr" for qcs404
|
||||
|
||||
- reg:
|
||||
Usage: required
|
||||
Value type: <prop-encoded-array>
|
||||
Definition: base address and size of the rbcpr register region
|
||||
|
||||
- interrupts:
|
||||
Usage: required
|
||||
Value type: <prop-encoded-array>
|
||||
Definition: should specify the CPR interrupt
|
||||
|
||||
- clocks:
|
||||
Usage: required
|
||||
Value type: <prop-encoded-array>
|
||||
Definition: phandle to the reference clock
|
||||
|
||||
- clock-names:
|
||||
Usage: required
|
||||
Value type: <stringlist>
|
||||
Definition: must be "ref"
|
||||
|
||||
- vdd-apc-supply:
|
||||
Usage: required
|
||||
Value type: <phandle>
|
||||
Definition: phandle to the vdd-apc-supply regulator
|
||||
|
||||
- #power-domain-cells:
|
||||
Usage: required
|
||||
Value type: <u32>
|
||||
Definition: should be 0
|
||||
|
||||
- operating-points-v2:
|
||||
Usage: required
|
||||
Value type: <phandle>
|
||||
Definition: A phandle to the OPP table containing the
|
||||
performance states supported by the CPR
|
||||
power domain
|
||||
|
||||
- acc-syscon:
|
||||
Usage: optional
|
||||
Value type: <phandle>
|
||||
Definition: phandle to syscon for writing ACC settings
|
||||
|
||||
- nvmem-cells:
|
||||
Usage: required
|
||||
Value type: <phandle>
|
||||
Definition: phandle to nvmem cells containing the data
|
||||
that makes up a fuse corner, for each fuse corner.
|
||||
As well as the CPR fuse revision.
|
||||
|
||||
- nvmem-cell-names:
|
||||
Usage: required
|
||||
Value type: <stringlist>
|
||||
Definition: should be "cpr_quotient_offset1", "cpr_quotient_offset2",
|
||||
"cpr_quotient_offset3", "cpr_init_voltage1",
|
||||
"cpr_init_voltage2", "cpr_init_voltage3", "cpr_quotient1",
|
||||
"cpr_quotient2", "cpr_quotient3", "cpr_ring_osc1",
|
||||
"cpr_ring_osc2", "cpr_ring_osc3", "cpr_fuse_revision"
|
||||
for qcs404.
|
||||
|
||||
Example:
|
||||
|
||||
cpr_opp_table: cpr-opp-table {
|
||||
compatible = "operating-points-v2-qcom-level";
|
||||
|
||||
cpr_opp1: opp1 {
|
||||
opp-level = <1>;
|
||||
qcom,opp-fuse-level = <1>;
|
||||
};
|
||||
cpr_opp2: opp2 {
|
||||
opp-level = <2>;
|
||||
qcom,opp-fuse-level = <2>;
|
||||
};
|
||||
cpr_opp3: opp3 {
|
||||
opp-level = <3>;
|
||||
qcom,opp-fuse-level = <3>;
|
||||
};
|
||||
};
|
||||
|
||||
power-controller@b018000 {
|
||||
compatible = "qcom,qcs404-cpr", "qcom,cpr";
|
||||
reg = <0x0b018000 0x1000>;
|
||||
interrupts = <0 15 IRQ_TYPE_EDGE_RISING>;
|
||||
clocks = <&xo_board>;
|
||||
clock-names = "ref";
|
||||
vdd-apc-supply = <&pms405_s3>;
|
||||
#power-domain-cells = <0>;
|
||||
operating-points-v2 = <&cpr_opp_table>;
|
||||
acc-syscon = <&tcsr>;
|
||||
|
||||
nvmem-cells = <&cpr_efuse_quot_offset1>,
|
||||
<&cpr_efuse_quot_offset2>,
|
||||
<&cpr_efuse_quot_offset3>,
|
||||
<&cpr_efuse_init_voltage1>,
|
||||
<&cpr_efuse_init_voltage2>,
|
||||
<&cpr_efuse_init_voltage3>,
|
||||
<&cpr_efuse_quot1>,
|
||||
<&cpr_efuse_quot2>,
|
||||
<&cpr_efuse_quot3>,
|
||||
<&cpr_efuse_ring1>,
|
||||
<&cpr_efuse_ring2>,
|
||||
<&cpr_efuse_ring3>,
|
||||
<&cpr_efuse_revision>;
|
||||
nvmem-cell-names = "cpr_quotient_offset1",
|
||||
"cpr_quotient_offset2",
|
||||
"cpr_quotient_offset3",
|
||||
"cpr_init_voltage1",
|
||||
"cpr_init_voltage2",
|
||||
"cpr_init_voltage3",
|
||||
"cpr_quotient1",
|
||||
"cpr_quotient2",
|
||||
"cpr_quotient3",
|
||||
"cpr_ring_osc1",
|
||||
"cpr_ring_osc2",
|
||||
"cpr_ring_osc3",
|
||||
"cpr_fuse_revision";
|
||||
};
|
||||
@@ -13715,6 +13715,14 @@ S: Maintained
|
||||
F: Documentation/devicetree/bindings/opp/qcom-nvmem-cpufreq.txt
|
||||
F: drivers/cpufreq/qcom-cpufreq-nvmem.c
|
||||
|
||||
QUALCOMM CORE POWER REDUCTION (CPR) AVS DRIVER
|
||||
M: Niklas Cassel <nks@flawful.org>
|
||||
L: linux-pm@vger.kernel.org
|
||||
L: linux-arm-msm@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/power/avs/qcom,cpr.txt
|
||||
F: drivers/power/avs/qcom-cpr.c
|
||||
|
||||
QUALCOMM EMAC GIGABIT ETHERNET DRIVER
|
||||
M: Timur Tabi <timur@kernel.org>
|
||||
L: netdev@vger.kernel.org
|
||||
|
||||
@@ -111,6 +111,7 @@
|
||||
|
||||
#define INTEL_FAM6_ATOM_TREMONT_D 0x86 /* Jacobsville */
|
||||
#define INTEL_FAM6_ATOM_TREMONT 0x96 /* Elkhart Lake */
|
||||
#define INTEL_FAM6_ATOM_TREMONT_L 0x9C /* Jasper Lake */
|
||||
|
||||
/* Xeon Phi */
|
||||
|
||||
|
||||
@@ -241,6 +241,7 @@ config ACPI_CPU_FREQ_PSS
|
||||
|
||||
config ACPI_PROCESSOR_CSTATE
|
||||
def_bool y
|
||||
depends on ACPI_PROCESSOR
|
||||
depends on IA64 || X86
|
||||
|
||||
config ACPI_PROCESSOR_IDLE
|
||||
|
||||
@@ -705,3 +705,185 @@ void __init acpi_processor_init(void)
|
||||
acpi_scan_add_handler_with_hotplug(&processor_handler, "processor");
|
||||
acpi_scan_add_handler(&processor_container_handler);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ACPI_PROCESSOR_CSTATE
|
||||
/**
|
||||
* acpi_processor_claim_cst_control - Request _CST control from the platform.
|
||||
*/
|
||||
bool acpi_processor_claim_cst_control(void)
|
||||
{
|
||||
static bool cst_control_claimed;
|
||||
acpi_status status;
|
||||
|
||||
if (!acpi_gbl_FADT.cst_control || cst_control_claimed)
|
||||
return true;
|
||||
|
||||
status = acpi_os_write_port(acpi_gbl_FADT.smi_command,
|
||||
acpi_gbl_FADT.cst_control, 8);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
pr_warn("ACPI: Failed to claim processor _CST control\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
cst_control_claimed = true;
|
||||
return true;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(acpi_processor_claim_cst_control);
|
||||
|
||||
/**
|
||||
* acpi_processor_evaluate_cst - Evaluate the processor _CST control method.
|
||||
* @handle: ACPI handle of the processor object containing the _CST.
|
||||
* @cpu: The numeric ID of the target CPU.
|
||||
* @info: Object write the C-states information into.
|
||||
*
|
||||
* Extract the C-state information for the given CPU from the output of the _CST
|
||||
* control method under the corresponding ACPI processor object (or processor
|
||||
* device object) and populate @info with it.
|
||||
*
|
||||
* If any ACPI_ADR_SPACE_FIXED_HARDWARE C-states are found, invoke
|
||||
* acpi_processor_ffh_cstate_probe() to verify them and update the
|
||||
* cpu_cstate_entry data for @cpu.
|
||||
*/
|
||||
int acpi_processor_evaluate_cst(acpi_handle handle, u32 cpu,
|
||||
struct acpi_processor_power *info)
|
||||
{
|
||||
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
|
||||
union acpi_object *cst;
|
||||
acpi_status status;
|
||||
u64 count;
|
||||
int last_index = 0;
|
||||
int i, ret = 0;
|
||||
|
||||
status = acpi_evaluate_object(handle, "_CST", NULL, &buffer);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
acpi_handle_debug(handle, "No _CST\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
cst = buffer.pointer;
|
||||
|
||||
/* There must be at least 2 elements. */
|
||||
if (!cst || cst->type != ACPI_TYPE_PACKAGE || cst->package.count < 2) {
|
||||
acpi_handle_warn(handle, "Invalid _CST output\n");
|
||||
ret = -EFAULT;
|
||||
goto end;
|
||||
}
|
||||
|
||||
count = cst->package.elements[0].integer.value;
|
||||
|
||||
/* Validate the number of C-states. */
|
||||
if (count < 1 || count != cst->package.count - 1) {
|
||||
acpi_handle_warn(handle, "Inconsistent _CST data\n");
|
||||
ret = -EFAULT;
|
||||
goto end;
|
||||
}
|
||||
|
||||
for (i = 1; i <= count; i++) {
|
||||
union acpi_object *element;
|
||||
union acpi_object *obj;
|
||||
struct acpi_power_register *reg;
|
||||
struct acpi_processor_cx cx;
|
||||
|
||||
/*
|
||||
* If there is not enough space for all C-states, skip the
|
||||
* excess ones and log a warning.
|
||||
*/
|
||||
if (last_index >= ACPI_PROCESSOR_MAX_POWER - 1) {
|
||||
acpi_handle_warn(handle,
|
||||
"No room for more idle states (limit: %d)\n",
|
||||
ACPI_PROCESSOR_MAX_POWER - 1);
|
||||
break;
|
||||
}
|
||||
|
||||
memset(&cx, 0, sizeof(cx));
|
||||
|
||||
element = &cst->package.elements[i];
|
||||
if (element->type != ACPI_TYPE_PACKAGE)
|
||||
continue;
|
||||
|
||||
if (element->package.count != 4)
|
||||
continue;
|
||||
|
||||
obj = &element->package.elements[0];
|
||||
|
||||
if (obj->type != ACPI_TYPE_BUFFER)
|
||||
continue;
|
||||
|
||||
reg = (struct acpi_power_register *)obj->buffer.pointer;
|
||||
|
||||
obj = &element->package.elements[1];
|
||||
if (obj->type != ACPI_TYPE_INTEGER)
|
||||
continue;
|
||||
|
||||
cx.type = obj->integer.value;
|
||||
/*
|
||||
* There are known cases in which the _CST output does not
|
||||
* contain C1, so if the type of the first state found is not
|
||||
* C1, leave an empty slot for C1 to be filled in later.
|
||||
*/
|
||||
if (i == 1 && cx.type != ACPI_STATE_C1)
|
||||
last_index = 1;
|
||||
|
||||
cx.address = reg->address;
|
||||
cx.index = last_index + 1;
|
||||
|
||||
if (reg->space_id == ACPI_ADR_SPACE_FIXED_HARDWARE) {
|
||||
if (!acpi_processor_ffh_cstate_probe(cpu, &cx, reg)) {
|
||||
/*
|
||||
* In the majority of cases _CST describes C1 as
|
||||
* a FIXED_HARDWARE C-state, but if the command
|
||||
* line forbids using MWAIT, use CSTATE_HALT for
|
||||
* C1 regardless.
|
||||
*/
|
||||
if (cx.type == ACPI_STATE_C1 &&
|
||||
boot_option_idle_override == IDLE_NOMWAIT) {
|
||||
cx.entry_method = ACPI_CSTATE_HALT;
|
||||
snprintf(cx.desc, ACPI_CX_DESC_LEN, "ACPI HLT");
|
||||
} else {
|
||||
cx.entry_method = ACPI_CSTATE_FFH;
|
||||
}
|
||||
} else if (cx.type == ACPI_STATE_C1) {
|
||||
/*
|
||||
* In the special case of C1, FIXED_HARDWARE can
|
||||
* be handled by executing the HLT instruction.
|
||||
*/
|
||||
cx.entry_method = ACPI_CSTATE_HALT;
|
||||
snprintf(cx.desc, ACPI_CX_DESC_LEN, "ACPI HLT");
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
} else if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_IO) {
|
||||
cx.entry_method = ACPI_CSTATE_SYSTEMIO;
|
||||
snprintf(cx.desc, ACPI_CX_DESC_LEN, "ACPI IOPORT 0x%x",
|
||||
cx.address);
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cx.type == ACPI_STATE_C1)
|
||||
cx.valid = 1;
|
||||
|
||||
obj = &element->package.elements[2];
|
||||
if (obj->type != ACPI_TYPE_INTEGER)
|
||||
continue;
|
||||
|
||||
cx.latency = obj->integer.value;
|
||||
|
||||
obj = &element->package.elements[3];
|
||||
if (obj->type != ACPI_TYPE_INTEGER)
|
||||
continue;
|
||||
|
||||
memcpy(&info->states[++last_index], &cx, sizeof(cx));
|
||||
}
|
||||
|
||||
acpi_handle_info(handle, "Found %d idle states\n", last_index);
|
||||
|
||||
info->count = last_index;
|
||||
|
||||
end:
|
||||
kfree(buffer.pointer);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(acpi_processor_evaluate_cst);
|
||||
#endif /* CONFIG_ACPI_PROCESSOR_CSTATE */
|
||||
|
||||
+15
-159
@@ -299,164 +299,24 @@ static int acpi_processor_get_power_info_default(struct acpi_processor *pr)
|
||||
|
||||
static int acpi_processor_get_power_info_cst(struct acpi_processor *pr)
|
||||
{
|
||||
acpi_status status;
|
||||
u64 count;
|
||||
int current_count;
|
||||
int i, ret = 0;
|
||||
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
|
||||
union acpi_object *cst;
|
||||
int ret;
|
||||
|
||||
if (nocst)
|
||||
return -ENODEV;
|
||||
|
||||
current_count = 0;
|
||||
ret = acpi_processor_evaluate_cst(pr->handle, pr->id, &pr->power);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
status = acpi_evaluate_object(pr->handle, "_CST", NULL, &buffer);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No _CST, giving up\n"));
|
||||
return -ENODEV;
|
||||
}
|
||||
/*
|
||||
* It is expected that there will be at least 2 states, C1 and
|
||||
* something else (C2 or C3), so fail if that is not the case.
|
||||
*/
|
||||
if (pr->power.count < 2)
|
||||
return -EFAULT;
|
||||
|
||||
cst = buffer.pointer;
|
||||
|
||||
/* There must be at least 2 elements */
|
||||
if (!cst || (cst->type != ACPI_TYPE_PACKAGE) || cst->package.count < 2) {
|
||||
pr_err("not enough elements in _CST\n");
|
||||
ret = -EFAULT;
|
||||
goto end;
|
||||
}
|
||||
|
||||
count = cst->package.elements[0].integer.value;
|
||||
|
||||
/* Validate number of power states. */
|
||||
if (count < 1 || count != cst->package.count - 1) {
|
||||
pr_err("count given by _CST is not valid\n");
|
||||
ret = -EFAULT;
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* Tell driver that at least _CST is supported. */
|
||||
pr->flags.has_cst = 1;
|
||||
|
||||
for (i = 1; i <= count; i++) {
|
||||
union acpi_object *element;
|
||||
union acpi_object *obj;
|
||||
struct acpi_power_register *reg;
|
||||
struct acpi_processor_cx cx;
|
||||
|
||||
memset(&cx, 0, sizeof(cx));
|
||||
|
||||
element = &(cst->package.elements[i]);
|
||||
if (element->type != ACPI_TYPE_PACKAGE)
|
||||
continue;
|
||||
|
||||
if (element->package.count != 4)
|
||||
continue;
|
||||
|
||||
obj = &(element->package.elements[0]);
|
||||
|
||||
if (obj->type != ACPI_TYPE_BUFFER)
|
||||
continue;
|
||||
|
||||
reg = (struct acpi_power_register *)obj->buffer.pointer;
|
||||
|
||||
if (reg->space_id != ACPI_ADR_SPACE_SYSTEM_IO &&
|
||||
(reg->space_id != ACPI_ADR_SPACE_FIXED_HARDWARE))
|
||||
continue;
|
||||
|
||||
/* There should be an easy way to extract an integer... */
|
||||
obj = &(element->package.elements[1]);
|
||||
if (obj->type != ACPI_TYPE_INTEGER)
|
||||
continue;
|
||||
|
||||
cx.type = obj->integer.value;
|
||||
/*
|
||||
* Some buggy BIOSes won't list C1 in _CST -
|
||||
* Let acpi_processor_get_power_info_default() handle them later
|
||||
*/
|
||||
if (i == 1 && cx.type != ACPI_STATE_C1)
|
||||
current_count++;
|
||||
|
||||
cx.address = reg->address;
|
||||
cx.index = current_count + 1;
|
||||
|
||||
cx.entry_method = ACPI_CSTATE_SYSTEMIO;
|
||||
if (reg->space_id == ACPI_ADR_SPACE_FIXED_HARDWARE) {
|
||||
if (acpi_processor_ffh_cstate_probe
|
||||
(pr->id, &cx, reg) == 0) {
|
||||
cx.entry_method = ACPI_CSTATE_FFH;
|
||||
} else if (cx.type == ACPI_STATE_C1) {
|
||||
/*
|
||||
* C1 is a special case where FIXED_HARDWARE
|
||||
* can be handled in non-MWAIT way as well.
|
||||
* In that case, save this _CST entry info.
|
||||
* Otherwise, ignore this info and continue.
|
||||
*/
|
||||
cx.entry_method = ACPI_CSTATE_HALT;
|
||||
snprintf(cx.desc, ACPI_CX_DESC_LEN, "ACPI HLT");
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
if (cx.type == ACPI_STATE_C1 &&
|
||||
(boot_option_idle_override == IDLE_NOMWAIT)) {
|
||||
/*
|
||||
* In most cases the C1 space_id obtained from
|
||||
* _CST object is FIXED_HARDWARE access mode.
|
||||
* But when the option of idle=halt is added,
|
||||
* the entry_method type should be changed from
|
||||
* CSTATE_FFH to CSTATE_HALT.
|
||||
* When the option of idle=nomwait is added,
|
||||
* the C1 entry_method type should be
|
||||
* CSTATE_HALT.
|
||||
*/
|
||||
cx.entry_method = ACPI_CSTATE_HALT;
|
||||
snprintf(cx.desc, ACPI_CX_DESC_LEN, "ACPI HLT");
|
||||
}
|
||||
} else {
|
||||
snprintf(cx.desc, ACPI_CX_DESC_LEN, "ACPI IOPORT 0x%x",
|
||||
cx.address);
|
||||
}
|
||||
|
||||
if (cx.type == ACPI_STATE_C1) {
|
||||
cx.valid = 1;
|
||||
}
|
||||
|
||||
obj = &(element->package.elements[2]);
|
||||
if (obj->type != ACPI_TYPE_INTEGER)
|
||||
continue;
|
||||
|
||||
cx.latency = obj->integer.value;
|
||||
|
||||
obj = &(element->package.elements[3]);
|
||||
if (obj->type != ACPI_TYPE_INTEGER)
|
||||
continue;
|
||||
|
||||
current_count++;
|
||||
memcpy(&(pr->power.states[current_count]), &cx, sizeof(cx));
|
||||
|
||||
/*
|
||||
* We support total ACPI_PROCESSOR_MAX_POWER - 1
|
||||
* (From 1 through ACPI_PROCESSOR_MAX_POWER - 1)
|
||||
*/
|
||||
if (current_count >= (ACPI_PROCESSOR_MAX_POWER - 1)) {
|
||||
pr_warn("Limiting number of power states to max (%d)\n",
|
||||
ACPI_PROCESSOR_MAX_POWER);
|
||||
pr_warn("Please increase ACPI_PROCESSOR_MAX_POWER if needed.\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %d power states\n",
|
||||
current_count));
|
||||
|
||||
/* Validate number of power states discovered */
|
||||
if (current_count < 2)
|
||||
ret = -EFAULT;
|
||||
|
||||
end:
|
||||
kfree(buffer.pointer);
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void acpi_processor_power_verify_c3(struct acpi_processor *pr,
|
||||
@@ -909,7 +769,6 @@ static int acpi_processor_setup_cstates(struct acpi_processor *pr)
|
||||
|
||||
static inline void acpi_processor_cstate_first_run_checks(void)
|
||||
{
|
||||
acpi_status status;
|
||||
static int first_run;
|
||||
|
||||
if (first_run)
|
||||
@@ -921,13 +780,10 @@ static inline void acpi_processor_cstate_first_run_checks(void)
|
||||
max_cstate);
|
||||
first_run++;
|
||||
|
||||
if (acpi_gbl_FADT.cst_control && !nocst) {
|
||||
status = acpi_os_write_port(acpi_gbl_FADT.smi_command,
|
||||
acpi_gbl_FADT.cst_control, 8);
|
||||
if (ACPI_FAILURE(status))
|
||||
ACPI_EXCEPTION((AE_INFO, status,
|
||||
"Notifying BIOS of _CST ability failed"));
|
||||
}
|
||||
if (nocst)
|
||||
return;
|
||||
|
||||
acpi_processor_claim_cst_control();
|
||||
}
|
||||
#else
|
||||
|
||||
|
||||
@@ -1006,8 +1006,10 @@ int __pm_runtime_idle(struct device *dev, int rpmflags)
|
||||
int retval;
|
||||
|
||||
if (rpmflags & RPM_GET_PUT) {
|
||||
if (!atomic_dec_and_test(&dev->power.usage_count))
|
||||
if (!atomic_dec_and_test(&dev->power.usage_count)) {
|
||||
trace_rpm_usage_rcuidle(dev, rpmflags);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
might_sleep_if(!(rpmflags & RPM_ASYNC) && !dev->power.irq_safe);
|
||||
@@ -1038,8 +1040,10 @@ int __pm_runtime_suspend(struct device *dev, int rpmflags)
|
||||
int retval;
|
||||
|
||||
if (rpmflags & RPM_GET_PUT) {
|
||||
if (!atomic_dec_and_test(&dev->power.usage_count))
|
||||
if (!atomic_dec_and_test(&dev->power.usage_count)) {
|
||||
trace_rpm_usage_rcuidle(dev, rpmflags);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
might_sleep_if(!(rpmflags & RPM_ASYNC) && !dev->power.irq_safe);
|
||||
@@ -1101,6 +1105,7 @@ int pm_runtime_get_if_in_use(struct device *dev)
|
||||
retval = dev->power.disable_depth > 0 ? -EINVAL :
|
||||
dev->power.runtime_status == RPM_ACTIVE
|
||||
&& atomic_inc_not_zero(&dev->power.usage_count);
|
||||
trace_rpm_usage_rcuidle(dev, 0);
|
||||
spin_unlock_irqrestore(&dev->power.lock, flags);
|
||||
return retval;
|
||||
}
|
||||
@@ -1434,6 +1439,8 @@ void pm_runtime_allow(struct device *dev)
|
||||
dev->power.runtime_auto = true;
|
||||
if (atomic_dec_and_test(&dev->power.usage_count))
|
||||
rpm_idle(dev, RPM_AUTO | RPM_ASYNC);
|
||||
else
|
||||
trace_rpm_usage_rcuidle(dev, RPM_AUTO | RPM_ASYNC);
|
||||
|
||||
out:
|
||||
spin_unlock_irq(&dev->power.lock);
|
||||
@@ -1501,6 +1508,8 @@ static void update_autosuspend(struct device *dev, int old_delay, int old_use)
|
||||
if (!old_use || old_delay >= 0) {
|
||||
atomic_inc(&dev->power.usage_count);
|
||||
rpm_resume(dev, 0);
|
||||
} else {
|
||||
trace_rpm_usage_rcuidle(dev, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1125,6 +1125,9 @@ static void *wakeup_sources_stats_seq_next(struct seq_file *m,
|
||||
break;
|
||||
}
|
||||
|
||||
if (!next_ws)
|
||||
print_wakeup_source_stats(m, &deleted_ws);
|
||||
|
||||
return next_ws;
|
||||
}
|
||||
|
||||
|
||||
@@ -455,6 +455,8 @@ static unsigned int brcm_avs_cpufreq_get(unsigned int cpu)
|
||||
struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
|
||||
struct private_data *priv = policy->driver_data;
|
||||
|
||||
cpufreq_cpu_put(policy);
|
||||
|
||||
return brcm_avs_get_frequency(priv->base);
|
||||
}
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
static struct cppc_cpudata **all_cpu_data;
|
||||
|
||||
struct cppc_workaround_oem_info {
|
||||
char oem_id[ACPI_OEM_ID_SIZE +1];
|
||||
char oem_id[ACPI_OEM_ID_SIZE + 1];
|
||||
char oem_table_id[ACPI_OEM_TABLE_ID_SIZE + 1];
|
||||
u32 oem_revision;
|
||||
};
|
||||
@@ -93,9 +93,13 @@ static void cppc_check_hisi_workaround(void)
|
||||
for (i = 0; i < ARRAY_SIZE(wa_info); i++) {
|
||||
if (!memcmp(wa_info[i].oem_id, tbl->oem_id, ACPI_OEM_ID_SIZE) &&
|
||||
!memcmp(wa_info[i].oem_table_id, tbl->oem_table_id, ACPI_OEM_TABLE_ID_SIZE) &&
|
||||
wa_info[i].oem_revision == tbl->oem_revision)
|
||||
wa_info[i].oem_revision == tbl->oem_revision) {
|
||||
apply_hisi_workaround = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
acpi_put_table(tbl);
|
||||
}
|
||||
|
||||
/* Callback function used to retrieve the max frequency from DMI */
|
||||
|
||||
@@ -109,6 +109,7 @@ static const struct of_device_id blacklist[] __initconst = {
|
||||
{ .compatible = "fsl,imx8mq", },
|
||||
{ .compatible = "fsl,imx8mm", },
|
||||
{ .compatible = "fsl,imx8mn", },
|
||||
{ .compatible = "fsl,imx8mp", },
|
||||
|
||||
{ .compatible = "marvell,armadaxp", },
|
||||
|
||||
|
||||
@@ -35,7 +35,8 @@ static int imx_cpufreq_dt_probe(struct platform_device *pdev)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (of_machine_is_compatible("fsl,imx8mn"))
|
||||
if (of_machine_is_compatible("fsl,imx8mn") ||
|
||||
of_machine_is_compatible("fsl,imx8mp"))
|
||||
speed_grade = (cell_value & IMX8MN_OCOTP_CFG3_SPEED_GRADE_MASK)
|
||||
>> OCOTP_CFG3_SPEED_GRADE_SHIFT;
|
||||
else
|
||||
@@ -54,7 +55,8 @@ static int imx_cpufreq_dt_probe(struct platform_device *pdev)
|
||||
if (of_machine_is_compatible("fsl,imx8mm") ||
|
||||
of_machine_is_compatible("fsl,imx8mq"))
|
||||
speed_grade = 1;
|
||||
if (of_machine_is_compatible("fsl,imx8mn"))
|
||||
if (of_machine_is_compatible("fsl,imx8mn") ||
|
||||
of_machine_is_compatible("fsl,imx8mp"))
|
||||
speed_grade = 0xb;
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user