New driver for AXI fan control.
 Attenuator bypass support and support for inverting pwm output
 in adt7475 driver.
 Support for new power supply version in ibm-cffps driver.
 PMBus drivers:
   Support for multi-phase chips.
   Support for LTC2972, LTC2979, LTC3884, LTC3889, LTC7880, LTM4664,
   LTM4677, LTM4678, LTM4680, and LTM4700 added to ltc2978 driver.
   Support for TPS53681, TPS53647, and TPS53667 added to tps53679
   driver.
   Support for various 2nd Gen Renesas digital multiphase chips
   added to isl68137 driver.
 
 Minor improvements and fixes in nct7904, ibmpowernv, lm73, ibmaem,
 and k10temp drivers.
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEEiHPvMQj9QTOCiqgVyx8mb86fmYEFAl6CFCEACgkQyx8mb86f
 mYHoHA/+OnoYUyknO9zpdH4DJ9Hte7GqnNKUE6txORInZXqICQAHfrRYbFA6HGxi
 8BYlV1b3A/9nvi9uR1XNheDTjlnvkJYMvZEYABSxDvdVkzSgPo2lvW/SvIf4Dq0k
 OhqFKnCZ/decs7VhsnqaNK5iyv26wWDt8YMXiSC9PmSoUi4YhVgUfLFJXSU2QlGh
 tRg97gVGVVJyimpaP+5b6khC3JiS1XPpbkD8d95Xqw6w6JUxN75O9ezWRTyz8Dbe
 DqT+9uOFnvZrIyoPRatb3zVdtM8FwFMaJmQDOlIqYJ7mzzDW7visViKVu2sjODe8
 6CM587vbuFOrzXzPqjjDho9T2ejz3oL3c25SuO1Jxu3KGJ/Aq61rP0V1PNoGDAWx
 rqPLwhGgLqtiBpLFPoNnRvzI10wmPGaaVlk3JCFZOj2uUv7RFuGw99sckucmW2dd
 9XRcp7ig6LxhnaFozBfLJsXiHaaFQvV+wZdT43reEE78Uv9HWOUZ8UH/w/nPDuit
 YnOQon9BHU+bC9ebpgtkBiWdA+sU8nk14T7xNMunR/+bYYDQEXjUms9z2gHtv9lX
 f0ZO4r8wCLL3Mn+cAwk4S32nnSu2A1pUoQAqg2c6UpYcr4kVJRP1FTA25bzh9MRH
 IdOGhQ54FK8mENARLpzLYaxgI4K/FsF70z9DZFsvjpd4lKT9Fyk=
 =S/bJ
 -----END PGP SIGNATURE-----

Merge tag 'hwmon-for-v5.7' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging

Pull hwmon updates from Guenter Roeck:

 - New driver for AXI fan control

 - Attenuator bypass support and support for inverting pwm output in
   adt7475 driver

 - Support for new power supply version in ibm-cffps driver

 - PMBus drivers:

     * support for multi-phase chips

     * ltc2978 driver: add support for LTC2972, LTC2979, LTC3884,
       LTC3889, LTC7880, LTM4664, LTM4677, LTM4678, LTM4680, and
       LTM4700/

     * tps53679 driver: add support for TPS53681, TPS53647, and TPS53667

     * isl68137 driver: support for various 2nd Gen Renesas digital
       multiphase chips added to isl68137 driver

 - Minor improvements and fixes in nct7904, ibmpowernv, lm73, ibmaem,
   and k10temp drivers

* tag 'hwmon-for-v5.7' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging: (29 commits)
  docs: hwmon: Update documentation for isl68137 pmbus driver
  hwmon: (pmbus) add support for 2nd Gen Renesas digital multiphase
  hwmon: (pmbus/ibm-cffps) Add another PSU CCIN to version detection
  hwmon: (nct7904) Fix the incorrect quantity for fan & temp attributes
  hwmon: (ibmpowernv) Use scnprintf() for avoiding potential buffer overflow
  hwmon: (adt7475) Add support for inverting pwm output
  hwmon: (adt7475) Add attenuator bypass support
  dt-bindings: hwmon: Document adt7475 pwm-active-state property
  dt-bindings: hwmon: Document adt7475 bypass-attenuator property
  dt-bindings: hwmon: Document adt7475 binding
  hwmon: (lm73) Add support for of_match_table
  dt-bindings: Add TI LM73 as a trivial device
  hwmon: (pmbus/tps53679) Add documentation
  hwmon: (pmbus/tps53679) Add support for TPS53647 and TPS53667
  hwmon: (pmbus/tps53679) Add support for TPS53681
  hwmon: (pmbus/tps53679) Add support for IIN and PIN to TPS53679 and TPS53688
  hwmon: (pmbus/tps53679) Add support for multiple chips IDs
  hwmon: (pmbus) Implement multi-phase support
  hwmon: (pmbus) Add 'phase' parameter where needed for multi-phase support
  hwmon: (pmbus) Add IC_DEVICE_ID and IC_DEVICE_REV command definitions
  ...
This commit is contained in:
Linus Torvalds 2020-03-30 13:34:25 -07:00
Родитель ff7b862a4c 5b10a81946
Коммит 47acac8cae
41 изменённых файлов: 2325 добавлений и 311 удалений

Просмотреть файл

@ -0,0 +1,62 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
# Copyright 2019 Analog Devices Inc.
%YAML 1.2
---
$id: http://devicetree.org/schemas/bindings/hwmon/adi,axi-fan-control.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Analog Devices AXI FAN Control Device Tree Bindings
maintainers:
- Nuno Sá <nuno.sa@analog.com>
description: |+
Bindings for the Analog Devices AXI FAN Control driver. Spefications of the
core can be found in:
https://wiki.analog.com/resources/fpga/docs/axi_fan_control
properties:
compatible:
enum:
- adi,axi-fan-control-1.00.a
reg:
maxItems: 1
clocks:
maxItems: 1
interrupts:
maxItems: 1
pulses-per-revolution:
description:
Value specifying the number of pulses per revolution of the controlled
FAN.
allOf:
- $ref: /schemas/types.yaml#/definitions/uint32
enum: [1, 2, 4]
required:
- compatible
- reg
- clocks
- interrupts
- pulses-per-revolution
examples:
- |
fpga_axi: fpga-axi@0 {
#address-cells = <0x2>;
#size-cells = <0x1>;
axi_fan_control: axi-fan-control@80000000 {
compatible = "adi,axi-fan-control-1.00.a";
reg = <0x0 0x80000000 0x10000>;
clocks = <&clk 71>;
interrupts = <0 110 0>;
pulses-per-revolution = <2>;
};
};
...

Просмотреть файл

@ -0,0 +1,84 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/adt7475.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: ADT7475 hwmon sensor
maintainers:
- Jean Delvare <jdelvare@suse.com>
description: |
The ADT7473, ADT7475, ADT7476, and ADT7490 are thermal monitors and multiple
PWN fan controllers.
They support monitoring and controlling up to four fans (the ADT7490 can only
control up to three). They support reading a single on chip temperature
sensor and two off chip temperature sensors (the ADT7490 additionally
supports measuring up to three current external temperature sensors with
series resistance cancellation (SRC)).
Datasheets:
https://www.onsemi.com/pub/Collateral/ADT7473-D.PDF
https://www.onsemi.com/pub/Collateral/ADT7475-D.PDF
https://www.onsemi.com/pub/Collateral/ADT7476-D.PDF
https://www.onsemi.com/pub/Collateral/ADT7490-D.PDF
Description taken from onsemiconductors specification sheets, with minor
rephrasing.
properties:
compatible:
enum:
- adi,adt7473
- adi,adt7475
- adi,adt7476
- adi,adt7490
reg:
maxItems: 1
patternProperties:
"^adi,bypass-attenuator-in[0-4]$":
description: |
Configures bypassing the individual voltage input attenuator. If
set to 1 the attenuator is bypassed if set to 0 the attenuator is
not bypassed. If the property is absent then the attenuator
retains it's configuration from the bios/bootloader.
allOf:
- $ref: /schemas/types.yaml#/definitions/uint32
- enum: [0, 1]
"^adi,pwm-active-state$":
description: |
Integer array, represents the active state of the pwm outputs If set to 0
the pwm uses a logic low output for 100% duty cycle. If set to 1 the pwm
uses a logic high output for 100% duty cycle.
allOf:
- $ref: /schemas/types.yaml#/definitions/uint32-array
- minItems: 3
maxItems: 3
items:
enum: [0, 1]
default: 1
required:
- compatible
- reg
examples:
- |
i2c {
#address-cells = <1>;
#size-cells = <0>;
hwmon@2e {
compatible = "adi,adt7476";
reg = <0x2e>;
adi,bypass-attenuator-in0 = <1>;
adi,bypass-attenuator-in1 = <0>;
adi,pwm-active-state = <1 0 1>;
};
};

Просмотреть файл

