Merge d46ede3188 ("Merge tag 'pmdomain-v6.11' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/linux-pm") into android-mainline

Steps on the way to v6.11-rc1

Signed-off-by: Lee Jones <joneslee@google.com>
Change-Id: Ifa579b99625553a29d8143dc25b1f23b00a62edd
This commit is contained in:
Lee Jones
2024-08-06 09:02:50 +01:00
277 changed files with 10653 additions and 3654 deletions
@@ -694,3 +694,9 @@ Description:
(RO) indicates whether or not the kernel directly supports
modifying the crash elfcorehdr for CPU hot un/plug and/or
on/offline changes.
What: /sys/devices/system/cpu/enabled
Date: Nov 2022
Contact: Linux kernel mailing list <linux-kernel@vger.kernel.org>
Description:
(RO) the list of CPUs that can be brought online.
@@ -12,7 +12,7 @@
acpi= [HW,ACPI,X86,ARM64,RISCV64,EARLY]
Advanced Configuration and Power Interface
Format: { force | on | off | strict | noirq | rsdt |
copy_dsdt }
copy_dsdt | nospcr }
force -- enable ACPI if default was off
on -- enable ACPI but allow fallback to DT [arm64,riscv64]
off -- disable ACPI if default was on
@@ -21,8 +21,12 @@
strictly ACPI specification compliant.
rsdt -- prefer RSDT over (default) XSDT
copy_dsdt -- copy DSDT to memory
For ARM64 and RISCV64, ONLY "acpi=off", "acpi=on" or
"acpi=force" are available
nospcr -- disable console in ACPI SPCR table as
default _serial_ console on ARM64
For ARM64, ONLY "acpi=off", "acpi=on", "acpi=force" or
"acpi=nospcr" are available
For RISCV64, ONLY "acpi=off", "acpi=on" or "acpi=force"
are available
See also Documentation/power/runtime_pm.rst, pci=noacpi
+79
View File
@@ -0,0 +1,79 @@
.. SPDX-License-Identifier: GPL-2.0
.. _cpuhp_index:
====================
CPU Hotplug and ACPI
====================
CPU hotplug in the arm64 world is commonly used to describe the kernel taking
CPUs online/offline using PSCI. This document is about ACPI firmware allowing
CPUs that were not available during boot to be added to the system later.
``possible`` and ``present`` refer to the state of the CPU as seen by linux.
CPU Hotplug on physical systems - CPUs not present at boot
----------------------------------------------------------
Physical systems need to mark a CPU that is ``possible`` but not ``present`` as
being ``present``. An example would be a dual socket machine, where the package
in one of the sockets can be replaced while the system is running.
This is not supported.
In the arm64 world CPUs are not a single device but a slice of the system.
There are no systems that support the physical addition (or removal) of CPUs
while the system is running, and ACPI is not able to sufficiently describe
them.
e.g. New CPUs come with new caches, but the platform's cache toplogy is
described in a static table, the PPTT. How caches are shared between CPUs is
not discoverable, and must be described by firmware.
e.g. The GIC redistributor for each CPU must be accessed by the driver during
boot to discover the system wide supported features. ACPI's MADT GICC
structures can describe a redistributor associated with a disabled CPU, but
can't describe whether the redistributor is accessible, only that it is not
'always on'.
arm64's ACPI tables assume that everything described is ``present``.
CPU Hotplug on virtual systems - CPUs not enabled at boot
---------------------------------------------------------
Virtual systems have the advantage that all the properties the system will
ever have can be described at boot. There are no power-domain considerations
as such devices are emulated.
CPU Hotplug on virtual systems is supported. It is distinct from physical
CPU Hotplug as all resources are described as ``present``, but CPUs may be
marked as disabled by firmware. Only the CPU's online/offline behaviour is
influenced by firmware. An example is where a virtual machine boots with a
single CPU, and additional CPUs are added once a cloud orchestrator deploys
the workload.
For a virtual machine, the VMM (e.g. Qemu) plays the part of firmware.
Virtual hotplug is implemented as a firmware policy affecting which CPUs can be
brought online. Firmware can enforce its policy via PSCI's return codes. e.g.
``DENIED``.
The ACPI tables must describe all the resources of the virtual machine. CPUs
that firmware wishes to disable either from boot (or later) should not be
``enabled`` in the MADT GICC structures, but should have the ``online capable``
bit set, to indicate they can be enabled later. The boot CPU must be marked as
``enabled``. The 'always on' GICR structure must be used to describe the
redistributors.
CPUs described as ``online capable`` but not ``enabled`` can be set to enabled
by the DSDT's Processor object's _STA method. On virtual systems the _STA method
must always report the CPU as ``present``. Changes to the firmware policy can
be notified to the OS via device-check or eject-request.
CPUs described as ``enabled`` in the static table, should not have their _STA
modified dynamically by firmware. Soft-restart features such as kexec will
re-read the static properties of the system from these static tables, and
may malfunction if these no longer describe the running system. Linux will
re-discover the dynamic properties of the system from the _STA method later
during boot.
+1
View File
@@ -13,6 +13,7 @@ ARM64 Architecture
asymmetric-32bit
booting
cpu-feature-registers
cpu-hotplug
elf_hwcaps
hugetlbpage
kdump
+20 -22
View File
@@ -18,12 +18,10 @@ ARMv8.2 adds optional support for Large Virtual Address space. This is
only available when running with a 64KB page size and expands the
number of descriptors in the first level of translation.
User addresses have bits 63:48 set to 0 while the kernel addresses have
the same bits set to 1. TTBRx selection is given by bit 63 of the
virtual address. The swapper_pg_dir contains only kernel (global)
mappings while the user pgd contains only user (non-global) mappings.
The swapper_pg_dir address is written to TTBR1 and never written to
TTBR0.
TTBRx selection is given by bit 55 of the virtual address. The
swapper_pg_dir contains only kernel (global) mappings while the user pgd
contains only user (non-global) mappings. The swapper_pg_dir address is
written to TTBR1 and never written to TTBR0.
AArch64 Linux memory layout with 4KB pages + 4 levels (48-bit)::
@@ -65,14 +63,14 @@ Translation table lookup with 4KB pages::
+--------+--------+--------+--------+--------+--------+--------+--------+
|63 56|55 48|47 40|39 32|31 24|23 16|15 8|7 0|
+--------+--------+--------+--------+--------+--------+--------+--------+
| | | | | |
| | | | | v
| | | | | [11:0] in-page offset
| | | | +-> [20:12] L3 index
| | | +-----------> [29:21] L2 index
| | +---------------------> [38:30] L1 index
| +-------------------------------> [47:39] L0 index
+-------------------------------------------------> [63] TTBR0/1
| | | | | |
| | | | | v
| | | | | [11:0] in-page offset
| | | | +-> [20:12] L3 index
| | | +-----------> [29:21] L2 index
| | +---------------------> [38:30] L1 index
| +-------------------------------> [47:39] L0 index
+----------------------------------------> [55] TTBR0/1
Translation table lookup with 64KB pages::
@@ -80,14 +78,14 @@ Translation table lookup with 64KB pages::
+--------+--------+--------+--------+--------+--------+--------+--------+
|63 56|55 48|47 40|39 32|31 24|23 16|15 8|7 0|
+--------+--------+--------+--------+--------+--------+--------+--------+
| | | | |
| | | | v
| | | | [15:0] in-page offset
| | | +----------> [28:16] L3 index
| | +--------------------------> [41:29] L2 index
| +-------------------------------> [47:42] L1 index (48-bit)
| [51:42] L1 index (52-bit)
+-------------------------------------------------> [63] TTBR0/1
| | | | |
| | | | v
| | | | [15:0] in-page offset
| | | +----------> [28:16] L3 index
| | +--------------------------> [41:29] L2 index
| +-------------------------------> [47:42] L1 index (48-bit)
| [51:42] L1 index (52-bit)
+----------------------------------------> [55] TTBR0/1
When using KVM without the Virtualization Host Extensions, the
+15 -1
View File
@@ -132,16 +132,26 @@ stable kernels.
+----------------+-----------------+-----------------+-----------------------------+
| ARM | Cortex-A710 | #2224489 | ARM64_ERRATUM_2224489 |
+----------------+-----------------+-----------------+-----------------------------+
| ARM | Cortex-A710 | #3324338 | ARM64_ERRATUM_3194386 |
+----------------+-----------------+-----------------+-----------------------------+
| ARM | Cortex-A715 | #2645198 | ARM64_ERRATUM_2645198 |
+----------------+-----------------+-----------------+-----------------------------+
| ARM | Cortex-A720 | #3456091 | ARM64_ERRATUM_3194386 |
+----------------+-----------------+-----------------+-----------------------------+
| ARM | Cortex-X1 | #1502854 | N/A |
+----------------+-----------------+-----------------+-----------------------------+
| ARM | Cortex-X2 | #2119858 | ARM64_ERRATUM_2119858 |
+----------------+-----------------+-----------------+-----------------------------+
| ARM | Cortex-X2 | #2224489 | ARM64_ERRATUM_2224489 |
+----------------+-----------------+-----------------+-----------------------------+
| ARM | Cortex-X2 | #3324338 | ARM64_ERRATUM_3194386 |
+----------------+-----------------+-----------------+-----------------------------+
| ARM | Cortex-X3 | #3324335 | ARM64_ERRATUM_3194386 |
+----------------+-----------------+-----------------+-----------------------------+
| ARM | Cortex-X4 | #3194386 | ARM64_ERRATUM_3194386 |
+----------------+-----------------+-----------------+-----------------------------+
| ARM | Cortex-X925 | #3324334 | ARM64_ERRATUM_3194386 |
+----------------+-----------------+-----------------+-----------------------------+
| ARM | Neoverse-N1 | #1188873,1418040| ARM64_ERRATUM_1418040 |
+----------------+-----------------+-----------------+-----------------------------+
| ARM | Neoverse-N1 | #1349291 | N/A |
@@ -156,9 +166,13 @@ stable kernels.
+----------------+-----------------+-----------------+-----------------------------+
| ARM | Neoverse-N2 | #2253138 | ARM64_ERRATUM_2253138 |
+----------------+-----------------+-----------------+-----------------------------+
| ARM | Neoverse-N2 | #3324339 | ARM64_ERRATUM_3194386 |
+----------------+-----------------+-----------------+-----------------------------+
| ARM | Neoverse-V1 | #1619801 | N/A |
+----------------+-----------------+-----------------+-----------------------------+
| ARM | Neoverse-V3 | #3312417 | ARM64_ERRATUM_3312417 |
| ARM | Neoverse-V2 | #3324336 | ARM64_ERRATUM_3194386 |
+----------------+-----------------+-----------------+-----------------------------+
| ARM | Neoverse-V3 | #3312417 | ARM64_ERRATUM_3194386 |
+----------------+-----------------+-----------------+-----------------------------+
| ARM | MMU-500 | #841119,826419 | N/A |
+----------------+-----------------+-----------------+-----------------------------+
@@ -53,14 +53,20 @@ properties:
- arm,cortex-a710-pmu
- arm,cortex-a715-pmu
- arm,cortex-a720-pmu
- arm,cortex-a725-pmu
- arm,cortex-x1-pmu
- arm,cortex-x2-pmu
- arm,cortex-x3-pmu
- arm,cortex-x4-pmu
- arm,cortex-x925-pmu
- arm,neoverse-e1-pmu
- arm,neoverse-n1-pmu
- arm,neoverse-n2-pmu
- arm,neoverse-n3-pmu
- arm,neoverse-v1-pmu
- arm,neoverse-v2-pmu
- arm,neoverse-v3-pmu
- arm,neoverse-v3ae-pmu
- brcm,vulcan-pmu
- cavium,thunder-pmu
- nvidia,denver-pmu
@@ -1,47 +0,0 @@
GMT G762/G763 PWM Fan controller
Required node properties:
- "compatible": must be either "gmt,g762" or "gmt,g763"
- "reg": I2C bus address of the device
- "clocks": a fixed clock providing input clock frequency
on CLK pin of the chip.
Optional properties:
- "fan_startv": fan startup voltage. Accepted values are 0, 1, 2 and 3.
The higher the more.
- "pwm_polarity": pwm polarity. Accepted values are 0 (positive duty)
and 1 (negative duty).
- "fan_gear_mode": fan gear mode. Supported values are 0, 1 and 2.
If an optional property is not set in .dts file, then current value is kept
unmodified (e.g. u-boot installed value).
Additional information on operational parameters for the device is available
in Documentation/hwmon/g762.rst. A detailed datasheet for the device is available
at http://natisbad.org/NAS/refs/GMT_EDS-762_763-080710-0.2.pdf.
Example g762 node:
clocks {
#address-cells = <1>;
#size-cells = <0>;
g762_clk: fixedclk {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <8192>;
}
}
g762: g762@3e {
compatible = "gmt,g762";
reg = <0x3e>;
clocks = <&g762_clk>
fan_gear_mode = <0>; /* chip default */
fan_startv = <1>; /* chip default */
pwm_polarity = <0>; /* chip default */
};
@@ -0,0 +1,95 @@
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/hwmon/gmt,g762.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: GMT G761/G762/G763 PWM Fan controller
maintainers:
- Christian Marangi <ansuelsmth@gmail.com>
description: |
GMT G761/G762/G763 PWM Fan controller.
G761 supports an internal-clock hence the clocks property is optional.
If not defined, internal-clock will be used. (31KHz is the clock of
the internal crystal oscillator)
If an optional property is not set in DT, then current value is kept
unmodified (e.g. bootloader installed value).
Additional information on operational parameters for the device is available
in Documentation/hwmon/g762.rst. A detailed datasheet for the device is available
at http://natisbad.org/NAS/refs/GMT_EDS-762_763-080710-0.2.pdf.
properties:
compatible:
enum:
- gmt,g761
- gmt,g762
- gmt,g763
reg:
maxItems: 1
clocks:
description: a fixed clock providing input clock frequency on CLK
pin of the chip.
maxItems: 1
fan_startv:
description: Fan startup voltage step
$ref: /schemas/types.yaml#/definitions/uint32
enum: [0, 1, 2, 3]
pwm_polarity:
description: PWM polarity (positive or negative duty)
$ref: /schemas/types.yaml#/definitions/uint32
enum: [0, 1]
fan_gear_mode:
description: FAN gear mode. Configure High speed fan setting factor
$ref: /schemas/types.yaml#/definitions/uint32
enum: [0, 1, 2]
required:
- compatible
- reg
if:
properties:
compatible:
contains:
enum:
- gmt,g762
- gmt,g763
then:
required:
- clocks
additionalProperties: false
examples:
- |
i2c {
#address-cells = <1>;
#size-cells = <0>;
g762@3e {
compatible = "gmt,g762";
reg = <0x3e>;
clocks = <&g762_clk>;
fan_gear_mode = <0>;
fan_startv = <1>;
pwm_polarity = <0>;
};
g761@1e {
compatible = "gmt,g761";
reg = <0x1e>;
fan_gear_mode = <0>;
fan_startv = <1>;
pwm_polarity = <0>;
};
};
@@ -0,0 +1,92 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/hwmon/maxim,max6639.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Maxim max6639
maintainers:
- Naresh Solanki <naresh.solanki@9elements.com>
description: |
The MAX6639 is a 2-channel temperature monitor with dual, automatic, PWM
fan-speed controller. It monitors its own temperature and one external
diode-connected transistor or the temperatures of two external diode-connected
transistors, typically available in CPUs, FPGAs, or GPUs.
Datasheets:
https://datasheets.maximintegrated.com/en/ds/MAX6639-MAX6639F.pdf
properties:
compatible:
enum:
- maxim,max6639
reg:
maxItems: 1
'#address-cells':
const: 1
'#size-cells':
const: 0
'#pwm-cells':
const: 3
required:
- compatible
- reg
patternProperties:
"^fan@[0-1]$":
type: object
description:
Represents the two fans and their specific configuration.
$ref: fan-common.yaml#
unevaluatedProperties: false
properties:
reg:
description:
The fan number.
required:
- reg
additionalProperties: false
examples:
- |
i2c {
#address-cells = <1>;
#size-cells = <0>;
fan1: fan-controller@10 {
compatible = "maxim,max6639";
reg = <0x10>;
#address-cells = <1>;
#size-cells = <0>;
#pwm-cells = <3>;
fan@0 {
reg = <0x0>;
pulses-per-revolution = <2>;
max-rpm = <4000>;
target-rpm = <1000>;
pwms = <&fan1 0 25000 0>;
};
fan@1 {
reg = <0x1>;
pulses-per-revolution = <2>;
max-rpm = <8000>;
pwms = <&fan1 1 25000 0>;
};
};
};
...
@@ -66,6 +66,14 @@ properties:
description: phandle to the regulator that provides the VS supply typically
in range from 2.7 V to 5.5 V.
ti,alert-polarity-active-high:
description: Alert pin is asserted based on the value of Alert polarity Bit
of Mask/Enable register. Default value is Normal (0 which maps to
active-low open collector). The other value is Inverted
(1 which maps to active-high open collector). Specify this property to set
the alert polarity to active-high.
$ref: /schemas/types.yaml#/definitions/flag
required:
- compatible
- reg
@@ -88,5 +96,6 @@ examples:
label = "vdd_3v0";
shunt-resistor = <1000>;
vs-supply = <&vdd_3v0>;
ti,alert-polarity-active-high;
};
};
@@ -9,6 +9,14 @@ title: TMP108 temperature sensor
maintainers:
- Krzysztof Kozlowski <krzk@kernel.org>
description: |
The TMP108 is a digital-output temperature sensor with a
dynamically-programmable limit window, and under- and overtemperature
alert functions.
Datasheets:
https://www.ti.com/product/TMP108
properties:
compatible:
enum:
@@ -24,6 +32,9 @@ properties:
"#thermal-sensor-cells":
const: 0
vcc-supply:
description: phandle to the regulator that provides the V+ supply
required:
- compatible
- reg
@@ -45,6 +56,7 @@ examples:
interrupts = <7 IRQ_TYPE_LEVEL_LOW>;
pinctrl-names = "default";
pinctrl-0 = <&tmp_alrt>;
vcc-supply = <&supply>;
#thermal-sensor-cells = <0>;
};
};
@@ -30,6 +30,9 @@ properties:
- items:
- const: fsl,imx8dxl-ddr-pmu
- const: fsl,imx8-ddr-pmu
- items:
- const: fsl,imx95-ddr-pmu
- const: fsl,imx93-ddr-pmu
reg:
maxItems: 1
@@ -20,6 +20,8 @@ properties:
enum:
- amlogic,meson-a1-pwrc
- amlogic,meson-s4-pwrc
- amlogic,a4-pwrc
- amlogic,a5-pwrc
- amlogic,c3-pwrc
- amlogic,t7-pwrc
@@ -0,0 +1,48 @@
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/pwm/adi,axi-pwmgen.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Analog Devices AXI PWM generator
maintainers:
- Michael Hennerich <Michael.Hennerich@analog.com>
- Nuno Sá <nuno.sa@analog.com>
description:
The Analog Devices AXI PWM generator can generate PWM signals
with variable pulse width and period.
https://wiki.analog.com/resources/fpga/docs/axi_pwm_gen
allOf:
- $ref: pwm.yaml#
properties:
compatible:
const: adi,axi-pwmgen-2.00.a
reg:
maxItems: 1
"#pwm-cells":
const: 2
clocks:
maxItems: 1
required:
- reg
- clocks
unevaluatedProperties: false
examples:
- |
pwm@44b00000 {
compatible = "adi,axi-pwmgen-2.00.a";
reg = <0x44b00000 0x1000>;
clocks = <&spi_clk>;
#pwm-cells = <2>;
};
@@ -23,7 +23,9 @@ properties:
- atmel,sama5d2-pwm
- microchip,sam9x60-pwm
- items:
- const: microchip,sama7g5-pwm
- enum:
- microchip,sama7d65-pwm
- microchip,sama7g5-pwm
- const: atmel,sama5d2-pwm
- items:
- const: microchip,sam9x7-pwm
@@ -0,0 +1,92 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/pwm/fsl,vf610-ftm-pwm.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Freescale FlexTimer Module (FTM) PWM controller
description: |
The same FTM PWM device can have a different endianness on different SoCs. The
device tree provides a property to describing this so that an operating system
device driver can handle all variants of the device. Refer to the table below
for the endianness of the FTM PWM block as integrated into the existing SoCs:
SoC | FTM-PWM endianness
--------+-------------------
Vybrid | LE
LS1 | BE
LS2 | LE
Please see ../regmap/regmap.txt for more detail about how to specify endian
modes in device tree.
maintainers:
- Frank Li <Frank.Li@nxp.com>
properties:
compatible:
enum:
- fsl,vf610-ftm-pwm
- fsl,imx8qm-ftm-pwm
reg:
maxItems: 1
"#pwm-cells":
const: 3
clocks:
minItems: 4
maxItems: 4
clock-names:
items:
- const: ftm_sys
- const: ftm_ext
- const: ftm_fix
- const: ftm_cnt_clk_en
pinctrl-0: true
pinctrl-1: true
pinctrl-names:
minItems: 1
items:
- const: default
- const: sleep
big-endian:
$ref: /schemas/types.yaml#/definitions/flag
description:
Boolean property, required if the FTM PWM registers use a big-
endian rather than little-endian layout.
required:
- compatible
- reg
- clocks
- clock-names
allOf:
- $ref: pwm.yaml#
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/clock/vf610-clock.h>
pwm@40038000 {
compatible = "fsl,vf610-ftm-pwm";
reg = <0x40038000 0x1000>;
#pwm-cells = <3>;
clocks = <&clks VF610_CLK_FTM0>,
<&clks VF610_CLK_FTM0_EXT_SEL>,
<&clks VF610_CLK_FTM0_FIX_SEL>,
<&clks VF610_CLK_FTM0_EXT_FIX_EN>;
clock-names = "ftm_sys", "ftm_ext", "ftm_fix", "ftm_cnt_clk_en";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_pwm0_1>;
big-endian;
};
@@ -68,7 +68,6 @@ required:
- reg
- clocks
- clock-names
- interrupts
additionalProperties: false
@@ -1,55 +0,0 @@
Freescale FlexTimer Module (FTM) PWM controller
The same FTM PWM device can have a different endianness on different SoCs. The
device tree provides a property to describing this so that an operating system
device driver can handle all variants of the device. Refer to the table below
for the endianness of the FTM PWM block as integrated into the existing SoCs:
SoC | FTM-PWM endianness
--------+-------------------
Vybrid | LE
LS1 | BE
LS2 | LE
Please see ../regmap/regmap.txt for more detail about how to specify endian
modes in device tree.
Required properties:
- compatible : should be "fsl,<soc>-ftm-pwm" and one of the following
compatible strings:
- "fsl,vf610-ftm-pwm" for PWM compatible with the one integrated on VF610
- "fsl,imx8qm-ftm-pwm" for PWM compatible with the one integrated on i.MX8QM
- reg: Physical base address and length of the controller's registers
- #pwm-cells: Should be 3. See pwm.yaml in this directory for a description of
the cells format.
- clock-names: Should include the following module clock source entries:
"ftm_sys" (module clock, also can be used as counter clock),
"ftm_ext" (external counter clock),
"ftm_fix" (fixed counter clock),
"ftm_cnt_clk_en" (external and fixed counter clock enable/disable).
- clocks: Must contain a phandle and clock specifier for each entry in
clock-names, please see clock/clock-bindings.txt for details of the property
values.
- pinctrl-names: Must contain a "default" entry.
- pinctrl-NNN: One property must exist for each entry in pinctrl-names.
See pinctrl/pinctrl-bindings.txt for details of the property values.
- big-endian: Boolean property, required if the FTM PWM registers use a big-
endian rather than little-endian layout.
Example:
pwm0: pwm@40038000 {
compatible = "fsl,vf610-ftm-pwm";
reg = <0x40038000 0x1000>;
#pwm-cells = <3>;
clock-names = "ftm_sys", "ftm_ext",
"ftm_fix", "ftm_cnt_clk_en";
clocks = <&clks VF610_CLK_FTM0>,
<&clks VF610_CLK_FTM0_EXT_SEL>,
<&clks VF610_CLK_FTM0_FIX_SEL>,
<&clks VF610_CLK_FTM0_EXT_FIX_EN>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_pwm0_1>;
big-endian;
};
@@ -0,0 +1,46 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/pwm/pwm-gpio.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Generic software PWM for modulating GPIOs
maintainers:
- Stefan Wahren <wahrenst@gmx.net>
allOf:
- $ref: pwm.yaml#
properties:
compatible:
const: pwm-gpio
"#pwm-cells":
const: 3
description:
See pwm.yaml in this directory for a description of the cells format.
The first cell which represents the PWM instance number must always
be zero.
gpios:
description:
GPIO to be modulated
maxItems: 1
required:
- compatible
- "#pwm-cells"
- gpios
additionalProperties: false
examples:
- |
#include <dt-bindings/gpio/gpio.h>
pwm {
#pwm-cells = <3>;
compatible = "pwm-gpio";
gpios = <&gpio 1 GPIO_ACTIVE_HIGH>;
};
@@ -16,8 +16,10 @@ properties:
pattern: "^pwm(@.*|-([0-9]|[1-9][0-9]+))?$"
"#pwm-cells":
description:
Number of cells in a PWM specifier.
description: |
Number of cells in a PWM specifier. Typically the cells represent, in
order: the chip-relative PWM number, the PWM period in nanoseconds and
optionally a number of flags (defined in <dt-bindings/pwm/pwm.h>).
required:
- "#pwm-cells"
@@ -168,6 +168,8 @@ properties:
- isil,isl69269
# Intersil ISL76682 Ambient Light Sensor
- isil,isl76682
# JEDEC JESD300 (SPD5118) Hub and Serial Presence Detect
- jedec,spd5118
# Linear Technology LTC2488
- lineartechnology,ltc2488
# 5 Bit Programmable, Pulse-Width Modulator
@@ -286,14 +288,22 @@ properties:
- mps,mp2857
# Monolithic Power Systems Inc. multi-phase controller mp2888
- mps,mp2888
# Monolithic Power Systems Inc. multi-phase controller mp2891
- mps,mp2891
# Monolithic Power Systems Inc. multi-phase controller mp2971
- mps,mp2971
# Monolithic Power Systems Inc. multi-phase controller mp2973
- mps,mp2973
# Monolithic Power Systems Inc. multi-phase controller mp2975
- mps,mp2975
# Monolithic Power Systems Inc. multi-phase controller mp2993
- mps,mp2993
# Monolithic Power Systems Inc. multi-phase hot-swap controller mp5920
- mps,mp5920
# Monolithic Power Systems Inc. multi-phase hot-swap controller mp5990
- mps,mp5990
# Monolithic Power Systems Inc. digital step-down converter mp9941
- mps,mp9941
# Monolithic Power Systems Inc. synchronous step-down converter mpq8785
- mps,mpq8785
# Temperature sensor with integrated fan control
@@ -27,7 +27,12 @@ hardware descriptions such as device tree or ACPI:
to the lines for a more permanent solution of this type.
- gpio-beeper: drivers/input/misc/gpio-beeper.c is used to provide a beep from
an external speaker connected to a GPIO line.
an external speaker connected to a GPIO line. (If the beep is controlled by
off/on, for an actual PWM waveform, see pwm-gpio below.)
- pwm-gpio: drivers/pwm/pwm-gpio.c is used to toggle a GPIO with a high
resolution timer producing a PWM waveform on the GPIO line, as well as
Linux high resolution timers can do.
- extcon-gpio: drivers/extcon/extcon-gpio.c is used when you need to read an
external connector status, such as a headset line for an audio driver or an
-153
View File
@@ -1,153 +0,0 @@
Kernel driver adm1021
=====================
Supported chips:
* Analog Devices ADM1021
Prefix: 'adm1021'
Addresses scanned: I2C 0x18 - 0x1a, 0x29 - 0x2b, 0x4c - 0x4e
Datasheet: Publicly available at the Analog Devices website
* Analog Devices ADM1021A/ADM1023
Prefix: 'adm1023'
Addresses scanned: I2C 0x18 - 0x1a, 0x29 - 0x2b, 0x4c - 0x4e
Datasheet: Publicly available at the Analog Devices website
* Genesys Logic GL523SM
Prefix: 'gl523sm'
Addresses scanned: I2C 0x18 - 0x1a, 0x29 - 0x2b, 0x4c - 0x4e
Datasheet:
* Maxim MAX1617
Prefix: 'max1617'
Addresses scanned: I2C 0x18 - 0x1a, 0x29 - 0x2b, 0x4c - 0x4e
Datasheet: Publicly available at the Maxim website
* Maxim MAX1617A
Prefix: 'max1617a'
Addresses scanned: I2C 0x18 - 0x1a, 0x29 - 0x2b, 0x4c - 0x4e
Datasheet: Publicly available at the Maxim website
* National Semiconductor LM84
Prefix: 'lm84'
Addresses scanned: I2C 0x18 - 0x1a, 0x29 - 0x2b, 0x4c - 0x4e
Datasheet: Publicly available at the National Semiconductor website
* Philips NE1617
Prefix: 'max1617' (probably detected as a max1617)
Addresses scanned: I2C 0x18 - 0x1a, 0x29 - 0x2b, 0x4c - 0x4e
Datasheet: Publicly available at the Philips website
* Philips NE1617A
Prefix: 'max1617' (probably detected as a max1617)
Addresses scanned: I2C 0x18 - 0x1a, 0x29 - 0x2b, 0x4c - 0x4e
Datasheet: Publicly available at the Philips website
* TI THMC10
Prefix: 'thmc10'
Addresses scanned: I2C 0x18 - 0x1a, 0x29 - 0x2b, 0x4c - 0x4e
Datasheet: Publicly available at the TI website
* Onsemi MC1066
Prefix: 'mc1066'
Addresses scanned: I2C 0x18 - 0x1a, 0x29 - 0x2b, 0x4c - 0x4e
Datasheet: Publicly available at the Onsemi website
Authors:
- Frodo Looijaard <frodol@dds.nl>,
- Philip Edelbrock <phil@netroedge.com>
Module Parameters
-----------------
* read_only: int
Don't set any values, read only mode
Description
-----------
The chips supported by this driver are very similar. The Maxim MAX1617 is
the oldest; it has the problem that it is not very well detectable. The
MAX1617A solves that. The ADM1021 is a straight clone of the MAX1617A.
Ditto for the THMC10. From here on, we will refer to all these chips as
ADM1021-clones.
The ADM1021 and MAX1617A reports a die code, which is a sort of revision
code. This can help us pinpoint problems; it is not very useful
otherwise.
ADM1021-clones implement two temperature sensors. One of them is internal,
and measures the temperature of the chip itself; the other is external and
is realised in the form of a transistor-like device. A special alarm
indicates whether the remote sensor is connected.
Each sensor has its own low and high limits. When they are crossed, the
corresponding alarm is set and remains on as long as the temperature stays
out of range. Temperatures are measured in degrees Celsius. Measurements
are possible between -65 and +127 degrees, with a resolution of one degree.
If an alarm triggers, it will remain triggered until the hardware register
is read at least once. This means that the cause for the alarm may already
have disappeared!
This driver only updates its values each 1.5 seconds; reading it more often
will do no harm, but will return 'old' values. It is possible to make
ADM1021-clones do faster measurements, but there is really no good reason
for that.
Netburst-based Xeon support
---------------------------
Some Xeon processors based on the Netburst (early Pentium 4, from 2001 to
2003) microarchitecture had real MAX1617, ADM1021, or compatible chips
within them, with two temperature sensors. Other Xeon processors of this
era (with 400 MHz FSB) had chips with only one temperature sensor.
If you have such an old Xeon, and you get two valid temperatures when
loading the adm1021 module, then things are good.
If nothing happens when loading the adm1021 module, and you are certain
that your specific Xeon processor model includes compatible sensors, you
will have to explicitly instantiate the sensor chips from user-space. See
method 4 in Documentation/i2c/instantiating-devices.rst. Possible slave
addresses are 0x18, 0x1a, 0x29, 0x2b, 0x4c, or 0x4e. It is likely that
only temp2 will be correct and temp1 will have to be ignored.
Previous generations of the Xeon processor (based on Pentium II/III)
didn't have these sensors. Next generations of Xeon processors (533 MHz
FSB and faster) lost them, until the Core-based generation which
introduced integrated digital thermal sensors. These are supported by
the coretemp driver.
+6 -1
View File
@@ -47,13 +47,18 @@ fan1_input ro tachometer speed
fan1_min rw "
fan1_max rw "
fan1_fault ro "
fan1_div rw Fan divisor can be either 2 or 4.
fan1_pulses rw Pulses per revolution can be either 2 or 4.
fan1_target rw Target fan speed, to be used with pwm1_enable
mode 4.
pwm1 rw pwm1
pwm1_enable rw regulator mode, 1=open loop, 2=fan controlled
by remote temperature, 3=fan controlled by
combination of the on-chip temperature and
remote-sensor temperature,
4=fan controlled by target rpm set with
fan1_target attribute.
pwm1_mode rw Fan duty control mode (0=DC, 1=PWM)
pwm1_auto_channels_temp ro 1 if pwm_enable==2, 3 if pwm_enable==3
pwm1_auto_point1_pwm ro Hardwired to 0, shared for both
temperature channels.
+1
View File
@@ -8,6 +8,7 @@ Supported boards:
* PRIME X570-PRO
* Pro WS X570-ACE
* ProArt X570-CREATOR WIFI
* ProArt X670E-CREATOR WIFI
* ProArt B550-CREATOR
* ROG CROSSHAIR VIII DARK HERO
* ROG CROSSHAIR VIII HERO (WI-FI)
+8
View File
@@ -39,3 +39,11 @@ fan[1-6]_target Sets fan speed target rpm.
pwm[1-6] Sets the fan speed. Values from 0-255. Can only be read if pwm
was set directly.
======================= =====================================================================
Debugfs entries
---------------
======================= ===================
firmware_version Firmware version
bootloader_version Bootloader version
======================= ===================
+3 -3
View File
@@ -15,11 +15,11 @@ Supported devices:
Corsair HX850i
Corsair HX1000i (Series 2022 and 2023)
Corsair HX1000i (Legacy and Series 2023)
Corsair HX1200i
Corsair HX1200i (Legacy and Series 2023)
Corsair HX1500i (Series 2022 and 2023)
Corsair HX1500i (Legacy and Series 2023)
Corsair RM550i
+26
View File
@@ -0,0 +1,26 @@
.. SPDX-License-Identifier: GPL-2.0-or-later
Kernel driver cros_ec_hwmon
===========================
Supported chips:
* ChromeOS embedded controllers.
Prefix: 'cros_ec'
Addresses scanned: -
Author:
- Thomas Weißschuh <linux@weissschuh.net>
Description
-----------
This driver implements support for hardware monitoring commands exposed by the
ChromeOS embedded controller used in Chromebooks and other devices.
The channel labels exposed via hwmon are retrieved from the EC itself.
Fan and temperature readings are supported.
+2
View File
@@ -360,6 +360,8 @@ Firmware Bug Affected Machines
======================================================= =================
Reading of fan states return spurious errors. Precision 490
OptiPlex 7060
Reading of fan types causes erratic fan behaviour. Studio XPS 8000
Studio XPS 8100
+6 -2
View File
@@ -25,7 +25,6 @@ Hardware Monitoring Kernel Drivers
acpi_power_meter
ad7314
adc128d818
adm1021
adm1025
adm1026
adm1031
@@ -58,6 +57,7 @@ Hardware Monitoring Kernel Drivers
coretemp
corsair-cpro
corsair-psu
cros_ec_hwmon
da9052
da9055
dell-smm-hwmon
@@ -154,7 +154,6 @@ Hardware Monitoring Kernel Drivers
max34440
max6620
max6639
max6642
max6650
max6697
max8688
@@ -165,9 +164,13 @@ Hardware Monitoring Kernel Drivers
mlxreg-fan
mp2856
mp2888
mp2891
mp2975
mp2993
mp5023
mp5920
mp5990
mp9941
mpq8785
nct6683
nct6775
@@ -215,6 +218,7 @@ Hardware Monitoring Kernel Drivers
smsc47m192
smsc47m1
sparx5-temp
spd5118
stpddc60
surface_fan
sy7636a-hwmon
+10 -3
View File
@@ -131,7 +131,14 @@ The Fault Queue bits select how many consecutive temperature faults must occur
before overtemperature or undertemperature faults are indicated in the
corresponding status bits.
Notes
-----
PEC Support
-----------
PEC is not implemented.
When reading a register value, the PEC byte is computed and sent by the chip.
PEC on word data transaction respresents a signifcant increase in bandwitdh
usage (+33% for both write and reads) in normal conditions.
Since this operation implies there will be an extra delay to each
transaction, PEC can be disabled or enabled through sysfs.
Just write 1 to the "pec" file for enabling PEC and 0 for disabling it.
-27
View File
@@ -1,27 +0,0 @@
Kernel driver max6642
=====================
Supported chips:
* Maxim MAX6642
Prefix: 'max6642'
Addresses scanned: I2C 0x48-0x4f
Datasheet: Publicly available at the Maxim website
http://datasheets.maxim-ic.com/en/ds/MAX6642.pdf
Authors:
Per Dalen <per.dalen@appeartv.com>
Description
-----------
The MAX6642 is a digital temperature sensor. It senses its own temperature as
well as the temperature on one external diode.
All temperature values are given in degrees Celsius. Resolution
is 0.25 degree for the local temperature and for the remote temperature.
+179
View File
@@ -0,0 +1,179 @@
.. SPDX-License-Identifier: GPL-2.0
Kernel driver mp2891
====================
Supported chips:
* MPS mp2891
Prefix: 'mp2891'
* Datasheet
Publicly available at the MPS website : https://www.monolithicpower.com/en/mp2891.html
Author:
Noah Wang <noahwang.wang@outlook.com>
Description
-----------
This driver implements support for Monolithic Power Systems, Inc. (MPS)
MP2891 Multi-phase Digital VR Controller.
Device compliant with:
- PMBus rev 1.3 interface.
Device supports direct and linear format for reading input voltage,
output voltage, input current, output current, input power, output
power, and temperature.
The driver exports the following attributes via the 'sysfs' files
for input voltage:
**in1_input**
**in1_label**
**in1_crit**
**in1_crit_alarm**
**in1_lcrit**
**in1_lcrit_alarm**
**in1_min**
**in1_min_alarm**
The driver provides the following attributes for output voltage:
**in2_input**
**in2_label**
**in2_crit**
**in2_crit_alarm**
**in2_lcrit**
**in2_lcrit_alarm**
**in2_min**
**in2_min_alarm**
**in3_input**
**in3_label**
**in3_crit**
**in3_crit_alarm**
**in3_lcrit**
**in3_lcrit_alarm**
**in3_min**
**in3_min_alarm**
The driver provides the following attributes for input current:
**curr1_input**
**curr1_label**
**curr1_max**
**curr1_max_alarm**
**curr2_input**
**curr2_label**
**curr2_max**
**curr2_max_alarm**
The driver provides the following attributes for output current:
**curr3_input**
**curr3_label**
**curr3_crit**
**curr3_crit_alarm**
**curr3_max**
**curr3_max_alarm**
**curr4_input**
**curr4_label**
**curr4_crit**
**curr4_crit_alarm**
**curr4_max**
**curr4_max_alarm**
The driver provides the following attributes for input power:
**power1_input**
**power1_label**
**power1_max**
**power1_alarm**
**power2_input**
**power2_label**
**power2_max**
**power2_alarm**
The driver provides the following attributes for output power:
**power3_input**
**power3_label**
**power4_input**
**power4_label**
The driver provides the following attributes for temperature:
**temp1_input**
**temp1_crit**
**temp1_crit_alarm**
**temp1_max**
**temp1_max_alarm**
**temp2_input**
**temp2_crit**
**temp2_crit_alarm**
**temp2_max**
**temp2_max_alarm**
+150
View File
@@ -0,0 +1,150 @@
.. SPDX-License-Identifier: GPL-2.0
Kernel driver mp2993
====================
Supported chips:
* MPS mp2993
Prefix: 'mp2993'
* Datasheet
https://scnbwymvp-my.sharepoint.com/:f:/g/personal/admin_scnbwy_com/Eth4kX1_J1hMsaASHiOYL4QBHU5a75r-tRfLKbHnJFdKLQ?e=vxj3DF
Author:
Noah Wang <noahwang.wang@outlook.com>
Description
-----------
This driver implements support for Monolithic Power Systems, Inc. (MPS)
MP2993 Dual Loop Digital Multi-phase Controller.
Device compliant with:
- PMBus rev 1.3 interface.
The driver exports the following attributes via the 'sysfs' files
for input voltage:
**in1_input**
**in1_label**
**in1_crit**
**in1_crit_alarm**
**in1_lcrit**
**in1_lcrit_alarm**
**in1_max**
**in1_max_alarm**
**in1_min**
**in1_min_alarm**
The driver provides the following attributes for output voltage:
**in2_input**
**in2_label**
**in2_crit**
**in2_crit_alarm**
**in2_lcrit**
**in2_lcrit_alarm**
**in3_input**
**in3_label**
**in3_crit**
**in3_crit_alarm**
**in3_lcrit**
**in3_lcrit_alarm**
The driver provides the following attributes for input current:
**curr1_input**
**curr1_label**
**curr1_max**
**curr1_max_alarm**
The driver provides the following attributes for output current:
**curr2_input**
**curr2_label**
**curr2_crit**
**curr2_crit_alarm**
**curr2_max**
**curr2_max_alarm**
**curr3_input**
**curr3_label**
**curr3_crit**
**curr3_crit_alarm**
**curr3_max**
**curr3_max_alarm**
The driver provides the following attributes for input power:
**power1_input**
**power1_label**
The driver provides the following attributes for output power:
**power2_input**
**power2_label**
**power3_input**
**power3_label**
The driver provides the following attributes for temperature:
**temp1_input**
**temp1_crit**
**temp1_crit_alarm**
**temp1_max**
**temp1_max_alarm**
**temp2_input**
**temp2_crit**
**temp2_crit_alarm**
**temp2_max**
**temp2_max_alarm**
+91
View File
@@ -0,0 +1,91 @@
.. SPDX-License-Identifier: GPL-2.0
Kernel driver mp5920
====================
Supported chips:
* MPS MP5920
Prefix: 'mp5920'
* Datasheet
Publicly available at the MPS website : https://www.monolithicpower.com/en/mp5920.html
Authors:
Tony Ao <tony_ao@wiwynn.com>
Alex Vdovydchenko <xzeol@yahoo.com>
Description
-----------
This driver implements support for Monolithic Power Systems, Inc. (MPS)
MP5920 Hot-Swap Controller.
Device compliant with:
- PMBus rev 1.3 interface.
Device supports direct and linear format for reading input voltage,
output voltage, output current, input power and temperature.
The driver exports the following attributes via the 'sysfs' files
for input voltage:
**in1_input**
**in1_label**
**in1_rated_max**
**in1_rated_min**
**in1_crit**
**in1_alarm**
The driver provides the following attributes for output voltage:
**in2_input**
**in2_label**
**in2_rated_max**
**in2_rated_min**
**in2_alarm**
The driver provides the following attributes for output current:
**curr1_input**
**curr1_label**
**curr1_crit**
**curr1_alarm**
**curr1_rated_max**
The driver provides the following attributes for input power:
**power1_input**
**power1_label**
**power1_max**
**power1_rated_max**
The driver provides the following attributes for temperature:
**temp1_input**
**temp1_max**
**temp1_crit**
**temp1_alarm**
+92
View File
@@ -0,0 +1,92 @@
.. SPDX-License-Identifier: GPL-2.0
Kernel driver mp9941
====================
Supported chips:
* MPS mp9941
Prefix: 'mp9941'
* Datasheet
https://scnbwymvp-my.sharepoint.com/:f:/g/personal/admin_scnbwy_com/Eth4kX1_J1hMsaASHiOYL4QBHU5a75r-tRfLKbHnJFdKLQ?e=vxj3DF
Author:
Noah Wang <noahwang.wang@outlook.com>
Description
-----------
This driver implements support for Monolithic Power Systems, Inc. (MPS)
MP9941 digital step-down converter.
Device compliant with:
- PMBus rev 1.3 interface.
The driver exports the following attributes via the 'sysfs' files
for input voltage:
**in1_input**
**in1_label**
**in1_crit**
**in1_crit_alarm**
The driver provides the following attributes for output voltage:
**in2_input**
**in2_label**
**in2_lcrit**
**in2_lcrit_alarm**
**in2_rated_max**
**in2_rated_min**
The driver provides the following attributes for input current:
**curr1_input**
**curr1_label**
**curr1_max**
**curr1_max_alarm**
The driver provides the following attributes for output current:
**curr2_input**
**curr2_label**
The driver provides the following attributes for input power:
**power1_input**
**power1_label**
The driver provides the following attributes for output power:
**power2_input**
**power2_label**
The driver provides the following attributes for temperature:
**temp1_input**
**temp1_crit**
**temp1_crit_alarm**
**temp1_max**
**temp1_max_alarm**
+63
View File
@@ -0,0 +1,63 @@
.. SPDX-License-Identifier: GPL-2.0-or-later
Kernel driver spd5118
=====================
Supported chips:
* SPD5118 (JEDEC JESD300) compliant temperature sensor chips
JEDEC standard download:
https://www.jedec.org/standards-documents/docs/jesd300-5b01
(account required)
Prefix: 'spd5118'
Addresses scanned: I2C 0x50 - 0x57
Author:
Guenter Roeck <linux@roeck-us.net>
Description
-----------
This driver implements support for SPD5118 (JEDEC JESD300) compliant temperature
sensors, which are used on many DDR5 memory modules. Some systems use the sensor
to prevent memory overheating by automatically throttling the memory controller.
The driver auto-detects SPD5118 compliant chips, but can also be instantiated
using devicetree/firmware nodes.
A SPD5118 compliant chip supports a single temperature sensor. Critical minimum,
minimum, maximum, and critical temperature can be configured. There are alarms
for low critical, low, high, and critical thresholds.
Hardware monitoring sysfs entries
---------------------------------
======================= ==================================
temp1_input Temperature (RO)
temp1_lcrit Low critical high temperature (RW)
temp1_min Minimum temperature (RW)
temp1_max Maximum temperature (RW)
temp1_crit Critical high temperature (RW)
temp1_lcrit_alarm Temperature low critical alarm
temp1_min_alarm Temperature low alarm
temp1_max_alarm Temperature high alarm
temp1_crit_alarm Temperature critical alarm
======================= ==================================
Alarm attributes are sticky until read and will be cleared afterwards
unless the alarm condition still applies.
SPD (Serial Presence Detect) support
------------------------------------
The driver also supports reading the SPD NVRAM on SPD5118 compatible chips.
SPD data is available from the 'eeprom' binary attribute file attached to the
chip's I2C device.
+60
View File
@@ -3549,6 +3549,15 @@ W: https://ez.analog.com/linux-software-drivers
F: Documentation/devicetree/bindings/spi/adi,axi-spi-engine.yaml
F: drivers/spi/spi-axi-spi-engine.c
AXI PWM GENERATOR
M: Michael Hennerich <michael.hennerich@analog.com>
M: Nuno Sá <nuno.sa@analog.com>
L: linux-pwm@vger.kernel.org
S: Supported
W: https://ez.analog.com/linux-software-drivers
F: Documentation/devicetree/bindings/pwm/adi,axi-pwmgen.yaml
F: drivers/pwm/pwm-axi-pwmgen.c
AXXIA I2C CONTROLLER
M: Krzysztof Adamski <krzysztof.adamski@nokia.com>
L: linux-i2c@vger.kernel.org
@@ -5128,11 +5137,25 @@ S: Maintained
F: Documentation/devicetree/bindings/sound/google,cros-ec-codec.yaml
F: sound/soc/codecs/cros_ec_codec.*
CHROMEOS EC CHARGE CONTROL
M: Thomas Weißschuh <thomas@weissschuh.net>
S: Maintained
F: drivers/power/supply/cros_charge-control.c
CHROMEOS EC HARDWARE MONITORING
M: Thomas Weißschuh <thomas@weissschuh.net>
L: chrome-platform@lists.linux.dev
L: linux-hwmon@vger.kernel.org
S: Maintained
F: Documentation/hwmon/cros_ec_hwmon.rst
F: drivers/hwmon/cros_ec_hwmon.c
CHROMEOS EC SUBDRIVERS
M: Benson Leung <bleung@chromium.org>
R: Guenter Roeck <groeck@chromium.org>
L: chrome-platform@lists.linux.dev
S: Maintained
F: drivers/power/supply/cros_charge-control.c
F: drivers/power/supply/cros_usbpd-charger.c
N: cros_ec
N: cros-ec
@@ -15258,6 +15281,27 @@ S: Maintained
F: Documentation/devicetree/bindings/leds/backlight/mps,mp3309c.yaml
F: drivers/video/backlight/mp3309c.c
MPS MP2891 DRIVER
M: Noah Wang <noahwang.wang@outlook.com>
L: linux-hwmon@vger.kernel.org
S: Maintained
F: Documentation/hwmon/mp2891.rst
F: drivers/hwmon/pmbus/mp2891.c
MPS MP2993 DRIVER
M: Noah Wang <noahwang.wang@outlook.com>
L: linux-hwmon@vger.kernel.org
S: Maintained
F: Documentation/hwmon/mp2993.rst
F: drivers/hwmon/pmbus/mp2993.c
MPS MP9941 DRIVER
M: Noah Wang <noahwang.wang@outlook.com>
L: linux-hwmon@vger.kernel.org
S: Maintained
F: Documentation/hwmon/mp9941.rst
F: drivers/hwmon/pmbus/mp9941.c
MR800 AVERMEDIA USB FM RADIO DRIVER
M: Alexey Klimov <klimov.linux@gmail.com>
L: linux-media@vger.kernel.org
@@ -17354,6 +17398,14 @@ F: Documentation/driver-api/pci/p2pdma.rst
F: drivers/pci/p2pdma.c
F: include/linux/pci-p2pdma.h
PCI POWER CONTROL
M: Bartosz Golaszewski <brgl@bgdev.pl>
L: linux-pci@vger.kernel.org
S: Maintained
T: git git://git.kernel.org/pub/scm/linux/kernel/git/pci/pci.git
F: drivers/pci/pwrctl/*
F: include/linux/pci-pwrctl.h
PCI SUBSYSTEM
M: Bjorn Helgaas <bhelgaas@google.com>
L: linux-pci@vger.kernel.org
@@ -17894,6 +17946,14 @@ F: include/linux/pm_*
F: include/linux/powercap.h
F: kernel/configs/nopm.config
POWER SEQUENCING
M: Bartosz Golaszewski <brgl@bgdev.pl>
L: linux-pm@vger.kernel.org
S: Maintained
T: git git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux.git
F: drivers/power/sequencing/
F: include/linux/pwrseq/
POWER STATE COORDINATION INTERFACE (PSCI)
M: Mark Rutland <mark.rutland@arm.com>
M: Lorenzo Pieralisi <lpieralisi@kernel.org>
-2
View File
@@ -78,8 +78,6 @@ obj-$(CONFIG_CPU_XSC3) += xscale-cp0.o
obj-$(CONFIG_CPU_MOHAWK) += xscale-cp0.o
obj-$(CONFIG_IWMMXT) += iwmmxt.o
obj-$(CONFIG_PERF_EVENTS) += perf_regs.o perf_callchain.o
obj-$(CONFIG_HW_PERF_EVENTS) += perf_event_xscale.o perf_event_v6.o \
perf_event_v7.o
AFLAGS_iwmmxt.o := -Wa,-mcpu=iwmmxt
obj-$(CONFIG_ARM_CPU_TOPOLOGY) += topology.o
obj-$(CONFIG_VDSO) += vdso.o
+14 -27
View File
@@ -5,6 +5,7 @@ config ARM64
select ACPI_CCA_REQUIRED if ACPI
select ACPI_GENERIC_GSI if ACPI
select ACPI_GTDT if ACPI
select ACPI_HOTPLUG_CPU if ACPI_PROCESSOR && HOTPLUG_CPU
select ACPI_IORT if ACPI
select ACPI_REDUCED_HARDWARE_ONLY if ACPI
select ACPI_MCFG if (ACPI && PCI)
@@ -381,7 +382,7 @@ config BROKEN_GAS_INST
config BUILTIN_RETURN_ADDRESS_STRIPS_PAC
bool
# Clang's __builtin_return_adddress() strips the PAC since 12.0.0
# Clang's __builtin_return_address() strips the PAC since 12.0.0
# https://github.com/llvm/llvm-project/commit/2a96f47c5ffca84cd774ad402cacd137f4bf45e2
default y if CC_IS_CLANG
# GCC's __builtin_return_address() strips the PAC since 11.1.0,
@@ -1067,15 +1068,21 @@ config ARM64_ERRATUM_3117295
If unsure, say Y.
config ARM64_WORKAROUND_SPECULATIVE_SSBS
bool
config ARM64_ERRATUM_3194386
bool "Cortex-X4: 3194386: workaround for MSR SSBS not self-synchronizing"
select ARM64_WORKAROUND_SPECULATIVE_SSBS
bool "Cortex-{A720,X4,X925}/Neoverse-V3: workaround for MSR SSBS not self-synchronizing"
default y
help
This option adds the workaround for ARM Cortex-X4 erratum 3194386.
This option adds the workaround for the following errata:
* ARM Cortex-A710 erratam 3324338
* ARM Cortex-A720 erratum 3456091
* ARM Cortex-X2 erratum 3324338
* ARM Cortex-X3 erratum 3324335
* ARM Cortex-X4 erratum 3194386
* ARM Cortex-X925 erratum 3324334
* ARM Neoverse N2 erratum 3324339
* ARM Neoverse V2 erratum 3324336
* ARM Neoverse-V3 erratum 3312417
On affected cores "MSR SSBS, #0" instructions may not affect
subsequent speculative instructions, which may permit unexepected
@@ -1089,26 +1096,6 @@ config ARM64_ERRATUM_3194386
If unsure, say Y.
config ARM64_ERRATUM_3312417
bool "Neoverse-V3: 3312417: workaround for MSR SSBS not self-synchronizing"
select ARM64_WORKAROUND_SPECULATIVE_SSBS
default y
help
This option adds the workaround for ARM Neoverse-V3 erratum 3312417.
On affected cores "MSR SSBS, #0" instructions may not affect
subsequent speculative instructions, which may permit unexepected
speculative store bypassing.
Work around this problem by placing a speculation barrier after
kernel changes to SSBS. The presence of the SSBS special-purpose
register is hidden from hwcaps and EL0 reads of ID_AA64PFR1_EL1, such
that userspace will use the PR_SPEC_STORE_BYPASS prctl to change
SSBS.
If unsure, say Y.
config CAVIUM_ERRATUM_22375
bool "Cavium erratum 22375, 24313"
default y
+12
View File
@@ -119,6 +119,18 @@ static inline u32 get_acpi_id_for_cpu(unsigned int cpu)
return acpi_cpu_get_madt_gicc(cpu)->uid;
}
static inline int get_cpu_for_acpi_id(u32 uid)
{
int cpu;
for (cpu = 0; cpu < nr_cpu_ids; cpu++)
if (acpi_cpu_get_madt_gicc(cpu) &&
uid == get_acpi_id_for_cpu(cpu))
return cpu;
return -EINVAL;
}
static inline void arch_fix_phys_package_id(int num, u32 slot) { }
void __init acpi_init_cpus(void);
int apei_claim_sea(struct pt_regs *regs);
-15
View File
@@ -175,21 +175,6 @@ static inline bool gic_prio_masking_enabled(void)
static inline void gic_pmr_mask_irqs(void)
{
BUILD_BUG_ON(GICD_INT_DEF_PRI < (__GIC_PRIO_IRQOFF |
GIC_PRIO_PSR_I_SET));
BUILD_BUG_ON(GICD_INT_DEF_PRI >= GIC_PRIO_IRQON);
/*
* Need to make sure IRQON allows IRQs when SCR_EL3.FIQ is cleared
* and non-secure PMR accesses are not subject to the shifts that
* are applied to IRQ priorities
*/
BUILD_BUG_ON((0x80 | (GICD_INT_DEF_PRI >> 1)) >= GIC_PRIO_IRQON);
/*
* Same situation as above, but now we make sure that we can mask
* regular interrupts.
*/
BUILD_BUG_ON((0x80 | (GICD_INT_DEF_PRI >> 1)) < (__GIC_PRIO_IRQOFF_NS |
GIC_PRIO_PSR_I_SET));
gic_write_pmr(GIC_PRIO_IRQOFF);
}
+1 -1
View File
@@ -15,7 +15,7 @@
#include <linux/bug.h>
#include <linux/init.h>
#include <linux/jump_label.h>
#include <linux/smp.h>
#include <linux/percpu.h>
#include <linux/types.h>
#include <clocksource/arm_arch_timer.h>
+1 -1
View File
@@ -6,7 +6,7 @@
#ifndef __ASM_PMUV3_H
#define __ASM_PMUV3_H
#include <linux/kvm_host.h>
#include <asm/kvm_host.h>
#include <asm/cpufeature.h>
#include <asm/sysreg.h>
+1 -1
View File
@@ -59,7 +59,7 @@ cpucap_is_possible(const unsigned int cap)
case ARM64_WORKAROUND_REPEAT_TLBI:
return IS_ENABLED(CONFIG_ARM64_WORKAROUND_REPEAT_TLBI);
case ARM64_WORKAROUND_SPECULATIVE_SSBS:
return IS_ENABLED(CONFIG_ARM64_WORKAROUND_SPECULATIVE_SSBS);
return IS_ENABLED(CONFIG_ARM64_ERRATUM_3194386);
}
return true;
+2 -2
View File
@@ -588,14 +588,14 @@ static inline bool id_aa64pfr0_32bit_el1(u64 pfr0)
{
u32 val = cpuid_feature_extract_unsigned_field(pfr0, ID_AA64PFR0_EL1_EL1_SHIFT);
return val == ID_AA64PFR0_EL1_ELx_32BIT_64BIT;
return val == ID_AA64PFR0_EL1_EL1_AARCH32;
}
static inline bool id_aa64pfr0_32bit_el0(u64 pfr0)
{
u32 val = cpuid_feature_extract_unsigned_field(pfr0, ID_AA64PFR0_EL1_EL0_SHIFT);
return val == ID_AA64PFR0_EL1_ELx_32BIT_64BIT;
return val == ID_AA64PFR0_EL1_EL0_AARCH32;
}
static inline bool id_aa64pfr0_sve(u64 pfr0)
+6
View File
@@ -86,9 +86,12 @@
#define ARM_CPU_PART_CORTEX_X2 0xD48
#define ARM_CPU_PART_NEOVERSE_N2 0xD49
#define ARM_CPU_PART_CORTEX_A78C 0xD4B
#define ARM_CPU_PART_CORTEX_X3 0xD4E
#define ARM_CPU_PART_NEOVERSE_V2 0xD4F
#define ARM_CPU_PART_CORTEX_A720 0xD81
#define ARM_CPU_PART_CORTEX_X4 0xD82
#define ARM_CPU_PART_NEOVERSE_V3 0xD84
#define ARM_CPU_PART_CORTEX_X925 0xD85
#define APM_CPU_PART_XGENE 0x000
#define APM_CPU_VAR_POTENZA 0x00
@@ -162,9 +165,12 @@
#define MIDR_CORTEX_X2 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X2)
#define MIDR_NEOVERSE_N2 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_N2)
#define MIDR_CORTEX_A78C MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A78C)
#define MIDR_CORTEX_X3 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X3)
#define MIDR_NEOVERSE_V2 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_V2)
#define MIDR_CORTEX_A720 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A720)
#define MIDR_CORTEX_X4 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X4)
#define MIDR_NEOVERSE_V3 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_V3)
#define MIDR_CORTEX_X925 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X925)
#define MIDR_THUNDERX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX)
#define MIDR_THUNDERX_81XX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX_81XX)
#define MIDR_THUNDERX_83XX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX_83XX)
+27 -6
View File
@@ -121,6 +121,14 @@
#define ESR_ELx_FSC_SECC (0x18)
#define ESR_ELx_FSC_SECC_TTW(n) (0x1c + (n))
/* Status codes for individual page table levels */
#define ESR_ELx_FSC_ACCESS_L(n) (ESR_ELx_FSC_ACCESS + n)
#define ESR_ELx_FSC_PERM_L(n) (ESR_ELx_FSC_PERM + n)
#define ESR_ELx_FSC_FAULT_nL (0x2C)
#define ESR_ELx_FSC_FAULT_L(n) (((n) < 0 ? ESR_ELx_FSC_FAULT_nL : \
ESR_ELx_FSC_FAULT) + (n))
/* ISS field definitions for Data Aborts */
#define ESR_ELx_ISV_SHIFT (24)
#define ESR_ELx_ISV (UL(1) << ESR_ELx_ISV_SHIFT)
@@ -388,20 +396,33 @@ static inline bool esr_is_data_abort(unsigned long esr)
static inline bool esr_fsc_is_translation_fault(unsigned long esr)
{
/* Translation fault, level -1 */
if ((esr & ESR_ELx_FSC) == 0b101011)
return true;
return (esr & ESR_ELx_FSC_TYPE) == ESR_ELx_FSC_FAULT;
esr = esr & ESR_ELx_FSC;
return (esr == ESR_ELx_FSC_FAULT_L(3)) ||
(esr == ESR_ELx_FSC_FAULT_L(2)) ||
(esr == ESR_ELx_FSC_FAULT_L(1)) ||
(esr == ESR_ELx_FSC_FAULT_L(0)) ||
(esr == ESR_ELx_FSC_FAULT_L(-1));
}
static inline bool esr_fsc_is_permission_fault(unsigned long esr)
{
return (esr & ESR_ELx_FSC_TYPE) == ESR_ELx_FSC_PERM;
esr = esr & ESR_ELx_FSC;
return (esr == ESR_ELx_FSC_PERM_L(3)) ||
(esr == ESR_ELx_FSC_PERM_L(2)) ||
(esr == ESR_ELx_FSC_PERM_L(1)) ||
(esr == ESR_ELx_FSC_PERM_L(0));
}
static inline bool esr_fsc_is_access_flag_fault(unsigned long esr)
{
return (esr & ESR_ELx_FSC_TYPE) == ESR_ELx_FSC_ACCESS;
esr = esr & ESR_ELx_FSC;
return (esr == ESR_ELx_FSC_ACCESS_L(3)) ||
(esr == ESR_ELx_FSC_ACCESS_L(2)) ||
(esr == ESR_ELx_FSC_ACCESS_L(1)) ||
(esr == ESR_ELx_FSC_ACCESS_L(0));
}
/* Indicate whether ESR.EC==0x1A is for an ERETAx instruction */
+2 -2
View File
@@ -72,11 +72,11 @@ static inline void __cpu_set_tcr_t0sz(unsigned long t0sz)
{
unsigned long tcr = read_sysreg(tcr_el1);
if ((tcr & TCR_T0SZ_MASK) >> TCR_T0SZ_OFFSET == t0sz)
if ((tcr & TCR_T0SZ_MASK) == t0sz)
return;
tcr &= ~TCR_T0SZ_MASK;
tcr |= t0sz << TCR_T0SZ_OFFSET;
tcr |= t0sz;
write_sysreg(tcr, tcr_el1);
isb();
}
+2 -2
View File
@@ -182,7 +182,7 @@ void mte_check_tfsr_el1(void);
static inline void mte_check_tfsr_entry(void)
{
if (!system_supports_mte())
if (!kasan_hw_tags_enabled())
return;
mte_check_tfsr_el1();
@@ -190,7 +190,7 @@ static inline void mte_check_tfsr_entry(void)
static inline void mte_check_tfsr_exit(void)
{
if (!system_supports_mte())
if (!kasan_hw_tags_enabled())
return;
/*
+5 -28
View File
@@ -21,35 +21,12 @@
#define INIT_PSTATE_EL2 \
(PSR_D_BIT | PSR_A_BIT | PSR_I_BIT | PSR_F_BIT | PSR_MODE_EL2h)
/*
* PMR values used to mask/unmask interrupts.
*
* GIC priority masking works as follows: if an IRQ's priority is a higher value
* than the value held in PMR, that IRQ is masked. Lowering the value of PMR
* means masking more IRQs (or at least that the same IRQs remain masked).
*
* To mask interrupts, we clear the most significant bit of PMR.
*
* Some code sections either automatically switch back to PSR.I or explicitly
* require to not use priority masking. If bit GIC_PRIO_PSR_I_SET is included
* in the priority mask, it indicates that PSR.I should be set and
* interrupt disabling temporarily does not rely on IRQ priorities.
*/
#define GIC_PRIO_IRQON 0xe0
#define __GIC_PRIO_IRQOFF (GIC_PRIO_IRQON & ~0x80)
#define __GIC_PRIO_IRQOFF_NS 0xa0
#define GIC_PRIO_PSR_I_SET (1 << 4)
#include <linux/irqchip/arm-gic-v3-prio.h>
#define GIC_PRIO_IRQOFF \
({ \
extern struct static_key_false gic_nonsecure_priorities;\
u8 __prio = __GIC_PRIO_IRQOFF; \
\
if (static_branch_unlikely(&gic_nonsecure_priorities)) \
__prio = __GIC_PRIO_IRQOFF_NS; \
\
__prio; \
})
#define GIC_PRIO_IRQON GICV3_PRIO_UNMASKED
#define GIC_PRIO_IRQOFF GICV3_PRIO_IRQ
#define GIC_PRIO_PSR_I_SET GICV3_PRIO_PSR_I_SET
/* Additional SPSR bits not exposed in the UABI */
#define PSR_MODE_THREAD_BIT (1 << 0)
+1 -12
View File
@@ -25,22 +25,11 @@
#ifndef __ASSEMBLY__
#include <asm/percpu.h>
#include <linux/threads.h>
#include <linux/cpumask.h>
#include <linux/thread_info.h>
DECLARE_PER_CPU_READ_MOSTLY(int, cpu_number);
/*
* We don't use this_cpu_read(cpu_number) as that has implicit writes to
* preempt_count, and associated (compiler) barriers, that we'd like to avoid
* the expense of. If we're preemptible, the value can be stale at use anyway.
* And we can't use this_cpu_ptr() either, as that winds up recursing back
* here under CONFIG_DEBUG_PREEMPT=y.
*/
#define raw_smp_processor_id() (*raw_cpu_ptr(&cpu_number))
#define raw_smp_processor_id() (current_thread_info()->cpu)
/*
* Logical CPU mapping.
-4
View File
@@ -872,10 +872,6 @@
/* Position the attr at the correct index */
#define MAIR_ATTRIDX(attr, idx) ((attr) << ((idx) * 8))
/* id_aa64pfr0 */
#define ID_AA64PFR0_EL1_ELx_64BIT_ONLY 0x1
#define ID_AA64PFR0_EL1_ELx_32BIT_64BIT 0x2
/* id_aa64mmfr0 */
#define ID_AA64MMFR0_EL1_TGRAN4_SUPPORTED_MIN 0x0
#define ID_AA64MMFR0_EL1_TGRAN4_LPA2 ID_AA64MMFR0_EL1_TGRAN4_52_BIT
-1
View File
@@ -46,7 +46,6 @@ obj-$(CONFIG_PERF_EVENTS) += perf_regs.o perf_callchain.o
obj-$(CONFIG_HARDLOCKUP_DETECTOR_PERF) += watchdog_hld.o
obj-$(CONFIG_HAVE_HW_BREAKPOINT) += hw_breakpoint.o
obj-$(CONFIG_CPU_PM) += sleep.o suspend.o
obj-$(CONFIG_CPU_IDLE) += cpuidle.o
obj-$(CONFIG_JUMP_LABEL) += jump_label.o
obj-$(CONFIG_KGDB) += kgdb.o
obj-$(CONFIG_EFI) += efi.o efi-rt-wrapper.o
+31 -98
View File
@@ -30,6 +30,7 @@
#include <linux/pgtable.h>
#include <acpi/ghes.h>
#include <acpi/processor.h>
#include <asm/cputype.h>
#include <asm/cpu_ops.h>
#include <asm/daifflags.h>
@@ -45,6 +46,7 @@ EXPORT_SYMBOL(acpi_pci_disabled);
static bool param_acpi_off __initdata;
static bool param_acpi_on __initdata;
static bool param_acpi_force __initdata;
static bool param_acpi_nospcr __initdata;
static int __init parse_acpi(char *arg)
{
@@ -58,6 +60,8 @@ static int __init parse_acpi(char *arg)
param_acpi_on = true;
else if (strcmp(arg, "force") == 0) /* force ACPI to be enabled */
param_acpi_force = true;
else if (strcmp(arg, "nospcr") == 0) /* disable SPCR as default console */
param_acpi_nospcr = true;
else
return -EINVAL; /* Core will print when we return error */
@@ -237,7 +241,20 @@ done:
acpi_put_table(facs);
}
#endif
acpi_parse_spcr(earlycon_acpi_spcr_enable, true);
/*
* For varying privacy and security reasons, sometimes need
* to completely silence the serial console output, and only
* enable it when needed.
* But there are many existing systems that depend on this
* behaviour, use acpi=nospcr to disable console in ACPI SPCR
* table as default serial console.
*/
acpi_parse_spcr(earlycon_acpi_spcr_enable,
!param_acpi_nospcr);
pr_info("Use ACPI SPCR as default console: %s\n",
param_acpi_nospcr ? "No" : "Yes");
if (IS_ENABLED(CONFIG_ACPI_BGRT))
acpi_table_parse(ACPI_SIG_BGRT, acpi_parse_bgrt);
}
@@ -423,107 +440,23 @@ 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)
#ifdef CONFIG_ACPI_HOTPLUG_CPU
int acpi_map_cpu(acpi_handle handle, phys_cpuid_t physid, u32 apci_id,
int *pcpu)
{
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;
/* If an error code is passed in this stub can't fix it */
if (*pcpu < 0) {
pr_warn_once("Unable to map CPU to valid ID\n");
return *pcpu;
}
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;
return 0;
}
EXPORT_SYMBOL(acpi_map_cpu);
static bool acpi_ffh_smccc_owner_allowed(u32 fid)
int acpi_unmap_cpu(int cpu)
{
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;
return 0;
}
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 */
EXPORT_SYMBOL(acpi_unmap_cpu);
#endif /* CONFIG_ACPI_HOTPLUG_CPU */
-11
View File
@@ -34,17 +34,6 @@ int __init acpi_numa_get_nid(unsigned int cpu)
return acpi_early_node_map[cpu];
}
static inline int get_cpu_for_acpi_id(u32 uid)
{
int cpu;
for (cpu = 0; cpu < nr_cpu_ids; cpu++)
if (uid == get_acpi_id_for_cpu(cpu))
return cpu;
return -EINVAL;
}
static int __init acpi_parse_gicc_pxm(union acpi_subtable_headers *header,
const unsigned long end)
{
+10 -7
View File
@@ -432,14 +432,17 @@ static const struct midr_range erratum_spec_unpriv_load_list[] = {
};
#endif
#ifdef CONFIG_ARM64_WORKAROUND_SPECULATIVE_SSBS
static const struct midr_range erratum_spec_ssbs_list[] = {
#ifdef CONFIG_ARM64_ERRATUM_3194386
static const struct midr_range erratum_spec_ssbs_list[] = {
MIDR_ALL_VERSIONS(MIDR_CORTEX_A710),
MIDR_ALL_VERSIONS(MIDR_CORTEX_A720),
MIDR_ALL_VERSIONS(MIDR_CORTEX_X2),
MIDR_ALL_VERSIONS(MIDR_CORTEX_X3),
MIDR_ALL_VERSIONS(MIDR_CORTEX_X4),
#endif
#ifdef CONFIG_ARM64_ERRATUM_3312417
MIDR_ALL_VERSIONS(MIDR_CORTEX_X925),
MIDR_ALL_VERSIONS(MIDR_NEOVERSE_N2),
MIDR_ALL_VERSIONS(MIDR_NEOVERSE_V3),
#endif
MIDR_ALL_VERSIONS(MIDR_NEOVERSE_V2),
{}
};
#endif
@@ -741,9 +744,9 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
MIDR_FIXED(MIDR_CPU_VAR_REV(1,1), BIT(25)),
},
#endif
#ifdef CONFIG_ARM64_WORKAROUND_SPECULATIVE_SSBS
#ifdef CONFIG_ARM64_ERRATUM_3194386
{
.desc = "ARM errata 3194386, 3312417",
.desc = "SSBS not fully self-synchronizing",
.capability = ARM64_WORKAROUND_SPECULATIVE_SSBS,
ERRATA_MIDR_RANGE_LIST(erratum_spec_ssbs_list),
},
+3 -2
View File
@@ -285,8 +285,8 @@ static const struct arm64_ftr_bits ftr_id_aa64pfr0[] = {
S_ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR0_EL1_FP_SHIFT, 4, ID_AA64PFR0_EL1_FP_NI),
ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64PFR0_EL1_EL3_SHIFT, 4, 0),
ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64PFR0_EL1_EL2_SHIFT, 4, 0),
ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64PFR0_EL1_EL1_SHIFT, 4, ID_AA64PFR0_EL1_ELx_64BIT_ONLY),
ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64PFR0_EL1_EL0_SHIFT, 4, ID_AA64PFR0_EL1_ELx_64BIT_ONLY),
ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64PFR0_EL1_EL1_SHIFT, 4, ID_AA64PFR0_EL1_EL1_IMP),
ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64PFR0_EL1_EL0_SHIFT, 4, ID_AA64PFR0_EL1_EL0_IMP),
ARM64_FTR_END,
};
@@ -429,6 +429,7 @@ static const struct arm64_ftr_bits ftr_id_aa64mmfr0[] = {
};
static const struct arm64_ftr_bits ftr_id_aa64mmfr1[] = {
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR1_EL1_ECBHB_SHIFT, 4, 0),
ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64MMFR1_EL1_TIDCP1_SHIFT, 4, 0),
ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR1_EL1_AFP_SHIFT, 4, 0),
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR1_EL1_HCX_SHIFT, 4, 0),
-5
View File
@@ -105,11 +105,6 @@ KVM_NVHE_ALIAS(__hyp_stub_vectors);
KVM_NVHE_ALIAS(vgic_v2_cpuif_trap);
KVM_NVHE_ALIAS(vgic_v3_cpuif_trap);
#ifdef CONFIG_ARM64_PSEUDO_NMI
/* Static key checked in GIC_PRIO_IRQOFF. */
KVM_NVHE_ALIAS(gic_nonsecure_priorities);
#endif
/* EL2 exception handling */
KVM_NVHE_ALIAS(__start___kvm_ex_table);
KVM_NVHE_ALIAS(__stop___kvm_ex_table);
+1 -1
View File
@@ -567,7 +567,7 @@ static enum mitigation_state spectre_v4_enable_hw_mitigation(void)
* Mitigate this with an unconditional speculation barrier, as CPUs
* could mis-speculate branches and bypass a conditional barrier.
*/
if (IS_ENABLED(CONFIG_ARM64_WORKAROUND_SPECULATIVE_SSBS))
if (IS_ENABLED(CONFIG_ARM64_ERRATUM_3194386))
spec_bar();
return SPECTRE_MITIGATED;
+1 -1
View File
@@ -40,7 +40,7 @@ static int cpu_psci_cpu_boot(unsigned int cpu)
{
phys_addr_t pa_secondary_entry = __pa_symbol(secondary_entry);
int err = psci_ops.cpu_on(cpu_logical_map(cpu), pa_secondary_entry);
if (err)
if (err && err != -EPERM)
pr_err("failed to boot CPU%d (%d)\n", cpu, err);
return err;
+1
View File
@@ -74,4 +74,5 @@ static void __exit reloc_test_exit(void)
module_init(reloc_test_init);
module_exit(reloc_test_exit);
MODULE_DESCRIPTION("Relocation testing module");
MODULE_LICENSE("GPL v2");
+63 -10
View File
@@ -57,8 +57,6 @@
#undef CREATE_TRACE_POINTS
#include <trace/hooks/debug.h>
DEFINE_PER_CPU_READ_MOSTLY(int, cpu_number);
EXPORT_PER_CPU_SYMBOL(cpu_number);
EXPORT_TRACEPOINT_SYMBOL_GPL(ipi_raise);
EXPORT_TRACEPOINT_SYMBOL_GPL(ipi_entry);
EXPORT_TRACEPOINT_SYMBOL_GPL(ipi_exit);
@@ -137,7 +135,8 @@ int __cpu_up(unsigned int cpu, struct task_struct *idle)
/* Now bring the CPU into our world */
ret = boot_secondary(cpu, idle);
if (ret) {
pr_err("CPU%u: failed to boot: %d\n", cpu, ret);
if (ret != -EPERM)
pr_err("CPU%u: failed to boot: %d\n", cpu, ret);
return ret;
}
@@ -515,6 +514,59 @@ static int __init smp_cpu_setup(int cpu)
static bool bootcpu_valid __initdata;
static unsigned int cpu_count = 1;
int arch_register_cpu(int cpu)
{
acpi_handle acpi_handle = acpi_get_processor_handle(cpu);
struct cpu *c = &per_cpu(cpu_devices, cpu);
if (!acpi_disabled && !acpi_handle &&
IS_ENABLED(CONFIG_ACPI_HOTPLUG_CPU))
return -EPROBE_DEFER;
#ifdef CONFIG_ACPI_HOTPLUG_CPU
/* For now block anything that looks like physical CPU Hotplug */
if (invalid_logical_cpuid(cpu) || !cpu_present(cpu)) {
pr_err_once("Changing CPU present bit is not supported\n");
return -ENODEV;
}
#endif
/*
* Availability of the acpi handle is sufficient to establish
* that _STA has aleady been checked. No need to recheck here.
*/
c->hotpluggable = arch_cpu_is_hotpluggable(cpu);
return register_cpu(c, cpu);
}
#ifdef CONFIG_ACPI_HOTPLUG_CPU
void arch_unregister_cpu(int cpu)
{
acpi_handle acpi_handle = acpi_get_processor_handle(cpu);
struct cpu *c = &per_cpu(cpu_devices, cpu);
acpi_status status;
unsigned long long sta;
if (!acpi_handle) {
pr_err_once("Removing a CPU without associated ACPI handle\n");
return;
}
status = acpi_evaluate_integer(acpi_handle, "_STA", NULL, &sta);
if (ACPI_FAILURE(status))
return;
/* For now do not allow anything that looks like physical CPU HP */
if (cpu_present(cpu) && !(sta & ACPI_STA_DEVICE_PRESENT)) {
pr_err_once("Changing CPU present bit is not supported\n");
return;
}
unregister_cpu(c);
}
#endif /* CONFIG_ACPI_HOTPLUG_CPU */
#ifdef CONFIG_ACPI
static struct acpi_madt_generic_interrupt cpu_madt_gicc[NR_CPUS];
@@ -535,7 +587,8 @@ acpi_map_gic_cpu_interface(struct acpi_madt_generic_interrupt *processor)
{
u64 hwid = processor->arm_mpidr;
if (!acpi_gicc_is_usable(processor)) {
if (!(processor->flags &
(ACPI_MADT_ENABLED | ACPI_MADT_GICC_ONLINE_CAPABLE))) {
pr_debug("skipping disabled CPU entry with 0x%llx MPIDR\n", hwid);
return;
}
@@ -754,8 +807,6 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
*/
for_each_possible_cpu(cpu) {
per_cpu(cpu_number, cpu) = cpu;
if (cpu == smp_processor_id())
continue;
@@ -772,13 +823,15 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
}
}
static const char *ipi_types[NR_IPI] __tracepoint_string = {
static const char *ipi_types[MAX_IPI] __tracepoint_string = {
[IPI_RESCHEDULE] = "Rescheduling interrupts",
[IPI_CALL_FUNC] = "Function call interrupts",
[IPI_CPU_STOP] = "CPU stop interrupts",
[IPI_CPU_CRASH_STOP] = "CPU stop (for crash dump) interrupts",
[IPI_TIMER] = "Timer broadcast interrupts",
[IPI_IRQ_WORK] = "IRQ work interrupts",
[IPI_CPU_BACKTRACE] = "CPU backtrace interrupts",
[IPI_KGDB_ROUNDUP] = "KGDB roundup interrupts",
};
static void smp_cross_call(const struct cpumask *target, unsigned int ipinr);
@@ -789,7 +842,7 @@ int arch_show_interrupts(struct seq_file *p, int prec)
{
unsigned int cpu, i;
for (i = 0; i < NR_IPI; i++) {
for (i = 0; i < MAX_IPI; i++) {
seq_printf(p, "%*s%u:%s", prec - 1, "IPI", i,
prec >= 4 ? " " : "");
for_each_online_cpu(cpu)
@@ -1034,12 +1087,12 @@ void __init set_smp_ipi_range(int ipi_base, int n)
if (ipi_should_be_nmi(i)) {
err = request_percpu_nmi(ipi_base + i, ipi_handler,
"IPI", &cpu_number);
"IPI", &irq_stat);
WARN(err, "Could not request IPI %d as NMI, err=%d\n",
i, err);
} else {
err = request_percpu_irq(ipi_base + i, ipi_handler,
"IPI", &cpu_number);
"IPI", &irq_stat);
WARN(err, "Could not request IPI %d as IRQ, err=%d\n",
i, err);
}
@@ -52,11 +52,11 @@
* Supported by KVM
*/
#define PVM_ID_AA64PFR0_RESTRICT_UNSIGNED (\
FIELD_PREP(ARM64_FEATURE_MASK(ID_AA64PFR0_EL1_EL0), ID_AA64PFR0_EL1_ELx_64BIT_ONLY) | \
FIELD_PREP(ARM64_FEATURE_MASK(ID_AA64PFR0_EL1_EL1), ID_AA64PFR0_EL1_ELx_64BIT_ONLY) | \
FIELD_PREP(ARM64_FEATURE_MASK(ID_AA64PFR0_EL1_EL2), ID_AA64PFR0_EL1_ELx_64BIT_ONLY) | \
FIELD_PREP(ARM64_FEATURE_MASK(ID_AA64PFR0_EL1_EL3), ID_AA64PFR0_EL1_ELx_64BIT_ONLY) | \
FIELD_PREP(ARM64_FEATURE_MASK(ID_AA64PFR0_EL1_RAS), ID_AA64PFR0_EL1_RAS_IMP) \
SYS_FIELD_PREP_ENUM(ID_AA64PFR0_EL1, EL0, IMP) | \
SYS_FIELD_PREP_ENUM(ID_AA64PFR0_EL1, EL1, IMP) | \
SYS_FIELD_PREP_ENUM(ID_AA64PFR0_EL1, EL2, IMP) | \
SYS_FIELD_PREP_ENUM(ID_AA64PFR0_EL1, EL3, IMP) | \
SYS_FIELD_PREP_ENUM(ID_AA64PFR0_EL1, RAS, IMP) \
)
/*
+2 -2
View File
@@ -33,9 +33,9 @@ static void pvm_init_traps_aa64pfr0(struct kvm_vcpu *vcpu)
/* Protected KVM does not support AArch32 guests. */
BUILD_BUG_ON(FIELD_GET(ARM64_FEATURE_MASK(ID_AA64PFR0_EL1_EL0),
PVM_ID_AA64PFR0_RESTRICT_UNSIGNED) != ID_AA64PFR0_EL1_ELx_64BIT_ONLY);
PVM_ID_AA64PFR0_RESTRICT_UNSIGNED) != ID_AA64PFR0_EL1_EL0_IMP);
BUILD_BUG_ON(FIELD_GET(ARM64_FEATURE_MASK(ID_AA64PFR0_EL1_EL1),
PVM_ID_AA64PFR0_RESTRICT_UNSIGNED) != ID_AA64PFR0_EL1_ELx_64BIT_ONLY);
PVM_ID_AA64PFR0_RESTRICT_UNSIGNED) != ID_AA64PFR0_EL1_EL1_IMP);
/*
* Linux guests assume support for floating-point and Advanced SIMD. Do
+1 -1
View File
@@ -276,7 +276,7 @@ static bool pvm_access_id_aarch32(struct kvm_vcpu *vcpu,
* of AArch32 feature id registers.
*/
BUILD_BUG_ON(FIELD_GET(ARM64_FEATURE_MASK(ID_AA64PFR0_EL1_EL1),
PVM_ID_AA64PFR0_RESTRICT_UNSIGNED) > ID_AA64PFR0_EL1_ELx_64BIT_ONLY);
PVM_ID_AA64PFR0_RESTRICT_UNSIGNED) > ID_AA64PFR0_EL1_EL1_IMP);
return pvm_access_raz_wi(vcpu, p, r);
}
-1
View File
@@ -14,7 +14,6 @@
#include <asm/kvm_emulate.h>
#include <kvm/arm_pmu.h>
#include <kvm/arm_vgic.h>
#include <asm/arm_pmuv3.h>
#define PERF_ATTR_CFG1_COUNTER_64BIT BIT(0)
+83 -62
View File
@@ -35,6 +35,17 @@ EXPORT_PER_CPU_SYMBOL(processors);
struct acpi_processor_errata errata __read_mostly;
EXPORT_SYMBOL_GPL(errata);
acpi_handle acpi_get_processor_handle(int cpu)
{
struct acpi_processor *pr;
pr = per_cpu(processors, cpu);
if (pr)
return pr->handle;
return NULL;
}
static int acpi_processor_errata_piix4(struct pci_dev *dev)
{
u8 value1 = 0;
@@ -183,20 +194,44 @@ static void __init acpi_pcc_cpufreq_init(void) {}
#endif /* CONFIG_X86 */
/* Initialization */
#ifdef CONFIG_ACPI_HOTPLUG_CPU
static int acpi_processor_hotadd_init(struct acpi_processor *pr)
static DEFINE_PER_CPU(void *, processor_device_array);
static int acpi_processor_set_per_cpu(struct acpi_processor *pr,
struct acpi_device *device)
{
BUG_ON(pr->id >= nr_cpu_ids);
/*
* Buggy BIOS check.
* ACPI id of processors can be reported wrongly by the BIOS.
* Don't trust it blindly
*/
if (per_cpu(processor_device_array, pr->id) != NULL &&
per_cpu(processor_device_array, pr->id) != device) {
dev_warn(&device->dev,
"BIOS reported wrong ACPI id %d for the processor\n",
pr->id);
return -EINVAL;
}
/*
* processor_device_array is not cleared on errors to allow buggy BIOS
* checks.
*/
per_cpu(processor_device_array, pr->id) = device;
per_cpu(processors, pr->id) = pr;
return 0;
}
#ifdef CONFIG_ACPI_HOTPLUG_CPU
static int acpi_processor_hotadd_init(struct acpi_processor *pr,
struct acpi_device *device)
{
unsigned long long sta;
acpi_status status;
int ret;
if (invalid_phys_cpuid(pr->phys_id))
return -ENODEV;
status = acpi_evaluate_integer(pr->handle, "_STA", NULL, &sta);
if (ACPI_FAILURE(status) || !(sta & ACPI_STA_DEVICE_PRESENT))
return -ENODEV;
cpu_maps_update_begin();
cpus_write_lock();
@@ -204,19 +239,26 @@ static int acpi_processor_hotadd_init(struct acpi_processor *pr)
if (ret)
goto out;
ret = arch_register_cpu(pr->id);
ret = acpi_processor_set_per_cpu(pr, device);
if (ret) {
acpi_unmap_cpu(pr->id);
goto out;
}
ret = arch_register_cpu(pr->id);
if (ret) {
/* Leave the processor device array in place to detect buggy bios */
per_cpu(processors, pr->id) = NULL;
acpi_unmap_cpu(pr->id);
goto out;
}
/*
* CPU got hot-added, but cpu_data is not initialized yet. Set a flag
* to delay cpu_idle/throttling initialization and do it when the CPU
* gets online for the first time.
* CPU got hot-added, but cpu_data is not initialized yet. Do
* cpu_idle/throttling initialization when the CPU gets online for
* the first time.
*/
pr_info("CPU%d has been hot-added\n", pr->id);
pr->flags.need_hotplug_init = 1;
out:
cpus_write_unlock();
@@ -224,7 +266,8 @@ out:
return ret;
}
#else
static inline int acpi_processor_hotadd_init(struct acpi_processor *pr)
static inline int acpi_processor_hotadd_init(struct acpi_processor *pr,
struct acpi_device *device)
{
return -ENODEV;
}
@@ -239,6 +282,7 @@ static int acpi_processor_get_info(struct acpi_device *device)
acpi_status status = AE_OK;
static int cpu0_initialized;
unsigned long long value;
int ret;
acpi_processor_errata();
@@ -315,19 +359,19 @@ static int acpi_processor_get_info(struct acpi_device *device)
}
/*
* Extra Processor objects may be enumerated on MP systems with
* less than the max # of CPUs. They should be ignored _iff
* they are physically not present.
*
* NOTE: Even if the processor has a cpuid, it may not be present
* because cpuid <-> apicid mapping is persistent now.
* This code is not called unless we know the CPU is present and
* enabled. The two paths are:
* a) Initially present CPUs on architectures that do not defer
* their arch_register_cpu() calls until this point.
* b) Hotplugged CPUs (enabled bit in _STA has transitioned from not
* enabled to enabled)
*/
if (invalid_logical_cpuid(pr->id) || !cpu_present(pr->id)) {
int ret = acpi_processor_hotadd_init(pr);
if (ret)
return ret;
}
if (!get_cpu_device(pr->id))
ret = acpi_processor_hotadd_init(pr, device);
else
ret = acpi_processor_set_per_cpu(pr, device);
if (ret)
return ret;
/*
* On some boxes several processors use the same processor bus id.
@@ -372,8 +416,6 @@ static int acpi_processor_get_info(struct acpi_device *device)
* (cpu_data(cpu)) values, like CPU feature flags, family, model, etc.
* Such things have to be put in and set up by the processor driver's .probe().
*/
static DEFINE_PER_CPU(void *, processor_device_array);
static int acpi_processor_add(struct acpi_device *device,
const struct acpi_device_id *id)
{
@@ -400,39 +442,17 @@ static int acpi_processor_add(struct acpi_device *device,
result = acpi_processor_get_info(device);
if (result) /* Processor is not physically present or unavailable */
return 0;
BUG_ON(pr->id >= nr_cpu_ids);
/*
* Buggy BIOS check.
* ACPI id of processors can be reported wrongly by the BIOS.
* Don't trust it blindly
*/
if (per_cpu(processor_device_array, pr->id) != NULL &&
per_cpu(processor_device_array, pr->id) != device) {
dev_warn(&device->dev,
"BIOS reported wrong ACPI id %d for the processor\n",
pr->id);
/* Give up, but do not abort the namespace scan. */
goto err;
}
/*
* processor_device_array is not cleared on errors to allow buggy BIOS
* checks.
*/
per_cpu(processor_device_array, pr->id) = device;
per_cpu(processors, pr->id) = pr;
goto err_clear_driver_data;
dev = get_cpu_device(pr->id);
if (!dev) {
result = -ENODEV;
goto err;
goto err_clear_per_cpu;
}
result = acpi_bind_one(dev, device);
if (result)
goto err;
goto err_clear_per_cpu;
pr->dev = dev;
@@ -443,10 +463,11 @@ static int acpi_processor_add(struct acpi_device *device,
dev_err(dev, "Processor driver could not be attached\n");
acpi_unbind_one(dev);
err:
free_cpumask_var(pr->throttling.shared_cpu_map);
device->driver_data = NULL;
err_clear_per_cpu:
per_cpu(processors, pr->id) = NULL;
err_clear_driver_data:
device->driver_data = NULL;
free_cpumask_var(pr->throttling.shared_cpu_map);
err_free_pr:
kfree(pr);
return result;
@@ -454,7 +475,7 @@ static int acpi_processor_add(struct acpi_device *device,
#ifdef CONFIG_ACPI_HOTPLUG_CPU
/* Removal */
static void acpi_processor_remove(struct acpi_device *device)
static void acpi_processor_post_eject(struct acpi_device *device)
{
struct acpi_processor *pr;
@@ -476,10 +497,6 @@ static void acpi_processor_remove(struct acpi_device *device)
device_release_driver(pr->dev);
acpi_unbind_one(pr->dev);
/* Clean up. */
per_cpu(processor_device_array, pr->id) = NULL;
per_cpu(processors, pr->id) = NULL;
cpu_maps_update_begin();
cpus_write_lock();
@@ -487,6 +504,10 @@ static void acpi_processor_remove(struct acpi_device *device)
arch_unregister_cpu(pr->id);
acpi_unmap_cpu(pr->id);
/* Clean up. */
per_cpu(processor_device_array, pr->id) = NULL;
per_cpu(processors, pr->id) = NULL;
cpus_write_unlock();
cpu_maps_update_done();
@@ -622,7 +643,7 @@ static struct acpi_scan_handler processor_handler = {
.ids = processor_device_ids,
.attach = acpi_processor_add,
#ifdef CONFIG_ACPI_HOTPLUG_CPU
.detach = acpi_processor_remove,
.post_eject = acpi_processor_post_eject,
#endif
.hotplug = {
.enabled = true,
+4 -2
View File
@@ -1,8 +1,10 @@
# SPDX-License-Identifier: GPL-2.0-only
obj-$(CONFIG_ACPI_AGDI) += agdi.o
obj-$(CONFIG_ACPI_IORT) += iort.o
obj-$(CONFIG_ACPI_GTDT) += gtdt.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
obj-$(CONFIG_ARM_AMBA) += amba.o
obj-y += dma.o init.o
obj-y += thermal_cpufreq.o
+1 -5
View File
@@ -27,11 +27,7 @@ static const struct acpi_device_id amba_id_list[] = {
static void amba_register_dummy_clk(void)
{
static struct clk *amba_dummy_clk;
/* If clock already registered */
if (amba_dummy_clk)
return;
struct clk *amba_dummy_clk;
amba_dummy_clk = clk_register_fixed_rate(NULL, "apb_pclk", NULL, 0, 0);
clk_register_clkdev(amba_dummy_clk, "apb_pclk", NULL);
@@ -10,9 +10,6 @@
#include <linux/cpuidle.h>
#include <linux/cpu_pm.h>
#include <linux/psci.h>
#ifdef CONFIG_ACPI_PROCESSOR_IDLE
#include <acpi/processor.h>
#define ARM64_LPI_IS_RETENTION_STATE(arch_flags) (!(arch_flags))
@@ -71,4 +68,3 @@ __cpuidle int acpi_processor_ffh_lpi_enter(struct acpi_lpi_state *lpi)
return CPU_PM_CPU_IDLE_ENTER_PARAM_RCU(psci_cpu_suspend_enter,
lpi->index, state);
}
#endif
+107
View File
@@ -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;
}
+15
View File
@@ -756,6 +756,21 @@ end:
}
EXPORT_SYMBOL_GPL(battery_hook_register);
static void devm_battery_hook_unregister(void *data)
{
struct acpi_battery_hook *hook = data;
battery_hook_unregister(hook);
}
int devm_battery_hook_register(struct device *dev, struct acpi_battery_hook *hook)
{
battery_hook_register(hook);
return devm_add_action_or_reset(dev, devm_battery_hook_unregister, hook);
}
EXPORT_SYMBOL_GPL(devm_battery_hook_register);
/*
* This function gets called right after the battery sysfs
* attributes have been added, so that the drivers that
+2 -1
View File
@@ -90,7 +90,8 @@ static int map_gicc_mpidr(struct acpi_subtable_header *entry,
struct acpi_madt_generic_interrupt *gicc =
container_of(entry, struct acpi_madt_generic_interrupt, header);
if (!acpi_gicc_is_usable(gicc))
if (!(gicc->flags &
(ACPI_MADT_ENABLED | ACPI_MADT_GICC_ONLINE_CAPABLE)))
return -ENODEV;
/* device_declaration means Device object in DSDT, in the
+12 -31
View File
@@ -33,7 +33,6 @@ MODULE_AUTHOR("Paul Diefenbaugh");
MODULE_DESCRIPTION("ACPI Processor Driver");
MODULE_LICENSE("GPL");
static int acpi_processor_start(struct device *dev);
static int acpi_processor_stop(struct device *dev);
static const struct acpi_device_id processor_device_ids[] = {
@@ -47,7 +46,6 @@ static struct device_driver acpi_processor_driver = {
.name = "processor",
.bus = &cpu_subsys,
.acpi_match_table = processor_device_ids,
.probe = acpi_processor_start,
.remove = acpi_processor_stop,
};
@@ -115,12 +113,9 @@ static int acpi_soft_cpu_online(unsigned int cpu)
* CPU got physically hotplugged and onlined for the first time:
* Initialize missing things.
*/
if (pr->flags.need_hotplug_init) {
if (!pr->flags.previously_online) {
int ret;
pr_info("Will online and init hotplugged CPU: %d\n",
pr->id);
pr->flags.need_hotplug_init = 0;
ret = __acpi_processor_start(device);
WARN(ret, "Failed to start CPU: %d\n", pr->id);
} else {
@@ -167,9 +162,6 @@ static int __acpi_processor_start(struct acpi_device *device)
if (!pr)
return -ENODEV;
if (pr->flags.need_hotplug_init)
return 0;
result = acpi_cppc_processor_probe(pr);
if (result && !IS_ENABLED(CONFIG_ACPI_CPU_FREQ_PSS))
dev_dbg(&device->dev, "CPPC data invalid or not present\n");
@@ -185,32 +177,21 @@ static int __acpi_processor_start(struct acpi_device *device)
status = acpi_install_notify_handler(device->handle, ACPI_DEVICE_NOTIFY,
acpi_processor_notify, device);
if (ACPI_SUCCESS(status))
return 0;
if (!ACPI_SUCCESS(status)) {
result = -ENODEV;
goto err_thermal_exit;
}
pr->flags.previously_online = 1;
result = -ENODEV;
return 0;
err_thermal_exit:
acpi_processor_thermal_exit(pr, device);
err_power_exit:
acpi_processor_power_exit(pr);
return result;
}
static int acpi_processor_start(struct device *dev)
{
struct acpi_device *device = ACPI_COMPANION(dev);
int ret;
if (!device)
return -ENODEV;
/* Protect against concurrent CPU hotplug operations */
cpu_hotplug_disable();
ret = __acpi_processor_start(device);
cpu_hotplug_enable();
return ret;
}
static int acpi_processor_stop(struct device *dev)
{
struct acpi_device *device = ACPI_COMPANION(dev);
@@ -279,9 +260,9 @@ static int __init acpi_processor_driver_init(void)
if (result < 0)
return result;
result = cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN,
"acpi/cpu-drv:online",
acpi_soft_cpu_online, NULL);
result = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN,
"acpi/cpu-drv:online",
acpi_soft_cpu_online, NULL);
if (result < 0)
goto err;
hp_online = result;
+39 -8
View File
@@ -243,13 +243,17 @@ static int acpi_scan_try_to_offline(struct acpi_device *device)
return 0;
}
static int acpi_scan_check_and_detach(struct acpi_device *adev, void *check)
#define ACPI_SCAN_CHECK_FLAG_STATUS BIT(0)
#define ACPI_SCAN_CHECK_FLAG_EJECT BIT(1)
static int acpi_scan_check_and_detach(struct acpi_device *adev, void *p)
{
struct acpi_scan_handler *handler = adev->handler;
uintptr_t flags = (uintptr_t)p;
acpi_dev_for_each_child_reverse(adev, acpi_scan_check_and_detach, check);
acpi_dev_for_each_child_reverse(adev, acpi_scan_check_and_detach, p);
if (check) {
if (flags & ACPI_SCAN_CHECK_FLAG_STATUS) {
acpi_bus_get_status(adev);
/*
* Skip devices that are still there and take the enabled
@@ -269,8 +273,6 @@ static int acpi_scan_check_and_detach(struct acpi_device *adev, void *check)
if (handler) {
if (handler->detach)
handler->detach(adev);
adev->handler = NULL;
} else {
device_release_driver(&adev->dev);
}
@@ -280,6 +282,28 @@ static int acpi_scan_check_and_detach(struct acpi_device *adev, void *check)
*/
acpi_device_set_power(adev, ACPI_STATE_D3_COLD);
adev->flags.initialized = false;
/* For eject this is deferred to acpi_bus_post_eject() */
if (!(flags & ACPI_SCAN_CHECK_FLAG_EJECT)) {
adev->handler = NULL;
acpi_device_clear_enumerated(adev);
}
return 0;
}
static int acpi_bus_post_eject(struct acpi_device *adev, void *not_used)
{
struct acpi_scan_handler *handler = adev->handler;
acpi_dev_for_each_child_reverse(adev, acpi_bus_post_eject, NULL);
if (handler) {
if (handler->post_eject)
handler->post_eject(adev);
adev->handler = NULL;
}
acpi_device_clear_enumerated(adev);
return 0;
@@ -287,7 +311,9 @@ static int acpi_scan_check_and_detach(struct acpi_device *adev, void *check)
static void acpi_scan_check_subtree(struct acpi_device *adev)
{
acpi_scan_check_and_detach(adev, (void *)true);
uintptr_t flags = ACPI_SCAN_CHECK_FLAG_STATUS;
acpi_scan_check_and_detach(adev, (void *)flags);
}
static int acpi_scan_hot_remove(struct acpi_device *device)
@@ -295,6 +321,7 @@ static int acpi_scan_hot_remove(struct acpi_device *device)
acpi_handle handle = device->handle;
unsigned long long sta;
acpi_status status;
uintptr_t flags = ACPI_SCAN_CHECK_FLAG_EJECT;
if (device->handler && device->handler->hotplug.demand_offline) {
if (!acpi_scan_is_offline(device, true))
@@ -307,7 +334,7 @@ static int acpi_scan_hot_remove(struct acpi_device *device)
acpi_handle_debug(handle, "Ejecting\n");
acpi_bus_trim(device);
acpi_scan_check_and_detach(device, (void *)flags);
acpi_evaluate_lck(handle, 0);
/*
@@ -330,6 +357,8 @@ static int acpi_scan_hot_remove(struct acpi_device *device)
} else if (sta & ACPI_STA_DEVICE_ENABLED) {
acpi_handle_warn(handle,
"Eject incomplete - status 0x%llx\n", sta);
} else {
acpi_bus_post_eject(device, NULL);
}
return 0;
@@ -2596,7 +2625,9 @@ EXPORT_SYMBOL(acpi_bus_scan);
*/
void acpi_bus_trim(struct acpi_device *adev)
{
acpi_scan_check_and_detach(adev, NULL);
uintptr_t flags = 0;
acpi_scan_check_and_detach(adev, (void *)flags);
}
EXPORT_SYMBOL_GPL(acpi_bus_trim);
+11 -1
View File
@@ -95,6 +95,7 @@ void unregister_cpu(struct cpu *cpu)
{
int logical_cpu = cpu->dev.id;
set_cpu_enabled(logical_cpu, false);
unregister_cpu_under_node(logical_cpu, cpu_to_node(logical_cpu));
device_unregister(&cpu->dev);
@@ -273,6 +274,13 @@ static ssize_t print_cpus_offline(struct device *dev,
}
static DEVICE_ATTR(offline, 0444, print_cpus_offline, NULL);
static ssize_t print_cpus_enabled(struct device *dev,
struct device_attribute *attr, char *buf)
{
return sysfs_emit(buf, "%*pbl\n", cpumask_pr_args(cpu_enabled_mask));
}
static DEVICE_ATTR(enabled, 0444, print_cpus_enabled, NULL);
static ssize_t print_cpus_isolated(struct device *dev,
struct device_attribute *attr, char *buf)
{
@@ -413,6 +421,7 @@ int register_cpu(struct cpu *cpu, int num)
register_cpu_under_node(num, cpu_to_node(num));
dev_pm_qos_expose_latency_limit(&cpu->dev,
PM_QOS_RESUME_LATENCY_NO_CONSTRAINT);
set_cpu_enabled(num, true);
return 0;
}
@@ -494,6 +503,7 @@ static struct attribute *cpu_root_attrs[] = {
&cpu_attrs[2].attr.attr,
&dev_attr_kernel_max.attr,
&dev_attr_offline.attr,
&dev_attr_enabled.attr,
&dev_attr_isolated.attr,
#ifdef CONFIG_NO_HZ_FULL
&dev_attr_nohz_full.attr,
@@ -558,7 +568,7 @@ static void __init cpu_dev_register_generic(void)
for_each_present_cpu(i) {
ret = arch_register_cpu(i);
if (ret)
if (ret && ret != -EPROBE_DEFER)
pr_warn("register_cpu %d failed (%d)\n", i, ret);
}
}
+1 -1
View File
@@ -294,7 +294,7 @@ static int ts_nbus_probe(struct platform_device *pdev)
state.duty_cycle = state.period;
state.enabled = true;
ret = pwm_apply_state(pwm, &state);
ret = pwm_apply_might_sleep(pwm, &state);
if (ret < 0)
return dev_err_probe(dev, ret, "failed to configure PWM\n");
+2
View File
@@ -47,6 +47,8 @@ static int tpm_bios_measurements_open(struct inode *inode,
if (!err) {
seq = file->private_data;
seq->private = chip;
} else {
put_device(&chip->dev);
}
return err;
+1
View File
@@ -318,6 +318,7 @@ static void tpm_tis_spi_remove(struct spi_device *dev)
}
static const struct spi_device_id tpm_tis_spi_id[] = {
{ "attpm20p", (unsigned long)tpm_tis_spi_probe },
{ "st33htpm-spi", (unsigned long)tpm_tis_spi_probe },
{ "slb9670", (unsigned long)tpm_tis_spi_probe },
{ "tpm_tis_spi", (unsigned long)tpm_tis_spi_probe },
+41
View File
@@ -363,6 +363,43 @@ static int gdsc_disable(struct generic_pm_domain *domain)
return 0;
}
static int gdsc_set_hwmode(struct generic_pm_domain *domain, struct device *dev, bool mode)
{
struct gdsc *sc = domain_to_gdsc(domain);
int ret;
ret = gdsc_hwctrl(sc, mode);
if (ret)
return ret;
/*
* Wait for the GDSC to go through a power down and
* up cycle. If we poll the status register before the
* power cycle is finished we might read incorrect values.
*/
udelay(1);
/*
* When the GDSC is switched to HW mode, HW can disable the GDSC.
* When the GDSC is switched back to SW mode, the GDSC will be enabled
* again, hence we need to poll for GDSC to complete the power up.
*/
if (!mode)
return gdsc_poll_status(sc, GDSC_ON);
return 0;
}
static bool gdsc_get_hwmode(struct generic_pm_domain *domain, struct device *dev)
{
struct gdsc *sc = domain_to_gdsc(domain);
u32 val;
regmap_read(sc->regmap, sc->gdscr, &val);
return !!(val & HW_CONTROL_MASK);
}
static int gdsc_init(struct gdsc *sc)
{
u32 mask, val;
@@ -451,6 +488,10 @@ static int gdsc_init(struct gdsc *sc)
sc->pd.power_off = gdsc_disable;
if (!sc->pd.power_on)
sc->pd.power_on = gdsc_enable;
if (sc->flags & HW_CTRL_TRIGGER) {
sc->pd.set_hwmode_dev = gdsc_set_hwmode;
sc->pd.get_hwmode_dev = gdsc_get_hwmode;
}
ret = pm_genpd_init(&sc->pd, NULL, !on);
if (ret)
+1
View File
@@ -67,6 +67,7 @@ struct gdsc {
#define ALWAYS_ON BIT(6)
#define RETAIN_FF_ENABLE BIT(7)
#define NO_RET_PERIPH BIT(8)
#define HW_CTRL_TRIGGER BIT(9)
struct reset_controller_dev *rcdev;
unsigned int *resets;
unsigned int reset_count;
+1 -1
View File
@@ -236,7 +236,7 @@ static struct gdsc mvs0_gdsc = {
.name = "mvs0_gdsc",
},
.pwrsts = PWRSTS_OFF_ON,
.flags = HW_CTRL | RETAIN_FF_ENABLE,
.flags = HW_CTRL_TRIGGER | RETAIN_FF_ENABLE,
};
static struct gdsc mvsc_gdsc = {
+2 -2
View File
@@ -293,7 +293,7 @@ static struct gdsc mvs0_gdsc = {
.pd = {
.name = "mvs0_gdsc",
},
.flags = HW_CTRL,
.flags = HW_CTRL_TRIGGER,
.pwrsts = PWRSTS_OFF_ON,
};
@@ -302,7 +302,7 @@ static struct gdsc mvs1_gdsc = {
.pd = {
.name = "mvs1_gdsc",
},
.flags = HW_CTRL,
.flags = HW_CTRL_TRIGGER,
.pwrsts = PWRSTS_OFF_ON,
};
+2 -2
View File
@@ -465,7 +465,7 @@ static int stm32_count_events_configure(struct counter_device *counter)
ret = stm32_count_capture_configure(counter, event_node->channel, true);
if (ret)
return ret;
dier |= TIM_DIER_CC_IE(event_node->channel);
dier |= TIM_DIER_CCxIE(event_node->channel + 1);
break;
default:
/* should never reach this path */
@@ -478,7 +478,7 @@ static int stm32_count_events_configure(struct counter_device *counter)
/* check for disabled capture events */
for (i = 0 ; i < priv->nchannels; i++) {
if (!(dier & TIM_DIER_CC_IE(i))) {
if (!(dier & TIM_DIER_CCxIE(i + 1))) {
ret = stm32_count_capture_configure(counter, i, false);
if (ret)
return ret;
+1
View File
@@ -131,4 +131,5 @@ static struct coreboot_driver cbmem_entry_driver = {
module_coreboot_driver(cbmem_entry_driver);
MODULE_AUTHOR("Jack Rosenthal <jrosenth@chromium.org>");
MODULE_DESCRIPTION("Driver for exporting CBMEM entries in sysfs");
MODULE_LICENSE("GPL");
+1
View File
@@ -255,4 +255,5 @@ module_init(coreboot_table_driver_init);
module_exit(coreboot_table_driver_exit);
MODULE_AUTHOR("Google, Inc.");
MODULE_DESCRIPTION("Module providing coreboot table access");
MODULE_LICENSE("GPL");
@@ -97,4 +97,5 @@ static struct coreboot_driver framebuffer_driver = {
module_coreboot_driver(framebuffer_driver);
MODULE_AUTHOR("Samuel Holland <samuel@sholland.org>");
MODULE_DESCRIPTION("Memory based framebuffer accessed through coreboot table");
MODULE_LICENSE("GPL");
+1
View File
@@ -1090,4 +1090,5 @@ module_init(gsmi_init);
module_exit(gsmi_exit);
MODULE_AUTHOR("Google, Inc.");
MODULE_DESCRIPTION("EFI SMI interface for Google platforms");
MODULE_LICENSE("GPL");
@@ -113,4 +113,5 @@ static struct coreboot_driver memconsole_driver = {
module_coreboot_driver(memconsole_driver);
MODULE_AUTHOR("Google, Inc.");
MODULE_DESCRIPTION("Memory based BIOS console accessed through coreboot table");
MODULE_LICENSE("GPL");
@@ -154,4 +154,5 @@ module_init(memconsole_x86_init);
module_exit(memconsole_x86_exit);
MODULE_AUTHOR("Google, Inc.");
MODULE_DESCRIPTION("EBDA specific parts of the memory based BIOS console.");
MODULE_LICENSE("GPL");
+1
View File
@@ -50,4 +50,5 @@ void memconsole_exit(void)
EXPORT_SYMBOL(memconsole_exit);
MODULE_AUTHOR("Google, Inc.");
MODULE_DESCRIPTION("Architecture-independent parts of the memory based BIOS console");
MODULE_LICENSE("GPL");
+1
View File
@@ -323,4 +323,5 @@ static struct coreboot_driver vpd_driver = {
module_coreboot_driver(vpd_driver);
MODULE_AUTHOR("Google, Inc.");
MODULE_DESCRIPTION("Driver for exporting Vital Product Data content to sysfs");
MODULE_LICENSE("GPL");
+43 -24
View File
@@ -105,18 +105,6 @@ config SENSORS_AD7418
This driver can also be built as a module. If so, the module
will be called ad7418.
config SENSORS_ADM1021
tristate "Analog Devices ADM1021 and compatibles"
depends on I2C
depends on SENSORS_LM90=n
help
If you say yes here you get support for Analog Devices ADM1021
and ADM1023 sensor chips and clones: Maxim MAX1617 and MAX1617A,
Genesys Logic GL523SM, National Semiconductor LM84 and TI THMC10.
This driver can also be built as a module. If so, the module
will be called adm1021.
config SENSORS_ADM1025
tristate "Analog Devices ADM1025 and compatibles"
depends on I2C
@@ -506,6 +494,17 @@ config SENSORS_CORSAIR_PSU
This driver can also be built as a module. If so, the module
will be called corsair-psu.
config SENSORS_CROS_EC
tristate "ChromeOS Embedded Controller sensors"
depends on MFD_CROS_EC_DEV
default MFD_CROS_EC_DEV
help
If you say yes here you get support for ChromeOS Embedded Controller
sensors.
This driver can also be built as a module. If so, the module
will be called cros_ec_hwmon.
config SENSORS_DRIVETEMP
tristate "Hard disk drives with temperature sensors"
depends on SCSI && ATA
@@ -1241,18 +1240,6 @@ config SENSORS_MAX6639
This driver can also be built as a module. If so, the module
will be called max6639.
config SENSORS_MAX6642
tristate "Maxim MAX6642 sensor chip"
depends on I2C
depends on SENSORS_LM90=n
help
If you say yes here you get support for MAX6642 sensor chip.
MAX6642 is a SMBus-Compatible Remote/Local Temperature Sensor
with Overtemperature Alarm from Maxim.
This driver can also be built as a module. If so, the module
will be called max6642.
config SENSORS_MAX6650
tristate "Maxim MAX6650 sensor chip"
depends on I2C
@@ -2127,6 +2114,7 @@ config SENSORS_ADS7871
config SENSORS_AMC6821
tristate "Texas Instruments AMC6821"
depends on I2C
select REGMAP_I2C
help
If you say yes here you get support for the Texas Instruments
AMC6821 hardware monitoring chips.
@@ -2181,6 +2169,37 @@ config SENSORS_INA3221
This driver can also be built as a module. If so, the module
will be called ina3221.
config SENSORS_SPD5118
tristate "SPD5118 Compliant Temperature Sensors"
depends on I2C
select REGMAP_I2C
help
If you say yes here you get support for SPD5118 (JEDEC JESD300)
compliant temperature sensors. Such sensors are found on DDR5 memory
modules.
This driver can also be built as a module. If so, the module
will be called spd5118.
config SENSORS_SPD5118_DETECT
bool "Enable detect function"
depends on SENSORS_SPD5118
default (!DMI || !X86)
help
If enabled, the driver auto-detects if a chip in the SPD address
range is compliant to the SPD51888 standard and auto-instantiates
if that is the case. If disabled, SPD5118 compliant devices have
to be instantiated by other means. On X86 systems with DMI support
this will typically be done from DMI DDR detection code in the
I2C SMBus subsystem. Devicetree based systems will instantiate
attached devices if the DIMMs are listed in the devicetree file.
Disabling the detect function will speed up boot time and reduce
the risk of mis-detecting SPD5118 compliant devices. However, it
may result in missed DIMMs under some circumstances.
If unsure, say Y.
config SENSORS_TC74
tristate "Microchip TC74"
depends on I2C
+2 -2
View File
@@ -31,7 +31,6 @@ obj-$(CONFIG_SENSORS_AD7414) += ad7414.o
obj-$(CONFIG_SENSORS_AD7418) += ad7418.o
obj-$(CONFIG_SENSORS_ADC128D818) += adc128d818.o
obj-$(CONFIG_SENSORS_ADCXX) += adcxx.o
obj-$(CONFIG_SENSORS_ADM1021) += adm1021.o
obj-$(CONFIG_SENSORS_ADM1025) += adm1025.o
obj-$(CONFIG_SENSORS_ADM1026) += adm1026.o
obj-$(CONFIG_SENSORS_ADM1029) += adm1029.o
@@ -64,6 +63,7 @@ obj-$(CONFIG_SENSORS_CHIPCAP2) += chipcap2.o
obj-$(CONFIG_SENSORS_CORETEMP) += coretemp.o
obj-$(CONFIG_SENSORS_CORSAIR_CPRO) += corsair-cpro.o
obj-$(CONFIG_SENSORS_CORSAIR_PSU) += corsair-psu.o
obj-$(CONFIG_SENSORS_CROS_EC) += cros_ec_hwmon.o
obj-$(CONFIG_SENSORS_DA9052_ADC)+= da9052-hwmon.o
obj-$(CONFIG_SENSORS_DA9055)+= da9055-hwmon.o
obj-$(CONFIG_SENSORS_DELL_SMM) += dell-smm-hwmon.o
@@ -154,7 +154,6 @@ obj-$(CONFIG_SENSORS_MAX31760) += max31760.o
obj-$(CONFIG_SENSORS_MAX6620) += max6620.o
obj-$(CONFIG_SENSORS_MAX6621) += max6621.o
obj-$(CONFIG_SENSORS_MAX6639) += max6639.o
obj-$(CONFIG_SENSORS_MAX6642) += max6642.o
obj-$(CONFIG_SENSORS_MAX6650) += max6650.o
obj-$(CONFIG_SENSORS_MAX6697) += max6697.o
obj-$(CONFIG_SENSORS_MAX31790) += max31790.o
@@ -207,6 +206,7 @@ obj-$(CONFIG_SENSORS_SMSC47B397)+= smsc47b397.o
obj-$(CONFIG_SENSORS_SMSC47M1) += smsc47m1.o
obj-$(CONFIG_SENSORS_SMSC47M192)+= smsc47m192.o
obj-$(CONFIG_SENSORS_SPARX5) += sparx5-temp.o
obj-$(CONFIG_SENSORS_SPD5118) += spd5118.o
obj-$(CONFIG_SENSORS_STTS751) += stts751.o
obj-$(CONFIG_SENSORS_SURFACE_FAN)+= surface_fan.o
obj-$(CONFIG_SENSORS_SY7636A) += sy7636a-hwmon.o
+1 -6
View File
@@ -230,8 +230,6 @@ static void ad7418_init_client(struct i2c_client *client)
}
}
static const struct i2c_device_id ad7418_id[];
static int ad7418_probe(struct i2c_client *client)
{
struct device *dev = &client->dev;
@@ -252,10 +250,7 @@ static int ad7418_probe(struct i2c_client *client)
mutex_init(&data->lock);
data->client = client;
if (dev->of_node)
data->type = (uintptr_t)of_device_get_match_data(dev);
else
data->type = i2c_match_id(ad7418_id, client)->driver_data;
data->type = (uintptr_t)i2c_get_match_data(client);
switch (data->type) {
case ad7416:
+2 -2
View File
@@ -175,7 +175,7 @@ static ssize_t adc128_in_store(struct device *dev,
mutex_lock(&data->update_lock);
/* 10 mV LSB on limit registers */
regval = clamp_val(DIV_ROUND_CLOSEST(val, 10), 0, 255);
regval = DIV_ROUND_CLOSEST(clamp_val(val, 0, 2550), 10);
data->in[index][nr] = regval << 4;
reg = index == 1 ? ADC128_REG_IN_MIN(nr) : ADC128_REG_IN_MAX(nr);
i2c_smbus_write_byte_data(data->client, reg, regval);
@@ -213,7 +213,7 @@ static ssize_t adc128_temp_store(struct device *dev,
return err;
mutex_lock(&data->update_lock);
regval = clamp_val(DIV_ROUND_CLOSEST(val, 1000), -128, 127);
regval = DIV_ROUND_CLOSEST(clamp_val(val, -128000, 127000), 1000);
data->temp[index] = regval << 1;
i2c_smbus_write_byte_data(data->client,
index == 1 ? ADC128_REG_TEMP_MAX
-505
View File
@@ -1,505 +0,0 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* adm1021.c - Part of lm_sensors, Linux kernel modules for hardware
* monitoring
* Copyright (c) 1998, 1999 Frodo Looijaard <frodol@dds.nl> and
* Philip Edelbrock <phil@netroedge.com>
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
#include <linux/hwmon.h>
#include <linux/hwmon-sysfs.h>
#include <linux/err.h>
#include <linux/mutex.h>
/* Addresses to scan */
static const unsigned short normal_i2c[] = {
0x18, 0x19, 0x1a, 0x29, 0x2a, 0x2b, 0x4c, 0x4d, 0x4e, I2C_CLIENT_END };
enum chips {
adm1021, adm1023, max1617, max1617a, thmc10, lm84, gl523sm, mc1066 };
/* adm1021 constants specified below */
/* The adm1021 registers */
/* Read-only */
/* For nr in 0-1 */
#define ADM1021_REG_TEMP(nr) (nr)
#define ADM1021_REG_STATUS 0x02
/* 0x41 = AD, 0x49 = TI, 0x4D = Maxim, 0x23 = Genesys , 0x54 = Onsemi */
#define ADM1021_REG_MAN_ID 0xFE
/* ADM1021 = 0x0X, ADM1023 = 0x3X */
#define ADM1021_REG_DEV_ID 0xFF
/* These use different addresses for reading/writing */
#define ADM1021_REG_CONFIG_R 0x03
#define ADM1021_REG_CONFIG_W 0x09
#define ADM1021_REG_CONV_RATE_R 0x04
#define ADM1021_REG_CONV_RATE_W 0x0A
/* These are for the ADM1023's additional precision on the remote temp sensor */
#define ADM1023_REG_REM_TEMP_PREC 0x10
#define ADM1023_REG_REM_OFFSET 0x11
#define ADM1023_REG_REM_OFFSET_PREC 0x12
#define ADM1023_REG_REM_TOS_PREC 0x13
#define ADM1023_REG_REM_THYST_PREC 0x14
/* limits */
/* For nr in 0-1 */
#define ADM1021_REG_TOS_R(nr) (0x05 + 2 * (nr))
#define ADM1021_REG_TOS_W(nr) (0x0B + 2 * (nr))
#define ADM1021_REG_THYST_R(nr) (0x06 + 2 * (nr))
#define ADM1021_REG_THYST_W(nr) (0x0C + 2 * (nr))
/* write-only */
#define ADM1021_REG_ONESHOT 0x0F
/* Initial values */
/*
* Note: Even though I left the low and high limits named os and hyst,
* they don't quite work like a thermostat the way the LM75 does. I.e.,
* a lower temp than THYST actually triggers an alarm instead of
* clearing it. Weird, ey? --Phil
*/
/* Each client has this additional data */
struct adm1021_data {
struct i2c_client *client;
enum chips type;
const struct attribute_group *groups[3];
struct mutex update_lock;
bool valid; /* true if following fields are valid */
char low_power; /* !=0 if device in low power mode */
unsigned long last_updated; /* In jiffies */
int temp_max[2]; /* Register values */
int temp_min[2];
int temp[2];
u8 alarms;
/* Special values for ADM1023 only */
u8 remote_temp_offset;
u8 remote_temp_offset_prec;
};
/* (amalysh) read only mode, otherwise any limit's writing confuse BIOS */
static bool read_only;
static struct adm1021_data *adm1021_update_device(struct device *dev)
{
struct adm1021_data *data = dev_get_drvdata(dev);
struct i2c_client *client = data->client;
mutex_lock(&data->update_lock);
if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
|| !data->valid) {
int i;
dev_dbg(dev, "Starting adm1021 update\n");
for (i = 0; i < 2; i++) {
data->temp[i] = 1000 *
(s8) i2c_smbus_read_byte_data(
client, ADM1021_REG_TEMP(i));
data->temp_max[i] = 1000 *
(s8) i2c_smbus_read_byte_data(
client, ADM1021_REG_TOS_R(i));
if (data->type != lm84) {
data->temp_min[i] = 1000 *
(s8) i2c_smbus_read_byte_data(client,
ADM1021_REG_THYST_R(i));
}
}
data->alarms = i2c_smbus_read_byte_data(client,
ADM1021_REG_STATUS) & 0x7c;
if (data->type == adm1023) {
/*
* The ADM1023 provides 3 extra bits of precision for
* the remote sensor in extra registers.
*/
data->temp[1] += 125 * (i2c_smbus_read_byte_data(
client, ADM1023_REG_REM_TEMP_PREC) >> 5);
data->temp_max[1] += 125 * (i2c_smbus_read_byte_data(
client, ADM1023_REG_REM_TOS_PREC) >> 5);
data->temp_min[1] += 125 * (i2c_smbus_read_byte_data(
client, ADM1023_REG_REM_THYST_PREC) >> 5);
data->remote_temp_offset =
i2c_smbus_read_byte_data(client,
ADM1023_REG_REM_OFFSET);
data->remote_temp_offset_prec =
i2c_smbus_read_byte_data(client,
ADM1023_REG_REM_OFFSET_PREC);
}
data->last_updated = jiffies;
data->valid = true;
}
mutex_unlock(&data->update_lock);
return data;
}
static ssize_t temp_show(struct device *dev, struct device_attribute *devattr,
char *buf)
{
int index = to_sensor_dev_attr(devattr)->index;
struct adm1021_data *data = adm1021_update_device(dev);
return sprintf(buf, "%d\n", data->temp[index]);
}
static ssize_t temp_max_show(struct device *dev,
struct device_attribute *devattr, char *buf)
{
int index = to_sensor_dev_attr(devattr)->index;
struct adm1021_data *data = adm1021_update_device(dev);
return sprintf(buf, "%d\n", data->temp_max[index]);
}
static ssize_t temp_min_show(struct device *dev,
struct device_attribute *devattr, char *buf)
{
int index = to_sensor_dev_attr(devattr)->index;
struct adm1021_data *data = adm1021_update_device(dev);
return sprintf(buf, "%d\n", data->temp_min[index]);
}
static ssize_t alarm_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
int index = to_sensor_dev_attr(attr)->index;
struct adm1021_data *data = adm1021_update_device(dev);
return sprintf(buf, "%u\n", (data->alarms >> index) & 1);
}
static ssize_t alarms_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct adm1021_data *data = adm1021_update_device(dev);
return sprintf(buf, "%u\n", data->alarms);
}
static ssize_t temp_max_store(struct device *dev,
struct device_attribute *devattr,
const char *buf, size_t count)
{
int index = to_sensor_dev_attr(devattr)->index;
struct adm1021_data *data = dev_get_drvdata(dev);
struct i2c_client *client = data->client;
long temp;
int reg_val, err;
err = kstrtol(buf, 10, &temp);
if (err)
return err;
temp /= 1000;
mutex_lock(&data->update_lock);
reg_val = clamp_val(temp, -128, 127);
data->temp_max[index] = reg_val * 1000;
if (!read_only)
i2c_smbus_write_byte_data(client, ADM1021_REG_TOS_W(index),
reg_val);
mutex_unlock(&data->update_lock);
return count;
}
static ssize_t temp_min_store(struct device *dev,
struct device_attribute *devattr,
const char *buf, size_t count)
{
int index = to_sensor_dev_attr(devattr)->index;
struct adm1021_data *data = dev_get_drvdata(dev);
struct i2c_client *client = data->client;
long temp;
int reg_val, err;
err = kstrtol(buf, 10, &temp);
if (err)
return err;
temp /= 1000;
mutex_lock(&data->update_lock);
reg_val = clamp_val(temp, -128, 127);
data->temp_min[index] = reg_val * 1000;
if (!read_only)
i2c_smbus_write_byte_data(client, ADM1021_REG_THYST_W(index),
reg_val);
mutex_unlock(&data->update_lock);
return count;
}
static ssize_t low_power_show(struct device *dev,
struct device_attribute *devattr, char *buf)
{
struct adm1021_data *data = adm1021_update_device(dev);
return sprintf(buf, "%d\n", data->low_power);
}
static ssize_t low_power_store(struct device *dev,
struct device_attribute *devattr,
const char *buf, size_t count)
{
struct adm1021_data *data = dev_get_drvdata(dev);
struct i2c_client *client = data->client;
char low_power;
unsigned long val;
int err;
err = kstrtoul(buf, 10, &val);
if (err)
return err;
low_power = val != 0;
mutex_lock(&data->update_lock);
if (low_power != data->low_power) {
int config = i2c_smbus_read_byte_data(
client, ADM1021_REG_CONFIG_R);
data->low_power = low_power;
i2c_smbus_write_byte_data(client, ADM1021_REG_CONFIG_W,
(config & 0xBF) | (low_power << 6));
}
mutex_unlock(&data->update_lock);
return count;
}
static SENSOR_DEVICE_ATTR_RO(temp1_input, temp, 0);
static SENSOR_DEVICE_ATTR_RW(temp1_max, temp_max, 0);
static SENSOR_DEVICE_ATTR_RW(temp1_min, temp_min, 0);
static SENSOR_DEVICE_ATTR_RO(temp2_input, temp, 1);
static SENSOR_DEVICE_ATTR_RW(temp2_max, temp_max, 1);
static SENSOR_DEVICE_ATTR_RW(temp2_min, temp_min, 1);
static SENSOR_DEVICE_ATTR_RO(temp1_max_alarm, alarm, 6);
static SENSOR_DEVICE_ATTR_RO(temp1_min_alarm, alarm, 5);
static SENSOR_DEVICE_ATTR_RO(temp2_max_alarm, alarm, 4);
static SENSOR_DEVICE_ATTR_RO(temp2_min_alarm, alarm, 3);
static SENSOR_DEVICE_ATTR_RO(temp2_fault, alarm, 2);
static DEVICE_ATTR_RO(alarms);
static DEVICE_ATTR_RW(low_power);
static struct attribute *adm1021_attributes[] = {
&sensor_dev_attr_temp1_max.dev_attr.attr,
&sensor_dev_attr_temp1_input.dev_attr.attr,
&sensor_dev_attr_temp2_max.dev_attr.attr,
&sensor_dev_attr_temp2_input.dev_attr.attr,
&sensor_dev_attr_temp1_max_alarm.dev_attr.attr,
&sensor_dev_attr_temp2_max_alarm.dev_attr.attr,
&sensor_dev_attr_temp2_fault.dev_attr.attr,
&dev_attr_alarms.attr,
&dev_attr_low_power.attr,
NULL
};
static const struct attribute_group adm1021_group = {
.attrs = adm1021_attributes,
};
static struct attribute *adm1021_min_attributes[] = {
&sensor_dev_attr_temp1_min.dev_attr.attr,
&sensor_dev_attr_temp2_min.dev_attr.attr,
&sensor_dev_attr_temp1_min_alarm.dev_attr.attr,
&sensor_dev_attr_temp2_min_alarm.dev_attr.attr,
NULL
};
static const struct attribute_group adm1021_min_group = {
.attrs = adm1021_min_attributes,
};
/* Return 0 if detection is successful, -ENODEV otherwise */
static int adm1021_detect(struct i2c_client *client,
struct i2c_board_info *info)
{
struct i2c_adapter *adapter = client->adapter;
const char *type_name;
int reg, conv_rate, status, config, man_id, dev_id;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
pr_debug("detect failed, smbus byte data not supported!\n");
return -ENODEV;
}
status = i2c_smbus_read_byte_data(client, ADM1021_REG_STATUS);
conv_rate = i2c_smbus_read_byte_data(client,
ADM1021_REG_CONV_RATE_R);
config = i2c_smbus_read_byte_data(client, ADM1021_REG_CONFIG_R);
/* Check unused bits */
if ((status & 0x03) || (config & 0x3F) || (conv_rate & 0xF8)) {
pr_debug("detect failed, chip not detected!\n");
return -ENODEV;
}
/* Determine the chip type. */
man_id = i2c_smbus_read_byte_data(client, ADM1021_REG_MAN_ID);
dev_id = i2c_smbus_read_byte_data(client, ADM1021_REG_DEV_ID);
if (man_id < 0 || dev_id < 0)
return -ENODEV;
if (man_id == 0x4d && dev_id == 0x01) {
/*
* dev_id 0x01 matches MAX6680, MAX6695, MAX6696, and possibly
* others. Read register which is unsupported on MAX1617 but
* exists on all those chips and compare with the dev_id
* register. If it matches, it may be a MAX1617A.
*/
reg = i2c_smbus_read_byte_data(client,
ADM1023_REG_REM_TEMP_PREC);
if (reg != dev_id)
return -ENODEV;
type_name = "max1617a";
} else if (man_id == 0x41) {
if ((dev_id & 0xF0) == 0x30)
type_name = "adm1023";
else if ((dev_id & 0xF0) == 0x00)
type_name = "adm1021";
else
return -ENODEV;
} else if (man_id == 0x49)
type_name = "thmc10";
else if (man_id == 0x23)
type_name = "gl523sm";
else if (man_id == 0x54)
type_name = "mc1066";
else {
int lte, rte, lhi, rhi, llo, rlo;
/* extra checks for LM84 and MAX1617 to avoid misdetections */
llo = i2c_smbus_read_byte_data(client, ADM1021_REG_THYST_R(0));
rlo = i2c_smbus_read_byte_data(client, ADM1021_REG_THYST_R(1));
/* fail if any of the additional register reads failed */
if (llo < 0 || rlo < 0)
return -ENODEV;
lte = i2c_smbus_read_byte_data(client, ADM1021_REG_TEMP(0));
rte = i2c_smbus_read_byte_data(client, ADM1021_REG_TEMP(1));
lhi = i2c_smbus_read_byte_data(client, ADM1021_REG_TOS_R(0));
rhi = i2c_smbus_read_byte_data(client, ADM1021_REG_TOS_R(1));
/*
* Fail for negative temperatures and negative high limits.
* This check also catches read errors on the tested registers.
*/
if ((s8)lte < 0 || (s8)rte < 0 || (s8)lhi < 0 || (s8)rhi < 0)
return -ENODEV;
/* fail if all registers hold the same value */
if (lte == rte && lte == lhi && lte == rhi && lte == llo
&& lte == rlo)
return -ENODEV;
/*
* LM84 Mfr ID is in a different place,
* and it has more unused bits. Registers at 0xfe and 0xff
* are undefined and return the most recently read value,
* here the value of the configuration register.
*/
if (conv_rate == 0x00
&& man_id == config && dev_id == config
&& (config & 0x7F) == 0x00
&& (status & 0xAB) == 0x00) {
type_name = "lm84";
} else {
if ((config & 0x3f) || (status & 0x03))
return -ENODEV;
/* fail if low limits are larger than high limits */
if ((s8)llo > lhi || (s8)rlo > rhi)
return -ENODEV;
type_name = "max1617";
}
}
pr_debug("Detected chip %s at adapter %d, address 0x%02x.\n",
type_name, i2c_adapter_id(adapter), client->addr);
strscpy(info->type, type_name, I2C_NAME_SIZE);
return 0;
}
static void adm1021_init_client(struct i2c_client *client)
{
/* Enable ADC and disable suspend mode */
i2c_smbus_write_byte_data(client, ADM1021_REG_CONFIG_W,
i2c_smbus_read_byte_data(client, ADM1021_REG_CONFIG_R) & 0xBF);
/* Set Conversion rate to 1/sec (this can be tinkered with) */
i2c_smbus_write_byte_data(client, ADM1021_REG_CONV_RATE_W, 0x04);
}
static const struct i2c_device_id adm1021_id[];
static int adm1021_probe(struct i2c_client *client)
{
struct device *dev = &client->dev;
struct adm1021_data *data;
struct device *hwmon_dev;
data = devm_kzalloc(dev, sizeof(struct adm1021_data), GFP_KERNEL);
if (!data)
return -ENOMEM;
data->client = client;
data->type = i2c_match_id(adm1021_id, client)->driver_data;
mutex_init(&data->update_lock);
/* Initialize the ADM1021 chip */
if (data->type != lm84 && !read_only)
adm1021_init_client(client);
data->groups[0] = &adm1021_group;
if (data->type != lm84)
data->groups[1] = &adm1021_min_group;
hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
data, data->groups);
return PTR_ERR_OR_ZERO(hwmon_dev);
}
static const struct i2c_device_id adm1021_id[] = {
{ "adm1021", adm1021 },
{ "adm1023", adm1023 },
{ "max1617", max1617 },
{ "max1617a", max1617a },
{ "thmc10", thmc10 },
{ "lm84", lm84 },
{ "gl523sm", gl523sm },
{ "mc1066", mc1066 },
{ }
};
MODULE_DEVICE_TABLE(i2c, adm1021_id);
static struct i2c_driver adm1021_driver = {
.class = I2C_CLASS_HWMON,
.driver = {
.name = "adm1021",
},
.probe = adm1021_probe,
.id_table = adm1021_id,
.detect = adm1021_detect,
.address_list = normal_i2c,
};
module_i2c_driver(adm1021_driver);
MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl> and "
"Philip Edelbrock <phil@netroedge.com>");
MODULE_DESCRIPTION("adm1021 driver");
MODULE_LICENSE("GPL");
module_param(read_only, bool, 0);
MODULE_PARM_DESC(read_only, "Don't set any values, read only mode");
+1 -3
View File
@@ -1021,8 +1021,6 @@ static void adm1031_init_client(struct i2c_client *client)
data->update_interval = update_intervals[i];
}
static const struct i2c_device_id adm1031_id[];
static int adm1031_probe(struct i2c_client *client)
{
struct device *dev = &client->dev;
@@ -1035,7 +1033,7 @@ static int adm1031_probe(struct i2c_client *client)
i2c_set_clientdata(client, data);
data->client = client;
data->chip_type = i2c_match_id(adm1031_id, client)->driver_data;
data->chip_type = (uintptr_t)i2c_get_match_data(client);
mutex_init(&data->update_lock);
if (data->chip_type == adm1030)

Some files were not shown because too many files have changed in this diff Show More