mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-09 15:29:16 +00:00
hwmon updates for v6.6
- New drivers * Driver for Renesas HS3001 - Chip support added to existing drivers * pmbus/mp2975 driver now supports MP2971 and MP2973 - Functional improvements * Additional voltage and temperature sensor support for NCT6798/NCT6799 in nt6755 driver * it87 driver now detects AMDTSI sensor type * dimmtemp now supports more than 32 DIMMs - Driver removals * sm665 driver removed as unsupportable and long since obsolete - Minor fixes, cleanups, and simplifications in several drivers -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEiHPvMQj9QTOCiqgVyx8mb86fmYEFAmTsyv4ACgkQyx8mb86f mYHlOQ//QgyjtXm3+3e0AzxvFIrp+HZz2QfOEuXOpA9RFZGnpmBhIspeRa88CWYE uHMhdMXY8HQxD3nEDbk4MfClJYQmOaZPHUi/3fVu9K0aHaxXSUDlljSGMeEJ5D8U taaxl3FjDRvPvf1jLfU95qrV4V0/z10da+gA/ryItkooyvZbZSoi33RgIWRL0KH4 yFsNYY8xWxnBe0gkoQoTVBFs/wbFRrNOrV698qpAYnPuXHh/lCR3T9rQ78C2xnmg urg4b1UCilrrEz30IuatHGwqvaDWXVZXpp3LGCeabLytQg4bSsrdPEyVM66fBLtI RvsX7KyhdcVojsshQ27vJte3gGdywgW4OxfIFjmreFSc+A9pjYjwbTc2ZPrrn+jm fvDMoSB5Ac5hgWgN1hvh8ioget9CHL7whydFJnDPGjnxOLZoZjIN4ssitydpPQ7Q wZfont4/R8Tj0RFapp0VHYMtry7fwWCQnrQ6Cb+IskjXDOclEyYjOCJt71bTTl2Q mGH3BoY4R8pE3EcKKMXTiwIIINiBDe4CBV2eQe5hnVIgXQ+Y/XbJZoLjCtiGCoCk ySh0eP0MO0En2fkc6LFeiy37r9PEscbagmhTufiGha3q26xIkJountqGpYVDWgZB zILIW1UOECKVQ2kFuVps3oBQbOKzwzReo4Nm+XjhWtHxT/1HpyM= =dpys -----END PGP SIGNATURE----- Merge tag 'hwmon-for-v6.6' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging Pull hwmon updates from Guenter Roeck: "New drivers: - Renesas HS3001 Chip support added to existing drivers: - pmbus/mp2975 driver now supports MP2971 and MP2973 Functional improvements: - Additional voltage and temperature sensor support for NCT6798/NCT6799 in nt6755 driver - it87 driver now detects AMDTSI sensor type - dimmtemp now supports more than 32 DIMMs Driver removals: - sm665 driver removed as unsupportable and long since obsolete .. and minor fixes, cleanups, and simplifications in several drivers" * tag 'hwmon-for-v6.6' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging: (57 commits) hwmon: (tmp513) Simplify probe() hwmon: (tmp513) Fix the channel number in tmp51x_is_visible() hwmon: (mlxreg-fan) Extend number of supported fans hwmon: (sis5595) Do PCI error checks on own line hwmon: (vt8231) Do PCI error checks on own line hwmon: (via686a) Do PCI error checks on own line hwmon: pmbus: Fix -EIO seen on pli1209 hwmon: pmbus: Drop unnecessary clear fault page hwmon: pmbus: Reduce clear fault page invocations hwmon: (nsa320-hwmon) Remove redundant of_match_ptr() hwmon: (pmbus/ucd9200) fix Wvoid-pointer-to-enum-cast warning hwmon: (pmbus/ucd9000) fix Wvoid-pointer-to-enum-cast warning hwmon: (pmbus/tps53679) fix Wvoid-pointer-to-enum-cast warning hwmon: (pmbus/ibm-cffps) fix Wvoid-pointer-to-enum-cast warning hwmon: (tmp513) fix Wvoid-pointer-to-enum-cast warning hwmon: (max6697) fix Wvoid-pointer-to-enum-cast warning hwmon: (max20730) fix Wvoid-pointer-to-enum-cast warning hwmon: (lm90) fix Wvoid-pointer-to-enum-cast warning hwmon: (lm85) fix Wvoid-pointer-to-enum-cast warning hwmon: (lm75) fix Wvoid-pointer-to-enum-cast warning ...
This commit is contained in:
commit
41e97d7acf
@ -119,6 +119,10 @@ properties:
|
||||
- fsl,mpr121
|
||||
# Monolithic Power Systems Inc. multi-phase controller mp2888
|
||||
- mps,mp2888
|
||||
# Monolithic Power Systems Inc. multi-phase controller mp2971
|
||||
- mps,mp2971
|
||||
# Monolithic Power Systems Inc. multi-phase controller mp2973
|
||||
- mps,mp2973
|
||||
# Monolithic Power Systems Inc. multi-phase controller mp2975
|
||||
- mps,mp2975
|
||||
# Honeywell Humidicon HIH-6130 humidity/temperature sensor
|
||||
@ -315,6 +319,8 @@ properties:
|
||||
- plx,pex8648
|
||||
# Pulsedlight LIDAR range-finding sensor
|
||||
- pulsedlight,lidar-lite-v2
|
||||
# Renesas HS3001 Temperature and Relative Humidity Sensors
|
||||
- renesas,hs3001
|
||||
# Renesas ISL29501 time-of-flight sensor
|
||||
- renesas,isl29501
|
||||
# Rohm DH2228FV
|
||||
|
37
Documentation/hwmon/hs3001.rst
Normal file
37
Documentation/hwmon/hs3001.rst
Normal file
@ -0,0 +1,37 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
Kernel driver HS3001
|
||||
====================
|
||||
|
||||
Supported chips:
|
||||
|
||||
* Renesas HS3001, HS3002, HS3003, HS3004
|
||||
|
||||
Prefix: 'hs3001'
|
||||
|
||||
Addresses scanned: -
|
||||
|
||||
Datasheet: https://www.renesas.com/us/en/document/dst/hs300x-datasheet?r=417401
|
||||
|
||||
Author:
|
||||
|
||||
- Andre Werner <andre.werner@systec-electronic.com>
|
||||
|
||||
Description
|
||||
-----------
|
||||
|
||||
This driver implements support for the Renesas HS3001 chips, a humidity
|
||||
and temperature family. Temperature is measured in degrees celsius, relative
|
||||
humidity is expressed as a percentage. In the sysfs interface, all values are
|
||||
scaled by 1000, i.e. the value for 31.5 degrees celsius is 31500.
|
||||
|
||||
The device communicates with the I2C protocol. Sensors have the I2C
|
||||
address 0x44 by default.
|
||||
|
||||
sysfs-Interface
|
||||
---------------
|
||||
|
||||
=================== =================
|
||||
temp1_input: temperature input
|
||||
humidity1_input: humidity input
|
||||
=================== =================
|
@ -78,6 +78,7 @@ Hardware Monitoring Kernel Drivers
|
||||
gxp-fan-ctrl
|
||||
hih6130
|
||||
hp-wmi-sensors
|
||||
hs3001
|
||||
ibmaem
|
||||
ibm-cffps
|
||||
ibmpowernv
|
||||
@ -195,7 +196,6 @@ Hardware Monitoring Kernel Drivers
|
||||
shtc1
|
||||
sis5595
|
||||
sl28cpld
|
||||
smm665
|
||||
smpro-hwmon
|
||||
smsc47b397
|
||||
smsc47m192
|
||||
|
@ -80,7 +80,13 @@ Supported chips:
|
||||
|
||||
Datasheet: Available from Nuvoton upon request
|
||||
|
||||
* Nuvoton NCT6796D-S/NCT6799D-R
|
||||
|
||||
Prefix: 'nct6799'
|
||||
|
||||
Addresses scanned: ISA address retrieved from Super I/O registers
|
||||
|
||||
Datasheet: Available from Nuvoton upon request
|
||||
|
||||
Authors:
|
||||
|
||||
@ -277,4 +283,7 @@ will not reflect a usable value. It often reports unreasonably high
|
||||
temperatures, and in some cases the reported temperature declines if the actual
|
||||
temperature increases (similar to the raw PECI temperature value - see PECI
|
||||
specification for details). CPUTIN should therefore be ignored on ASUS
|
||||
boards. The CPU temperature on ASUS boards is reported from PECI 0.
|
||||
boards. The CPU temperature on ASUS boards is reported from PECI 0 or TSI 0.
|
||||
|
||||
NCT6796D-S and NCT6799D-R chips are very similar and their chip_id indicates
|
||||
they are different versions. This driver treats them the same way.
|
||||
|
@ -163,7 +163,7 @@ Emerson DS1200 power modules might look as follows::
|
||||
.driver = {
|
||||
.name = "ds1200",
|
||||
},
|
||||
.probe_new = ds1200_probe,
|
||||
.probe = ds1200_probe,
|
||||
.id_table = ds1200_id,
|
||||
};
|
||||
|
||||
|
@ -1,187 +0,0 @@
|
||||
Kernel driver smm665
|
||||
====================
|
||||
|
||||
Supported chips:
|
||||
|
||||
* Summit Microelectronics SMM465
|
||||
|
||||
Prefix: 'smm465'
|
||||
|
||||
Addresses scanned: -
|
||||
|
||||
Datasheet:
|
||||
|
||||
http://www.summitmicro.com/prod_select/summary/SMM465/SMM465DS.pdf
|
||||
|
||||
* Summit Microelectronics SMM665, SMM665B
|
||||
|
||||
Prefix: 'smm665'
|
||||
|
||||
Addresses scanned: -
|
||||
|
||||
Datasheet:
|
||||
|
||||
http://www.summitmicro.com/prod_select/summary/SMM665/SMM665B_2089_20.pdf
|
||||
|
||||
* Summit Microelectronics SMM665C
|
||||
|
||||
Prefix: 'smm665c'
|
||||
|
||||
Addresses scanned: -
|
||||
|
||||
Datasheet:
|
||||
|
||||
http://www.summitmicro.com/prod_select/summary/SMM665C/SMM665C_2125.pdf
|
||||
|
||||
* Summit Microelectronics SMM764
|
||||
|
||||
Prefix: 'smm764'
|
||||
|
||||
Addresses scanned: -
|
||||
|
||||
Datasheet:
|
||||
|
||||
http://www.summitmicro.com/prod_select/summary/SMM764/SMM764_2098.pdf
|
||||
|
||||
* Summit Microelectronics SMM766, SMM766B
|
||||
|
||||
Prefix: 'smm766'
|
||||
|
||||
Addresses scanned: -
|
||||
|
||||
Datasheets:
|
||||
|
||||
http://www.summitmicro.com/prod_select/summary/SMM766/SMM766_2086.pdf
|
||||
|
||||
http://www.summitmicro.com/prod_select/summary/SMM766B/SMM766B_2122.pdf
|
||||
|
||||
Author: Guenter Roeck <linux@roeck-us.net>
|
||||
|
||||
|
||||
Module Parameters
|
||||
-----------------
|
||||
|
||||
* vref: int
|
||||
Default: 1250 (mV)
|
||||
|
||||
Reference voltage on VREF_ADC pin in mV. It should not be necessary to set
|
||||
this parameter unless a non-default reference voltage is used.
|
||||
|
||||
|
||||
Description
|
||||
-----------
|
||||
|
||||
[From datasheet] The SMM665 is an Active DC Output power supply Controller
|
||||
that monitors, margins and cascade sequences power. The part monitors six
|
||||
power supply channels as well as VDD, 12V input, two general-purpose analog
|
||||
inputs and an internal temperature sensor using a 10-bit ADC.
|
||||
|
||||
Each monitored channel has its own high and low limits, plus a critical
|
||||
limit.
|
||||
|
||||
Support for SMM465, SMM764, and SMM766 has been implemented but is untested.
|
||||
|
||||
|
||||
Usage Notes
|
||||
-----------
|
||||
|
||||
This driver does not probe for devices, since there is no register which
|
||||
can be safely used to identify the chip. You will have to instantiate
|
||||
the devices explicitly. When instantiating the device, you have to specify
|
||||
its configuration register address.
|
||||
|
||||
Example: the following will load the driver for an SMM665 at address 0x57
|
||||
on I2C bus #1::
|
||||
|
||||
$ modprobe smm665
|
||||
$ echo smm665 0x57 > /sys/bus/i2c/devices/i2c-1/new_device
|
||||
|
||||
|
||||
Sysfs entries
|
||||
-------------
|
||||
|
||||
This driver uses the values in the datasheet to convert ADC register values
|
||||
into the values specified in the sysfs-interface document. All attributes are
|
||||
read only.
|
||||
|
||||
Min, max, lcrit, and crit values are used by the chip to trigger external signals
|
||||
and/or other activity. Triggered signals can include HEALTHY, RST, Power Off,
|
||||
or Fault depending on the chip configuration. The driver reports values as lcrit
|
||||
or crit if exceeding the limits triggers RST, Power Off, or Fault, and as min or
|
||||
max otherwise. For details please see the SMM665 datasheet.
|
||||
|
||||
For SMM465 and SMM764, values for Channel E and F are reported but undefined.
|
||||
|
||||
======================= =======================================================
|
||||
in1_input 12V input voltage (mV)
|
||||
in2_input 3.3V (VDD) input voltage (mV)
|
||||
in3_input Channel A voltage (mV)
|
||||
in4_input Channel B voltage (mV)
|
||||
in5_input Channel C voltage (mV)
|
||||
in6_input Channel D voltage (mV)
|
||||
in7_input Channel E voltage (mV)
|
||||
in8_input Channel F voltage (mV)
|
||||
in9_input AIN1 voltage (mV)
|
||||
in10_input AIN2 voltage (mV)
|
||||
|
||||
in1_min 12v input minimum voltage (mV)
|
||||
in2_min 3.3V (VDD) input minimum voltage (mV)
|
||||
in3_min Channel A minimum voltage (mV)
|
||||
in4_min Channel B minimum voltage (mV)
|
||||
in5_min Channel C minimum voltage (mV)
|
||||
in6_min Channel D minimum voltage (mV)
|
||||
in7_min Channel E minimum voltage (mV)
|
||||
in8_min Channel F minimum voltage (mV)
|
||||
in9_min AIN1 minimum voltage (mV)
|
||||
in10_min AIN2 minimum voltage (mV)
|
||||
|
||||
in1_max 12v input maximum voltage (mV)
|
||||
in2_max 3.3V (VDD) input maximum voltage (mV)
|
||||
in3_max Channel A maximum voltage (mV)
|
||||
in4_max Channel B maximum voltage (mV)
|
||||
in5_max Channel C maximum voltage (mV)
|
||||
in6_max Channel D maximum voltage (mV)
|
||||
in7_max Channel E maximum voltage (mV)
|
||||
in8_max Channel F maximum voltage (mV)
|
||||
in9_max AIN1 maximum voltage (mV)
|
||||
in10_max AIN2 maximum voltage (mV)
|
||||
|
||||
in1_lcrit 12v input critical minimum voltage (mV)
|
||||
in2_lcrit 3.3V (VDD) input critical minimum voltage (mV)
|
||||
in3_lcrit Channel A critical minimum voltage (mV)
|
||||
in4_lcrit Channel B critical minimum voltage (mV)
|
||||
in5_lcrit Channel C critical minimum voltage (mV)
|
||||
in6_lcrit Channel D critical minimum voltage (mV)
|
||||
in7_lcrit Channel E critical minimum voltage (mV)
|
||||
in8_lcrit Channel F critical minimum voltage (mV)
|
||||
in9_lcrit AIN1 critical minimum voltage (mV)
|
||||
in10_lcrit AIN2 critical minimum voltage (mV)
|
||||
|
||||
in1_crit 12v input critical maximum voltage (mV)
|
||||
in2_crit 3.3V (VDD) input critical maximum voltage (mV)
|
||||
in3_crit Channel A critical maximum voltage (mV)
|
||||
in4_crit Channel B critical maximum voltage (mV)
|
||||
in5_crit Channel C critical maximum voltage (mV)
|
||||
in6_crit Channel D critical maximum voltage (mV)
|
||||
in7_crit Channel E critical maximum voltage (mV)
|
||||
in8_crit Channel F critical maximum voltage (mV)
|
||||
in9_crit AIN1 critical maximum voltage (mV)
|
||||
in10_crit AIN2 critical maximum voltage (mV)
|
||||
|
||||
in1_crit_alarm 12v input critical alarm
|
||||
in2_crit_alarm 3.3V (VDD) input critical alarm
|
||||
in3_crit_alarm Channel A critical alarm
|
||||
in4_crit_alarm Channel B critical alarm
|
||||
in5_crit_alarm Channel C critical alarm
|
||||
in6_crit_alarm Channel D critical alarm
|
||||
in7_crit_alarm Channel E critical alarm
|
||||
in8_crit_alarm Channel F critical alarm
|
||||
in9_crit_alarm AIN1 critical alarm
|
||||
in10_crit_alarm AIN2 critical alarm
|
||||
|
||||
temp1_input Chip temperature
|
||||
temp1_min Minimum chip temperature
|
||||
temp1_max Maximum chip temperature
|
||||
temp1_crit Critical chip temperature
|
||||
temp1_crit_alarm Temperature critical alarm
|
||||
======================= =======================================================
|
13
MAINTAINERS
13
MAINTAINERS
@ -9509,6 +9509,12 @@ S: Maintained
|
||||
W: http://artax.karlin.mff.cuni.cz/~mikulas/vyplody/hpfs/index-e.cgi
|
||||
F: fs/hpfs/
|
||||
|
||||
HS3001 Hardware Temperature and Humidity Sensor
|
||||
M: Andre Werner <andre.werner@systec-electronic.com>
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/hwmon/hs3001.c
|
||||
|
||||
HSI SUBSYSTEM
|
||||
M: Sebastian Reichel <sre@kernel.org>
|
||||
S: Maintained
|
||||
@ -19625,13 +19631,6 @@ M: Nicolas Pitre <nico@fluxnic.net>
|
||||
S: Odd Fixes
|
||||
F: drivers/net/ethernet/smsc/smc91x.*
|
||||
|
||||
SMM665 HARDWARE MONITOR DRIVER
|
||||
M: Guenter Roeck <linux@roeck-us.net>
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/hwmon/smm665.rst
|
||||
F: drivers/hwmon/smm665.c
|
||||
|
||||
SMSC EMC2103 HARDWARE MONITOR DRIVER
|
||||
M: Steve Glendinning <steve.glendinning@shawell.net>
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
|
@ -734,6 +734,16 @@ config SENSORS_HIH6130
|
||||
This driver can also be built as a module. If so, the module
|
||||
will be called hih6130.
|
||||
|
||||
config SENSORS_HS3001
|
||||
tristate "Renesas HS3001 humidity and temperature sensors"
|
||||
depends on I2C
|
||||
help
|
||||
If you say yes here you get support for the Renesas HS3001,
|
||||
to HS3004 humidity and temperature sensors.
|
||||
|
||||
This driver can also be built as a module. If so, the module
|
||||
will be called hs3001.
|
||||
|
||||
config SENSORS_IBMAEM
|
||||
tristate "IBM Active Energy Manager temperature/power sensors and control"
|
||||
select IPMI_SI
|
||||
@ -1951,20 +1961,6 @@ config SENSORS_SFCTEMP
|
||||
This driver can also be built as a module. If so, the module
|
||||
will be called sfctemp.
|
||||
|
||||
config SENSORS_SMM665
|
||||
tristate "Summit Microelectronics SMM665"
|
||||
depends on I2C
|
||||
help
|
||||
If you say yes here you get support for the hardware monitoring
|
||||
features of the Summit Microelectronics SMM665/SMM665B Six-Channel
|
||||
Active DC Output Controller / Monitor.
|
||||
|
||||
Other supported chips are SMM465, SMM665C, SMM764, and SMM766.
|
||||
Support for those chips is untested.
|
||||
|
||||
This driver can also be built as a module. If so, the module will
|
||||
be called smm665.
|
||||
|
||||
config SENSORS_ADC128D818
|
||||
tristate "Texas Instruments ADC128D818"
|
||||
depends on I2C
|
||||
|
@ -86,6 +86,7 @@ obj-$(CONFIG_SENSORS_GSC) += gsc-hwmon.o
|
||||
obj-$(CONFIG_SENSORS_GPIO_FAN) += gpio-fan.o
|
||||
obj-$(CONFIG_SENSORS_GXP_FAN_CTRL) += gxp-fan-ctrl.o
|
||||
obj-$(CONFIG_SENSORS_HIH6130) += hih6130.o
|
||||
obj-$(CONFIG_SENSORS_HS3001) += hs3001.o
|
||||
obj-$(CONFIG_SENSORS_ULTRA45) += ultra45_env.o
|
||||
obj-$(CONFIG_SENSORS_I5500) += i5500_temp.o
|
||||
obj-$(CONFIG_SENSORS_I5K_AMB) += i5k_amb.o
|
||||
@ -191,7 +192,6 @@ obj-$(CONFIG_SENSORS_SHT3x) += sht3x.o
|
||||
obj-$(CONFIG_SENSORS_SHT4x) += sht4x.o
|
||||
obj-$(CONFIG_SENSORS_SHTC1) += shtc1.o
|
||||
obj-$(CONFIG_SENSORS_SIS5595) += sis5595.o
|
||||
obj-$(CONFIG_SENSORS_SMM665) += smm665.o
|
||||
obj-$(CONFIG_SENSORS_SMPRO) += smpro-hwmon.o
|
||||
obj-$(CONFIG_SENSORS_SMSC47B397)+= smsc47b397.o
|
||||
obj-$(CONFIG_SENSORS_SMSC47M1) += smsc47m1.o
|
||||
|
@ -16,7 +16,7 @@
|
||||
#include <linux/hwmon-sysfs.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
@ -253,7 +253,7 @@ static int ad7418_probe(struct i2c_client *client)
|
||||
mutex_init(&data->lock);
|
||||
data->client = client;
|
||||
if (dev->of_node)
|
||||
data->type = (enum chips)of_device_get_match_data(dev);
|
||||
data->type = (uintptr_t)of_device_get_match_data(dev);
|
||||
else
|
||||
data->type = i2c_match_id(ad7418_id, client)->driver_data;
|
||||
|
||||
|
@ -18,7 +18,7 @@
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_data/ads7828.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/slab.h>
|
||||
@ -139,8 +139,7 @@ static int ads7828_probe(struct i2c_client *client)
|
||||
}
|
||||
|
||||
if (client->dev.of_node)
|
||||
chip = (enum ads7828_chips)
|
||||
of_device_get_match_data(&client->dev);
|
||||
chip = (uintptr_t)of_device_get_match_data(&client->dev);
|
||||
else
|
||||
chip = i2c_match_id(ads7828_device_ids, client)->driver_data;
|
||||
|
||||
|
@ -10,7 +10,6 @@
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/i2c.h>
|
||||
@ -1653,7 +1652,7 @@ static int adt7475_probe(struct i2c_client *client)
|
||||
i2c_set_clientdata(client, data);
|
||||
|
||||
if (client->dev.of_node)
|
||||
chip = (enum chips)of_device_get_match_data(&client->dev);
|
||||
chip = (uintptr_t)of_device_get_match_data(&client->dev);
|
||||
else
|
||||
chip = id->driver_data;
|
||||
|
||||
|
@ -11,7 +11,8 @@
|
||||
#include <linux/init.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#define CTRL 0x0
|
||||
#define PD BIT(0)
|
||||
|
@ -12,8 +12,7 @@
|
||||
#include <linux/io.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/reset.h>
|
||||
|
@ -340,7 +340,7 @@ static const struct ec_board_info board_info_crosshair_x670e_hero = {
|
||||
.sensors = SENSOR_TEMP_CPU | SENSOR_TEMP_CPU_PACKAGE |
|
||||
SENSOR_TEMP_MB | SENSOR_TEMP_VRM |
|
||||
SENSOR_SET_TEMP_WATER,
|
||||
.mutex_path = ASUS_HW_ACCESS_MUTEX_RMTW_ASMX,
|
||||
.mutex_path = ACPI_GLOBAL_LOCK_PSEUDO_PATH,
|
||||
.family = family_amd_600_series,
|
||||
};
|
||||
|
||||
|
@ -891,15 +891,8 @@ static struct pvt_hwmon *pvt_create_data(struct platform_device *pdev)
|
||||
static int pvt_request_regs(struct pvt_hwmon *pvt)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(pvt->dev);
|
||||
struct resource *res;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!res) {
|
||||
dev_err(pvt->dev, "Couldn't find PVT memresource\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pvt->regs = devm_ioremap_resource(pvt->dev, res);
|
||||
pvt->regs = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(pvt->regs))
|
||||
return PTR_ERR(pvt->regs);
|
||||
|
||||
|
@ -39,7 +39,6 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_data/g762.h>
|
||||
|
||||
#define DRVNAME "g762"
|
||||
|
@ -6,7 +6,7 @@
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#define OFS_FAN_INST 0 /* Is 0 because plreg base will be set at INST */
|
||||
|
@ -435,25 +435,11 @@ static union acpi_object *hp_wmi_get_wobj(const char *guid, u8 instance)
|
||||
/* hp_wmi_wobj_instance_count - find count of WMI object instances */
|
||||
static u8 hp_wmi_wobj_instance_count(const char *guid)
|
||||
{
|
||||
u8 hi = HP_WMI_MAX_INSTANCES;
|
||||
union acpi_object *wobj;
|
||||
u8 lo = 0;
|
||||
u8 mid;
|
||||
int count;
|
||||
|
||||
while (lo < hi) {
|
||||
mid = (lo + hi) / 2;
|
||||
count = wmi_instance_count(guid);
|
||||
|
||||
wobj = hp_wmi_get_wobj(guid, mid);
|
||||
if (!wobj) {
|
||||
hi = mid;
|
||||
continue;
|
||||
}
|
||||
|
||||
lo = mid + 1;
|
||||
kfree(wobj);
|
||||
}
|
||||
|
||||
return lo;
|
||||
return clamp(count, 0, (int)HP_WMI_MAX_INSTANCES);
|
||||
}
|
||||
|
||||
static int check_wobj(const union acpi_object *wobj,
|
||||
@ -1927,7 +1913,7 @@ static bool add_event_handler(struct hp_wmi_sensors *state)
|
||||
static int hp_wmi_sensors_init(struct hp_wmi_sensors *state)
|
||||
{
|
||||
struct hp_wmi_info *connected[HP_WMI_MAX_INSTANCES];
|
||||
struct hp_wmi_platform_events *pevents;
|
||||
struct hp_wmi_platform_events *pevents = NULL;
|
||||
struct device *dev = &state->wdev->dev;
|
||||
struct hp_wmi_info *info;
|
||||
struct device *hwdev;
|
||||
|
242
drivers/hwmon/hs3001.c
Normal file
242
drivers/hwmon/hs3001.c
Normal file
@ -0,0 +1,242 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* This is a non-complete driver implementation for the
|
||||
* HS3001 humidity and temperature sensor and compatibles. It does not include
|
||||
* the configuration possibilities, where it needs to be set to 'programming mode'
|
||||
* during power-up.
|
||||
*
|
||||
*
|
||||
* Copyright (C) 2023 SYS TEC electronic AG
|
||||
* Author: Andre Werner <andre.werner@systec-electronic.com>
|
||||
*/
|
||||
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
/* Measurement times */
|
||||
#define HS3001_WAKEUP_TIME 100 /* us */
|
||||
#define HS3001_8BIT_RESOLUTION 550 /* us */
|
||||
#define HS3001_10BIT_RESOLUTION 1310 /* us */
|
||||
#define HS3001_12BIT_RESOLUTION 4500 /* us */
|
||||
#define HS3001_14BIT_RESOLUTION 16900 /* us */
|
||||
|
||||
#define HS3001_RESPONSE_LENGTH 4
|
||||
|
||||
#define HS3001_FIXPOINT_ARITH 1000U
|
||||
|
||||
#define HS3001_MASK_HUMIDITY_0X3FFF GENMASK(13, 0)
|
||||
#define HS3001_MASK_STATUS_0XC0 GENMASK(7, 6)
|
||||
|
||||
/* Definitions for Status Bits of A/D Data */
|
||||
#define HS3001_DATA_VALID 0x00 /* Valid Data */
|
||||
#define HS3001_DATA_STALE 0x01 /* Stale Data */
|
||||
|
||||
struct hs3001_data {
|
||||
struct i2c_client *client;
|
||||
struct mutex i2c_lock; /* lock for sending i2c commands */
|
||||
u32 wait_time; /* in us */
|
||||
int temperature; /* in milli degree */
|
||||
u32 humidity; /* in milli % */
|
||||
};
|
||||
|
||||
static int hs3001_extract_temperature(u16 raw)
|
||||
{
|
||||
/* fixpoint arithmetic 1 digit */
|
||||
u32 temp = (raw >> 2) * HS3001_FIXPOINT_ARITH * 165;
|
||||
|
||||
temp /= (1 << 14) - 1;
|
||||
|
||||
return (int)temp - 40 * HS3001_FIXPOINT_ARITH;
|
||||
}
|
||||
|
||||
static u32 hs3001_extract_humidity(u16 raw)
|
||||
{
|
||||
u32 hum = (raw & HS3001_MASK_HUMIDITY_0X3FFF) * HS3001_FIXPOINT_ARITH * 100;
|
||||
|
||||
return hum /= (1 << 14) - 1;
|
||||
}
|
||||
|
||||
static int hs3001_data_fetch_command(struct i2c_client *client,
|
||||
struct hs3001_data *data)
|
||||
{
|
||||
int ret;
|
||||
u8 buf[HS3001_RESPONSE_LENGTH];
|
||||
u8 hs3001_status;
|
||||
|
||||
ret = i2c_master_recv(client, buf, HS3001_RESPONSE_LENGTH);
|
||||
if (ret != HS3001_RESPONSE_LENGTH) {
|
||||
ret = ret < 0 ? ret : -EIO;
|
||||
dev_dbg(&client->dev,
|
||||
"Error in i2c communication. Error code: %d.\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
hs3001_status = FIELD_GET(HS3001_MASK_STATUS_0XC0, buf[0]);
|
||||
if (hs3001_status == HS3001_DATA_STALE) {
|
||||
dev_dbg(&client->dev, "Sensor busy.\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
if (hs3001_status != HS3001_DATA_VALID) {
|
||||
dev_dbg(&client->dev, "Data invalid.\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
data->humidity =
|
||||
hs3001_extract_humidity(be16_to_cpup((__be16 *)&buf[0]));
|
||||
data->temperature =
|
||||
hs3001_extract_temperature(be16_to_cpup((__be16 *)&buf[2]));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static umode_t hs3001_is_visible(const void *data, enum hwmon_sensor_types type,
|
||||
u32 attr, int channel)
|
||||
{
|
||||
/* Both, humidity and temperature can only be read. */
|
||||
return 0444;
|
||||
}
|
||||
|
||||
static int hs3001_read(struct device *dev, enum hwmon_sensor_types type,
|
||||
u32 attr, int channel, long *val)
|
||||
{
|
||||
struct hs3001_data *data = dev_get_drvdata(dev);
|
||||
struct i2c_client *client = data->client;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&data->i2c_lock);
|
||||
ret = i2c_master_send(client, NULL, 0);
|
||||
if (ret < 0) {
|
||||
mutex_unlock(&data->i2c_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Sensor needs some time to process measurement depending on
|
||||
* resolution (ref. datasheet)
|
||||
*/
|
||||
fsleep(data->wait_time);
|
||||
|
||||
ret = hs3001_data_fetch_command(client, data);
|
||||
mutex_unlock(&data->i2c_lock);
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
switch (type) {
|
||||
case hwmon_temp:
|
||||
switch (attr) {
|
||||
case hwmon_temp_input:
|
||||
*val = data->temperature;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
case hwmon_humidity:
|
||||
switch (attr) {
|
||||
case hwmon_humidity_input:
|
||||
*val = data->humidity;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct hwmon_channel_info *hs3001_info[] = {
|
||||
HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT),
|
||||
HWMON_CHANNEL_INFO(humidity, HWMON_H_INPUT),
|
||||
NULL
|
||||
};
|
||||
|
||||
static const struct hwmon_ops hs3001_hwmon_ops = {
|
||||
.is_visible = hs3001_is_visible,
|
||||
.read = hs3001_read,
|
||||
};
|
||||
|
||||
static const struct hwmon_chip_info hs3001_chip_info = {
|
||||
.ops = &hs3001_hwmon_ops,
|
||||
.info = hs3001_info,
|
||||
};
|
||||
|
||||
/* device ID table */
|
||||
static const struct i2c_device_id hs3001_ids[] = {
|
||||
{ "hs3001", 0 },
|
||||
{ },
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(i2c, hs3001_ids);
|
||||
|
||||
static const struct of_device_id hs3001_of_match[] = {
|
||||
{.compatible = "renesas,hs3001"},
|
||||
{ },
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(of, hs3001_of_match);
|
||||
|
||||
static int hs3001_probe(struct i2c_client *client)
|
||||
{
|
||||
struct hs3001_data *data;
|
||||
struct device *hwmon_dev;
|
||||
struct device *dev = &client->dev;
|
||||
|
||||
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
data->client = client;
|
||||
|
||||
/*
|
||||
* Measurement time = wake-up time + measurement time temperature
|
||||
* + measurement time humidity. This is currently static, because
|
||||
* enabling programming mode is not supported, yet.
|
||||
*/
|
||||
data->wait_time = (HS3001_WAKEUP_TIME + HS3001_14BIT_RESOLUTION +
|
||||
HS3001_14BIT_RESOLUTION);
|
||||
|
||||
mutex_init(&data->i2c_lock);
|
||||
|
||||
hwmon_dev = devm_hwmon_device_register_with_info(dev,
|
||||
client->name,
|
||||
data,
|
||||
&hs3001_chip_info,
|
||||
NULL);
|
||||
|
||||
if (IS_ERR(hwmon_dev))
|
||||
return dev_err_probe(dev, PTR_ERR(hwmon_dev),
|
||||
"Unable to register hwmon device.\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct i2c_driver hs3001_i2c_driver = {
|
||||
.driver = {
|
||||
.name = "hs3001",
|
||||
.of_match_table = hs3001_of_match,
|
||||
},
|
||||
.probe = hs3001_probe,
|
||||
.id_table = hs3001_ids,
|
||||
};
|
||||
|
||||
module_i2c_driver(hs3001_i2c_driver);
|
||||
|
||||
MODULE_AUTHOR("Andre Werner <andre.werner@systec-electronic.com>");
|
||||
MODULE_DESCRIPTION("HS3001 humidity and temperature sensor base driver");
|
||||
MODULE_LICENSE("GPL");
|
@ -31,7 +31,6 @@
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/hwmon-sysfs.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/util_macros.h>
|
||||
@ -625,7 +624,7 @@ static int ina2xx_probe(struct i2c_client *client)
|
||||
enum ina2xx_ids chip;
|
||||
|
||||
if (client->dev.of_node)
|
||||
chip = (enum ina2xx_ids)of_device_get_match_data(&client->dev);
|
||||
chip = (uintptr_t)of_device_get_match_data(&client->dev);
|
||||
else
|
||||
chip = i2c_match_id(ina2xx_id, client)->driver_data;
|
||||
|
||||
|
@ -221,6 +221,10 @@ static bool fix_pwm_polarity;
|
||||
* Super-I/O configuration space.
|
||||
*/
|
||||
#define IT87_REG_VID 0x0a
|
||||
|
||||
/* Interface Selection register on other chips */
|
||||
#define IT87_REG_IFSEL 0x0a
|
||||
|
||||
/*
|
||||
* The IT8705F and IT8712F earlier than revision 0x08 use register 0x0b
|
||||
* for fan divisors. Later IT8712F revisions must use 16-bit tachometer
|
||||
@ -1159,28 +1163,66 @@ static SENSOR_DEVICE_ATTR_2(temp4_input, S_IRUGO, show_temp, NULL, 3, 0);
|
||||
static SENSOR_DEVICE_ATTR_2(temp5_input, S_IRUGO, show_temp, NULL, 4, 0);
|
||||
static SENSOR_DEVICE_ATTR_2(temp6_input, S_IRUGO, show_temp, NULL, 5, 0);
|
||||
|
||||
static int get_temp_type(struct it87_data *data, int index)
|
||||
{
|
||||
/*
|
||||
* 2 is deprecated;
|
||||
* 3 = thermal diode;
|
||||
* 4 = thermistor;
|
||||
* 5 = AMDTSI;
|
||||
* 6 = Intel PECI;
|
||||
* 0 = disabled
|
||||
*/
|
||||
u8 reg, extra;
|
||||
int ttype, type = 0;
|
||||
|
||||
/* Detect PECI vs. AMDTSI */
|
||||
ttype = 6;
|
||||
if ((has_temp_peci(data, index)) || data->type == it8721 ||
|
||||
data->type == it8720) {
|
||||
extra = it87_read_value(data, IT87_REG_IFSEL);
|
||||
if ((extra & 0x70) == 0x40)
|
||||
ttype = 5;
|
||||
}
|
||||
|
||||
reg = it87_read_value(data, IT87_REG_TEMP_ENABLE);
|
||||
|
||||
/* Per chip special detection */
|
||||
switch (data->type) {
|
||||
case it8622:
|
||||
if (!(reg & 0xc0) && index == 3)
|
||||
type = ttype;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (type || index >= 3)
|
||||
return type;
|
||||
|
||||
extra = it87_read_value(data, IT87_REG_TEMP_EXTRA);
|
||||
|
||||
if ((has_temp_peci(data, index) && (reg >> 6 == index + 1)) ||
|
||||
(has_temp_old_peci(data, index) && (extra & 0x80)))
|
||||
type = ttype; /* Intel PECI or AMDTSI */
|
||||
else if (reg & BIT(index))
|
||||
type = 3; /* thermal diode */
|
||||
else if (reg & BIT(index + 3))
|
||||
type = 4; /* thermistor */
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
static ssize_t show_temp_type(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
|
||||
int nr = sensor_attr->index;
|
||||
struct it87_data *data = it87_update_device(dev);
|
||||
u8 reg, extra;
|
||||
|
||||
if (IS_ERR(data))
|
||||
return PTR_ERR(data);
|
||||
|
||||
reg = data->sensor; /* In case value is updated while used */
|
||||
extra = data->extra;
|
||||
|
||||
if ((has_temp_peci(data, nr) && (reg >> 6 == nr + 1)) ||
|
||||
(has_temp_old_peci(data, nr) && (extra & 0x80)))
|
||||
return sprintf(buf, "6\n"); /* Intel PECI */
|
||||
if (reg & (1 << nr))
|
||||
return sprintf(buf, "3\n"); /* thermal diode */
|
||||
if (reg & (8 << nr))
|
||||
return sprintf(buf, "4\n"); /* thermistor */
|
||||
return sprintf(buf, "0\n"); /* disabled */
|
||||
return sprintf(buf, "%d\n", get_temp_type(data, sensor_attr->index));
|
||||
}
|
||||
|
||||
static ssize_t set_temp_type(struct device *dev, struct device_attribute *attr,
|
||||
@ -2313,6 +2355,12 @@ static umode_t it87_temp_is_visible(struct kobject *kobj,
|
||||
if (!(data->has_temp & BIT(i)))
|
||||
return 0;
|
||||
|
||||
if (a == 3) {
|
||||
if (get_temp_type(data, i) == 0)
|
||||
return 0;
|
||||
return attr->mode;
|
||||
}
|
||||
|
||||
if (a == 5 && !has_temp_offset(data))
|
||||
return 0;
|
||||
|
||||
|
@ -334,24 +334,6 @@ static struct regmap *lan966x_init_regmap(struct platform_device *pdev,
|
||||
return devm_regmap_init_mmio(&pdev->dev, base, ®map_config);
|
||||
}
|
||||
|
||||
static void lan966x_clk_disable(void *data)
|
||||
{
|
||||
struct lan966x_hwmon *hwmon = data;
|
||||
|
||||
clk_disable_unprepare(hwmon->clk);
|
||||
}
|
||||
|
||||
static int lan966x_clk_enable(struct device *dev, struct lan966x_hwmon *hwmon)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = clk_prepare_enable(hwmon->clk);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return devm_add_action_or_reset(dev, lan966x_clk_disable, hwmon);
|
||||
}
|
||||
|
||||
static int lan966x_hwmon_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
@ -363,15 +345,11 @@ static int lan966x_hwmon_probe(struct platform_device *pdev)
|
||||
if (!hwmon)
|
||||
return -ENOMEM;
|
||||
|
||||
hwmon->clk = devm_clk_get(dev, NULL);
|
||||
hwmon->clk = devm_clk_get_enabled(dev, NULL);
|
||||
if (IS_ERR(hwmon->clk))
|
||||
return dev_err_probe(dev, PTR_ERR(hwmon->clk),
|
||||
"failed to get clock\n");
|
||||
|
||||
ret = lan966x_clk_enable(dev, hwmon);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret, "failed to enable clock\n");
|
||||
|
||||
hwmon->clk_rate = clk_get_rate(hwmon->clk);
|
||||
|
||||
hwmon->regmap_pvt = lan966x_init_regmap(pdev, "pvt");
|
||||
|
@ -33,7 +33,7 @@
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/sysfs.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
@ -1105,7 +1105,7 @@ static int lm63_probe(struct i2c_client *client)
|
||||
|
||||
/* Set the device type */
|
||||
if (client->dev.of_node)
|
||||
data->kind = (enum chips)of_device_get_match_data(&client->dev);
|
||||
data->kind = (uintptr_t)of_device_get_match_data(&client->dev);
|
||||
else
|
||||
data->kind = i2c_match_id(lm63_id, client)->driver_data;
|
||||
if (data->kind == lm64)
|
||||
|
@ -13,7 +13,6 @@
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/hwmon-sysfs.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/util_macros.h>
|
||||
@ -579,7 +578,7 @@ static int lm75_probe(struct i2c_client *client)
|
||||
enum lm75_type kind;
|
||||
|
||||
if (client->dev.of_node)
|
||||
kind = (enum lm75_type)of_device_get_match_data(&client->dev);
|
||||
kind = (uintptr_t)of_device_get_match_data(&client->dev);
|
||||
else
|
||||
kind = i2c_match_id(lm75_ids, client)->driver_data;
|
||||
|
||||
|
@ -12,7 +12,7 @@
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/jiffies.h>
|
||||
@ -1559,7 +1559,7 @@ static int lm85_probe(struct i2c_client *client)
|
||||
|
||||
data->client = client;
|
||||
if (client->dev.of_node)
|
||||
data->type = (enum chips)of_device_get_match_data(&client->dev);
|
||||
data->type = (uintptr_t)of_device_get_match_data(&client->dev);
|
||||
else
|
||||
data->type = i2c_match_id(lm85_id, client)->driver_data;
|
||||
mutex_init(&data->update_lock);
|
||||
|
@ -106,7 +106,7 @@
|
||||
#include <linux/kstrtox.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/workqueue.h>
|
||||
@ -2765,7 +2765,7 @@ static int lm90_probe(struct i2c_client *client)
|
||||
|
||||
/* Set the device type */
|
||||
if (client->dev.of_node)
|
||||
data->kind = (enum chips)of_device_get_match_data(&client->dev);
|
||||
data->kind = (uintptr_t)of_device_get_match_data(&client->dev);
|
||||
else
|
||||
data->kind = i2c_match_id(lm90_id, client)->driver_data;
|
||||
|
||||
|
@ -16,7 +16,6 @@
|
||||
#include <linux/mfd/lochnagar2_regs.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
|
@ -9,8 +9,9 @@
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/hwmon-sysfs.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <lantiq_soc.h>
|
||||
|
||||
|
@ -11,7 +11,6 @@
|
||||
#include <linux/init.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
|
@ -12,7 +12,7 @@
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
#define MAX6621_DRV_NAME "max6621"
|
||||
|
@ -618,11 +618,17 @@ MODULE_DEVICE_TABLE(i2c, max6639_id);
|
||||
|
||||
static DEFINE_SIMPLE_DEV_PM_OPS(max6639_pm_ops, max6639_suspend, max6639_resume);
|
||||
|
||||
static const struct of_device_id max6639_of_match[] = {
|
||||
{ .compatible = "maxim,max6639", },
|
||||
{ },
|
||||
};
|
||||
|
||||
static struct i2c_driver max6639_driver = {
|
||||
.class = I2C_CLASS_HWMON,
|
||||
.driver = {
|
||||
.name = "max6639",
|
||||
.pm = pm_sleep_ptr(&max6639_pm_ops),
|
||||
.of_match_table = max6639_of_match,
|
||||
},
|
||||
.probe = max6639_probe,
|
||||
.id_table = max6639_id,
|
||||
|
@ -15,7 +15,6 @@
|
||||
#include <linux/hwmon-sysfs.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of.h>
|
||||
|
||||
#include <linux/platform_data/max6697.h>
|
||||
@ -703,7 +702,7 @@ static int max6697_probe(struct i2c_client *client)
|
||||
return -ENOMEM;
|
||||
|
||||
if (client->dev.of_node)
|
||||
data->type = (enum chips)of_device_get_match_data(&client->dev);
|
||||
data->type = (uintptr_t)of_device_get_match_data(&client->dev);
|
||||
else
|
||||
data->type = i2c_match_id(max6697_id, client)->driver_data;
|
||||
data->chip = &max6697_chip_data[data->type];
|
||||
|
@ -20,7 +20,6 @@
|
||||
#include <linux/err.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
|
||||
/* Vdd / reference voltage in millivolt */
|
||||
#define MCP3021_VDD_REF_MAX 5500
|
||||
|
@ -12,7 +12,7 @@
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/thermal.h>
|
||||
|
||||
#define MLXREG_FAN_MAX_TACHO 14
|
||||
#define MLXREG_FAN_MAX_TACHO 24
|
||||
#define MLXREG_FAN_MAX_PWM 4
|
||||
#define MLXREG_FAN_PWM_NOT_CONNECTED 0xff
|
||||
#define MLXREG_FAN_MAX_STATE 10
|
||||
@ -300,6 +300,16 @@ static const struct hwmon_channel_info * const mlxreg_fan_hwmon_info[] = {
|
||||
HWMON_F_INPUT | HWMON_F_FAULT,
|
||||
HWMON_F_INPUT | HWMON_F_FAULT,
|
||||
HWMON_F_INPUT | HWMON_F_FAULT,
|
||||
HWMON_F_INPUT | HWMON_F_FAULT,
|
||||
HWMON_F_INPUT | HWMON_F_FAULT,
|
||||
HWMON_F_INPUT | HWMON_F_FAULT,
|
||||
HWMON_F_INPUT | HWMON_F_FAULT,
|
||||
HWMON_F_INPUT | HWMON_F_FAULT,
|
||||
HWMON_F_INPUT | HWMON_F_FAULT,
|
||||
HWMON_F_INPUT | HWMON_F_FAULT,
|
||||
HWMON_F_INPUT | HWMON_F_FAULT,
|
||||
HWMON_F_INPUT | HWMON_F_FAULT,
|
||||
HWMON_F_INPUT | HWMON_F_FAULT,
|
||||
HWMON_F_INPUT | HWMON_F_FAULT),
|
||||
HWMON_CHANNEL_INFO(pwm,
|
||||
HWMON_PWM_INPUT,
|
||||
|
@ -33,7 +33,8 @@
|
||||
* (0xd451)
|
||||
* nct6798d 14 7 7 2+6 0xd428 0xc1 0x5ca3
|
||||
* (0xd429)
|
||||
* nct6799d 14 7 7 2+6 0xd802 0xc1 0x5ca3
|
||||
* nct6796d-s 18 7 7 6+2 0xd801 0xc1 0x5ca3
|
||||
* nct6799d-r 18 7 7 6+2 0xd802 0xc1 0x5ca3
|
||||
*
|
||||
* #temp lists the number of monitored temperature sources (first value) plus
|
||||
* the number of directly connectable temperature sensors (second value).
|
||||
@ -79,14 +80,17 @@ static const char * const nct6775_device_names[] = {
|
||||
|
||||
/* Common and NCT6775 specific data */
|
||||
|
||||
/* Voltage min/max registers for nr=7..14 are in bank 5 */
|
||||
/*
|
||||
* Voltage min/max registers for nr=7..14 are in bank 5
|
||||
* min/max: 15-17 for NCT6799 only
|
||||
*/
|
||||
|
||||
static const u16 NCT6775_REG_IN_MAX[] = {
|
||||
0x2b, 0x2d, 0x2f, 0x31, 0x33, 0x35, 0x37, 0x554, 0x556, 0x558, 0x55a,
|
||||
0x55c, 0x55e, 0x560, 0x562 };
|
||||
0x55c, 0x55e, 0x560, 0x562, 0x564, 0x570, 0x572 };
|
||||
static const u16 NCT6775_REG_IN_MIN[] = {
|
||||
0x2c, 0x2e, 0x30, 0x32, 0x34, 0x36, 0x38, 0x555, 0x557, 0x559, 0x55b,
|
||||
0x55d, 0x55f, 0x561, 0x563 };
|
||||
0x55d, 0x55f, 0x561, 0x563, 0x565, 0x571, 0x573 };
|
||||
static const u16 NCT6775_REG_IN[] = {
|
||||
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x550, 0x551, 0x552
|
||||
};
|
||||
@ -97,31 +101,23 @@ static const u16 NCT6775_REG_IN[] = {
|
||||
|
||||
static const u16 NCT6775_REG_ALARM[NUM_REG_ALARM] = { 0x459, 0x45A, 0x45B };
|
||||
|
||||
/* 0..15 voltages, 16..23 fans, 24..29 temperatures, 30..31 intrusion */
|
||||
|
||||
static const s8 NCT6775_ALARM_BITS[] = {
|
||||
0, 1, 2, 3, 8, 21, 20, 16, /* in0.. in7 */
|
||||
17, -1, -1, -1, -1, -1, -1, /* in8..in14 */
|
||||
-1, /* unused */
|
||||
6, 7, 11, -1, -1, /* fan1..fan5 */
|
||||
-1, -1, -1, /* unused */
|
||||
4, 5, 13, -1, -1, -1, /* temp1..temp6 */
|
||||
12, -1 }; /* intrusion0, intrusion1 */
|
||||
static const s8 NCT6775_ALARM_BITS[NUM_ALARM_BITS] = {
|
||||
0, 1, 2, 3, 8, 21, 20, 16, 17, -1, -1, -1, /* in0-in11 */
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* in12-in23 */
|
||||
6, 7, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* fan1-fan12 */
|
||||
4, 5, 13, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* temp1-temp12 */
|
||||
12, -1, /* intr0-intr1 */
|
||||
};
|
||||
|
||||
static const u16 NCT6775_REG_BEEP[NUM_REG_BEEP] = { 0x56, 0x57, 0x453, 0x4e };
|
||||
|
||||
/*
|
||||
* 0..14 voltages, 15 global beep enable, 16..23 fans, 24..29 temperatures,
|
||||
* 30..31 intrusion
|
||||
*/
|
||||
static const s8 NCT6775_BEEP_BITS[] = {
|
||||
0, 1, 2, 3, 8, 9, 10, 16, /* in0.. in7 */
|
||||
17, -1, -1, -1, -1, -1, -1, /* in8..in14 */
|
||||
21, /* global beep enable */
|
||||
6, 7, 11, 28, -1, /* fan1..fan5 */
|
||||
-1, -1, -1, /* unused */
|
||||
4, 5, 13, -1, -1, -1, /* temp1..temp6 */
|
||||
12, -1 }; /* intrusion0, intrusion1 */
|
||||
static const s8 NCT6775_BEEP_BITS[NUM_BEEP_BITS] = {
|
||||
0, 1, 2, 3, 8, 9, 10, 16, 17, -1, -1, -1, /* in0-in11 */
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* in12-in23 */
|
||||
6, 7, 11, 28, -1, -1, -1, -1, -1, -1, -1, -1, /* fan1-fan12 */
|
||||
4, 5, 13, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* temp1-temp12 */
|
||||
12, -1, 21 /* intr0-intr1, beep_en */
|
||||
};
|
||||
|
||||
/* DC or PWM output fan configuration */
|
||||
static const u8 NCT6775_REG_PWM_MODE[] = { 0x04, 0x04, 0x12 };
|
||||
@ -255,25 +251,24 @@ static const u16 NCT6775_REG_TSI_TEMP[] = { 0x669 };
|
||||
#define NCT6776_REG_FAN_STEP_UP_TIME NCT6775_REG_FAN_STEP_DOWN_TIME
|
||||
#define NCT6776_REG_FAN_STEP_DOWN_TIME NCT6775_REG_FAN_STEP_UP_TIME
|
||||
|
||||
static const s8 NCT6776_ALARM_BITS[] = {
|
||||
0, 1, 2, 3, 8, 21, 20, 16, /* in0.. in7 */
|
||||
17, -1, -1, -1, -1, -1, -1, /* in8..in14 */
|
||||
-1, /* unused */
|
||||
6, 7, 11, 10, 23, /* fan1..fan5 */
|
||||
-1, -1, -1, /* unused */
|
||||
4, 5, 13, -1, -1, -1, /* temp1..temp6 */
|
||||
12, 9 }; /* intrusion0, intrusion1 */
|
||||
static const s8 NCT6776_ALARM_BITS[NUM_ALARM_BITS] = {
|
||||
0, 1, 2, 3, 8, 21, 20, 16, 17, -1, -1, -1, /* in0-in11 */
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* in12-in23 */
|
||||
6, 7, 11, 10, 23, -1, -1, -1, -1, -1, -1, -1, /* fan1-fan12 */
|
||||
4, 5, 13, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* temp1-temp12 */
|
||||
12, 9, /* intr0-intr1 */
|
||||
};
|
||||
|
||||
static const u16 NCT6776_REG_BEEP[NUM_REG_BEEP] = { 0xb2, 0xb3, 0xb4, 0xb5 };
|
||||
/* 0xbf: nct6799 only */
|
||||
static const u16 NCT6776_REG_BEEP[NUM_REG_BEEP] = { 0xb2, 0xb3, 0xb4, 0xb5, 0xbf };
|
||||
|
||||
static const s8 NCT6776_BEEP_BITS[] = {
|
||||
0, 1, 2, 3, 4, 5, 6, 7, /* in0.. in7 */
|
||||
8, -1, -1, -1, -1, -1, -1, /* in8..in14 */
|
||||
24, /* global beep enable */
|
||||
25, 26, 27, 28, 29, /* fan1..fan5 */
|
||||
-1, -1, -1, /* unused */
|
||||
16, 17, 18, 19, 20, 21, /* temp1..temp6 */
|
||||
30, 31 }; /* intrusion0, intrusion1 */
|
||||
static const s8 NCT6776_BEEP_BITS[NUM_BEEP_BITS] = {
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, -1, -1, -1, /* in0-in11 */
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* in12-in23 */
|
||||
25, 26, 27, 28, 29, -1, -1, -1, -1, -1, -1, -1, /* fan1-fan12 */
|
||||
16, 17, 18, 19, 20, 21, -1, -1, -1, -1, -1, -1, /* temp1-temp12 */
|
||||
30, 31, 24 /* intr0-intr1, beep_en */
|
||||
};
|
||||
|
||||
static const u16 NCT6776_REG_TOLERANCE_H[] = {
|
||||
0x10c, 0x20c, 0x30c, 0x80c, 0x90c, 0xa0c, 0xb0c };
|
||||
@ -337,30 +332,35 @@ static const u16 NCT6776_REG_TSI_TEMP[] = {
|
||||
|
||||
/* NCT6779 specific data */
|
||||
|
||||
/*
|
||||
* 15-17 for NCT6799 only, register labels are:
|
||||
* CPUVC, VIN1, AVSB, 3VCC, VIN0, VIN8, VIN4, 3VSB
|
||||
* VBAT, VTT, VIN5, VIN6, VIN2, VIN3, VIN7, VIN9
|
||||
* VHIF, VIN10
|
||||
*/
|
||||
static const u16 NCT6779_REG_IN[] = {
|
||||
0x480, 0x481, 0x482, 0x483, 0x484, 0x485, 0x486, 0x487,
|
||||
0x488, 0x489, 0x48a, 0x48b, 0x48c, 0x48d, 0x48e };
|
||||
0x488, 0x489, 0x48a, 0x48b, 0x48c, 0x48d, 0x48e, 0x48f,
|
||||
0x470, 0x471};
|
||||
|
||||
static const u16 NCT6779_REG_ALARM[NUM_REG_ALARM] = {
|
||||
0x459, 0x45A, 0x45B, 0x568 };
|
||||
|
||||
static const s8 NCT6779_ALARM_BITS[] = {
|
||||
0, 1, 2, 3, 8, 21, 20, 16, /* in0.. in7 */
|
||||
17, 24, 25, 26, 27, 28, 29, /* in8..in14 */
|
||||
-1, /* unused */
|
||||
6, 7, 11, 10, 23, /* fan1..fan5 */
|
||||
-1, -1, -1, /* unused */
|
||||
4, 5, 13, -1, -1, -1, /* temp1..temp6 */
|
||||
12, 9 }; /* intrusion0, intrusion1 */
|
||||
static const s8 NCT6779_ALARM_BITS[NUM_ALARM_BITS] = {
|
||||
0, 1, 2, 3, 8, 21, 20, 16, 17, 24, 25, 26, /* in0-in11 */
|
||||
27, 28, 29, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* in12-in23 */
|
||||
6, 7, 11, 10, 23, -1, -1, -1, -1, -1, -1, -1, /* fan1-fan12 */
|
||||
4, 5, 13, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* temp1-temp12 */
|
||||
12, 9, /* intr0-intr1 */
|
||||
};
|
||||
|
||||
static const s8 NCT6779_BEEP_BITS[] = {
|
||||
0, 1, 2, 3, 4, 5, 6, 7, /* in0.. in7 */
|
||||
8, 9, 10, 11, 12, 13, 14, /* in8..in14 */
|
||||
24, /* global beep enable */
|
||||
25, 26, 27, 28, 29, /* fan1..fan5 */
|
||||
-1, -1, -1, /* unused */
|
||||
16, 17, -1, -1, -1, -1, /* temp1..temp6 */
|
||||
30, 31 }; /* intrusion0, intrusion1 */
|
||||
static const s8 NCT6779_BEEP_BITS[NUM_BEEP_BITS] = {
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, /* in0-in11 */
|
||||
12, 13, 14, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* in12-in23 */
|
||||
25, 26, 27, 28, 29, -1, -1, -1, -1, -1, -1, -1, /* fan1-fan12 */
|
||||
16, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* temp1-temp12 */
|
||||
30, 31, 24 /* intr0-intr1, beep_en */
|
||||
};
|
||||
|
||||
static const u16 NCT6779_REG_FAN[] = {
|
||||
0x4c0, 0x4c2, 0x4c4, 0x4c6, 0x4c8, 0x4ca, 0x4ce };
|
||||
@ -448,14 +448,13 @@ static const u16 NCT6791_REG_WEIGHT_DUTY_BASE[NUM_FAN] = { 0, 0x23e };
|
||||
static const u16 NCT6791_REG_ALARM[NUM_REG_ALARM] = {
|
||||
0x459, 0x45A, 0x45B, 0x568, 0x45D };
|
||||
|
||||
static const s8 NCT6791_ALARM_BITS[] = {
|
||||
0, 1, 2, 3, 8, 21, 20, 16, /* in0.. in7 */
|
||||
17, 24, 25, 26, 27, 28, 29, /* in8..in14 */
|
||||
-1, /* unused */
|
||||
6, 7, 11, 10, 23, 33, /* fan1..fan6 */
|
||||
-1, -1, /* unused */
|
||||
4, 5, 13, -1, -1, -1, /* temp1..temp6 */
|
||||
12, 9 }; /* intrusion0, intrusion1 */
|
||||
static const s8 NCT6791_ALARM_BITS[NUM_ALARM_BITS] = {
|
||||
0, 1, 2, 3, 8, 21, 20, 16, 17, 24, 25, 26, /* in0-in11 */
|
||||
27, 28, 29, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* in12-in23 */
|
||||
6, 7, 11, 10, 23, 33, -1, -1, -1, -1, -1, -1, /* fan1-fan12 */
|
||||
4, 5, 13, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* temp1-temp12 */
|
||||
12, 9, /* intr0-intr1 */
|
||||
};
|
||||
|
||||
/* NCT6792/NCT6793 specific data */
|
||||
|
||||
@ -618,6 +617,28 @@ static const char *const nct6796_temp_label[] = {
|
||||
|
||||
static const u16 NCT6796_REG_TSI_TEMP[] = { 0x409, 0x40b };
|
||||
|
||||
static const u16 NCT6798_REG_TEMP[] = {
|
||||
0x27, 0x150, 0x670, 0x672, 0x674, 0x676, 0x678, 0x67a};
|
||||
|
||||
static const u16 NCT6798_REG_TEMP_SOURCE[] = {
|
||||
0x621, 0x622, 0xc26, 0xc27, 0xc28, 0xc29, 0xc2a, 0xc2b };
|
||||
|
||||
static const u16 NCT6798_REG_TEMP_MON[] = {
|
||||
0x73, 0x75, 0x77, 0x79, 0x7b, 0x7d, 0x4a0 };
|
||||
static const u16 NCT6798_REG_TEMP_OVER[] = {
|
||||
0x39, 0x155, 0xc1a, 0xc1b, 0xc1c, 0xc1d, 0xc1e, 0xc1f };
|
||||
static const u16 NCT6798_REG_TEMP_HYST[] = {
|
||||
0x3a, 0x153, 0xc20, 0xc21, 0xc22, 0xc23, 0xc24, 0xc25 };
|
||||
|
||||
static const u16 NCT6798_REG_TEMP_CRIT[32] = {
|
||||
0x135, 0x235, 0x335, 0x835, 0x935, 0xa35, 0xb35, 0 };
|
||||
|
||||
static const u16 NCT6798_REG_TEMP_ALTERNATE[32] = {
|
||||
0x490, 0x491, 0x492, 0x493, 0x494, 0x495, 0x496, 0,
|
||||
0, 0, 0, 0, 0x4a2, 0, 0, 0,
|
||||
0, 0x400, 0x401, 0x402, 0x404, 0x405, 0x406, 0x407,
|
||||
0x408, 0x419, 0x41a, 0x4f4, 0x4f5 };
|
||||
|
||||
static const char *const nct6798_temp_label[] = {
|
||||
"",
|
||||
"SYSTIN",
|
||||
@ -656,6 +677,26 @@ static const char *const nct6798_temp_label[] = {
|
||||
#define NCT6798_TEMP_MASK 0xbfff0ffe
|
||||
#define NCT6798_VIRT_TEMP_MASK 0x80000c00
|
||||
|
||||
static const u16 NCT6799_REG_ALARM[NUM_REG_ALARM] = {
|
||||
0x459, 0x45A, 0x45B, 0x568, 0x45D, 0xc01 };
|
||||
|
||||
static const s8 NCT6799_ALARM_BITS[NUM_ALARM_BITS] = {
|
||||
0, 1, 2, 3, 8, -1, 20, 16, 17, 24, 25, 26, /* in0-in11 */
|
||||
27, 28, 29, 30, 31, -1, -1, -1, -1, -1, -1, -1, /* in12-in23 */
|
||||
6, 7, 11, 10, 23, 33, -1, -1, -1, -1, -1, -1, /* fan1-fan12 */
|
||||
4, 5, 40, 41, 42, 43, 44, -1, -1, -1, -1, -1, /* temp1-temp12 */
|
||||
12, 9, /* intr0-intr1 */
|
||||
};
|
||||
|
||||
static const s8 NCT6799_BEEP_BITS[NUM_BEEP_BITS] = {
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, /* in0-in11 */
|
||||
12, 13, 14, 15, 34, 35, -1, -1, -1, -1, -1, -1, /* in12-in23 */
|
||||
25, 26, 27, 28, 29, -1, -1, -1, -1, -1, -1, -1, /* fan1-fan12 */
|
||||
16, 17, 18, 19, 20, 21, 22, 23, -1, -1, -1, -1, /* temp1-temp12 */
|
||||
30, 31, 24 /* intr0-intr1, beep_en */
|
||||
};
|
||||
|
||||
/* PECI Calibration only for NCT6799D, not NCT6796D-S */
|
||||
static const char *const nct6799_temp_label[] = {
|
||||
"",
|
||||
"SYSTIN",
|
||||
@ -685,8 +726,8 @@ static const char *const nct6799_temp_label[] = {
|
||||
"Agent1 Dimm1",
|
||||
"BYTE_TEMP0",
|
||||
"BYTE_TEMP1",
|
||||
"PECI Agent 0 Calibration", /* undocumented */
|
||||
"PECI Agent 1 Calibration", /* undocumented */
|
||||
"PECI/TSI Agent 0 Calibration",
|
||||
"PECI/TSI Agent 1 Calibration",
|
||||
"",
|
||||
"Virtual_TEMP"
|
||||
};
|
||||
@ -763,27 +804,23 @@ static const u16 NCT6106_REG_AUTO_PWM[] = { 0x164, 0x174, 0x184 };
|
||||
static const u16 NCT6106_REG_ALARM[NUM_REG_ALARM] = {
|
||||
0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d };
|
||||
|
||||
static const s8 NCT6106_ALARM_BITS[] = {
|
||||
0, 1, 2, 3, 4, 5, 7, 8, /* in0.. in7 */
|
||||
9, -1, -1, -1, -1, -1, -1, /* in8..in14 */
|
||||
-1, /* unused */
|
||||
32, 33, 34, -1, -1, /* fan1..fan5 */
|
||||
-1, -1, -1, /* unused */
|
||||
16, 17, 18, 19, 20, 21, /* temp1..temp6 */
|
||||
48, -1 /* intrusion0, intrusion1 */
|
||||
static const s8 NCT6106_ALARM_BITS[NUM_ALARM_BITS] = {
|
||||
0, 1, 2, 3, 4, 5, 7, 8, 9, -1, -1, -1, /* in0-in11 */
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* in12-in23 */
|
||||
32, 33, 34, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* fan1-fan12 */
|
||||
16, 17, 18, 19, 20, 21, -1, -1, -1, -1, -1, -1, /* temp1-temp12 */
|
||||
48, -1, /* intr0-intr1 */
|
||||
};
|
||||
|
||||
static const u16 NCT6106_REG_BEEP[NUM_REG_BEEP] = {
|
||||
0x3c0, 0x3c1, 0x3c2, 0x3c3, 0x3c4 };
|
||||
|
||||
static const s8 NCT6106_BEEP_BITS[] = {
|
||||
0, 1, 2, 3, 4, 5, 7, 8, /* in0.. in7 */
|
||||
9, 10, 11, 12, -1, -1, -1, /* in8..in14 */
|
||||
32, /* global beep enable */
|
||||
24, 25, 26, 27, 28, /* fan1..fan5 */
|
||||
-1, -1, -1, /* unused */
|
||||
16, 17, 18, 19, 20, 21, /* temp1..temp6 */
|
||||
34, -1 /* intrusion0, intrusion1 */
|
||||
static const s8 NCT6106_BEEP_BITS[NUM_BEEP_BITS] = {
|
||||
0, 1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 12, /* in0-in11 */
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* in12-in23 */
|
||||
24, 25, 26, 27, 28, -1, -1, -1, -1, -1, -1, -1, /* fan1-fan12 */
|
||||
16, 17, 18, 19, 20, 21, -1, -1, -1, -1, -1, -1, /* temp1-temp12 */
|
||||
34, -1, 32 /* intr0-intr1, beep_en */
|
||||
};
|
||||
|
||||
static const u16 NCT6106_REG_TEMP_ALTERNATE[32] = {
|
||||
@ -843,24 +880,20 @@ static const u16 NCT6116_REG_AUTO_TEMP[] = {
|
||||
static const u16 NCT6116_REG_AUTO_PWM[] = {
|
||||
0x164, 0x174, 0x184, 0x1d4, 0x1e4 };
|
||||
|
||||
static const s8 NCT6116_ALARM_BITS[] = {
|
||||
0, 1, 2, 3, 4, 5, 7, 8, /* in0.. in7 */
|
||||
9, -1, -1, -1, -1, -1, -1, /* in8..in9 */
|
||||
-1, /* unused */
|
||||
32, 33, 34, 35, 36, /* fan1..fan5 */
|
||||
-1, -1, -1, /* unused */
|
||||
16, 17, 18, -1, -1, -1, /* temp1..temp6 */
|
||||
48, -1 /* intrusion0, intrusion1 */
|
||||
static const s8 NCT6116_ALARM_BITS[NUM_ALARM_BITS] = {
|
||||
0, 1, 2, 3, 4, 5, 7, 8, 9, -1, -1, -1, /* in0-in11 */
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* in12-in23 */
|
||||
32, 33, 34, 35, 36, -1, -1, -1, -1, -1, -1, -1, /* fan1-fan12 */
|
||||
16, 17, 18, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* temp1-temp12 */
|
||||
48, -1, /* intr0-intr1 */
|
||||
};
|
||||
|
||||
static const s8 NCT6116_BEEP_BITS[] = {
|
||||
0, 1, 2, 3, 4, 5, 7, 8, /* in0.. in7 */
|
||||
9, 10, 11, 12, -1, -1, -1, /* in8..in14 */
|
||||
32, /* global beep enable */
|
||||
24, 25, 26, 27, 28, /* fan1..fan5 */
|
||||
-1, -1, -1, /* unused */
|
||||
16, 17, 18, -1, -1, -1, /* temp1..temp6 */
|
||||
34, -1 /* intrusion0, intrusion1 */
|
||||
static const s8 NCT6116_BEEP_BITS[NUM_BEEP_BITS] = {
|
||||
0, 1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 12, /* in0-in11 */
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* in12-in23 */
|
||||
24, 25, 26, 27, 28, -1, -1, -1, -1, -1, -1, -1, /* fan1-fan12 */
|
||||
16, 17, 18, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* temp1-temp12 */
|
||||
34, -1, 32 /* intr0-intr1, beep_en */
|
||||
};
|
||||
|
||||
static const u16 NCT6116_REG_TSI_TEMP[] = { 0x59, 0x5b };
|
||||
@ -958,12 +991,12 @@ static const u16 scale_in[15] = {
|
||||
/*
|
||||
* NCT6798 scaling:
|
||||
* CPUVC, IN1, AVSB, 3VCC, IN0, IN8, IN4, 3VSB, VBAT, VTT, IN5, IN6, IN2,
|
||||
* IN3, IN7
|
||||
* Additional scales to be added later: IN9 (800), VHIF (1600)
|
||||
* IN3, IN7, IN9, VHIF, IN10
|
||||
* 15-17 for NCT6799 only
|
||||
*/
|
||||
static const u16 scale_in_6798[15] = {
|
||||
static const u16 scale_in_6798[NUM_IN] = {
|
||||
800, 800, 1600, 1600, 800, 800, 800, 1600, 1600, 1600, 1600, 1600, 800,
|
||||
800, 800
|
||||
800, 800, 800, 1600, 800
|
||||
};
|
||||
|
||||
static inline long in_from_reg(u8 reg, u8 nr, const u16 *scales)
|
||||
@ -3862,13 +3895,9 @@ int nct6775_probe(struct device *dev, struct nct6775_data *data,
|
||||
case nct6795:
|
||||
case nct6796:
|
||||
case nct6797:
|
||||
case nct6798:
|
||||
case nct6799:
|
||||
data->in_num = 15;
|
||||
data->pwm_num = (data->kind == nct6796 ||
|
||||
data->kind == nct6797 ||
|
||||
data->kind == nct6798 ||
|
||||
data->kind == nct6799) ? 7 : 6;
|
||||
data->kind == nct6797) ? 7 : 6;
|
||||
data->auto_pwm_num = 4;
|
||||
data->has_fan_div = false;
|
||||
data->temp_fixed_num = 6;
|
||||
@ -3912,16 +3941,6 @@ int nct6775_probe(struct device *dev, struct nct6775_data *data,
|
||||
data->temp_mask = NCT6796_TEMP_MASK;
|
||||
data->virt_temp_mask = NCT6796_VIRT_TEMP_MASK;
|
||||
break;
|
||||
case nct6798:
|
||||
data->temp_label = nct6798_temp_label;
|
||||
data->temp_mask = NCT6798_TEMP_MASK;
|
||||
data->virt_temp_mask = NCT6798_VIRT_TEMP_MASK;
|
||||
break;
|
||||
case nct6799:
|
||||
data->temp_label = nct6799_temp_label;
|
||||
data->temp_mask = NCT6799_TEMP_MASK;
|
||||
data->virt_temp_mask = NCT6799_VIRT_TEMP_MASK;
|
||||
break;
|
||||
}
|
||||
|
||||
data->REG_CONFIG = NCT6775_REG_CONFIG;
|
||||
@ -3980,8 +3999,6 @@ int nct6775_probe(struct device *dev, struct nct6775_data *data,
|
||||
case nct6795:
|
||||
case nct6796:
|
||||
case nct6797:
|
||||
case nct6798:
|
||||
case nct6799:
|
||||
data->REG_TSI_TEMP = NCT6796_REG_TSI_TEMP;
|
||||
num_reg_tsi_temp = ARRAY_SIZE(NCT6796_REG_TSI_TEMP);
|
||||
break;
|
||||
@ -3990,9 +4007,6 @@ int nct6775_probe(struct device *dev, struct nct6775_data *data,
|
||||
break;
|
||||
}
|
||||
|
||||
if (data->kind == nct6798 || data->kind == nct6799)
|
||||
data->scale_in = scale_in_6798;
|
||||
|
||||
reg_temp = NCT6779_REG_TEMP;
|
||||
num_reg_temp = ARRAY_SIZE(NCT6779_REG_TEMP);
|
||||
if (data->kind == nct6791) {
|
||||
@ -4008,6 +4022,95 @@ int nct6775_probe(struct device *dev, struct nct6775_data *data,
|
||||
reg_temp_alternate = NCT6779_REG_TEMP_ALTERNATE;
|
||||
reg_temp_crit = NCT6779_REG_TEMP_CRIT;
|
||||
|
||||
break;
|
||||
case nct6798:
|
||||
case nct6799:
|
||||
data->in_num = data->kind == nct6799 ? 18 : 15;
|
||||
data->scale_in = scale_in_6798;
|
||||
data->pwm_num = 7;
|
||||
data->auto_pwm_num = 4;
|
||||
data->has_fan_div = false;
|
||||
data->temp_fixed_num = 6;
|
||||
data->num_temp_alarms = 7;
|
||||
data->num_temp_beeps = 8;
|
||||
|
||||
data->ALARM_BITS = NCT6799_ALARM_BITS;
|
||||
data->BEEP_BITS = NCT6799_BEEP_BITS;
|
||||
|
||||
data->fan_from_reg = fan_from_reg_rpm;
|
||||
data->fan_from_reg_min = fan_from_reg13;
|
||||
data->target_temp_mask = 0xff;
|
||||
data->tolerance_mask = 0x07;
|
||||
data->speed_tolerance_limit = 63;
|
||||
|
||||
switch (data->kind) {
|
||||
default:
|
||||
case nct6798:
|
||||
data->temp_label = nct6798_temp_label;
|
||||
data->temp_mask = NCT6798_TEMP_MASK;
|
||||
data->virt_temp_mask = NCT6798_VIRT_TEMP_MASK;
|
||||
break;
|
||||
case nct6799:
|
||||
data->temp_label = nct6799_temp_label;
|
||||
data->temp_mask = NCT6799_TEMP_MASK;
|
||||
data->virt_temp_mask = NCT6799_VIRT_TEMP_MASK;
|
||||
break;
|
||||
}
|
||||
|
||||
data->REG_CONFIG = NCT6775_REG_CONFIG;
|
||||
data->REG_VBAT = NCT6775_REG_VBAT;
|
||||
data->REG_DIODE = NCT6775_REG_DIODE;
|
||||
data->DIODE_MASK = NCT6775_DIODE_MASK;
|
||||
data->REG_VIN = NCT6779_REG_IN;
|
||||
data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN;
|
||||
data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX;
|
||||
data->REG_TARGET = NCT6775_REG_TARGET;
|
||||
data->REG_FAN = NCT6779_REG_FAN;
|
||||
data->REG_FAN_MODE = NCT6775_REG_FAN_MODE;
|
||||
data->REG_FAN_MIN = NCT6776_REG_FAN_MIN;
|
||||
data->REG_FAN_PULSES = NCT6779_REG_FAN_PULSES;
|
||||
data->FAN_PULSE_SHIFT = NCT6775_FAN_PULSE_SHIFT;
|
||||
data->REG_FAN_TIME[0] = NCT6775_REG_FAN_STOP_TIME;
|
||||
data->REG_FAN_TIME[1] = NCT6776_REG_FAN_STEP_UP_TIME;
|
||||
data->REG_FAN_TIME[2] = NCT6776_REG_FAN_STEP_DOWN_TIME;
|
||||
data->REG_TOLERANCE_H = NCT6776_REG_TOLERANCE_H;
|
||||
data->REG_PWM[0] = NCT6775_REG_PWM;
|
||||
data->REG_PWM[1] = NCT6775_REG_FAN_START_OUTPUT;
|
||||
data->REG_PWM[2] = NCT6775_REG_FAN_STOP_OUTPUT;
|
||||
data->REG_PWM[5] = NCT6791_REG_WEIGHT_DUTY_STEP;
|
||||
data->REG_PWM[6] = NCT6791_REG_WEIGHT_DUTY_BASE;
|
||||
data->REG_PWM_READ = NCT6775_REG_PWM_READ;
|
||||
data->REG_PWM_MODE = NCT6776_REG_PWM_MODE;
|
||||
data->PWM_MODE_MASK = NCT6776_PWM_MODE_MASK;
|
||||
data->REG_AUTO_TEMP = NCT6775_REG_AUTO_TEMP;
|
||||
data->REG_AUTO_PWM = NCT6775_REG_AUTO_PWM;
|
||||
data->REG_CRITICAL_TEMP = NCT6775_REG_CRITICAL_TEMP;
|
||||
data->REG_CRITICAL_TEMP_TOLERANCE = NCT6775_REG_CRITICAL_TEMP_TOLERANCE;
|
||||
data->REG_CRITICAL_PWM_ENABLE = NCT6779_REG_CRITICAL_PWM_ENABLE;
|
||||
data->CRITICAL_PWM_ENABLE_MASK = NCT6779_CRITICAL_PWM_ENABLE_MASK;
|
||||
data->REG_CRITICAL_PWM = NCT6779_REG_CRITICAL_PWM;
|
||||
data->REG_TEMP_OFFSET = NCT6779_REG_TEMP_OFFSET;
|
||||
data->REG_TEMP_SOURCE = NCT6798_REG_TEMP_SOURCE;
|
||||
data->REG_TEMP_SEL = NCT6775_REG_TEMP_SEL;
|
||||
data->REG_WEIGHT_TEMP_SEL = NCT6791_REG_WEIGHT_TEMP_SEL;
|
||||
data->REG_WEIGHT_TEMP[0] = NCT6791_REG_WEIGHT_TEMP_STEP;
|
||||
data->REG_WEIGHT_TEMP[1] = NCT6791_REG_WEIGHT_TEMP_STEP_TOL;
|
||||
data->REG_WEIGHT_TEMP[2] = NCT6791_REG_WEIGHT_TEMP_BASE;
|
||||
data->REG_ALARM = NCT6799_REG_ALARM;
|
||||
data->REG_BEEP = NCT6792_REG_BEEP;
|
||||
data->REG_TSI_TEMP = NCT6796_REG_TSI_TEMP;
|
||||
num_reg_tsi_temp = ARRAY_SIZE(NCT6796_REG_TSI_TEMP);
|
||||
|
||||
reg_temp = NCT6798_REG_TEMP;
|
||||
num_reg_temp = ARRAY_SIZE(NCT6798_REG_TEMP);
|
||||
reg_temp_mon = NCT6798_REG_TEMP_MON;
|
||||
num_reg_temp_mon = ARRAY_SIZE(NCT6798_REG_TEMP_MON);
|
||||
reg_temp_over = NCT6798_REG_TEMP_OVER;
|
||||
reg_temp_hyst = NCT6798_REG_TEMP_HYST;
|
||||
reg_temp_config = NCT6779_REG_TEMP_CONFIG;
|
||||
reg_temp_alternate = NCT6798_REG_TEMP_ALTERNATE;
|
||||
reg_temp_crit = NCT6798_REG_TEMP_CRIT;
|
||||
|
||||
break;
|
||||
default:
|
||||
return -ENODEV;
|
||||
|
@ -35,7 +35,7 @@ static const char * const nct6775_sio_names[] __initconst = {
|
||||
"NCT6796D",
|
||||
"NCT6797D",
|
||||
"NCT6798D",
|
||||
"NCT6799D",
|
||||
"NCT6796D-S/NCT6799D-R",
|
||||
};
|
||||
|
||||
static unsigned short force_id;
|
||||
|
@ -8,7 +8,7 @@ enum kinds { nct6106, nct6116, nct6775, nct6776, nct6779, nct6791, nct6792,
|
||||
nct6793, nct6795, nct6796, nct6797, nct6798, nct6799 };
|
||||
enum pwm_enable { off, manual, thermal_cruise, speed_cruise, sf3, sf4 };
|
||||
|
||||
#define NUM_TEMP 10 /* Max number of temp attribute sets w/ limits*/
|
||||
#define NUM_TEMP 12 /* Max number of temp attribute sets w/ limits*/
|
||||
#define NUM_TEMP_FIXED 6 /* Max number of fixed temp attribute sets */
|
||||
#define NUM_TSI_TEMP 8 /* Max number of TSI temp register pairs */
|
||||
|
||||
@ -16,6 +16,7 @@ enum pwm_enable { off, manual, thermal_cruise, speed_cruise, sf3, sf4 };
|
||||
#define NUM_REG_BEEP 5 /* Max number of beep registers */
|
||||
|
||||
#define NUM_FAN 7
|
||||
#define NUM_IN 18
|
||||
|
||||
struct nct6775_data {
|
||||
int addr; /* IO base of hw monitor block */
|
||||
@ -97,7 +98,7 @@ struct nct6775_data {
|
||||
/* Register values */
|
||||
u8 bank; /* current register bank */
|
||||
u8 in_num; /* number of in inputs we have */
|
||||
u8 in[15][3]; /* [0]=in, [1]=in_max, [2]=in_min */
|
||||
u8 in[NUM_IN][3]; /* [0]=in, [1]=in_max, [2]=in_min */
|
||||
const u16 *scale_in; /* internal scaling factors */
|
||||
unsigned int rpm[NUM_FAN];
|
||||
u16 fan_min[NUM_FAN];
|
||||
@ -166,7 +167,7 @@ struct nct6775_data {
|
||||
u16 have_temp;
|
||||
u16 have_temp_fixed;
|
||||
u16 have_tsi_temp;
|
||||
u16 have_in;
|
||||
u32 have_in;
|
||||
|
||||
/* Remember extra register values over suspend/resume */
|
||||
u8 vbat;
|
||||
@ -239,10 +240,25 @@ nct6775_add_attr_group(struct nct6775_data *data, const struct attribute_group *
|
||||
|
||||
#define NCT6791_REG_HM_IO_SPACE_LOCK_ENABLE 0x28
|
||||
|
||||
#define FAN_ALARM_BASE 16
|
||||
#define TEMP_ALARM_BASE 24
|
||||
#define INTRUSION_ALARM_BASE 30
|
||||
#define BEEP_ENABLE_BASE 15
|
||||
/*
|
||||
* ALARM_BITS and BEEP_BITS store bit-index for the mask of the registers
|
||||
* loaded into data->alarm and data->beep.
|
||||
*
|
||||
* Every input register (IN/TEMP/FAN) must have a corresponding
|
||||
* ALARM/BEEP bit at the same index BITS[BASE + index]
|
||||
* Set value to -1 to disable the visibility of that '*_alarm' attribute and
|
||||
* to pad the bits until the next BASE
|
||||
*
|
||||
* Beep has an additional GLOBAL_BEEP_ENABLE bit
|
||||
*/
|
||||
#define VIN_ALARM_BASE 0
|
||||
#define FAN_ALARM_BASE 24
|
||||
#define TEMP_ALARM_BASE 36
|
||||
#define INTRUSION_ALARM_BASE 48
|
||||
#define BEEP_ENABLE_BASE 50
|
||||
|
||||
#define NUM_ALARM_BITS (INTRUSION_ALARM_BASE + 4)
|
||||
#define NUM_BEEP_BITS (BEEP_ENABLE_BASE + 1)
|
||||
|
||||
/*
|
||||
* Not currently used:
|
||||
|
@ -20,8 +20,6 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
/* Tests for error return values rely upon this value being < 0x80 */
|
||||
@ -193,7 +191,7 @@ static struct platform_driver nsa320_hwmon_driver = {
|
||||
.probe = nsa320_hwmon_probe,
|
||||
.driver = {
|
||||
.name = "nsa320-hwmon",
|
||||
.of_match_table = of_match_ptr(of_nsa320_hwmon_match),
|
||||
.of_match_table = of_nsa320_hwmon_match,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -434,23 +434,9 @@ static const struct hwmon_chip_info oxp_ec_chip_info = {
|
||||
/* Initialization logic */
|
||||
static int oxp_platform_probe(struct platform_device *pdev)
|
||||
{
|
||||
const struct dmi_system_id *dmi_entry;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct device *hwdev;
|
||||
|
||||
/*
|
||||
* Have to check for AMD processor here because DMI strings are the
|
||||
* same between Intel and AMD boards, the only way to tell them apart
|
||||
* is the CPU.
|
||||
* Intel boards seem to have different EC registers and values to
|
||||
* read/write.
|
||||
*/
|
||||
dmi_entry = dmi_first_match(dmi_table);
|
||||
if (!dmi_entry || boot_cpu_data.x86_vendor != X86_VENDOR_AMD)
|
||||
return -ENODEV;
|
||||
|
||||
board = (enum oxp_board)(unsigned long)dmi_entry->driver_data;
|
||||
|
||||
hwdev = devm_hwmon_device_register_with_info(dev, "oxpec", NULL,
|
||||
&oxp_ec_chip_info, NULL);
|
||||
|
||||
@ -469,6 +455,21 @@ static struct platform_device *oxp_platform_device;
|
||||
|
||||
static int __init oxp_platform_init(void)
|
||||
{
|
||||
const struct dmi_system_id *dmi_entry;
|
||||
|
||||
/*
|
||||
* Have to check for AMD processor here because DMI strings are the
|
||||
* same between Intel and AMD boards, the only way to tell them apart
|
||||
* is the CPU.
|
||||
* Intel boards seem to have different EC registers and values to
|
||||
* read/write.
|
||||
*/
|
||||
dmi_entry = dmi_first_match(dmi_table);
|
||||
if (!dmi_entry || boot_cpu_data.x86_vendor != X86_VENDOR_AMD)
|
||||
return -ENODEV;
|
||||
|
||||
board = (enum oxp_board)(unsigned long)dmi_entry->driver_data;
|
||||
|
||||
oxp_platform_device =
|
||||
platform_create_bundle(&oxp_platform_driver,
|
||||
oxp_platform_probe, NULL, 0, NULL, 0);
|
||||
|
@ -219,19 +219,21 @@ static int check_populated_dimms(struct peci_dimmtemp *priv)
|
||||
{
|
||||
int chan_rank_max = priv->gen_info->chan_rank_max;
|
||||
int dimm_idx_max = priv->gen_info->dimm_idx_max;
|
||||
u32 chan_rank_empty = 0;
|
||||
u32 dimm_mask = 0;
|
||||
int chan_rank, dimm_idx, ret;
|
||||
DECLARE_BITMAP(dimm_mask, DIMM_NUMS_MAX);
|
||||
DECLARE_BITMAP(chan_rank_empty, CHAN_RANK_MAX);
|
||||
|
||||
int chan_rank, dimm_idx, ret, i;
|
||||
u32 pcs;
|
||||
|
||||
BUILD_BUG_ON(BITS_PER_TYPE(chan_rank_empty) < CHAN_RANK_MAX);
|
||||
BUILD_BUG_ON(BITS_PER_TYPE(dimm_mask) < DIMM_NUMS_MAX);
|
||||
if (chan_rank_max * dimm_idx_max > DIMM_NUMS_MAX) {
|
||||
WARN_ONCE(1, "Unsupported number of DIMMs - chan_rank_max: %d, dimm_idx_max: %d",
|
||||
chan_rank_max, dimm_idx_max);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
bitmap_zero(dimm_mask, DIMM_NUMS_MAX);
|
||||
bitmap_zero(chan_rank_empty, CHAN_RANK_MAX);
|
||||
|
||||
for (chan_rank = 0; chan_rank < chan_rank_max; chan_rank++) {
|
||||
ret = peci_pcs_read(priv->peci_dev, PECI_PCS_DDR_DIMM_TEMP, chan_rank, &pcs);
|
||||
if (ret) {
|
||||
@ -242,7 +244,7 @@ static int check_populated_dimms(struct peci_dimmtemp *priv)
|
||||
* detection to be performed at a later point in time.
|
||||
*/
|
||||
if (ret == -EINVAL) {
|
||||
chan_rank_empty |= BIT(chan_rank);
|
||||
bitmap_set(chan_rank_empty, chan_rank, 1);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -251,7 +253,7 @@ static int check_populated_dimms(struct peci_dimmtemp *priv)
|
||||
|
||||
for (dimm_idx = 0; dimm_idx < dimm_idx_max; dimm_idx++)
|
||||
if (__dimm_temp(pcs, dimm_idx))
|
||||
dimm_mask |= BIT(chan_rank * dimm_idx_max + dimm_idx);
|
||||
bitmap_set(dimm_mask, chan_rank * dimm_idx_max + dimm_idx, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -260,7 +262,7 @@ static int check_populated_dimms(struct peci_dimmtemp *priv)
|
||||
* host platform boot. Retrying a couple of times lets us make sure
|
||||
* that the state is persistent.
|
||||
*/
|
||||
if (chan_rank_empty == GENMASK(chan_rank_max - 1, 0)) {
|
||||
if (bitmap_full(chan_rank_empty, chan_rank_max)) {
|
||||
if (priv->no_dimm_retry_count < NO_DIMM_RETRY_COUNT_MAX) {
|
||||
priv->no_dimm_retry_count++;
|
||||
|
||||
@ -274,14 +276,16 @@ static int check_populated_dimms(struct peci_dimmtemp *priv)
|
||||
* It's possible that memory training is not done yet. In this case we
|
||||
* defer the detection to be performed at a later point in time.
|
||||
*/
|
||||
if (!dimm_mask) {
|
||||
if (bitmap_empty(dimm_mask, DIMM_NUMS_MAX)) {
|
||||
priv->no_dimm_retry_count = 0;
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
dev_dbg(priv->dev, "Scanned populated DIMMs: %#x\n", dimm_mask);
|
||||
for_each_set_bit(i, dimm_mask, DIMM_NUMS_MAX) {
|
||||
dev_dbg(priv->dev, "Found DIMM%#x\n", i);
|
||||
}
|
||||
|
||||
bitmap_from_arr32(priv->dimm_mask, &dimm_mask, DIMM_NUMS_MAX);
|
||||
bitmap_copy(priv->dimm_mask, dimm_mask, DIMM_NUMS_MAX);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -317,6 +317,13 @@ config SENSORS_MP2975
|
||||
This driver can also be built as a module. If so, the module will
|
||||
be called mp2975.
|
||||
|
||||
config SENSORS_MP2975_REGULATOR
|
||||
depends on SENSORS_MP2975 && REGULATOR
|
||||
bool "Regulator support for MPS MP2975"
|
||||
help
|
||||
If you say yes here you get regulator support for MPS MP2975
|
||||
Dual Loop Digital Multi-Phase Controller.
|
||||
|
||||
config SENSORS_MP5023
|
||||
tristate "MPS MP5023"
|
||||
help
|
||||
|
@ -3,14 +3,51 @@
|
||||
* Copyright 2023 IBM Corp.
|
||||
*/
|
||||
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/minmax.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/pmbus.h>
|
||||
#include <linux/hwmon-sysfs.h>
|
||||
#include "pmbus.h"
|
||||
|
||||
#define ACBEL_MFR_FW_REVISION 0xd9
|
||||
|
||||
static ssize_t acbel_fsg032_debugfs_read(struct file *file, char __user *buf, size_t count,
|
||||
loff_t *ppos)
|
||||
{
|
||||
struct i2c_client *client = file->private_data;
|
||||
u8 data[I2C_SMBUS_BLOCK_MAX + 2] = { 0 };
|
||||
char out[8];
|
||||
int rc;
|
||||
|
||||
rc = i2c_smbus_read_block_data(client, ACBEL_MFR_FW_REVISION, data);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
rc = snprintf(out, sizeof(out), "%*phN\n", min(rc, 3), data);
|
||||
return simple_read_from_buffer(buf, count, ppos, out, rc);
|
||||
}
|
||||
|
||||
static const struct file_operations acbel_debugfs_ops = {
|
||||
.llseek = noop_llseek,
|
||||
.read = acbel_fsg032_debugfs_read,
|
||||
.write = NULL,
|
||||
.open = simple_open,
|
||||
};
|
||||
|
||||
static void acbel_fsg032_init_debugfs(struct i2c_client *client)
|
||||
{
|
||||
struct dentry *debugfs = pmbus_get_debugfs_dir(client);
|
||||
|
||||
if (!debugfs)
|
||||
return;
|
||||
|
||||
debugfs_create_file("fw_version", 0444, debugfs, client, &acbel_debugfs_ops);
|
||||
}
|
||||
|
||||
static const struct i2c_device_id acbel_fsg032_id[] = {
|
||||
{ "acbel_fsg032" },
|
||||
{}
|
||||
@ -59,6 +96,7 @@ static int acbel_fsg032_probe(struct i2c_client *client)
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
acbel_fsg032_init_debugfs(client);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -9,7 +9,7 @@
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of.h>
|
||||
#include "pmbus.h"
|
||||
|
||||
struct dps920ab_data {
|
||||
|
@ -13,7 +13,7 @@
|
||||
#include <linux/leds.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/pmbus.h>
|
||||
|
||||
#include "pmbus.h"
|
||||
@ -489,7 +489,7 @@ static int ibm_cffps_probe(struct i2c_client *client)
|
||||
const struct i2c_device_id *id;
|
||||
|
||||
if (md) {
|
||||
vs = (enum versions)md;
|
||||
vs = (uintptr_t)md;
|
||||
} else {
|
||||
id = i2c_match_id(ibm_cffps_id, client);
|
||||
if (id)
|
||||
|
@ -6,7 +6,7 @@
|
||||
*
|
||||
* VOUT_MODE is not supported by the device. The driver fakes VOUT linear16
|
||||
* mode with exponent value -8 as direct mode with m=256/b=0/R=0.
|
||||
*
|
||||
*
|
||||
* The device supports VOUT_PEAK, IOUT_PEAK, and TEMPERATURE_PEAK, however
|
||||
* this driver does not currently support them.
|
||||
*/
|
||||
@ -16,7 +16,7 @@
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/regulator/driver.h>
|
||||
#include "pmbus.h"
|
||||
|
||||
|
@ -15,7 +15,7 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/pmbus.h>
|
||||
#include <linux/util_macros.h>
|
||||
#include "pmbus.h"
|
||||
@ -114,6 +114,7 @@ static ssize_t max20730_debugfs_read(struct file *file, char __user *buf,
|
||||
const struct pmbus_driver_info *info;
|
||||
const struct max20730_data *data;
|
||||
char tbuf[DEBUG_FS_DATA_MAX] = { 0 };
|
||||
char *result = tbuf;
|
||||
u16 val;
|
||||
|
||||
info = pmbus_get_driver_info(psu->client);
|
||||
@ -148,13 +149,13 @@ static ssize_t max20730_debugfs_read(struct file *file, char __user *buf,
|
||||
>> MAX20730_MFR_DEVSET1_TSTAT_BIT_POS;
|
||||
|
||||
if (val == 0)
|
||||
len = strlcpy(tbuf, "2000\n", DEBUG_FS_DATA_MAX);
|
||||
result = "2000\n";
|
||||
else if (val == 1)
|
||||
len = strlcpy(tbuf, "125\n", DEBUG_FS_DATA_MAX);
|
||||
result = "125\n";
|
||||
else if (val == 2)
|
||||
len = strlcpy(tbuf, "62.5\n", DEBUG_FS_DATA_MAX);
|
||||
result = "62.5\n";
|
||||
else
|
||||
len = strlcpy(tbuf, "32\n", DEBUG_FS_DATA_MAX);
|
||||
result = "32\n";
|
||||
break;
|
||||
case MAX20730_DEBUGFS_INTERNAL_GAIN:
|
||||
val = (data->mfr_devset1 & MAX20730_MFR_DEVSET1_RGAIN_MASK)
|
||||
@ -163,35 +164,35 @@ static ssize_t max20730_debugfs_read(struct file *file, char __user *buf,
|
||||
if (data->id == max20734) {
|
||||
/* AN6209 */
|
||||
if (val == 0)
|
||||
len = strlcpy(tbuf, "0.8\n", DEBUG_FS_DATA_MAX);
|
||||
result = "0.8\n";
|
||||
else if (val == 1)
|
||||
len = strlcpy(tbuf, "3.2\n", DEBUG_FS_DATA_MAX);
|
||||
result = "3.2\n";
|
||||
else if (val == 2)
|
||||
len = strlcpy(tbuf, "1.6\n", DEBUG_FS_DATA_MAX);
|
||||
result = "1.6\n";
|
||||
else
|
||||
len = strlcpy(tbuf, "6.4\n", DEBUG_FS_DATA_MAX);
|
||||
result = "6.4\n";
|
||||
} else if (data->id == max20730 || data->id == max20710) {
|
||||
/* AN6042 or AN6140 */
|
||||
if (val == 0)
|
||||
len = strlcpy(tbuf, "0.9\n", DEBUG_FS_DATA_MAX);
|
||||
result = "0.9\n";
|
||||
else if (val == 1)
|
||||
len = strlcpy(tbuf, "3.6\n", DEBUG_FS_DATA_MAX);
|
||||
result = "3.6\n";
|
||||
else if (val == 2)
|
||||
len = strlcpy(tbuf, "1.8\n", DEBUG_FS_DATA_MAX);
|
||||
result = "1.8\n";
|
||||
else
|
||||
len = strlcpy(tbuf, "7.2\n", DEBUG_FS_DATA_MAX);
|
||||
result = "7.2\n";
|
||||
} else if (data->id == max20743) {
|
||||
/* AN6042 */
|
||||
if (val == 0)
|
||||
len = strlcpy(tbuf, "0.45\n", DEBUG_FS_DATA_MAX);
|
||||
result = "0.45\n";
|
||||
else if (val == 1)
|
||||
len = strlcpy(tbuf, "1.8\n", DEBUG_FS_DATA_MAX);
|
||||
result = "1.8\n";
|
||||
else if (val == 2)
|
||||
len = strlcpy(tbuf, "0.9\n", DEBUG_FS_DATA_MAX);
|
||||
result = "0.9\n";
|
||||
else
|
||||
len = strlcpy(tbuf, "3.6\n", DEBUG_FS_DATA_MAX);
|
||||
result = "3.6\n";
|
||||
} else {
|
||||
len = strlcpy(tbuf, "Not supported\n", DEBUG_FS_DATA_MAX);
|
||||
result = "Not supported\n";
|
||||
}
|
||||
break;
|
||||
case MAX20730_DEBUGFS_BOOT_VOLTAGE:
|
||||
@ -199,26 +200,26 @@ static ssize_t max20730_debugfs_read(struct file *file, char __user *buf,
|
||||
>> MAX20730_MFR_DEVSET1_VBOOT_BIT_POS;
|
||||
|
||||
if (val == 0)
|
||||
len = strlcpy(tbuf, "0.6484\n", DEBUG_FS_DATA_MAX);
|
||||
result = "0.6484\n";
|
||||
else if (val == 1)
|
||||
len = strlcpy(tbuf, "0.8984\n", DEBUG_FS_DATA_MAX);
|
||||
result = "0.8984\n";
|
||||
else if (val == 2)
|
||||
len = strlcpy(tbuf, "1.0\n", DEBUG_FS_DATA_MAX);
|
||||
result = "1.0\n";
|
||||
else
|
||||
len = strlcpy(tbuf, "Invalid\n", DEBUG_FS_DATA_MAX);
|
||||
result = "Invalid\n";
|
||||
break;
|
||||
case MAX20730_DEBUGFS_OUT_V_RAMP_RATE:
|
||||
val = (data->mfr_devset2 & MAX20730_MFR_DEVSET2_VRATE)
|
||||
>> MAX20730_MFR_DEVSET2_VRATE_BIT_POS;
|
||||
|
||||
if (val == 0)
|
||||
len = strlcpy(tbuf, "4\n", DEBUG_FS_DATA_MAX);
|
||||
result = "4\n";
|
||||
else if (val == 1)
|
||||
len = strlcpy(tbuf, "2\n", DEBUG_FS_DATA_MAX);
|
||||
result = "2\n";
|
||||
else if (val == 2)
|
||||
len = strlcpy(tbuf, "1\n", DEBUG_FS_DATA_MAX);
|
||||
result = "1\n";
|
||||
else
|
||||
len = strlcpy(tbuf, "Invalid\n", DEBUG_FS_DATA_MAX);
|
||||
result = "Invalid\n";
|
||||
break;
|
||||
case MAX20730_DEBUGFS_OC_PROTECT_MODE:
|
||||
ret = (data->mfr_devset2 & MAX20730_MFR_DEVSET2_OCPM_MASK)
|
||||
@ -230,13 +231,13 @@ static ssize_t max20730_debugfs_read(struct file *file, char __user *buf,
|
||||
>> MAX20730_MFR_DEVSET2_SS_BIT_POS;
|
||||
|
||||
if (val == 0)
|
||||
len = strlcpy(tbuf, "0.75\n", DEBUG_FS_DATA_MAX);
|
||||
result = "0.75\n";
|
||||
else if (val == 1)
|
||||
len = strlcpy(tbuf, "1.5\n", DEBUG_FS_DATA_MAX);
|
||||
result = "1.5\n";
|
||||
else if (val == 2)
|
||||
len = strlcpy(tbuf, "3\n", DEBUG_FS_DATA_MAX);
|
||||
result = "3\n";
|
||||
else
|
||||
len = strlcpy(tbuf, "6\n", DEBUG_FS_DATA_MAX);
|
||||
result = "6\n";
|
||||
break;
|
||||
case MAX20730_DEBUGFS_IMAX:
|
||||
ret = (data->mfr_devset2 & MAX20730_MFR_DEVSET2_IMAX_MASK)
|
||||
@ -287,10 +288,11 @@ static ssize_t max20730_debugfs_read(struct file *file, char __user *buf,
|
||||
"%d.%d\n", ret / 10000, ret % 10000);
|
||||
break;
|
||||
default:
|
||||
len = strlcpy(tbuf, "Invalid\n", DEBUG_FS_DATA_MAX);
|
||||
result = "Invalid\n";
|
||||
}
|
||||
|
||||
return simple_read_from_buffer(buf, count, ppos, tbuf, len);
|
||||
len = strlen(result);
|
||||
return simple_read_from_buffer(buf, count, ppos, result, len);
|
||||
}
|
||||
|
||||
static const struct file_operations max20730_fops = {
|
||||
@ -714,7 +716,7 @@ static int max20730_probe(struct i2c_client *client)
|
||||
}
|
||||
|
||||
if (client->dev.of_node)
|
||||
chip_id = (enum chips)of_device_get_match_data(dev);
|
||||
chip_id = (uintptr_t)of_device_get_match_data(dev);
|
||||
else
|
||||
chip_id = i2c_match_id(max20730_id, client)->driver_data;
|
||||
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include "pmbus.h"
|
||||
|
||||
/* Vendor specific registers. */
|
||||
@ -34,6 +35,8 @@
|
||||
#define MP2975_MFR_OVP_TH_SET 0xe5
|
||||
#define MP2975_MFR_UVP_SET 0xe6
|
||||
|
||||
#define MP2973_MFR_RESO_SET 0xc7
|
||||
|
||||
#define MP2975_VOUT_FORMAT BIT(15)
|
||||
#define MP2975_VID_STEP_SEL_R1 BIT(4)
|
||||
#define MP2975_IMVP9_EN_R1 BIT(13)
|
||||
@ -48,43 +51,80 @@
|
||||
#define MP2975_SENSE_AMPL_HALF 2
|
||||
#define MP2975_VIN_UV_LIMIT_UNIT 8
|
||||
|
||||
#define MP2973_VOUT_FORMAT_R1 GENMASK(7, 6)
|
||||
#define MP2973_VOUT_FORMAT_R2 GENMASK(4, 3)
|
||||
#define MP2973_VOUT_FORMAT_DIRECT_R1 BIT(7)
|
||||
#define MP2973_VOUT_FORMAT_LINEAR_R1 BIT(6)
|
||||
#define MP2973_VOUT_FORMAT_DIRECT_R2 BIT(4)
|
||||
#define MP2973_VOUT_FORMAT_LINEAR_R2 BIT(3)
|
||||
|
||||
#define MP2973_MFR_VR_MULTI_CONFIG_R1 0x0d
|
||||
#define MP2973_MFR_VR_MULTI_CONFIG_R2 0x1d
|
||||
#define MP2973_VID_STEP_SEL_R1 BIT(4)
|
||||
#define MP2973_IMVP9_EN_R1 BIT(14)
|
||||
#define MP2973_VID_STEP_SEL_R2 BIT(3)
|
||||
#define MP2973_IMVP9_EN_R2 BIT(13)
|
||||
|
||||
#define MP2973_MFR_OCP_TOTAL_SET 0x5f
|
||||
#define MP2973_OCP_TOTAL_CUR_MASK GENMASK(6, 0)
|
||||
#define MP2973_MFR_OCP_LEVEL_RES BIT(15)
|
||||
|
||||
#define MP2973_MFR_READ_IOUT_PK 0x90
|
||||
#define MP2973_MFR_READ_POUT_PK 0x91
|
||||
|
||||
#define MP2975_MAX_PHASE_RAIL1 8
|
||||
#define MP2975_MAX_PHASE_RAIL2 4
|
||||
|
||||
#define MP2973_MAX_PHASE_RAIL1 14
|
||||
#define MP2973_MAX_PHASE_RAIL2 6
|
||||
|
||||
#define MP2971_MAX_PHASE_RAIL1 8
|
||||
#define MP2971_MAX_PHASE_RAIL2 3
|
||||
|
||||
#define MP2975_PAGE_NUM 2
|
||||
|
||||
#define MP2975_RAIL2_FUNC (PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT | \
|
||||
PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT | \
|
||||
PMBUS_HAVE_POUT | PMBUS_PHASE_VIRTUAL)
|
||||
|
||||
enum chips {
|
||||
mp2971, mp2973, mp2975
|
||||
};
|
||||
|
||||
static const int mp2975_max_phases[][MP2975_PAGE_NUM] = {
|
||||
[mp2975] = { MP2975_MAX_PHASE_RAIL1, MP2975_MAX_PHASE_RAIL2 },
|
||||
[mp2973] = { MP2973_MAX_PHASE_RAIL1, MP2973_MAX_PHASE_RAIL2 },
|
||||
[mp2971] = { MP2971_MAX_PHASE_RAIL1, MP2971_MAX_PHASE_RAIL2 },
|
||||
};
|
||||
|
||||
struct mp2975_data {
|
||||
struct pmbus_driver_info info;
|
||||
enum chips chip_id;
|
||||
int vout_scale;
|
||||
int max_phases[MP2975_PAGE_NUM];
|
||||
int vid_step[MP2975_PAGE_NUM];
|
||||
int vref[MP2975_PAGE_NUM];
|
||||
int vref_off[MP2975_PAGE_NUM];
|
||||
int vout_max[MP2975_PAGE_NUM];
|
||||
int vout_ov_fixed[MP2975_PAGE_NUM];
|
||||
int vout_format[MP2975_PAGE_NUM];
|
||||
int curr_sense_gain[MP2975_PAGE_NUM];
|
||||
};
|
||||
|
||||
#define to_mp2975_data(x) container_of(x, struct mp2975_data, info)
|
||||
static const struct i2c_device_id mp2975_id[] = {
|
||||
{"mp2971", mp2971},
|
||||
{"mp2973", mp2973},
|
||||
{"mp2975", mp2975},
|
||||
{}
|
||||
};
|
||||
|
||||
static int mp2975_read_byte_data(struct i2c_client *client, int page, int reg)
|
||||
{
|
||||
switch (reg) {
|
||||
case PMBUS_VOUT_MODE:
|
||||
/*
|
||||
* Enforce VOUT direct format, since device allows to set the
|
||||
* different formats for the different rails. Conversion from
|
||||
* VID to direct provided by driver internally, in case it is
|
||||
* necessary.
|
||||
*/
|
||||
return PB_VOUT_MODE_DIRECT;
|
||||
default:
|
||||
return -ENODATA;
|
||||
}
|
||||
}
|
||||
MODULE_DEVICE_TABLE(i2c, mp2975_id);
|
||||
|
||||
static const struct regulator_desc __maybe_unused mp2975_reg_desc[] = {
|
||||
PMBUS_REGULATOR("vout", 0),
|
||||
PMBUS_REGULATOR("vout", 1),
|
||||
};
|
||||
|
||||
#define to_mp2975_data(x) container_of(x, struct mp2975_data, info)
|
||||
|
||||
static int
|
||||
mp2975_read_word_helper(struct i2c_client *client, int page, int phase, u8 reg,
|
||||
@ -117,6 +157,41 @@ mp2975_vid2direct(int vrf, int val)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define MAX_LIN_MANTISSA (1023 * 1000)
|
||||
#define MIN_LIN_MANTISSA (511 * 1000)
|
||||
|
||||
/* Converts a milli-unit DIRECT value to LINEAR11 format */
|
||||
static u16 mp2975_data2reg_linear11(s64 val)
|
||||
{
|
||||
s16 exponent = 0, mantissa;
|
||||
bool negative = false;
|
||||
|
||||
/* simple case */
|
||||
if (val == 0)
|
||||
return 0;
|
||||
|
||||
/* Reduce large mantissa until it fits into 10 bit */
|
||||
while (val >= MAX_LIN_MANTISSA && exponent < 15) {
|
||||
exponent++;
|
||||
val >>= 1;
|
||||
}
|
||||
/* Increase small mantissa to improve precision */
|
||||
while (val < MIN_LIN_MANTISSA && exponent > -15) {
|
||||
exponent--;
|
||||
val <<= 1;
|
||||
}
|
||||
|
||||
/* Convert mantissa from milli-units to units */
|
||||
mantissa = clamp_val(DIV_ROUND_CLOSEST_ULL(val, 1000), 0, 0x3ff);
|
||||
|
||||
/* restore sign */
|
||||
if (negative)
|
||||
mantissa = -mantissa;
|
||||
|
||||
/* Convert to 5 bit exponent, 11 bit mantissa */
|
||||
return (mantissa & 0x7ff) | ((exponent << 11) & 0xf800);
|
||||
}
|
||||
|
||||
static int
|
||||
mp2975_read_phase(struct i2c_client *client, struct mp2975_data *data,
|
||||
int page, int phase, u8 reg)
|
||||
@ -214,6 +289,89 @@ mp2975_read_phases(struct i2c_client *client, struct mp2975_data *data,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mp2973_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 mp2975_data *data = to_mp2975_data(info);
|
||||
int ret;
|
||||
|
||||
switch (reg) {
|
||||
case PMBUS_OT_FAULT_LIMIT:
|
||||
ret = mp2975_read_word_helper(client, page, phase, reg,
|
||||
GENMASK(7, 0));
|
||||
break;
|
||||
case PMBUS_VIN_OV_FAULT_LIMIT:
|
||||
ret = mp2975_read_word_helper(client, page, phase, reg,
|
||||
GENMASK(7, 0));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = DIV_ROUND_CLOSEST(ret, MP2975_VIN_UV_LIMIT_UNIT);
|
||||
break;
|
||||
case PMBUS_VOUT_OV_FAULT_LIMIT:
|
||||
/*
|
||||
* MP2971 and mp2973 only supports tracking (ovp1) mode.
|
||||
*/
|
||||
ret = mp2975_read_word_helper(client, page, phase,
|
||||
MP2975_MFR_OVP_TH_SET,
|
||||
GENMASK(2, 0));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = data->vout_max[page] + 50 * (ret + 1);
|
||||
break;
|
||||
case PMBUS_VOUT_UV_FAULT_LIMIT:
|
||||
ret = mp2975_read_word_helper(client, page, phase, reg,
|
||||
GENMASK(8, 0));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret = mp2975_vid2direct(info->vrm_version[page], ret);
|
||||
break;
|
||||
case PMBUS_VIRT_READ_POUT_MAX:
|
||||
ret = pmbus_read_word_data(client, page, phase,
|
||||
MP2973_MFR_READ_POUT_PK);
|
||||
break;
|
||||
case PMBUS_VIRT_READ_IOUT_MAX:
|
||||
ret = pmbus_read_word_data(client, page, phase,
|
||||
MP2973_MFR_READ_IOUT_PK);
|
||||
break;
|
||||
case PMBUS_IOUT_OC_FAULT_LIMIT:
|
||||
ret = mp2975_read_word_helper(client, page, phase,
|
||||
MP2973_MFR_OCP_TOTAL_SET,
|
||||
GENMASK(15, 0));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (ret & MP2973_MFR_OCP_LEVEL_RES)
|
||||
ret = 2 * (ret & MP2973_OCP_TOTAL_CUR_MASK);
|
||||
else
|
||||
ret = ret & MP2973_OCP_TOTAL_CUR_MASK;
|
||||
|
||||
ret = mp2975_data2reg_linear11(ret * info->phases[page] * 1000);
|
||||
break;
|
||||
case PMBUS_UT_WARN_LIMIT:
|
||||
case PMBUS_UT_FAULT_LIMIT:
|
||||
case PMBUS_VIN_UV_WARN_LIMIT:
|
||||
case PMBUS_VIN_UV_FAULT_LIMIT:
|
||||
case PMBUS_VOUT_UV_WARN_LIMIT:
|
||||
case PMBUS_VOUT_OV_WARN_LIMIT:
|
||||
case PMBUS_VIN_OV_WARN_LIMIT:
|
||||
case PMBUS_IIN_OC_FAULT_LIMIT:
|
||||
case PMBUS_IOUT_OC_LV_FAULT_LIMIT:
|
||||
case PMBUS_IOUT_OC_WARN_LIMIT:
|
||||
case PMBUS_IOUT_UC_FAULT_LIMIT:
|
||||
case PMBUS_POUT_OP_FAULT_LIMIT:
|
||||
case PMBUS_POUT_OP_WARN_LIMIT:
|
||||
case PMBUS_PIN_OP_WARN_LIMIT:
|
||||
return -ENXIO;
|
||||
default:
|
||||
return -ENODATA;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mp2975_read_word_data(struct i2c_client *client, int page,
|
||||
int phase, int reg)
|
||||
{
|
||||
@ -222,6 +380,11 @@ static int mp2975_read_word_data(struct i2c_client *client, int page,
|
||||
int ret;
|
||||
|
||||
switch (reg) {
|
||||
case PMBUS_STATUS_WORD:
|
||||
/* MP2973 & MP2971 return PGOOD instead of PB_STATUS_POWER_GOOD_N. */
|
||||
ret = pmbus_read_word_data(client, page, phase, reg);
|
||||
ret ^= PB_STATUS_POWER_GOOD_N;
|
||||
break;
|
||||
case PMBUS_OT_FAULT_LIMIT:
|
||||
ret = mp2975_read_word_helper(client, page, phase, reg,
|
||||
GENMASK(7, 0));
|
||||
@ -260,24 +423,6 @@ static int mp2975_read_word_data(struct i2c_client *client, int page,
|
||||
ret = DIV_ROUND_CLOSEST(data->vref[page] * 10 - 50 *
|
||||
(ret + 1) * data->vout_scale, 10);
|
||||
break;
|
||||
case PMBUS_READ_VOUT:
|
||||
ret = mp2975_read_word_helper(client, page, phase, reg,
|
||||
GENMASK(11, 0));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* READ_VOUT can be provided in VID or direct format. The
|
||||
* format type is specified by bit 15 of the register
|
||||
* MP2975_MFR_DC_LOOP_CTRL. The driver enforces VOUT direct
|
||||
* format, since device allows to set the different formats for
|
||||
* the different rails and also all VOUT limits registers are
|
||||
* provided in a direct format. In case format is VID - convert
|
||||
* to direct.
|
||||
*/
|
||||
if (data->vout_format[page] == vid)
|
||||
ret = mp2975_vid2direct(info->vrm_version[page], ret);
|
||||
break;
|
||||
case PMBUS_VIRT_READ_POUT_MAX:
|
||||
ret = mp2975_read_word_helper(client, page, phase,
|
||||
MP2975_MFR_READ_POUT_PK,
|
||||
@ -326,25 +471,25 @@ static int mp2975_read_word_data(struct i2c_client *client, int page,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mp2975_identify_multiphase_rail2(struct i2c_client *client)
|
||||
static int mp2975_identify_multiphase_rail2(struct i2c_client *client,
|
||||
struct mp2975_data *data)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Identify multiphase for rail 2 - could be from 0 to 4.
|
||||
* Identify multiphase for rail 2 - could be from 0 to data->max_phases[1].
|
||||
* In case phase number is zero – only page zero is supported
|
||||
*/
|
||||
ret = i2c_smbus_write_byte_data(client, PMBUS_PAGE, 2);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Identify multiphase for rail 2 - could be from 0 to 4. */
|
||||
ret = i2c_smbus_read_word_data(client, MP2975_MFR_VR_MULTI_CONFIG_R2);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret &= GENMASK(2, 0);
|
||||
return (ret >= 4) ? 4 : ret;
|
||||
return (ret >= data->max_phases[1]) ? data->max_phases[1] : ret;
|
||||
}
|
||||
|
||||
static void mp2975_set_phase_rail1(struct pmbus_driver_info *info)
|
||||
@ -375,7 +520,7 @@ mp2975_identify_multiphase(struct i2c_client *client, struct mp2975_data *data,
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Identify multiphase for rail 1 - could be from 1 to 8. */
|
||||
/* Identify multiphase for rail 1 - could be from 1 to data->max_phases[0]. */
|
||||
ret = i2c_smbus_read_word_data(client, MP2975_MFR_VR_MULTI_CONFIG_R1);
|
||||
if (ret <= 0)
|
||||
return ret;
|
||||
@ -383,21 +528,23 @@ mp2975_identify_multiphase(struct i2c_client *client, struct mp2975_data *data,
|
||||
info->phases[0] = ret & GENMASK(3, 0);
|
||||
|
||||
/*
|
||||
* The device provides a total of 8 PWM pins, and can be configured
|
||||
* The device provides a total of $n PWM pins, and can be configured
|
||||
* to different phase count applications for rail 1 and rail 2.
|
||||
* Rail 1 can be set to 8 phases, while rail 2 can only be set to 4
|
||||
* phases at most. When rail 1’s phase count is configured as 0, rail
|
||||
* Rail 1 can be set to $n phases, while rail 2 can be set to less than
|
||||
* that. When rail 1’s phase count is configured as 0, rail
|
||||
* 1 operates with 1-phase DCM. When rail 2 phase count is configured
|
||||
* as 0, rail 2 is disabled.
|
||||
*/
|
||||
if (info->phases[0] > MP2975_MAX_PHASE_RAIL1)
|
||||
if (info->phases[0] > data->max_phases[0])
|
||||
return -EINVAL;
|
||||
|
||||
mp2975_set_phase_rail1(info);
|
||||
num_phases2 = min(MP2975_MAX_PHASE_RAIL1 - info->phases[0],
|
||||
MP2975_MAX_PHASE_RAIL2);
|
||||
if (info->phases[1] && info->phases[1] <= num_phases2)
|
||||
mp2975_set_phase_rail2(info, num_phases2);
|
||||
if (data->chip_id == mp2975) {
|
||||
mp2975_set_phase_rail1(info);
|
||||
num_phases2 = min(data->max_phases[0] - info->phases[0],
|
||||
data->max_phases[1]);
|
||||
if (info->phases[1] && info->phases[1] <= num_phases2)
|
||||
mp2975_set_phase_rail2(info, num_phases2);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -451,6 +598,35 @@ mp2975_identify_rails_vid(struct i2c_client *client, struct mp2975_data *data,
|
||||
MP2975_MFR_VR_MULTI_CONFIG_R2, 1,
|
||||
MP2975_IMVP9_EN_R2,
|
||||
MP2975_VID_STEP_SEL_R2);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
mp2973_identify_rails_vid(struct i2c_client *client, struct mp2975_data *data,
|
||||
struct pmbus_driver_info *info)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = i2c_smbus_write_byte_data(client, PMBUS_PAGE, 2);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Identify VID mode for rail 1. */
|
||||
ret = mp2975_identify_vid(client, data, info,
|
||||
MP2973_MFR_VR_MULTI_CONFIG_R1, 0,
|
||||
MP2973_IMVP9_EN_R1, MP2973_VID_STEP_SEL_R1);
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Identify VID mode for rail 2, if connected. */
|
||||
if (info->phases[1])
|
||||
ret = mp2975_identify_vid(client, data, info,
|
||||
MP2973_MFR_VR_MULTI_CONFIG_R2, 1,
|
||||
MP2973_IMVP9_EN_R2,
|
||||
MP2973_VID_STEP_SEL_R2);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -565,20 +741,37 @@ mp2975_vout_max_get(struct i2c_client *client, struct mp2975_data *data,
|
||||
}
|
||||
|
||||
static int
|
||||
mp2975_identify_vout_format(struct i2c_client *client,
|
||||
struct mp2975_data *data, int page)
|
||||
mp2975_set_vout_format(struct i2c_client *client,
|
||||
struct mp2975_data *data, int page)
|
||||
{
|
||||
int ret;
|
||||
int ret, i;
|
||||
|
||||
ret = i2c_smbus_read_word_data(client, MP2975_MFR_DC_LOOP_CTRL);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
/* Enable DIRECT VOUT format 1mV/LSB */
|
||||
if (data->chip_id == mp2975) {
|
||||
ret = i2c_smbus_read_word_data(client, MP2975_MFR_DC_LOOP_CTRL);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (ret & MP2975_VOUT_FORMAT) {
|
||||
ret &= ~MP2975_VOUT_FORMAT;
|
||||
ret = i2c_smbus_write_word_data(client, MP2975_MFR_DC_LOOP_CTRL, ret);
|
||||
}
|
||||
} else {
|
||||
ret = i2c_smbus_read_word_data(client, MP2973_MFR_RESO_SET);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
i = ret;
|
||||
|
||||
if (ret & MP2975_VOUT_FORMAT)
|
||||
data->vout_format[page] = vid;
|
||||
else
|
||||
data->vout_format[page] = direct;
|
||||
return 0;
|
||||
if (page == 0) {
|
||||
i &= ~MP2973_VOUT_FORMAT_R1;
|
||||
i |= MP2973_VOUT_FORMAT_DIRECT_R1;
|
||||
} else {
|
||||
i &= ~MP2973_VOUT_FORMAT_R2;
|
||||
i |= MP2973_VOUT_FORMAT_DIRECT_R2;
|
||||
}
|
||||
if (i != ret)
|
||||
ret = i2c_smbus_write_word_data(client, MP2973_MFR_RESO_SET, i);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
@ -600,7 +793,7 @@ mp2975_vout_ov_scale_get(struct i2c_client *client, struct mp2975_data *data,
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
thres_dev = ret & MP2975_PRT_THRES_DIV_OV_EN ? MP2975_PROT_DEV_OV_ON :
|
||||
MP2975_PROT_DEV_OV_OFF;
|
||||
MP2975_PROT_DEV_OV_OFF;
|
||||
|
||||
/* Select the gain of remote sense amplifier. */
|
||||
ret = i2c_smbus_read_word_data(client, PMBUS_VOUT_SCALE_LOOP);
|
||||
@ -624,10 +817,10 @@ mp2975_vout_per_rail_config_get(struct i2c_client *client,
|
||||
for (i = 0; i < data->info.pages; i++) {
|
||||
ret = i2c_smbus_write_byte_data(client, PMBUS_PAGE, i);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
continue;
|
||||
|
||||
/* Obtain voltage reference offsets. */
|
||||
ret = mp2975_vref_offset_get(client, data, i);
|
||||
/* Set VOUT format for READ_VOUT command : direct. */
|
||||
ret = mp2975_set_vout_format(client, data, i);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
@ -636,12 +829,12 @@ mp2975_vout_per_rail_config_get(struct i2c_client *client,
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* Get VOUT format for READ_VOUT command : VID or direct.
|
||||
* Pages on same device can be configured with different
|
||||
* formats.
|
||||
*/
|
||||
ret = mp2975_identify_vout_format(client, data, i);
|
||||
/* Skip if reading Vref is unsupported */
|
||||
if (data->chip_id != mp2975)
|
||||
continue;
|
||||
|
||||
/* Obtain voltage reference offsets. */
|
||||
ret = mp2975_vref_offset_get(client, data, i);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
@ -676,8 +869,32 @@ static struct pmbus_driver_info mp2975_info = {
|
||||
PMBUS_HAVE_IIN | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT |
|
||||
PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP | PMBUS_HAVE_POUT |
|
||||
PMBUS_HAVE_PIN | PMBUS_HAVE_STATUS_INPUT | PMBUS_PHASE_VIRTUAL,
|
||||
.read_byte_data = mp2975_read_byte_data,
|
||||
.read_word_data = mp2975_read_word_data,
|
||||
#if IS_ENABLED(CONFIG_SENSORS_MP2975_REGULATOR)
|
||||
.num_regulators = 1,
|
||||
.reg_desc = mp2975_reg_desc,
|
||||
#endif
|
||||
};
|
||||
|
||||
static struct pmbus_driver_info mp2973_info = {
|
||||
.pages = 1,
|
||||
.format[PSC_VOLTAGE_IN] = linear,
|
||||
.format[PSC_VOLTAGE_OUT] = direct,
|
||||
.format[PSC_TEMPERATURE] = linear,
|
||||
.format[PSC_CURRENT_IN] = linear,
|
||||
.format[PSC_CURRENT_OUT] = linear,
|
||||
.format[PSC_POWER] = linear,
|
||||
.m[PSC_VOLTAGE_OUT] = 1,
|
||||
.R[PSC_VOLTAGE_OUT] = 3,
|
||||
.func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT |
|
||||
PMBUS_HAVE_IIN | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT |
|
||||
PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP | PMBUS_HAVE_POUT |
|
||||
PMBUS_HAVE_PIN | PMBUS_HAVE_STATUS_INPUT,
|
||||
.read_word_data = mp2973_read_word_data,
|
||||
#if IS_ENABLED(CONFIG_SENSORS_MP2975_REGULATOR)
|
||||
.num_regulators = 1,
|
||||
.reg_desc = mp2975_reg_desc,
|
||||
#endif
|
||||
};
|
||||
|
||||
static int mp2975_probe(struct i2c_client *client)
|
||||
@ -691,11 +908,23 @@ static int mp2975_probe(struct i2c_client *client)
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
memcpy(&data->info, &mp2975_info, sizeof(*info));
|
||||
if (client->dev.of_node)
|
||||
data->chip_id = (enum chips)(unsigned long)of_device_get_match_data(&client->dev);
|
||||
else
|
||||
data->chip_id = i2c_match_id(mp2975_id, client)->driver_data;
|
||||
|
||||
memcpy(data->max_phases, mp2975_max_phases[data->chip_id],
|
||||
sizeof(data->max_phases));
|
||||
|
||||
if (data->chip_id == mp2975)
|
||||
memcpy(&data->info, &mp2975_info, sizeof(*info));
|
||||
else
|
||||
memcpy(&data->info, &mp2973_info, sizeof(*info));
|
||||
|
||||
info = &data->info;
|
||||
|
||||
/* Identify multiphase configuration for rail 2. */
|
||||
ret = mp2975_identify_multiphase_rail2(client);
|
||||
ret = mp2975_identify_multiphase_rail2(client, data);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
@ -704,6 +933,8 @@ static int mp2975_probe(struct i2c_client *client)
|
||||
data->info.pages = MP2975_PAGE_NUM;
|
||||
data->info.phases[1] = ret;
|
||||
data->info.func[1] = MP2975_RAIL2_FUNC;
|
||||
if (IS_ENABLED(CONFIG_SENSORS_MP2975_REGULATOR))
|
||||
data->info.num_regulators = MP2975_PAGE_NUM;
|
||||
}
|
||||
|
||||
/* Identify multiphase configuration. */
|
||||
@ -711,25 +942,32 @@ static int mp2975_probe(struct i2c_client *client)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Identify VID setting per rail. */
|
||||
ret = mp2975_identify_rails_vid(client, data, info);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (data->chip_id == mp2975) {
|
||||
/* Identify VID setting per rail. */
|
||||
ret = mp2975_identify_rails_vid(client, data, info);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Obtain current sense gain of power stage. */
|
||||
ret = mp2975_current_sense_gain_get(client, data);
|
||||
if (ret)
|
||||
return ret;
|
||||
/* Obtain current sense gain of power stage. */
|
||||
ret = mp2975_current_sense_gain_get(client, data);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Obtain voltage reference values. */
|
||||
ret = mp2975_vref_get(client, data, info);
|
||||
if (ret)
|
||||
return ret;
|
||||
/* Obtain voltage reference values. */
|
||||
ret = mp2975_vref_get(client, data, info);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Obtain vout over-voltage scales. */
|
||||
ret = mp2975_vout_ov_scale_get(client, data, info);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
/* Obtain vout over-voltage scales. */
|
||||
ret = mp2975_vout_ov_scale_get(client, data, info);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
} else {
|
||||
/* Identify VID setting per rail. */
|
||||
ret = mp2973_identify_rails_vid(client, data, info);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Obtain offsets, maximum and format for vout. */
|
||||
ret = mp2975_vout_per_rail_config_get(client, data, info);
|
||||
@ -739,15 +977,10 @@ static int mp2975_probe(struct i2c_client *client)
|
||||
return pmbus_do_probe(client, info);
|
||||
}
|
||||
|
||||
static const struct i2c_device_id mp2975_id[] = {
|
||||
{"mp2975", 0},
|
||||
{}
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(i2c, mp2975_id);
|
||||
|
||||
static const struct of_device_id __maybe_unused mp2975_of_match[] = {
|
||||
{.compatible = "mps,mp2975"},
|
||||
{.compatible = "mps,mp2971", .data = (void *)mp2971},
|
||||
{.compatible = "mps,mp2973", .data = (void *)mp2973},
|
||||
{.compatible = "mps,mp2975", .data = (void *)mp2975},
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, mp2975_of_match);
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of.h>
|
||||
#include "pmbus.h"
|
||||
|
||||
static struct pmbus_driver_info mp5023_info = {
|
||||
|
@ -12,7 +12,7 @@
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/pmbus.h>
|
||||
#include "pmbus.h"
|
||||
|
||||
|
@ -5,6 +5,7 @@
|
||||
* Copyright (c) 2022 9elements GmbH
|
||||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/pmbus.h>
|
||||
@ -53,6 +54,30 @@ static int pli1209bc_read_word_data(struct i2c_client *client, int page,
|
||||
}
|
||||
}
|
||||
|
||||
static int pli1209bc_write_byte(struct i2c_client *client, int page, u8 reg)
|
||||
{
|
||||
int ret;
|
||||
|
||||
switch (reg) {
|
||||
case PMBUS_CLEAR_FAULTS:
|
||||
ret = pmbus_write_byte(client, page, reg);
|
||||
/*
|
||||
* PLI1209 takes 230 usec to execute the CLEAR_FAULTS command.
|
||||
* During that time it's busy and NACKs all requests on the
|
||||
* SMBUS interface. It also NACKs reads on PMBUS_STATUS_BYTE
|
||||
* making it impossible to poll the BUSY flag.
|
||||
*
|
||||
* Just wait for not BUSY unconditionally.
|
||||
*/
|
||||
usleep_range(250, 300);
|
||||
break;
|
||||
default:
|
||||
ret = -ENODATA;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_SENSORS_PLI1209BC_REGULATOR)
|
||||
static const struct regulator_desc pli1209bc_reg_desc = {
|
||||
.name = "vout2",
|
||||
@ -102,6 +127,7 @@ static struct pmbus_driver_info pli1209bc_info = {
|
||||
| PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP
|
||||
| PMBUS_HAVE_STATUS_IOUT | PMBUS_HAVE_STATUS_INPUT,
|
||||
.read_word_data = pli1209bc_read_word_data,
|
||||
.write_byte = pli1209bc_write_byte,
|
||||
#if IS_ENABLED(CONFIG_SENSORS_PLI1209BC_REGULATOR)
|
||||
.num_regulators = 1,
|
||||
.reg_desc = &pli1209bc_reg_desc,
|
||||
|
@ -561,7 +561,8 @@ static bool pmbus_check_register(struct i2c_client *client,
|
||||
rv = pmbus_check_status_cml(client);
|
||||
if (rv < 0 && (data->flags & PMBUS_READ_STATUS_AFTER_FAILED_CHECK))
|
||||
data->read_status(client, -1);
|
||||
pmbus_clear_fault_page(client, -1);
|
||||
if (reg < PMBUS_VIRT_BASE)
|
||||
pmbus_clear_fault_page(client, -1);
|
||||
return rv >= 0;
|
||||
}
|
||||
|
||||
@ -2540,7 +2541,6 @@ static int pmbus_identify_common(struct i2c_client *client,
|
||||
}
|
||||
}
|
||||
|
||||
pmbus_clear_fault_page(client, page);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -10,7 +10,7 @@
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/kstrtox.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of.h>
|
||||
#include "pmbus.h"
|
||||
|
||||
#define STORE_DEFAULT_ALL 0x11
|
||||
|
@ -12,7 +12,7 @@
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of.h>
|
||||
#include "pmbus.h"
|
||||
|
||||
enum chips {
|
||||
@ -235,7 +235,7 @@ static int tps53679_probe(struct i2c_client *client)
|
||||
enum chips chip_id;
|
||||
|
||||
if (dev->of_node)
|
||||
chip_id = (enum chips)of_device_get_match_data(dev);
|
||||
chip_id = (uintptr_t)of_device_get_match_data(dev);
|
||||
else
|
||||
chip_id = i2c_match_id(tps53679_id, client)->driver_data;
|
||||
|
||||
|
@ -10,7 +10,7 @@
|
||||
#include <linux/delay.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/slab.h>
|
||||
@ -588,7 +588,7 @@ static int ucd9000_probe(struct i2c_client *client)
|
||||
}
|
||||
|
||||
if (client->dev.of_node)
|
||||
chip = (enum chips)of_device_get_match_data(&client->dev);
|
||||
chip = (uintptr_t)of_device_get_match_data(&client->dev);
|
||||
else
|
||||
chip = mid->driver_data;
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/slab.h>
|
||||
@ -103,7 +103,7 @@ static int ucd9200_probe(struct i2c_client *client)
|
||||
}
|
||||
|
||||
if (client->dev.of_node)
|
||||
chip = (enum chips)of_device_get_match_data(&client->dev);
|
||||
chip = (uintptr_t)of_device_get_match_data(&client->dev);
|
||||
else
|
||||
chip = mid->driver_data;
|
||||
|
||||
|
@ -13,7 +13,6 @@
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of.h>
|
||||
|
||||
/*
|
||||
|
@ -8,7 +8,7 @@
|
||||
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/scpi_protocol.h>
|
||||
#include <linux/slab.h>
|
||||
|
@ -147,8 +147,20 @@ static const u16 mode_to_update_interval[] = {
|
||||
100,
|
||||
};
|
||||
|
||||
static const struct hwmon_channel_info * const sht3x_channel_info[] = {
|
||||
HWMON_CHANNEL_INFO(chip, HWMON_C_UPDATE_INTERVAL),
|
||||
HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT | HWMON_T_MIN |
|
||||
HWMON_T_MIN_HYST | HWMON_T_MAX |
|
||||
HWMON_T_MAX_HYST | HWMON_T_ALARM),
|
||||
HWMON_CHANNEL_INFO(humidity, HWMON_H_INPUT | HWMON_H_MIN |
|
||||
HWMON_H_MIN_HYST | HWMON_H_MAX |
|
||||
HWMON_H_MAX_HYST | HWMON_H_ALARM),
|
||||
NULL,
|
||||
};
|
||||
|
||||
struct sht3x_data {
|
||||
struct i2c_client *client;
|
||||
enum sht3x_chips chip_id;
|
||||
struct mutex i2c_lock; /* lock for sending i2c commands */
|
||||
struct mutex data_lock; /* lock for updating driver data */
|
||||
|
||||
@ -276,27 +288,24 @@ out:
|
||||
return data;
|
||||
}
|
||||
|
||||
/* sysfs attributes */
|
||||
static ssize_t temp1_input_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
static int temp1_input_read(struct device *dev)
|
||||
{
|
||||
struct sht3x_data *data = sht3x_update_client(dev);
|
||||
|
||||
if (IS_ERR(data))
|
||||
return PTR_ERR(data);
|
||||
|
||||
return sprintf(buf, "%d\n", data->temperature);
|
||||
return data->temperature;
|
||||
}
|
||||
|
||||
static ssize_t humidity1_input_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
static int humidity1_input_read(struct device *dev)
|
||||
{
|
||||
struct sht3x_data *data = sht3x_update_client(dev);
|
||||
|
||||
if (IS_ERR(data))
|
||||
return PTR_ERR(data);
|
||||
|
||||
return sprintf(buf, "%u\n", data->humidity);
|
||||
return data->humidity;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -332,33 +341,24 @@ static int limits_update(struct sht3x_data *data)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t temp1_limit_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
static int temp1_limit_read(struct device *dev, int index)
|
||||
{
|
||||
struct sht3x_data *data = dev_get_drvdata(dev);
|
||||
u8 index = to_sensor_dev_attr(attr)->index;
|
||||
int temperature_limit = data->temperature_limits[index];
|
||||
|
||||
return sysfs_emit(buf, "%d\n", temperature_limit);
|
||||
return data->temperature_limits[index];
|
||||
}
|
||||
|
||||
static ssize_t humidity1_limit_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
static int humidity1_limit_read(struct device *dev, int index)
|
||||
{
|
||||
struct sht3x_data *data = dev_get_drvdata(dev);
|
||||
u8 index = to_sensor_dev_attr(attr)->index;
|
||||
u32 humidity_limit = data->humidity_limits[index];
|
||||
|
||||
return sysfs_emit(buf, "%u\n", humidity_limit);
|
||||
return data->humidity_limits[index];
|
||||
}
|
||||
|
||||
/*
|
||||
* limit_store must only be called with data_lock held
|
||||
* limit_write must only be called with data_lock held
|
||||
*/
|
||||
static size_t limit_store(struct device *dev,
|
||||
size_t count,
|
||||
static size_t limit_write(struct device *dev,
|
||||
u8 index,
|
||||
int temperature,
|
||||
u32 humidity)
|
||||
@ -379,7 +379,7 @@ static size_t limit_store(struct device *dev,
|
||||
* ST = (T + 45) / 175 * 2^16
|
||||
* SRH = RH / 100 * 2^16
|
||||
* adapted for fixed point arithmetic and packed the same as
|
||||
* in limit_show()
|
||||
* in limit_read()
|
||||
*/
|
||||
raw = ((u32)(temperature + 45000) * 24543) >> (16 + 7);
|
||||
raw |= ((humidity * 42950) >> 16) & 0xfe00;
|
||||
@ -400,50 +400,35 @@ static size_t limit_store(struct device *dev,
|
||||
|
||||
data->temperature_limits[index] = temperature;
|
||||
data->humidity_limits[index] = humidity;
|
||||
return count;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t temp1_limit_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf,
|
||||
size_t count)
|
||||
static int temp1_limit_write(struct device *dev, int index, int val)
|
||||
{
|
||||
int temperature;
|
||||
int ret;
|
||||
struct sht3x_data *data = dev_get_drvdata(dev);
|
||||
u8 index = to_sensor_dev_attr(attr)->index;
|
||||
|
||||
ret = kstrtoint(buf, 0, &temperature);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
temperature = clamp_val(temperature, SHT3X_MIN_TEMPERATURE,
|
||||
temperature = clamp_val(val, SHT3X_MIN_TEMPERATURE,
|
||||
SHT3X_MAX_TEMPERATURE);
|
||||
mutex_lock(&data->data_lock);
|
||||
ret = limit_store(dev, count, index, temperature,
|
||||
ret = limit_write(dev, index, temperature,
|
||||
data->humidity_limits[index]);
|
||||
mutex_unlock(&data->data_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t humidity1_limit_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf,
|
||||
size_t count)
|
||||
static int humidity1_limit_write(struct device *dev, int index, int val)
|
||||
{
|
||||
u32 humidity;
|
||||
int ret;
|
||||
struct sht3x_data *data = dev_get_drvdata(dev);
|
||||
u8 index = to_sensor_dev_attr(attr)->index;
|
||||
|
||||
ret = kstrtou32(buf, 0, &humidity);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
humidity = clamp_val(humidity, SHT3X_MIN_HUMIDITY, SHT3X_MAX_HUMIDITY);
|
||||
humidity = clamp_val(val, SHT3X_MIN_HUMIDITY, SHT3X_MAX_HUMIDITY);
|
||||
mutex_lock(&data->data_lock);
|
||||
ret = limit_store(dev, count, index, data->temperature_limits[index],
|
||||
ret = limit_write(dev, index, data->temperature_limits[index],
|
||||
humidity);
|
||||
mutex_unlock(&data->data_lock);
|
||||
|
||||
@ -474,7 +459,6 @@ static void sht3x_select_command(struct sht3x_data *data)
|
||||
}
|
||||
|
||||
static int status_register_read(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buffer, int length)
|
||||
{
|
||||
int ret;
|
||||
@ -487,34 +471,30 @@ static int status_register_read(struct device *dev,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t temp1_alarm_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
static int temp1_alarm_read(struct device *dev)
|
||||
{
|
||||
char buffer[SHT3X_WORD_LEN + SHT3X_CRC8_LEN];
|
||||
int ret;
|
||||
|
||||
ret = status_register_read(dev, attr, buffer,
|
||||
ret = status_register_read(dev, buffer,
|
||||
SHT3X_WORD_LEN + SHT3X_CRC8_LEN);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return sysfs_emit(buf, "%d\n", !!(buffer[0] & 0x04));
|
||||
return !!(buffer[0] & 0x04);
|
||||
}
|
||||
|
||||
static ssize_t humidity1_alarm_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
static int humidity1_alarm_read(struct device *dev)
|
||||
{
|
||||
char buffer[SHT3X_WORD_LEN + SHT3X_CRC8_LEN];
|
||||
int ret;
|
||||
|
||||
ret = status_register_read(dev, attr, buffer,
|
||||
ret = status_register_read(dev, buffer,
|
||||
SHT3X_WORD_LEN + SHT3X_CRC8_LEN);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return sysfs_emit(buf, "%d\n", !!(buffer[0] & 0x08));
|
||||
return !!(buffer[0] & 0x08);
|
||||
}
|
||||
|
||||
static ssize_t heater_enable_show(struct device *dev,
|
||||
@ -524,7 +504,7 @@ static ssize_t heater_enable_show(struct device *dev,
|
||||
char buffer[SHT3X_WORD_LEN + SHT3X_CRC8_LEN];
|
||||
int ret;
|
||||
|
||||
ret = status_register_read(dev, attr, buffer,
|
||||
ret = status_register_read(dev, buffer,
|
||||
SHT3X_WORD_LEN + SHT3X_CRC8_LEN);
|
||||
if (ret)
|
||||
return ret;
|
||||
@ -560,39 +540,28 @@ static ssize_t heater_enable_store(struct device *dev,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t update_interval_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
static int update_interval_read(struct device *dev)
|
||||
{
|
||||
struct sht3x_data *data = dev_get_drvdata(dev);
|
||||
|
||||
return sysfs_emit(buf, "%u\n",
|
||||
mode_to_update_interval[data->mode]);
|
||||
return mode_to_update_interval[data->mode];
|
||||
}
|
||||
|
||||
static ssize_t update_interval_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf,
|
||||
size_t count)
|
||||
static int update_interval_write(struct device *dev, int val)
|
||||
{
|
||||
u16 update_interval;
|
||||
u8 mode;
|
||||
int ret;
|
||||
const char *command;
|
||||
struct sht3x_data *data = dev_get_drvdata(dev);
|
||||
struct i2c_client *client = data->client;
|
||||
|
||||
ret = kstrtou16(buf, 0, &update_interval);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
mode = get_mode_from_update_interval(update_interval);
|
||||
mode = get_mode_from_update_interval(val);
|
||||
|
||||
mutex_lock(&data->data_lock);
|
||||
/* mode did not change */
|
||||
if (mode == data->mode) {
|
||||
mutex_unlock(&data->data_lock);
|
||||
return count;
|
||||
return 0;
|
||||
}
|
||||
|
||||
mutex_lock(&data->i2c_lock);
|
||||
@ -634,7 +603,7 @@ out:
|
||||
if (ret != SHT3X_CMD_LENGTH)
|
||||
return ret < 0 ? ret : -EIO;
|
||||
|
||||
return count;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t repeatability_show(struct device *dev,
|
||||
@ -668,60 +637,219 @@ static ssize_t repeatability_store(struct device *dev,
|
||||
return count;
|
||||
}
|
||||
|
||||
static SENSOR_DEVICE_ATTR_RO(temp1_input, temp1_input, 0);
|
||||
static SENSOR_DEVICE_ATTR_RO(humidity1_input, humidity1_input, 0);
|
||||
static SENSOR_DEVICE_ATTR_RW(temp1_max, temp1_limit, limit_max);
|
||||
static SENSOR_DEVICE_ATTR_RW(humidity1_max, humidity1_limit, limit_max);
|
||||
static SENSOR_DEVICE_ATTR_RW(temp1_max_hyst, temp1_limit, limit_max_hyst);
|
||||
static SENSOR_DEVICE_ATTR_RW(humidity1_max_hyst, humidity1_limit,
|
||||
limit_max_hyst);
|
||||
static SENSOR_DEVICE_ATTR_RW(temp1_min, temp1_limit, limit_min);
|
||||
static SENSOR_DEVICE_ATTR_RW(humidity1_min, humidity1_limit, limit_min);
|
||||
static SENSOR_DEVICE_ATTR_RW(temp1_min_hyst, temp1_limit, limit_min_hyst);
|
||||
static SENSOR_DEVICE_ATTR_RW(humidity1_min_hyst, humidity1_limit,
|
||||
limit_min_hyst);
|
||||
static SENSOR_DEVICE_ATTR_RO(temp1_alarm, temp1_alarm, 0);
|
||||
static SENSOR_DEVICE_ATTR_RO(humidity1_alarm, humidity1_alarm, 0);
|
||||
static SENSOR_DEVICE_ATTR_RW(heater_enable, heater_enable, 0);
|
||||
static SENSOR_DEVICE_ATTR_RW(update_interval, update_interval, 0);
|
||||
static SENSOR_DEVICE_ATTR_RW(repeatability, repeatability, 0);
|
||||
|
||||
static struct attribute *sht3x_attrs[] = {
|
||||
&sensor_dev_attr_temp1_input.dev_attr.attr,
|
||||
&sensor_dev_attr_humidity1_input.dev_attr.attr,
|
||||
&sensor_dev_attr_temp1_max.dev_attr.attr,
|
||||
&sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
|
||||
&sensor_dev_attr_humidity1_max.dev_attr.attr,
|
||||
&sensor_dev_attr_humidity1_max_hyst.dev_attr.attr,
|
||||
&sensor_dev_attr_temp1_min.dev_attr.attr,
|
||||
&sensor_dev_attr_temp1_min_hyst.dev_attr.attr,
|
||||
&sensor_dev_attr_humidity1_min.dev_attr.attr,
|
||||
&sensor_dev_attr_humidity1_min_hyst.dev_attr.attr,
|
||||
&sensor_dev_attr_temp1_alarm.dev_attr.attr,
|
||||
&sensor_dev_attr_humidity1_alarm.dev_attr.attr,
|
||||
&sensor_dev_attr_heater_enable.dev_attr.attr,
|
||||
&sensor_dev_attr_update_interval.dev_attr.attr,
|
||||
&sensor_dev_attr_repeatability.dev_attr.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
static struct attribute *sts3x_attrs[] = {
|
||||
&sensor_dev_attr_temp1_input.dev_attr.attr,
|
||||
&sensor_dev_attr_temp1_max.dev_attr.attr,
|
||||
&sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
|
||||
&sensor_dev_attr_temp1_min.dev_attr.attr,
|
||||
&sensor_dev_attr_temp1_min_hyst.dev_attr.attr,
|
||||
&sensor_dev_attr_temp1_alarm.dev_attr.attr,
|
||||
&sensor_dev_attr_heater_enable.dev_attr.attr,
|
||||
&sensor_dev_attr_update_interval.dev_attr.attr,
|
||||
&sensor_dev_attr_repeatability.dev_attr.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
ATTRIBUTE_GROUPS(sht3x);
|
||||
ATTRIBUTE_GROUPS(sts3x);
|
||||
|
||||
static const struct i2c_device_id sht3x_ids[];
|
||||
static umode_t sht3x_is_visible(const void *data, enum hwmon_sensor_types type,
|
||||
u32 attr, int channel)
|
||||
{
|
||||
const struct sht3x_data *chip_data = data;
|
||||
|
||||
switch (type) {
|
||||
case hwmon_chip:
|
||||
switch (attr) {
|
||||
case hwmon_chip_update_interval:
|
||||
return 0644;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case hwmon_temp:
|
||||
switch (attr) {
|
||||
case hwmon_temp_input:
|
||||
case hwmon_temp_alarm:
|
||||
return 0444;
|
||||
case hwmon_temp_max:
|
||||
case hwmon_temp_max_hyst:
|
||||
case hwmon_temp_min:
|
||||
case hwmon_temp_min_hyst:
|
||||
return 0644;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case hwmon_humidity:
|
||||
if (chip_data->chip_id == sts3x)
|
||||
break;
|
||||
switch (attr) {
|
||||
case hwmon_humidity_input:
|
||||
case hwmon_humidity_alarm:
|
||||
return 0444;
|
||||
case hwmon_humidity_max:
|
||||
case hwmon_humidity_max_hyst:
|
||||
case hwmon_humidity_min:
|
||||
case hwmon_humidity_min_hyst:
|
||||
return 0644;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sht3x_read(struct device *dev, enum hwmon_sensor_types type,
|
||||
u32 attr, int channel, long *val)
|
||||
{
|
||||
enum sht3x_limits index;
|
||||
|
||||
switch (type) {
|
||||
case hwmon_chip:
|
||||
switch (attr) {
|
||||
case hwmon_chip_update_interval:
|
||||
*val = update_interval_read(dev);
|
||||
break;
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
break;
|
||||
case hwmon_temp:
|
||||
switch (attr) {
|
||||
case hwmon_temp_input:
|
||||
*val = temp1_input_read(dev);
|
||||
break;
|
||||
case hwmon_temp_alarm:
|
||||
*val = temp1_alarm_read(dev);
|
||||
break;
|
||||
case hwmon_temp_max:
|
||||
index = limit_max;
|
||||
*val = temp1_limit_read(dev, index);
|
||||
break;
|
||||
case hwmon_temp_max_hyst:
|
||||
index = limit_max_hyst;
|
||||
*val = temp1_limit_read(dev, index);
|
||||
break;
|
||||
case hwmon_temp_min:
|
||||
index = limit_min;
|
||||
*val = temp1_limit_read(dev, index);
|
||||
break;
|
||||
case hwmon_temp_min_hyst:
|
||||
index = limit_min_hyst;
|
||||
*val = temp1_limit_read(dev, index);
|
||||
break;
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
break;
|
||||
case hwmon_humidity:
|
||||
switch (attr) {
|
||||
case hwmon_humidity_input:
|
||||
*val = humidity1_input_read(dev);
|
||||
break;
|
||||
case hwmon_humidity_alarm:
|
||||
*val = humidity1_alarm_read(dev);
|
||||
break;
|
||||
case hwmon_humidity_max:
|
||||
index = limit_max;
|
||||
*val = humidity1_limit_read(dev, index);
|
||||
break;
|
||||
case hwmon_humidity_max_hyst:
|
||||
index = limit_max_hyst;
|
||||
*val = humidity1_limit_read(dev, index);
|
||||
break;
|
||||
case hwmon_humidity_min:
|
||||
index = limit_min;
|
||||
*val = humidity1_limit_read(dev, index);
|
||||
break;
|
||||
case hwmon_humidity_min_hyst:
|
||||
index = limit_min_hyst;
|
||||
*val = humidity1_limit_read(dev, index);
|
||||
break;
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sht3x_write(struct device *dev, enum hwmon_sensor_types type,
|
||||
u32 attr, int channel, long val)
|
||||
{
|
||||
enum sht3x_limits index;
|
||||
|
||||
switch (type) {
|
||||
case hwmon_chip:
|
||||
switch (attr) {
|
||||
case hwmon_chip_update_interval:
|
||||
return update_interval_write(dev, val);
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
case hwmon_temp:
|
||||
switch (attr) {
|
||||
case hwmon_temp_max:
|
||||
index = limit_max;
|
||||
break;
|
||||
case hwmon_temp_max_hyst:
|
||||
index = limit_max_hyst;
|
||||
break;
|
||||
case hwmon_temp_min:
|
||||
index = limit_min;
|
||||
break;
|
||||
case hwmon_temp_min_hyst:
|
||||
index = limit_min_hyst;
|
||||
break;
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
return temp1_limit_write(dev, index, val);
|
||||
case hwmon_humidity:
|
||||
switch (attr) {
|
||||
case hwmon_humidity_max:
|
||||
index = limit_max;
|
||||
break;
|
||||
case hwmon_humidity_max_hyst:
|
||||
index = limit_max_hyst;
|
||||
break;
|
||||
case hwmon_humidity_min:
|
||||
index = limit_min;
|
||||
break;
|
||||
case hwmon_humidity_min_hyst:
|
||||
index = limit_min_hyst;
|
||||
break;
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
return humidity1_limit_write(dev, index, val);
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
}
|
||||
|
||||
static const struct hwmon_ops sht3x_ops = {
|
||||
.is_visible = sht3x_is_visible,
|
||||
.read = sht3x_read,
|
||||
.write = sht3x_write,
|
||||
};
|
||||
|
||||
static const struct hwmon_chip_info sht3x_chip_info = {
|
||||
.ops = &sht3x_ops,
|
||||
.info = sht3x_channel_info,
|
||||
};
|
||||
|
||||
/* device ID table */
|
||||
static const struct i2c_device_id sht3x_ids[] = {
|
||||
{"sht3x", sht3x},
|
||||
{"sts3x", sts3x},
|
||||
{}
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(i2c, sht3x_ids);
|
||||
|
||||
static int sht3x_probe(struct i2c_client *client)
|
||||
{
|
||||
@ -730,7 +858,6 @@ static int sht3x_probe(struct i2c_client *client)
|
||||
struct device *hwmon_dev;
|
||||
struct i2c_adapter *adap = client->adapter;
|
||||
struct device *dev = &client->dev;
|
||||
const struct attribute_group **attribute_groups;
|
||||
|
||||
/*
|
||||
* we require full i2c support since the sht3x uses multi-byte read and
|
||||
@ -753,6 +880,7 @@ static int sht3x_probe(struct i2c_client *client)
|
||||
data->mode = 0;
|
||||
data->last_update = jiffies - msecs_to_jiffies(3000);
|
||||
data->client = client;
|
||||
data->chip_id = i2c_match_id(sht3x_ids, client)->driver_data;
|
||||
crc8_populate_msb(sht3x_crc8_table, SHT3X_CRC8_POLYNOMIAL);
|
||||
|
||||
sht3x_select_command(data);
|
||||
@ -771,15 +899,11 @@ static int sht3x_probe(struct i2c_client *client)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (i2c_match_id(sht3x_ids, client)->driver_data == sts3x)
|
||||
attribute_groups = sts3x_groups;
|
||||
else
|
||||
attribute_groups = sht3x_groups;
|
||||
|
||||
hwmon_dev = devm_hwmon_device_register_with_groups(dev,
|
||||
client->name,
|
||||
data,
|
||||
attribute_groups);
|
||||
hwmon_dev = devm_hwmon_device_register_with_info(dev,
|
||||
client->name,
|
||||
data,
|
||||
&sht3x_chip_info,
|
||||
sht3x_groups);
|
||||
|
||||
if (IS_ERR(hwmon_dev))
|
||||
dev_dbg(dev, "unable to register hwmon device\n");
|
||||
@ -787,15 +911,6 @@ static int sht3x_probe(struct i2c_client *client)
|
||||
return PTR_ERR_OR_ZERO(hwmon_dev);
|
||||
}
|
||||
|
||||
/* device ID table */
|
||||
static const struct i2c_device_id sht3x_ids[] = {
|
||||
{"sht3x", sht3x},
|
||||
{"sts3x", sts3x},
|
||||
{}
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(i2c, sht3x_ids);
|
||||
|
||||
static struct i2c_driver sht3x_i2c_driver = {
|
||||
.driver.name = "sht3x",
|
||||
.probe = sht3x_probe,
|
||||
|
@ -798,7 +798,7 @@ static int sis5595_pci_probe(struct pci_dev *dev,
|
||||
{
|
||||
u16 address;
|
||||
u8 enable;
|
||||
int *i;
|
||||
int *i, err;
|
||||
|
||||
for (i = blacklist; *i != 0; i++) {
|
||||
struct pci_dev *d;
|
||||
@ -818,8 +818,8 @@ static int sis5595_pci_probe(struct pci_dev *dev,
|
||||
pci_write_config_word(dev, SIS5595_BASE_REG, force_addr);
|
||||
}
|
||||
|
||||
if (PCIBIOS_SUCCESSFUL !=
|
||||
pci_read_config_word(dev, SIS5595_BASE_REG, &address)) {
|
||||
err = pci_read_config_word(dev, SIS5595_BASE_REG, &address);
|
||||
if (err != PCIBIOS_SUCCESSFUL) {
|
||||
dev_err(&dev->dev, "Failed to read ISA address\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
@ -836,22 +836,23 @@ static int sis5595_pci_probe(struct pci_dev *dev,
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (PCIBIOS_SUCCESSFUL !=
|
||||
pci_read_config_byte(dev, SIS5595_ENABLE_REG, &enable)) {
|
||||
err = pci_read_config_byte(dev, SIS5595_ENABLE_REG, &enable);
|
||||
if (err != PCIBIOS_SUCCESSFUL) {
|
||||
dev_err(&dev->dev, "Failed to read enable register\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
if (!(enable & 0x80)) {
|
||||
if ((PCIBIOS_SUCCESSFUL !=
|
||||
pci_write_config_byte(dev, SIS5595_ENABLE_REG,
|
||||
enable | 0x80))
|
||||
|| (PCIBIOS_SUCCESSFUL !=
|
||||
pci_read_config_byte(dev, SIS5595_ENABLE_REG, &enable))
|
||||
|| (!(enable & 0x80))) {
|
||||
/* doesn't work for some chips! */
|
||||
dev_err(&dev->dev, "Failed to enable HWM device\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
err = pci_write_config_byte(dev, SIS5595_ENABLE_REG, enable | 0x80);
|
||||
if (err != PCIBIOS_SUCCESSFUL)
|
||||
goto enable_fail;
|
||||
|
||||
err = pci_read_config_byte(dev, SIS5595_ENABLE_REG, &enable);
|
||||
if (err != PCIBIOS_SUCCESSFUL)
|
||||
goto enable_fail;
|
||||
|
||||
/* doesn't work for some chips! */
|
||||
if (!(enable & 0x80))
|
||||
goto enable_fail;
|
||||
}
|
||||
|
||||
if (platform_driver_register(&sis5595_driver)) {
|
||||
@ -871,6 +872,10 @@ static int sis5595_pci_probe(struct pci_dev *dev,
|
||||
*/
|
||||
return -ENODEV;
|
||||
|
||||
enable_fail:
|
||||
dev_err(&dev->dev, "Failed to enable HWM device\n");
|
||||
goto exit;
|
||||
|
||||
exit_unregister:
|
||||
pci_dev_put(dev);
|
||||
platform_driver_unregister(&sis5595_driver);
|
||||
|
@ -1,706 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Driver for SMM665 Power Controller / Monitor
|
||||
*
|
||||
* Copyright (C) 2010 Ericsson AB.
|
||||
*
|
||||
* This driver should also work for SMM465, SMM764, and SMM766, but is untested
|
||||
* for those chips. Only monitoring functionality is implemented.
|
||||
*
|
||||
* Datasheets:
|
||||
* http://www.summitmicro.com/prod_select/summary/SMM665/SMM665B_2089_20.pdf
|
||||
* http://www.summitmicro.com/prod_select/summary/SMM766B/SMM766B_2122.pdf
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/hwmon-sysfs.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/jiffies.h>
|
||||
|
||||
/* Internal reference voltage (VREF, x 1000 */
|
||||
#define SMM665_VREF_ADC_X1000 1250
|
||||
|
||||
/* module parameters */
|
||||
static int vref = SMM665_VREF_ADC_X1000;
|
||||
module_param(vref, int, 0);
|
||||
MODULE_PARM_DESC(vref, "Reference voltage in mV");
|
||||
|
||||
enum chips { smm465, smm665, smm665c, smm764, smm766 };
|
||||
|
||||
/*
|
||||
* ADC channel addresses
|
||||
*/
|
||||
#define SMM665_MISC16_ADC_DATA_A 0x00
|
||||
#define SMM665_MISC16_ADC_DATA_B 0x01
|
||||
#define SMM665_MISC16_ADC_DATA_C 0x02
|
||||
#define SMM665_MISC16_ADC_DATA_D 0x03
|
||||
#define SMM665_MISC16_ADC_DATA_E 0x04
|
||||
#define SMM665_MISC16_ADC_DATA_F 0x05
|
||||
#define SMM665_MISC16_ADC_DATA_VDD 0x06
|
||||
#define SMM665_MISC16_ADC_DATA_12V 0x07
|
||||
#define SMM665_MISC16_ADC_DATA_INT_TEMP 0x08
|
||||
#define SMM665_MISC16_ADC_DATA_AIN1 0x09
|
||||
#define SMM665_MISC16_ADC_DATA_AIN2 0x0a
|
||||
|
||||
/*
|
||||
* Command registers
|
||||
*/
|
||||
#define SMM665_MISC8_CMD_STS 0x80
|
||||
#define SMM665_MISC8_STATUS1 0x81
|
||||
#define SMM665_MISC8_STATUSS2 0x82
|
||||
#define SMM665_MISC8_IO_POLARITY 0x83
|
||||
#define SMM665_MISC8_PUP_POLARITY 0x84
|
||||
#define SMM665_MISC8_ADOC_STATUS1 0x85
|
||||
#define SMM665_MISC8_ADOC_STATUS2 0x86
|
||||
#define SMM665_MISC8_WRITE_PROT 0x87
|
||||
#define SMM665_MISC8_STS_TRACK 0x88
|
||||
|
||||
/*
|
||||
* Configuration registers and register groups
|
||||
*/
|
||||
#define SMM665_ADOC_ENABLE 0x0d
|
||||
#define SMM665_LIMIT_BASE 0x80 /* First limit register */
|
||||
|
||||
/*
|
||||
* Limit register bit masks
|
||||
*/
|
||||
#define SMM665_TRIGGER_RST 0x8000
|
||||
#define SMM665_TRIGGER_HEALTHY 0x4000
|
||||
#define SMM665_TRIGGER_POWEROFF 0x2000
|
||||
#define SMM665_TRIGGER_SHUTDOWN 0x1000
|
||||
#define SMM665_ADC_MASK 0x03ff
|
||||
|
||||
#define smm665_is_critical(lim) ((lim) & (SMM665_TRIGGER_RST \
|
||||
| SMM665_TRIGGER_POWEROFF \
|
||||
| SMM665_TRIGGER_SHUTDOWN))
|
||||
/*
|
||||
* Fault register bit definitions
|
||||
* Values are merged from status registers 1/2,
|
||||
* with status register 1 providing the upper 8 bits.
|
||||
*/
|
||||
#define SMM665_FAULT_A 0x0001
|
||||
#define SMM665_FAULT_B 0x0002
|
||||
#define SMM665_FAULT_C 0x0004
|
||||
#define SMM665_FAULT_D 0x0008
|
||||
#define SMM665_FAULT_E 0x0010
|
||||
#define SMM665_FAULT_F 0x0020
|
||||
#define SMM665_FAULT_VDD 0x0040
|
||||
#define SMM665_FAULT_12V 0x0080
|
||||
#define SMM665_FAULT_TEMP 0x0100
|
||||
#define SMM665_FAULT_AIN1 0x0200
|
||||
#define SMM665_FAULT_AIN2 0x0400
|
||||
|
||||
/*
|
||||
* I2C Register addresses
|
||||
*
|
||||
* The configuration register needs to be the configured base register.
|
||||
* The command/status register address is derived from it.
|
||||
*/
|
||||
#define SMM665_REGMASK 0x78
|
||||
#define SMM665_CMDREG_BASE 0x48
|
||||
#define SMM665_CONFREG_BASE 0x50
|
||||
|
||||
/*
|
||||
* Equations given by chip manufacturer to calculate voltage/temperature values
|
||||
* vref = Reference voltage on VREF_ADC pin (module parameter)
|
||||
* adc = 10bit ADC value read back from registers
|
||||
*/
|
||||
|
||||
/* Voltage A-F and VDD */
|
||||
#define SMM665_VMON_ADC_TO_VOLTS(adc) ((adc) * vref / 256)
|
||||
|
||||
/* Voltage 12VIN */
|
||||
#define SMM665_12VIN_ADC_TO_VOLTS(adc) ((adc) * vref * 3 / 256)
|
||||
|
||||
/* Voltage AIN1, AIN2 */
|
||||
#define SMM665_AIN_ADC_TO_VOLTS(adc) ((adc) * vref / 512)
|
||||
|
||||
/* Temp Sensor */
|
||||
#define SMM665_TEMP_ADC_TO_CELSIUS(adc) (((adc) <= 511) ? \
|
||||
((int)(adc) * 1000 / 4) : \
|
||||
(((int)(adc) - 0x400) * 1000 / 4))
|
||||
|
||||
#define SMM665_NUM_ADC 11
|
||||
|
||||
/*
|
||||
* Chip dependent ADC conversion time, in uS
|
||||
*/
|
||||
#define SMM665_ADC_WAIT_SMM665 70
|
||||
#define SMM665_ADC_WAIT_SMM766 185
|
||||
|
||||
struct smm665_data {
|
||||
enum chips type;
|
||||
int conversion_time; /* ADC conversion time */
|
||||
struct i2c_client *client;
|
||||
struct mutex update_lock;
|
||||
bool valid;
|
||||
unsigned long last_updated; /* in jiffies */
|
||||
u16 adc[SMM665_NUM_ADC]; /* adc values (raw) */
|
||||
u16 faults; /* fault status */
|
||||
/* The following values are in mV */
|
||||
int critical_min_limit[SMM665_NUM_ADC];
|
||||
int alarm_min_limit[SMM665_NUM_ADC];
|
||||
int critical_max_limit[SMM665_NUM_ADC];
|
||||
int alarm_max_limit[SMM665_NUM_ADC];
|
||||
struct i2c_client *cmdreg;
|
||||
};
|
||||
|
||||
/*
|
||||
* smm665_read16()
|
||||
*
|
||||
* Read 16 bit value from <reg>, <reg+1>. Upper 8 bits are in <reg>.
|
||||
*/
|
||||
static int smm665_read16(struct i2c_client *client, int reg)
|
||||
{
|
||||
int rv, val;
|
||||
|
||||
rv = i2c_smbus_read_byte_data(client, reg);
|
||||
if (rv < 0)
|
||||
return rv;
|
||||
val = rv << 8;
|
||||
rv = i2c_smbus_read_byte_data(client, reg + 1);
|
||||
if (rv < 0)
|
||||
return rv;
|
||||
val |= rv;
|
||||
return val;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read adc value.
|
||||
*/
|
||||
static int smm665_read_adc(struct smm665_data *data, int adc)
|
||||
{
|
||||
struct i2c_client *client = data->cmdreg;
|
||||
int rv;
|
||||
int radc;
|
||||
|
||||
/*
|
||||
* Algorithm for reading ADC, per SMM665 datasheet
|
||||
*
|
||||
* {[S][addr][W][Ack]} {[offset][Ack]} {[S][addr][R][Nack]}
|
||||
* [wait conversion time]
|
||||
* {[S][addr][R][Ack]} {[datahi][Ack]} {[datalo][Ack][P]}
|
||||
*
|
||||
* To implement the first part of this exchange,
|
||||
* do a full read transaction and expect a failure/Nack.
|
||||
* This sets up the address pointer on the SMM665
|
||||
* and starts the ADC conversion.
|
||||
* Then do a two-byte read transaction.
|
||||
*/
|
||||
rv = i2c_smbus_read_byte_data(client, adc << 3);
|
||||
if (rv != -ENXIO) {
|
||||
/*
|
||||
* We expect ENXIO to reflect NACK
|
||||
* (per Documentation/i2c/fault-codes.rst).
|
||||
* Everything else is an error.
|
||||
*/
|
||||
dev_dbg(&client->dev,
|
||||
"Unexpected return code %d when setting ADC index", rv);
|
||||
return (rv < 0) ? rv : -EIO;
|
||||
}
|
||||
|
||||
udelay(data->conversion_time);
|
||||
|
||||
/*
|
||||
* Now read two bytes.
|
||||
*
|
||||
* Neither i2c_smbus_read_byte() nor
|
||||
* i2c_smbus_read_block_data() worked here,
|
||||
* so use i2c_smbus_read_word_swapped() instead.
|
||||
* We could also try to use i2c_master_recv(),
|
||||
* but that is not always supported.
|
||||
*/
|
||||
rv = i2c_smbus_read_word_swapped(client, 0);
|
||||
if (rv < 0) {
|
||||
dev_dbg(&client->dev, "Failed to read ADC value: error %d", rv);
|
||||
return rv;
|
||||
}
|
||||
/*
|
||||
* Validate/verify readback adc channel (in bit 11..14).
|
||||
*/
|
||||
radc = (rv >> 11) & 0x0f;
|
||||
if (radc != adc) {
|
||||
dev_dbg(&client->dev, "Unexpected RADC: Expected %d got %d",
|
||||
adc, radc);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return rv & SMM665_ADC_MASK;
|
||||
}
|
||||
|
||||
static struct smm665_data *smm665_update_device(struct device *dev)
|
||||
{
|
||||
struct smm665_data *data = dev_get_drvdata(dev);
|
||||
struct i2c_client *client = data->client;
|
||||
struct smm665_data *ret = data;
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
|
||||
if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
|
||||
int i, val;
|
||||
|
||||
/*
|
||||
* read status registers
|
||||
*/
|
||||
val = smm665_read16(client, SMM665_MISC8_STATUS1);
|
||||
if (unlikely(val < 0)) {
|
||||
ret = ERR_PTR(val);
|
||||
goto abort;
|
||||
}
|
||||
data->faults = val;
|
||||
|
||||
/* Read adc registers */
|
||||
for (i = 0; i < SMM665_NUM_ADC; i++) {
|
||||
val = smm665_read_adc(data, i);
|
||||
if (unlikely(val < 0)) {
|
||||
ret = ERR_PTR(val);
|
||||
goto abort;
|
||||
}
|
||||
data->adc[i] = val;
|
||||
}
|
||||
data->last_updated = jiffies;
|
||||
data->valid = true;
|
||||
}
|
||||
abort:
|
||||
mutex_unlock(&data->update_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Return converted value from given adc */
|
||||
static int smm665_convert(u16 adcval, int index)
|
||||
{
|
||||
int val = 0;
|
||||
|
||||
switch (index) {
|
||||
case SMM665_MISC16_ADC_DATA_12V:
|
||||
val = SMM665_12VIN_ADC_TO_VOLTS(adcval & SMM665_ADC_MASK);
|
||||
break;
|
||||
|
||||
case SMM665_MISC16_ADC_DATA_VDD:
|
||||
case SMM665_MISC16_ADC_DATA_A:
|
||||
case SMM665_MISC16_ADC_DATA_B:
|
||||
case SMM665_MISC16_ADC_DATA_C:
|
||||
case SMM665_MISC16_ADC_DATA_D:
|
||||
case SMM665_MISC16_ADC_DATA_E:
|
||||
case SMM665_MISC16_ADC_DATA_F:
|
||||
val = SMM665_VMON_ADC_TO_VOLTS(adcval & SMM665_ADC_MASK);
|
||||
break;
|
||||
|
||||
case SMM665_MISC16_ADC_DATA_AIN1:
|
||||
case SMM665_MISC16_ADC_DATA_AIN2:
|
||||
val = SMM665_AIN_ADC_TO_VOLTS(adcval & SMM665_ADC_MASK);
|
||||
break;
|
||||
|
||||
case SMM665_MISC16_ADC_DATA_INT_TEMP:
|
||||
val = SMM665_TEMP_ADC_TO_CELSIUS(adcval & SMM665_ADC_MASK);
|
||||
break;
|
||||
|
||||
default:
|
||||
/* If we get here, the developer messed up */
|
||||
WARN_ON_ONCE(1);
|
||||
break;
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static int smm665_get_min(struct device *dev, int index)
|
||||
{
|
||||
struct smm665_data *data = dev_get_drvdata(dev);
|
||||
|
||||
return data->alarm_min_limit[index];
|
||||
}
|
||||
|
||||
static int smm665_get_max(struct device *dev, int index)
|
||||
{
|
||||
struct smm665_data *data = dev_get_drvdata(dev);
|
||||
|
||||
return data->alarm_max_limit[index];
|
||||
}
|
||||
|
||||
static int smm665_get_lcrit(struct device *dev, int index)
|
||||
{
|
||||
struct smm665_data *data = dev_get_drvdata(dev);
|
||||
|
||||
return data->critical_min_limit[index];
|
||||
}
|
||||
|
||||
static int smm665_get_crit(struct device *dev, int index)
|
||||
{
|
||||
struct smm665_data *data = dev_get_drvdata(dev);
|
||||
|
||||
return data->critical_max_limit[index];
|
||||
}
|
||||
|
||||
static ssize_t smm665_show_crit_alarm(struct device *dev,
|
||||
struct device_attribute *da, char *buf)
|
||||
{
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
|
||||
struct smm665_data *data = smm665_update_device(dev);
|
||||
int val = 0;
|
||||
|
||||
if (IS_ERR(data))
|
||||
return PTR_ERR(data);
|
||||
|
||||
if (data->faults & (1 << attr->index))
|
||||
val = 1;
|
||||
|
||||
return sysfs_emit(buf, "%d\n", val);
|
||||
}
|
||||
|
||||
static ssize_t smm665_show_input(struct device *dev,
|
||||
struct device_attribute *da, char *buf)
|
||||
{
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
|
||||
struct smm665_data *data = smm665_update_device(dev);
|
||||
int adc = attr->index;
|
||||
int val;
|
||||
|
||||
if (IS_ERR(data))
|
||||
return PTR_ERR(data);
|
||||
|
||||
val = smm665_convert(data->adc[adc], adc);
|
||||
return sysfs_emit(buf, "%d\n", val);
|
||||
}
|
||||
|
||||
#define SMM665_SHOW(what) \
|
||||
static ssize_t smm665_show_##what(struct device *dev, \
|
||||
struct device_attribute *da, char *buf) \
|
||||
{ \
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(da); \
|
||||
const int val = smm665_get_##what(dev, attr->index); \
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", val); \
|
||||
}
|
||||
|
||||
SMM665_SHOW(min);
|
||||
SMM665_SHOW(max);
|
||||
SMM665_SHOW(lcrit);
|
||||
SMM665_SHOW(crit);
|
||||
|
||||
/*
|
||||
* These macros are used below in constructing device attribute objects
|
||||
* for use with sysfs_create_group() to make a sysfs device file
|
||||
* for each register.
|
||||
*/
|
||||
|
||||
#define SMM665_ATTR(name, type, cmd_idx) \
|
||||
static SENSOR_DEVICE_ATTR(name##_##type, S_IRUGO, \
|
||||
smm665_show_##type, NULL, cmd_idx)
|
||||
|
||||
/* Construct a sensor_device_attribute structure for each register */
|
||||
|
||||
/* Input voltages */
|
||||
SMM665_ATTR(in1, input, SMM665_MISC16_ADC_DATA_12V);
|
||||
SMM665_ATTR(in2, input, SMM665_MISC16_ADC_DATA_VDD);
|
||||
SMM665_ATTR(in3, input, SMM665_MISC16_ADC_DATA_A);
|
||||
SMM665_ATTR(in4, input, SMM665_MISC16_ADC_DATA_B);
|
||||
SMM665_ATTR(in5, input, SMM665_MISC16_ADC_DATA_C);
|
||||
SMM665_ATTR(in6, input, SMM665_MISC16_ADC_DATA_D);
|
||||
SMM665_ATTR(in7, input, SMM665_MISC16_ADC_DATA_E);
|
||||
SMM665_ATTR(in8, input, SMM665_MISC16_ADC_DATA_F);
|
||||
SMM665_ATTR(in9, input, SMM665_MISC16_ADC_DATA_AIN1);
|
||||
SMM665_ATTR(in10, input, SMM665_MISC16_ADC_DATA_AIN2);
|
||||
|
||||
/* Input voltages min */
|
||||
SMM665_ATTR(in1, min, SMM665_MISC16_ADC_DATA_12V);
|
||||
SMM665_ATTR(in2, min, SMM665_MISC16_ADC_DATA_VDD);
|
||||
SMM665_ATTR(in3, min, SMM665_MISC16_ADC_DATA_A);
|
||||
SMM665_ATTR(in4, min, SMM665_MISC16_ADC_DATA_B);
|
||||
SMM665_ATTR(in5, min, SMM665_MISC16_ADC_DATA_C);
|
||||
SMM665_ATTR(in6, min, SMM665_MISC16_ADC_DATA_D);
|
||||
SMM665_ATTR(in7, min, SMM665_MISC16_ADC_DATA_E);
|
||||
SMM665_ATTR(in8, min, SMM665_MISC16_ADC_DATA_F);
|
||||
SMM665_ATTR(in9, min, SMM665_MISC16_ADC_DATA_AIN1);
|
||||
SMM665_ATTR(in10, min, SMM665_MISC16_ADC_DATA_AIN2);
|
||||
|
||||
/* Input voltages max */
|
||||
SMM665_ATTR(in1, max, SMM665_MISC16_ADC_DATA_12V);
|
||||
SMM665_ATTR(in2, max, SMM665_MISC16_ADC_DATA_VDD);
|
||||
SMM665_ATTR(in3, max, SMM665_MISC16_ADC_DATA_A);
|
||||
SMM665_ATTR(in4, max, SMM665_MISC16_ADC_DATA_B);
|
||||
SMM665_ATTR(in5, max, SMM665_MISC16_ADC_DATA_C);
|
||||
SMM665_ATTR(in6, max, SMM665_MISC16_ADC_DATA_D);
|
||||
SMM665_ATTR(in7, max, SMM665_MISC16_ADC_DATA_E);
|
||||
SMM665_ATTR(in8, max, SMM665_MISC16_ADC_DATA_F);
|
||||
SMM665_ATTR(in9, max, SMM665_MISC16_ADC_DATA_AIN1);
|
||||
SMM665_ATTR(in10, max, SMM665_MISC16_ADC_DATA_AIN2);
|
||||
|
||||
/* Input voltages lcrit */
|
||||
SMM665_ATTR(in1, lcrit, SMM665_MISC16_ADC_DATA_12V);
|
||||
SMM665_ATTR(in2, lcrit, SMM665_MISC16_ADC_DATA_VDD);
|
||||
SMM665_ATTR(in3, lcrit, SMM665_MISC16_ADC_DATA_A);
|
||||
SMM665_ATTR(in4, lcrit, SMM665_MISC16_ADC_DATA_B);
|
||||
SMM665_ATTR(in5, lcrit, SMM665_MISC16_ADC_DATA_C);
|
||||
SMM665_ATTR(in6, lcrit, SMM665_MISC16_ADC_DATA_D);
|
||||
SMM665_ATTR(in7, lcrit, SMM665_MISC16_ADC_DATA_E);
|
||||
SMM665_ATTR(in8, lcrit, SMM665_MISC16_ADC_DATA_F);
|
||||
SMM665_ATTR(in9, lcrit, SMM665_MISC16_ADC_DATA_AIN1);
|
||||
SMM665_ATTR(in10, lcrit, SMM665_MISC16_ADC_DATA_AIN2);
|
||||
|
||||
/* Input voltages crit */
|
||||
SMM665_ATTR(in1, crit, SMM665_MISC16_ADC_DATA_12V);
|
||||
SMM665_ATTR(in2, crit, SMM665_MISC16_ADC_DATA_VDD);
|
||||
SMM665_ATTR(in3, crit, SMM665_MISC16_ADC_DATA_A);
|
||||
SMM665_ATTR(in4, crit, SMM665_MISC16_ADC_DATA_B);
|
||||
SMM665_ATTR(in5, crit, SMM665_MISC16_ADC_DATA_C);
|
||||
SMM665_ATTR(in6, crit, SMM665_MISC16_ADC_DATA_D);
|
||||
SMM665_ATTR(in7, crit, SMM665_MISC16_ADC_DATA_E);
|
||||
SMM665_ATTR(in8, crit, SMM665_MISC16_ADC_DATA_F);
|
||||
SMM665_ATTR(in9, crit, SMM665_MISC16_ADC_DATA_AIN1);
|
||||
SMM665_ATTR(in10, crit, SMM665_MISC16_ADC_DATA_AIN2);
|
||||
|
||||
/* critical alarms */
|
||||
SMM665_ATTR(in1, crit_alarm, SMM665_FAULT_12V);
|
||||
SMM665_ATTR(in2, crit_alarm, SMM665_FAULT_VDD);
|
||||
SMM665_ATTR(in3, crit_alarm, SMM665_FAULT_A);
|
||||
SMM665_ATTR(in4, crit_alarm, SMM665_FAULT_B);
|
||||
SMM665_ATTR(in5, crit_alarm, SMM665_FAULT_C);
|
||||
SMM665_ATTR(in6, crit_alarm, SMM665_FAULT_D);
|
||||
SMM665_ATTR(in7, crit_alarm, SMM665_FAULT_E);
|
||||
SMM665_ATTR(in8, crit_alarm, SMM665_FAULT_F);
|
||||
SMM665_ATTR(in9, crit_alarm, SMM665_FAULT_AIN1);
|
||||
SMM665_ATTR(in10, crit_alarm, SMM665_FAULT_AIN2);
|
||||
|
||||
/* Temperature */
|
||||
SMM665_ATTR(temp1, input, SMM665_MISC16_ADC_DATA_INT_TEMP);
|
||||
SMM665_ATTR(temp1, min, SMM665_MISC16_ADC_DATA_INT_TEMP);
|
||||
SMM665_ATTR(temp1, max, SMM665_MISC16_ADC_DATA_INT_TEMP);
|
||||
SMM665_ATTR(temp1, lcrit, SMM665_MISC16_ADC_DATA_INT_TEMP);
|
||||
SMM665_ATTR(temp1, crit, SMM665_MISC16_ADC_DATA_INT_TEMP);
|
||||
SMM665_ATTR(temp1, crit_alarm, SMM665_FAULT_TEMP);
|
||||
|
||||
/*
|
||||
* Finally, construct an array of pointers to members of the above objects,
|
||||
* as required for sysfs_create_group()
|
||||
*/
|
||||
static struct attribute *smm665_attrs[] = {
|
||||
&sensor_dev_attr_in1_input.dev_attr.attr,
|
||||
&sensor_dev_attr_in1_min.dev_attr.attr,
|
||||
&sensor_dev_attr_in1_max.dev_attr.attr,
|
||||
&sensor_dev_attr_in1_lcrit.dev_attr.attr,
|
||||
&sensor_dev_attr_in1_crit.dev_attr.attr,
|
||||
&sensor_dev_attr_in1_crit_alarm.dev_attr.attr,
|
||||
|
||||
&sensor_dev_attr_in2_input.dev_attr.attr,
|
||||
&sensor_dev_attr_in2_min.dev_attr.attr,
|
||||
&sensor_dev_attr_in2_max.dev_attr.attr,
|
||||
&sensor_dev_attr_in2_lcrit.dev_attr.attr,
|
||||
&sensor_dev_attr_in2_crit.dev_attr.attr,
|
||||
&sensor_dev_attr_in2_crit_alarm.dev_attr.attr,
|
||||
|
||||
&sensor_dev_attr_in3_input.dev_attr.attr,
|
||||
&sensor_dev_attr_in3_min.dev_attr.attr,
|
||||
&sensor_dev_attr_in3_max.dev_attr.attr,
|
||||
&sensor_dev_attr_in3_lcrit.dev_attr.attr,
|
||||
&sensor_dev_attr_in3_crit.dev_attr.attr,
|
||||
&sensor_dev_attr_in3_crit_alarm.dev_attr.attr,
|
||||
|
||||
&sensor_dev_attr_in4_input.dev_attr.attr,
|
||||
&sensor_dev_attr_in4_min.dev_attr.attr,
|
||||
&sensor_dev_attr_in4_max.dev_attr.attr,
|
||||
&sensor_dev_attr_in4_lcrit.dev_attr.attr,
|
||||
&sensor_dev_attr_in4_crit.dev_attr.attr,
|
||||
&sensor_dev_attr_in4_crit_alarm.dev_attr.attr,
|
||||
|
||||
&sensor_dev_attr_in5_input.dev_attr.attr,
|
||||
&sensor_dev_attr_in5_min.dev_attr.attr,
|
||||
&sensor_dev_attr_in5_max.dev_attr.attr,
|
||||
&sensor_dev_attr_in5_lcrit.dev_attr.attr,
|
||||
&sensor_dev_attr_in5_crit.dev_attr.attr,
|
||||
&sensor_dev_attr_in5_crit_alarm.dev_attr.attr,
|
||||
|
||||
&sensor_dev_attr_in6_input.dev_attr.attr,
|
||||
&sensor_dev_attr_in6_min.dev_attr.attr,
|
||||
&sensor_dev_attr_in6_max.dev_attr.attr,
|
||||
&sensor_dev_attr_in6_lcrit.dev_attr.attr,
|
||||
&sensor_dev_attr_in6_crit.dev_attr.attr,
|
||||
&sensor_dev_attr_in6_crit_alarm.dev_attr.attr,
|
||||
|
||||
&sensor_dev_attr_in7_input.dev_attr.attr,
|
||||
&sensor_dev_attr_in7_min.dev_attr.attr,
|
||||
&sensor_dev_attr_in7_max.dev_attr.attr,
|
||||
&sensor_dev_attr_in7_lcrit.dev_attr.attr,
|
||||
&sensor_dev_attr_in7_crit.dev_attr.attr,
|
||||
&sensor_dev_attr_in7_crit_alarm.dev_attr.attr,
|
||||
|
||||
&sensor_dev_attr_in8_input.dev_attr.attr,
|
||||
&sensor_dev_attr_in8_min.dev_attr.attr,
|
||||
&sensor_dev_attr_in8_max.dev_attr.attr,
|
||||
&sensor_dev_attr_in8_lcrit.dev_attr.attr,
|
||||
&sensor_dev_attr_in8_crit.dev_attr.attr,
|
||||
&sensor_dev_attr_in8_crit_alarm.dev_attr.attr,
|
||||
|
||||
&sensor_dev_attr_in9_input.dev_attr.attr,
|
||||
&sensor_dev_attr_in9_min.dev_attr.attr,
|
||||
&sensor_dev_attr_in9_max.dev_attr.attr,
|
||||
&sensor_dev_attr_in9_lcrit.dev_attr.attr,
|
||||
&sensor_dev_attr_in9_crit.dev_attr.attr,
|
||||
&sensor_dev_attr_in9_crit_alarm.dev_attr.attr,
|
||||
|
||||
&sensor_dev_attr_in10_input.dev_attr.attr,
|
||||
&sensor_dev_attr_in10_min.dev_attr.attr,
|
||||
&sensor_dev_attr_in10_max.dev_attr.attr,
|
||||
&sensor_dev_attr_in10_lcrit.dev_attr.attr,
|
||||
&sensor_dev_attr_in10_crit.dev_attr.attr,
|
||||
&sensor_dev_attr_in10_crit_alarm.dev_attr.attr,
|
||||
|
||||
&sensor_dev_attr_temp1_input.dev_attr.attr,
|
||||
&sensor_dev_attr_temp1_min.dev_attr.attr,
|
||||
&sensor_dev_attr_temp1_max.dev_attr.attr,
|
||||
&sensor_dev_attr_temp1_lcrit.dev_attr.attr,
|
||||
&sensor_dev_attr_temp1_crit.dev_attr.attr,
|
||||
&sensor_dev_attr_temp1_crit_alarm.dev_attr.attr,
|
||||
|
||||
NULL,
|
||||
};
|
||||
|
||||
ATTRIBUTE_GROUPS(smm665);
|
||||
|
||||
static const struct i2c_device_id smm665_id[];
|
||||
|
||||
static int smm665_probe(struct i2c_client *client)
|
||||
{
|
||||
struct i2c_adapter *adapter = client->adapter;
|
||||
struct smm665_data *data;
|
||||
struct device *hwmon_dev;
|
||||
int i, ret;
|
||||
|
||||
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA
|
||||
| I2C_FUNC_SMBUS_WORD_DATA))
|
||||
return -ENODEV;
|
||||
|
||||
if (i2c_smbus_read_byte_data(client, SMM665_ADOC_ENABLE) < 0)
|
||||
return -ENODEV;
|
||||
|
||||
data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
i2c_set_clientdata(client, data);
|
||||
mutex_init(&data->update_lock);
|
||||
|
||||
data->client = client;
|
||||
data->type = i2c_match_id(smm665_id, client)->driver_data;
|
||||
data->cmdreg = i2c_new_dummy_device(adapter, (client->addr & ~SMM665_REGMASK)
|
||||
| SMM665_CMDREG_BASE);
|
||||
if (IS_ERR(data->cmdreg))
|
||||
return PTR_ERR(data->cmdreg);
|
||||
|
||||
switch (data->type) {
|
||||
case smm465:
|
||||
case smm665:
|
||||
data->conversion_time = SMM665_ADC_WAIT_SMM665;
|
||||
break;
|
||||
case smm665c:
|
||||
case smm764:
|
||||
case smm766:
|
||||
data->conversion_time = SMM665_ADC_WAIT_SMM766;
|
||||
break;
|
||||
}
|
||||
|
||||
ret = -ENODEV;
|
||||
if (i2c_smbus_read_byte_data(data->cmdreg, SMM665_MISC8_CMD_STS) < 0)
|
||||
goto out_unregister;
|
||||
|
||||
/*
|
||||
* Read limits.
|
||||
*
|
||||
* Limit registers start with register SMM665_LIMIT_BASE.
|
||||
* Each channel uses 8 registers, providing four limit values
|
||||
* per channel. Each limit value requires two registers, with the
|
||||
* high byte in the first register and the low byte in the second
|
||||
* register. The first two limits are under limit values, followed
|
||||
* by two over limit values.
|
||||
*
|
||||
* Limit register order matches the ADC register order, so we use
|
||||
* ADC register defines throughout the code to index limit registers.
|
||||
*
|
||||
* We save the first retrieved value both as "critical" and "alarm"
|
||||
* value. The second value overwrites either the critical or the
|
||||
* alarm value, depending on its configuration. This ensures that both
|
||||
* critical and alarm values are initialized, even if both registers are
|
||||
* configured as critical or non-critical.
|
||||
*/
|
||||
for (i = 0; i < SMM665_NUM_ADC; i++) {
|
||||
int val;
|
||||
|
||||
val = smm665_read16(client, SMM665_LIMIT_BASE + i * 8);
|
||||
if (unlikely(val < 0))
|
||||
goto out_unregister;
|
||||
data->critical_min_limit[i] = data->alarm_min_limit[i]
|
||||
= smm665_convert(val, i);
|
||||
val = smm665_read16(client, SMM665_LIMIT_BASE + i * 8 + 2);
|
||||
if (unlikely(val < 0))
|
||||
goto out_unregister;
|
||||
if (smm665_is_critical(val))
|
||||
data->critical_min_limit[i] = smm665_convert(val, i);
|
||||
else
|
||||
data->alarm_min_limit[i] = smm665_convert(val, i);
|
||||
val = smm665_read16(client, SMM665_LIMIT_BASE + i * 8 + 4);
|
||||
if (unlikely(val < 0))
|
||||
goto out_unregister;
|
||||
data->critical_max_limit[i] = data->alarm_max_limit[i]
|
||||
= smm665_convert(val, i);
|
||||
val = smm665_read16(client, SMM665_LIMIT_BASE + i * 8 + 6);
|
||||
if (unlikely(val < 0))
|
||||
goto out_unregister;
|
||||
if (smm665_is_critical(val))
|
||||
data->critical_max_limit[i] = smm665_convert(val, i);
|
||||
else
|
||||
data->alarm_max_limit[i] = smm665_convert(val, i);
|
||||
}
|
||||
|
||||
hwmon_dev = devm_hwmon_device_register_with_groups(&client->dev,
|
||||
client->name, data,
|
||||
smm665_groups);
|
||||
if (IS_ERR(hwmon_dev)) {
|
||||
ret = PTR_ERR(hwmon_dev);
|
||||
goto out_unregister;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
out_unregister:
|
||||
i2c_unregister_device(data->cmdreg);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void smm665_remove(struct i2c_client *client)
|
||||
{
|
||||
struct smm665_data *data = i2c_get_clientdata(client);
|
||||
|
||||
i2c_unregister_device(data->cmdreg);
|
||||
}
|
||||
|
||||
static const struct i2c_device_id smm665_id[] = {
|
||||
{"smm465", smm465},
|
||||
{"smm665", smm665},
|
||||
{"smm665c", smm665c},
|
||||
{"smm764", smm764},
|
||||
{"smm766", smm766},
|
||||
{}
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(i2c, smm665_id);
|
||||
|
||||
/* This is the driver that will be inserted */
|
||||
static struct i2c_driver smm665_driver = {
|
||||
.driver = {
|
||||
.name = "smm665",
|
||||
},
|
||||
.probe = smm665_probe,
|
||||
.remove = smm665_remove,
|
||||
.id_table = smm665_id,
|
||||
};
|
||||
|
||||
module_i2c_driver(smm665_driver);
|
||||
|
||||
MODULE_AUTHOR("Guenter Roeck");
|
||||
MODULE_DESCRIPTION("SMM665 driver");
|
||||
MODULE_LICENSE("GPL");
|
@ -20,7 +20,7 @@
|
||||
#include <linux/hwmon-sysfs.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/sysfs.h>
|
||||
|
||||
/* Addresses to scan */
|
||||
|
@ -14,7 +14,7 @@
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
|
@ -434,7 +434,7 @@ static umode_t tmp51x_is_visible(const void *_data,
|
||||
|
||||
switch (type) {
|
||||
case hwmon_temp:
|
||||
if (data->id == tmp512 && channel == 4)
|
||||
if (data->id == tmp512 && channel == 3)
|
||||
return 0;
|
||||
switch (attr) {
|
||||
case hwmon_temp_input:
|
||||
@ -720,10 +720,7 @@ static int tmp51x_probe(struct i2c_client *client)
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
if (client->dev.of_node)
|
||||
data->id = (enum tmp51x_ids)device_get_match_data(&client->dev);
|
||||
else
|
||||
data->id = i2c_match_id(tmp51x_id, client)->driver_data;
|
||||
data->id = (uintptr_t)i2c_get_match_data(client);
|
||||
|
||||
ret = tmp51x_configure(dev, data);
|
||||
if (ret < 0) {
|
||||
|
@ -14,7 +14,7 @@
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
#define TEMPERATURE 0x2c
|
||||
|
@ -9,7 +9,8 @@
|
||||
#include <linux/types.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/hwmon-sysfs.h>
|
||||
|
@ -13,7 +13,6 @@
|
||||
#include <linux/hwmon-sysfs.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/vexpress.h>
|
||||
|
||||
|
@ -855,16 +855,17 @@ static int via686a_pci_probe(struct pci_dev *dev,
|
||||
const struct pci_device_id *id)
|
||||
{
|
||||
u16 address, val;
|
||||
int ret;
|
||||
|
||||
if (force_addr) {
|
||||
address = force_addr & ~(VIA686A_EXTENT - 1);
|
||||
dev_warn(&dev->dev, "Forcing ISA address 0x%x\n", address);
|
||||
if (PCIBIOS_SUCCESSFUL !=
|
||||
pci_write_config_word(dev, VIA686A_BASE_REG, address | 1))
|
||||
ret = pci_write_config_word(dev, VIA686A_BASE_REG, address | 1);
|
||||
if (ret != PCIBIOS_SUCCESSFUL)
|
||||
return -ENODEV;
|
||||
}
|
||||
if (PCIBIOS_SUCCESSFUL !=
|
||||
pci_read_config_word(dev, VIA686A_BASE_REG, &val))
|
||||
ret = pci_read_config_word(dev, VIA686A_BASE_REG, &val);
|
||||
if (ret != PCIBIOS_SUCCESSFUL)
|
||||
return -ENODEV;
|
||||
|
||||
address = val & ~(VIA686A_EXTENT - 1);
|
||||
@ -874,8 +875,8 @@ static int via686a_pci_probe(struct pci_dev *dev,
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (PCIBIOS_SUCCESSFUL !=
|
||||
pci_read_config_word(dev, VIA686A_ENABLE_REG, &val))
|
||||
ret = pci_read_config_word(dev, VIA686A_ENABLE_REG, &val);
|
||||
if (ret != PCIBIOS_SUCCESSFUL)
|
||||
return -ENODEV;
|
||||
if (!(val & 0x0001)) {
|
||||
if (!force_addr) {
|
||||
@ -886,9 +887,8 @@ static int via686a_pci_probe(struct pci_dev *dev,
|
||||
}
|
||||
|
||||
dev_warn(&dev->dev, "Enabling sensors\n");
|
||||
if (PCIBIOS_SUCCESSFUL !=
|
||||
pci_write_config_word(dev, VIA686A_ENABLE_REG,
|
||||
val | 0x0001))
|
||||
ret = pci_write_config_word(dev, VIA686A_ENABLE_REG, val | 0x1);
|
||||
if (ret != PCIBIOS_SUCCESSFUL)
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
|
@ -971,13 +971,15 @@ static int vt8231_pci_probe(struct pci_dev *dev,
|
||||
const struct pci_device_id *id)
|
||||
{
|
||||
u16 address, val;
|
||||
int ret;
|
||||
|
||||
if (force_addr) {
|
||||
address = force_addr & 0xff00;
|
||||
dev_warn(&dev->dev, "Forcing ISA address 0x%x\n",
|
||||
address);
|
||||
|
||||
if (PCIBIOS_SUCCESSFUL !=
|
||||
pci_write_config_word(dev, VT8231_BASE_REG, address | 1))
|
||||
ret = pci_write_config_word(dev, VT8231_BASE_REG, address | 1);
|
||||
if (ret != PCIBIOS_SUCCESSFUL)
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
@ -997,9 +999,8 @@ static int vt8231_pci_probe(struct pci_dev *dev,
|
||||
|
||||
if (!(val & 0x0001)) {
|
||||
dev_warn(&dev->dev, "enabling sensors\n");
|
||||
if (PCIBIOS_SUCCESSFUL !=
|
||||
pci_write_config_word(dev, VT8231_ENABLE_REG,
|
||||
val | 0x0001))
|
||||
ret = pci_write_config_word(dev, VT8231_ENABLE_REG, val | 0x1);
|
||||
if (ret != PCIBIOS_SUCCESSFUL)
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
|
@ -12,7 +12,7 @@
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/hwmon-sysfs.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
/* W83773 has 3 channels */
|
||||
|
Loading…
x
Reference in New Issue
Block a user