@ -2,20 +2,30 @@ ltc2978
Required properties:
- compatible: should contain one of:
* "lltc,ltc2972"
* "lltc,ltc2974"
* "lltc,ltc2975"
* "lltc,ltc2977"
* "lltc,ltc2978"
* "lltc,ltc2979"
* "lltc,ltc2980"
* "lltc,ltc3880"
* "lltc,ltc3882"
* "lltc,ltc3883"
* "lltc,ltc3884"
* "lltc,ltc3886"
* "lltc,ltc3887"
* "lltc,ltc3889"
* "lltc,ltc7880"
* "lltc,ltm2987"
* "lltc,ltm4664"
* "lltc,ltm4675"
* "lltc,ltm4676"
* "lltc,ltm4677"
* "lltc,ltm4678"
* "lltc,ltm4680"
* "lltc,ltm4686"
* "lltc,ltm4700"
- reg: I2C slave address
Optional properties:
@ -25,13 +35,17 @@ Optional properties:
standard binding for regulators; see regulator.txt.
Valid names of regulators depend on number of supplies supported per device:
* ltc2972 vout0 - vout1
* ltc2974, ltc2975 : vout0 - vout3
* ltc2977, ltc2980, ltm2987 : vout0 - vout7
* ltc2977, ltc2979, ltc2980, ltm2987 : vout0 - vout7
* ltc2978 : vout0 - vout7
* ltc3880, ltc3882, ltc3886 : vout0 - vout1
* ltc3880, ltc3882, ltc3884, ltc3886, ltc3887, ltc3889 : vout0 - vout1
* ltc7880 : vout0 - vout1
* ltc3883 : vout0
* ltm4676 : vout0 - vout1
* ltm4686 : vout0 - vout1
* ltm4664 : vout0 - vout1
* ltm4675, ltm4676, ltm4677, ltm4678 : vout0 - vout1
* ltm4680, ltm4686 : vout0 - vout1
* ltm4700 : vout0 - vout1
Example:
ltc2978@5e {

Просмотреть файл

@ -34,14 +34,6 @@ properties:
- adi,adt7461
# +/-1C TDM Extended Temp Range I.C
- adt7461
# +/-1C TDM Extended Temp Range I.C
- adi,adt7473
# +/-1C TDM Extended Temp Range I.C
- adi,adt7475
# +/-1C TDM Extended Temp Range I.C
- adi,adt7476
# +/-1C TDM Extended Temp Range I.C
- adi,adt7490
# Three-Axis Digital Accelerometer
- adi,adxl345
# Three-Axis Digital Accelerometer (backward-compatibility value "adi,adxl345" must be listed too)
@ -350,6 +342,8 @@ properties:
- ti,ads7830
# Temperature Monitoring and Fan Control
- ti,amc6821
# Temperature sensor with 2-wire interface
- ti,lm73
# Temperature sensor with integrated fan control
- ti,lm96000
# I2C Touch-Screen Controller

Просмотреть файл

@ -162,6 +162,7 @@ Hardware Monitoring Kernel Drivers
tmp421
tmp513
tps40422
tps53679
twl4030-madc-hwmon
ucd9000
ucd9200

Просмотреть файл

@ -3,7 +3,7 @@ Kernel driver isl68137
Supported chips:
* Intersil ISL68137
* Renesas ISL68137
Prefix: 'isl68137'
@ -11,19 +11,405 @@ Supported chips:
Datasheet:
Publicly available at the Intersil website
https://www.intersil.com/content/dam/Intersil/documents/isl6/isl68137.pdf
Publicly available at the Renesas website
https://www.renesas.com/us/en/www/doc/datasheet/isl68137.pdf
* Renesas ISL68220
Prefix: 'raa_dmpvr2_2rail'
Addresses scanned: -
Datasheet:
Publicly available (after August 2020 launch) at the Renesas website
* Renesas ISL68221
Prefix: 'raa_dmpvr2_3rail'
Addresses scanned: -
Datasheet:
Publicly available (after August 2020 launch) at the Renesas website
* Renesas ISL68222
Prefix: 'raa_dmpvr2_2rail'
Addresses scanned: -
Datasheet:
Publicly available (after August 2020 launch) at the Renesas website
* Renesas ISL68223
Prefix: 'raa_dmpvr2_2rail'
Addresses scanned: -
Datasheet:
Publicly available (after August 2020 launch) at the Renesas website
* Renesas ISL68224
Prefix: 'raa_dmpvr2_3rail'
Addresses scanned: -
Datasheet:
Publicly available (after August 2020 launch) at the Renesas website
* Renesas ISL68225
Prefix: 'raa_dmpvr2_2rail'
Addresses scanned: -
Datasheet:
Publicly available (after August 2020 launch) at the Renesas website
* Renesas ISL68226
Prefix: 'raa_dmpvr2_3rail'
Addresses scanned: -
Datasheet:
Publicly available (after August 2020 launch) at the Renesas website
* Renesas ISL68227
Prefix: 'raa_dmpvr2_1rail'
Addresses scanned: -
Datasheet:
Publicly available (after August 2020 launch) at the Renesas website
* Renesas ISL68229
Prefix: 'raa_dmpvr2_3rail'
Addresses scanned: -
Datasheet:
Publicly available (after August 2020 launch) at the Renesas website
* Renesas ISL68233
Prefix: 'raa_dmpvr2_2rail'
Addresses scanned: -
Datasheet:
Publicly available (after August 2020 launch) at the Renesas website
* Renesas ISL68239
Prefix: 'raa_dmpvr2_3rail'
Addresses scanned: -
Datasheet:
Publicly available (after August 2020 launch) at the Renesas website
* Renesas ISL69222
Prefix: 'raa_dmpvr2_2rail'
Addresses scanned: -
Datasheet:
Publicly available (after August 2020 launch) at the Renesas website
* Renesas ISL69223
Prefix: 'raa_dmpvr2_3rail'
Addresses scanned: -
Datasheet:
Publicly available (after August 2020 launch) at the Renesas website
* Renesas ISL69224
Prefix: 'raa_dmpvr2_2rail'
Addresses scanned: -
Datasheet:
Publicly available (after August 2020 launch) at the Renesas website
* Renesas ISL69225
Prefix: 'raa_dmpvr2_2rail'
Addresses scanned: -
Datasheet:
Publicly available (after August 2020 launch) at the Renesas website
* Renesas ISL69227
Prefix: 'raa_dmpvr2_3rail'
Addresses scanned: -
Datasheet:
Publicly available (after August 2020 launch) at the Renesas website
* Renesas ISL69228
Prefix: 'raa_dmpvr2_3rail'
Addresses scanned: -
Datasheet:
Publicly available (after August 2020 launch) at the Renesas website
* Renesas ISL69234
Prefix: 'raa_dmpvr2_2rail'
Addresses scanned: -
Datasheet:
Publicly available (after August 2020 launch) at the Renesas website
* Renesas ISL69236
Prefix: 'raa_dmpvr2_2rail'
Addresses scanned: -
Datasheet:
Publicly available (after August 2020 launch) at the Renesas website
* Renesas ISL69239
Prefix: 'raa_dmpvr2_3rail'
Addresses scanned: -
Datasheet:
Publicly available (after August 2020 launch) at the Renesas website
* Renesas ISL69242
Prefix: 'raa_dmpvr2_2rail'
Addresses scanned: -
Datasheet:
Publicly available (after August 2020 launch) at the Renesas website
* Renesas ISL69243
Prefix: 'raa_dmpvr2_1rail'
Addresses scanned: -
Datasheet:
Publicly available (after August 2020 launch) at the Renesas website
* Renesas ISL69247
Prefix: 'raa_dmpvr2_2rail'
Addresses scanned: -
Datasheet:
Publicly available (after August 2020 launch) at the Renesas website
* Renesas ISL69248
Prefix: 'raa_dmpvr2_2rail'
Addresses scanned: -
Datasheet:
Publicly available (after August 2020 launch) at the Renesas website
* Renesas ISL69254
Prefix: 'raa_dmpvr2_2rail'
Addresses scanned: -
Datasheet:
Publicly available (after August 2020 launch) at the Renesas website
* Renesas ISL69255
Prefix: 'raa_dmpvr2_2rail'
Addresses scanned: -
Datasheet:
Publicly available (after August 2020 launch) at the Renesas website
* Renesas ISL69256
Prefix: 'raa_dmpvr2_2rail'
Addresses scanned: -
Datasheet:
Publicly available (after August 2020 launch) at the Renesas website
* Renesas ISL69259
Prefix: 'raa_dmpvr2_2rail'
Addresses scanned: -
Datasheet:
Publicly available (after August 2020 launch) at the Renesas website
* Renesas ISL69260
Prefix: 'raa_dmpvr2_2rail'
Addresses scanned: -
Datasheet:
Publicly available (after August 2020 launch) at the Renesas website
* Renesas ISL69268
Prefix: 'raa_dmpvr2_2rail'
Addresses scanned: -
Datasheet:
Publicly available (after August 2020 launch) at the Renesas website
* Renesas ISL69269
Prefix: 'raa_dmpvr2_3rail'
Addresses scanned: -
Datasheet:
Publicly available (after August 2020 launch) at the Renesas website
* Renesas ISL69298
Prefix: 'raa_dmpvr2_2rail'
Addresses scanned: -
Datasheet:
Publicly available (after August 2020 launch) at the Renesas website
* Renesas RAA228000
Prefix: 'raa_dmpvr2_hv'
Addresses scanned: -
Datasheet:
Publicly available (after August 2020 launch) at the Renesas website
* Renesas RAA228004
Prefix: 'raa_dmpvr2_hv'
Addresses scanned: -
Datasheet:
Publicly available (after August 2020 launch) at the Renesas website
* Renesas RAA228006
Prefix: 'raa_dmpvr2_hv'
Addresses scanned: -
Datasheet:
Publicly available (after August 2020 launch) at the Renesas website
* Renesas RAA228228
Prefix: 'raa_dmpvr2_2rail'
Addresses scanned: -
Datasheet:
Publicly available (after August 2020 launch) at the Renesas website
* Renesas RAA229001
Prefix: 'raa_dmpvr2_2rail'
Addresses scanned: -
Datasheet:
Publicly available (after August 2020 launch) at the Renesas website
* Renesas RAA229004
Prefix: 'raa_dmpvr2_2rail'
Addresses scanned: -
Datasheet:
Publicly available (after August 2020 launch) at the Renesas website
Authors:
- Maxim Sloyko <maxims@google.com>
- Robert Lippert <rlippert@google.com>
- Patrick Venture <venture@google.com>
- Grant Peltier <grant.peltier.jg@renesas.com>
Description
-----------
Intersil ISL68137 is a digital output 7-phase configurable PWM
controller with an AVSBus interface.
This driver supports the Renesas ISL68137 and all 2nd generation Renesas
digital multiphase voltage regulators (raa_dmpvr2). The ISL68137 is a digital
output 7-phase configurable PWM controller with an AVSBus interface. 2nd
generation devices are grouped into 4 distinct configurations: '1rail' for
single-rail devices, '2rail' for dual-rail devices, '3rail' for 3-rail devices,
and 'hv' for high voltage single-rail devices. Consult the individual datasheets
for more information.
Usage Notes
-----------
@ -33,10 +419,14 @@ devices explicitly.
The ISL68137 AVS operation mode must be enabled/disabled at runtime.
Beyond the normal sysfs pmbus attributes, the driver exposes a control attribute.
Beyond the normal sysfs pmbus attributes, the driver exposes a control attribute
for the ISL68137.
Additional Sysfs attributes
---------------------------
For 2nd generation Renesas digital multiphase voltage regulators, only the
normal sysfs pmbus attributes are supported.
ISL68137 sysfs attributes
-------------------------
======================= ====================================
avs(0|1)_enable Controls the AVS state of each rail.
@ -78,3 +468,138 @@ temp[1-3]_crit_alarm Chip temperature critical high alarm
temp[1-3]_max Maximum temperature
temp[1-3]_max_alarm Chip temperature high alarm
======================= ====================================
raa_dmpvr2_1rail/hv sysfs attributes
------------------------------------
======================= ==========================================
curr1_label "iin"
curr1_input Measured input current
curr1_crit Critical maximum current
curr1_crit_alarm Current critical high alarm
curr2_label "iout"
curr2_input Measured output current
curr2_crit Critical maximum current
curr2_crit_alarm Current critical high alarm
in1_label "vin"
in1_input Measured input voltage
in1_lcrit Critical minimum input voltage
in1_lcrit_alarm Input voltage critical low alarm
in1_crit Critical maximum input voltage
in1_crit_alarm Input voltage critical high alarm
in2_label "vmon"
in2_input Scaled VMON voltage read from the VMON pin
in3_label "vout"
in3_input Measured output voltage
in3_lcrit Critical minimum output voltage
in3_lcrit_alarm Output voltage critical low alarm
in3_crit Critical maximum output voltage
in3_crit_alarm Output voltage critical high alarm
power1_label "pin"
power1_input Measured input power
power1_alarm Input power high alarm
power2_label "pout"
power2_input Measured output power
temp[1-3]_input Measured temperature
temp[1-3]_crit Critical high temperature
temp[1-3]_crit_alarm Chip temperature critical high alarm
temp[1-3]_max Maximum temperature
temp[1-3]_max_alarm Chip temperature high alarm
======================= ==========================================
raa_dmpvr2_2rail sysfs attributes
---------------------------------
======================= ==========================================
curr[1-2]_label "iin[1-2]"
curr[1-2]_input Measured input current
curr[1-2]_crit Critical maximum current
curr[1-2]_crit_alarm Current critical high alarm
curr[3-4]_label "iout[1-2]"
curr[3-4]_input Measured output current
curr[3-4]_crit Critical maximum current
curr[3-4]_crit_alarm Current critical high alarm
in1_label "vin"
in1_input Measured input voltage
in1_lcrit Critical minimum input voltage
in1_lcrit_alarm Input voltage critical low alarm
in1_crit Critical maximum input voltage
in1_crit_alarm Input voltage critical high alarm
in2_label "vmon"
in2_input Scaled VMON voltage read from the VMON pin
in[3-4]_label "vout[1-2]"
in[3-4]_input Measured output voltage
in[3-4]_lcrit Critical minimum output voltage
in[3-4]_lcrit_alarm Output voltage critical low alarm
in[3-4]_crit Critical maximum output voltage
in[3-4]_crit_alarm Output voltage critical high alarm
power[1-2]_label "pin[1-2]"
power[1-2]_input Measured input power
power[1-2]_alarm Input power high alarm
power[3-4]_label "pout[1-2]"
power[3-4]_input Measured output power
temp[1-5]_input Measured temperature
temp[1-5]_crit Critical high temperature
temp[1-5]_crit_alarm Chip temperature critical high alarm
temp[1-5]_max Maximum temperature
temp[1-5]_max_alarm Chip temperature high alarm
======================= ==========================================
raa_dmpvr2_3rail sysfs attributes
---------------------------------
======================= ==========================================
curr[1-3]_label "iin[1-3]"
curr[1-3]_input Measured input current
curr[1-3]_crit Critical maximum current
curr[1-3]_crit_alarm Current critical high alarm
curr[4-6]_label "iout[1-3]"
curr[4-6]_input Measured output current
curr[4-6]_crit Critical maximum current
curr[4-6]_crit_alarm Current critical high alarm
in1_label "vin"
in1_input Measured input voltage
in1_lcrit Critical minimum input voltage
in1_lcrit_alarm Input voltage critical low alarm
in1_crit Critical maximum input voltage
in1_crit_alarm Input voltage critical high alarm
in2_label "vmon"
in2_input Scaled VMON voltage read from the VMON pin
in[3-5]_label "vout[1-3]"
in[3-5]_input Measured output voltage
in[3-5]_lcrit Critical minimum output voltage
in[3-5]_lcrit_alarm Output voltage critical low alarm
in[3-5]_crit Critical maximum output voltage
in[3-5]_crit_alarm Output voltage critical high alarm
power[1-3]_label "pin[1-3]"
power[1-3]_input Measured input power
power[1-3]_alarm Input power high alarm
power[4-6]_label "pout[1-3]"
power[4-6]_input Measured output power
temp[1-7]_input Measured temperature
temp[1-7]_crit Critical high temperature
temp[1-7]_crit_alarm Chip temperature critical high alarm
temp[1-7]_max Maximum temperature
temp[1-7]_max_alarm Chip temperature high alarm
======================= ==========================================

Просмотреть файл

@ -100,9 +100,10 @@ socket type, not the processor's actual capabilities. Therefore, if you
are using an AM3 processor on an AM2+ mainboard, you can safely use the
"force=1" parameter.
There is one temperature measurement value, available as temp1_input in
sysfs. It is measured in degrees Celsius with a resolution of 1/8th degree.
Please note that it is defined as a relative value; to quote the AMD manual::
For CPUs older than Family 17h, there is one temperature measurement value,
available as temp1_input in sysfs. It is measured in degrees Celsius with a
resolution of 1/8th degree. Please note that it is defined as a relative
value; to quote the AMD manual::
Tctl is the processor temperature control value, used by the platform to
control cooling systems. Tctl is a non-physical temperature on an
@ -126,3 +127,25 @@ it.
Models from 17h family report relative temperature, the driver aims to
compensate and report the real temperature.
On Family 17h and Family 18h CPUs, additional temperature sensors may report
Core Complex Die (CCD) temperatures. Up to 8 such temperatures are reported
as temp{3..10}_input, labeled Tccd{1..8}. Actual support depends on the CPU
variant.
Various Family 17h and 18h CPUs report voltage and current telemetry
information. The following attributes may be reported.
Attribute Label Description
=============== ======= ================
in0_input Vcore Core voltage
in1_input Vsoc SoC voltage
curr1_input Icore Core current
curr2_input Isoc SoC current
=============== ======= ================
Current values are raw (unscaled) as reported by the CPU. Core current is
reported as multiples of 1A / LSB. SoC is reported as multiples of 0.25A
/ LSB. The real current is board specific. Reported currents should be seen
as rough guidance, and should be scaled using sensors3.conf as appropriate
for a given board.

Просмотреть файл

@ -3,13 +3,21 @@ Kernel driver ltc2978
Supported chips:
* Linear Technology LTC2972
Prefix: 'ltc2972'
Addresses scanned: -
Datasheet: https://www.analog.com/en/products/ltc2972.html
* Linear Technology LTC2974
Prefix: 'ltc2974'
Addresses scanned: -
Datasheet: http://www.linear.com/product/ltc2974
Datasheet: https://www.analog.com/en/products/ltc2974
* Linear Technology LTC2975
@ -17,7 +25,7 @@ Supported chips:
Addresses scanned: -
Datasheet: http://www.linear.com/product/ltc2975
Datasheet: https://www.analog.com/en/products/ltc2975
* Linear Technology LTC2977
@ -25,7 +33,7 @@ Supported chips:
Addresses scanned: -
Datasheet: http://www.linear.com/product/ltc2977
Datasheet: https://www.analog.com/en/products/ltc2977
* Linear Technology LTC2978, LTC2978A
@ -33,9 +41,17 @@ Supported chips:
Addresses scanned: -
Datasheet: http://www.linear.com/product/ltc2978
Datasheet: https://www.analog.com/en/products/ltc2978
http://www.linear.com/product/ltc2978a
https://www.analog.com/en/products/ltc2978a
* Linear Technology LTC2979
Prefix: 'ltc2979'
Addresses scanned: -
Datasheet: https://www.analog.com/en/products/ltc2979
* Linear Technology LTC2980
@ -43,7 +59,7 @@ Supported chips:
Addresses scanned: -
Datasheet: http://www.linear.com/product/ltc2980
Datasheet: https://www.analog.com/en/products/ltc2980
* Linear Technology LTC3880
@ -51,7 +67,7 @@ Supported chips:
Addresses scanned: -
Datasheet: http://www.linear.com/product/ltc3880
Datasheet: https://www.analog.com/en/products/ltc3880
* Linear Technology LTC3882
@ -59,7 +75,7 @@ Supported chips:
Addresses scanned: -
Datasheet: http://www.linear.com/product/ltc3882
Datasheet: https://www.analog.com/en/products/ltc3882
* Linear Technology LTC3883
@ -67,7 +83,15 @@ Supported chips:
Addresses scanned: -
Datasheet: http://www.linear.com/product/ltc3883
Datasheet: https://www.analog.com/en/products/ltc3883
* Linear Technology LTC3884
Prefix: 'ltc3884'
Addresses scanned: -
Datasheet: https://www.analog.com/en/products/ltc3884
* Linear Technology LTC3886
@ -75,7 +99,7 @@ Supported chips:
Addresses scanned: -
Datasheet: http://www.linear.com/product/ltc3886
Datasheet: https://www.analog.com/en/products/ltc3886
* Linear Technology LTC3887
@ -83,7 +107,23 @@ Supported chips:
Addresses scanned: -
Datasheet: http://www.linear.com/product/ltc3887
Datasheet: https://www.analog.com/en/products/ltc3887
* Linear Technology LTC3889
Prefix: 'ltc3889'
Addresses scanned: -
Datasheet: https://www.analog.com/en/products/ltc3889
* Linear Technology LTC7880
Prefix: 'ltc7880'
Addresses scanned: -
Datasheet: https://www.analog.com/en/products/ltc7880
* Linear Technology LTM2987
@ -91,15 +131,23 @@ Supported chips:
Addresses scanned: -
Datasheet: http://www.linear.com/product/ltm2987
Datasheet: https://www.analog.com/en/products/ltm2987
* Linear Technology LTM4675
* Linear Technology LTM4644
Prefix: 'ltm4644'
Addresses scanned: -
Datasheet: https://www.analog.com/en/products/ltm4644
* Linear Technology LTM4675
Prefix: 'ltm4675'
Addresses scanned: -
Datasheet: http://www.linear.com/product/ltm4675
Datasheet: https://www.analog.com/en/products/ltm4675
* Linear Technology LTM4676
@ -107,7 +155,31 @@ Supported chips:
Addresses scanned: -
Datasheet: http://www.linear.com/product/ltm4676
Datasheet: https://www.analog.com/en/products/ltm4676
* Linear Technology LTM4677
Prefix: 'ltm4677'
Addresses scanned: -
Datasheet: https://www.analog.com/en/products/ltm4677
* Linear Technology LTM4678
Prefix: 'ltm4678'
Addresses scanned: -
Datasheet: https://www.analog.com/en/products/ltm4678
* Analog Devices LTM4680
Prefix: 'ltm4680'
Addresses scanned: -
Datasheet: http://www.analog.com/ltm4680
* Analog Devices LTM4686
@ -117,6 +189,15 @@ Supported chips:
Datasheet: http://www.analog.com/ltm4686
* Analog Devices LTM4700
Prefix: 'ltm4700'
Addresses scanned: -
Datasheet: http://www.analog.com/ltm4700
Author: Guenter Roeck <linux@roeck-us.net>
@ -166,13 +247,13 @@ in1_min Minimum input voltage.
in1_max Maximum input voltage.
LTC2974, LTC2975, LTC2977, LTC2980, LTC2978, and
LTM2987 only.
LTC2974, LTC2975, LTC2977, LTC2980, LTC2978,
LTC2979 and LTM2987 only.
in1_lcrit Critical minimum input voltage.
LTC2974, LTC2975, LTC2977, LTC2980, LTC2978, and
LTM2987 only.
LTC2972, LTC2974, LTC2975, LTC2977, LTC2980, LTC2978,
LTC2979 and LTM2987 only.
in1_crit Critical maximum input voltage.
@ -180,29 +261,34 @@ in1_min_alarm Input voltage low alarm.
in1_max_alarm Input voltage high alarm.
LTC2974, LTC2975, LTC2977, LTC2980, LTC2978, and
LTM2987 only.
LTC2972, LTC2974, LTC2975, LTC2977, LTC2980, LTC2978,
LTC2979 and LTM2987 only.
in1_lcrit_alarm Input voltage critical low alarm.
LTC2974, LTC2975, LTC2977, LTC2980, LTC2978, and
LTM2987 only.
LTC2972, LTC2974, LTC2975, LTC2977, LTC2980, LTC2978,
LTC2979 and LTM2987 only.
in1_crit_alarm Input voltage critical high alarm.
in1_lowest Lowest input voltage.
LTC2974, LTC2975, LTC2977, LTC2980, LTC2978, and
LTM2987 only.
LTC2972, LTC2974, LTC2975, LTC2977, LTC2980, LTC2978,
and LTM2987 only.
in1_highest Highest input voltage.
in1_reset_history Reset input voltage history.
in[N]_label "vout[1-8]".
- LTC2972: N=2-3
- LTC2974, LTC2975: N=2-5
- LTC2977, LTC2980, LTM2987: N=2-9
- LTC2977, LTC2979, LTC2980, LTM2987: N=2-9
- LTC2978: N=2-9
- LTC3880, LTC3882, LTC23886 LTC3887, LTM4675, LTM4676:
N=2-3
- LTC3880, LTC3882, LTC3884, LTC23886 LTC3887, LTC3889,
LTC7880, LTM4644, LTM4675, LTM4676, LTM4677, LTM4678,
LTM4680, LTM4700: N=2-3
- LTC3883: N=2
in[N]_input Measured output voltage.
@ -225,8 +311,7 @@ in[N]_crit_alarm Output voltage critical high alarm.
in[N]_lowest Lowest output voltage.
LTC2974, LTC2975,and LTC2978 only.
LTC2972, LTC2974, LTC2975,and LTC2978 only.
in[N]_highest Highest output voltage.
@ -234,20 +319,24 @@ in[N]_reset_history Reset output voltage history.
temp[N]_input Measured temperature.
- On LTC2972, temp[1-2] report external temperatures,
and temp 3 reports the chip temperature.
- On LTC2974 and LTC2975, temp[1-4] report external
temperatures, and temp5 reports the chip temperature.
- On LTC2977, LTC2980, LTC2978, and LTM2987, only one
temperature measurement is supported and reports
the chip temperature.
- On LTC3880, LTC3882, LTC3887, LTM4675, and LTM4676,
temp1 and temp2 report external temperatures, and
temp3 reports the chip temperature.
- On LTC2977, LTC2979, LTC2980, LTC2978, and LTM2987,
only one temperature measurement is supported and
reports the chip temperature.
- On LTC3880, LTC3882, LTC3886, LTC3887, LTC3889,
LTM4664, LTM4675, LTM4676, LTM4677, LTM4678, LTM4680,
and LTM4700, temp1 and temp2 report external
temperatures, and temp3 reports the chip temperature.
- On LTC3883, temp1 reports an external temperature,
and temp2 reports the chip temperature.
temp[N]_min Mimimum temperature.
LTC2974, LCT2977, LTM2980, LTC2978, and LTM2987 only.
LTC2972, LTC2974, LCT2977, LTM2980, LTC2978,
LTC2979, and LTM2987 only.
temp[N]_max Maximum temperature.
@ -257,8 +346,8 @@ temp[N]_crit Critical high temperature.
temp[N]_min_alarm Temperature low alarm.
LTC2974, LTC2975, LTC2977, LTM2980, LTC2978, and
LTM2987 only.
LTC2972, LTC2974, LTC2975, LTC2977, LTM2980, LTC2978,
LTC2979, and LTM2987 only.
temp[N]_max_alarm Temperature high alarm.
@ -269,8 +358,8 @@ temp[N]_crit_alarm Temperature critical high alarm.
temp[N]_lowest Lowest measured temperature.
- LTC2974, LTC2975, LTC2977, LTM2980, LTC2978, and
LTM2987 only.
- LTC2972, LTC2974, LTC2975, LTC2977, LTM2980, LTC2978,
LTC2979, and LTM2987 only.
- Not supported for chip temperature sensor on LTC2974
and LTC2975.
@ -290,19 +379,22 @@ power1_input Measured input power.
power[N]_label "pout[1-4]".
- LTC2972: N=1-2
- LTC2974, LTC2975: N=1-4
- LTC2977, LTC2980, LTM2987: Not supported
- LTC2977, LTC2979, LTC2980, LTM2987: Not supported
- LTC2978: Not supported
- LTC3880, LTC3882, LTC3886, LTC3887, LTM4675, LTM4676:
N=1-2
- LTC3880, LTC3882, LTC3884, LTC3886, LTC3887, LTC3889,
LTM4664, LTM4675, LTM4676, LTM4677, LTM4678, LTM4680,
LTM4700: N=1-2
- LTC3883: N=2
power[N]_input Measured output power.
curr1_label "iin".
LTC3880, LTC3883, LTC3886, LTC3887, LTM4675,
and LTM4676 only.
LTC3880, LTC3883, LTC3884, LTC3886, LTC3887, LTC3889,
LTM4644, LTM4675, LTM4676, LTM4677, LTM4678, LTM4680,
and LTM4700 only.
curr1_input Measured input current.
@ -320,11 +412,13 @@ curr1_reset_history Reset input current history.
curr[N]_label "iout[1-4]".
- LTC2972: N-1-2
- LTC2974, LTC2975: N=1-4
- LTC2977, LTC2980, LTM2987: not supported
- LTC2977, LTC2979, LTC2980, LTM2987: not supported
- LTC2978: not supported
- LTC3880, LTC3882, LTC3886, LTC3887, LTM4675, LTM4676:
N=2-3
- LTC3880, LTC3882, LTC3884, LTC3886, LTC3887, LTC3889,
LTM4664, LTM4675, LTM4676, LTM4677, LTM4678, LTM4680,
LTM4700: N=2-3
- LTC3883: N=2
curr[N]_input Measured output current.
@ -335,7 +429,7 @@ curr[N]_crit Critical high output current.
curr[N]_lcrit Critical low output current.
LTC2974 and LTC2975 only.
LTC2972, LTC2974 and LTC2975 only.
curr[N]_max_alarm Output current high alarm.
@ -343,11 +437,11 @@ curr[N]_crit_alarm Output current critical high alarm.
curr[N]_lcrit_alarm Output current critical low alarm.
LTC2974 and LTC2975 only.
LTC2972, LTC2974 and LTC2975 only.
curr[N]_lowest Lowest output current.
LTC2974 and LTC2975 only.
LTC2972, LTC2974 and LTC2975 only.
curr[N]_highest Highest output current.

Просмотреть файл

@ -162,9 +162,12 @@ Read byte from page <page>, register <reg>.
::
int (*read_word_data)(struct i2c_client *client, int page, int reg);
int (*read_word_data)(struct i2c_client *client, int page, int phase,
int reg);
Read word from page <page>, register <reg>.
Read word from page <page>, phase <pase>, register <reg>. If the chip does not
support multiple phases, the phase parameter can be ignored. If the chip
supports multiple phases, a phase value of 0xff indicates all phases.
::
@ -201,16 +204,21 @@ is mandatory.
::
int pmbus_set_page(struct i2c_client *client, u8 page);
int pmbus_set_page(struct i2c_client *client, u8 page, u8 phase);
Set PMBus page register to <page> for subsequent commands.
Set PMBus page register to <page> and <phase> for subsequent commands.
If the chip does not support multiple phases, the phase parameter is
ignored. Otherwise, a phase value of 0xff selects all phases.
::
int pmbus_read_word_data(struct i2c_client *client, u8 page, u8 reg);
int pmbus_read_word_data(struct i2c_client *client, u8 page, u8 phase,
u8 reg);
Read word data from <page>, <reg>. Similar to i2c_smbus_read_word_data(), but
selects page first.
Read word data from <page>, <phase>, <reg>. Similar to
i2c_smbus_read_word_data(), but selects page and phase first. If the chip does
not support multiple phases, the phase parameter is ignored. Otherwise, a phase
value of 0xff selects all phases.
::

Просмотреть файл

@ -227,7 +227,9 @@ currX_lcrit_alarm Output current critical low alarm.
From IOUT_UC_FAULT status.
currX_crit_alarm Current critical high alarm.
From IIN_OC_FAULT or IOUT_OC_FAULT status.
currX_label "iin" or "ioutY"
currX_label "iin", "iinY", "iinY.Z", "ioutY", or "ioutY.Z",
where Y reflects the page number and Z reflects the
phase.
powerX_input Measured power. From READ_PIN or READ_POUT register.
powerX_cap Output power cap. From POUT_MAX register.
@ -239,7 +241,9 @@ powerX_alarm Power high alarm.
From PIN_OP_WARNING or POUT_OP_WARNING status.
powerX_crit_alarm Output power critical high alarm.
From POUT_OP_FAULT status.
powerX_label "pin" or "poutY"
powerX_label "pin", "pinY", "pinY.Z", "poutY", or "poutY.Z",
where Y reflects the page number and Z reflects the
phase.
tempX_input Measured temperature.
From READ_TEMPERATURE_X register.

Просмотреть файл

@ -0,0 +1,178 @@
Kernel driver tps53679
======================
Supported chips:
* Texas Instruments TPS53647
Prefix: 'tps53647'
Addresses scanned: -
Datasheet: http://www.ti.com/lit/gpn/tps53647
* Texas Instruments TPS53667
Prefix: 'tps53667'
Addresses scanned: -
Datasheet: http://www.ti.com/lit/gpn/TPS53667
* Texas Instruments TPS53679
Prefix: 'tps53679'
Addresses scanned: -
Datasheet: http://www.ti.com/lit/gpn/TPS53679 (short version)
* Texas Instruments TPS53681
Prefix: 'tps53681'
Addresses scanned: -
Datasheet: http://www.ti.com/lit/gpn/TPS53681
* Texas Instruments TPS53688
Prefix: 'tps53688'
Addresses scanned: -
Datasheet: Available under NDA
Authors:
Vadim Pasternak <vadimp@mellanox.com>
Guenter Roeck <linux@roeck-us.net>
Description
-----------
Chips in this series are multi-phase step-down converters with one or two
output channels and up to 8 phases per channel.
Usage Notes
-----------
This driver does not probe for PMBus devices. You will have to instantiate
devices explicitly.
Example: the following commands will load the driver for an TPS53681 at address
0x60 on I2C bus #1::
# modprobe tps53679
# echo tps53681 0x60 > /sys/bus/i2c/devices/i2c-1/new_device
Sysfs attributes
----------------
======================= ========================================================
in1_label "vin"
in1_input Measured input voltage.
in1_lcrit Critical minimum input voltage
TPS53679, TPS53681, TPS53688 only.
in1_lcrit_alarm Input voltage critical low alarm.
TPS53679, TPS53681, TPS53688 only.
in1_crit Critical maximum input voltage.
in1_crit_alarm Input voltage critical high alarm.
in[N]_label "vout[1-2]"
- TPS53647, TPS53667: N=2
- TPS53679, TPS53588: N=2,3
in[N]_input Measured output voltage.
in[N]_lcrit Critical minimum input voltage.
TPS53679, TPS53681, TPS53688 only.
in[N]_lcrit_alarm Critical minimum voltage alarm.
TPS53679, TPS53681, TPS53688 only.
in[N]_alarm Output voltage alarm.
TPS53647, TPS53667 only.
in[N]_crit Critical maximum output voltage.
TPS53679, TPS53681, TPS53688 only.
in[N]_crit_alarm Output voltage critical high alarm.
TPS53679, TPS53681, TPS53688 only.
temp[N]_input Measured temperature.
- TPS53647, TPS53667: N=1
- TPS53679, TPS53681, TPS53588: N=1,2
temp[N]_max Maximum temperature.
temp[N]_crit Critical high temperature.
temp[N]_max_alarm Temperature high alarm.
temp[N]_crit_alarm Temperature critical high alarm.
power1_label "pin".
power1_input Measured input power.
power[N]_label "pout[1-2]".
- TPS53647, TPS53667: N=2
- TPS53679, TPS53681, TPS53588: N=2,3
power[N]_input Measured output power.
curr1_label "iin".
curr1_input Measured input current.
curr1_max Maximum input current.
curr1_max_alarm Input current high alarm.
curr1_crit Critical input current.
curr1_crit_alarm Input current critical alarm.
curr[N]_label "iout[1-2]" or "iout1.[0-5]".
The first digit is the output channel, the second
digit is the phase within the channel. Per-phase
telemetry supported on TPS53681 only.
- TPS53647, TPS53667: N=2
- TPS53679, TPS53588: N=2,3
- TPS53681: N=2-9
curr[N]_input Measured output current.
curr[N]_max Maximum output current.
curr[N]_crit Critical high output current.
curr[N]_max_alarm Output current high alarm.
curr[N]_crit_alarm Output current critical high alarm.
Limit and alarm attributes are only available for
non-phase telemetry (iout1, iout2).
======================= ========================================================

Просмотреть файл

@ -2957,6 +2957,14 @@ S: Maintained
F: Documentation/devicetree/bindings/sound/axentia,*
F: sound/soc/atmel/tse850-pcm5142.c
AXI-FAN-CONTROL HARDWARE MONITOR DRIVER
M: Nuno Sá <nuno.sa@analog.com>
W: http://ez.analog.com/community/linux-device-drivers
L: linux-hwmon@vger.kernel.org
S: Supported
F: drivers/hwmon/axi-fan-control.c
F: Documentation/devicetree/bindings/hwmon/adi,axi-fan-control.yaml
AXXIA I2C CONTROLLER
M: Krzysztof Adamski <krzysztof.adamski@nokia.com>
L: linux-i2c@vger.kernel.org

Просмотреть файл

@ -280,6 +280,15 @@ config SENSORS_ASC7621
This driver can also be built as a module. If so, the module
will be called asc7621.
config SENSORS_AXI_FAN_CONTROL
tristate "Analog Devices FAN Control HDL Core driver"
help
If you say yes here you get support for the Analog Devices
AXI HDL FAN monitoring core.
This driver can also be built as a module. If so, the module
will be called axi-fan-control
config SENSORS_K8TEMP
tristate "AMD Athlon64/FX or Opteron temperature sensor"
depends on X86 && PCI

Просмотреть файл

@ -52,6 +52,7 @@ obj-$(CONFIG_SENSORS_AS370) += as370-hwmon.o
obj-$(CONFIG_SENSORS_ASC7621) += asc7621.o
obj-$(CONFIG_SENSORS_ASPEED) += aspeed-pwm-tacho.o
obj-$(CONFIG_SENSORS_ATXP1) += atxp1.o
obj-$(CONFIG_SENSORS_AXI_FAN_CONTROL) += axi-fan-control.o
obj-$(CONFIG_SENSORS_CORETEMP) += coretemp.o
obj-$(CONFIG_SENSORS_DA9052_ADC)+= da9052-hwmon.o
obj-$(CONFIG_SENSORS_DA9055)+= da9055-hwmon.o

Просмотреть файл

@ -19,6 +19,7 @@
#include <linux/hwmon-vid.h>
#include <linux/err.h>
#include <linux/jiffies.h>
#include <linux/of.h>
#include <linux/util_macros.h>
/* Indexes for the sysfs hooks */
@ -193,6 +194,7 @@ struct adt7475_data {
unsigned long measure_updated;
bool valid;
u8 config2;
u8 config4;
u8 config5;
u8 has_voltage;
@ -1458,6 +1460,85 @@ static int adt7475_update_limits(struct i2c_client *client)
return 0;
}
static int set_property_bit(const struct i2c_client *client, char *property,
u8 *config, u8 bit_index)
{
u32 prop_value = 0;
int ret = of_property_read_u32(client->dev.of_node, property,
&prop_value);
if (!ret) {
if (prop_value)
*config |= (1 << bit_index);
else
*config &= ~(1 << bit_index);
}
return ret;
}
static int load_attenuators(const struct i2c_client *client, int chip,
struct adt7475_data *data)
{
int ret;
if (chip == adt7476 || chip == adt7490) {
set_property_bit(client, "adi,bypass-attenuator-in0",
&data->config4, 4);
set_property_bit(client, "adi,bypass-attenuator-in1",
&data->config4, 5);
set_property_bit(client, "adi,bypass-attenuator-in3",
&data->config4, 6);
set_property_bit(client, "adi,bypass-attenuator-in4",
&data->config4, 7);
ret = i2c_smbus_write_byte_data(client, REG_CONFIG4,
data->config4);
if (ret < 0)
return ret;
} else if (chip == adt7473 || chip == adt7475) {
set_property_bit(client, "adi,bypass-attenuator-in1",
&data->config2, 5);
ret = i2c_smbus_write_byte_data(client, REG_CONFIG2,
data->config2);
if (ret < 0)
return ret;
}
return 0;
}
static int adt7475_set_pwm_polarity(struct i2c_client *client)
{
u32 states[ADT7475_PWM_COUNT];
int ret, i;
u8 val;
ret = of_property_read_u32_array(client->dev.of_node,
"adi,pwm-active-state", states,
ARRAY_SIZE(states));
if (ret)
return ret;
for (i = 0; i < ADT7475_PWM_COUNT; i++) {
ret = adt7475_read(PWM_CONFIG_REG(i));
if (ret < 0)
return ret;
val = ret;
if (states[i])
val &= ~BIT(4);
else
val |= BIT(4);
ret = i2c_smbus_write_byte_data(client, PWM_CONFIG_REG(i), val);
if (ret)
return ret;
}
return 0;
}
static int adt7475_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
@ -1472,7 +1553,7 @@ static int adt7475_probe(struct i2c_client *client,
struct adt7475_data *data;
struct device *hwmon_dev;
int i, ret = 0, revision, group_num = 0;
u8 config2, config3;
u8 config3;
data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
if (data == NULL)
@ -1546,8 +1627,12 @@ static int adt7475_probe(struct i2c_client *client,
}
/* Voltage attenuators can be bypassed, globally or individually */
config2 = adt7475_read(REG_CONFIG2);
if (config2 & CONFIG2_ATTN) {
data->config2 = adt7475_read(REG_CONFIG2);
ret = load_attenuators(client, chip, data);
if (ret)
dev_warn(&client->dev, "Error configuring attenuator bypass\n");
if (data->config2 & CONFIG2_ATTN) {
data->bypass_attn = (0x3 << 3) | 0x3;
} else {
data->bypass_attn = ((data->config4 & CONFIG4_ATTN_IN10) >> 4) |
@ -1562,6 +1647,10 @@ static int adt7475_probe(struct i2c_client *client,
for (i = 0; i < ADT7475_PWM_COUNT; i++)
adt7475_read_pwm(client, i);
ret = adt7475_set_pwm_polarity(client);
if (ret && ret != -EINVAL)
dev_warn(&client->dev, "Error configuring pwm polarity\n");
/* Start monitoring */
switch (chip) {
case adt7475:

Просмотреть файл

@ -0,0 +1,469 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Fan Control HDL CORE driver
*
* Copyright 2019 Analog Devices Inc.
*/
#include <linux/bits.h>
#include <linux/clk.h>
#include <linux/fpga/adi-axi-common.h>
#include <linux/hwmon.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#define ADI_AXI_PCORE_VER_MAJOR(version) (((version) >> 16) & 0xff)
#define ADI_AXI_PCORE_VER_MINOR(version) (((version) >> 8) & 0xff)
#define ADI_AXI_PCORE_VER_PATCH(version) ((version) & 0xff)
/* register map */
#define ADI_REG_RSTN 0x0080
#define ADI_REG_PWM_WIDTH 0x0084
#define ADI_REG_TACH_PERIOD 0x0088
#define ADI_REG_TACH_TOLERANCE 0x008c
#define ADI_REG_PWM_PERIOD 0x00c0
#define ADI_REG_TACH_MEASUR 0x00c4
#define ADI_REG_TEMPERATURE 0x00c8
#define ADI_REG_IRQ_MASK 0x0040
#define ADI_REG_IRQ_PENDING 0x0044
#define ADI_REG_IRQ_SRC 0x0048
/* IRQ sources */
#define ADI_IRQ_SRC_PWM_CHANGED BIT(0)
#define ADI_IRQ_SRC_TACH_ERR BIT(1)
#define ADI_IRQ_SRC_TEMP_INCREASE BIT(2)
#define ADI_IRQ_SRC_NEW_MEASUR BIT(3)
#define ADI_IRQ_SRC_MASK GENMASK(3, 0)
#define ADI_IRQ_MASK_OUT_ALL 0xFFFFFFFFU
#define SYSFS_PWM_MAX 255
struct axi_fan_control_data {
void __iomem *base;
struct device *hdev;
unsigned long clk_rate;
int irq;
/* pulses per revolution */
u32 ppr;
bool hw_pwm_req;
bool update_tacho_params;
u8 fan_fault;
};
static inline void axi_iowrite(const u32 val, const u32 reg,
const struct axi_fan_control_data *ctl)
{
iowrite32(val, ctl->base + reg);
}
static inline u32 axi_ioread(const u32 reg,
const struct axi_fan_control_data *ctl)
{
return ioread32(ctl->base + reg);
}
static long axi_fan_control_get_pwm_duty(const struct axi_fan_control_data *ctl)
{
u32 pwm_width = axi_ioread(ADI_REG_PWM_WIDTH, ctl);
u32 pwm_period = axi_ioread(ADI_REG_PWM_PERIOD, ctl);
/*
* PWM_PERIOD is a RO register set by the core. It should never be 0.
* For now we are trusting the HW...
*/
return DIV_ROUND_CLOSEST(pwm_width * SYSFS_PWM_MAX, pwm_period);
}
static int axi_fan_control_set_pwm_duty(const long val,
struct axi_fan_control_data *ctl)
{
u32 pwm_period = axi_ioread(ADI_REG_PWM_PERIOD, ctl);
u32 new_width;
long __val = clamp_val(val, 0, SYSFS_PWM_MAX);
new_width = DIV_ROUND_CLOSEST(__val * pwm_period, SYSFS_PWM_MAX);
axi_iowrite(new_width, ADI_REG_PWM_WIDTH, ctl);
return 0;
}
static long axi_fan_control_get_fan_rpm(const struct axi_fan_control_data *ctl)
{
const u32 tach = axi_ioread(ADI_REG_TACH_MEASUR, ctl);
if (tach == 0)
/* should we return error, EAGAIN maybe? */
return 0;
/*
* The tacho period should be:
* TACH = 60/(ppr * rpm), where rpm is revolutions per second
* and ppr is pulses per revolution.
* Given the tacho period, we can multiply it by the input clock
* so that we know how many clocks we need to have this period.
* From this, we can derive the RPM value.
*/
return DIV_ROUND_CLOSEST(60 * ctl->clk_rate, ctl->ppr * tach);
}
static int axi_fan_control_read_temp(struct device *dev, u32 attr, long *val)
{
struct axi_fan_control_data *ctl = dev_get_drvdata(dev);
long raw_temp;
switch (attr) {
case hwmon_temp_input:
raw_temp = axi_ioread(ADI_REG_TEMPERATURE, ctl);
/*
* The formula for the temperature is:
* T = (ADC * 501.3743 / 2^bits) - 273.6777
* It's multiplied by 1000 to have millidegrees as
* specified by the hwmon sysfs interface.
*/
*val = ((raw_temp * 501374) >> 16) - 273677;
return 0;
default:
return -ENOTSUPP;
}
}
static int axi_fan_control_read_fan(struct device *dev, u32 attr, long *val)
{
struct axi_fan_control_data *ctl = dev_get_drvdata(dev);
switch (attr) {
case hwmon_fan_fault:
*val = ctl->fan_fault;
/* clear it now */
ctl->fan_fault = 0;
return 0;
case hwmon_fan_input:
*val = axi_fan_control_get_fan_rpm(ctl);
return 0;
default:
return -ENOTSUPP;
}
}
static int axi_fan_control_read_pwm(struct device *dev, u32 attr, long *val)
{
struct axi_fan_control_data *ctl = dev_get_drvdata(dev);
switch (attr) {
case hwmon_pwm_input:
*val = axi_fan_control_get_pwm_duty(ctl);
return 0;
default:
return -ENOTSUPP;
}
}
static int axi_fan_control_write_pwm(struct device *dev, u32 attr, long val)
{
struct axi_fan_control_data *ctl = dev_get_drvdata(dev);
switch (attr) {
case hwmon_pwm_input:
return axi_fan_control_set_pwm_duty(val, ctl);
default:
return -ENOTSUPP;
}
}
static int axi_fan_control_read_labels(struct device *dev,
enum hwmon_sensor_types type,
u32 attr, int channel, const char **str)
{
switch (type) {
case hwmon_fan:
*str = "FAN";
return 0;
case hwmon_temp:
*str = "SYSMON4";
return 0;
default:
return -ENOTSUPP;
}
}
static int axi_fan_control_read(struct device *dev,
enum hwmon_sensor_types type,
u32 attr, int channel, long *val)
{
switch (type) {
case hwmon_fan:
return axi_fan_control_read_fan(dev, attr, val);
case hwmon_pwm:
return axi_fan_control_read_pwm(dev, attr, val);
case hwmon_temp:
return axi_fan_control_read_temp(dev, attr, val);
default:
return -ENOTSUPP;
}
}
static int axi_fan_control_write(struct device *dev,
enum hwmon_sensor_types type,
u32 attr, int channel, long val)
{
switch (type) {
case hwmon_pwm:
return axi_fan_control_write_pwm(dev, attr, val);
default:
return -ENOTSUPP;
}
}
static umode_t axi_fan_control_fan_is_visible(const u32 attr)
{
switch (attr) {
case hwmon_fan_input:
case hwmon_fan_fault:
case hwmon_fan_label:
return 0444;
default:
return 0;
}
}
static umode_t axi_fan_control_pwm_is_visible(const u32 attr)
{
switch (attr) {
case hwmon_pwm_input:
return 0644;
default:
return 0;
}
}
static umode_t axi_fan_control_temp_is_visible(const u32 attr)
{
switch (attr) {
case hwmon_temp_input:
case hwmon_temp_label:
return 0444;
default:
return 0;
}
}
static umode_t axi_fan_control_is_visible(const void *data,
enum hwmon_sensor_types type,
u32 attr, int channel)
{
switch (type) {
case hwmon_fan:
return axi_fan_control_fan_is_visible(attr);
case hwmon_pwm:
return axi_fan_control_pwm_is_visible(attr);
case hwmon_temp:
return axi_fan_control_temp_is_visible(attr);
default:
return 0;
}
}
/*
* This core has two main ways of changing the PWM duty cycle. It is done,
* either by a request from userspace (writing on pwm1_input) or by the
* core itself. When the change is done by the core, it will use predefined
* parameters to evaluate the tach signal and, on that case we cannot set them.
* On the other hand, when the request is done by the user, with some arbitrary
* value that the core does not now about, we have to provide the tach
* parameters so that, the core can evaluate the signal. On the IRQ handler we
* distinguish this by using the ADI_IRQ_SRC_TEMP_INCREASE interrupt. This tell
* us that the CORE requested a new duty cycle. After this, there is 5s delay
* on which the core waits for the fan rotation speed to stabilize. After this
* we get ADI_IRQ_SRC_PWM_CHANGED irq where we will decide if we need to set
* the tach parameters or not on the next tach measurement cycle (corresponding
* already to the ney duty cycle) based on the %ctl->hw_pwm_req flag.
*/
static irqreturn_t axi_fan_control_irq_handler(int irq, void *data)
{
struct axi_fan_control_data *ctl = (struct axi_fan_control_data *)data;
u32 irq_pending = axi_ioread(ADI_REG_IRQ_PENDING, ctl);
u32 clear_mask;
if (irq_pending & ADI_IRQ_SRC_NEW_MEASUR) {
if (ctl->update_tacho_params) {
u32 new_tach = axi_ioread(ADI_REG_TACH_MEASUR, ctl);
/* get 25% tolerance */
u32 tach_tol = DIV_ROUND_CLOSEST(new_tach * 25, 100);
/* set new tacho parameters */
axi_iowrite(new_tach, ADI_REG_TACH_PERIOD, ctl);
axi_iowrite(tach_tol, ADI_REG_TACH_TOLERANCE, ctl);
ctl->update_tacho_params = false;
}
}
if (irq_pending & ADI_IRQ_SRC_PWM_CHANGED) {
/*
* if the pwm changes on behalf of software,
* we need to provide new tacho parameters to the core.
* Wait for the next measurement for that...
*/
if (!ctl->hw_pwm_req) {
ctl->update_tacho_params = true;
} else {
ctl->hw_pwm_req = false;
sysfs_notify(&ctl->hdev->kobj, NULL, "pwm1");
}
}
if (irq_pending & ADI_IRQ_SRC_TEMP_INCREASE)
/* hardware requested a new pwm */
ctl->hw_pwm_req = true;
if (irq_pending & ADI_IRQ_SRC_TACH_ERR)
ctl->fan_fault = 1;
/* clear all interrupts */
clear_mask = irq_pending & ADI_IRQ_SRC_MASK;
axi_iowrite(clear_mask, ADI_REG_IRQ_PENDING, ctl);
return IRQ_HANDLED;
}
static int axi_fan_control_init(struct axi_fan_control_data *ctl,
const struct device_node *np)
{
int ret;
/* get fan pulses per revolution */
ret = of_property_read_u32(np, "pulses-per-revolution", &ctl->ppr);
if (ret)
return ret;
/* 1, 2 and 4 are the typical and accepted values */
if (ctl->ppr != 1 && ctl->ppr != 2 && ctl->ppr != 4)
return -EINVAL;
/*
* Enable all IRQs
*/
axi_iowrite(ADI_IRQ_MASK_OUT_ALL &
~(ADI_IRQ_SRC_NEW_MEASUR | ADI_IRQ_SRC_TACH_ERR |
ADI_IRQ_SRC_PWM_CHANGED | ADI_IRQ_SRC_TEMP_INCREASE),
ADI_REG_IRQ_MASK, ctl);
/* bring the device out of reset */
axi_iowrite(0x01, ADI_REG_RSTN, ctl);
return ret;
}
static const struct hwmon_channel_info *axi_fan_control_info[] = {
HWMON_CHANNEL_INFO(pwm, HWMON_PWM_INPUT),
HWMON_CHANNEL_INFO(fan, HWMON_F_INPUT | HWMON_F_FAULT | HWMON_F_LABEL),
HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT | HWMON_T_LABEL),
NULL
};
static const struct hwmon_ops axi_fan_control_hwmon_ops = {
.is_visible = axi_fan_control_is_visible,
.read = axi_fan_control_read,
.write = axi_fan_control_write,
.read_string = axi_fan_control_read_labels,
};
static const struct hwmon_chip_info axi_chip_info = {
.ops = &axi_fan_control_hwmon_ops,
.info = axi_fan_control_info,
};
static const u32 version_1_0_0 = ADI_AXI_PCORE_VER(1, 0, 'a');
static const struct of_device_id axi_fan_control_of_match[] = {
{ .compatible = "adi,axi-fan-control-1.00.a",
.data = (void *)&version_1_0_0},
{},
};
MODULE_DEVICE_TABLE(of, axi_fan_control_of_match);
static int axi_fan_control_probe(struct platform_device *pdev)
{
struct axi_fan_control_data *ctl;
struct clk *clk;
const struct of_device_id *id;
const char *name = "axi_fan_control";
u32 version;
int ret;
id = of_match_node(axi_fan_control_of_match, pdev->dev.of_node);
if (!id)
return -EINVAL;
ctl = devm_kzalloc(&pdev->dev, sizeof(*ctl), GFP_KERNEL);
if (!ctl)
return -ENOMEM;
ctl->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(ctl->base))
return PTR_ERR(ctl->base);
clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(clk)) {
dev_err(&pdev->dev, "clk_get failed with %ld\n", PTR_ERR(clk));
return PTR_ERR(clk);
}
ctl->clk_rate = clk_get_rate(clk);
if (!ctl->clk_rate)
return -EINVAL;
version = axi_ioread(ADI_AXI_REG_VERSION, ctl);
if (ADI_AXI_PCORE_VER_MAJOR(version) !=
ADI_AXI_PCORE_VER_MAJOR((*(u32 *)id->data))) {
dev_err(&pdev->dev, "Major version mismatch. Expected %d.%.2d.%c, Reported %d.%.2d.%c\n",
ADI_AXI_PCORE_VER_MAJOR((*(u32 *)id->data)),
ADI_AXI_PCORE_VER_MINOR((*(u32 *)id->data)),
ADI_AXI_PCORE_VER_PATCH((*(u32 *)id->data)),
ADI_AXI_PCORE_VER_MAJOR(version),
ADI_AXI_PCORE_VER_MINOR(version),
ADI_AXI_PCORE_VER_PATCH(version));
return -ENODEV;
}
ctl->irq = platform_get_irq(pdev, 0);
if (ctl->irq < 0)
return ctl->irq;
ret = devm_request_threaded_irq(&pdev->dev, ctl->irq, NULL,
axi_fan_control_irq_handler,
IRQF_ONESHOT | IRQF_TRIGGER_HIGH,
pdev->driver_override, ctl);
if (ret) {
dev_err(&pdev->dev, "failed to request an irq, %d", ret);
return ret;
}
ret = axi_fan_control_init(ctl, pdev->dev.of_node);
if (ret) {
dev_err(&pdev->dev, "Failed to initialize device\n");
return ret;
}
ctl->hdev = devm_hwmon_device_register_with_info(&pdev->dev,
name,
ctl,
&axi_chip_info,
NULL);
return PTR_ERR_OR_ZERO(ctl->hdev);
}
static struct platform_driver axi_fan_control_driver = {
.driver = {
.name = "axi_fan_control_driver",
.of_match_table = axi_fan_control_of_match,
},
.probe = axi_fan_control_probe,
};
module_platform_driver(axi_fan_control_driver);
MODULE_AUTHOR("Nuno Sa <nuno.sa@analog.com>");
MODULE_DESCRIPTION("Analog Devices Fan Control HDL CORE driver");
MODULE_LICENSE("GPL");

Просмотреть файл

@ -219,7 +219,7 @@ struct aem_read_sensor_req {
struct aem_read_sensor_resp {
struct aem_iana_id id;
u8 bytes[0];
u8 bytes[];
} __packed;
/* Data structures to talk to the IPMI layer */

Просмотреть файл

@ -186,7 +186,7 @@ static void make_sensor_label(struct device_node *np,
u32 id;
size_t n;
n = snprintf(sdata->label, sizeof(sdata->label), "%s", label);
n = scnprintf(sdata->label, sizeof(sdata->label), "%s", label);
/*
* Core temp pretty print
@ -199,11 +199,11 @@ static void make_sensor_label(struct device_node *np,
* The digital thermal sensors are associated
* with a core.
*/
n += snprintf(sdata->label + n,
n += scnprintf(sdata->label + n,
sizeof(sdata->label) - n, " %d",
cpuid);
else
n += snprintf(sdata->label + n,
n += scnprintf(sdata->label + n,
sizeof(sdata->label) - n, " phy%d", id);
}
@ -211,7 +211,7 @@ static void make_sensor_label(struct device_node *np,
* Membuffer pretty print
*/
if (!of_property_read_u32(np, "ibm,chip-id", &id))
n += snprintf(sdata->label + n, sizeof(sdata->label) - n,
n += scnprintf(sdata->label + n, sizeof(sdata->label) - n,
" %d", id & 0xffff);
}

Просмотреть файл

@ -96,13 +96,20 @@ struct k10temp_data {
void (*read_tempreg)(struct pci_dev *pdev, u32 *regval);
int temp_offset;
u32 temp_adjust_mask;
bool show_tdie;
u32 show_tccd;
u32 show_temp;
u32 svi_addr[2];
bool is_zen;
bool show_current;
int cfactor[2];
};
#define TCTL_BIT 0
#define TDIE_BIT 1
#define TCCD_BIT(x) ((x) + 2)
#define HAVE_TEMP(d, channel) ((d)->show_temp & BIT(channel))
#define HAVE_TDIE(d) HAVE_TEMP(d, TDIE_BIT)
struct tctl_offset {
u8 model;
char const *id;
@ -180,8 +187,8 @@ static long get_raw_temp(struct k10temp_data *data)
}
const char *k10temp_temp_label[] = {
"Tdie",
"Tctl",
"Tdie",
"Tccd1",
"Tccd2",
"Tccd3",
@ -269,13 +276,13 @@ static int k10temp_read_temp(struct device *dev, u32 attr, int channel,
switch (attr) {
case hwmon_temp_input:
switch (channel) {
case 0: /* Tdie */
*val = get_raw_temp(data) - data->temp_offset;
case 0: /* Tctl */
*val = get_raw_temp(data);
if (*val < 0)
*val = 0;
break;
case 1: /* Tctl */
*val = get_raw_temp(data);
case 1: /* Tdie */
*val = get_raw_temp(data) - data->temp_offset;
if (*val < 0)
*val = 0;
break;
@ -333,23 +340,11 @@ static umode_t k10temp_is_visible(const void *_data,
case hwmon_temp:
switch (attr) {
case hwmon_temp_input:
switch (channel) {
case 0: /* Tdie, or Tctl if we don't show it */
break;
case 1: /* Tctl */
if (!data->show_tdie)
return 0;
break;
case 2 ... 9: /* Tccd{1-8} */
if (!(data->show_tccd & BIT(channel - 2)))
return 0;
break;
default:
if (!HAVE_TEMP(data, channel))
return 0;
}
break;
case hwmon_temp_max:
if (channel || data->show_tdie)
if (channel || data->is_zen)
return 0;
break;
case hwmon_temp_crit:
@ -368,20 +363,9 @@ static umode_t k10temp_is_visible(const void *_data,
return 0;
break;
case hwmon_temp_label:
/* No labels if we don't show the die temperature */
if (!data->show_tdie)
/* Show temperature labels only on Zen CPUs */
if (!data->is_zen || !HAVE_TEMP(data, channel))
return 0;
switch (channel) {
case 0: /* Tdie */
case 1: /* Tctl */
break;
case 2 ... 9: /* Tccd{1-8} */
if (!(data->show_tccd & BIT(channel - 2)))
return 0;
break;
default:
return 0;
}
break;
default:
return 0;
@ -480,7 +464,7 @@ static void k10temp_init_debugfs(struct k10temp_data *data)
char name[32];
/* Only show debugfs data for Family 17h/18h CPUs */
if (!data->show_tdie)
if (!data->is_zen)
return;
scnprintf(name, sizeof(name), "k10temp-%s", pci_name(data->pdev));
@ -546,7 +530,7 @@ static void k10temp_get_ccd_support(struct pci_dev *pdev,
amd_smn_read(amd_pci_dev_to_node_id(pdev),
F17H_M70H_CCD_TEMP(i), &regval);
if (regval & F17H_M70H_CCD_TEMP_VALID)
data->show_tccd |= BIT(i);
data->show_temp |= BIT(TCCD_BIT(i));
}
}
@ -573,6 +557,7 @@ static int k10temp_probe(struct pci_dev *pdev, const struct pci_device_id *id)
return -ENOMEM;
data->pdev = pdev;
data->show_temp |= BIT(TCTL_BIT); /* Always show Tctl */
if (boot_cpu_data.x86 == 0x15 &&
((boot_cpu_data.x86_model & 0xf0) == 0x60 ||
@ -582,7 +567,8 @@ static int k10temp_probe(struct pci_dev *pdev, const struct pci_device_id *id)
} 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->show_tdie = true;
data->show_temp |= BIT(TDIE_BIT); /* show Tdie */
data->is_zen = true;
switch (boot_cpu_data.x86_model) {
case 0x1: /* Zen */

Просмотреть файл

@ -262,10 +262,20 @@ static int lm73_detect(struct i2c_client *new_client,
return 0;
}
static const struct of_device_id lm73_of_match[] = {
{
.compatible = "ti,lm73",
},
{ },
};
MODULE_DEVICE_TABLE(of, lm73_of_match);
static struct i2c_driver lm73_driver = {
.class = I2C_CLASS_HWMON,
.driver = {
.name = "lm73",
.of_match_table = lm73_of_match,
},
.probe = lm73_probe,
.id_table = lm73_ids,

Просмотреть файл

@ -7,6 +7,11 @@
*
* Copyright (c) 2019 Advantech
* Author: Amy.Shih <amy.shih@advantech.com.tw>
*
* Supports the following chips:
*
* Chip #vin #fan #pwm #temp #dts chip ID
* nct7904d 20 12 4 5 8 0xc5
*/
#include <linux/module.h>
@ -820,6 +825,10 @@ static const struct hwmon_channel_info *nct7904_info[] = {
HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_ALARM,
HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_ALARM,
HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_ALARM,
HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_ALARM,
HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_ALARM,
HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_ALARM,
HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_ALARM,
HWMON_F_INPUT | HWMON_F_MIN | HWMON_F_ALARM),
HWMON_CHANNEL_INFO(pwm,
HWMON_PWM_INPUT | HWMON_PWM_ENABLE,
@ -853,6 +862,18 @@ static const struct hwmon_channel_info *nct7904_info[] = {
HWMON_T_CRIT_HYST,
HWMON_T_INPUT | HWMON_T_ALARM | HWMON_T_MAX |
HWMON_T_MAX_HYST | HWMON_T_TYPE | HWMON_T_CRIT |
HWMON_T_CRIT_HYST,
HWMON_T_INPUT | HWMON_T_ALARM | HWMON_T_MAX |
HWMON_T_MAX_HYST | HWMON_T_TYPE | HWMON_T_CRIT |
HWMON_T_CRIT_HYST,
HWMON_T_INPUT | HWMON_T_ALARM | HWMON_T_MAX |
HWMON_T_MAX_HYST | HWMON_T_TYPE | HWMON_T_CRIT |
HWMON_T_CRIT_HYST,
HWMON_T_INPUT | HWMON_T_ALARM | HWMON_T_MAX |
HWMON_T_MAX_HYST | HWMON_T_TYPE | HWMON_T_CRIT |
HWMON_T_CRIT_HYST,
HWMON_T_INPUT | HWMON_T_ALARM | HWMON_T_MAX |
HWMON_T_MAX_HYST | HWMON_T_TYPE | HWMON_T_CRIT |
HWMON_T_CRIT_HYST),
NULL
};

Просмотреть файл

@ -92,10 +92,10 @@ config SENSORS_IRPS5401
be called irps5401.
config SENSORS_ISL68137
tristate "Intersil ISL68137"
tristate "Renesas Digital Multiphase Voltage Regulators"
help
If you say yes here you get hardware monitoring support for Intersil
ISL68137.
If you say yes here you get hardware monitoring support for Renesas
digital multiphase voltage regulators.
This driver can also be built as a module. If so, the module will
be called isl68137.
@ -113,8 +113,8 @@ config SENSORS_LTC2978
tristate "Linear Technologies LTC2978 and compatibles"
help
If you say yes here you get hardware monitoring support for Linear
Technology LTC2974, LTC2975, LTC2977, LTC2978, LTC2980, LTC3880,
LTC3883, LTC3886, LTC3887, LTCM2987, LTM4675, and LTM4676.
Technology LTC2972, LTC2974, LTC2975, LTC2977, LTC2978, LTC2979,
LTC2980, and LTM2987.
This driver can also be built as a module. If so, the module will
be called ltc2978.
@ -123,9 +123,10 @@ config SENSORS_LTC2978_REGULATOR
bool "Regulator support for LTC2978 and compatibles"
depends on SENSORS_LTC2978 && REGULATOR
help
If you say yes here you get regulator support for Linear
Technology LTC2974, LTC2977, LTC2978, LTC3880, LTC3883, LTM4676
and LTM4686.
If you say yes here you get regulator support for Linear Technology
LTC3880, LTC3883, LTC3884, LTC3886, LTC3887, LTC3889, LTC7880,
LTM4644, LTM4675, LTM4676, LTM4677, LTM4678, LTM4680, LTM4686,
and LTM4700.
config SENSORS_LTC3815
tristate "Linear Technologies LTC3815"
@ -209,10 +210,10 @@ config SENSORS_TPS40422
be called tps40422.
config SENSORS_TPS53679
tristate "TI TPS53679, TPS53688"
tristate "TI TPS53647, TPS53667, TPS53679, TPS53681, TPS53688"
help
If you say yes here you get hardware monitoring support for TI
TPS53679, TPS53688
TPS53647, TPS53667, TPS53679, TPS53681, and TPS53688.
This driver can also be built as a module. If so, the module will
be called tps53679.

Просмотреть файл

@ -226,7 +226,8 @@ static int adm1275_write_pmon_config(const struct adm1275_data *data,
return ret;
}
static int adm1275_read_word_data(struct i2c_client *client, int page, int reg)
static int adm1275_read_word_data(struct i2c_client *client, int page,
int phase, int reg)
{
const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
const struct adm1275_data *data = to_adm1275_data(info);
@ -239,58 +240,68 @@ static int adm1275_read_word_data(struct i2c_client *client, int page, int reg)
case PMBUS_IOUT_UC_FAULT_LIMIT:
if (!data->have_uc_fault)
return -ENXIO;
ret = pmbus_read_word_data(client, 0, ADM1275_IOUT_WARN2_LIMIT);
ret = pmbus_read_word_data(client, 0, 0xff,
ADM1275_IOUT_WARN2_LIMIT);
break;
case PMBUS_IOUT_OC_FAULT_LIMIT:
if (!data->have_oc_fault)
return -ENXIO;
ret = pmbus_read_word_data(client, 0, ADM1275_IOUT_WARN2_LIMIT);
ret = pmbus_read_word_data(client, 0, 0xff,
ADM1275_IOUT_WARN2_LIMIT);
break;
case PMBUS_VOUT_OV_WARN_LIMIT:
if (data->have_vout)
return -ENODATA;
ret = pmbus_read_word_data(client, 0,
ret = pmbus_read_word_data(client, 0, 0xff,
ADM1075_VAUX_OV_WARN_LIMIT);
break;
case PMBUS_VOUT_UV_WARN_LIMIT:
if (data->have_vout)
return -ENODATA;
ret = pmbus_read_word_data(client, 0,
ret = pmbus_read_word_data(client, 0, 0xff,
ADM1075_VAUX_UV_WARN_LIMIT);
break;
case PMBUS_READ_VOUT:
if (data->have_vout)
return -ENODATA;
ret = pmbus_read_word_data(client, 0, ADM1075_READ_VAUX);
ret = pmbus_read_word_data(client, 0, 0xff,
ADM1075_READ_VAUX);
break;
case PMBUS_VIRT_READ_IOUT_MIN:
if (!data->have_iout_min)
return -ENXIO;
ret = pmbus_read_word_data(client, 0, ADM1293_IOUT_MIN);
ret = pmbus_read_word_data(client, 0, 0xff,
ADM1293_IOUT_MIN);
break;
case PMBUS_VIRT_READ_IOUT_MAX:
ret = pmbus_read_word_data(client, 0, ADM1275_PEAK_IOUT);
ret = pmbus_read_word_data(client, 0, 0xff,
ADM1275_PEAK_IOUT);
break;
case PMBUS_VIRT_READ_VOUT_MAX:
ret = pmbus_read_word_data(client, 0, ADM1275_PEAK_VOUT);
ret = pmbus_read_word_data(client, 0, 0xff,
ADM1275_PEAK_VOUT);
break;
case PMBUS_VIRT_READ_VIN_MAX:
ret = pmbus_read_word_data(client, 0, ADM1275_PEAK_VIN);
ret = pmbus_read_word_data(client, 0, 0xff,
ADM1275_PEAK_VIN);
break;
case PMBUS_VIRT_READ_PIN_MIN:
if (!data->have_pin_min)
return -ENXIO;
ret = pmbus_read_word_data(client, 0, ADM1293_PIN_MIN);
ret = pmbus_read_word_data(client, 0, 0xff,
ADM1293_PIN_MIN);
break;
case PMBUS_VIRT_READ_PIN_MAX:
if (!data->have_pin_max)
return -ENXIO;
ret = pmbus_read_word_data(client, 0, ADM1276_PEAK_PIN);
ret = pmbus_read_word_data(client, 0, 0xff,
ADM1276_PEAK_PIN);
break;
case PMBUS_VIRT_READ_TEMP_MAX:
if (!data->have_temp_max)
return -ENXIO;
ret = pmbus_read_word_data(client, 0, ADM1278_PEAK_TEMP);
ret = pmbus_read_word_data(client, 0, 0xff,
ADM1278_PEAK_TEMP);
break;
case PMBUS_VIRT_RESET_IOUT_HISTORY:
case PMBUS_VIRT_RESET_VOUT_HISTORY:

Просмотреть файл

@ -33,9 +33,12 @@
#define CFFPS_INPUT_HISTORY_CMD 0xD6
#define CFFPS_INPUT_HISTORY_SIZE 100
#define CFFPS_CCIN_REVISION GENMASK(7, 0)
#define CFFPS_CCIN_REVISION_LEGACY 0xde
#define CFFPS_CCIN_VERSION GENMASK(15, 8)
#define CFFPS_CCIN_VERSION_1 0x2b
#define CFFPS_CCIN_VERSION_2 0x2e
#define CFFPS_CCIN_VERSION_3 0x51
/* STATUS_MFR_SPECIFIC bits */
#define CFFPS_MFR_FAN_FAULT BIT(0)
@ -148,7 +151,7 @@ static ssize_t ibm_cffps_debugfs_read(struct file *file, char __user *buf,
struct ibm_cffps *psu = to_psu(idxp, idx);
char data[I2C_SMBUS_BLOCK_MAX + 2] = { 0 };
pmbus_set_page(psu->client, 0);
pmbus_set_page(psu->client, 0, 0xff);
switch (idx) {
case CFFPS_DEBUGFS_INPUT_HISTORY:
@ -247,7 +250,7 @@ static ssize_t ibm_cffps_debugfs_write(struct file *file,
switch (idx) {
case CFFPS_DEBUGFS_ON_OFF_CONFIG:
pmbus_set_page(psu->client, 0);
pmbus_set_page(psu->client, 0, 0xff);
rc = simple_write_to_buffer(&data, 1, ppos, buf, count);
if (rc <= 0)
@ -325,13 +328,13 @@ static int ibm_cffps_read_byte_data(struct i2c_client *client, int page,
}
static int ibm_cffps_read_word_data(struct i2c_client *client, int page,
int reg)
int phase, int reg)
{
int rc, mfr;
switch (reg) {
case PMBUS_STATUS_WORD:
rc = pmbus_read_word_data(client, page, reg);
rc = pmbus_read_word_data(client, page, phase, reg);
if (rc < 0)
return rc;
@ -348,7 +351,8 @@ static int ibm_cffps_read_word_data(struct i2c_client *client, int page,
rc |= PB_STATUS_OFF;
break;
case PMBUS_VIRT_READ_VMON:
rc = pmbus_read_word_data(client, page, CFFPS_12VCS_VOUT_CMD);
rc = pmbus_read_word_data(client, page, phase,
CFFPS_12VCS_VOUT_CMD);
break;
default:
rc = -ENODATA;
@ -379,7 +383,7 @@ static int ibm_cffps_led_brightness_set(struct led_classdev *led_cdev,
dev_dbg(&psu->client->dev, "LED brightness set: %d. Command: %d.\n",
brightness, next_led_state);
pmbus_set_page(psu->client, 0);
pmbus_set_page(psu->client, 0, 0xff);
rc = i2c_smbus_write_byte_data(psu->client, CFFPS_SYS_CONFIG_CMD,
next_led_state);
@ -401,7 +405,7 @@ static int ibm_cffps_led_blink_set(struct led_classdev *led_cdev,
dev_dbg(&psu->client->dev, "LED blink set.\n");
pmbus_set_page(psu->client, 0);
pmbus_set_page(psu->client, 0, 0xff);
rc = i2c_smbus_write_byte_data(psu->client, CFFPS_SYS_CONFIG_CMD,
CFFPS_LED_BLINK);
@ -485,11 +489,14 @@ static int ibm_cffps_probe(struct i2c_client *client,
vs = (enum versions)id->driver_data;
if (vs == cffps_unknown) {
u16 ccin_revision = 0;
u16 ccin_version = CFFPS_CCIN_VERSION_1;
int ccin = i2c_smbus_read_word_swapped(client, CFFPS_CCIN_CMD);
if (ccin > 0)
if (ccin > 0) {
ccin_revision = FIELD_GET(CFFPS_CCIN_REVISION, ccin);
ccin_version = FIELD_GET(CFFPS_CCIN_VERSION, ccin);
}
switch (ccin_version) {
default:
@ -499,6 +506,12 @@ static int ibm_cffps_probe(struct i2c_client *client,
case CFFPS_CCIN_VERSION_2:
vs = cffps2;
break;
case CFFPS_CCIN_VERSION_3:
if (ccin_revision == CFFPS_CCIN_REVISION_LEGACY)
vs = cffps1;
else
vs = cffps2;
break;
}
/* Set the client name to include the version number. */

Просмотреть файл

@ -21,37 +21,42 @@
#define IR35221_MFR_IOUT_VALLEY 0xcb
#define IR35221_MFR_TEMP_VALLEY 0xcc
static int ir35221_read_word_data(struct i2c_client *client, int page, int reg)
static int ir35221_read_word_data(struct i2c_client *client, int page,
int phase, int reg)
{
int ret;
switch (reg) {
case PMBUS_VIRT_READ_VIN_MAX:
ret = pmbus_read_word_data(client, page, IR35221_MFR_VIN_PEAK);
ret = pmbus_read_word_data(client, page, phase,
IR35221_MFR_VIN_PEAK);
break;
case PMBUS_VIRT_READ_VOUT_MAX:
ret = pmbus_read_word_data(client, page, IR35221_MFR_VOUT_PEAK);
ret = pmbus_read_word_data(client, page, phase,
IR35221_MFR_VOUT_PEAK);
break;
case PMBUS_VIRT_READ_IOUT_MAX:
ret = pmbus_read_word_data(client, page, IR35221_MFR_IOUT_PEAK);
ret = pmbus_read_word_data(client, page, phase,
IR35221_MFR_IOUT_PEAK);
break;
case PMBUS_VIRT_READ_TEMP_MAX:
ret = pmbus_read_word_data(client, page, IR35221_MFR_TEMP_PEAK);
ret = pmbus_read_word_data(client, page, phase,
IR35221_MFR_TEMP_PEAK);
break;
case PMBUS_VIRT_READ_VIN_MIN:
ret = pmbus_read_word_data(client, page,
ret = pmbus_read_word_data(client, page, phase,
IR35221_MFR_VIN_VALLEY);
break;
case PMBUS_VIRT_READ_VOUT_MIN:
ret = pmbus_read_word_data(client, page,
ret = pmbus_read_word_data(client, page, phase,
IR35221_MFR_VOUT_VALLEY);
break;
case PMBUS_VIRT_READ_IOUT_MIN:
ret = pmbus_read_word_data(client, page,
ret = pmbus_read_word_data(client, page, phase,
IR35221_MFR_IOUT_VALLEY);
break;
case PMBUS_VIRT_READ_TEMP_MIN:
ret = pmbus_read_word_data(client, page,
ret = pmbus_read_word_data(client, page, phase,
IR35221_MFR_TEMP_VALLEY);
break;
default:

Просмотреть файл

@ -1,8 +1,9 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Hardware monitoring driver for Intersil ISL68137
* Hardware monitoring driver for Renesas Digital Multiphase Voltage Regulators
*
* Copyright (c) 2017 Google Inc
* Copyright (c) 2020 Renesas Electronics America
*
*/
@ -14,9 +15,19 @@
#include <linux/module.h>
#include <linux/string.h>
#include <linux/sysfs.h>
#include "pmbus.h"
#define ISL68137_VOUT_AVS 0x30
#define RAA_DMPVR2_READ_VMON 0xc8
enum versions {
isl68137,
raa_dmpvr2_1rail,
raa_dmpvr2_2rail,
raa_dmpvr2_3rail,
raa_dmpvr2_hv,
};
static ssize_t isl68137_avs_enable_show_page(struct i2c_client *client,
int page,
@ -49,7 +60,8 @@ static ssize_t isl68137_avs_enable_store_page(struct i2c_client *client,
* enabling AVS control is the workaround.
*/
if (op_val == ISL68137_VOUT_AVS) {
rc = pmbus_read_word_data(client, page, PMBUS_VOUT_COMMAND);
rc = pmbus_read_word_data(client, page, 0xff,
PMBUS_VOUT_COMMAND);
if (rc < 0)
return rc;
@ -98,13 +110,31 @@ static const struct attribute_group enable_group = {
.attrs = enable_attrs,
};
static const struct attribute_group *attribute_groups[] = {
static const struct attribute_group *isl68137_attribute_groups[] = {
&enable_group,
NULL,
};
static struct pmbus_driver_info isl68137_info = {
.pages = 2,
static int raa_dmpvr2_read_word_data(struct i2c_client *client, int page,
int phase, int reg)
{
int ret;
switch (reg) {
case PMBUS_VIRT_READ_VMON:
ret = pmbus_read_word_data(client, page, phase,
RAA_DMPVR2_READ_VMON);
break;
default:
ret = -ENODATA;
break;
}
return ret;
}
static struct pmbus_driver_info raa_dmpvr_info = {
.pages = 3,
.format[PSC_VOLTAGE_IN] = direct,
.format[PSC_VOLTAGE_OUT] = direct,
.format[PSC_CURRENT_IN] = direct,
@ -113,7 +143,7 @@ static struct pmbus_driver_info isl68137_info = {
.format[PSC_TEMPERATURE] = direct,
.m[PSC_VOLTAGE_IN] = 1,
.b[PSC_VOLTAGE_IN] = 0,
.R[PSC_VOLTAGE_IN] = 3,
.R[PSC_VOLTAGE_IN] = 2,
.m[PSC_VOLTAGE_OUT] = 1,
.b[PSC_VOLTAGE_OUT] = 0,
.R[PSC_VOLTAGE_OUT] = 3,
@ -133,24 +163,76 @@ static struct pmbus_driver_info isl68137_info = {
| PMBUS_HAVE_STATUS_INPUT | PMBUS_HAVE_TEMP | PMBUS_HAVE_TEMP2
| PMBUS_HAVE_TEMP3 | PMBUS_HAVE_STATUS_TEMP
| PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
| PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT | PMBUS_HAVE_POUT,
.func[1] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
| PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT | PMBUS_HAVE_POUT,
.groups = attribute_groups,
| PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT | PMBUS_HAVE_POUT
| PMBUS_HAVE_VMON,
.func[1] = PMBUS_HAVE_IIN | PMBUS_HAVE_PIN | PMBUS_HAVE_STATUS_INPUT
| PMBUS_HAVE_TEMP | PMBUS_HAVE_TEMP3 | PMBUS_HAVE_STATUS_TEMP
| PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_IOUT
| PMBUS_HAVE_STATUS_IOUT | PMBUS_HAVE_POUT,
.func[2] = PMBUS_HAVE_IIN | PMBUS_HAVE_PIN | PMBUS_HAVE_STATUS_INPUT
| PMBUS_HAVE_TEMP | PMBUS_HAVE_TEMP3 | PMBUS_HAVE_STATUS_TEMP
| PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_IOUT
| PMBUS_HAVE_STATUS_IOUT | PMBUS_HAVE_POUT,
};
static int isl68137_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
return pmbus_do_probe(client, id, &isl68137_info);
struct pmbus_driver_info *info;
info = devm_kzalloc(&client->dev, sizeof(*info), GFP_KERNEL);
if (!info)
return -ENOMEM;
memcpy(info, &raa_dmpvr_info, sizeof(*info));
switch (id->driver_data) {
case isl68137:
info->pages = 2;
info->R[PSC_VOLTAGE_IN] = 3;
info->func[0] &= ~PMBUS_HAVE_VMON;
info->func[1] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
| PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT
| PMBUS_HAVE_POUT;
info->groups = isl68137_attribute_groups;
break;
case raa_dmpvr2_1rail:
info->pages = 1;
info->read_word_data = raa_dmpvr2_read_word_data;
break;
case raa_dmpvr2_2rail:
info->pages = 2;
info->read_word_data = raa_dmpvr2_read_word_data;
break;
case raa_dmpvr2_3rail:
info->read_word_data = raa_dmpvr2_read_word_data;
break;
case raa_dmpvr2_hv:
info->pages = 1;
info->R[PSC_VOLTAGE_IN] = 1;
info->m[PSC_VOLTAGE_OUT] = 2;
info->R[PSC_VOLTAGE_OUT] = 2;
info->m[PSC_CURRENT_IN] = 2;
info->m[PSC_POWER] = 2;
info->R[PSC_POWER] = -1;
info->read_word_data = raa_dmpvr2_read_word_data;
break;
default:
return -ENODEV;
}
return pmbus_do_probe(client, id, info);
}
static const struct i2c_device_id isl68137_id[] = {
{"isl68137", 0},
static const struct i2c_device_id raa_dmpvr_id[] = {
{"isl68137", isl68137},
{"raa_dmpvr2_1rail", raa_dmpvr2_1rail},
{"raa_dmpvr2_2rail", raa_dmpvr2_2rail},
{"raa_dmpvr2_3rail", raa_dmpvr2_3rail},
{"raa_dmpvr2_hv", raa_dmpvr2_hv},
{}
};
MODULE_DEVICE_TABLE(i2c, isl68137_id);
MODULE_DEVICE_TABLE(i2c, raa_dmpvr_id);
/* This is the driver that will be inserted */
static struct i2c_driver isl68137_driver = {
@ -159,11 +241,11 @@ static struct i2c_driver isl68137_driver = {
},
.probe = isl68137_probe,
.remove = pmbus_do_remove,
.id_table = isl68137_id,
.id_table = raa_dmpvr_id,
};
module_i2c_driver(isl68137_driver);
MODULE_AUTHOR("Maxim Sloyko <maxims@google.com>");
MODULE_DESCRIPTION("PMBus driver for Intersil ISL68137");
MODULE_DESCRIPTION("PMBus driver for Renesas digital multiphase voltage regulators");
MODULE_LICENSE("GPL");

Просмотреть файл

@ -211,7 +211,8 @@ struct lm25066_data {
#define to_lm25066_data(x) container_of(x, struct lm25066_data, info)
static int lm25066_read_word_data(struct i2c_client *client, int page, int reg)
static int lm25066_read_word_data(struct i2c_client *client, int page,
int phase, int reg)
{
const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
const struct lm25066_data *data = to_lm25066_data(info);
@ -219,7 +220,7 @@ static int lm25066_read_word_data(struct i2c_client *client, int page, int reg)
switch (reg) {
case PMBUS_VIRT_READ_VMON:
ret = pmbus_read_word_data(client, 0, LM25066_READ_VAUX);
ret = pmbus_read_word_data(client, 0, 0xff, LM25066_READ_VAUX);
if (ret < 0)
break;
/* Adjust returned value to match VIN coefficients */
@ -244,33 +245,40 @@ static int lm25066_read_word_data(struct i2c_client *client, int page, int reg)
}
break;
case PMBUS_READ_IIN:
ret = pmbus_read_word_data(client, 0, LM25066_MFR_READ_IIN);
ret = pmbus_read_word_data(client, 0, 0xff,
LM25066_MFR_READ_IIN);
break;
case PMBUS_READ_PIN:
ret = pmbus_read_word_data(client, 0, LM25066_MFR_READ_PIN);
ret = pmbus_read_word_data(client, 0, 0xff,
LM25066_MFR_READ_PIN);
break;
case PMBUS_IIN_OC_WARN_LIMIT:
ret = pmbus_read_word_data(client, 0,
ret = pmbus_read_word_data(client, 0, 0xff,
LM25066_MFR_IIN_OC_WARN_LIMIT);
break;
case PMBUS_PIN_OP_WARN_LIMIT:
ret = pmbus_read_word_data(client, 0,
ret = pmbus_read_word_data(client, 0, 0xff,
LM25066_MFR_PIN_OP_WARN_LIMIT);
break;
case PMBUS_VIRT_READ_VIN_AVG:
ret = pmbus_read_word_data(client, 0, LM25066_READ_AVG_VIN);
ret = pmbus_read_word_data(client, 0, 0xff,
LM25066_READ_AVG_VIN);
break;
case PMBUS_VIRT_READ_VOUT_AVG:
ret = pmbus_read_word_data(client, 0, LM25066_READ_AVG_VOUT);
ret = pmbus_read_word_data(client, 0, 0xff,
LM25066_READ_AVG_VOUT);
break;
case PMBUS_VIRT_READ_IIN_AVG:
ret = pmbus_read_word_data(client, 0, LM25066_READ_AVG_IIN);
ret = pmbus_read_word_data(client, 0, 0xff,
LM25066_READ_AVG_IIN);
break;
case PMBUS_VIRT_READ_PIN_AVG:
ret = pmbus_read_word_data(client, 0, LM25066_READ_AVG_PIN);
ret = pmbus_read_word_data(client, 0, 0xff,
LM25066_READ_AVG_PIN);
break;
case PMBUS_VIRT_READ_PIN_MAX:
ret = pmbus_read_word_data(client, 0, LM25066_READ_PIN_PEAK);
ret = pmbus_read_word_data(client, 0, 0xff,
LM25066_READ_PIN_PEAK);
break;
case PMBUS_VIRT_RESET_PIN_HISTORY:
ret = 0;
@ -288,13 +296,14 @@ static int lm25066_read_word_data(struct i2c_client *client, int page, int reg)
return ret;
}
static int lm25056_read_word_data(struct i2c_client *client, int page, int reg)
static int lm25056_read_word_data(struct i2c_client *client, int page,
int phase, int reg)
{
int ret;
switch (reg) {
case PMBUS_VIRT_VMON_UV_WARN_LIMIT:
ret = pmbus_read_word_data(client, 0,
ret = pmbus_read_word_data(client, 0, 0xff,
LM25056_VAUX_UV_WARN_LIMIT);
if (ret < 0)
break;
@ -302,7 +311,7 @@ static int lm25056_read_word_data(struct i2c_client *client, int page, int reg)
ret = DIV_ROUND_CLOSEST(ret * 293, 6140);
break;
case PMBUS_VIRT_VMON_OV_WARN_LIMIT:
ret = pmbus_read_word_data(client, 0,
ret = pmbus_read_word_data(client, 0, 0xff,
LM25056_VAUX_OV_WARN_LIMIT);
if (ret < 0)
break;
@ -310,7 +319,7 @@ static int lm25056_read_word_data(struct i2c_client *client, int page, int reg)
ret = DIV_ROUND_CLOSEST(ret * 293, 6140);
break;
default:
ret = lm25066_read_word_data(client, page, reg);
ret = lm25066_read_word_data(client, page, phase, reg);
break;
}
return ret;

Просмотреть файл

@ -19,8 +19,15 @@
#include <linux/regulator/driver.h>
#include "pmbus.h"
enum chips { ltc2974, ltc2975, ltc2977, ltc2978, ltc2980, ltc3880, ltc3882,
ltc3883, ltc3886, ltc3887, ltm2987, ltm4675, ltm4676, ltm4686 };
enum chips {
/* Managers */
ltc2972, ltc2974, ltc2975, ltc2977, ltc2978, ltc2979, ltc2980,
/* Controllers */
ltc3880, ltc3882, ltc3883, ltc3884, ltc3886, ltc3887, ltc3889, ltc7880,
/* Modules */
ltm2987, ltm4664, ltm4675, ltm4676, ltm4677, ltm4678, ltm4680, ltm4686,
ltm4700,
};
/* Common for all chips */
#define LTC2978_MFR_VOUT_PEAK 0xdd
@ -43,9 +50,10 @@ enum chips { ltc2974, ltc2975, ltc2977, ltc2978, ltc2980, ltc3880, ltc3882,
#define LTC3880_MFR_CLEAR_PEAKS 0xe3
#define LTC3880_MFR_TEMPERATURE2_PEAK 0xf4
/* LTC3883 and LTC3886 only */
/* LTC3883, LTC3884, LTC3886, LTC3889 and LTC7880 only */
#define LTC3883_MFR_IIN_PEAK 0xe1
/* LTC2975 only */
#define LTC2975_MFR_IIN_PEAK 0xc4
#define LTC2975_MFR_IIN_MIN 0xc5
@ -54,27 +62,41 @@ enum chips { ltc2974, ltc2975, ltc2977, ltc2978, ltc2980, ltc3880, ltc3882,
#define LTC2978_ID_MASK 0xfff0
#define LTC2972_ID 0x0310
#define LTC2974_ID 0x0210
#define LTC2975_ID 0x0220
#define LTC2977_ID 0x0130
#define LTC2978_ID_REV1 0x0110 /* Early revision */
#define LTC2978_ID_REV2 0x0120
#define LTC2979_ID_A 0x8060
#define LTC2979_ID_B 0x8070
#define LTC2980_ID_A 0x8030 /* A/B for two die IDs */
#define LTC2980_ID_B 0x8040
#define LTC3880_ID 0x4020
#define LTC3882_ID 0x4200
#define LTC3882_ID_D1 0x4240 /* Dash 1 */
#define LTC3883_ID 0x4300
#define LTC3884_ID 0x4C00
#define LTC3886_ID 0x4600
#define LTC3887_ID 0x4700
#define LTM2987_ID_A 0x8010 /* A/B for two die IDs */
#define LTM2987_ID_B 0x8020
#define LTC3889_ID 0x4900
#define LTC7880_ID 0x49E0
#define LTM4664_ID 0x4120
#define LTM4675_ID 0x47a0
#define LTM4676_ID_REV1 0x4400
#define LTM4676_ID_REV2 0x4480
#define LTM4676A_ID 0x47e0
#define LTM4677_ID_REV1 0x47B0
#define LTM4677_ID_REV2 0x47D0
#define LTM4678_ID_REV1 0x4100
#define LTM4678_ID_REV2 0x4110
#define LTM4680_ID 0x4140
#define LTM4686_ID 0x4770
#define LTM4700_ID 0x4130
#define LTC2972_NUM_PAGES 2
#define LTC2974_NUM_PAGES 4
#define LTC2978_NUM_PAGES 8
#define LTC3880_NUM_PAGES 2
@ -151,7 +173,8 @@ static int ltc_wait_ready(struct i2c_client *client)
return -ETIMEDOUT;
}
static int ltc_read_word_data(struct i2c_client *client, int page, int reg)
static int ltc_read_word_data(struct i2c_client *client, int page, int phase,
int reg)
{
int ret;
@ -159,7 +182,7 @@ static int ltc_read_word_data(struct i2c_client *client, int page, int reg)
if (ret < 0)
return ret;
return pmbus_read_word_data(client, page, reg);
return pmbus_read_word_data(client, page, 0xff, reg);
}
static int ltc_read_byte_data(struct i2c_client *client, int page, int reg)
@ -202,7 +225,7 @@ static int ltc_get_max(struct ltc2978_data *data, struct i2c_client *client,
{
int ret;
ret = ltc_read_word_data(client, page, reg);
ret = ltc_read_word_data(client, page, 0xff, reg);
if (ret >= 0) {
if (lin11_to_val(ret) > lin11_to_val(*pmax))
*pmax = ret;
@ -216,7 +239,7 @@ static int ltc_get_min(struct ltc2978_data *data, struct i2c_client *client,
{
int ret;
ret = ltc_read_word_data(client, page, reg);
ret = ltc_read_word_data(client, page, 0xff, reg);
if (ret >= 0) {
if (lin11_to_val(ret) < lin11_to_val(*pmin))
*pmin = ret;
@ -238,7 +261,8 @@ static int ltc2978_read_word_data_common(struct i2c_client *client, int page,
&data->vin_max);
break;
case PMBUS_VIRT_READ_VOUT_MAX:
ret = ltc_read_word_data(client, page, LTC2978_MFR_VOUT_PEAK);
ret = ltc_read_word_data(client, page, 0xff,
LTC2978_MFR_VOUT_PEAK);
if (ret >= 0) {
/*
* VOUT is 16 bit unsigned with fixed exponent,
@ -269,7 +293,8 @@ static int ltc2978_read_word_data_common(struct i2c_client *client, int page,
return ret;
}
static int ltc2978_read_word_data(struct i2c_client *client, int page, int reg)
static int ltc2978_read_word_data(struct i2c_client *client, int page,
int phase, int reg)
{
const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
struct ltc2978_data *data = to_ltc2978_data(info);
@ -281,7 +306,8 @@ static int ltc2978_read_word_data(struct i2c_client *client, int page, int reg)
&data->vin_min);
break;
case PMBUS_VIRT_READ_VOUT_MIN:
ret = ltc_read_word_data(client, page, LTC2978_MFR_VOUT_MIN);
ret = ltc_read_word_data(client, page, phase,
LTC2978_MFR_VOUT_MIN);
if (ret >= 0) {
/*
* VOUT_MIN is known to not be supported on some lots
@ -314,7 +340,8 @@ static int ltc2978_read_word_data(struct i2c_client *client, int page, int reg)
return ret;
}
static int ltc2974_read_word_data(struct i2c_client *client, int page, int reg)
static int ltc2974_read_word_data(struct i2c_client *client, int page,
int phase, int reg)
{
const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
struct ltc2978_data *data = to_ltc2978_data(info);
@ -333,13 +360,14 @@ static int ltc2974_read_word_data(struct i2c_client *client, int page, int reg)
ret = 0;
break;
default:
ret = ltc2978_read_word_data(client, page, reg);
ret = ltc2978_read_word_data(client, page, phase, reg);
break;
}
return ret;
}
static int ltc2975_read_word_data(struct i2c_client *client, int page, int reg)
static int ltc2975_read_word_data(struct i2c_client *client, int page,
int phase, int reg)
{
const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
struct ltc2978_data *data = to_ltc2978_data(info);
@ -367,13 +395,14 @@ static int ltc2975_read_word_data(struct i2c_client *client, int page, int reg)
ret = 0;
break;
default:
ret = ltc2978_read_word_data(client, page, reg);
ret = ltc2978_read_word_data(client, page, phase, reg);
break;
}
return ret;
}
static int ltc3880_read_word_data(struct i2c_client *client, int page, int reg)
static int ltc3880_read_word_data(struct i2c_client *client, int page,
int phase, int reg)
{
const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
struct ltc2978_data *data = to_ltc2978_data(info);
@ -405,7 +434,8 @@ static int ltc3880_read_word_data(struct i2c_client *client, int page, int reg)
return ret;
}
static int ltc3883_read_word_data(struct i2c_client *client, int page, int reg)
static int ltc3883_read_word_data(struct i2c_client *client, int page,
int phase, int reg)
{
const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
struct ltc2978_data *data = to_ltc2978_data(info);
@ -420,7 +450,7 @@ static int ltc3883_read_word_data(struct i2c_client *client, int page, int reg)
ret = 0;
break;
default:
ret = ltc3880_read_word_data(client, page, reg);
ret = ltc3880_read_word_data(client, page, phase, reg);
break;
}
return ret;
@ -492,20 +522,30 @@ static int ltc2978_write_word_data(struct i2c_client *client, int page,
}
static const struct i2c_device_id ltc2978_id[] = {
{"ltc2972", ltc2972},
{"ltc2974", ltc2974},
{"ltc2975", ltc2975},
{"ltc2977", ltc2977},
{"ltc2978", ltc2978},
{"ltc2979", ltc2979},
{"ltc2980", ltc2980},
{"ltc3880", ltc3880},
{"ltc3882", ltc3882},
{"ltc3883", ltc3883},
{"ltc3884", ltc3884},
{"ltc3886", ltc3886},
{"ltc3887", ltc3887},
{"ltc3889", ltc3889},
{"ltc7880", ltc7880},
{"ltm2987", ltm2987},
{"ltm4664", ltm4664},
{"ltm4675", ltm4675},
{"ltm4676", ltm4676},
{"ltm4677", ltm4677},
{"ltm4678", ltm4678},
{"ltm4680", ltm4680},
{"ltm4686", ltm4686},
{"ltm4700", ltm4700},
{}
};
MODULE_DEVICE_TABLE(i2c, ltc2978_id);
@ -555,7 +595,9 @@ static int ltc2978_get_id(struct i2c_client *client)
chip_id &= LTC2978_ID_MASK;
if (chip_id == LTC2974_ID)
if (chip_id == LTC2972_ID)
return ltc2972;
else if (chip_id == LTC2974_ID)
return ltc2974;
else if (chip_id == LTC2975_ID)
return ltc2975;
@ -563,6 +605,8 @@ static int ltc2978_get_id(struct i2c_client *client)
return ltc2977;
else if (chip_id == LTC2978_ID_REV1 || chip_id == LTC2978_ID_REV2)
return ltc2978;
else if (chip_id == LTC2979_ID_A || chip_id == LTC2979_ID_B)
return ltc2979;
else if (chip_id == LTC2980_ID_A || chip_id == LTC2980_ID_B)
return ltc2980;
else if (chip_id == LTC3880_ID)
@ -571,19 +615,35 @@ static int ltc2978_get_id(struct i2c_client *client)
return ltc3882;
else if (chip_id == LTC3883_ID)
return ltc3883;
else if (chip_id == LTC3884_ID)
return ltc3884;
else if (chip_id == LTC3886_ID)
return ltc3886;
else if (chip_id == LTC3887_ID)
return ltc3887;
else if (chip_id == LTC3889_ID)
return ltc3889;
else if (chip_id == LTC7880_ID)
return ltc7880;
else if (chip_id == LTM2987_ID_A || chip_id == LTM2987_ID_B)
return ltm2987;
else if (chip_id == LTM4664_ID)
return ltm4664;
else if (chip_id == LTM4675_ID)
return ltm4675;
else if (chip_id == LTM4676_ID_REV1 || chip_id == LTM4676_ID_REV2 ||
chip_id == LTM4676A_ID)
return ltm4676;
else if (chip_id == LTM4677_ID_REV1 || chip_id == LTM4677_ID_REV2)
return ltm4677;
else if (chip_id == LTM4678_ID_REV1 || chip_id == LTM4678_ID_REV2)
return ltm4678;
else if (chip_id == LTM4680_ID)
return ltm4680;
else if (chip_id == LTM4686_ID)
return ltm4686;
else if (chip_id == LTM4700_ID)
return ltm4700;
dev_err(&client->dev, "Unsupported chip ID 0x%x\n", chip_id);
return -ENODEV;
@ -637,6 +697,19 @@ static int ltc2978_probe(struct i2c_client *client,
data->temp2_max = 0x7c00;
switch (data->id) {
case ltc2972:
info->read_word_data = ltc2975_read_word_data;
info->pages = LTC2972_NUM_PAGES;
info->func[0] = PMBUS_HAVE_IIN | PMBUS_HAVE_PIN
| PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT
| PMBUS_HAVE_TEMP2;
for (i = 0; i < info->pages; i++) {
info->func[i] |= PMBUS_HAVE_VOUT
| PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_POUT
| PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP
| PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT;
}
break;
case ltc2974:
info->read_word_data = ltc2974_read_word_data;
info->pages = LTC2974_NUM_PAGES;
@ -662,8 +735,10 @@ static int ltc2978_probe(struct i2c_client *client,
| PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT;
}
break;
case ltc2977:
case ltc2978:
case ltc2979:
case ltc2980:
case ltm2987:
info->read_word_data = ltc2978_read_word_data;
@ -680,6 +755,7 @@ static int ltc2978_probe(struct i2c_client *client,
case ltc3887:
case ltm4675:
case ltm4676:
case ltm4677:
case ltm4686:
data->features |= FEAT_CLEAR_PEAKS | FEAT_NEEDS_POLLING;
info->read_word_data = ltc3880_read_word_data;
@ -721,7 +797,14 @@ static int ltc2978_probe(struct i2c_client *client,
| PMBUS_HAVE_PIN | PMBUS_HAVE_POUT | PMBUS_HAVE_TEMP
| PMBUS_HAVE_TEMP2 | PMBUS_HAVE_STATUS_TEMP;
break;
case ltc3884:
case ltc3886:
case ltc3889:
case ltc7880:
case ltm4664:
case ltm4678:
case ltm4680:
case ltm4700:
data->features |= FEAT_CLEAR_PEAKS | FEAT_NEEDS_POLLING;
info->read_word_data = ltc3883_read_word_data;
info->pages = LTC3880_NUM_PAGES;
@ -752,22 +835,33 @@ static int ltc2978_probe(struct i2c_client *client,
return pmbus_do_probe(client, id, info);
}
#ifdef CONFIG_OF
static const struct of_device_id ltc2978_of_match[] = {
{ .compatible = "lltc,ltc2972" },
{ .compatible = "lltc,ltc2974" },
{ .compatible = "lltc,ltc2975" },
{ .compatible = "lltc,ltc2977" },
{ .compatible = "lltc,ltc2978" },
{ .compatible = "lltc,ltc2979" },
{ .compatible = "lltc,ltc2980" },
{ .compatible = "lltc,ltc3880" },
{ .compatible = "lltc,ltc3882" },
{ .compatible = "lltc,ltc3883" },
{ .compatible = "lltc,ltc3884" },
{ .compatible = "lltc,ltc3886" },
{ .compatible = "lltc,ltc3887" },
{ .compatible = "lltc,ltc3889" },
{ .compatible = "lltc,ltc7880" },
{ .compatible = "lltc,ltm2987" },
{ .compatible = "lltc,ltm4664" },
{ .compatible = "lltc,ltm4675" },
{ .compatible = "lltc,ltm4676" },
{ .compatible = "lltc,ltm4677" },
{ .compatible = "lltc,ltm4678" },
{ .compatible = "lltc,ltm4680" },
{ .compatible = "lltc,ltm4686" },
{ .compatible = "lltc,ltm4700" },
{ }
};
MODULE_DEVICE_TABLE(of, ltc2978_of_match);

Просмотреть файл

@ -55,7 +55,7 @@ static int ltc3815_write_byte(struct i2c_client *client, int page, u8 reg)
* LTC3815 does not support the CLEAR_FAULTS command.
* Emulate it by clearing the status register.
*/
ret = pmbus_read_word_data(client, 0, PMBUS_STATUS_WORD);
ret = pmbus_read_word_data(client, 0, 0xff, PMBUS_STATUS_WORD);
if (ret > 0) {
pmbus_write_word_data(client, 0, PMBUS_STATUS_WORD,
ret);
@ -69,25 +69,31 @@ static int ltc3815_write_byte(struct i2c_client *client, int page, u8 reg)
return ret;
}
static int ltc3815_read_word_data(struct i2c_client *client, int page, int reg)
static int ltc3815_read_word_data(struct i2c_client *client, int page,
int phase, int reg)
{
int ret;
switch (reg) {
case PMBUS_VIRT_READ_VIN_MAX:
ret = pmbus_read_word_data(client, page, LTC3815_MFR_VIN_PEAK);
ret = pmbus_read_word_data(client, page, phase,
LTC3815_MFR_VIN_PEAK);
break;
case PMBUS_VIRT_READ_VOUT_MAX:
ret = pmbus_read_word_data(client, page, LTC3815_MFR_VOUT_PEAK);
ret = pmbus_read_word_data(client, page, phase,
LTC3815_MFR_VOUT_PEAK);
break;
case PMBUS_VIRT_READ_TEMP_MAX:
ret = pmbus_read_word_data(client, page, LTC3815_MFR_TEMP_PEAK);
ret = pmbus_read_word_data(client, page, phase,
LTC3815_MFR_TEMP_PEAK);
break;
case PMBUS_VIRT_READ_IOUT_MAX:
ret = pmbus_read_word_data(client, page, LTC3815_MFR_IOUT_PEAK);
ret = pmbus_read_word_data(client, page, phase,
LTC3815_MFR_IOUT_PEAK);
break;
case PMBUS_VIRT_READ_IIN_MAX:
ret = pmbus_read_word_data(client, page, LTC3815_MFR_IIN_PEAK);
ret = pmbus_read_word_data(client, page, phase,
LTC3815_MFR_IIN_PEAK);
break;
case PMBUS_VIRT_RESET_VOUT_HISTORY:
case PMBUS_VIRT_RESET_VIN_HISTORY:

Просмотреть файл

@ -15,17 +15,18 @@
#define MAX16064_MFR_VOUT_PEAK 0xd4
#define MAX16064_MFR_TEMPERATURE_PEAK 0xd6
static int max16064_read_word_data(struct i2c_client *client, int page, int reg)
static int max16064_read_word_data(struct i2c_client *client, int page,
int phase, int reg)
{
int ret;
switch (reg) {
case PMBUS_VIRT_READ_VOUT_MAX:
ret = pmbus_read_word_data(client, page,
ret = pmbus_read_word_data(client, page, phase,
MAX16064_MFR_VOUT_PEAK);
break;
case PMBUS_VIRT_READ_TEMP_MAX:
ret = pmbus_read_word_data(client, page,
ret = pmbus_read_word_data(client, page, phase,
MAX16064_MFR_TEMPERATURE_PEAK);
break;
case PMBUS_VIRT_RESET_VOUT_HISTORY:

Просмотреть файл

@ -85,7 +85,8 @@ static u32 max_current[][5] = {
[max20743] = { 18900, 24100, 29200, 34100 },
};
static int max20730_read_word_data(struct i2c_client *client, int page, int reg)
static int max20730_read_word_data(struct i2c_client *client, int page,
int phase, int reg)
{
const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
const struct max20730_data *data = to_max20730_data(info);

Просмотреть файл

@ -72,7 +72,7 @@ static int max31785_read_long_data(struct i2c_client *client, int page,
cmdbuf[0] = reg;
rc = pmbus_set_page(client, page);
rc = pmbus_set_page(client, page, 0xff);
if (rc < 0)
return rc;
@ -110,7 +110,7 @@ static int max31785_get_pwm_mode(struct i2c_client *client, int page)
if (config < 0)
return config;
command = pmbus_read_word_data(client, page, PMBUS_FAN_COMMAND_1);
command = pmbus_read_word_data(client, page, 0xff, PMBUS_FAN_COMMAND_1);
if (command < 0)
return command;
@ -126,7 +126,7 @@ static int max31785_get_pwm_mode(struct i2c_client *client, int page)
}
static int max31785_read_word_data(struct i2c_client *client, int page,
int reg)
int phase, int reg)
{
u32 val;
int rv;

Просмотреть файл

@ -41,7 +41,8 @@ struct max34440_data {
#define to_max34440_data(x) container_of(x, struct max34440_data, info)
static int max34440_read_word_data(struct i2c_client *client, int page, int reg)
static int max34440_read_word_data(struct i2c_client *client, int page,
int phase, int reg)
{
int ret;
const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
@ -49,44 +50,44 @@ static int max34440_read_word_data(struct i2c_client *client, int page, int reg)
switch (reg) {
case PMBUS_VIRT_READ_VOUT_MIN:
ret = pmbus_read_word_data(client, page,
ret = pmbus_read_word_data(client, page, phase,
MAX34440_MFR_VOUT_MIN);
break;
case PMBUS_VIRT_READ_VOUT_MAX:
ret = pmbus_read_word_data(client, page,
ret = pmbus_read_word_data(client, page, phase,
MAX34440_MFR_VOUT_PEAK);
break;
case PMBUS_VIRT_READ_IOUT_AVG:
if (data->id != max34446 && data->id != max34451)
return -ENXIO;
ret = pmbus_read_word_data(client, page,
ret = pmbus_read_word_data(client, page, phase,
MAX34446_MFR_IOUT_AVG);
break;
case PMBUS_VIRT_READ_IOUT_MAX:
ret = pmbus_read_word_data(client, page,
ret = pmbus_read_word_data(client, page, phase,
MAX34440_MFR_IOUT_PEAK);
break;
case PMBUS_VIRT_READ_POUT_AVG:
if (data->id != max34446)
return -ENXIO;
ret = pmbus_read_word_data(client, page,
ret = pmbus_read_word_data(client, page, phase,
MAX34446_MFR_POUT_AVG);
break;
case PMBUS_VIRT_READ_POUT_MAX:
if (data->id != max34446)
return -ENXIO;
ret = pmbus_read_word_data(client, page,
ret = pmbus_read_word_data(client, page, phase,
MAX34446_MFR_POUT_PEAK);
break;
case PMBUS_VIRT_READ_TEMP_AVG:
if (data->id != max34446 && data->id != max34460 &&
data->id != max34461)
return -ENXIO;
ret = pmbus_read_word_data(client, page,
ret = pmbus_read_word_data(client, page, phase,
MAX34446_MFR_TEMPERATURE_AVG);
break;
case PMBUS_VIRT_READ_TEMP_MAX:
ret = pmbus_read_word_data(client, page,
ret = pmbus_read_word_data(client, page, phase,
MAX34440_MFR_TEMPERATURE_PEAK);
break;
case PMBUS_VIRT_RESET_POUT_HISTORY:
@ -159,14 +160,14 @@ static int max34440_read_byte_data(struct i2c_client *client, int page, int reg)
int mfg_status;
if (page >= 0) {
ret = pmbus_set_page(client, page);
ret = pmbus_set_page(client, page, 0xff);
if (ret < 0)
return ret;
}
switch (reg) {
case PMBUS_STATUS_IOUT:
mfg_status = pmbus_read_word_data(client, 0,
mfg_status = pmbus_read_word_data(client, 0, 0xff,
PMBUS_STATUS_MFR_SPECIFIC);
if (mfg_status < 0)
return mfg_status;
@ -176,7 +177,7 @@ static int max34440_read_byte_data(struct i2c_client *client, int page, int reg)
ret |= PB_IOUT_OC_FAULT;
break;
case PMBUS_STATUS_TEMPERATURE:
mfg_status = pmbus_read_word_data(client, 0,
mfg_status = pmbus_read_word_data(client, 0, 0xff,
PMBUS_STATUS_MFR_SPECIFIC);
if (mfg_status < 0)
return mfg_status;

Просмотреть файл

@ -28,7 +28,8 @@
#define MAX8688_STATUS_OT_FAULT BIT(13)
#define MAX8688_STATUS_OT_WARNING BIT(14)
static int max8688_read_word_data(struct i2c_client *client, int page, int reg)
static int max8688_read_word_data(struct i2c_client *client, int page,
int phase, int reg)
{
int ret;
@ -37,13 +38,15 @@ static int max8688_read_word_data(struct i2c_client *client, int page, int reg)
switch (reg) {
case PMBUS_VIRT_READ_VOUT_MAX:
ret = pmbus_read_word_data(client, 0, MAX8688_MFR_VOUT_PEAK);
ret = pmbus_read_word_data(client, 0, 0xff,
MAX8688_MFR_VOUT_PEAK);
break;
case PMBUS_VIRT_READ_IOUT_MAX:
ret = pmbus_read_word_data(client, 0, MAX8688_MFR_IOUT_PEAK);
ret = pmbus_read_word_data(client, 0, 0xff,
MAX8688_MFR_IOUT_PEAK);
break;
case PMBUS_VIRT_READ_TEMP_MAX:
ret = pmbus_read_word_data(client, 0,
ret = pmbus_read_word_data(client, 0, 0xff,
MAX8688_MFR_TEMPERATURE_PEAK);
break;
case PMBUS_VIRT_RESET_VOUT_HISTORY:
@ -94,7 +97,7 @@ static int max8688_read_byte_data(struct i2c_client *client, int page, int reg)
switch (reg) {
case PMBUS_STATUS_VOUT:
mfg_status = pmbus_read_word_data(client, 0,
mfg_status = pmbus_read_word_data(client, 0, 0xff,
MAX8688_MFG_STATUS);
if (mfg_status < 0)
return mfg_status;
@ -108,7 +111,7 @@ static int max8688_read_byte_data(struct i2c_client *client, int page, int reg)
ret |= PB_VOLTAGE_OV_FAULT;
break;
case PMBUS_STATUS_IOUT:
mfg_status = pmbus_read_word_data(client, 0,
mfg_status = pmbus_read_word_data(client, 0, 0xff,
MAX8688_MFG_STATUS);
if (mfg_status < 0)
return mfg_status;
@ -120,7 +123,7 @@ static int max8688_read_byte_data(struct i2c_client *client, int page, int reg)
ret |= PB_IOUT_OC_FAULT;
break;
case PMBUS_STATUS_TEMPERATURE:
mfg_status = pmbus_read_word_data(client, 0,
mfg_status = pmbus_read_word_data(client, 0, 0xff,
MAX8688_MFG_STATUS);
if (mfg_status < 0)
return mfg_status;

Просмотреть файл

@ -102,10 +102,10 @@ static int pmbus_identify(struct i2c_client *client,
int page;
for (page = 1; page < PMBUS_PAGES; page++) {
if (pmbus_set_page(client, page) < 0)
if (pmbus_set_page(client, page, 0xff) < 0)
break;
}
pmbus_set_page(client, 0);
pmbus_set_page(client, 0, 0xff);
info->pages = page;
} else {
info->pages = 1;

Просмотреть файл

@ -119,6 +119,9 @@ enum pmbus_regs {
PMBUS_MFR_DATE = 0x9D,
PMBUS_MFR_SERIAL = 0x9E,
PMBUS_IC_DEVICE_ID = 0xAD,
PMBUS_IC_DEVICE_REV = 0xAE,
/*
* Virtual registers.
* Useful to support attributes which are not supported by standard PMBus
@ -359,6 +362,7 @@ enum pmbus_sensor_classes {
};
#define PMBUS_PAGES 32 /* Per PMBus specification */
#define PMBUS_PHASES 8 /* Maximum number of phases per page */
/* Functionality bit mask */
#define PMBUS_HAVE_VIN BIT(0)
@ -385,13 +389,15 @@ enum pmbus_sensor_classes {
#define PMBUS_HAVE_PWM34 BIT(21)
#define PMBUS_HAVE_SAMPLES BIT(22)
#define PMBUS_PAGE_VIRTUAL BIT(31)
#define PMBUS_PHASE_VIRTUAL BIT(30) /* Phases on this page are virtual */
#define PMBUS_PAGE_VIRTUAL BIT(31) /* Page is virtual */
enum pmbus_data_format { linear = 0, direct, vid };
enum vrm_version { vr11 = 0, vr12, vr13, imvp9, amd625mv };
struct pmbus_driver_info {
int pages; /* Total number of pages */
u8 phases[PMBUS_PAGES]; /* Number of phases per page */
enum pmbus_data_format format[PSC_NUM_CLASSES];
enum vrm_version vrm_version[PMBUS_PAGES]; /* vrm version per page */
/*
@ -403,6 +409,7 @@ struct pmbus_driver_info {
int R[PSC_NUM_CLASSES]; /* exponent */
u32 func[PMBUS_PAGES]; /* Functionality, per page */
u32 pfunc[PMBUS_PHASES];/* Functionality, per phase */
/*
* The following functions map manufacturing specific register values
* to PMBus standard register values. Specify only if mapping is
@ -415,7 +422,8 @@ struct pmbus_driver_info {
* the standard register.
*/
int (*read_byte_data)(struct i2c_client *client, int page, int reg);
int (*read_word_data)(struct i2c_client *client, int page, int reg);
int (*read_word_data)(struct i2c_client *client, int page, int phase,
int reg);
int (*write_word_data)(struct i2c_client *client, int page, int reg,
u16 word);
int (*write_byte)(struct i2c_client *client, int page, u8 value);
@ -454,9 +462,11 @@ extern const struct regulator_ops pmbus_regulator_ops;
/* Function declarations */
void pmbus_clear_cache(struct i2c_client *client);
int pmbus_set_page(struct i2c_client *client, int page);
int pmbus_read_word_data(struct i2c_client *client, int page, u8 reg);
int pmbus_write_word_data(struct i2c_client *client, int page, u8 reg, u16 word);
int pmbus_set_page(struct i2c_client *client, int page, int phase);
int pmbus_read_word_data(struct i2c_client *client, int page, int phase,
u8 reg);
int pmbus_write_word_data(struct i2c_client *client, int page, u8 reg,
u16 word);
int pmbus_read_byte_data(struct i2c_client *client, int page, u8 reg);
int pmbus_write_byte(struct i2c_client *client, int page, u8 value);
int pmbus_write_byte_data(struct i2c_client *client, int page, u8 reg,

Просмотреть файл

@ -49,6 +49,7 @@ struct pmbus_sensor {
char name[PMBUS_NAME_SIZE]; /* sysfs sensor name */
struct device_attribute attribute;
u8 page; /* page number */
u8 phase; /* phase number, 0xff for all phases */
u16 reg; /* register */
enum pmbus_sensor_classes class; /* sensor class */
bool update; /* runtime sensor update needed */
@ -109,6 +110,7 @@ struct pmbus_data {
int (*read_status)(struct i2c_client *client, int page);
u8 currpage;
u8 currphase; /* current phase, 0xff for all */
};
struct pmbus_debugfs_entry {
@ -146,15 +148,16 @@ void pmbus_clear_cache(struct i2c_client *client)
}
EXPORT_SYMBOL_GPL(pmbus_clear_cache);
int pmbus_set_page(struct i2c_client *client, int page)
int pmbus_set_page(struct i2c_client *client, int page, int phase)
{
struct pmbus_data *data = i2c_get_clientdata(client);
int rv;
if (page < 0 || page == data->currpage)
if (page < 0)
return 0;
if (!(data->info->func[page] & PMBUS_PAGE_VIRTUAL)) {
if (!(data->info->func[page] & PMBUS_PAGE_VIRTUAL) &&
data->info->pages > 1 && page != data->currpage) {
rv = i2c_smbus_write_byte_data(client, PMBUS_PAGE, page);
if (rv < 0)
return rv;
@ -166,9 +169,17 @@ int pmbus_set_page(struct i2c_client *client, int page)
if (rv != page)
return -EIO;
}
data->currpage = page;
if (data->info->phases[page] && data->currphase != phase &&
!(data->info->func[page] & PMBUS_PHASE_VIRTUAL)) {
rv = i2c_smbus_write_byte_data(client, PMBUS_PHASE,
phase);
if (rv)
return rv;
}
data->currphase = phase;
return 0;
}
EXPORT_SYMBOL_GPL(pmbus_set_page);
@ -177,7 +188,7 @@ int pmbus_write_byte(struct i2c_client *client, int page, u8 value)
{
int rv;
rv = pmbus_set_page(client, page);
rv = pmbus_set_page(client, page, 0xff);
if (rv < 0)
return rv;
@ -208,7 +219,7 @@ int pmbus_write_word_data(struct i2c_client *client, int page, u8 reg,
{
int rv;
rv = pmbus_set_page(client, page);
rv = pmbus_set_page(client, page, 0xff);
if (rv < 0)
return rv;
@ -286,11 +297,11 @@ int pmbus_update_fan(struct i2c_client *client, int page, int id,
}
EXPORT_SYMBOL_GPL(pmbus_update_fan);
int pmbus_read_word_data(struct i2c_client *client, int page, u8 reg)
int pmbus_read_word_data(struct i2c_client *client, int page, int phase, u8 reg)
{
int rv;
rv = pmbus_set_page(client, page);
rv = pmbus_set_page(client, page, phase);
if (rv < 0)
return rv;
@ -320,14 +331,15 @@ static int pmbus_read_virt_reg(struct i2c_client *client, int page, int reg)
* _pmbus_read_word_data() is similar to pmbus_read_word_data(), but checks if
* a device specific mapping function exists and calls it if necessary.
*/
static int _pmbus_read_word_data(struct i2c_client *client, int page, int reg)
static int _pmbus_read_word_data(struct i2c_client *client, int page,
int phase, int reg)
{
struct pmbus_data *data = i2c_get_clientdata(client);
const struct pmbus_driver_info *info = data->info;
int status;
if (info->read_word_data) {
status = info->read_word_data(client, page, reg);
status = info->read_word_data(client, page, phase, reg);
if (status != -ENODATA)
return status;
}
@ -335,14 +347,20 @@ static int _pmbus_read_word_data(struct i2c_client *client, int page, int reg)
if (reg >= PMBUS_VIRT_BASE)
return pmbus_read_virt_reg(client, page, reg);
return pmbus_read_word_data(client, page, reg);
return pmbus_read_word_data(client, page, phase, reg);
}
/* Same as above, but without phase parameter, for use in check functions */
static int __pmbus_read_word_data(struct i2c_client *client, int page, int reg)
{
return _pmbus_read_word_data(client, page, 0xff, reg);
}
int pmbus_read_byte_data(struct i2c_client *client, int page, u8 reg)
{
int rv;
rv = pmbus_set_page(client, page);
rv = pmbus_set_page(client, page, 0xff);
if (rv < 0)
return rv;
@ -354,7 +372,7 @@ int pmbus_write_byte_data(struct i2c_client *client, int page, u8 reg, u8 value)
{
int rv;
rv = pmbus_set_page(client, page);
rv = pmbus_set_page(client, page, 0xff);
if (rv < 0)
return rv;
@ -440,7 +458,7 @@ static int pmbus_get_fan_rate(struct i2c_client *client, int page, int id,
have_rpm = !!(config & pmbus_fan_rpm_mask[id]);
if (want_rpm == have_rpm)
return pmbus_read_word_data(client, page,
return pmbus_read_word_data(client, page, 0xff,
pmbus_fan_command_registers[id]);
/* Can't sensibly map between RPM and PWM, just return zero */
@ -530,7 +548,7 @@ EXPORT_SYMBOL_GPL(pmbus_check_byte_register);
bool pmbus_check_word_register(struct i2c_client *client, int page, int reg)
{
return pmbus_check_register(client, _pmbus_read_word_data, page, reg);
return pmbus_check_register(client, __pmbus_read_word_data, page, reg);
}
EXPORT_SYMBOL_GPL(pmbus_check_word_register);
@ -595,6 +613,7 @@ static struct pmbus_data *pmbus_update_device(struct device *dev)
sensor->data
= _pmbus_read_word_data(client,
sensor->page,
sensor->phase,
sensor->reg);
}
pmbus_clear_faults(client);
@ -1076,7 +1095,8 @@ static int pmbus_add_boolean(struct pmbus_data *data,
static struct pmbus_sensor *pmbus_add_sensor(struct pmbus_data *data,
const char *name, const char *type,
int seq, int page, int reg,
int seq, int page, int phase,
int reg,
enum pmbus_sensor_classes class,
bool update, bool readonly,
bool convert)
@ -1100,6 +1120,7 @@ static struct pmbus_sensor *pmbus_add_sensor(struct pmbus_data *data,
readonly = true;
sensor->page = page;
sensor->phase = phase;
sensor->reg = reg;
sensor->class = class;
sensor->update = update;
@ -1119,7 +1140,7 @@ static struct pmbus_sensor *pmbus_add_sensor(struct pmbus_data *data,
static int pmbus_add_label(struct pmbus_data *data,
const char *name, int seq,
const char *lstring, int index)
const char *lstring, int index, int phase)
{
struct pmbus_label *label;
struct device_attribute *a;
@ -1131,11 +1152,21 @@ static int pmbus_add_label(struct pmbus_data *data,
a = &label->attribute;
snprintf(label->name, sizeof(label->name), "%s%d_label", name, seq);
if (!index)
strncpy(label->label, lstring, sizeof(label->label) - 1);
else
snprintf(label->label, sizeof(label->label), "%s%d", lstring,
index);
if (!index) {
if (phase == 0xff)
strncpy(label->label, lstring,
sizeof(label->label) - 1);
else
snprintf(label->label, sizeof(label->label), "%s.%d",
lstring, phase);
} else {
if (phase == 0xff)
snprintf(label->label, sizeof(label->label), "%s%d",
lstring, index);
else
snprintf(label->label, sizeof(label->label), "%s%d.%d",
lstring, index, phase);
}
pmbus_dev_attr_init(a, label->name, 0444, pmbus_show_label, NULL);
return pmbus_add_attribute(data, &a->attr);
@ -1200,7 +1231,7 @@ static int pmbus_add_limit_attrs(struct i2c_client *client,
for (i = 0; i < nlimit; i++) {
if (pmbus_check_word_register(client, page, l->reg)) {
curr = pmbus_add_sensor(data, name, l->attr, index,
page, l->reg, attr->class,
page, 0xff, l->reg, attr->class,
attr->update || l->update,
false, true);
if (!curr)
@ -1227,7 +1258,7 @@ static int pmbus_add_sensor_attrs_one(struct i2c_client *client,
struct pmbus_data *data,
const struct pmbus_driver_info *info,
const char *name,
int index, int page,
int index, int page, int phase,
const struct pmbus_sensor_attr *attr,
bool paged)
{
@ -1237,15 +1268,16 @@ static int pmbus_add_sensor_attrs_one(struct i2c_client *client,
if (attr->label) {
ret = pmbus_add_label(data, name, index, attr->label,
paged ? page + 1 : 0);
paged ? page + 1 : 0, phase);
if (ret)
return ret;
}
base = pmbus_add_sensor(data, name, "input", index, page, attr->reg,
attr->class, true, true, true);
base = pmbus_add_sensor(data, name, "input", index, page, phase,
attr->reg, attr->class, true, true, true);
if (!base)
return -ENOMEM;
if (attr->sfunc) {
/* No limit and alarm attributes for phase specific sensors */
if (attr->sfunc && phase == 0xff) {
ret = pmbus_add_limit_attrs(client, data, info, name,
index, page, base, attr);
if (ret < 0)
@ -1315,10 +1347,25 @@ static int pmbus_add_sensor_attrs(struct i2c_client *client,
continue;
ret = pmbus_add_sensor_attrs_one(client, data, info,
name, index, page,
attrs, paged);
0xff, attrs, paged);
if (ret)
return ret;
index++;
if (info->phases[page]) {
int phase;
for (phase = 0; phase < info->phases[page];
phase++) {
if (!(info->pfunc[phase] & attrs->func))
continue;
ret = pmbus_add_sensor_attrs_one(client,
data, info, name, index, page,
phase, attrs, paged);
if (ret)
return ret;
index++;
}
}
}
attrs++;
}
@ -1822,7 +1869,7 @@ static int pmbus_add_fan_ctrl(struct i2c_client *client,
struct pmbus_sensor *sensor;
sensor = pmbus_add_sensor(data, "fan", "target", index, page,
PMBUS_VIRT_FAN_TARGET_1 + id, PSC_FAN,
PMBUS_VIRT_FAN_TARGET_1 + id, 0xff, PSC_FAN,
false, false, true);
if (!sensor)
@ -1833,14 +1880,14 @@ static int pmbus_add_fan_ctrl(struct i2c_client *client,
return 0;
sensor = pmbus_add_sensor(data, "pwm", NULL, index, page,
PMBUS_VIRT_PWM_1 + id, PSC_PWM,
PMBUS_VIRT_PWM_1 + id, 0xff, PSC_PWM,
false, false, true);
if (!sensor)
return -ENOMEM;
sensor = pmbus_add_sensor(data, "pwm", "enable", index, page,
PMBUS_VIRT_PWM_ENABLE_1 + id, PSC_PWM,
PMBUS_VIRT_PWM_ENABLE_1 + id, 0xff, PSC_PWM,
true, false, false);
if (!sensor)
@ -1882,7 +1929,7 @@ static int pmbus_add_fan_attributes(struct i2c_client *client,
continue;
if (pmbus_add_sensor(data, "fan", "input", index,
page, pmbus_fan_registers[f],
page, pmbus_fan_registers[f], 0xff,
PSC_FAN, true, true, true) == NULL)
return -ENOMEM;
@ -1964,7 +2011,7 @@ static ssize_t pmbus_show_samples(struct device *dev,
struct i2c_client *client = to_i2c_client(dev->parent);
struct pmbus_samples_reg *reg = to_samples_reg(devattr);
val = _pmbus_read_word_data(client, reg->page, reg->attr->reg);
val = _pmbus_read_word_data(client, reg->page, 0xff, reg->attr->reg);
if (val < 0)
return val;
@ -2120,7 +2167,7 @@ static int pmbus_read_status_byte(struct i2c_client *client, int page)
static int pmbus_read_status_word(struct i2c_client *client, int page)
{
return _pmbus_read_word_data(client, page, PMBUS_STATUS_WORD);
return _pmbus_read_word_data(client, page, 0xff, PMBUS_STATUS_WORD);
}
static int pmbus_init_common(struct i2c_client *client, struct pmbus_data *data,
@ -2482,6 +2529,8 @@ int pmbus_do_probe(struct i2c_client *client, const struct i2c_device_id *id,
if (pdata)
data->flags = pdata->flags;
data->info = info;
data->currpage = 0xff;
data->currphase = 0xfe;
ret = pmbus_init_common(client, data, info);
if (ret < 0)

Просмотреть файл

@ -6,13 +6,21 @@
* Copyright (c) 2017 Vadim Pasternak <vadimp@mellanox.com>
*/
#include <linux/bits.h>
#include <linux/err.h>
#include <linux/i2c.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include "pmbus.h"
enum chips {
tps53647, tps53667, tps53679, tps53681, tps53688
};
#define TPS53647_PAGE_NUM 1
#define TPS53679_PROT_VR12_5MV 0x01 /* VR12.0 mode, 5-mV DAC */
#define TPS53679_PROT_VR12_5_10MV 0x02 /* VR12.5 mode, 10-mV DAC */
#define TPS53679_PROT_VR13_10MV 0x04 /* VR13.0 mode, 10-mV DAC */
@ -20,13 +28,19 @@
#define TPS53679_PROT_VR13_5MV 0x07 /* VR13.0 mode, 5-mV DAC */
#define TPS53679_PAGE_NUM 2
static int tps53679_identify(struct i2c_client *client,
struct pmbus_driver_info *info)
#define TPS53681_DEVICE_ID 0x81
#define TPS53681_PMBUS_REVISION 0x33
#define TPS53681_MFR_SPECIFIC_20 0xe4 /* Number of phases, per page */
static int tps53679_identify_mode(struct i2c_client *client,
struct pmbus_driver_info *info)
{
u8 vout_params;
int i, ret;
for (i = 0; i < TPS53679_PAGE_NUM; i++) {
for (i = 0; i < info->pages; i++) {
/* Read the register with VOUT scaling value.*/
ret = pmbus_read_byte_data(client, i, PMBUS_VOUT_MODE);
if (ret < 0)
@ -52,48 +66,180 @@ static int tps53679_identify(struct i2c_client *client,
return 0;
}
static int tps53679_identify_phases(struct i2c_client *client,
struct pmbus_driver_info *info)
{
int ret;
/* On TPS53681, only channel A provides per-phase output current */
ret = pmbus_read_byte_data(client, 0, TPS53681_MFR_SPECIFIC_20);
if (ret < 0)
return ret;
info->phases[0] = (ret & 0x07) + 1;
return 0;
}
static int tps53679_identify_chip(struct i2c_client *client,
u8 revision, u16 id)
{
u8 buf[I2C_SMBUS_BLOCK_MAX];
int ret;
ret = pmbus_read_byte_data(client, 0, PMBUS_REVISION);
if (ret < 0)
return ret;
if (ret != revision) {
dev_err(&client->dev, "Unexpected PMBus revision 0x%x\n", ret);
return -ENODEV;
}
ret = i2c_smbus_read_block_data(client, PMBUS_IC_DEVICE_ID, buf);
if (ret < 0)
return ret;
if (ret != 1 || buf[0] != id) {
dev_err(&client->dev, "Unexpected device ID 0x%x\n", buf[0]);
return -ENODEV;
}
return 0;
}
/*
* Common identification function for chips with multi-phase support.
* Since those chips have special configuration registers, we want to have
* some level of reassurance that we are really talking with the chip
* being probed. Check PMBus revision and chip ID.
*/
static int tps53679_identify_multiphase(struct i2c_client *client,
struct pmbus_driver_info *info,
int pmbus_rev, int device_id)
{
int ret;
ret = tps53679_identify_chip(client, pmbus_rev, device_id);
if (ret < 0)
return ret;
ret = tps53679_identify_mode(client, info);
if (ret < 0)
return ret;
return tps53679_identify_phases(client, info);
}
static int tps53679_identify(struct i2c_client *client,
struct pmbus_driver_info *info)
{
return tps53679_identify_mode(client, info);
}
static int tps53681_identify(struct i2c_client *client,
struct pmbus_driver_info *info)
{
return tps53679_identify_multiphase(client, info,
TPS53681_PMBUS_REVISION,
TPS53681_DEVICE_ID);
}
static int tps53681_read_word_data(struct i2c_client *client, int page,
int phase, int reg)
{
/*
* For reading the total output current (READ_IOUT) for all phases,
* the chip datasheet is a bit vague. It says "PHASE must be set to
* FFh to access all phases simultaneously. PHASE may also be set to
* 80h readack (!) the total phase current".
* Experiments show that the command does _not_ report the total
* current for all phases if the phase is set to 0xff. Instead, it
* appears to report the current of one of the phases. Override phase
* parameter with 0x80 when reading the total output current on page 0.
*/
if (reg == PMBUS_READ_IOUT && page == 0 && phase == 0xff)
return pmbus_read_word_data(client, page, 0x80, reg);
return -ENODATA;
}
static struct pmbus_driver_info tps53679_info = {
.pages = TPS53679_PAGE_NUM,
.format[PSC_VOLTAGE_IN] = linear,
.format[PSC_VOLTAGE_OUT] = vid,
.format[PSC_TEMPERATURE] = linear,
.format[PSC_CURRENT_OUT] = linear,
.format[PSC_POWER] = linear,
.func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT |
.func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_IIN | PMBUS_HAVE_PIN |
PMBUS_HAVE_STATUS_INPUT |
PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT |
PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT |
PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP |
PMBUS_HAVE_POUT,
.func[1] = PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT |
.func[1] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT |
PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT |
PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP |
PMBUS_HAVE_POUT,
.identify = tps53679_identify,
.pfunc[0] = PMBUS_HAVE_IOUT,
.pfunc[1] = PMBUS_HAVE_IOUT,
.pfunc[2] = PMBUS_HAVE_IOUT,
.pfunc[3] = PMBUS_HAVE_IOUT,
.pfunc[4] = PMBUS_HAVE_IOUT,
.pfunc[5] = PMBUS_HAVE_IOUT,
};
static int tps53679_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct device *dev = &client->dev;
struct pmbus_driver_info *info;
enum chips chip_id;
info = devm_kmemdup(&client->dev, &tps53679_info, sizeof(*info),
GFP_KERNEL);
if (dev->of_node)
chip_id = (enum chips)of_device_get_match_data(dev);
else
chip_id = id->driver_data;
info = devm_kmemdup(dev, &tps53679_info, sizeof(*info), GFP_KERNEL);
if (!info)
return -ENOMEM;
switch (chip_id) {
case tps53647:
case tps53667:
info->pages = TPS53647_PAGE_NUM;
info->identify = tps53679_identify;
break;
case tps53679:
case tps53688:
info->pages = TPS53679_PAGE_NUM;
info->identify = tps53679_identify;
break;
case tps53681:
info->pages = TPS53679_PAGE_NUM;
info->phases[0] = 6;
info->identify = tps53681_identify;
info->read_word_data = tps53681_read_word_data;
break;
default:
return -ENODEV;
}
return pmbus_do_probe(client, id, info);
}
static const struct i2c_device_id tps53679_id[] = {
{"tps53679", 0},
{"tps53688", 0},
{"tps53647", tps53647},
{"tps53667", tps53667},
{"tps53679", tps53679},
{"tps53681", tps53681},
{"tps53688", tps53688},
{}
};
MODULE_DEVICE_TABLE(i2c, tps53679_id);
static const struct of_device_id __maybe_unused tps53679_of_match[] = {
{.compatible = "ti,tps53679"},
{.compatible = "ti,tps53688"},
{.compatible = "ti,tps53647", .data = (void *)tps53647},
{.compatible = "ti,tps53667", .data = (void *)tps53667},
{.compatible = "ti,tps53679", .data = (void *)tps53679},
{.compatible = "ti,tps53681", .data = (void *)tps53681},
{.compatible = "ti,tps53688", .data = (void *)tps53688},
{}
};
MODULE_DEVICE_TABLE(of, tps53679_of_match);

Просмотреть файл

@ -370,7 +370,7 @@ static void ucd9000_probe_gpio(struct i2c_client *client,
#ifdef CONFIG_DEBUG_FS
static int ucd9000_get_mfr_status(struct i2c_client *client, u8 *buffer)
{
int ret = pmbus_set_page(client, 0);
int ret = pmbus_set_page(client, 0, 0xff);
if (ret < 0)
return ret;

Просмотреть файл

@ -18,7 +18,8 @@
#define XDPE122_AMD_625MV 0x10 /* AMD mode 6.25mV */
#define XDPE122_PAGE_NUM 2
static int xdpe122_read_word_data(struct i2c_client *client, int page, int reg)
static int xdpe122_read_word_data(struct i2c_client *client, int page,
int phase, int reg)
{
const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
long val;
@ -29,7 +30,7 @@ static int xdpe122_read_word_data(struct i2c_client *client, int page, int reg)
switch (reg) {
case PMBUS_VOUT_OV_FAULT_LIMIT:
case PMBUS_VOUT_UV_FAULT_LIMIT:
ret = pmbus_read_word_data(client, page, reg);
ret = pmbus_read_word_data(client, page, phase, reg);
if (ret < 0)
return ret;

Просмотреть файл

@ -125,7 +125,8 @@ static inline void zl6100_wait(const struct zl6100_data *data)
}
}
static int zl6100_read_word_data(struct i2c_client *client, int page, int reg)
static int zl6100_read_word_data(struct i2c_client *client, int page,
int phase, int reg)
{
const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
struct zl6100_data *data = to_zl6100_data(info);
@ -167,7 +168,7 @@ static int zl6100_read_word_data(struct i2c_client *client, int page, int reg)
}
zl6100_wait(data);
ret = pmbus_read_word_data(client, page, vreg);
ret = pmbus_read_word_data(client, page, phase, vreg);
data->access = ktime_get();
if (ret < 0)
return ret;