mirror of
https://github.com/torvalds/linux.git
synced 2024-11-25 21:51:40 +00:00
hwmon changes for v5.10-rc1
New driver and chip support: - Moortec MR75203 PVT controller - MPS Multi-phase mp2975 controller - ADM1266 - Zen3 CPUs - Intel MAX 10 BMC Enhancements: - Support for rated attributes in hwmon core - MAX20730 - Device monitoring via debugfs - VOUT readin adjustment vie devicetree bindings - LM75 - Devicetree support - Regulator support - Improved accumulationm logic in amd_energy driver - Added fan sensor to gsc-hwmon driver - Support for simplified I2C probing Various other minor fixes and improvements. -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEiHPvMQj9QTOCiqgVyx8mb86fmYEFAl+DpLQACgkQyx8mb86f mYF+BQ/+NxQsQkSInPakiTq9u1rK9icxjJghn7QmVbFTym3Bzf14bvi88OUu49Cj 10VxbwNQPGDzqWPW3cLOaATclTzAfV3Px35QM/ZiURx4WuEje8XLT/kqh9DtB4il OhF4q3oXiS5sk4aL6nfNAxsHAiYXpeKj0E5RV1c9chR6tUY9muMcE/DAgUOaIrrX G6b9o5wXX5nqwcfaoJC0T0jd6mJ3ZCBWqzoIzFoMtAzejN5XOZiQH3sSmW4ZTuVz GEscC7nqzabtT9R3d5NONyehi9zSJC2+1HByzmQB1/vHoV/1aUV0hq7dyEodGXEl W5rxIrP1KMe/vKOTg252mbQ+0aXYh0KRy5zywr8rY6G568P1bemZ7K6rH5GHm/Z9 uGXkvhSo2TL0npAhaYvfD+/SFOgzwL5ue9bLByCzUaFClM5o4xmbRf0tKkr/5mRr LI1GXVMw4Ty++LpaJ6c4Qv+7XizfBIRZ/mJ4QWLpVE+R/Oj0shMrEDQgtLFyukbE UILkSBtADlY27RNw8K/YEr4/Q33TCLqZWMtqsKhHhOOLMTqtFyzRDx6dTainVUVA n4KSWDag9jtUy7WbwVuhaTd0ByOz3DVxJELb+ALjBelnwY56H7QUuXZm6uAQRrnE C7JZ2Ya6KUOwj1xtFan/0pemkHoqv58R4PjpQq/skajCquKk0Ow= =kwzT -----END PGP SIGNATURE----- Merge tag 'hwmon-for-v5.10' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging Pull hwmon updates from Guenter Roeck: "New driver and chip support: - Moortec MR75203 PVT controller - MPS Multi-phase mp2975 controller - ADM1266 - Zen3 CPUs - Intel MAX 10 BMC Enhancements: - Support for rated attributes in hwmon core - MAX20730: - Device monitoring via debugfs - VOUT readin adjustment vie devicetree bindings - LM75: - Devicetree support - Regulator support - Improved accumulationm logic in amd_energy driver - Added fan sensor to gsc-hwmon driver - Support for simplified I2C probing Various other minor fixes and improvements" * tag 'hwmon-for-v5.10' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging: (64 commits) hwmon: (pmbus/max20730) adjust the vout reading given voltage divider dt-bindings: hwmon: max20730: adding device tree doc for max20730 hwmon: Add hardware monitoring driver for Moortec MR75203 PVT controller hwmon: Add DT bindings schema for PVT controller dt-bindings: hwmon: Add the +vs supply to the lm75 bindings dt-bindings: hwmon: Convert lm75 bindings to yaml docs: hwmon: (ltc2945) update datasheet link hwmon: (mlxreg-fan) Fix double "Mellanox" hwmon: (pmbus/max20730) add device monitoring via debugfs hwmon: (pmbus/max34440) Fix OC fault limits hwmon: (bt1-pvt) Wait for the completion with timeout hwmon: (bt1-pvt) Cache current update timeout hwmon: (bt1-pvt) Test sensor power supply on probe hwmon: (lm75) Add regulator support hwmon: Add hwmon driver for Intel MAX 10 BMC dt-bindings: Add MP2975 voltage regulator device hwmon: (pmbus) Add support for MPS Multi-phase mp2975 controller hwmon: (tmp513) fix spelling typo in comments hwmon: (amd_energy) Update driver documentation hwmon: (amd_energy) Improve the accumulation logic ...
This commit is contained in:
commit
c4439713e8
51
Documentation/devicetree/bindings/hwmon/adi,adm1266.yaml
Normal file
51
Documentation/devicetree/bindings/hwmon/adi,adm1266.yaml
Normal file
@ -0,0 +1,51 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/hwmon/adi,adm1266.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Analog Devices ADM1266 Cascadable Super Sequencer with Margin
|
||||
Control and Fault Recording
|
||||
|
||||
maintainers:
|
||||
- Alexandru Tachici <alexandru.tachici@analog.com>
|
||||
|
||||
description: |
|
||||
Analog Devices ADM1266 Cascadable Super Sequencer with Margin
|
||||
Control and Fault Recording.
|
||||
https://www.analog.com/media/en/technical-documentation/data-sheets/ADM1266.pdf
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- adi,adm1266
|
||||
|
||||
reg:
|
||||
description: |
|
||||
I2C address of slave device.
|
||||
items:
|
||||
minimum: 0x40
|
||||
maximum: 0x4F
|
||||
|
||||
avcc-supply:
|
||||
description: |
|
||||
Phandle to the Avcc power supply.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
i2c0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
adm1266@40 {
|
||||
compatible = "adi,adm1266";
|
||||
reg = <0x40>;
|
||||
};
|
||||
};
|
||||
...
|
@ -1,39 +0,0 @@
|
||||
*LM75 hwmon sensor.
|
||||
|
||||
Required properties:
|
||||
- compatible: manufacturer and chip name, one of
|
||||
"adi,adt75",
|
||||
"dallas,ds1775",
|
||||
"dallas,ds75",
|
||||
"dallas,ds7505",
|
||||
"gmt,g751",
|
||||
"national,lm75",
|
||||
"national,lm75a",
|
||||
"national,lm75b",
|
||||
"maxim,max6625",
|
||||
"maxim,max6626",
|
||||
"maxim,max31725",
|
||||
"maxim,max31726",
|
||||
"maxim,mcp980x",
|
||||
"nxp,pct2075",
|
||||
"st,stds75",
|
||||
"st,stlm75",
|
||||
"microchip,tcn75",
|
||||
"ti,tmp100",
|
||||
"ti,tmp101",
|
||||
"ti,tmp105",
|
||||
"ti,tmp112",
|
||||
"ti,tmp175",
|
||||
"ti,tmp275",
|
||||
"ti,tmp75",
|
||||
"ti,tmp75b",
|
||||
"ti,tmp75c",
|
||||
|
||||
- reg: I2C bus address of the device
|
||||
|
||||
Example:
|
||||
|
||||
sensor@48 {
|
||||
compatible = "st,stlm75";
|
||||
reg = <0x48>;
|
||||
};
|
66
Documentation/devicetree/bindings/hwmon/lm75.yaml
Normal file
66
Documentation/devicetree/bindings/hwmon/lm75.yaml
Normal file
@ -0,0 +1,66 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only or BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/hwmon/lm75.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: LM75 hwmon sensor
|
||||
|
||||
maintainers:
|
||||
- Jean Delvare <jdelvare@suse.com>
|
||||
- Guenter Roeck <linux@roeck-us.net>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- adi,adt75
|
||||
- dallas,ds1775
|
||||
- dallas,ds75
|
||||
- dallas,ds7505
|
||||
- gmt,g751
|
||||
- national,lm75
|
||||
- national,lm75a
|
||||
- national,lm75b
|
||||
- maxim,max6625
|
||||
- maxim,max6626
|
||||
- maxim,max31725
|
||||
- maxim,max31726
|
||||
- maxim,mcp980x
|
||||
- nxp,pct2075
|
||||
- st,stds75
|
||||
- st,stlm75
|
||||
- microchip,tcn75
|
||||
- ti,tmp100
|
||||
- ti,tmp101
|
||||
- ti,tmp105
|
||||
- ti,tmp112
|
||||
- ti,tmp175
|
||||
- ti,tmp275
|
||||
- ti,tmp75
|
||||
- ti,tmp75b
|
||||
- ti,tmp75c
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
vs-supply:
|
||||
description: phandle to the regulator that provides the +VS supply
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
sensor@48 {
|
||||
compatible = "st,stlm75";
|
||||
reg = <0x48>;
|
||||
vs-supply = <&vs>;
|
||||
};
|
||||
};
|
65
Documentation/devicetree/bindings/hwmon/maxim,max20730.yaml
Normal file
65
Documentation/devicetree/bindings/hwmon/maxim,max20730.yaml
Normal file
@ -0,0 +1,65 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
|
||||
$id: http://devicetree.org/schemas/hwmon/maxim,max20730.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Maxim max20730
|
||||
|
||||
maintainers:
|
||||
- Jean Delvare <jdelvare@suse.com>
|
||||
- Guenter Roeck <linux@roeck-us.net>
|
||||
|
||||
description: |
|
||||
The MAX20730 is a fully integrated, highly efficient switching regulator
|
||||
with PMBus for applications operating from 4.5V to 16V and requiring
|
||||
up to 25A (max) load. This single-chip regulator provides extremely
|
||||
compact, high efficiency power-delivery solutions with high-precision
|
||||
output voltages and excellent transient response.
|
||||
|
||||
Datasheets:
|
||||
https://datasheets.maximintegrated.com/en/ds/MAX20730.pdf
|
||||
https://datasheets.maximintegrated.com/en/ds/MAX20734.pdf
|
||||
https://datasheets.maximintegrated.com/en/ds/MAX20743.pdf
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- maxim,max20730
|
||||
- maxim,max20734
|
||||
- maxim,max20743
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
vout-voltage-divider:
|
||||
description: |
|
||||
If voltage divider present at vout, the voltage at voltage sensor pin
|
||||
will be scaled. The properties will convert the raw reading to a more
|
||||
meaningful number if voltage divider present. It has two numbers,
|
||||
the first number is the output resistor, the second number is the total
|
||||
resistance. Therefore, the adjusted vout is equal to
|
||||
Vout = Vout * output_resistance / total resistance.
|
||||
$ref: /schemas/types.yaml#/definitions/uint32-array
|
||||
minItems: 2
|
||||
maxItems: 2
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
max20730@10 {
|
||||
compatible = "maxim,max20730";
|
||||
reg = <0x10>;
|
||||
vout-voltage-divider = <1000 2000>; // vout would be scaled to 0.5
|
||||
};
|
||||
};
|
71
Documentation/devicetree/bindings/hwmon/moortec,mr75203.yaml
Normal file
71
Documentation/devicetree/bindings/hwmon/moortec,mr75203.yaml
Normal file
@ -0,0 +1,71 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/hwmon/moortec,mr75203.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Moortec Semiconductor MR75203 PVT Controller bindings
|
||||
|
||||
maintainers:
|
||||
- Rahul Tanwar <rtanwar@maxlinear.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: moortec,mr75203
|
||||
|
||||
reg:
|
||||
items:
|
||||
- description: PVT common registers
|
||||
- description: PVT temprature sensor registers
|
||||
- description: PVT process detector registers
|
||||
- description: PVT voltage monitor registers
|
||||
|
||||
reg-names:
|
||||
items:
|
||||
- const: common
|
||||
- const: ts
|
||||
- const: pd
|
||||
- const: vm
|
||||
|
||||
intel,vm-map:
|
||||
description:
|
||||
PVT controller has 5 VM (voltage monitor) sensors.
|
||||
vm-map defines CPU core to VM instance mapping. A
|
||||
value of 0xff means that VM sensor is unused.
|
||||
$ref: /schemas/types.yaml#definitions/uint8-array
|
||||
maxItems: 5
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
resets:
|
||||
maxItems: 1
|
||||
|
||||
"#thermal-sensor-cells":
|
||||
const: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- reg-names
|
||||
- intel,vm-map
|
||||
- clocks
|
||||
- resets
|
||||
- "#thermal-sensor-cells"
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
pvt: pvt@e0680000 {
|
||||
compatible = "moortec,mr75203";
|
||||
reg = <0xe0680000 0x80>,
|
||||
<0xe0680080 0x180>,
|
||||
<0xe0680200 0x200>,
|
||||
<0xe0680400 0xc00>;
|
||||
reg-names = "common", "ts", "pd", "vm";
|
||||
intel,vm-map = [03 01 04 ff ff];
|
||||
clocks = <&osc0>;
|
||||
resets = <&rcu0 0x40 7>;
|
||||
#thermal-sensor-cells = <1>;
|
||||
};
|
61
Documentation/devicetree/bindings/hwmon/sensirion,shtc1.yaml
Normal file
61
Documentation/devicetree/bindings/hwmon/sensirion,shtc1.yaml
Normal file
@ -0,0 +1,61 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/hwmon/sensirion,shtc1.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Sensirion SHTC1 Humidity and Temperature Sensor IC
|
||||
|
||||
maintainers:
|
||||
- Christopher Ruehl chris.ruehl@gtsys.com.hk
|
||||
|
||||
description: |
|
||||
The SHTC1, SHTW1 and SHTC3 are digital humidity and temperature sensor
|
||||
designed especially for battery-driven high-volume consumer electronics
|
||||
applications.
|
||||
For further information refere to Documentation/hwmon/shtc1.rst
|
||||
|
||||
This binding document describes the binding for the hardware monitor
|
||||
portion of the driver.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- sensirion,shtc1
|
||||
- sensirion,shtw1
|
||||
- sensirion,shtc3
|
||||
|
||||
reg:
|
||||
const: 0x70
|
||||
|
||||
sensirion,blocking-io:
|
||||
$ref: /schemas/types.yaml#definitions/flag
|
||||
description:
|
||||
If set, the driver hold the i2c bus until measurement is finished.
|
||||
|
||||
sensirion,low-precision:
|
||||
$ref: /schemas/types.yaml#definitions/flag
|
||||
description:
|
||||
If set, the sensor aquire data with low precision (not recommended).
|
||||
The driver aquire data with high precision by default.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
clock-frequency = <400000>;
|
||||
|
||||
shtc3@70 {
|
||||
compatible = "sensirion,shtc3";
|
||||
reg = <0x70>;
|
||||
sensirion,blocking-io;
|
||||
};
|
||||
};
|
||||
...
|
@ -80,6 +80,8 @@ properties:
|
||||
- fsl,mpl3115
|
||||
# MPR121: Proximity Capacitive Touch Sensor Controller
|
||||
- fsl,mpr121
|
||||
# Monolithic Power Systems Inc. multi-phase controller mp2975
|
||||
- mps,mp2975
|
||||
# G751: Digital Temperature Sensor and Thermal Watchdog with Two-Wire Interface
|
||||
- gmt,g751
|
||||
# Infineon IR38064 Voltage Regulator
|
||||
|
37
Documentation/hwmon/adm1266.rst
Normal file
37
Documentation/hwmon/adm1266.rst
Normal file
@ -0,0 +1,37 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
Kernel driver adm1266
|
||||
=====================
|
||||
|
||||
Supported chips:
|
||||
* Analog Devices ADM1266
|
||||
Prefix: 'adm1266'
|
||||
Datasheet: https://www.analog.com/media/en/technical-documentation/data-sheets/ADM1266.pdf
|
||||
|
||||
Author: Alexandru Tachici <alexandru.tachici@analog.com>
|
||||
|
||||
|
||||
Description
|
||||
-----------
|
||||
|
||||
This driver supports hardware monitoring for Analog Devices ADM1266 sequencer.
|
||||
|
||||
ADM1266 is a sequencer that features voltage readback from 17 channels via an
|
||||
integrated 12 bit SAR ADC, accessed using a PMBus interface.
|
||||
|
||||
The driver is a client driver to the core PMBus driver. Please see
|
||||
Documentation/hwmon/pmbus for details on PMBus client drivers.
|
||||
|
||||
|
||||
Sysfs entries
|
||||
-------------
|
||||
|
||||
The following attributes are supported. Limits are read-write, history reset
|
||||
attributes are write-only, all other attributes are read-only.
|
||||
|
||||
inX_label "voutx"
|
||||
inX_input Measured voltage.
|
||||
inX_min Minimum Voltage.
|
||||
inX_max Maximum voltage.
|
||||
inX_min_alarm Voltage low alarm.
|
||||
inX_max_alarm Voltage high alarm.
|
@ -84,6 +84,11 @@ per run to a respective 64-bit counter. The kernel thread starts
|
||||
running during probe, wakes up every 100secs and stops running
|
||||
when driver is removed.
|
||||
|
||||
Frequency of the accumulator thread is set during the probe
|
||||
based on the chosen energy unit resolution. For example
|
||||
A. fine grain (1.625 micro J)
|
||||
B. course grain (0.125 milli J)
|
||||
|
||||
A socket and core energy read would return the current register
|
||||
value added to the respective energy accumulator.
|
||||
|
||||
|
@ -30,6 +30,24 @@ Transport is not supported, the driver uses SMART attributes to read
|
||||
the drive temperature.
|
||||
|
||||
|
||||
Usage Note
|
||||
----------
|
||||
|
||||
Reading the drive temperature may reset the spin down timer on some drives.
|
||||
This has been observed with WD120EFAX drives, but may be seen with other
|
||||
drives as well. The same behavior is observed if the 'hdtemp' or 'smartd'
|
||||
tools are used to access the drive.
|
||||
With the WD120EFAX drive, reading the drive temperature using the drivetemp
|
||||
driver is still possible _after_ it transitioned to standby mode, and
|
||||
reading the drive temperature in this mode will not cause the drive to
|
||||
change its mode (meaning the drive will not spin up). It is unknown if other
|
||||
drives experience similar behavior.
|
||||
|
||||
A known workaround for WD120EFAX drives is to read the drive temperature at
|
||||
intervals larger than twice the spin-down time. Otherwise affected drives
|
||||
will never spin down.
|
||||
|
||||
|
||||
Sysfs entries
|
||||
-------------
|
||||
|
||||
|
@ -30,6 +30,7 @@ Hardware Monitoring Kernel Drivers
|
||||
adm1026
|
||||
adm1031
|
||||
adm1177
|
||||
adm1266
|
||||
adm1275
|
||||
adm9240
|
||||
ads7828
|
||||
@ -73,6 +74,7 @@ Hardware Monitoring Kernel Drivers
|
||||
ina209
|
||||
ina2xx
|
||||
ina3221
|
||||
intel-m10-bmc-hwmon
|
||||
ir35221
|
||||
ir38064
|
||||
isl68137
|
||||
|
78
Documentation/hwmon/intel-m10-bmc-hwmon.rst
Normal file
78
Documentation/hwmon/intel-m10-bmc-hwmon.rst
Normal file
@ -0,0 +1,78 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
Kernel driver intel-m10-bmc-hwmon
|
||||
=================================
|
||||
|
||||
Supported chips:
|
||||
|
||||
* Intel MAX 10 BMC for Intel PAC N3000
|
||||
|
||||
Prefix: 'n3000bmc-hwmon'
|
||||
|
||||
Author: Xu Yilun <yilun.xu@intel.com>
|
||||
|
||||
|
||||
Description
|
||||
-----------
|
||||
|
||||
This driver adds the temperature, voltage, current and power reading
|
||||
support for the Intel MAX 10 Board Management Controller (BMC) chip.
|
||||
The BMC chip is integrated in some Intel Programmable Acceleration
|
||||
Cards (PAC). It connects to a set of sensor chips to monitor the
|
||||
sensor data of different components on the board. The BMC firmware is
|
||||
responsible for sensor data sampling and recording in shared
|
||||
registers. The host driver reads the sensor data from these shared
|
||||
registers and exposes them to users as hwmon interfaces.
|
||||
|
||||
The BMC chip is implemented using the Intel MAX 10 CPLD. It could be
|
||||
reprogramed to some variants in order to support different Intel
|
||||
PACs. The driver is designed to be able to distinguish between the
|
||||
variants, but now it only supports the BMC for Intel PAC N3000.
|
||||
|
||||
|
||||
Sysfs attributes
|
||||
----------------
|
||||
|
||||
The following attributes are supported:
|
||||
|
||||
- Intel MAX 10 BMC for Intel PAC N3000:
|
||||
|
||||
======================= =======================================================
|
||||
tempX_input Temperature of the component (specified by tempX_label)
|
||||
tempX_max Temperature maximum setpoint of the component
|
||||
tempX_crit Temperature critical setpoint of the component
|
||||
tempX_max_hyst Hysteresis for temperature maximum of the component
|
||||
tempX_crit_hyst Hysteresis for temperature critical of the component
|
||||
temp1_label "Board Temperature"
|
||||
temp2_label "FPGA Die Temperature"
|
||||
temp3_label "QSFP0 Temperature"
|
||||
temp4_label "QSFP1 Temperature"
|
||||
temp5_label "Retimer A Temperature"
|
||||
temp6_label "Retimer A SerDes Temperature"
|
||||
temp7_label "Retimer B Temperature"
|
||||
temp8_label "Retimer B SerDes Temperature"
|
||||
|
||||
inX_input Measured voltage of the component (specified by
|
||||
inX_label)
|
||||
in0_label "QSFP0 Supply Voltage"
|
||||
in1_label "QSFP1 Supply Voltage"
|
||||
in2_label "FPGA Core Voltage"
|
||||
in3_label "12V Backplane Voltage"
|
||||
in4_label "1.2V Voltage"
|
||||
in5_label "12V AUX Voltage"
|
||||
in6_label "1.8V Voltage"
|
||||
in7_label "3.3V Voltage"
|
||||
|
||||
currX_input Measured current of the component (specified by
|
||||
currX_label)
|
||||
curr1_label "FPGA Core Current"
|
||||
curr2_label "12V Backplane Current"
|
||||
curr3_label "12V AUX Current"
|
||||
|
||||
powerX_input Measured power of the component (specified by
|
||||
powerX_label)
|
||||
power1_label "Board Power"
|
||||
|
||||
======================= =======================================================
|
||||
|
||||
All the attributes are read-only.
|
@ -11,7 +11,7 @@ Supported chips:
|
||||
|
||||
Datasheet:
|
||||
|
||||
http://cds.linear.com/docs/en/datasheet/2945fa.pdf
|
||||
https://www.analog.com/media/en/technical-documentation/data-sheets/2945fb.pdf
|
||||
|
||||
Author: Guenter Roeck <linux@roeck-us.net>
|
||||
|
||||
|
116
Documentation/hwmon/mp2975.rst
Normal file
116
Documentation/hwmon/mp2975.rst
Normal file
@ -0,0 +1,116 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
Kernel driver mp2975
|
||||
====================
|
||||
|
||||
Supported chips:
|
||||
|
||||
* MPS MP12254
|
||||
|
||||
Prefix: 'mp2975'
|
||||
|
||||
Author:
|
||||
|
||||
Vadim Pasternak <vadimp@nvidia.com>
|
||||
|
||||
Description
|
||||
-----------
|
||||
|
||||
This driver implements support for Monolithic Power Systems, Inc. (MPS)
|
||||
vendor dual-loop, digital, multi-phase controller MP2975.
|
||||
|
||||
This device:
|
||||
- Supports up to two power rail.
|
||||
- Provides 8 pulse-width modulations (PWMs), and can be configured up
|
||||
to 8-phase operation for rail 1 and up to 4-phase operation for rail
|
||||
2.
|
||||
- Supports two pages 0 and 1 for telemetry and also pages 2 and 3 for
|
||||
configuration.
|
||||
- Can configured VOUT readout in direct or VID format and allows
|
||||
setting of different formats on rails 1 and 2. For VID the following
|
||||
protocols are available: VR13 mode with 5-mV DAC; VR13 mode with
|
||||
10-mV DAC, IMVP9 mode with 5-mV DAC.
|
||||
|
||||
Device supports:
|
||||
- SVID interface.
|
||||
- AVSBus interface.
|
||||
|
||||
Device complaint with:
|
||||
- PMBus rev 1.3 interface.
|
||||
|
||||
Device supports direct format for reading output current, output voltage,
|
||||
input and output power and temperature.
|
||||
Device supports linear format for reading input voltage and input power.
|
||||
Device supports VID and direct formats for reading output voltage.
|
||||
The below VID modes are supported: VR12, VR13, IMVP9.
|
||||
|
||||
The driver provides the next attributes for the current:
|
||||
- for current in: input, maximum alarm;
|
||||
- for current out input, maximum alarm and highest values;
|
||||
- for phase current: input and label.
|
||||
attributes.
|
||||
The driver exports the following attributes via the 'sysfs' files, where
|
||||
- 'n' is number of telemetry pages (from 1 to 2);
|
||||
- 'k' is number of configured phases (from 1 to 8);
|
||||
- indexes 1, 1*n for "iin";
|
||||
- indexes n+1, n+2 for "iout";
|
||||
- indexes 2*n+1 ... 2*n + k for phases.
|
||||
|
||||
**curr[1-{2n}]_alarm**
|
||||
|
||||
**curr[{n+1}-{n+2}]_highest**
|
||||
|
||||
**curr[1-{2n+k}]_input**
|
||||
|
||||
**curr[1-{2n+k}]_label**
|
||||
|
||||
The driver provides the next attributes for the voltage:
|
||||
- for voltage in: input, high critical threshold, high critical alarm, all only
|
||||
from page 0;
|
||||
- for voltage out: input, low and high critical thresholds, low and high
|
||||
critical alarms, from pages 0 and 1;
|
||||
The driver exports the following attributes via the 'sysfs' files, where
|
||||
- 'n' is number of telemetry pages (from 1 to 2);
|
||||
- indexes 1 for "iin";
|
||||
- indexes n+1, n+2 for "vout";
|
||||
|
||||
**in[1-{2n+1}]_crit**
|
||||
|
||||
**in[1-{2n+1}]_crit_alarm**
|
||||
|
||||
**in[1-{2n+1}]_input**
|
||||
|
||||
**in[1-{2n+1}]_label**
|
||||
|
||||
**in[2-{n+1}]_lcrit**
|
||||
|
||||
**in[2-{n+1}1_lcrit_alarm**
|
||||
|
||||
The driver provides the next attributes for the power:
|
||||
- for power in alarm and input.
|
||||
- for power out: highest and input.
|
||||
The driver exports the following attributes via the 'sysfs' files, where
|
||||
- 'n' is number of telemetry pages (from 1 to 2);
|
||||
- indexes 1 for "pin";
|
||||
- indexes n+1, n+2 for "pout";
|
||||
|
||||
**power1_alarm**
|
||||
|
||||
**power[2-{n+1}]_highest**
|
||||
|
||||
**power[1-{2n+1}]_input**
|
||||
|
||||
**power[1-{2n+1}]_label**
|
||||
|
||||
The driver provides the next attributes for the temperature (only from page 0):
|
||||
|
||||
|
||||
**temp1_crit**
|
||||
|
||||
**temp1_crit_alarm**
|
||||
|
||||
**temp1_input**
|
||||
|
||||
**temp1_max**
|
||||
|
||||
**temp1_max_alarm**
|
@ -270,8 +270,7 @@ obtain the chip status. Therefore, it must _not_ be called from that function.
|
||||
|
||||
::
|
||||
|
||||
int pmbus_do_probe(struct i2c_client *client, const struct i2c_device_id *id,
|
||||
struct pmbus_driver_info *info);
|
||||
int pmbus_do_probe(struct i2c_client *client, struct pmbus_driver_info *info);
|
||||
|
||||
Execute probe function. Similar to standard probe function for other drivers,
|
||||
with the pointer to struct pmbus_driver_info as additional argument. Calls
|
||||
|
@ -143,10 +143,9 @@ Emerson DS1200 power modules might look as follows::
|
||||
| PMBUS_HAVE_FAN12 | PMBUS_HAVE_STATUS_FAN12,
|
||||
};
|
||||
|
||||
static int ds1200_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
static int ds1200_probe(struct i2c_client *client)
|
||||
{
|
||||
return pmbus_do_probe(client, id, &ds1200_info);
|
||||
return pmbus_do_probe(client, &ds1200_info);
|
||||
}
|
||||
|
||||
static int ds1200_remove(struct i2c_client *client)
|
||||
@ -166,7 +165,7 @@ Emerson DS1200 power modules might look as follows::
|
||||
.driver = {
|
||||
.name = "ds1200",
|
||||
},
|
||||
.probe = ds1200_probe,
|
||||
.probe_new = ds1200_probe,
|
||||
.remove = ds1200_remove,
|
||||
.id_table = ds1200_id,
|
||||
};
|
||||
@ -211,6 +210,10 @@ inX_lcrit_alarm Voltage critical low alarm.
|
||||
inX_crit_alarm Voltage critical high alarm.
|
||||
From VOLTAGE_OV_FAULT status.
|
||||
inX_label "vin", "vcap", or "voutY"
|
||||
inX_rated_min Minimum rated voltage.
|
||||
From MFR_VIN_MIN or MFR_VOUT_MIN register.
|
||||
inX_rated_max Maximum rated voltage.
|
||||
From MFR_VIN_MAX or MFR_VOUT_MAX register.
|
||||
|
||||
currX_input Measured current. From READ_IIN or READ_IOUT register.
|
||||
currX_max Maximum current.
|
||||
@ -230,6 +233,8 @@ currX_crit_alarm Current critical high alarm.
|
||||
currX_label "iin", "iinY", "iinY.Z", "ioutY", or "ioutY.Z",
|
||||
where Y reflects the page number and Z reflects the
|
||||
phase.
|
||||
currX_rated_max Maximum rated current.
|
||||
From MFR_IIN_MAX or MFR_IOUT_MAX register.
|
||||
|
||||
powerX_input Measured power. From READ_PIN or READ_POUT register.
|
||||
powerX_cap Output power cap. From POUT_MAX register.
|
||||
@ -244,10 +249,12 @@ powerX_crit_alarm Output power critical high alarm.
|
||||
powerX_label "pin", "pinY", "pinY.Z", "poutY", or "poutY.Z",
|
||||
where Y reflects the page number and Z reflects the
|
||||
phase.
|
||||
powerX_rated_max Maximum rated power.
|
||||
From MFR_PIN_MAX or MFR_POUT_MAX register.
|
||||
|
||||
tempX_input Measured temperature.
|
||||
From READ_TEMPERATURE_X register.
|
||||
tempX_min Mimimum temperature. From UT_WARN_LIMIT register.
|
||||
tempX_min Minimum temperature. From UT_WARN_LIMIT register.
|
||||
tempX_max Maximum temperature. From OT_WARN_LIMIT register.
|
||||
tempX_lcrit Critical low temperature.
|
||||
From UT_FAULT_LIMIT register.
|
||||
@ -265,4 +272,9 @@ tempX_lcrit_alarm Chip temperature critical low alarm. Set by comparing
|
||||
tempX_crit_alarm Chip temperature critical high alarm. Set by comparing
|
||||
READ_TEMPERATURE_X with OT_FAULT_LIMIT if
|
||||
TEMP_OT_FAULT status is set.
|
||||
tempX_rated_min Minimum rated temperature.
|
||||
From MFR_TAMBIENT_MIN register.
|
||||
tempX_rated_max Maximum rated temperature.
|
||||
From MFR_TAMBIENT_MAX, MFR_MAX_TEMP_1, MFR_MAX_TEMP_2 or
|
||||
MFR_MAX_TEMP_3 register.
|
||||
======================= ========================================================
|
||||
|
@ -241,6 +241,20 @@ Voltages
|
||||
Affects the way the driver calculates the CPU core reference
|
||||
voltage from the vid pins.
|
||||
|
||||
`in[0-*]_rated_min`
|
||||
Minimum rated voltage.
|
||||
|
||||
Unit: millivolt
|
||||
|
||||
RO
|
||||
|
||||
`in[0-*]_rated_max`
|
||||
Maximum rated voltage.
|
||||
|
||||
Unit: millivolt
|
||||
|
||||
RO
|
||||
|
||||
Also see the Alarms section for status flags associated with voltages.
|
||||
|
||||
|
||||
@ -574,6 +588,20 @@ Temperatures
|
||||
|
||||
RW
|
||||
|
||||
`temp[1-*]_rated_min`
|
||||
Minimum rated temperature.
|
||||
|
||||
Unit: millidegree Celsius
|
||||
|
||||
RO
|
||||
|
||||
`temp[1-*]_rated_max`
|
||||
Maximum rated temperature.
|
||||
|
||||
Unit: millidegree Celsius
|
||||
|
||||
RO
|
||||
|
||||
Some chips measure temperature using external thermistors and an ADC, and
|
||||
report the temperature measurement as a voltage. Converting this voltage
|
||||
back to a temperature (or the other way around for limits) requires
|
||||
@ -664,6 +692,20 @@ Currents
|
||||
|
||||
RW
|
||||
|
||||
`curr[1-*]_rated_min`
|
||||
Minimum rated current.
|
||||
|
||||
Unit: milliampere
|
||||
|
||||
RO
|
||||
|
||||
`curr[1-*]_rated_max`
|
||||
Maximum rated current.
|
||||
|
||||
Unit: milliampere
|
||||
|
||||
RO
|
||||
|
||||
Also see the Alarms section for status flags associated with currents.
|
||||
|
||||
*****
|
||||
@ -830,6 +872,20 @@ Power
|
||||
|
||||
RW
|
||||
|
||||
`power[1-*]_rated_min`
|
||||
Minimum rated power.
|
||||
|
||||
Unit: microWatt
|
||||
|
||||
RO
|
||||
|
||||
`power[1-*]_rated_max`
|
||||
Maximum rated power.
|
||||
|
||||
Unit: microWatt
|
||||
|
||||
RO
|
||||
|
||||
Also see the Alarms section for status flags associated with power readings.
|
||||
|
||||
******
|
||||
@ -877,6 +933,20 @@ Humidity
|
||||
|
||||
RW
|
||||
|
||||
`humidity[1-*]_rated_min`
|
||||
Minimum rated humidity.
|
||||
|
||||
Unit: milli-percent (per cent mille, pcm)
|
||||
|
||||
RO
|
||||
|
||||
`humidity[1-*]_rated_max`
|
||||
Maximum rated humidity.
|
||||
|
||||
Unit: milli-percent (per cent mille, pcm)
|
||||
|
||||
RO
|
||||
|
||||
******
|
||||
Alarms
|
||||
******
|
||||
|
@ -1080,7 +1080,7 @@ config SENSORS_MCP3021
|
||||
will be called mcp3021.
|
||||
|
||||
config SENSORS_MLXREG_FAN
|
||||
tristate "Mellanox Mellanox FAN driver"
|
||||
tristate "Mellanox FAN driver"
|
||||
depends on MELLANOX_PLATFORM
|
||||
imply THERMAL
|
||||
select REGMAP
|
||||
@ -1112,6 +1112,16 @@ config SENSORS_MENF21BMC_HWMON
|
||||
This driver can also be built as a module. If so the module
|
||||
will be called menf21bmc_hwmon.
|
||||
|
||||
config SENSORS_MR75203
|
||||
tristate "Moortec Semiconductor MR75203 PVT Controller"
|
||||
select REGMAP_MMIO
|
||||
help
|
||||
If you say yes here you get support for Moortec MR75203
|
||||
PVT controller.
|
||||
|
||||
This driver can also be built as a module. If so, the module
|
||||
will be called mr75203.
|
||||
|
||||
config SENSORS_ADCXX
|
||||
tristate "National Semiconductor ADCxxxSxxx"
|
||||
depends on SPI_MASTER
|
||||
@ -2064,6 +2074,17 @@ config SENSORS_XGENE
|
||||
If you say yes here you get support for the temperature
|
||||
and power sensors for APM X-Gene SoC.
|
||||
|
||||
config SENSORS_INTEL_M10_BMC_HWMON
|
||||
tristate "Intel MAX10 BMC Hardware Monitoring"
|
||||
depends on MFD_INTEL_M10_BMC
|
||||
help
|
||||
This driver provides support for the hardware monitoring functionality
|
||||
on Intel MAX10 BMC chip.
|
||||
|
||||
This BMC Chip is used on Intel FPGA PCIe Acceleration Cards (PAC). Its
|
||||
sensors monitor various telemetry data of different components on the
|
||||
card, e.g. board temperature, FPGA core temperature/voltage/current.
|
||||
|
||||
if ACPI
|
||||
|
||||
comment "ACPI drivers"
|
||||
|
@ -90,6 +90,7 @@ obj-$(CONFIG_SENSORS_IIO_HWMON) += iio_hwmon.o
|
||||
obj-$(CONFIG_SENSORS_INA209) += ina209.o
|
||||
obj-$(CONFIG_SENSORS_INA2XX) += ina2xx.o
|
||||
obj-$(CONFIG_SENSORS_INA3221) += ina3221.o
|
||||
obj-$(CONFIG_SENSORS_INTEL_M10_BMC_HWMON) += intel-m10-bmc-hwmon.o
|
||||
obj-$(CONFIG_SENSORS_IT87) += it87.o
|
||||
obj-$(CONFIG_SENSORS_JC42) += jc42.o
|
||||
obj-$(CONFIG_SENSORS_K8TEMP) += k8temp.o
|
||||
@ -142,6 +143,7 @@ obj-$(CONFIG_SENSORS_MCP3021) += mcp3021.o
|
||||
obj-$(CONFIG_SENSORS_TC654) += tc654.o
|
||||
obj-$(CONFIG_SENSORS_MLXREG_FAN) += mlxreg-fan.o
|
||||
obj-$(CONFIG_SENSORS_MENF21BMC_HWMON) += menf21bmc_hwmon.o
|
||||
obj-$(CONFIG_SENSORS_MR75203) += mr75203.o
|
||||
obj-$(CONFIG_SENSORS_NCT6683) += nct6683.o
|
||||
obj-$(CONFIG_SENSORS_NCT6775) += nct6775.o
|
||||
obj-$(CONFIG_SENSORS_NCT7802) += nct7802.o
|
||||
|
@ -169,8 +169,7 @@ static struct attribute *ad7414_attrs[] = {
|
||||
|
||||
ATTRIBUTE_GROUPS(ad7414);
|
||||
|
||||
static int ad7414_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *dev_id)
|
||||
static int ad7414_probe(struct i2c_client *client)
|
||||
{
|
||||
struct device *dev = &client->dev;
|
||||
struct ad7414_data *data;
|
||||
@ -222,7 +221,7 @@ static struct i2c_driver ad7414_driver = {
|
||||
.name = "ad7414",
|
||||
.of_match_table = of_match_ptr(ad7414_of_match),
|
||||
},
|
||||
.probe = ad7414_probe,
|
||||
.probe_new = ad7414_probe,
|
||||
.id_table = ad7414_id,
|
||||
};
|
||||
|
||||
|
@ -230,8 +230,9 @@ static void ad7418_init_client(struct i2c_client *client)
|
||||
}
|
||||
}
|
||||
|
||||
static int ad7418_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
static const struct i2c_device_id ad7418_id[];
|
||||
|
||||
static int ad7418_probe(struct i2c_client *client)
|
||||
{
|
||||
struct device *dev = &client->dev;
|
||||
struct i2c_adapter *adapter = client->adapter;
|
||||
@ -254,7 +255,7 @@ static int ad7418_probe(struct i2c_client *client,
|
||||
if (dev->of_node)
|
||||
data->type = (enum chips)of_device_get_match_data(dev);
|
||||
else
|
||||
data->type = id->driver_data;
|
||||
data->type = i2c_match_id(ad7418_id, client)->driver_data;
|
||||
|
||||
switch (data->type) {
|
||||
case ad7416:
|
||||
@ -305,7 +306,7 @@ static struct i2c_driver ad7418_driver = {
|
||||
.name = "ad7418",
|
||||
.of_match_table = ad7418_dt_ids,
|
||||
},
|
||||
.probe = ad7418_probe,
|
||||
.probe_new = ad7418_probe,
|
||||
.id_table = ad7418_id,
|
||||
};
|
||||
|
||||
|
@ -427,8 +427,7 @@ static int adc128_init_client(struct adc128_data *data)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int adc128_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
static int adc128_probe(struct i2c_client *client)
|
||||
{
|
||||
struct device *dev = &client->dev;
|
||||
struct regulator *regulator;
|
||||
@ -524,7 +523,7 @@ static struct i2c_driver adc128_driver = {
|
||||
.name = "adc128d818",
|
||||
.of_match_table = of_match_ptr(adc128_of_match),
|
||||
},
|
||||
.probe = adc128_probe,
|
||||
.probe_new = adc128_probe,
|
||||
.remove = adc128_remove,
|
||||
.id_table = adc128_id,
|
||||
.detect = adc128_detect,
|
||||
|
@ -425,8 +425,9 @@ static void adm1021_init_client(struct i2c_client *client)
|
||||
i2c_smbus_write_byte_data(client, ADM1021_REG_CONV_RATE_W, 0x04);
|
||||
}
|
||||
|
||||
static int adm1021_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
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;
|
||||
@ -437,7 +438,7 @@ static int adm1021_probe(struct i2c_client *client,
|
||||
return -ENOMEM;
|
||||
|
||||
data->client = client;
|
||||
data->type = id->driver_data;
|
||||
data->type = i2c_match_id(adm1021_id, client)->driver_data;
|
||||
mutex_init(&data->update_lock);
|
||||
|
||||
/* Initialize the ADM1021 chip */
|
||||
@ -472,7 +473,7 @@ static struct i2c_driver adm1021_driver = {
|
||||
.driver = {
|
||||
.name = "adm1021",
|
||||
},
|
||||
.probe = adm1021_probe,
|
||||
.probe_new = adm1021_probe,
|
||||
.id_table = adm1021_id,
|
||||
.detect = adm1021_detect,
|
||||
.address_list = normal_i2c,
|
||||
|
@ -517,8 +517,7 @@ static void adm1025_init_client(struct i2c_client *client)
|
||||
(reg&0x7E)|0x01);
|
||||
}
|
||||
|
||||
static int adm1025_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
static int adm1025_probe(struct i2c_client *client)
|
||||
{
|
||||
struct device *dev = &client->dev;
|
||||
struct device *hwmon_dev;
|
||||
@ -560,7 +559,7 @@ static struct i2c_driver adm1025_driver = {
|
||||
.driver = {
|
||||
.name = "adm1025",
|
||||
},
|
||||
.probe = adm1025_probe,
|
||||
.probe_new = adm1025_probe,
|
||||
.id_table = adm1025_id,
|
||||
.detect = adm1025_detect,
|
||||
.address_list = normal_i2c,
|
||||
|
@ -1816,8 +1816,7 @@ static void adm1026_init_client(struct i2c_client *client)
|
||||
}
|
||||
}
|
||||
|
||||
static int adm1026_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
static int adm1026_probe(struct i2c_client *client)
|
||||
{
|
||||
struct device *dev = &client->dev;
|
||||
struct device *hwmon_dev;
|
||||
@ -1860,7 +1859,7 @@ static struct i2c_driver adm1026_driver = {
|
||||
.driver = {
|
||||
.name = "adm1026",
|
||||
},
|
||||
.probe = adm1026_probe,
|
||||
.probe_new = adm1026_probe,
|
||||
.id_table = adm1026_id,
|
||||
.detect = adm1026_detect,
|
||||
.address_list = normal_i2c,
|
||||
|
@ -352,8 +352,7 @@ static int adm1029_init_client(struct i2c_client *client)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int adm1029_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
static int adm1029_probe(struct i2c_client *client)
|
||||
{
|
||||
struct device *dev = &client->dev;
|
||||
struct adm1029_data *data;
|
||||
@ -390,7 +389,7 @@ static struct i2c_driver adm1029_driver = {
|
||||
.driver = {
|
||||
.name = "adm1029",
|
||||
},
|
||||
.probe = adm1029_probe,
|
||||
.probe_new = adm1029_probe,
|
||||
.id_table = adm1029_id,
|
||||
.detect = adm1029_detect,
|
||||
.address_list = normal_i2c,
|
||||
|
@ -1022,8 +1022,9 @@ static void adm1031_init_client(struct i2c_client *client)
|
||||
data->update_interval = update_intervals[i];
|
||||
}
|
||||
|
||||
static int adm1031_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
static const struct i2c_device_id adm1031_id[];
|
||||
|
||||
static int adm1031_probe(struct i2c_client *client)
|
||||
{
|
||||
struct device *dev = &client->dev;
|
||||
struct device *hwmon_dev;
|
||||
@ -1035,7 +1036,7 @@ static int adm1031_probe(struct i2c_client *client,
|
||||
|
||||
i2c_set_clientdata(client, data);
|
||||
data->client = client;
|
||||
data->chip_type = id->driver_data;
|
||||
data->chip_type = i2c_match_id(adm1031_id, client)->driver_data;
|
||||
mutex_init(&data->update_lock);
|
||||
|
||||
if (data->chip_type == adm1030)
|
||||
@ -1068,7 +1069,7 @@ static struct i2c_driver adm1031_driver = {
|
||||
.driver = {
|
||||
.name = "adm1031",
|
||||
},
|
||||
.probe = adm1031_probe,
|
||||
.probe_new = adm1031_probe,
|
||||
.id_table = adm1031_id,
|
||||
.detect = adm1031_detect,
|
||||
.address_list = normal_i2c,
|
||||
|
@ -196,8 +196,7 @@ static void adm1177_remove(void *data)
|
||||
regulator_disable(st->reg);
|
||||
}
|
||||
|
||||
static int adm1177_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
static int adm1177_probe(struct i2c_client *client)
|
||||
{
|
||||
struct device *dev = &client->dev;
|
||||
struct device *hwmon_dev;
|
||||
@ -277,7 +276,7 @@ static struct i2c_driver adm1177_driver = {
|
||||
.name = "adm1177",
|
||||
.of_match_table = adm1177_dt_ids,
|
||||
},
|
||||
.probe = adm1177_probe,
|
||||
.probe_new = adm1177_probe,
|
||||
.id_table = adm1177_id,
|
||||
};
|
||||
module_i2c_driver(adm1177_driver);
|
||||
|
@ -38,6 +38,7 @@
|
||||
#include <linux/err.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
/* Addresses to scan */
|
||||
static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, 0x2f,
|
||||
@ -123,6 +124,7 @@ static inline unsigned int AOUT_FROM_REG(u8 reg)
|
||||
/* per client data */
|
||||
struct adm9240_data {
|
||||
struct i2c_client *client;
|
||||
struct regmap *regmap;
|
||||
struct mutex update_lock;
|
||||
char valid;
|
||||
unsigned long last_updated_measure;
|
||||
@ -143,68 +145,141 @@ struct adm9240_data {
|
||||
};
|
||||
|
||||
/* write new fan div, callers must hold data->update_lock */
|
||||
static void adm9240_write_fan_div(struct i2c_client *client, int nr,
|
||||
static int adm9240_write_fan_div(struct adm9240_data *data, int nr,
|
||||
u8 fan_div)
|
||||
{
|
||||
u8 reg, old, shift = (nr + 2) * 2;
|
||||
unsigned int reg, old, shift = (nr + 2) * 2;
|
||||
int err;
|
||||
|
||||
reg = i2c_smbus_read_byte_data(client, ADM9240_REG_VID_FAN_DIV);
|
||||
err = regmap_read(data->regmap, ADM9240_REG_VID_FAN_DIV, ®);
|
||||
if (err < 0)
|
||||
return err;
|
||||
old = (reg >> shift) & 3;
|
||||
reg &= ~(3 << shift);
|
||||
reg |= (fan_div << shift);
|
||||
i2c_smbus_write_byte_data(client, ADM9240_REG_VID_FAN_DIV, reg);
|
||||
dev_dbg(&client->dev,
|
||||
err = regmap_write(data->regmap, ADM9240_REG_VID_FAN_DIV, reg);
|
||||
if (err < 0)
|
||||
return err;
|
||||
dev_dbg(&data->client->dev,
|
||||
"fan%d clock divider changed from %u to %u\n",
|
||||
nr + 1, 1 << old, 1 << fan_div);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int adm9240_update_measure(struct adm9240_data *data)
|
||||
{
|
||||
unsigned int val;
|
||||
u8 regs[2];
|
||||
int err;
|
||||
int i;
|
||||
|
||||
err = regmap_bulk_read(data->regmap, ADM9240_REG_IN(0), &data->in[0], 6);
|
||||
if (err < 0)
|
||||
return err;
|
||||
err = regmap_bulk_read(data->regmap, ADM9240_REG_INT(0), ®s, 2);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
data->alarms = regs[0] | regs[1] << 8;
|
||||
|
||||
/*
|
||||
* read temperature: assume temperature changes less than
|
||||
* 0.5'C per two measurement cycles thus ignore possible
|
||||
* but unlikely aliasing error on lsb reading. --Grant
|
||||
*/
|
||||
err = regmap_read(data->regmap, ADM9240_REG_TEMP, &val);
|
||||
if (err < 0)
|
||||
return err;
|
||||
data->temp = val << 8;
|
||||
err = regmap_read(data->regmap, ADM9240_REG_TEMP_CONF, &val);
|
||||
if (err < 0)
|
||||
return err;
|
||||
data->temp |= val;
|
||||
|
||||
err = regmap_bulk_read(data->regmap, ADM9240_REG_FAN(0),
|
||||
&data->fan[0], 2);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
for (i = 0; i < 2; i++) { /* read fans */
|
||||
/* adjust fan clock divider on overflow */
|
||||
if (data->valid && data->fan[i] == 255 &&
|
||||
data->fan_div[i] < 3) {
|
||||
|
||||
err = adm9240_write_fan_div(data, i,
|
||||
++data->fan_div[i]);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
/* adjust fan_min if active, but not to 0 */
|
||||
if (data->fan_min[i] < 255 &&
|
||||
data->fan_min[i] >= 2)
|
||||
data->fan_min[i] /= 2;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int adm9240_update_config(struct adm9240_data *data)
|
||||
{
|
||||
unsigned int val;
|
||||
int i;
|
||||
int err;
|
||||
|
||||
for (i = 0; i < 6; i++) {
|
||||
err = regmap_raw_read(data->regmap, ADM9240_REG_IN_MIN(i),
|
||||
&data->in_min[i], 1);
|
||||
if (err < 0)
|
||||
return err;
|
||||
err = regmap_raw_read(data->regmap, ADM9240_REG_IN_MAX(i),
|
||||
&data->in_max[i], 1);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
err = regmap_bulk_read(data->regmap, ADM9240_REG_FAN_MIN(0),
|
||||
&data->fan_min[0], 2);
|
||||
if (err < 0)
|
||||
return err;
|
||||
err = regmap_bulk_read(data->regmap, ADM9240_REG_TEMP_MAX(0),
|
||||
&data->temp_max[0], 2);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
/* read fan divs and 5-bit VID */
|
||||
err = regmap_read(data->regmap, ADM9240_REG_VID_FAN_DIV, &val);
|
||||
if (err < 0)
|
||||
return err;
|
||||
data->fan_div[0] = (val >> 4) & 3;
|
||||
data->fan_div[1] = (val >> 6) & 3;
|
||||
data->vid = val & 0x0f;
|
||||
err = regmap_read(data->regmap, ADM9240_REG_VID4, &val);
|
||||
if (err < 0)
|
||||
return err;
|
||||
data->vid |= (val & 1) << 4;
|
||||
/* read analog out */
|
||||
err = regmap_raw_read(data->regmap, ADM9240_REG_ANALOG_OUT,
|
||||
&data->aout, 1);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static struct adm9240_data *adm9240_update_device(struct device *dev)
|
||||
{
|
||||
struct adm9240_data *data = dev_get_drvdata(dev);
|
||||
struct i2c_client *client = data->client;
|
||||
int i;
|
||||
int err;
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
|
||||
/* minimum measurement cycle: 1.75 seconds */
|
||||
if (time_after(jiffies, data->last_updated_measure + (HZ * 7 / 4))
|
||||
|| !data->valid) {
|
||||
|
||||
for (i = 0; i < 6; i++) { /* read voltages */
|
||||
data->in[i] = i2c_smbus_read_byte_data(client,
|
||||
ADM9240_REG_IN(i));
|
||||
}
|
||||
data->alarms = i2c_smbus_read_byte_data(client,
|
||||
ADM9240_REG_INT(0)) |
|
||||
i2c_smbus_read_byte_data(client,
|
||||
ADM9240_REG_INT(1)) << 8;
|
||||
|
||||
/*
|
||||
* read temperature: assume temperature changes less than
|
||||
* 0.5'C per two measurement cycles thus ignore possible
|
||||
* but unlikely aliasing error on lsb reading. --Grant
|
||||
*/
|
||||
data->temp = (i2c_smbus_read_byte_data(client,
|
||||
ADM9240_REG_TEMP) << 8) |
|
||||
i2c_smbus_read_byte_data(client,
|
||||
ADM9240_REG_TEMP_CONF);
|
||||
|
||||
for (i = 0; i < 2; i++) { /* read fans */
|
||||
data->fan[i] = i2c_smbus_read_byte_data(client,
|
||||
ADM9240_REG_FAN(i));
|
||||
|
||||
/* adjust fan clock divider on overflow */
|
||||
if (data->valid && data->fan[i] == 255 &&
|
||||
data->fan_div[i] < 3) {
|
||||
|
||||
adm9240_write_fan_div(client, i,
|
||||
++data->fan_div[i]);
|
||||
|
||||
/* adjust fan_min if active, but not to 0 */
|
||||
if (data->fan_min[i] < 255 &&
|
||||
data->fan_min[i] >= 2)
|
||||
data->fan_min[i] /= 2;
|
||||
}
|
||||
err = adm9240_update_measure(data);
|
||||
if (err < 0) {
|
||||
data->valid = 0;
|
||||
mutex_unlock(&data->update_lock);
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
data->last_updated_measure = jiffies;
|
||||
}
|
||||
@ -212,33 +287,12 @@ static struct adm9240_data *adm9240_update_device(struct device *dev)
|
||||
/* minimum config reading cycle: 300 seconds */
|
||||
if (time_after(jiffies, data->last_updated_config + (HZ * 300))
|
||||
|| !data->valid) {
|
||||
|
||||
for (i = 0; i < 6; i++) {
|
||||
data->in_min[i] = i2c_smbus_read_byte_data(client,
|
||||
ADM9240_REG_IN_MIN(i));
|
||||
data->in_max[i] = i2c_smbus_read_byte_data(client,
|
||||
ADM9240_REG_IN_MAX(i));
|
||||
err = adm9240_update_config(data);
|
||||
if (err < 0) {
|
||||
data->valid = 0;
|
||||
mutex_unlock(&data->update_lock);
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
for (i = 0; i < 2; i++) {
|
||||
data->fan_min[i] = i2c_smbus_read_byte_data(client,
|
||||
ADM9240_REG_FAN_MIN(i));
|
||||
}
|
||||
data->temp_max[0] = i2c_smbus_read_byte_data(client,
|
||||
ADM9240_REG_TEMP_MAX(0));
|
||||
data->temp_max[1] = i2c_smbus_read_byte_data(client,
|
||||
ADM9240_REG_TEMP_MAX(1));
|
||||
|
||||
/* read fan divs and 5-bit VID */
|
||||
i = i2c_smbus_read_byte_data(client, ADM9240_REG_VID_FAN_DIV);
|
||||
data->fan_div[0] = (i >> 4) & 3;
|
||||
data->fan_div[1] = (i >> 6) & 3;
|
||||
data->vid = i & 0x0f;
|
||||
data->vid |= (i2c_smbus_read_byte_data(client,
|
||||
ADM9240_REG_VID4) & 1) << 4;
|
||||
/* read analog out */
|
||||
data->aout = i2c_smbus_read_byte_data(client,
|
||||
ADM9240_REG_ANALOG_OUT);
|
||||
|
||||
data->last_updated_config = jiffies;
|
||||
data->valid = 1;
|
||||
}
|
||||
@ -253,6 +307,10 @@ static ssize_t temp1_input_show(struct device *dev,
|
||||
struct device_attribute *dummy, char *buf)
|
||||
{
|
||||
struct adm9240_data *data = adm9240_update_device(dev);
|
||||
|
||||
if (IS_ERR(data))
|
||||
return PTR_ERR(data);
|
||||
|
||||
return sprintf(buf, "%d\n", data->temp / 128 * 500); /* 9-bit value */
|
||||
}
|
||||
|
||||
@ -261,6 +319,10 @@ static ssize_t max_show(struct device *dev, struct device_attribute *devattr,
|
||||
{
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
|
||||
struct adm9240_data *data = adm9240_update_device(dev);
|
||||
|
||||
if (IS_ERR(data))
|
||||
return PTR_ERR(data);
|
||||
|
||||
return sprintf(buf, "%d\n", data->temp_max[attr->index] * 1000);
|
||||
}
|
||||
|
||||
@ -269,7 +331,6 @@ static ssize_t max_store(struct device *dev, struct device_attribute *devattr,
|
||||
{
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
|
||||
struct adm9240_data *data = dev_get_drvdata(dev);
|
||||
struct i2c_client *client = data->client;
|
||||
long val;
|
||||
int err;
|
||||
|
||||
@ -279,10 +340,10 @@ static ssize_t max_store(struct device *dev, struct device_attribute *devattr,
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
data->temp_max[attr->index] = TEMP_TO_REG(val);
|
||||
i2c_smbus_write_byte_data(client, ADM9240_REG_TEMP_MAX(attr->index),
|
||||
data->temp_max[attr->index]);
|
||||
err = regmap_write(data->regmap, ADM9240_REG_TEMP_MAX(attr->index),
|
||||
data->temp_max[attr->index]);
|
||||
mutex_unlock(&data->update_lock);
|
||||
return count;
|
||||
return err < 0 ? err : count;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR_RO(temp1_input);
|
||||
@ -295,6 +356,10 @@ static ssize_t in_show(struct device *dev, struct device_attribute *devattr,
|
||||
{
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
|
||||
struct adm9240_data *data = adm9240_update_device(dev);
|
||||
|
||||
if (IS_ERR(data))
|
||||
return PTR_ERR(data);
|
||||
|
||||
return sprintf(buf, "%d\n", IN_FROM_REG(data->in[attr->index],
|
||||
attr->index));
|
||||
}
|
||||
@ -304,6 +369,10 @@ static ssize_t in_min_show(struct device *dev,
|
||||
{
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
|
||||
struct adm9240_data *data = adm9240_update_device(dev);
|
||||
|
||||
if (IS_ERR(data))
|
||||
return PTR_ERR(data);
|
||||
|
||||
return sprintf(buf, "%d\n", IN_FROM_REG(data->in_min[attr->index],
|
||||
attr->index));
|
||||
}
|
||||
@ -313,6 +382,10 @@ static ssize_t in_max_show(struct device *dev,
|
||||
{
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
|
||||
struct adm9240_data *data = adm9240_update_device(dev);
|
||||
|
||||
if (IS_ERR(data))
|
||||
return PTR_ERR(data);
|
||||
|
||||
return sprintf(buf, "%d\n", IN_FROM_REG(data->in_max[attr->index],
|
||||
attr->index));
|
||||
}
|
||||
@ -323,7 +396,6 @@ static ssize_t in_min_store(struct device *dev,
|
||||
{
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
|
||||
struct adm9240_data *data = dev_get_drvdata(dev);
|
||||
struct i2c_client *client = data->client;
|
||||
unsigned long val;
|
||||
int err;
|
||||
|
||||
@ -333,10 +405,10 @@ static ssize_t in_min_store(struct device *dev,
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
data->in_min[attr->index] = IN_TO_REG(val, attr->index);
|
||||
i2c_smbus_write_byte_data(client, ADM9240_REG_IN_MIN(attr->index),
|
||||
data->in_min[attr->index]);
|
||||
err = regmap_write(data->regmap, ADM9240_REG_IN_MIN(attr->index),
|
||||
data->in_min[attr->index]);
|
||||
mutex_unlock(&data->update_lock);
|
||||
return count;
|
||||
return err < 0 ? err : count;
|
||||
}
|
||||
|
||||
static ssize_t in_max_store(struct device *dev,
|
||||
@ -345,7 +417,6 @@ static ssize_t in_max_store(struct device *dev,
|
||||
{
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
|
||||
struct adm9240_data *data = dev_get_drvdata(dev);
|
||||
struct i2c_client *client = data->client;
|
||||
unsigned long val;
|
||||
int err;
|
||||
|
||||
@ -355,10 +426,10 @@ static ssize_t in_max_store(struct device *dev,
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
data->in_max[attr->index] = IN_TO_REG(val, attr->index);
|
||||
i2c_smbus_write_byte_data(client, ADM9240_REG_IN_MAX(attr->index),
|
||||
data->in_max[attr->index]);
|
||||
err = regmap_write(data->regmap, ADM9240_REG_IN_MAX(attr->index),
|
||||
data->in_max[attr->index]);
|
||||
mutex_unlock(&data->update_lock);
|
||||
return count;
|
||||
return err < 0 ? err : count;
|
||||
}
|
||||
|
||||
static SENSOR_DEVICE_ATTR_RO(in0_input, in, 0);
|
||||
@ -386,6 +457,10 @@ static ssize_t fan_show(struct device *dev, struct device_attribute *devattr,
|
||||
{
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
|
||||
struct adm9240_data *data = adm9240_update_device(dev);
|
||||
|
||||
if (IS_ERR(data))
|
||||
return PTR_ERR(data);
|
||||
|
||||
return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[attr->index],
|
||||
1 << data->fan_div[attr->index]));
|
||||
}
|
||||
@ -395,6 +470,10 @@ static ssize_t fan_min_show(struct device *dev,
|
||||
{
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
|
||||
struct adm9240_data *data = adm9240_update_device(dev);
|
||||
|
||||
if (IS_ERR(data))
|
||||
return PTR_ERR(data);
|
||||
|
||||
return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan_min[attr->index],
|
||||
1 << data->fan_div[attr->index]));
|
||||
}
|
||||
@ -404,6 +483,10 @@ static ssize_t fan_div_show(struct device *dev,
|
||||
{
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
|
||||
struct adm9240_data *data = adm9240_update_device(dev);
|
||||
|
||||
if (IS_ERR(data))
|
||||
return PTR_ERR(data);
|
||||
|
||||
return sprintf(buf, "%d\n", 1 << data->fan_div[attr->index]);
|
||||
}
|
||||
|
||||
@ -469,13 +552,13 @@ static ssize_t fan_min_store(struct device *dev,
|
||||
|
||||
if (new_div != data->fan_div[nr]) {
|
||||
data->fan_div[nr] = new_div;
|
||||
adm9240_write_fan_div(client, nr, new_div);
|
||||
adm9240_write_fan_div(data, nr, new_div);
|
||||
}
|
||||
i2c_smbus_write_byte_data(client, ADM9240_REG_FAN_MIN(nr),
|
||||
data->fan_min[nr]);
|
||||
err = regmap_write(data->regmap, ADM9240_REG_FAN_MIN(nr),
|
||||
data->fan_min[nr]);
|
||||
|
||||
mutex_unlock(&data->update_lock);
|
||||
return count;
|
||||
return err < 0 ? err : count;
|
||||
}
|
||||
|
||||
static SENSOR_DEVICE_ATTR_RO(fan1_input, fan, 0);
|
||||
@ -490,6 +573,10 @@ static ssize_t alarms_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct adm9240_data *data = adm9240_update_device(dev);
|
||||
|
||||
if (IS_ERR(data))
|
||||
return PTR_ERR(data);
|
||||
|
||||
return sprintf(buf, "%u\n", data->alarms);
|
||||
}
|
||||
static DEVICE_ATTR_RO(alarms);
|
||||
@ -499,6 +586,10 @@ static ssize_t alarm_show(struct device *dev, struct device_attribute *attr,
|
||||
{
|
||||
int bitnr = to_sensor_dev_attr(attr)->index;
|
||||
struct adm9240_data *data = adm9240_update_device(dev);
|
||||
|
||||
if (IS_ERR(data))
|
||||
return PTR_ERR(data);
|
||||
|
||||
return sprintf(buf, "%u\n", (data->alarms >> bitnr) & 1);
|
||||
}
|
||||
static SENSOR_DEVICE_ATTR_RO(in0_alarm, alarm, 0);
|
||||
@ -516,6 +607,10 @@ static ssize_t cpu0_vid_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct adm9240_data *data = adm9240_update_device(dev);
|
||||
|
||||
if (IS_ERR(data))
|
||||
return PTR_ERR(data);
|
||||
|
||||
return sprintf(buf, "%d\n", vid_from_reg(data->vid, data->vrm));
|
||||
}
|
||||
static DEVICE_ATTR_RO(cpu0_vid);
|
||||
@ -525,6 +620,10 @@ static ssize_t aout_output_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct adm9240_data *data = adm9240_update_device(dev);
|
||||
|
||||
if (IS_ERR(data))
|
||||
return PTR_ERR(data);
|
||||
|
||||
return sprintf(buf, "%d\n", AOUT_FROM_REG(data->aout));
|
||||
}
|
||||
|
||||
@ -533,7 +632,6 @@ static ssize_t aout_output_store(struct device *dev,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct adm9240_data *data = dev_get_drvdata(dev);
|
||||
struct i2c_client *client = data->client;
|
||||
long val;
|
||||
int err;
|
||||
|
||||
@ -543,9 +641,9 @@ static ssize_t aout_output_store(struct device *dev,
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
data->aout = AOUT_TO_REG(val);
|
||||
i2c_smbus_write_byte_data(client, ADM9240_REG_ANALOG_OUT, data->aout);
|
||||
err = regmap_write(data->regmap, ADM9240_REG_ANALOG_OUT, data->aout);
|
||||
mutex_unlock(&data->update_lock);
|
||||
return count;
|
||||
return err < 0 ? err : count;
|
||||
}
|
||||
static DEVICE_ATTR_RW(aout_output);
|
||||
|
||||
@ -553,17 +651,19 @@ static ssize_t alarm_store(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct adm9240_data *data = dev_get_drvdata(dev);
|
||||
struct i2c_client *client = data->client;
|
||||
unsigned long val;
|
||||
int err;
|
||||
|
||||
if (kstrtoul(buf, 10, &val) || val != 0)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
i2c_smbus_write_byte_data(client, ADM9240_REG_CHASSIS_CLEAR, 0x80);
|
||||
err = regmap_write(data->regmap, ADM9240_REG_CHASSIS_CLEAR, 0x80);
|
||||
data->valid = 0; /* Force cache refresh */
|
||||
mutex_unlock(&data->update_lock);
|
||||
dev_dbg(&client->dev, "chassis intrusion latch cleared\n");
|
||||
if (err < 0)
|
||||
return err;
|
||||
dev_dbg(&data->client->dev, "chassis intrusion latch cleared\n");
|
||||
|
||||
return count;
|
||||
}
|
||||
@ -662,11 +762,18 @@ static int adm9240_detect(struct i2c_client *new_client,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void adm9240_init_client(struct i2c_client *client)
|
||||
static int adm9240_init_client(struct i2c_client *client, struct adm9240_data *data)
|
||||
{
|
||||
struct adm9240_data *data = i2c_get_clientdata(client);
|
||||
u8 conf = i2c_smbus_read_byte_data(client, ADM9240_REG_CONFIG);
|
||||
u8 mode = i2c_smbus_read_byte_data(client, ADM9240_REG_TEMP_CONF) & 3;
|
||||
u8 conf, mode;
|
||||
int err;
|
||||
|
||||
err = regmap_raw_read(data->regmap, ADM9240_REG_CONFIG, &conf, 1);
|
||||
if (err < 0)
|
||||
return err;
|
||||
err = regmap_raw_read(data->regmap, ADM9240_REG_TEMP_CONF, &mode, 1);
|
||||
if (err < 0)
|
||||
return err;
|
||||
mode &= 3;
|
||||
|
||||
data->vrm = vid_which_vrm(); /* need this to report vid as mV */
|
||||
|
||||
@ -682,44 +789,67 @@ static void adm9240_init_client(struct i2c_client *client)
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 6; i++) {
|
||||
i2c_smbus_write_byte_data(client,
|
||||
ADM9240_REG_IN_MIN(i), 0);
|
||||
i2c_smbus_write_byte_data(client,
|
||||
ADM9240_REG_IN_MAX(i), 255);
|
||||
err = regmap_write(data->regmap,
|
||||
ADM9240_REG_IN_MIN(i), 0);
|
||||
if (err < 0)
|
||||
return err;
|
||||
err = regmap_write(data->regmap,
|
||||
ADM9240_REG_IN_MAX(i), 255);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
for (i = 0; i < 2; i++) {
|
||||
err = regmap_write(data->regmap,
|
||||
ADM9240_REG_FAN_MIN(i), 255);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
for (i = 0; i < 2; i++) {
|
||||
err = regmap_write(data->regmap,
|
||||
ADM9240_REG_TEMP_MAX(i), 127);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
i2c_smbus_write_byte_data(client,
|
||||
ADM9240_REG_FAN_MIN(0), 255);
|
||||
i2c_smbus_write_byte_data(client,
|
||||
ADM9240_REG_FAN_MIN(1), 255);
|
||||
i2c_smbus_write_byte_data(client,
|
||||
ADM9240_REG_TEMP_MAX(0), 127);
|
||||
i2c_smbus_write_byte_data(client,
|
||||
ADM9240_REG_TEMP_MAX(1), 127);
|
||||
|
||||
/* start measurement cycle */
|
||||
i2c_smbus_write_byte_data(client, ADM9240_REG_CONFIG, 1);
|
||||
err = regmap_write(data->regmap, ADM9240_REG_CONFIG, 1);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
dev_info(&client->dev,
|
||||
"cold start: config was 0x%02x mode %u\n", conf, mode);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int adm9240_probe(struct i2c_client *new_client,
|
||||
const struct i2c_device_id *id)
|
||||
static const struct regmap_config adm9240_regmap_config = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
.use_single_read = true,
|
||||
.use_single_write = true,
|
||||
};
|
||||
|
||||
static int adm9240_probe(struct i2c_client *new_client)
|
||||
{
|
||||
struct device *dev = &new_client->dev;
|
||||
struct device *hwmon_dev;
|
||||
struct adm9240_data *data;
|
||||
int err;
|
||||
|
||||
data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
i2c_set_clientdata(new_client, data);
|
||||
data->client = new_client;
|
||||
mutex_init(&data->update_lock);
|
||||
data->regmap = devm_regmap_init_i2c(new_client, &adm9240_regmap_config);
|
||||
if (IS_ERR(data->regmap))
|
||||
return PTR_ERR(data->regmap);
|
||||
|
||||
adm9240_init_client(new_client);
|
||||
err = adm9240_init_client(new_client, data);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
hwmon_dev = devm_hwmon_device_register_with_groups(dev,
|
||||
new_client->name,
|
||||
@ -741,7 +871,7 @@ static struct i2c_driver adm9240_driver = {
|
||||
.driver = {
|
||||
.name = "adm9240",
|
||||
},
|
||||
.probe = adm9240_probe,
|
||||
.probe_new = adm9240_probe,
|
||||
.id_table = adm9240_id,
|
||||
.detect = adm9240_detect,
|
||||
.address_list = normal_i2c,
|
||||
|
@ -99,8 +99,9 @@ static const struct regmap_config ads2830_regmap_config = {
|
||||
.val_bits = 8,
|
||||
};
|
||||
|
||||
static int ads7828_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
static const struct i2c_device_id ads7828_device_ids[];
|
||||
|
||||
static int ads7828_probe(struct i2c_client *client)
|
||||
{
|
||||
struct device *dev = &client->dev;
|
||||
struct ads7828_platform_data *pdata = dev_get_platdata(dev);
|
||||
@ -141,7 +142,7 @@ static int ads7828_probe(struct i2c_client *client,
|
||||
chip = (enum ads7828_chips)
|
||||
of_device_get_match_data(&client->dev);
|
||||
else
|
||||
chip = id->driver_data;
|
||||
chip = i2c_match_id(ads7828_device_ids, client)->driver_data;
|
||||
|
||||
/* Bound Vref with min/max values */
|
||||
vref_mv = clamp_val(vref_mv, ADS7828_EXT_VREF_MV_MIN,
|
||||
@ -207,7 +208,7 @@ static struct i2c_driver ads7828_driver = {
|
||||
},
|
||||
|
||||
.id_table = ads7828_device_ids,
|
||||
.probe = ads7828_probe,
|
||||
.probe_new = ads7828_probe,
|
||||
};
|
||||
|
||||
module_i2c_driver(ads7828_driver);
|
||||
|
@ -39,8 +39,7 @@ static const struct adt7x10_ops adt7410_i2c_ops = {
|
||||
.write_byte = adt7410_i2c_write_byte,
|
||||
};
|
||||
|
||||
static int adt7410_i2c_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
static int adt7410_i2c_probe(struct i2c_client *client)
|
||||
{
|
||||
if (!i2c_check_functionality(client->adapter,
|
||||
I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA))
|
||||
@ -67,7 +66,7 @@ static struct i2c_driver adt7410_driver = {
|
||||
.name = "adt7410",
|
||||
.pm = ADT7X10_DEV_PM_OPS,
|
||||
},
|
||||
.probe = adt7410_i2c_probe,
|
||||
.probe_new = adt7410_i2c_probe,
|
||||
.remove = adt7410_i2c_remove,
|
||||
.id_table = adt7410_ids,
|
||||
.address_list = I2C_ADDRS(0x48, 0x49, 0x4a, 0x4b),
|
||||
|
@ -666,8 +666,7 @@ static const struct hwmon_chip_info adt7411_chip_info = {
|
||||
.info = adt7411_info,
|
||||
};
|
||||
|
||||
static int adt7411_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
static int adt7411_probe(struct i2c_client *client)
|
||||
{
|
||||
struct device *dev = &client->dev;
|
||||
struct adt7411_data *data;
|
||||
@ -707,7 +706,7 @@ static struct i2c_driver adt7411_driver = {
|
||||
.driver = {
|
||||
.name = "adt7411",
|
||||
},
|
||||
.probe = adt7411_probe,
|
||||
.probe_new = adt7411_probe,
|
||||
.id_table = adt7411_id,
|
||||
.detect = adt7411_detect,
|
||||
.address_list = normal_i2c,
|
||||
|
@ -1787,8 +1787,7 @@ static int adt7462_detect(struct i2c_client *client,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int adt7462_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
static int adt7462_probe(struct i2c_client *client)
|
||||
{
|
||||
struct device *dev = &client->dev;
|
||||
struct adt7462_data *data;
|
||||
@ -1820,7 +1819,7 @@ static struct i2c_driver adt7462_driver = {
|
||||
.driver = {
|
||||
.name = "adt7462",
|
||||
},
|
||||
.probe = adt7462_probe,
|
||||
.probe_new = adt7462_probe,
|
||||
.id_table = adt7462_id,
|
||||
.detect = adt7462_detect,
|
||||
.address_list = normal_i2c,
|
||||
|
@ -1217,8 +1217,7 @@ static void adt7470_init_client(struct i2c_client *client)
|
||||
}
|
||||
}
|
||||
|
||||
static int adt7470_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
static int adt7470_probe(struct i2c_client *client)
|
||||
{
|
||||
struct device *dev = &client->dev;
|
||||
struct adt7470_data *data;
|
||||
@ -1276,7 +1275,7 @@ static struct i2c_driver adt7470_driver = {
|
||||
.driver = {
|
||||
.name = "adt7470",
|
||||
},
|
||||
.probe = adt7470_probe,
|
||||
.probe_new = adt7470_probe,
|
||||
.remove = adt7470_remove,
|
||||
.id_table = adt7470_id,
|
||||
.detect = adt7470_detect,
|
||||
|
@ -1539,8 +1539,7 @@ static int adt7475_set_pwm_polarity(struct i2c_client *client)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int adt7475_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
static int adt7475_probe(struct i2c_client *client)
|
||||
{
|
||||
enum chips chip;
|
||||
static const char * const names[] = {
|
||||
@ -1554,6 +1553,7 @@ static int adt7475_probe(struct i2c_client *client,
|
||||
struct device *hwmon_dev;
|
||||
int i, ret = 0, revision, group_num = 0;
|
||||
u8 config3;
|
||||
const struct i2c_device_id *id = i2c_match_id(adt7475_id, client);
|
||||
|
||||
data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
|
||||
if (data == NULL)
|
||||
@ -1728,7 +1728,7 @@ static struct i2c_driver adt7475_driver = {
|
||||
.name = "adt7475",
|
||||
.of_match_table = of_match_ptr(adt7475_of_match),
|
||||
},
|
||||
.probe = adt7475_probe,
|
||||
.probe_new = adt7475_probe,
|
||||
.id_table = adt7475_id,
|
||||
.detect = adt7475_detect,
|
||||
.address_list = normal_i2c,
|
||||
|
@ -900,8 +900,7 @@ static int amc6821_init_client(struct i2c_client *client)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int amc6821_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
static int amc6821_probe(struct i2c_client *client)
|
||||
{
|
||||
struct device *dev = &client->dev;
|
||||
struct amc6821_data *data;
|
||||
@ -940,7 +939,7 @@ static struct i2c_driver amc6821_driver = {
|
||||
.driver = {
|
||||
.name = "amc6821",
|
||||
},
|
||||
.probe = amc6821_probe,
|
||||
.probe_new = amc6821_probe,
|
||||
.id_table = amc6821_id,
|
||||
.detect = amc6821_detect,
|
||||
.address_list = normal_i2c,
|
||||
|
@ -35,7 +35,6 @@
|
||||
struct sensor_accumulator {
|
||||
u64 energy_ctr;
|
||||
u64 prev_value;
|
||||
char label[10];
|
||||
};
|
||||
|
||||
struct amd_energy_data {
|
||||
@ -47,11 +46,13 @@ struct amd_energy_data {
|
||||
struct mutex lock;
|
||||
/* An accumulator for each core and socket */
|
||||
struct sensor_accumulator *accums;
|
||||
unsigned int timeout_ms;
|
||||
/* Energy Status Units */
|
||||
u64 energy_units;
|
||||
int energy_units;
|
||||
int nr_cpus;
|
||||
int nr_socks;
|
||||
int core_id;
|
||||
char (*label)[10];
|
||||
};
|
||||
|
||||
static int amd_energy_read_labels(struct device *dev,
|
||||
@ -61,7 +62,7 @@ static int amd_energy_read_labels(struct device *dev,
|
||||
{
|
||||
struct amd_energy_data *data = dev_get_drvdata(dev);
|
||||
|
||||
*str = data->accums[channel].label;
|
||||
*str = data->label[channel];
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -73,108 +74,67 @@ static void get_energy_units(struct amd_energy_data *data)
|
||||
data->energy_units = (rapl_units & AMD_ENERGY_UNIT_MASK) >> 8;
|
||||
}
|
||||
|
||||
static void accumulate_socket_delta(struct amd_energy_data *data,
|
||||
int sock, int cpu)
|
||||
static void accumulate_delta(struct amd_energy_data *data,
|
||||
int channel, int cpu, u32 reg)
|
||||
{
|
||||
struct sensor_accumulator *s_accum;
|
||||
struct sensor_accumulator *accum;
|
||||
u64 input;
|
||||
|
||||
mutex_lock(&data->lock);
|
||||
rdmsrl_safe_on_cpu(cpu, ENERGY_PKG_MSR, &input);
|
||||
rdmsrl_safe_on_cpu(cpu, reg, &input);
|
||||
input &= AMD_ENERGY_MASK;
|
||||
|
||||
s_accum = &data->accums[data->nr_cpus + sock];
|
||||
if (input >= s_accum->prev_value)
|
||||
s_accum->energy_ctr +=
|
||||
input - s_accum->prev_value;
|
||||
accum = &data->accums[channel];
|
||||
if (input >= accum->prev_value)
|
||||
accum->energy_ctr +=
|
||||
input - accum->prev_value;
|
||||
else
|
||||
s_accum->energy_ctr += UINT_MAX -
|
||||
s_accum->prev_value + input;
|
||||
accum->energy_ctr += UINT_MAX -
|
||||
accum->prev_value + input;
|
||||
|
||||
s_accum->prev_value = input;
|
||||
mutex_unlock(&data->lock);
|
||||
}
|
||||
|
||||
static void accumulate_core_delta(struct amd_energy_data *data)
|
||||
{
|
||||
struct sensor_accumulator *c_accum;
|
||||
u64 input;
|
||||
int cpu;
|
||||
|
||||
mutex_lock(&data->lock);
|
||||
if (data->core_id >= data->nr_cpus)
|
||||
data->core_id = 0;
|
||||
|
||||
cpu = data->core_id;
|
||||
|
||||
if (!cpu_online(cpu))
|
||||
goto out;
|
||||
|
||||
rdmsrl_safe_on_cpu(cpu, ENERGY_CORE_MSR, &input);
|
||||
input &= AMD_ENERGY_MASK;
|
||||
|
||||
c_accum = &data->accums[cpu];
|
||||
|
||||
if (input >= c_accum->prev_value)
|
||||
c_accum->energy_ctr +=
|
||||
input - c_accum->prev_value;
|
||||
else
|
||||
c_accum->energy_ctr += UINT_MAX -
|
||||
c_accum->prev_value + input;
|
||||
|
||||
c_accum->prev_value = input;
|
||||
|
||||
out:
|
||||
data->core_id++;
|
||||
accum->prev_value = input;
|
||||
mutex_unlock(&data->lock);
|
||||
}
|
||||
|
||||
static void read_accumulate(struct amd_energy_data *data)
|
||||
{
|
||||
int sock;
|
||||
int sock, scpu, cpu;
|
||||
|
||||
for (sock = 0; sock < data->nr_socks; sock++) {
|
||||
int cpu;
|
||||
scpu = cpumask_first_and(cpu_online_mask,
|
||||
cpumask_of_node(sock));
|
||||
|
||||
cpu = cpumask_first_and(cpu_online_mask,
|
||||
cpumask_of_node(sock));
|
||||
|
||||
accumulate_socket_delta(data, sock, cpu);
|
||||
accumulate_delta(data, data->nr_cpus + sock,
|
||||
scpu, ENERGY_PKG_MSR);
|
||||
}
|
||||
|
||||
accumulate_core_delta(data);
|
||||
if (data->core_id >= data->nr_cpus)
|
||||
data->core_id = 0;
|
||||
|
||||
cpu = data->core_id;
|
||||
if (cpu_online(cpu))
|
||||
accumulate_delta(data, cpu, cpu, ENERGY_CORE_MSR);
|
||||
|
||||
data->core_id++;
|
||||
}
|
||||
|
||||
static void amd_add_delta(struct amd_energy_data *data, int ch,
|
||||
int cpu, long *val, bool is_core)
|
||||
int cpu, long *val, u32 reg)
|
||||
{
|
||||
struct sensor_accumulator *s_accum, *c_accum;
|
||||
struct sensor_accumulator *accum;
|
||||
u64 input;
|
||||
|
||||
mutex_lock(&data->lock);
|
||||
if (!is_core) {
|
||||
rdmsrl_safe_on_cpu(cpu, ENERGY_PKG_MSR, &input);
|
||||
input &= AMD_ENERGY_MASK;
|
||||
rdmsrl_safe_on_cpu(cpu, reg, &input);
|
||||
input &= AMD_ENERGY_MASK;
|
||||
|
||||
s_accum = &data->accums[ch];
|
||||
if (input >= s_accum->prev_value)
|
||||
input += s_accum->energy_ctr -
|
||||
s_accum->prev_value;
|
||||
else
|
||||
input += UINT_MAX - s_accum->prev_value +
|
||||
s_accum->energy_ctr;
|
||||
} else {
|
||||
rdmsrl_safe_on_cpu(cpu, ENERGY_CORE_MSR, &input);
|
||||
input &= AMD_ENERGY_MASK;
|
||||
|
||||
c_accum = &data->accums[ch];
|
||||
if (input >= c_accum->prev_value)
|
||||
input += c_accum->energy_ctr -
|
||||
c_accum->prev_value;
|
||||
else
|
||||
input += UINT_MAX - c_accum->prev_value +
|
||||
c_accum->energy_ctr;
|
||||
}
|
||||
accum = &data->accums[ch];
|
||||
if (input >= accum->prev_value)
|
||||
input += accum->energy_ctr -
|
||||
accum->prev_value;
|
||||
else
|
||||
input += UINT_MAX - accum->prev_value +
|
||||
accum->energy_ctr;
|
||||
|
||||
/* Energy consumed = (1/(2^ESU) * RAW * 1000000UL) μJoules */
|
||||
*val = div64_ul(input * 1000000UL, BIT(data->energy_units));
|
||||
@ -187,20 +147,22 @@ static int amd_energy_read(struct device *dev,
|
||||
u32 attr, int channel, long *val)
|
||||
{
|
||||
struct amd_energy_data *data = dev_get_drvdata(dev);
|
||||
u32 reg;
|
||||
int cpu;
|
||||
|
||||
if (channel >= data->nr_cpus) {
|
||||
cpu = cpumask_first_and(cpu_online_mask,
|
||||
cpumask_of_node
|
||||
(channel - data->nr_cpus));
|
||||
amd_add_delta(data, channel, cpu, val, false);
|
||||
reg = ENERGY_PKG_MSR;
|
||||
} else {
|
||||
cpu = channel;
|
||||
if (!cpu_online(cpu))
|
||||
return -ENODEV;
|
||||
|
||||
amd_add_delta(data, channel, cpu, val, true);
|
||||
reg = ENERGY_CORE_MSR;
|
||||
}
|
||||
amd_add_delta(data, channel, cpu, val, reg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -215,6 +177,7 @@ static umode_t amd_energy_is_visible(const void *_data,
|
||||
static int energy_accumulator(void *p)
|
||||
{
|
||||
struct amd_energy_data *data = (struct amd_energy_data *)p;
|
||||
unsigned int timeout = data->timeout_ms;
|
||||
|
||||
while (!kthread_should_stop()) {
|
||||
/*
|
||||
@ -227,14 +190,7 @@ static int energy_accumulator(void *p)
|
||||
if (kthread_should_stop())
|
||||
break;
|
||||
|
||||
/*
|
||||
* On a 240W system, with default resolution the
|
||||
* Socket Energy status register may wrap around in
|
||||
* 2^32*15.3 e-6/240 = 273.8041 secs (~4.5 mins)
|
||||
*
|
||||
* let us accumulate for every 100secs
|
||||
*/
|
||||
schedule_timeout(msecs_to_jiffies(100000));
|
||||
schedule_timeout(msecs_to_jiffies(timeout));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -247,12 +203,13 @@ static const struct hwmon_ops amd_energy_ops = {
|
||||
|
||||
static int amd_create_sensor(struct device *dev,
|
||||
struct amd_energy_data *data,
|
||||
u8 type, u32 config)
|
||||
enum hwmon_sensor_types type, u32 config)
|
||||
{
|
||||
struct hwmon_channel_info *info = &data->energy_info;
|
||||
struct sensor_accumulator *accums;
|
||||
int i, num_siblings, cpus, sockets;
|
||||
u32 *s_config;
|
||||
char (*label_l)[10];
|
||||
|
||||
/* Identify the number of siblings per core */
|
||||
num_siblings = ((cpuid_ebx(0x8000001e) >> 8) & 0xff) + 1;
|
||||
@ -276,21 +233,25 @@ static int amd_create_sensor(struct device *dev,
|
||||
if (!accums)
|
||||
return -ENOMEM;
|
||||
|
||||
label_l = devm_kcalloc(dev, cpus + sockets,
|
||||
sizeof(*label_l), GFP_KERNEL);
|
||||
if (!label_l)
|
||||
return -ENOMEM;
|
||||
|
||||
info->type = type;
|
||||
info->config = s_config;
|
||||
|
||||
data->nr_cpus = cpus;
|
||||
data->nr_socks = sockets;
|
||||
data->accums = accums;
|
||||
data->label = label_l;
|
||||
|
||||
for (i = 0; i < cpus + sockets; i++) {
|
||||
s_config[i] = config;
|
||||
if (i < cpus)
|
||||
scnprintf(accums[i].label, 10,
|
||||
"Ecore%03u", i);
|
||||
scnprintf(label_l[i], 10, "Ecore%03u", i);
|
||||
else
|
||||
scnprintf(accums[i].label, 10,
|
||||
"Esocket%u", (i - cpus));
|
||||
scnprintf(label_l[i], 10, "Esocket%u", (i - cpus));
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -301,6 +262,7 @@ static int amd_energy_probe(struct platform_device *pdev)
|
||||
struct device *hwmon_dev;
|
||||
struct amd_energy_data *data;
|
||||
struct device *dev = &pdev->dev;
|
||||
int ret;
|
||||
|
||||
data = devm_kzalloc(dev,
|
||||
sizeof(struct amd_energy_data), GFP_KERNEL);
|
||||
@ -313,8 +275,10 @@ static int amd_energy_probe(struct platform_device *pdev)
|
||||
dev_set_drvdata(dev, data);
|
||||
/* Populate per-core energy reporting */
|
||||
data->info[0] = &data->energy_info;
|
||||
amd_create_sensor(dev, data, hwmon_energy,
|
||||
HWMON_E_INPUT | HWMON_E_LABEL);
|
||||
ret = amd_create_sensor(dev, data, hwmon_energy,
|
||||
HWMON_E_INPUT | HWMON_E_LABEL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
mutex_init(&data->lock);
|
||||
get_energy_units(data);
|
||||
@ -326,11 +290,15 @@ static int amd_energy_probe(struct platform_device *pdev)
|
||||
if (IS_ERR(hwmon_dev))
|
||||
return PTR_ERR(hwmon_dev);
|
||||
|
||||
/*
|
||||
* On a system with peak wattage of 250W
|
||||
* timeout = 2 ^ 32 / 2 ^ energy_units / 250 secs
|
||||
*/
|
||||
data->timeout_ms = 1000 *
|
||||
BIT(min(28, 31 - data->energy_units)) / 250;
|
||||
|
||||
data->wrap_accumulate = kthread_run(energy_accumulator, data,
|
||||
"%s", dev_name(hwmon_dev));
|
||||
if (IS_ERR(data->wrap_accumulate))
|
||||
return PTR_ERR(data->wrap_accumulate);
|
||||
|
||||
return PTR_ERR_OR_ZERO(data->wrap_accumulate);
|
||||
}
|
||||
|
||||
|
@ -205,8 +205,7 @@ struct asb100_data {
|
||||
static int asb100_read_value(struct i2c_client *client, u16 reg);
|
||||
static void asb100_write_value(struct i2c_client *client, u16 reg, u16 val);
|
||||
|
||||
static int asb100_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id);
|
||||
static int asb100_probe(struct i2c_client *client);
|
||||
static int asb100_detect(struct i2c_client *client,
|
||||
struct i2c_board_info *info);
|
||||
static int asb100_remove(struct i2c_client *client);
|
||||
@ -224,7 +223,7 @@ static struct i2c_driver asb100_driver = {
|
||||
.driver = {
|
||||
.name = "asb100",
|
||||
},
|
||||
.probe = asb100_probe,
|
||||
.probe_new = asb100_probe,
|
||||
.remove = asb100_remove,
|
||||
.id_table = asb100_id,
|
||||
.detect = asb100_detect,
|
||||
@ -775,8 +774,7 @@ static int asb100_detect(struct i2c_client *client,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int asb100_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
static int asb100_probe(struct i2c_client *client)
|
||||
{
|
||||
int err;
|
||||
struct asb100_data *data;
|
||||
|
@ -1087,7 +1087,7 @@ static void asc7621_init_client(struct i2c_client *client)
|
||||
}
|
||||
|
||||
static int
|
||||
asc7621_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
||||
asc7621_probe(struct i2c_client *client)
|
||||
{
|
||||
struct asc7621_data *data;
|
||||
int i, err;
|
||||
@ -1193,7 +1193,7 @@ static struct i2c_driver asc7621_driver = {
|
||||
.driver = {
|
||||
.name = "asc7621",
|
||||
},
|
||||
.probe = asc7621_probe,
|
||||
.probe_new = asc7621_probe,
|
||||
.remove = asc7621_remove,
|
||||
.id_table = asc7621_id,
|
||||
.detect = asc7621_detect,
|
||||
|
@ -244,8 +244,7 @@ static struct attribute *atxp1_attrs[] = {
|
||||
};
|
||||
ATTRIBUTE_GROUPS(atxp1);
|
||||
|
||||
static int atxp1_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
static int atxp1_probe(struct i2c_client *client)
|
||||
{
|
||||
struct device *dev = &client->dev;
|
||||
struct atxp1_data *data;
|
||||
@ -288,7 +287,7 @@ static struct i2c_driver atxp1_driver = {
|
||||
.driver = {
|
||||
.name = "atxp1",
|
||||
},
|
||||
.probe = atxp1_probe,
|
||||
.probe_new = atxp1_probe,
|
||||
.id_table = atxp1_id,
|
||||
};
|
||||
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/completion.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/hwmon-sysfs.h>
|
||||
#include <linux/hwmon.h>
|
||||
@ -476,6 +477,7 @@ static int pvt_read_data(struct pvt_hwmon *pvt, enum pvt_sensor_type type,
|
||||
long *val)
|
||||
{
|
||||
struct pvt_cache *cache = &pvt->cache[type];
|
||||
unsigned long timeout;
|
||||
u32 data;
|
||||
int ret;
|
||||
|
||||
@ -499,7 +501,14 @@ static int pvt_read_data(struct pvt_hwmon *pvt, enum pvt_sensor_type type,
|
||||
pvt_update(pvt->regs + PVT_INTR_MASK, PVT_INTR_DVALID, 0);
|
||||
pvt_update(pvt->regs + PVT_CTRL, PVT_CTRL_EN, PVT_CTRL_EN);
|
||||
|
||||
wait_for_completion(&cache->conversion);
|
||||
/*
|
||||
* Wait with timeout since in case if the sensor is suddenly powered
|
||||
* down the request won't be completed and the caller will hang up on
|
||||
* this procedure until the power is back up again. Multiply the
|
||||
* timeout by the factor of two to prevent a false timeout.
|
||||
*/
|
||||
timeout = 2 * usecs_to_jiffies(ktime_to_us(pvt->timeout));
|
||||
ret = wait_for_completion_timeout(&cache->conversion, timeout);
|
||||
|
||||
pvt_update(pvt->regs + PVT_CTRL, PVT_CTRL_EN, 0);
|
||||
pvt_update(pvt->regs + PVT_INTR_MASK, PVT_INTR_DVALID,
|
||||
@ -509,6 +518,9 @@ static int pvt_read_data(struct pvt_hwmon *pvt, enum pvt_sensor_type type,
|
||||
|
||||
mutex_unlock(&pvt->iface_mtx);
|
||||
|
||||
if (!ret)
|
||||
return -ETIMEDOUT;
|
||||
|
||||
if (type == PVT_TEMP)
|
||||
*val = pvt_calc_poly(&poly_N_to_temp, data);
|
||||
else
|
||||
@ -654,44 +666,16 @@ static int pvt_write_trim(struct pvt_hwmon *pvt, long val)
|
||||
|
||||
static int pvt_read_timeout(struct pvt_hwmon *pvt, long *val)
|
||||
{
|
||||
unsigned long rate;
|
||||
ktime_t kt;
|
||||
u32 data;
|
||||
int ret;
|
||||
|
||||
rate = clk_get_rate(pvt->clks[PVT_CLOCK_REF].clk);
|
||||
if (!rate)
|
||||
return -ENODEV;
|
||||
|
||||
/*
|
||||
* Don't bother with mutex here, since we just read data from MMIO.
|
||||
* We also have to scale the ticks timeout up to compensate the
|
||||
* ms-ns-data translations.
|
||||
*/
|
||||
data = readl(pvt->regs + PVT_TTIMEOUT) + 1;
|
||||
|
||||
/*
|
||||
* Calculate ref-clock based delay (Ttotal) between two consecutive
|
||||
* data samples of the same sensor. So we first must calculate the
|
||||
* delay introduced by the internal ref-clock timer (Tref * Fclk).
|
||||
* Then add the constant timeout cuased by each conversion latency
|
||||
* (Tmin). The basic formulae for each conversion is following:
|
||||
* Ttotal = Tref * Fclk + Tmin
|
||||
* Note if alarms are enabled the sensors are polled one after
|
||||
* another, so in order to have the delay being applicable for each
|
||||
* sensor the requested value must be equally redistirbuted.
|
||||
*/
|
||||
#if defined(CONFIG_SENSORS_BT1_PVT_ALARMS)
|
||||
kt = ktime_set(PVT_SENSORS_NUM * (u64)data, 0);
|
||||
kt = ktime_divns(kt, rate);
|
||||
kt = ktime_add_ns(kt, PVT_SENSORS_NUM * PVT_TOUT_MIN);
|
||||
#else
|
||||
kt = ktime_set(data, 0);
|
||||
kt = ktime_divns(kt, rate);
|
||||
kt = ktime_add_ns(kt, PVT_TOUT_MIN);
|
||||
#endif
|
||||
ret = mutex_lock_interruptible(&pvt->iface_mtx);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Return the result in msec as hwmon sysfs interface requires. */
|
||||
*val = ktime_to_ms(kt);
|
||||
*val = ktime_to_ms(pvt->timeout);
|
||||
|
||||
mutex_unlock(&pvt->iface_mtx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -699,7 +683,7 @@ static int pvt_read_timeout(struct pvt_hwmon *pvt, long *val)
|
||||
static int pvt_write_timeout(struct pvt_hwmon *pvt, long val)
|
||||
{
|
||||
unsigned long rate;
|
||||
ktime_t kt;
|
||||
ktime_t kt, cache;
|
||||
u32 data;
|
||||
int ret;
|
||||
|
||||
@ -712,7 +696,7 @@ static int pvt_write_timeout(struct pvt_hwmon *pvt, long val)
|
||||
* between all available sensors to have the requested delay
|
||||
* applicable to each individual sensor.
|
||||
*/
|
||||
kt = ms_to_ktime(val);
|
||||
cache = kt = ms_to_ktime(val);
|
||||
#if defined(CONFIG_SENSORS_BT1_PVT_ALARMS)
|
||||
kt = ktime_divns(kt, PVT_SENSORS_NUM);
|
||||
#endif
|
||||
@ -741,6 +725,7 @@ static int pvt_write_timeout(struct pvt_hwmon *pvt, long val)
|
||||
return ret;
|
||||
|
||||
pvt_set_tout(pvt, data);
|
||||
pvt->timeout = cache;
|
||||
|
||||
mutex_unlock(&pvt->iface_mtx);
|
||||
|
||||
@ -982,10 +967,52 @@ static int pvt_request_clks(struct pvt_hwmon *pvt)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void pvt_init_iface(struct pvt_hwmon *pvt)
|
||||
static int pvt_check_pwr(struct pvt_hwmon *pvt)
|
||||
{
|
||||
unsigned long tout;
|
||||
int ret = 0;
|
||||
u32 data;
|
||||
|
||||
/*
|
||||
* Test out the sensor conversion functionality. If it is not done on
|
||||
* time then the domain must have been unpowered and we won't be able
|
||||
* to use the device later in this driver.
|
||||
* Note If the power source is lost during the normal driver work the
|
||||
* data read procedure will either return -ETIMEDOUT (for the
|
||||
* alarm-less driver configuration) or just stop the repeated
|
||||
* conversion. In the later case alas we won't be able to detect the
|
||||
* problem.
|
||||
*/
|
||||
pvt_update(pvt->regs + PVT_INTR_MASK, PVT_INTR_ALL, PVT_INTR_ALL);
|
||||
pvt_update(pvt->regs + PVT_CTRL, PVT_CTRL_EN, PVT_CTRL_EN);
|
||||
pvt_set_tout(pvt, 0);
|
||||
readl(pvt->regs + PVT_DATA);
|
||||
|
||||
tout = PVT_TOUT_MIN / NSEC_PER_USEC;
|
||||
usleep_range(tout, 2 * tout);
|
||||
|
||||
data = readl(pvt->regs + PVT_DATA);
|
||||
if (!(data & PVT_DATA_VALID)) {
|
||||
ret = -ENODEV;
|
||||
dev_err(pvt->dev, "Sensor is powered down\n");
|
||||
}
|
||||
|
||||
pvt_update(pvt->regs + PVT_CTRL, PVT_CTRL_EN, 0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int pvt_init_iface(struct pvt_hwmon *pvt)
|
||||
{
|
||||
unsigned long rate;
|
||||
u32 trim, temp;
|
||||
|
||||
rate = clk_get_rate(pvt->clks[PVT_CLOCK_REF].clk);
|
||||
if (!rate) {
|
||||
dev_err(pvt->dev, "Invalid reference clock rate\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/*
|
||||
* Make sure all interrupts and controller are disabled so not to
|
||||
* accidentally have ISR executed before the driver data is fully
|
||||
@ -1000,12 +1027,37 @@ static void pvt_init_iface(struct pvt_hwmon *pvt)
|
||||
pvt_set_mode(pvt, pvt_info[pvt->sensor].mode);
|
||||
pvt_set_tout(pvt, PVT_TOUT_DEF);
|
||||
|
||||
/*
|
||||
* Preserve the current ref-clock based delay (Ttotal) between the
|
||||
* sensors data samples in the driver data so not to recalculate it
|
||||
* each time on the data requests and timeout reads. It consists of the
|
||||
* delay introduced by the internal ref-clock timer (N / Fclk) and the
|
||||
* constant timeout caused by each conversion latency (Tmin):
|
||||
* Ttotal = N / Fclk + Tmin
|
||||
* If alarms are enabled the sensors are polled one after another and
|
||||
* in order to get the next measurement of a particular sensor the
|
||||
* caller will have to wait for at most until all the others are
|
||||
* polled. In that case the formulae will look a bit different:
|
||||
* Ttotal = 5 * (N / Fclk + Tmin)
|
||||
*/
|
||||
#if defined(CONFIG_SENSORS_BT1_PVT_ALARMS)
|
||||
pvt->timeout = ktime_set(PVT_SENSORS_NUM * PVT_TOUT_DEF, 0);
|
||||
pvt->timeout = ktime_divns(pvt->timeout, rate);
|
||||
pvt->timeout = ktime_add_ns(pvt->timeout, PVT_SENSORS_NUM * PVT_TOUT_MIN);
|
||||
#else
|
||||
pvt->timeout = ktime_set(PVT_TOUT_DEF, 0);
|
||||
pvt->timeout = ktime_divns(pvt->timeout, rate);
|
||||
pvt->timeout = ktime_add_ns(pvt->timeout, PVT_TOUT_MIN);
|
||||
#endif
|
||||
|
||||
trim = PVT_TRIM_DEF;
|
||||
if (!of_property_read_u32(pvt->dev->of_node,
|
||||
"baikal,pvt-temp-offset-millicelsius", &temp))
|
||||
trim = pvt_calc_trim(temp);
|
||||
|
||||
pvt_set_trim(pvt, trim);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pvt_request_irq(struct pvt_hwmon *pvt)
|
||||
@ -1109,7 +1161,13 @@ static int pvt_probe(struct platform_device *pdev)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
pvt_init_iface(pvt);
|
||||
ret = pvt_check_pwr(pvt);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = pvt_init_iface(pvt);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = pvt_request_irq(pvt);
|
||||
if (ret)
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include <linux/completion.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/ktime.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/seqlock.h>
|
||||
|
||||
@ -201,6 +202,7 @@ struct pvt_cache {
|
||||
* if alarms are disabled).
|
||||
* @sensor: current PVT sensor the data conversion is being performed for.
|
||||
* @cache: data cache descriptor.
|
||||
* @timeout: conversion timeout cache.
|
||||
*/
|
||||
struct pvt_hwmon {
|
||||
struct device *dev;
|
||||
@ -214,6 +216,7 @@ struct pvt_hwmon {
|
||||
struct mutex iface_mtx;
|
||||
enum pvt_sensor_type sensor;
|
||||
struct pvt_cache cache[PVT_SENSORS_NUM];
|
||||
ktime_t timeout;
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -2461,8 +2461,9 @@ static int dme1737_i2c_detect(struct i2c_client *client,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dme1737_i2c_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
static const struct i2c_device_id dme1737_id[];
|
||||
|
||||
static int dme1737_i2c_probe(struct i2c_client *client)
|
||||
{
|
||||
struct dme1737_data *data;
|
||||
struct device *dev = &client->dev;
|
||||
@ -2473,7 +2474,7 @@ static int dme1737_i2c_probe(struct i2c_client *client,
|
||||
return -ENOMEM;
|
||||
|
||||
i2c_set_clientdata(client, data);
|
||||
data->type = id->driver_data;
|
||||
data->type = i2c_match_id(dme1737_id, client)->driver_data;
|
||||
data->client = client;
|
||||
data->name = client->name;
|
||||
mutex_init(&data->update_lock);
|
||||
@ -2529,7 +2530,7 @@ static struct i2c_driver dme1737_i2c_driver = {
|
||||
.driver = {
|
||||
.name = "dme1737",
|
||||
},
|
||||
.probe = dme1737_i2c_probe,
|
||||
.probe_new = dme1737_i2c_probe,
|
||||
.remove = dme1737_i2c_remove,
|
||||
.id_table = dme1737_id,
|
||||
.detect = dme1737_i2c_detect,
|
||||
|
@ -342,8 +342,9 @@ static const struct attribute_group ds1621_group = {
|
||||
};
|
||||
__ATTRIBUTE_GROUPS(ds1621);
|
||||
|
||||
static int ds1621_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
static const struct i2c_device_id ds1621_id[];
|
||||
|
||||
static int ds1621_probe(struct i2c_client *client)
|
||||
{
|
||||
struct ds1621_data *data;
|
||||
struct device *hwmon_dev;
|
||||
@ -355,7 +356,7 @@ static int ds1621_probe(struct i2c_client *client,
|
||||
|
||||
mutex_init(&data->update_lock);
|
||||
|
||||
data->kind = id->driver_data;
|
||||
data->kind = i2c_match_id(ds1621_id, client)->driver_data;
|
||||
data->client = client;
|
||||
|
||||
/* Initialize the DS1621 chip */
|
||||
@ -383,7 +384,7 @@ static struct i2c_driver ds1621_driver = {
|
||||
.driver = {
|
||||
.name = "ds1621",
|
||||
},
|
||||
.probe = ds1621_probe,
|
||||
.probe_new = ds1621_probe,
|
||||
.id_table = ds1621_id,
|
||||
};
|
||||
|
||||
|
@ -211,8 +211,7 @@ static struct attribute *ds620_attrs[] = {
|
||||
|
||||
ATTRIBUTE_GROUPS(ds620);
|
||||
|
||||
static int ds620_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
static int ds620_probe(struct i2c_client *client)
|
||||
{
|
||||
struct device *dev = &client->dev;
|
||||
struct device *hwmon_dev;
|
||||
@ -246,7 +245,7 @@ static struct i2c_driver ds620_driver = {
|
||||
.driver = {
|
||||
.name = "ds620",
|
||||
},
|
||||
.probe = ds620_probe,
|
||||
.probe_new = ds620_probe,
|
||||
.id_table = ds620_id,
|
||||
};
|
||||
|
||||
|
@ -386,11 +386,13 @@ static const struct regmap_config emc1403_regmap_config = {
|
||||
.volatile_reg = emc1403_regmap_is_volatile,
|
||||
};
|
||||
|
||||
static int emc1403_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
static const struct i2c_device_id emc1403_idtable[];
|
||||
|
||||
static int emc1403_probe(struct i2c_client *client)
|
||||
{
|
||||
struct thermal_data *data;
|
||||
struct device *hwmon_dev;
|
||||
const struct i2c_device_id *id = i2c_match_id(emc1403_idtable, client);
|
||||
|
||||
data = devm_kzalloc(&client->dev, sizeof(struct thermal_data),
|
||||
GFP_KERNEL);
|
||||
@ -452,7 +454,7 @@ static struct i2c_driver sensor_emc1403 = {
|
||||
.name = "emc1403",
|
||||
},
|
||||
.detect = emc1403_detect,
|
||||
.probe = emc1403_probe,
|
||||
.probe_new = emc1403_probe,
|
||||
.id_table = emc1403_idtable,
|
||||
.address_list = emc1403_address_list,
|
||||
};
|
||||
|
@ -551,7 +551,7 @@ static const struct attribute_group emc2103_temp4_group = {
|
||||
};
|
||||
|
||||
static int
|
||||
emc2103_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
||||
emc2103_probe(struct i2c_client *client)
|
||||
{
|
||||
struct emc2103_data *data;
|
||||
struct device *hwmon_dev;
|
||||
@ -653,7 +653,7 @@ static struct i2c_driver emc2103_driver = {
|
||||
.driver = {
|
||||
.name = "emc2103",
|
||||
},
|
||||
.probe = emc2103_probe,
|
||||
.probe_new = emc2103_probe,
|
||||
.id_table = emc2103_ids,
|
||||
.detect = emc2103_detect,
|
||||
.address_list = normal_i2c,
|
||||
|
@ -444,8 +444,7 @@ static int emc6w201_detect(struct i2c_client *client,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int emc6w201_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
static int emc6w201_probe(struct i2c_client *client)
|
||||
{
|
||||
struct device *dev = &client->dev;
|
||||
struct emc6w201_data *data;
|
||||
@ -475,7 +474,7 @@ static struct i2c_driver emc6w201_driver = {
|
||||
.driver = {
|
||||
.name = "emc6w201",
|
||||
},
|
||||
.probe = emc6w201_probe,
|
||||
.probe_new = emc6w201_probe,
|
||||
.id_table = emc6w201_id,
|
||||
.detect = emc6w201_detect,
|
||||
.address_list = normal_i2c,
|
||||
|
@ -113,8 +113,7 @@ struct f75375_data {
|
||||
|
||||
static int f75375_detect(struct i2c_client *client,
|
||||
struct i2c_board_info *info);
|
||||
static int f75375_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id);
|
||||
static int f75375_probe(struct i2c_client *client);
|
||||
static int f75375_remove(struct i2c_client *client);
|
||||
|
||||
static const struct i2c_device_id f75375_id[] = {
|
||||
@ -130,7 +129,7 @@ static struct i2c_driver f75375_driver = {
|
||||
.driver = {
|
||||
.name = "f75375",
|
||||
},
|
||||
.probe = f75375_probe,
|
||||
.probe_new = f75375_probe,
|
||||
.remove = f75375_remove,
|
||||
.id_table = f75375_id,
|
||||
.detect = f75375_detect,
|
||||
@ -814,8 +813,7 @@ static void f75375_init(struct i2c_client *client, struct f75375_data *data,
|
||||
|
||||
}
|
||||
|
||||
static int f75375_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
static int f75375_probe(struct i2c_client *client)
|
||||
{
|
||||
struct f75375_data *data;
|
||||
struct f75375s_platform_data *f75375s_pdata =
|
||||
@ -832,7 +830,7 @@ static int f75375_probe(struct i2c_client *client,
|
||||
|
||||
i2c_set_clientdata(client, data);
|
||||
mutex_init(&data->update_lock);
|
||||
data->kind = id->driver_data;
|
||||
data->kind = i2c_match_id(f75375_id, client)->driver_data;
|
||||
|
||||
err = sysfs_create_group(&client->dev.kobj, &f75375_group);
|
||||
if (err)
|
||||
|
@ -214,8 +214,7 @@ static const int FSCHMD_NO_TEMP_SENSORS[7] = { 3, 3, 4, 3, 5, 5, 11 };
|
||||
* Functions declarations
|
||||
*/
|
||||
|
||||
static int fschmd_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id);
|
||||
static int fschmd_probe(struct i2c_client *client);
|
||||
static int fschmd_detect(struct i2c_client *client,
|
||||
struct i2c_board_info *info);
|
||||
static int fschmd_remove(struct i2c_client *client);
|
||||
@ -242,7 +241,7 @@ static struct i2c_driver fschmd_driver = {
|
||||
.driver = {
|
||||
.name = "fschmd",
|
||||
},
|
||||
.probe = fschmd_probe,
|
||||
.probe_new = fschmd_probe,
|
||||
.remove = fschmd_remove,
|
||||
.id_table = fschmd_id,
|
||||
.detect = fschmd_detect,
|
||||
@ -1081,15 +1080,14 @@ static int fschmd_detect(struct i2c_client *client,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fschmd_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
static int fschmd_probe(struct i2c_client *client)
|
||||
{
|
||||
struct fschmd_data *data;
|
||||
const char * const names[7] = { "Poseidon", "Hermes", "Scylla",
|
||||
"Heracles", "Heimdall", "Hades", "Syleus" };
|
||||
const int watchdog_minors[] = { WATCHDOG_MINOR, 212, 213, 214, 215 };
|
||||
int i, err;
|
||||
enum chips kind = id->driver_data;
|
||||
enum chips kind = i2c_match_id(fschmd_id, client)->driver_data;
|
||||
|
||||
data = kzalloc(sizeof(struct fschmd_data), GFP_KERNEL);
|
||||
if (!data)
|
||||
|
@ -752,7 +752,7 @@ static int fts_remove(struct i2c_client *client)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fts_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
||||
static int fts_probe(struct i2c_client *client)
|
||||
{
|
||||
u8 revision;
|
||||
struct fts_data *data;
|
||||
@ -819,7 +819,7 @@ static struct i2c_driver fts_driver = {
|
||||
.name = "ftsteutates",
|
||||
},
|
||||
.id_table = fts_id,
|
||||
.probe = fts_probe,
|
||||
.probe_new = fts_probe,
|
||||
.remove = fts_remove,
|
||||
.detect = fts_detect,
|
||||
.address_list = normal_i2c,
|
||||
|
@ -170,8 +170,7 @@ ATTRIBUTE_GROUPS(g760a);
|
||||
* new-style driver model code
|
||||
*/
|
||||
|
||||
static int g760a_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
static int g760a_probe(struct i2c_client *client)
|
||||
{
|
||||
struct device *dev = &client->dev;
|
||||
struct g760a_data *data;
|
||||
@ -207,7 +206,7 @@ static struct i2c_driver g760a_driver = {
|
||||
.driver = {
|
||||
.name = "g760a",
|
||||
},
|
||||
.probe = g760a_probe,
|
||||
.probe_new = g760a_probe,
|
||||
.id_table = g760a_id,
|
||||
};
|
||||
|
||||
|
@ -1033,7 +1033,7 @@ static inline int g762_fan_init(struct device *dev)
|
||||
data->fan_cmd1);
|
||||
}
|
||||
|
||||
static int g762_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
||||
static int g762_probe(struct i2c_client *client)
|
||||
{
|
||||
struct device *dev = &client->dev;
|
||||
struct device *hwmon_dev;
|
||||
@ -1079,7 +1079,7 @@ static struct i2c_driver g762_driver = {
|
||||
.name = DRVNAME,
|
||||
.of_match_table = of_match_ptr(g762_dt_match),
|
||||
},
|
||||
.probe = g762_probe,
|
||||
.probe_new = g762_probe,
|
||||
.id_table = g762_id,
|
||||
};
|
||||
|
||||
|
@ -611,8 +611,7 @@ static void gl518_init_client(struct i2c_client *client)
|
||||
gl518_write_value(client, GL518_REG_CONF, 0x40 | regvalue);
|
||||
}
|
||||
|
||||
static int gl518_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
static int gl518_probe(struct i2c_client *client)
|
||||
{
|
||||
struct device *dev = &client->dev;
|
||||
struct device *hwmon_dev;
|
||||
@ -653,7 +652,7 @@ static struct i2c_driver gl518_driver = {
|
||||
.driver = {
|
||||
.name = "gl518sm",
|
||||
},
|
||||
.probe = gl518_probe,
|
||||
.probe_new = gl518_probe,
|
||||
.id_table = gl518_id,
|
||||
.detect = gl518_detect,
|
||||
.address_list = normal_i2c,
|
||||
|
@ -854,8 +854,7 @@ static void gl520_init_client(struct i2c_client *client)
|
||||
gl520_write_value(client, GL520_REG_BEEP_MASK, data->beep_mask);
|
||||
}
|
||||
|
||||
static int gl520_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
static int gl520_probe(struct i2c_client *client)
|
||||
{
|
||||
struct device *dev = &client->dev;
|
||||
struct device *hwmon_dev;
|
||||
@ -896,7 +895,7 @@ static struct i2c_driver gl520_driver = {
|
||||
.driver = {
|
||||
.name = "gl520sm",
|
||||
},
|
||||
.probe = gl520_probe,
|
||||
.probe_new = gl520_probe,
|
||||
.id_table = gl520_id,
|
||||
.detect = gl520_detect,
|
||||
.address_list = normal_i2c,
|
||||
|
@ -17,6 +17,7 @@
|
||||
|
||||
#define GSC_HWMON_MAX_TEMP_CH 16
|
||||
#define GSC_HWMON_MAX_IN_CH 16
|
||||
#define GSC_HWMON_MAX_FAN_CH 16
|
||||
|
||||
#define GSC_HWMON_RESOLUTION 12
|
||||
#define GSC_HWMON_VREF 2500
|
||||
@ -27,11 +28,14 @@ struct gsc_hwmon_data {
|
||||
struct regmap *regmap;
|
||||
const struct gsc_hwmon_channel *temp_ch[GSC_HWMON_MAX_TEMP_CH];
|
||||
const struct gsc_hwmon_channel *in_ch[GSC_HWMON_MAX_IN_CH];
|
||||
const struct gsc_hwmon_channel *fan_ch[GSC_HWMON_MAX_FAN_CH];
|
||||
u32 temp_config[GSC_HWMON_MAX_TEMP_CH + 1];
|
||||
u32 in_config[GSC_HWMON_MAX_IN_CH + 1];
|
||||
u32 fan_config[GSC_HWMON_MAX_FAN_CH + 1];
|
||||
struct hwmon_channel_info temp_info;
|
||||
struct hwmon_channel_info in_info;
|
||||
const struct hwmon_channel_info *info[3];
|
||||
struct hwmon_channel_info fan_info;
|
||||
const struct hwmon_channel_info *info[4];
|
||||
struct hwmon_chip_info chip;
|
||||
};
|
||||
|
||||
@ -155,6 +159,9 @@ gsc_hwmon_read(struct device *dev, enum hwmon_sensor_types type, u32 attr,
|
||||
case hwmon_temp:
|
||||
ch = hwmon->temp_ch[channel];
|
||||
break;
|
||||
case hwmon_fan:
|
||||
ch = hwmon->fan_ch[channel];
|
||||
break;
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
@ -187,6 +194,9 @@ gsc_hwmon_read(struct device *dev, enum hwmon_sensor_types type, u32 attr,
|
||||
/* adjust by uV offset */
|
||||
tmp += ch->mvoffset;
|
||||
break;
|
||||
case mode_fan:
|
||||
tmp *= 30; /* convert to revolutions per minute */
|
||||
break;
|
||||
case mode_voltage_24bit:
|
||||
case mode_voltage_16bit:
|
||||
/* no adjustment needed */
|
||||
@ -211,6 +221,9 @@ gsc_hwmon_read_string(struct device *dev, enum hwmon_sensor_types type,
|
||||
case hwmon_temp:
|
||||
*buf = hwmon->temp_ch[channel]->name;
|
||||
break;
|
||||
case hwmon_fan:
|
||||
*buf = hwmon->fan_ch[channel]->name;
|
||||
break;
|
||||
default:
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
@ -304,7 +317,7 @@ static int gsc_hwmon_probe(struct platform_device *pdev)
|
||||
struct gsc_hwmon_platform_data *pdata = dev_get_platdata(dev);
|
||||
struct gsc_hwmon_data *hwmon;
|
||||
const struct attribute_group **groups;
|
||||
int i, i_in, i_temp;
|
||||
int i, i_in, i_temp, i_fan;
|
||||
|
||||
if (!pdata) {
|
||||
pdata = gsc_hwmon_get_devtree_pdata(dev);
|
||||
@ -324,7 +337,7 @@ static int gsc_hwmon_probe(struct platform_device *pdev)
|
||||
if (IS_ERR(hwmon->regmap))
|
||||
return PTR_ERR(hwmon->regmap);
|
||||
|
||||
for (i = 0, i_in = 0, i_temp = 0; i < hwmon->pdata->nchannels; i++) {
|
||||
for (i = 0, i_in = 0, i_temp = 0, i_fan = 0; i < hwmon->pdata->nchannels; i++) {
|
||||
const struct gsc_hwmon_channel *ch = &pdata->channels[i];
|
||||
|
||||
switch (ch->mode) {
|
||||
@ -338,6 +351,16 @@ static int gsc_hwmon_probe(struct platform_device *pdev)
|
||||
HWMON_T_LABEL;
|
||||
i_temp++;
|
||||
break;
|
||||
case mode_fan:
|
||||
if (i_fan == GSC_HWMON_MAX_FAN_CH) {
|
||||
dev_err(gsc->dev, "too many fan channels\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
hwmon->fan_ch[i_fan] = ch;
|
||||
hwmon->fan_config[i_fan] = HWMON_F_INPUT |
|
||||
HWMON_F_LABEL;
|
||||
i_fan++;
|
||||
break;
|
||||
case mode_voltage_24bit:
|
||||
case mode_voltage_16bit:
|
||||
case mode_voltage_raw:
|
||||
@ -361,10 +384,13 @@ static int gsc_hwmon_probe(struct platform_device *pdev)
|
||||
hwmon->chip.info = hwmon->info;
|
||||
hwmon->info[0] = &hwmon->temp_info;
|
||||
hwmon->info[1] = &hwmon->in_info;
|
||||
hwmon->info[2] = &hwmon->fan_info;
|
||||
hwmon->temp_info.type = hwmon_temp;
|
||||
hwmon->temp_info.config = hwmon->temp_config;
|
||||
hwmon->in_info.type = hwmon_in;
|
||||
hwmon->in_info.config = hwmon->in_config;
|
||||
hwmon->fan_info.type = hwmon_fan;
|
||||
hwmon->fan_info.config = hwmon->fan_config;
|
||||
|
||||
groups = pdata->fan_base ? gsc_hwmon_groups : NULL;
|
||||
hwmon_dev = devm_hwmon_device_register_with_info(dev,
|
||||
|
@ -204,8 +204,7 @@ static struct attribute *hih6130_attrs[] = {
|
||||
|
||||
ATTRIBUTE_GROUPS(hih6130);
|
||||
|
||||
static int hih6130_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
static int hih6130_probe(struct i2c_client *client)
|
||||
{
|
||||
struct device *dev = &client->dev;
|
||||
struct hih6130 *hih6130;
|
||||
@ -250,7 +249,7 @@ static struct i2c_driver hih6130_driver = {
|
||||
.name = "hih6130",
|
||||
.of_match_table = of_match_ptr(hih6130_of_match),
|
||||
},
|
||||
.probe = hih6130_probe,
|
||||
.probe_new = hih6130_probe,
|
||||
.id_table = hih6130_id,
|
||||
};
|
||||
|
||||
|
@ -431,6 +431,8 @@ static const char * const hwmon_temp_attr_templates[] = {
|
||||
[hwmon_temp_lowest] = "temp%d_lowest",
|
||||
[hwmon_temp_highest] = "temp%d_highest",
|
||||
[hwmon_temp_reset_history] = "temp%d_reset_history",
|
||||
[hwmon_temp_rated_min] = "temp%d_rated_min",
|
||||
[hwmon_temp_rated_max] = "temp%d_rated_max",
|
||||
};
|
||||
|
||||
static const char * const hwmon_in_attr_templates[] = {
|
||||
@ -450,6 +452,8 @@ static const char * const hwmon_in_attr_templates[] = {
|
||||
[hwmon_in_max_alarm] = "in%d_max_alarm",
|
||||
[hwmon_in_lcrit_alarm] = "in%d_lcrit_alarm",
|
||||
[hwmon_in_crit_alarm] = "in%d_crit_alarm",
|
||||
[hwmon_in_rated_min] = "in%d_rated_min",
|
||||
[hwmon_in_rated_max] = "in%d_rated_max",
|
||||
};
|
||||
|
||||
static const char * const hwmon_curr_attr_templates[] = {
|
||||
@ -469,6 +473,8 @@ static const char * const hwmon_curr_attr_templates[] = {
|
||||
[hwmon_curr_max_alarm] = "curr%d_max_alarm",
|
||||
[hwmon_curr_lcrit_alarm] = "curr%d_lcrit_alarm",
|
||||
[hwmon_curr_crit_alarm] = "curr%d_crit_alarm",
|
||||
[hwmon_curr_rated_min] = "curr%d_rated_min",
|
||||
[hwmon_curr_rated_max] = "curr%d_rated_max",
|
||||
};
|
||||
|
||||
static const char * const hwmon_power_attr_templates[] = {
|
||||
@ -501,6 +507,8 @@ static const char * const hwmon_power_attr_templates[] = {
|
||||
[hwmon_power_max_alarm] = "power%d_max_alarm",
|
||||
[hwmon_power_lcrit_alarm] = "power%d_lcrit_alarm",
|
||||
[hwmon_power_crit_alarm] = "power%d_crit_alarm",
|
||||
[hwmon_power_rated_min] = "power%d_rated_min",
|
||||
[hwmon_power_rated_max] = "power%d_rated_max",
|
||||
};
|
||||
|
||||
static const char * const hwmon_energy_attr_templates[] = {
|
||||
@ -519,6 +527,8 @@ static const char * const hwmon_humidity_attr_templates[] = {
|
||||
[hwmon_humidity_max_hyst] = "humidity%d_max_hyst",
|
||||
[hwmon_humidity_alarm] = "humidity%d_alarm",
|
||||
[hwmon_humidity_fault] = "humidity%d_fault",
|
||||
[hwmon_humidity_rated_min] = "humidity%d_rated_min",
|
||||
[hwmon_humidity_rated_max] = "humidity%d_rated_max",
|
||||
};
|
||||
|
||||
static const char * const hwmon_fan_attr_templates[] = {
|
||||
|
@ -531,8 +531,7 @@ static int ina209_init_client(struct i2c_client *client,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ina209_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
static int ina209_probe(struct i2c_client *client)
|
||||
{
|
||||
struct i2c_adapter *adapter = client->adapter;
|
||||
struct ina209_data *data;
|
||||
@ -597,7 +596,7 @@ static struct i2c_driver ina209_driver = {
|
||||
.name = "ina209",
|
||||
.of_match_table = of_match_ptr(ina209_of_match),
|
||||
},
|
||||
.probe = ina209_probe,
|
||||
.probe_new = ina209_probe,
|
||||
.remove = ina209_remove,
|
||||
.id_table = ina209_id,
|
||||
};
|
||||
|
@ -614,8 +614,9 @@ static const struct attribute_group ina226_group = {
|
||||
.attrs = ina226_attrs,
|
||||
};
|
||||
|
||||
static int ina2xx_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
static const struct i2c_device_id ina2xx_id[];
|
||||
|
||||
static int ina2xx_probe(struct i2c_client *client)
|
||||
{
|
||||
struct device *dev = &client->dev;
|
||||
struct ina2xx_data *data;
|
||||
@ -627,7 +628,7 @@ static int ina2xx_probe(struct i2c_client *client,
|
||||
if (client->dev.of_node)
|
||||
chip = (enum ina2xx_ids)of_device_get_match_data(&client->dev);
|
||||
else
|
||||
chip = id->driver_data;
|
||||
chip = i2c_match_id(ina2xx_id, client)->driver_data;
|
||||
|
||||
data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
|
||||
if (!data)
|
||||
@ -717,7 +718,7 @@ static struct i2c_driver ina2xx_driver = {
|
||||
.name = "ina2xx",
|
||||
.of_match_table = of_match_ptr(ina2xx_of_match),
|
||||
},
|
||||
.probe = ina2xx_probe,
|
||||
.probe_new = ina2xx_probe,
|
||||
.id_table = ina2xx_id,
|
||||
};
|
||||
|
||||
|
@ -822,8 +822,7 @@ static int ina3221_probe_from_dt(struct device *dev, struct ina3221_data *ina)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ina3221_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
static int ina3221_probe(struct i2c_client *client)
|
||||
{
|
||||
struct device *dev = &client->dev;
|
||||
struct ina3221_data *ina;
|
||||
@ -1016,7 +1015,7 @@ static const struct i2c_device_id ina3221_ids[] = {
|
||||
MODULE_DEVICE_TABLE(i2c, ina3221_ids);
|
||||
|
||||
static struct i2c_driver ina3221_i2c_driver = {
|
||||
.probe = ina3221_probe,
|
||||
.probe_new = ina3221_probe,
|
||||
.remove = ina3221_remove,
|
||||
.driver = {
|
||||
.name = INA3221_DRIVER_NAME,
|
||||
|
334
drivers/hwmon/intel-m10-bmc-hwmon.c
Normal file
334
drivers/hwmon/intel-m10-bmc-hwmon.c
Normal file
@ -0,0 +1,334 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Intel MAX 10 BMC HWMON Driver
|
||||
*
|
||||
* Copyright (C) 2018-2020 Intel Corporation. All rights reserved.
|
||||
*
|
||||
*/
|
||||
#include <linux/device.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/mfd/intel-m10-bmc.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
struct m10bmc_sdata {
|
||||
unsigned int reg_input;
|
||||
unsigned int reg_max;
|
||||
unsigned int reg_crit;
|
||||
unsigned int reg_hyst;
|
||||
unsigned int reg_min;
|
||||
unsigned int multiplier;
|
||||
const char *label;
|
||||
};
|
||||
|
||||
struct m10bmc_hwmon_board_data {
|
||||
const struct m10bmc_sdata *tables[hwmon_max];
|
||||
const struct hwmon_channel_info **hinfo;
|
||||
};
|
||||
|
||||
struct m10bmc_hwmon {
|
||||
struct device *dev;
|
||||
struct hwmon_chip_info chip;
|
||||
char *hw_name;
|
||||
struct intel_m10bmc *m10bmc;
|
||||
const struct m10bmc_hwmon_board_data *bdata;
|
||||
};
|
||||
|
||||
static const struct m10bmc_sdata n3000bmc_temp_tbl[] = {
|
||||
{ 0x100, 0x104, 0x108, 0x10c, 0x0, 500, "Board Temperature" },
|
||||
{ 0x110, 0x114, 0x118, 0x0, 0x0, 500, "FPGA Die Temperature" },
|
||||
{ 0x11c, 0x124, 0x120, 0x0, 0x0, 500, "QSFP0 Temperature" },
|
||||
{ 0x12c, 0x134, 0x130, 0x0, 0x0, 500, "QSFP1 Temperature" },
|
||||
{ 0x168, 0x0, 0x0, 0x0, 0x0, 500, "Retimer A Temperature" },
|
||||
{ 0x16c, 0x0, 0x0, 0x0, 0x0, 500, "Retimer A SerDes Temperature" },
|
||||
{ 0x170, 0x0, 0x0, 0x0, 0x0, 500, "Retimer B Temperature" },
|
||||
{ 0x174, 0x0, 0x0, 0x0, 0x0, 500, "Retimer B SerDes Temperature" },
|
||||
};
|
||||
|
||||
static const struct m10bmc_sdata n3000bmc_in_tbl[] = {
|
||||
{ 0x128, 0x0, 0x0, 0x0, 0x0, 1, "QSFP0 Supply Voltage" },
|
||||
{ 0x138, 0x0, 0x0, 0x0, 0x0, 1, "QSFP1 Supply Voltage" },
|
||||
{ 0x13c, 0x0, 0x0, 0x0, 0x0, 1, "FPGA Core Voltage" },
|
||||
{ 0x144, 0x0, 0x0, 0x0, 0x0, 1, "12V Backplane Voltage" },
|
||||
{ 0x14c, 0x0, 0x0, 0x0, 0x0, 1, "1.2V Voltage" },
|
||||
{ 0x150, 0x0, 0x0, 0x0, 0x0, 1, "12V AUX Voltage" },
|
||||
{ 0x158, 0x0, 0x0, 0x0, 0x0, 1, "1.8V Voltage" },
|
||||
{ 0x15c, 0x0, 0x0, 0x0, 0x0, 1, "3.3V Voltage" },
|
||||
};
|
||||
|
||||
static const struct m10bmc_sdata n3000bmc_curr_tbl[] = {
|
||||
{ 0x140, 0x0, 0x0, 0x0, 0x0, 1, "FPGA Core Current" },
|
||||
{ 0x148, 0x0, 0x0, 0x0, 0x0, 1, "12V Backplane Current" },
|
||||
{ 0x154, 0x0, 0x0, 0x0, 0x0, 1, "12V AUX Current" },
|
||||
};
|
||||
|
||||
static const struct m10bmc_sdata n3000bmc_power_tbl[] = {
|
||||
{ 0x160, 0x0, 0x0, 0x0, 0x0, 1000, "Board Power" },
|
||||
};
|
||||
|
||||
static const struct hwmon_channel_info *n3000bmc_hinfo[] = {
|
||||
HWMON_CHANNEL_INFO(temp,
|
||||
HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_MAX_HYST |
|
||||
HWMON_T_CRIT | HWMON_T_CRIT_HYST | HWMON_T_LABEL,
|
||||
HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_CRIT |
|
||||
HWMON_T_LABEL,
|
||||
HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_CRIT |
|
||||
HWMON_T_LABEL,
|
||||
HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_CRIT |
|
||||
HWMON_T_LABEL,
|
||||
HWMON_T_INPUT | HWMON_T_LABEL,
|
||||
HWMON_T_INPUT | HWMON_T_LABEL,
|
||||
HWMON_T_INPUT | HWMON_T_LABEL,
|
||||
HWMON_T_INPUT | HWMON_T_LABEL),
|
||||
HWMON_CHANNEL_INFO(in,
|
||||
HWMON_I_INPUT | HWMON_I_LABEL,
|
||||
HWMON_I_INPUT | HWMON_I_LABEL,
|
||||
HWMON_I_INPUT | HWMON_I_LABEL,
|
||||
HWMON_I_INPUT | HWMON_I_LABEL,
|
||||
HWMON_I_INPUT | HWMON_I_LABEL,
|
||||
HWMON_I_INPUT | HWMON_I_LABEL,
|
||||
HWMON_I_INPUT | HWMON_I_LABEL,
|
||||
HWMON_I_INPUT | HWMON_I_LABEL),
|
||||
HWMON_CHANNEL_INFO(curr,
|
||||
HWMON_C_INPUT | HWMON_C_LABEL,
|
||||
HWMON_C_INPUT | HWMON_C_LABEL,
|
||||
HWMON_C_INPUT | HWMON_C_LABEL),
|
||||
HWMON_CHANNEL_INFO(power,
|
||||
HWMON_P_INPUT | HWMON_P_LABEL),
|
||||
NULL
|
||||
};
|
||||
|
||||
static const struct m10bmc_hwmon_board_data n3000bmc_hwmon_bdata = {
|
||||
.tables = {
|
||||
[hwmon_temp] = n3000bmc_temp_tbl,
|
||||
[hwmon_in] = n3000bmc_in_tbl,
|
||||
[hwmon_curr] = n3000bmc_curr_tbl,
|
||||
[hwmon_power] = n3000bmc_power_tbl,
|
||||
},
|
||||
|
||||
.hinfo = n3000bmc_hinfo,
|
||||
};
|
||||
|
||||
static umode_t
|
||||
m10bmc_hwmon_is_visible(const void *data, enum hwmon_sensor_types type,
|
||||
u32 attr, int channel)
|
||||
{
|
||||
return 0444;
|
||||
}
|
||||
|
||||
static const struct m10bmc_sdata *
|
||||
find_sensor_data(struct m10bmc_hwmon *hw, enum hwmon_sensor_types type,
|
||||
int channel)
|
||||
{
|
||||
const struct m10bmc_sdata *tbl;
|
||||
|
||||
tbl = hw->bdata->tables[type];
|
||||
if (!tbl)
|
||||
return ERR_PTR(-EOPNOTSUPP);
|
||||
|
||||
return &tbl[channel];
|
||||
}
|
||||
|
||||
static int do_sensor_read(struct m10bmc_hwmon *hw,
|
||||
const struct m10bmc_sdata *data,
|
||||
unsigned int regoff, long *val)
|
||||
{
|
||||
unsigned int regval;
|
||||
int ret;
|
||||
|
||||
ret = m10bmc_sys_read(hw->m10bmc, regoff, ®val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* BMC Firmware will return 0xdeadbeef if the sensor value is invalid
|
||||
* at that time. This usually happens on sensor channels which connect
|
||||
* to external pluggable modules, e.g. QSFP temperature and voltage.
|
||||
* When the QSFP is unplugged from cage, driver will get 0xdeadbeef
|
||||
* from their registers.
|
||||
*/
|
||||
if (regval == 0xdeadbeef)
|
||||
return -ENODATA;
|
||||
|
||||
*val = regval * data->multiplier;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int m10bmc_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
|
||||
u32 attr, int channel, long *val)
|
||||
{
|
||||
struct m10bmc_hwmon *hw = dev_get_drvdata(dev);
|
||||
unsigned int reg = 0, reg_hyst = 0;
|
||||
const struct m10bmc_sdata *data;
|
||||
long hyst, value;
|
||||
int ret;
|
||||
|
||||
data = find_sensor_data(hw, type, channel);
|
||||
if (IS_ERR(data))
|
||||
return PTR_ERR(data);
|
||||
|
||||
switch (type) {
|
||||
case hwmon_temp:
|
||||
switch (attr) {
|
||||
case hwmon_temp_input:
|
||||
reg = data->reg_input;
|
||||
break;
|
||||
case hwmon_temp_max_hyst:
|
||||
reg_hyst = data->reg_hyst;
|
||||
fallthrough;
|
||||
case hwmon_temp_max:
|
||||
reg = data->reg_max;
|
||||
break;
|
||||
case hwmon_temp_crit_hyst:
|
||||
reg_hyst = data->reg_hyst;
|
||||
fallthrough;
|
||||
case hwmon_temp_crit:
|
||||
reg = data->reg_crit;
|
||||
break;
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
break;
|
||||
case hwmon_in:
|
||||
switch (attr) {
|
||||
case hwmon_in_input:
|
||||
reg = data->reg_input;
|
||||
break;
|
||||
case hwmon_in_max:
|
||||
reg = data->reg_max;
|
||||
break;
|
||||
case hwmon_in_crit:
|
||||
reg = data->reg_crit;
|
||||
break;
|
||||
case hwmon_in_min:
|
||||
reg = data->reg_min;
|
||||
break;
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
break;
|
||||
case hwmon_curr:
|
||||
switch (attr) {
|
||||
case hwmon_curr_input:
|
||||
reg = data->reg_input;
|
||||
break;
|
||||
case hwmon_curr_max:
|
||||
reg = data->reg_max;
|
||||
break;
|
||||
case hwmon_curr_crit:
|
||||
reg = data->reg_crit;
|
||||
break;
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
break;
|
||||
case hwmon_power:
|
||||
switch (attr) {
|
||||
case hwmon_power_input:
|
||||
reg = data->reg_input;
|
||||
break;
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
if (!reg)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
ret = do_sensor_read(hw, data, reg, &value);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (reg_hyst) {
|
||||
ret = do_sensor_read(hw, data, reg_hyst, &hyst);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
value -= hyst;
|
||||
}
|
||||
|
||||
*val = value;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int m10bmc_hwmon_read_string(struct device *dev,
|
||||
enum hwmon_sensor_types type,
|
||||
u32 attr, int channel, const char **str)
|
||||
{
|
||||
struct m10bmc_hwmon *hw = dev_get_drvdata(dev);
|
||||
const struct m10bmc_sdata *data;
|
||||
|
||||
data = find_sensor_data(hw, type, channel);
|
||||
if (IS_ERR(data))
|
||||
return PTR_ERR(data);
|
||||
|
||||
*str = data->label;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct hwmon_ops m10bmc_hwmon_ops = {
|
||||
.is_visible = m10bmc_hwmon_is_visible,
|
||||
.read = m10bmc_hwmon_read,
|
||||
.read_string = m10bmc_hwmon_read_string,
|
||||
};
|
||||
|
||||
static int m10bmc_hwmon_probe(struct platform_device *pdev)
|
||||
{
|
||||
const struct platform_device_id *id = platform_get_device_id(pdev);
|
||||
struct intel_m10bmc *m10bmc = dev_get_drvdata(pdev->dev.parent);
|
||||
struct device *hwmon_dev, *dev = &pdev->dev;
|
||||
struct m10bmc_hwmon *hw;
|
||||
int i;
|
||||
|
||||
hw = devm_kzalloc(dev, sizeof(*hw), GFP_KERNEL);
|
||||
if (!hw)
|
||||
return -ENOMEM;
|
||||
|
||||
hw->dev = dev;
|
||||
hw->m10bmc = m10bmc;
|
||||
hw->bdata = (const struct m10bmc_hwmon_board_data *)id->driver_data;
|
||||
|
||||
hw->chip.info = hw->bdata->hinfo;
|
||||
hw->chip.ops = &m10bmc_hwmon_ops;
|
||||
|
||||
hw->hw_name = devm_kstrdup(dev, id->name, GFP_KERNEL);
|
||||
if (!hw->hw_name)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; hw->hw_name[i]; i++)
|
||||
if (hwmon_is_bad_char(hw->hw_name[i]))
|
||||
hw->hw_name[i] = '_';
|
||||
|
||||
hwmon_dev = devm_hwmon_device_register_with_info(dev, hw->hw_name,
|
||||
hw, &hw->chip, NULL);
|
||||
return PTR_ERR_OR_ZERO(hwmon_dev);
|
||||
}
|
||||
|
||||
static const struct platform_device_id intel_m10bmc_hwmon_ids[] = {
|
||||
{
|
||||
.name = "n3000bmc-hwmon",
|
||||
.driver_data = (unsigned long)&n3000bmc_hwmon_bdata,
|
||||
},
|
||||
{ }
|
||||
};
|
||||
|
||||
static struct platform_driver intel_m10bmc_hwmon_driver = {
|
||||
.probe = m10bmc_hwmon_probe,
|
||||
.driver = {
|
||||
.name = "intel-m10-bmc-hwmon",
|
||||
},
|
||||
.id_table = intel_m10bmc_hwmon_ids,
|
||||
};
|
||||
module_platform_driver(intel_m10bmc_hwmon_driver);
|
||||
|
||||
MODULE_DEVICE_TABLE(platform, intel_m10bmc_hwmon_ids);
|
||||
MODULE_AUTHOR("Intel Corporation");
|
||||
MODULE_DESCRIPTION("Intel MAX 10 BMC hardware monitor");
|
||||
MODULE_LICENSE("GPL");
|
@ -458,7 +458,7 @@ static const struct hwmon_chip_info jc42_chip_info = {
|
||||
.info = jc42_info,
|
||||
};
|
||||
|
||||
static int jc42_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
||||
static int jc42_probe(struct i2c_client *client)
|
||||
{
|
||||
struct device *dev = &client->dev;
|
||||
struct device *hwmon_dev;
|
||||
@ -581,7 +581,7 @@ static struct i2c_driver jc42_driver = {
|
||||
.pm = JC42_DEV_PM_OPS,
|
||||
.of_match_table = of_match_ptr(jc42_of_ids),
|
||||
},
|
||||
.probe = jc42_probe,
|
||||
.probe_new = jc42_probe,
|
||||
.remove = jc42_remove,
|
||||
.id_table = jc42_id,
|
||||
.detect = jc42_detect,
|
||||
|
@ -21,7 +21,6 @@
|
||||
*/
|
||||
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/init.h>
|
||||
@ -73,22 +72,35 @@ static DEFINE_MUTEX(nb_smu_ind_mutex);
|
||||
#define F15H_M60H_HARDWARE_TEMP_CTRL_OFFSET 0xd8200c64
|
||||
#define F15H_M60H_REPORTED_TEMP_CTRL_OFFSET 0xd8200ca4
|
||||
|
||||
/* F17h M01h Access througn SMN */
|
||||
#define F17H_M01H_REPORTED_TEMP_CTRL_OFFSET 0x00059800
|
||||
/* Common for Zen CPU families (Family 17h and 18h) */
|
||||
#define ZEN_REPORTED_TEMP_CTRL_OFFSET 0x00059800
|
||||
|
||||
#define F17H_M70H_CCD_TEMP(x) (0x00059954 + ((x) * 4))
|
||||
#define F17H_M70H_CCD_TEMP_VALID BIT(11)
|
||||
#define F17H_M70H_CCD_TEMP_MASK GENMASK(10, 0)
|
||||
#define ZEN_CCD_TEMP(x) (0x00059954 + ((x) * 4))
|
||||
#define ZEN_CCD_TEMP_VALID BIT(11)
|
||||
#define ZEN_CCD_TEMP_MASK GENMASK(10, 0)
|
||||
|
||||
#define F17H_M01H_SVI 0x0005A000
|
||||
#define F17H_M01H_SVI_TEL_PLANE0 (F17H_M01H_SVI + 0xc)
|
||||
#define F17H_M01H_SVI_TEL_PLANE1 (F17H_M01H_SVI + 0x10)
|
||||
#define ZEN_CUR_TEMP_SHIFT 21
|
||||
#define ZEN_CUR_TEMP_RANGE_SEL_MASK BIT(19)
|
||||
|
||||
#define CUR_TEMP_SHIFT 21
|
||||
#define CUR_TEMP_RANGE_SEL_MASK BIT(19)
|
||||
#define ZEN_SVI_BASE 0x0005A000
|
||||
|
||||
#define CFACTOR_ICORE 1000000 /* 1A / LSB */
|
||||
#define CFACTOR_ISOC 250000 /* 0.25A / LSB */
|
||||
/* F17h thermal registers through SMN */
|
||||
#define F17H_M01H_SVI_TEL_PLANE0 (ZEN_SVI_BASE + 0xc)
|
||||
#define F17H_M01H_SVI_TEL_PLANE1 (ZEN_SVI_BASE + 0x10)
|
||||
#define F17H_M31H_SVI_TEL_PLANE0 (ZEN_SVI_BASE + 0x14)
|
||||
#define F17H_M31H_SVI_TEL_PLANE1 (ZEN_SVI_BASE + 0x10)
|
||||
|
||||
#define F17H_M01H_CFACTOR_ICORE 1000000 /* 1A / LSB */
|
||||
#define F17H_M01H_CFACTOR_ISOC 250000 /* 0.25A / LSB */
|
||||
#define F17H_M31H_CFACTOR_ICORE 1000000 /* 1A / LSB */
|
||||
#define F17H_M31H_CFACTOR_ISOC 310000 /* 0.31A / LSB */
|
||||
|
||||
/* F19h thermal registers through SMN */
|
||||
#define F19H_M01_SVI_TEL_PLANE0 (ZEN_SVI_BASE + 0x14)
|
||||
#define F19H_M01_SVI_TEL_PLANE1 (ZEN_SVI_BASE + 0x10)
|
||||
|
||||
#define F19H_M01H_CFACTOR_ICORE 1000000 /* 1A / LSB */
|
||||
#define F19H_M01H_CFACTOR_ISOC 310000 /* 0.31A / LSB */
|
||||
|
||||
struct k10temp_data {
|
||||
struct pci_dev *pdev;
|
||||
@ -168,10 +180,10 @@ static void read_tempreg_nb_f15(struct pci_dev *pdev, u32 *regval)
|
||||
F15H_M60H_REPORTED_TEMP_CTRL_OFFSET, regval);
|
||||
}
|
||||
|
||||
static void read_tempreg_nb_f17(struct pci_dev *pdev, u32 *regval)
|
||||
static void read_tempreg_nb_zen(struct pci_dev *pdev, u32 *regval)
|
||||
{
|
||||
amd_smn_read(amd_pci_dev_to_node_id(pdev),
|
||||
F17H_M01H_REPORTED_TEMP_CTRL_OFFSET, regval);
|
||||
ZEN_REPORTED_TEMP_CTRL_OFFSET, regval);
|
||||
}
|
||||
|
||||
static long get_raw_temp(struct k10temp_data *data)
|
||||
@ -180,7 +192,7 @@ static long get_raw_temp(struct k10temp_data *data)
|
||||
long temp;
|
||||
|
||||
data->read_tempreg(data->pdev, ®val);
|
||||
temp = (regval >> CUR_TEMP_SHIFT) * 125;
|
||||
temp = (regval >> ZEN_CUR_TEMP_SHIFT) * 125;
|
||||
if (regval & data->temp_adjust_mask)
|
||||
temp -= 49000;
|
||||
return temp;
|
||||
@ -288,8 +300,8 @@ static int k10temp_read_temp(struct device *dev, u32 attr, int channel,
|
||||
break;
|
||||
case 2 ... 9: /* Tccd{1-8} */
|
||||
amd_smn_read(amd_pci_dev_to_node_id(data->pdev),
|
||||
F17H_M70H_CCD_TEMP(channel - 2), ®val);
|
||||
*val = (regval & F17H_M70H_CCD_TEMP_MASK) * 125 - 49000;
|
||||
ZEN_CCD_TEMP(channel - 2), ®val);
|
||||
*val = (regval & ZEN_CCD_TEMP_MASK) * 125 - 49000;
|
||||
break;
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
@ -416,76 +428,6 @@ static bool has_erratum_319(struct pci_dev *pdev)
|
||||
(boot_cpu_data.x86_model == 4 && boot_cpu_data.x86_stepping <= 2);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
|
||||
static void k10temp_smn_regs_show(struct seq_file *s, struct pci_dev *pdev,
|
||||
u32 addr, int count)
|
||||
{
|
||||
u32 reg;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
if (!(i & 3))
|
||||
seq_printf(s, "0x%06x: ", addr + i * 4);
|
||||
amd_smn_read(amd_pci_dev_to_node_id(pdev), addr + i * 4, ®);
|
||||
seq_printf(s, "%08x ", reg);
|
||||
if ((i & 3) == 3)
|
||||
seq_puts(s, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
static int svi_show(struct seq_file *s, void *unused)
|
||||
{
|
||||
struct k10temp_data *data = s->private;
|
||||
|
||||
k10temp_smn_regs_show(s, data->pdev, F17H_M01H_SVI, 32);
|
||||
return 0;
|
||||
}
|
||||
DEFINE_SHOW_ATTRIBUTE(svi);
|
||||
|
||||
static int thm_show(struct seq_file *s, void *unused)
|
||||
{
|
||||
struct k10temp_data *data = s->private;
|
||||
|
||||
k10temp_smn_regs_show(s, data->pdev,
|
||||
F17H_M01H_REPORTED_TEMP_CTRL_OFFSET, 256);
|
||||
return 0;
|
||||
}
|
||||
DEFINE_SHOW_ATTRIBUTE(thm);
|
||||
|
||||
static void k10temp_debugfs_cleanup(void *ddir)
|
||||
{
|
||||
debugfs_remove_recursive(ddir);
|
||||
}
|
||||
|
||||
static void k10temp_init_debugfs(struct k10temp_data *data)
|
||||
{
|
||||
struct dentry *debugfs;
|
||||
char name[32];
|
||||
|
||||
/* Only show debugfs data for Family 17h/18h CPUs */
|
||||
if (!data->is_zen)
|
||||
return;
|
||||
|
||||
scnprintf(name, sizeof(name), "k10temp-%s", pci_name(data->pdev));
|
||||
|
||||
debugfs = debugfs_create_dir(name, NULL);
|
||||
if (debugfs) {
|
||||
debugfs_create_file("svi", 0444, debugfs, data, &svi_fops);
|
||||
debugfs_create_file("thm", 0444, debugfs, data, &thm_fops);
|
||||
devm_add_action_or_reset(&data->pdev->dev,
|
||||
k10temp_debugfs_cleanup, debugfs);
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static void k10temp_init_debugfs(struct k10temp_data *data)
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static const struct hwmon_channel_info *k10temp_info[] = {
|
||||
HWMON_CHANNEL_INFO(temp,
|
||||
HWMON_T_INPUT | HWMON_T_MAX |
|
||||
@ -528,8 +470,8 @@ static void k10temp_get_ccd_support(struct pci_dev *pdev,
|
||||
|
||||
for (i = 0; i < limit; i++) {
|
||||
amd_smn_read(amd_pci_dev_to_node_id(pdev),
|
||||
F17H_M70H_CCD_TEMP(i), ®val);
|
||||
if (regval & F17H_M70H_CCD_TEMP_VALID)
|
||||
ZEN_CCD_TEMP(i), ®val);
|
||||
if (regval & ZEN_CCD_TEMP_VALID)
|
||||
data->show_temp |= BIT(TCCD_BIT(i));
|
||||
}
|
||||
}
|
||||
@ -565,8 +507,8 @@ static int k10temp_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
data->read_htcreg = read_htcreg_nb_f15;
|
||||
data->read_tempreg = read_tempreg_nb_f15;
|
||||
} else if (boot_cpu_data.x86 == 0x17 || boot_cpu_data.x86 == 0x18) {
|
||||
data->temp_adjust_mask = CUR_TEMP_RANGE_SEL_MASK;
|
||||
data->read_tempreg = read_tempreg_nb_f17;
|
||||
data->temp_adjust_mask = ZEN_CUR_TEMP_RANGE_SEL_MASK;
|
||||
data->read_tempreg = read_tempreg_nb_zen;
|
||||
data->show_temp |= BIT(TDIE_BIT); /* show Tdie */
|
||||
data->is_zen = true;
|
||||
|
||||
@ -578,17 +520,33 @@ static int k10temp_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
data->show_current = !is_threadripper() && !is_epyc();
|
||||
data->svi_addr[0] = F17H_M01H_SVI_TEL_PLANE0;
|
||||
data->svi_addr[1] = F17H_M01H_SVI_TEL_PLANE1;
|
||||
data->cfactor[0] = CFACTOR_ICORE;
|
||||
data->cfactor[1] = CFACTOR_ISOC;
|
||||
data->cfactor[0] = F17H_M01H_CFACTOR_ICORE;
|
||||
data->cfactor[1] = F17H_M01H_CFACTOR_ISOC;
|
||||
k10temp_get_ccd_support(pdev, data, 4);
|
||||
break;
|
||||
case 0x31: /* Zen2 Threadripper */
|
||||
case 0x71: /* Zen2 */
|
||||
data->show_current = !is_threadripper() && !is_epyc();
|
||||
data->cfactor[0] = CFACTOR_ICORE;
|
||||
data->cfactor[1] = CFACTOR_ISOC;
|
||||
data->svi_addr[0] = F17H_M01H_SVI_TEL_PLANE1;
|
||||
data->svi_addr[1] = F17H_M01H_SVI_TEL_PLANE0;
|
||||
data->cfactor[0] = F17H_M31H_CFACTOR_ICORE;
|
||||
data->cfactor[1] = F17H_M31H_CFACTOR_ISOC;
|
||||
data->svi_addr[0] = F17H_M31H_SVI_TEL_PLANE0;
|
||||
data->svi_addr[1] = F17H_M31H_SVI_TEL_PLANE1;
|
||||
k10temp_get_ccd_support(pdev, data, 8);
|
||||
break;
|
||||
}
|
||||
} else if (boot_cpu_data.x86 == 0x19) {
|
||||
data->temp_adjust_mask = ZEN_CUR_TEMP_RANGE_SEL_MASK;
|
||||
data->read_tempreg = read_tempreg_nb_zen;
|
||||
data->show_temp |= BIT(TDIE_BIT);
|
||||
data->is_zen = true;
|
||||
|
||||
switch (boot_cpu_data.x86_model) {
|
||||
case 0x0 ... 0x1: /* Zen3 */
|
||||
data->show_current = true;
|
||||
data->svi_addr[0] = F19H_M01_SVI_TEL_PLANE0;
|
||||
data->svi_addr[1] = F19H_M01_SVI_TEL_PLANE1;
|
||||
data->cfactor[0] = F19H_M01H_CFACTOR_ICORE;
|
||||
data->cfactor[1] = F19H_M01H_CFACTOR_ISOC;
|
||||
k10temp_get_ccd_support(pdev, data, 8);
|
||||
break;
|
||||
}
|
||||
@ -610,12 +568,7 @@ static int k10temp_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
hwmon_dev = devm_hwmon_device_register_with_info(dev, "k10temp", data,
|
||||
&k10temp_chip_info,
|
||||
NULL);
|
||||
if (IS_ERR(hwmon_dev))
|
||||
return PTR_ERR(hwmon_dev);
|
||||
|
||||
k10temp_init_debugfs(data);
|
||||
|
||||
return 0;
|
||||
return PTR_ERR_OR_ZERO(hwmon_dev);
|
||||
}
|
||||
|
||||
static const struct pci_device_id k10temp_id_table[] = {
|
||||
@ -634,6 +587,7 @@ static const struct pci_device_id k10temp_id_table[] = {
|
||||
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_17H_M30H_DF_F3) },
|
||||
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_17H_M60H_DF_F3) },
|
||||
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_17H_M70H_DF_F3) },
|
||||
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_19H_DF_F3) },
|
||||
{ PCI_VDEVICE(HYGON, PCI_DEVICE_ID_AMD_17H_DF_F3) },
|
||||
{}
|
||||
};
|
||||
|
@ -417,8 +417,7 @@ static const struct attribute_group pem_fan_group = {
|
||||
.attrs = pem_fan_attributes,
|
||||
};
|
||||
|
||||
static int pem_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
static int pem_probe(struct i2c_client *client)
|
||||
{
|
||||
struct i2c_adapter *adapter = client->adapter;
|
||||
struct device *dev = &client->dev;
|
||||
@ -512,7 +511,7 @@ static struct i2c_driver pem_driver = {
|
||||
.driver = {
|
||||
.name = "lineage_pem",
|
||||
},
|
||||
.probe = pem_probe,
|
||||
.probe_new = pem_probe,
|
||||
.id_table = pem_id,
|
||||
};
|
||||
|
||||
|
@ -1087,8 +1087,9 @@ static void lm63_init_client(struct lm63_data *data)
|
||||
(data->config_fan & 0x20) ? "manual" : "auto");
|
||||
}
|
||||
|
||||
static int lm63_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
static const struct i2c_device_id lm63_id[];
|
||||
|
||||
static int lm63_probe(struct i2c_client *client)
|
||||
{
|
||||
struct device *dev = &client->dev;
|
||||
struct device *hwmon_dev;
|
||||
@ -1106,7 +1107,7 @@ static int lm63_probe(struct i2c_client *client,
|
||||
if (client->dev.of_node)
|
||||
data->kind = (enum chips)of_device_get_match_data(&client->dev);
|
||||
else
|
||||
data->kind = id->driver_data;
|
||||
data->kind = i2c_match_id(lm63_id, client)->driver_data;
|
||||
if (data->kind == lm64)
|
||||
data->temp2_offset = 16000;
|
||||
|
||||
@ -1163,7 +1164,7 @@ static struct i2c_driver lm63_driver = {
|
||||
.name = "lm63",
|
||||
.of_match_table = of_match_ptr(lm63_of_match),
|
||||
},
|
||||
.probe = lm63_probe,
|
||||
.probe_new = lm63_probe,
|
||||
.id_table = lm63_id,
|
||||
.detect = lm63_detect,
|
||||
.address_list = normal_i2c,
|
||||
|
@ -190,7 +190,7 @@ ATTRIBUTE_GROUPS(lm73);
|
||||
/* device probe and removal */
|
||||
|
||||
static int
|
||||
lm73_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
||||
lm73_probe(struct i2c_client *client)
|
||||
{
|
||||
struct device *dev = &client->dev;
|
||||
struct device *hwmon_dev;
|
||||
@ -277,7 +277,7 @@ static struct i2c_driver lm73_driver = {
|
||||
.name = "lm73",
|
||||
.of_match_table = lm73_of_match,
|
||||
},
|
||||
.probe = lm73_probe,
|
||||
.probe_new = lm73_probe,
|
||||
.id_table = lm73_ids,
|
||||
.detect = lm73_detect,
|
||||
.address_list = normal_i2c,
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include <linux/of.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/util_macros.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include "lm75.h"
|
||||
|
||||
/*
|
||||
@ -101,6 +102,7 @@ static const unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, 0x4c,
|
||||
struct lm75_data {
|
||||
struct i2c_client *client;
|
||||
struct regmap *regmap;
|
||||
struct regulator *vs;
|
||||
u8 orig_conf;
|
||||
u8 current_conf;
|
||||
u8 resolution; /* In bits, 9 to 16 */
|
||||
@ -534,6 +536,13 @@ static const struct regmap_config lm75_regmap_config = {
|
||||
.use_single_write = true,
|
||||
};
|
||||
|
||||
static void lm75_disable_regulator(void *data)
|
||||
{
|
||||
struct lm75_data *lm75 = data;
|
||||
|
||||
regulator_disable(lm75->vs);
|
||||
}
|
||||
|
||||
static void lm75_remove(void *data)
|
||||
{
|
||||
struct lm75_data *lm75 = data;
|
||||
@ -542,8 +551,9 @@ static void lm75_remove(void *data)
|
||||
i2c_smbus_write_byte_data(client, LM75_REG_CONF, lm75->orig_conf);
|
||||
}
|
||||
|
||||
static int
|
||||
lm75_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
||||
static const struct i2c_device_id lm75_ids[];
|
||||
|
||||
static int lm75_probe(struct i2c_client *client)
|
||||
{
|
||||
struct device *dev = &client->dev;
|
||||
struct device *hwmon_dev;
|
||||
@ -554,7 +564,7 @@ lm75_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
||||
if (client->dev.of_node)
|
||||
kind = (enum lm75_type)of_device_get_match_data(&client->dev);
|
||||
else
|
||||
kind = id->driver_data;
|
||||
kind = i2c_match_id(lm75_ids, client)->driver_data;
|
||||
|
||||
if (!i2c_check_functionality(client->adapter,
|
||||
I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA))
|
||||
@ -567,6 +577,10 @@ lm75_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
||||
data->client = client;
|
||||
data->kind = kind;
|
||||
|
||||
data->vs = devm_regulator_get(dev, "vs");
|
||||
if (IS_ERR(data->vs))
|
||||
return PTR_ERR(data->vs);
|
||||
|
||||
data->regmap = devm_regmap_init_i2c(client, &lm75_regmap_config);
|
||||
if (IS_ERR(data->regmap))
|
||||
return PTR_ERR(data->regmap);
|
||||
@ -581,6 +595,17 @@ lm75_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
||||
data->sample_time = data->params->default_sample_time;
|
||||
data->resolution = data->params->default_resolution;
|
||||
|
||||
/* Enable the power */
|
||||
err = regulator_enable(data->vs);
|
||||
if (err) {
|
||||
dev_err(dev, "failed to enable regulator: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
err = devm_add_action_or_reset(dev, lm75_disable_regulator, data);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* Cache original configuration */
|
||||
status = i2c_smbus_read_byte_data(client, LM75_REG_CONF);
|
||||
if (status < 0) {
|
||||
@ -893,7 +918,7 @@ static struct i2c_driver lm75_driver = {
|
||||
.of_match_table = of_match_ptr(lm75_of_match),
|
||||
.pm = LM75_DEV_PM_OPS,
|
||||
},
|
||||
.probe = lm75_probe,
|
||||
.probe_new = lm75_probe,
|
||||
.id_table = lm75_ids,
|
||||
.detect = lm75_detect,
|
||||
.address_list = normal_i2c,
|
||||
|
@ -315,7 +315,7 @@ static void lm77_init_client(struct i2c_client *client)
|
||||
lm77_write_value(client, LM77_REG_CONF, conf & 0xfe);
|
||||
}
|
||||
|
||||
static int lm77_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
||||
static int lm77_probe(struct i2c_client *client)
|
||||
{
|
||||
struct device *dev = &client->dev;
|
||||
struct device *hwmon_dev;
|
||||
@ -348,7 +348,7 @@ static struct i2c_driver lm77_driver = {
|
||||
.driver = {
|
||||
.name = "lm77",
|
||||
},
|
||||
.probe = lm77_probe,
|
||||
.probe_new = lm77_probe,
|
||||
.id_table = lm77_id,
|
||||
.detect = lm77_detect,
|
||||
.address_list = normal_i2c,
|
||||
|
@ -627,8 +627,9 @@ static int lm78_i2c_detect(struct i2c_client *client,
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static int lm78_i2c_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
static const struct i2c_device_id lm78_i2c_id[];
|
||||
|
||||
static int lm78_i2c_probe(struct i2c_client *client)
|
||||
{
|
||||
struct device *dev = &client->dev;
|
||||
struct device *hwmon_dev;
|
||||
@ -639,7 +640,7 @@ static int lm78_i2c_probe(struct i2c_client *client,
|
||||
return -ENOMEM;
|
||||
|
||||
data->client = client;
|
||||
data->type = id->driver_data;
|
||||
data->type = i2c_match_id(lm78_i2c_id, client)->driver_data;
|
||||
|
||||
/* Initialize the LM78 chip */
|
||||
lm78_init_device(data);
|
||||
@ -661,7 +662,7 @@ static struct i2c_driver lm78_driver = {
|
||||
.driver = {
|
||||
.name = "lm78",
|
||||
},
|
||||
.probe = lm78_i2c_probe,
|
||||
.probe_new = lm78_i2c_probe,
|
||||
.id_table = lm78_i2c_id,
|
||||
.detect = lm78_i2c_detect,
|
||||
.address_list = normal_i2c,
|
||||
|
@ -591,8 +591,7 @@ static int lm80_detect(struct i2c_client *client, struct i2c_board_info *info)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lm80_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
static int lm80_probe(struct i2c_client *client)
|
||||
{
|
||||
struct device *dev = &client->dev;
|
||||
struct device *hwmon_dev;
|
||||
@ -641,7 +640,7 @@ static struct i2c_driver lm80_driver = {
|
||||
.driver = {
|
||||
.name = "lm80",
|
||||
},
|
||||
.probe = lm80_probe,
|
||||
.probe_new = lm80_probe,
|
||||
.id_table = lm80_id,
|
||||
.detect = lm80_detect,
|
||||
.address_list = normal_i2c,
|
||||
|
@ -317,8 +317,9 @@ static int lm83_detect(struct i2c_client *new_client,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lm83_probe(struct i2c_client *new_client,
|
||||
const struct i2c_device_id *id)
|
||||
static const struct i2c_device_id lm83_id[];
|
||||
|
||||
static int lm83_probe(struct i2c_client *new_client)
|
||||
{
|
||||
struct device *hwmon_dev;
|
||||
struct lm83_data *data;
|
||||
@ -338,7 +339,7 @@ static int lm83_probe(struct i2c_client *new_client,
|
||||
* declare 1 and 3 common, and then 2 and 4 only for the LM83.
|
||||
*/
|
||||
data->groups[0] = &lm83_group;
|
||||
if (id->driver_data == lm83)
|
||||
if (i2c_match_id(lm83_id, new_client)->driver_data == lm83)
|
||||
data->groups[1] = &lm83_group_opt;
|
||||
|
||||
hwmon_dev = devm_hwmon_device_register_with_groups(&new_client->dev,
|
||||
@ -363,7 +364,7 @@ static struct i2c_driver lm83_driver = {
|
||||
.driver = {
|
||||
.name = "lm83",
|
||||
},
|
||||
.probe = lm83_probe,
|
||||
.probe_new = lm83_probe,
|
||||
.id_table = lm83_id,
|
||||
.detect = lm83_detect,
|
||||
.address_list = normal_i2c,
|
||||
|
@ -1544,7 +1544,9 @@ static int lm85_detect(struct i2c_client *client, struct i2c_board_info *info)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lm85_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
||||
static const struct i2c_device_id lm85_id[];
|
||||
|
||||
static int lm85_probe(struct i2c_client *client)
|
||||
{
|
||||
struct device *dev = &client->dev;
|
||||
struct device *hwmon_dev;
|
||||
@ -1559,7 +1561,7 @@ static int lm85_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
||||
if (client->dev.of_node)
|
||||
data->type = (enum chips)of_device_get_match_data(&client->dev);
|
||||
else
|
||||
data->type = id->driver_data;
|
||||
data->type = i2c_match_id(lm85_id, client)->driver_data;
|
||||
mutex_init(&data->update_lock);
|
||||
|
||||
/* Fill in the chip specific driver values */
|
||||
@ -1696,7 +1698,7 @@ static struct i2c_driver lm85_driver = {
|
||||
.name = "lm85",
|
||||
.of_match_table = of_match_ptr(lm85_of_match),
|
||||
},
|
||||
.probe = lm85_probe,
|
||||
.probe_new = lm85_probe,
|
||||
.id_table = lm85_id,
|
||||
.detect = lm85_detect,
|
||||
.address_list = normal_i2c,
|
||||
|
@ -912,7 +912,7 @@ static int lm87_init_client(struct i2c_client *client)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lm87_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
||||
static int lm87_probe(struct i2c_client *client)
|
||||
{
|
||||
struct lm87_data *data;
|
||||
struct device *hwmon_dev;
|
||||
@ -994,7 +994,7 @@ static struct i2c_driver lm87_driver = {
|
||||
.name = "lm87",
|
||||
.of_match_table = lm87_of_match,
|
||||
},
|
||||
.probe = lm87_probe,
|
||||
.probe_new = lm87_probe,
|
||||
.id_table = lm87_id,
|
||||
.detect = lm87_detect,
|
||||
.address_list = normal_i2c,
|
||||
|
@ -1779,8 +1779,7 @@ static const struct hwmon_ops lm90_ops = {
|
||||
.write = lm90_write,
|
||||
};
|
||||
|
||||
static int lm90_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
static int lm90_probe(struct i2c_client *client)
|
||||
{
|
||||
struct device *dev = &client->dev;
|
||||
struct i2c_adapter *adapter = client->adapter;
|
||||
@ -1816,7 +1815,7 @@ static int lm90_probe(struct i2c_client *client,
|
||||
if (client->dev.of_node)
|
||||
data->kind = (enum chips)of_device_get_match_data(&client->dev);
|
||||
else
|
||||
data->kind = id->driver_data;
|
||||
data->kind = i2c_match_id(lm90_id, client)->driver_data;
|
||||
if (data->kind == adm1032) {
|
||||
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE))
|
||||
client->flags &= ~I2C_CLIENT_PEC;
|
||||
@ -1952,7 +1951,7 @@ static struct i2c_driver lm90_driver = {
|
||||
.name = "lm90",
|
||||
.of_match_table = of_match_ptr(lm90_of_match),
|
||||
},
|
||||
.probe = lm90_probe,
|
||||
.probe_new = lm90_probe,
|
||||
.alert = lm90_alert,
|
||||
.id_table = lm90_id,
|
||||
.detect = lm90_detect,
|
||||
|
@ -292,8 +292,7 @@ static int lm92_detect(struct i2c_client *new_client,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lm92_probe(struct i2c_client *new_client,
|
||||
const struct i2c_device_id *id)
|
||||
static int lm92_probe(struct i2c_client *new_client)
|
||||
{
|
||||
struct device *hwmon_dev;
|
||||
struct lm92_data *data;
|
||||
@ -331,7 +330,7 @@ static struct i2c_driver lm92_driver = {
|
||||
.driver = {
|
||||
.name = "lm92",
|
||||
},
|
||||
.probe = lm92_probe,
|
||||
.probe_new = lm92_probe,
|
||||
.id_table = lm92_id,
|
||||
.detect = lm92_detect,
|
||||
.address_list = normal_i2c,
|
||||
|
@ -2583,8 +2583,7 @@ static int lm93_detect(struct i2c_client *client, struct i2c_board_info *info)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lm93_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
static int lm93_probe(struct i2c_client *client)
|
||||
{
|
||||
struct device *dev = &client->dev;
|
||||
struct lm93_data *data;
|
||||
@ -2636,7 +2635,7 @@ static struct i2c_driver lm93_driver = {
|
||||
.driver = {
|
||||
.name = "lm93",
|
||||
},
|
||||
.probe = lm93_probe,
|
||||
.probe_new = lm93_probe,
|
||||
.id_table = lm93_id,
|
||||
.detect = lm93_detect,
|
||||
.address_list = normal_i2c,
|
||||
|
@ -677,8 +677,9 @@ static int lm95234_init_client(struct i2c_client *client)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lm95234_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
static const struct i2c_device_id lm95234_id[];
|
||||
|
||||
static int lm95234_probe(struct i2c_client *client)
|
||||
{
|
||||
struct device *dev = &client->dev;
|
||||
struct lm95234_data *data;
|
||||
@ -698,7 +699,7 @@ static int lm95234_probe(struct i2c_client *client,
|
||||
return err;
|
||||
|
||||
data->groups[0] = &lm95234_common_group;
|
||||
if (id->driver_data == lm95234)
|
||||
if (i2c_match_id(lm95234_id, client)->driver_data == lm95234)
|
||||
data->groups[1] = &lm95234_group;
|
||||
|
||||
hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
|
||||
@ -719,7 +720,7 @@ static struct i2c_driver lm95234_driver = {
|
||||
.driver = {
|
||||
.name = DRVNAME,
|
||||
},
|
||||
.probe = lm95234_probe,
|
||||
.probe_new = lm95234_probe,
|
||||
.id_table = lm95234_id,
|
||||
.detect = lm95234_detect,
|
||||
.address_list = normal_i2c,
|
||||
|
@ -432,8 +432,7 @@ static const struct hwmon_chip_info lm95241_chip_info = {
|
||||
.info = lm95241_info,
|
||||
};
|
||||
|
||||
static int lm95241_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
static int lm95241_probe(struct i2c_client *client)
|
||||
{
|
||||
struct device *dev = &client->dev;
|
||||
struct lm95241_data *data;
|
||||
@ -469,7 +468,7 @@ static struct i2c_driver lm95241_driver = {
|
||||
.driver = {
|
||||
.name = DEVNAME,
|
||||
},
|
||||
.probe = lm95241_probe,
|
||||
.probe_new = lm95241_probe,
|
||||
.id_table = lm95241_id,
|
||||
.detect = lm95241_detect,
|
||||
.address_list = normal_i2c,
|
||||
|
@ -547,8 +547,7 @@ static const struct hwmon_chip_info lm95245_chip_info = {
|
||||
.info = lm95245_info,
|
||||
};
|
||||
|
||||
static int lm95245_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
static int lm95245_probe(struct i2c_client *client)
|
||||
{
|
||||
struct device *dev = &client->dev;
|
||||
struct lm95245_data *data;
|
||||
@ -598,7 +597,7 @@ static struct i2c_driver lm95245_driver = {
|
||||
.name = "lm95245",
|
||||
.of_match_table = of_match_ptr(lm95245_of_match),
|
||||
},
|
||||
.probe = lm95245_probe,
|
||||
.probe_new = lm95245_probe,
|
||||
.id_table = lm95245_id,
|
||||
.detect = lm95245_detect,
|
||||
.address_list = normal_i2c,
|
||||
|
@ -445,8 +445,7 @@ static const struct regmap_config ltc2945_regmap_config = {
|
||||
.max_register = LTC2945_MIN_ADIN_THRES_L,
|
||||
};
|
||||
|
||||
static int ltc2945_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
static int ltc2945_probe(struct i2c_client *client)
|
||||
{
|
||||
struct device *dev = &client->dev;
|
||||
struct device *hwmon_dev;
|
||||
@ -478,7 +477,7 @@ static struct i2c_driver ltc2945_driver = {
|
||||
.driver = {
|
||||
.name = "ltc2945",
|
||||
},
|
||||
.probe = ltc2945_probe,
|
||||
.probe_new = ltc2945_probe,
|
||||
.id_table = ltc2945_id,
|
||||
};
|
||||
|
||||
|
@ -15,8 +15,7 @@ static const struct regmap_config ltc2947_regmap_config = {
|
||||
.val_bits = 8,
|
||||
};
|
||||
|
||||
static int ltc2947_probe(struct i2c_client *i2c,
|
||||
const struct i2c_device_id *id)
|
||||
static int ltc2947_probe(struct i2c_client *i2c)
|
||||
{
|
||||
struct regmap *map;
|
||||
|
||||
@ -39,7 +38,7 @@ static struct i2c_driver ltc2947_driver = {
|
||||
.of_match_table = ltc2947_of_match,
|
||||
.pm = <c2947_pm_ops,
|
||||
},
|
||||
.probe = ltc2947_probe,
|
||||
.probe_new = ltc2947_probe,
|
||||
.id_table = ltc2947_id,
|
||||
};
|
||||
module_i2c_driver(ltc2947_driver);
|
||||
|
@ -200,8 +200,7 @@ static const struct attribute_group ltc2990_group = {
|
||||
};
|
||||
__ATTRIBUTE_GROUPS(ltc2990);
|
||||
|
||||
static int ltc2990_i2c_probe(struct i2c_client *i2c,
|
||||
const struct i2c_device_id *id)
|
||||
static int ltc2990_i2c_probe(struct i2c_client *i2c)
|
||||
{
|
||||
int ret;
|
||||
struct device *hwmon_dev;
|
||||
@ -269,7 +268,7 @@ static struct i2c_driver ltc2990_i2c_driver = {
|
||||
.driver = {
|
||||
.name = "ltc2990",
|
||||
},
|
||||
.probe = ltc2990_i2c_probe,
|
||||
.probe_new = ltc2990_i2c_probe,
|
||||
.id_table = ltc2990_i2c_id,
|
||||
};
|
||||
|
||||
|
@ -154,8 +154,7 @@ static struct attribute *ltc4151_attrs[] = {
|
||||
};
|
||||
ATTRIBUTE_GROUPS(ltc4151);
|
||||
|
||||
static int ltc4151_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
static int ltc4151_probe(struct i2c_client *client)
|
||||
{
|
||||
struct i2c_adapter *adapter = client->adapter;
|
||||
struct device *dev = &client->dev;
|
||||
@ -206,7 +205,7 @@ static struct i2c_driver ltc4151_driver = {
|
||||
.name = "ltc4151",
|
||||
.of_match_table = of_match_ptr(ltc4151_match),
|
||||
},
|
||||
.probe = ltc4151_probe,
|
||||
.probe_new = ltc4151_probe,
|
||||
.id_table = ltc4151_id,
|
||||
};
|
||||
|
||||
|
@ -218,8 +218,7 @@ static struct attribute *ltc4215_attrs[] = {
|
||||
};
|
||||
ATTRIBUTE_GROUPS(ltc4215);
|
||||
|
||||
static int ltc4215_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
static int ltc4215_probe(struct i2c_client *client)
|
||||
{
|
||||
struct i2c_adapter *adapter = client->adapter;
|
||||
struct device *dev = &client->dev;
|
||||
@ -256,7 +255,7 @@ static struct i2c_driver ltc4215_driver = {
|
||||
.driver = {
|
||||
.name = "ltc4215",
|
||||
},
|
||||
.probe = ltc4215_probe,
|
||||
.probe_new = ltc4215_probe,
|
||||
.id_table = ltc4215_id,
|
||||
};
|
||||
|
||||
|
@ -177,8 +177,7 @@ static const struct regmap_config ltc4222_regmap_config = {
|
||||
.max_register = LTC4222_ADC_CONTROL,
|
||||
};
|
||||
|
||||
static int ltc4222_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
static int ltc4222_probe(struct i2c_client *client)
|
||||
{
|
||||
struct device *dev = &client->dev;
|
||||
struct device *hwmon_dev;
|
||||
@ -211,7 +210,7 @@ static struct i2c_driver ltc4222_driver = {
|
||||
.driver = {
|
||||
.name = "ltc4222",
|
||||
},
|
||||
.probe = ltc4222_probe,
|
||||
.probe_new = ltc4222_probe,
|
||||
.id_table = ltc4222_id,
|
||||
};
|
||||
|
||||
|
@ -440,8 +440,7 @@ static bool ltc4245_use_extra_gpios(struct i2c_client *client)
|
||||
return false;
|
||||
}
|
||||
|
||||
static int ltc4245_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
static int ltc4245_probe(struct i2c_client *client)
|
||||
{
|
||||
struct i2c_adapter *adapter = client->adapter;
|
||||
struct ltc4245_data *data;
|
||||
@ -480,7 +479,7 @@ static struct i2c_driver ltc4245_driver = {
|
||||
.driver = {
|
||||
.name = "ltc4245",
|
||||
},
|
||||
.probe = ltc4245_probe,
|
||||
.probe_new = ltc4245_probe,
|
||||
.id_table = ltc4245_id,
|
||||
};
|
||||
|
||||
|
@ -141,8 +141,7 @@ static const struct regmap_config ltc4260_regmap_config = {
|
||||
.max_register = LTC4260_ADIN,
|
||||
};
|
||||
|
||||
static int ltc4260_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
static int ltc4260_probe(struct i2c_client *client)
|
||||
{
|
||||
struct device *dev = &client->dev;
|
||||
struct device *hwmon_dev;
|
||||
@ -174,7 +173,7 @@ static struct i2c_driver ltc4260_driver = {
|
||||
.driver = {
|
||||
.name = "ltc4260",
|
||||
},
|
||||
.probe = ltc4260_probe,
|
||||
.probe_new = ltc4260_probe,
|
||||
.id_table = ltc4260_id,
|
||||
};
|
||||
|
||||
|
@ -190,8 +190,7 @@ static struct attribute *ltc4261_attrs[] = {
|
||||
};
|
||||
ATTRIBUTE_GROUPS(ltc4261);
|
||||
|
||||
static int ltc4261_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
static int ltc4261_probe(struct i2c_client *client)
|
||||
{
|
||||
struct i2c_adapter *adapter = client->adapter;
|
||||
struct device *dev = &client->dev;
|
||||
@ -234,7 +233,7 @@ static struct i2c_driver ltc4261_driver = {
|
||||
.driver = {
|
||||
.name = "ltc4261",
|
||||
},
|
||||
.probe = ltc4261_probe,
|
||||
.probe_new = ltc4261_probe,
|
||||
.id_table = ltc4261_id,
|
||||
};
|
||||
|
||||
|
@ -493,8 +493,9 @@ static const struct attribute_group max16065_max_group = {
|
||||
.is_visible = max16065_secondary_is_visible,
|
||||
};
|
||||
|
||||
static int max16065_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
static const struct i2c_device_id max16065_id[];
|
||||
|
||||
static int max16065_probe(struct i2c_client *client)
|
||||
{
|
||||
struct i2c_adapter *adapter = client->adapter;
|
||||
struct max16065_data *data;
|
||||
@ -504,6 +505,7 @@ static int max16065_probe(struct i2c_client *client,
|
||||
bool have_secondary; /* true if chip has secondary limits */
|
||||
bool secondary_is_max = false; /* secondary limits reflect max */
|
||||
int groups = 0;
|
||||
const struct i2c_device_id *id = i2c_match_id(max16065_id, client);
|
||||
|
||||
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA
|
||||
| I2C_FUNC_SMBUS_READ_WORD_DATA))
|
||||
@ -598,7 +600,7 @@ static struct i2c_driver max16065_driver = {
|
||||
.driver = {
|
||||
.name = "max16065",
|
||||
},
|
||||
.probe = max16065_probe,
|
||||
.probe_new = max16065_probe,
|
||||
.id_table = max16065_id,
|
||||
};
|
||||
|
||||
|
@ -261,8 +261,7 @@ static void max1619_init_client(struct i2c_client *client)
|
||||
config & 0xBF); /* run */
|
||||
}
|
||||
|
||||
static int max1619_probe(struct i2c_client *new_client,
|
||||
const struct i2c_device_id *id)
|
||||
static int max1619_probe(struct i2c_client *new_client)
|
||||
{
|
||||
struct max1619_data *data;
|
||||
struct device *hwmon_dev;
|
||||
@ -306,7 +305,7 @@ static struct i2c_driver max1619_driver = {
|
||||
.name = "max1619",
|
||||
.of_match_table = of_match_ptr(max1619_of_match),
|
||||
},
|
||||
.probe = max1619_probe,
|
||||
.probe_new = max1619_probe,
|
||||
.id_table = max1619_id,
|
||||
.detect = max1619_detect,
|
||||
.address_list = normal_i2c,
|
||||
|
@ -391,8 +391,9 @@ static int max1668_detect(struct i2c_client *client,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int max1668_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
static const struct i2c_device_id max1668_id[];
|
||||
|
||||
static int max1668_probe(struct i2c_client *client)
|
||||
{
|
||||
struct i2c_adapter *adapter = client->adapter;
|
||||
struct device *dev = &client->dev;
|
||||
@ -407,7 +408,7 @@ static int max1668_probe(struct i2c_client *client,
|
||||
return -ENOMEM;
|
||||
|
||||
data->client = client;
|
||||
data->type = id->driver_data;
|
||||
data->type = i2c_match_id(max1668_id, client)->driver_data;
|
||||
mutex_init(&data->update_lock);
|
||||
|
||||
/* sysfs hooks */
|
||||
@ -434,7 +435,7 @@ static struct i2c_driver max1668_driver = {
|
||||
.driver = {
|
||||
.name = "max1668",
|
||||
},
|
||||
.probe = max1668_probe,
|
||||
.probe_new = max1668_probe,
|
||||
.id_table = max1668_id,
|
||||
.detect = max1668_detect,
|
||||
.address_list = max1668_addr_list,
|
||||
|
@ -292,7 +292,7 @@ static void max31730_remove(void *data)
|
||||
}
|
||||
|
||||
static int
|
||||
max31730_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
||||
max31730_probe(struct i2c_client *client)
|
||||
{
|
||||
struct device *dev = &client->dev;
|
||||
struct device *hwmon_dev;
|
||||
@ -427,7 +427,7 @@ static struct i2c_driver max31730_driver = {
|
||||
.of_match_table = of_match_ptr(max31730_of_match),
|
||||
.pm = &max31730_pm_ops,
|
||||
},
|
||||
.probe = max31730_probe,
|
||||
.probe_new = max31730_probe,
|
||||
.id_table = max31730_ids,
|
||||
.detect = max31730_detect,
|
||||
.address_list = normal_i2c,
|
||||
|
@ -448,8 +448,7 @@ static int max31790_init_client(struct i2c_client *client,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int max31790_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
static int max31790_probe(struct i2c_client *client)
|
||||
{
|
||||
struct i2c_adapter *adapter = client->adapter;
|
||||
struct device *dev = &client->dev;
|
||||
@ -491,7 +490,7 @@ MODULE_DEVICE_TABLE(i2c, max31790_id);
|
||||
|
||||
static struct i2c_driver max31790_driver = {
|
||||
.class = I2C_CLASS_HWMON,
|
||||
.probe = max31790_probe,
|
||||
.probe_new = max31790_probe,
|
||||
.driver = {
|
||||
.name = "max31790",
|
||||
},
|
||||
|
@ -477,8 +477,7 @@ static const struct hwmon_chip_info max6621_chip_info = {
|
||||
.info = max6621_info,
|
||||
};
|
||||
|
||||
static int max6621_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
static int max6621_probe(struct i2c_client *client)
|
||||
{
|
||||
struct device *dev = &client->dev;
|
||||
struct max6621_data *data;
|
||||
@ -555,7 +554,7 @@ static struct i2c_driver max6621_driver = {
|
||||
.name = MAX6621_DRV_NAME,
|
||||
.of_match_table = of_match_ptr(max6621_of_match),
|
||||
},
|
||||
.probe = max6621_probe,
|
||||
.probe_new = max6621_probe,
|
||||
.id_table = max6621_id,
|
||||
};
|
||||
|
||||
|
@ -516,8 +516,7 @@ static int max6639_detect(struct i2c_client *client,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int max6639_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
static int max6639_probe(struct i2c_client *client)
|
||||
{
|
||||
struct device *dev = &client->dev;
|
||||
struct max6639_data *data;
|
||||
@ -581,7 +580,7 @@ static struct i2c_driver max6639_driver = {
|
||||
.name = "max6639",
|
||||
.pm = &max6639_pm_ops,
|
||||
},
|
||||
.probe = max6639_probe,
|
||||
.probe_new = max6639_probe,
|
||||
.id_table = max6639_id,
|
||||
.detect = max6639_detect,
|
||||
.address_list = normal_i2c,
|
||||
|
@ -264,8 +264,7 @@ static struct attribute *max6642_attrs[] = {
|
||||
};
|
||||
ATTRIBUTE_GROUPS(max6642);
|
||||
|
||||
static int max6642_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
static int max6642_probe(struct i2c_client *client)
|
||||
{
|
||||
struct device *dev = &client->dev;
|
||||
struct max6642_data *data;
|
||||
@ -302,7 +301,7 @@ static struct i2c_driver max6642_driver = {
|
||||
.driver = {
|
||||
.name = "max6642",
|
||||
},
|
||||
.probe = max6642_probe,
|
||||
.probe_new = max6642_probe,
|
||||
.id_table = max6642_id,
|
||||
.detect = max6642_detect,
|
||||
.address_list = normal_i2c,
|
||||
|
@ -757,8 +757,9 @@ static const struct hwmon_chip_info max6650_chip_info = {
|
||||
.info = max6650_info,
|
||||
};
|
||||
|
||||
static int max6650_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
static const struct i2c_device_id max6650_id[];
|
||||
|
||||
static int max6650_probe(struct i2c_client *client)
|
||||
{
|
||||
struct thermal_cooling_device *cooling_dev;
|
||||
struct device *dev = &client->dev;
|
||||
@ -775,7 +776,8 @@ static int max6650_probe(struct i2c_client *client,
|
||||
data->client = client;
|
||||
i2c_set_clientdata(client, data);
|
||||
mutex_init(&data->update_lock);
|
||||
data->nr_fans = of_id ? (int)(uintptr_t)of_id->data : id->driver_data;
|
||||
data->nr_fans = of_id ? (int)(uintptr_t)of_id->data :
|
||||
i2c_match_id(max6650_id, client)->driver_data;
|
||||
|
||||
/*
|
||||
* Initialize the max6650 chip
|
||||
@ -817,7 +819,7 @@ static struct i2c_driver max6650_driver = {
|
||||
.name = "max6650",
|
||||
.of_match_table = of_match_ptr(max6650_dt_match),
|
||||
},
|
||||
.probe = max6650_probe,
|
||||
.probe_new = max6650_probe,
|
||||
.id_table = max6650_id,
|
||||
};
|
||||
|
||||
|
@ -685,8 +685,9 @@ done:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int max6697_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
static const struct i2c_device_id max6697_id[];
|
||||
|
||||
static int max6697_probe(struct i2c_client *client)
|
||||
{
|
||||
struct i2c_adapter *adapter = client->adapter;
|
||||
struct device *dev = &client->dev;
|
||||
@ -704,7 +705,7 @@ static int max6697_probe(struct i2c_client *client,
|
||||
if (client->dev.of_node)
|
||||
data->type = (enum chips)of_device_get_match_data(&client->dev);
|
||||
else
|
||||
data->type = id->driver_data;
|
||||
data->type = i2c_match_id(max6697_id, client)->driver_data;
|
||||
data->chip = &max6697_chip_data[data->type];
|
||||
data->client = client;
|
||||
mutex_init(&data->update_lock);
|
||||
@ -785,7 +786,7 @@ static struct i2c_driver max6697_driver = {
|
||||
.name = "max6697",
|
||||
.of_match_table = of_match_ptr(max6697_of_match),
|
||||
},
|
||||
.probe = max6697_probe,
|
||||
.probe_new = max6697_probe,
|
||||
.id_table = max6697_id,
|
||||
};
|
||||
|
||||
|
@ -100,8 +100,9 @@ static ssize_t in0_input_show(struct device *dev,
|
||||
|
||||
static DEVICE_ATTR_RO(in0_input);
|
||||
|
||||
static int mcp3021_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
static const struct i2c_device_id mcp3021_id[];
|
||||
|
||||
static int mcp3021_probe(struct i2c_client *client)
|
||||
{
|
||||
int err;
|
||||
struct mcp3021_data *data = NULL;
|
||||
@ -132,7 +133,7 @@ static int mcp3021_probe(struct i2c_client *client,
|
||||
data->vdd = MCP3021_VDD_REF_DEFAULT;
|
||||
}
|
||||
|
||||
switch (id->driver_data) {
|
||||
switch (i2c_match_id(mcp3021_id, client)->driver_data) {
|
||||
case mcp3021:
|
||||
data->sar_shift = MCP3021_SAR_SHIFT;
|
||||
data->sar_mask = MCP3021_SAR_MASK;
|
||||
@ -197,7 +198,7 @@ static struct i2c_driver mcp3021_driver = {
|
||||
.name = "mcp3021",
|
||||
.of_match_table = of_match_ptr(of_mcp3021_match),
|
||||
},
|
||||
.probe = mcp3021_probe,
|
||||
.probe_new = mcp3021_probe,
|
||||
.remove = mcp3021_remove,
|
||||
.id_table = mcp3021_id,
|
||||
};
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user