diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-07-25 00:10:30 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-07-25 00:10:30 -0400 |
commit | dd9506954539dcedd0294a065ff0976e61386fc6 (patch) | |
tree | 41f64447f5f96a0eb0409771b4f9e17163eda5a4 | |
parent | 52770c37db2c0ee5585dae2de3d19c8453f1e8dc (diff) | |
parent | 1d3dd4ce210f347dd214913544e22fd9a8122901 (diff) |
Merge tag 'hwmon-for-linus-v4.8' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging
Pull hwmon updates from Guenter Roeck:
- New drivers for FTS BMC "Teutates", TI INA3221, and Sensirion SHT3x.
- Added support for Microchip MCP9808 and TI TMP461.
- Cleanup and minor fixes in various drivers.
* tag 'hwmon-for-linus-v4.8' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging: (37 commits)
Documentation: dtb: xgene: Add hwmon dts binding documentation
hwmon: (ftsteutates) Remove unused including <linux/version.h>
hwmon: (adt7411) set bit 3 in CFG1 register
hwmon: Add driver for FTS BMC chip "Teutates"
hwmon: (sht3x) add humidity heater element control
hwmon: (jc42) Add support for generic JC-42.4 devicetree binding
dt/bindings: Add bindings for JC-42.4 compatible temperature sensors
hwmon: (tmp102) Convert to use regmap, and drop local cache
hwmon: (tmp102) Rework chip configuration
hwmon: (tmp102) Improve handling of initial read delay
hwmon: (lm90) Drop unnecessary else statements
hwmon: (lm90) Use bool for valid flag
hwmon: (lm90) Read limit registers only once
hwmon: (lm90) Simplify read functions
hwmon: (lm90) Use devm_hwmon_device_register_with_groups
hwmon: (lm90) Use devm_add_action for cleanup
hwmon: (lm75) Convert to use regmap
hwmon: (lm75) Add update_interval attribute
hwmon: (lm75) Drop lm75_read_value and lm75_write_value
hwmon: (lm75) Handle cleanup with devm_add_action
...
27 files changed, 2964 insertions, 606 deletions
diff --git a/Documentation/devicetree/bindings/hwmon/apm-xgene-hwmon.txt b/Documentation/devicetree/bindings/hwmon/apm-xgene-hwmon.txt new file mode 100644 index 000000000000..59b38557f1bb --- /dev/null +++ b/Documentation/devicetree/bindings/hwmon/apm-xgene-hwmon.txt | |||
@@ -0,0 +1,14 @@ | |||
1 | APM X-Gene hwmon driver | ||
2 | |||
3 | APM X-Gene SOC sensors are accessed over the "SLIMpro" mailbox. | ||
4 | |||
5 | Required properties : | ||
6 | - compatible : should be "apm,xgene-slimpro-hwmon" | ||
7 | - mboxes : use the label reference for the mailbox as the first parameter. | ||
8 | The second parameter is the channel number. | ||
9 | |||
10 | Example : | ||
11 | hwmonslimpro { | ||
12 | compatible = "apm,xgene-slimpro-hwmon"; | ||
13 | mboxes = <&mailbox 7>; | ||
14 | }; | ||
diff --git a/Documentation/devicetree/bindings/hwmon/jc42.txt b/Documentation/devicetree/bindings/hwmon/jc42.txt new file mode 100644 index 000000000000..07a250498fbb --- /dev/null +++ b/Documentation/devicetree/bindings/hwmon/jc42.txt | |||
@@ -0,0 +1,42 @@ | |||
1 | Properties for Jedec JC-42.4 compatible temperature sensors | ||
2 | |||
3 | Required properties: | ||
4 | - compatible: May include a device-specific string consisting of the | ||
5 | manufacturer and the name of the chip. A list of supported | ||
6 | chip names follows. | ||
7 | Must include "jedec,jc-42.4-temp" for any Jedec JC-42.4 | ||
8 | compatible temperature sensor. | ||
9 | |||
10 | Supported chip names: | ||
11 | adi,adt7408 | ||
12 | atmel,at30ts00 | ||
13 | atmel,at30tse004 | ||
14 | onnn,cat6095 | ||
15 | onnn,cat34ts02 | ||
16 | maxim,max6604 | ||
17 | microchip,mcp9804 | ||
18 | microchip,mcp9805 | ||
19 | microchip,mcp9808 | ||
20 | microchip,mcp98243 | ||
21 | microchip,mcp98244 | ||
22 | microchip,mcp9843 | ||
23 | nxp,se97 | ||
24 | nxp,se98 | ||
25 | st,stts2002 | ||
26 | st,stts2004 | ||
27 | st,stts3000 | ||
28 | st,stts424 | ||
29 | st,stts424e | ||
30 | idt,tse2002 | ||
31 | idt,tse2004 | ||
32 | idt,ts3000 | ||
33 | idt,ts3001 | ||
34 | |||
35 | - reg: I2C address | ||
36 | |||
37 | Example: | ||
38 | |||
39 | temp-sensor@1a { | ||
40 | compatible = "jedec,jc-42.4-temp"; | ||
41 | reg = <0x1a>; | ||
42 | }; | ||
diff --git a/Documentation/hwmon/abituguru b/Documentation/hwmon/abituguru index f1d4fe4c366c..44013d23b3f0 100644 --- a/Documentation/hwmon/abituguru +++ b/Documentation/hwmon/abituguru | |||
@@ -24,7 +24,7 @@ Supported chips: | |||
24 | AW9D-MAX) (2) | 24 | AW9D-MAX) (2) |
25 | 1) For revisions 2 and 3 uGuru's the driver can autodetect the | 25 | 1) For revisions 2 and 3 uGuru's the driver can autodetect the |
26 | sensortype (Volt or Temp) for bank1 sensors, for revision 1 uGuru's | 26 | sensortype (Volt or Temp) for bank1 sensors, for revision 1 uGuru's |
27 | this doesnot always work. For these uGuru's the autodection can | 27 | this does not always work. For these uGuru's the autodetection can |
28 | be overridden with the bank1_types module param. For all 3 known | 28 | be overridden with the bank1_types module param. For all 3 known |
29 | revison 1 motherboards the correct use of this param is: | 29 | revison 1 motherboards the correct use of this param is: |
30 | bank1_types=1,1,0,0,0,0,0,2,0,0,0,0,2,0,0,1 | 30 | bank1_types=1,1,0,0,0,0,0,2,0,0,0,0,2,0,0,1 |
diff --git a/Documentation/hwmon/ftsteutates b/Documentation/hwmon/ftsteutates new file mode 100644 index 000000000000..2a1bf69c6a26 --- /dev/null +++ b/Documentation/hwmon/ftsteutates | |||
@@ -0,0 +1,23 @@ | |||
1 | Kernel driver ftsteutates | ||
2 | ===================== | ||
3 | |||
4 | Supported chips: | ||
5 | * FTS Teutates | ||
6 | Prefix: 'ftsteutates' | ||
7 | Addresses scanned: I2C 0x73 (7-Bit) | ||
8 | |||
9 | Author: Thilo Cestonaro <thilo.cestonaro@ts.fujitsu.com> | ||
10 | |||
11 | |||
12 | Description | ||
13 | ----------- | ||
14 | The BMC Teutates is the Eleventh generation of Superior System | ||
15 | monitoring and thermal management solution. It is builds on the basic | ||
16 | functionality of the BMC Theseus and contains several new features and | ||
17 | enhancements. It can monitor up to 4 voltages, 16 temperatures and | ||
18 | 8 fans. It also contains an integrated watchdog which is currently | ||
19 | implemented in this driver. | ||
20 | |||
21 | Specification of the chip can be found here: | ||
22 | ftp:///pub/Mainboard-OEM-Sales/Services/Software&Tools/Linux_SystemMonitoring&Watchdog&GPIO/BMC-Teutates_Specification_V1.21.pdf | ||
23 | ftp:///pub/Mainboard-OEM-Sales/Services/Software&Tools/Linux_SystemMonitoring&Watchdog&GPIO/Fujitsu_mainboards-1-Sensors_HowTo-en-US.pdf | ||
diff --git a/Documentation/hwmon/ina3221 b/Documentation/hwmon/ina3221 new file mode 100644 index 000000000000..0ff74854cb2e --- /dev/null +++ b/Documentation/hwmon/ina3221 | |||
@@ -0,0 +1,35 @@ | |||
1 | Kernel driver ina3221 | ||
2 | ===================== | ||
3 | |||
4 | Supported chips: | ||
5 | * Texas Instruments INA3221 | ||
6 | Prefix: 'ina3221' | ||
7 | Addresses: I2C 0x40 - 0x43 | ||
8 | Datasheet: Publicly available at the Texas Instruments website | ||
9 | http://www.ti.com/ | ||
10 | |||
11 | Author: Andrew F. Davis <afd@ti.com> | ||
12 | |||
13 | Description | ||
14 | ----------- | ||
15 | |||
16 | The Texas Instruments INA3221 monitors voltage, current, and power on the high | ||
17 | side of up to three D.C. power supplies. The INA3221 monitors both shunt drop | ||
18 | and supply voltage, with programmable conversion times and averaging, current | ||
19 | and power are calculated host-side from these. | ||
20 | |||
21 | Sysfs entries | ||
22 | ------------- | ||
23 | |||
24 | in[123]_input Bus voltage(mV) channels | ||
25 | curr[123]_input Current(mA) measurement channels | ||
26 | shunt[123]_resistor Shunt resistance(uOhm) channels | ||
27 | curr[123]_crit Critical alert current(mA) setting, activates the | ||
28 | corresponding alarm when the respective current | ||
29 | is above this value | ||
30 | curr[123]_crit_alarm Critical alert current limit exceeded | ||
31 | curr[123]_max Warning alert current(mA) setting, activates the | ||
32 | corresponding alarm when the respective current | ||
33 | average is above this value. | ||
34 | curr[123]_max_alarm Warning alert current limit exceeded | ||
35 | in[456]_input Shunt voltage(uV) for channels 1, 2, and 3 respectively | ||
diff --git a/Documentation/hwmon/jc42 b/Documentation/hwmon/jc42 index f7f1830a2566..b4b671f22453 100644 --- a/Documentation/hwmon/jc42 +++ b/Documentation/hwmon/jc42 | |||
@@ -18,10 +18,11 @@ Supported chips: | |||
18 | * Maxim MAX6604 | 18 | * Maxim MAX6604 |
19 | Datasheets: | 19 | Datasheets: |
20 | http://datasheets.maxim-ic.com/en/ds/MAX6604.pdf | 20 | http://datasheets.maxim-ic.com/en/ds/MAX6604.pdf |
21 | * Microchip MCP9804, MCP9805, MCP98242, MCP98243, MCP98244, MCP9843 | 21 | * Microchip MCP9804, MCP9805, MCP9808, MCP98242, MCP98243, MCP98244, MCP9843 |
22 | Datasheets: | 22 | Datasheets: |
23 | http://ww1.microchip.com/downloads/en/DeviceDoc/22203C.pdf | 23 | http://ww1.microchip.com/downloads/en/DeviceDoc/22203C.pdf |
24 | http://ww1.microchip.com/downloads/en/DeviceDoc/21977b.pdf | 24 | http://ww1.microchip.com/downloads/en/DeviceDoc/21977b.pdf |
25 | http://ww1.microchip.com/downloads/en/DeviceDoc/25095A.pdf | ||
25 | http://ww1.microchip.com/downloads/en/DeviceDoc/21996a.pdf | 26 | http://ww1.microchip.com/downloads/en/DeviceDoc/21996a.pdf |
26 | http://ww1.microchip.com/downloads/en/DeviceDoc/22153c.pdf | 27 | http://ww1.microchip.com/downloads/en/DeviceDoc/22153c.pdf |
27 | http://ww1.microchip.com/downloads/en/DeviceDoc/22327A.pdf | 28 | http://ww1.microchip.com/downloads/en/DeviceDoc/22327A.pdf |
diff --git a/Documentation/hwmon/max1668 b/Documentation/hwmon/max1668 index 0616ed9758df..8f9d570dbfec 100644 --- a/Documentation/hwmon/max1668 +++ b/Documentation/hwmon/max1668 | |||
@@ -17,7 +17,7 @@ This driver implements support for the Maxim MAX1668, MAX1805 and MAX1989 | |||
17 | chips. | 17 | chips. |
18 | 18 | ||
19 | The three devices are very similar, but the MAX1805 has a reduced feature | 19 | The three devices are very similar, but the MAX1805 has a reduced feature |
20 | set; only two remote temperature inputs vs the four avaible on the other | 20 | set; only two remote temperature inputs vs the four available on the other |
21 | two ICs. | 21 | two ICs. |
22 | 22 | ||
23 | The driver is able to distinguish between the devices and creates sysfs | 23 | The driver is able to distinguish between the devices and creates sysfs |
diff --git a/Documentation/hwmon/sht3x b/Documentation/hwmon/sht3x new file mode 100644 index 000000000000..b0d88184f48e --- /dev/null +++ b/Documentation/hwmon/sht3x | |||
@@ -0,0 +1,76 @@ | |||
1 | Kernel driver sht3x | ||
2 | =================== | ||
3 | |||
4 | Supported chips: | ||
5 | * Sensirion SHT3x-DIS | ||
6 | Prefix: 'sht3x' | ||
7 | Addresses scanned: none | ||
8 | Datasheet: http://www.sensirion.com/fileadmin/user_upload/customers/sensirion/Dokumente/Humidity/Sensirion_Humidity_Datasheet_SHT3x_DIS.pdf | ||
9 | |||
10 | Author: | ||
11 | David Frey <david.frey@sensirion.com> | ||
12 | Pascal Sachs <pascal.sachs@sensirion.com> | ||
13 | |||
14 | Description | ||
15 | ----------- | ||
16 | |||
17 | This driver implements support for the Sensirion SHT3x-DIS chip, a humidity | ||
18 | and temperature sensor. Temperature is measured in degrees celsius, relative | ||
19 | humidity is expressed as a percentage. In the sysfs interface, all values are | ||
20 | scaled by 1000, i.e. the value for 31.5 degrees celsius is 31500. | ||
21 | |||
22 | The device communicates with the I2C protocol. Sensors can have the I2C | ||
23 | addresses 0x44 or 0x45, depending on the wiring. See | ||
24 | Documentation/i2c/instantiating-devices for methods to instantiate the device. | ||
25 | |||
26 | There are two options configurable by means of sht3x_platform_data: | ||
27 | 1. blocking (pull the I2C clock line down while performing the measurement) or | ||
28 | non-blocking mode. Blocking mode will guarantee the fastest result but | ||
29 | the I2C bus will be busy during that time. By default, non-blocking mode | ||
30 | is used. Make sure clock-stretching works properly on your device if you | ||
31 | want to use blocking mode. | ||
32 | 2. high or low accuracy. High accuracy is used by default and using it is | ||
33 | strongly recommended. | ||
34 | |||
35 | The sht3x sensor supports a single shot mode as well as 5 periodic measure | ||
36 | modes, which can be controlled with the update_interval sysfs interface. | ||
37 | The allowed update_interval in milliseconds are as follows: | ||
38 | * 0 single shot mode | ||
39 | * 2000 0.5 Hz periodic measurement | ||
40 | * 1000 1 Hz periodic measurement | ||
41 | * 500 2 Hz periodic measurement | ||
42 | * 250 4 Hz periodic measurement | ||
43 | * 100 10 Hz periodic measurement | ||
44 | |||
45 | In the periodic measure mode, the sensor automatically triggers a measurement | ||
46 | with the configured update interval on the chip. When a temperature or humidity | ||
47 | reading exceeds the configured limits, the alert attribute is set to 1 and | ||
48 | the alert pin on the sensor is set to high. | ||
49 | When the temperature and humidity readings move back between the hysteresis | ||
50 | values, the alert bit is set to 0 and the alert pin on the sensor is set to | ||
51 | low. | ||
52 | |||
53 | sysfs-Interface | ||
54 | --------------- | ||
55 | |||
56 | temp1_input: temperature input | ||
57 | humidity1_input: humidity input | ||
58 | temp1_max: temperature max value | ||
59 | temp1_max_hyst: temperature hysteresis value for max limit | ||
60 | humidity1_max: humidity max value | ||
61 | humidity1_max_hyst: humidity hysteresis value for max limit | ||
62 | temp1_min: temperature min value | ||
63 | temp1_min_hyst: temperature hysteresis value for min limit | ||
64 | humidity1_min: humidity min value | ||
65 | humidity1_min_hyst: humidity hysteresis value for min limit | ||
66 | temp1_alarm: alarm flag is set to 1 if the temperature is outside the | ||
67 | configured limits. Alarm only works in periodic measure mode | ||
68 | humidity1_alarm: alarm flag is set to 1 if the humidity is outside the | ||
69 | configured limits. Alarm only works in periodic measure mode | ||
70 | heater_enable: heater enable, heating element removes excess humidity from | ||
71 | sensor | ||
72 | 0: turned off | ||
73 | 1: turned on | ||
74 | update_interval: update interval, 0 for single shot, interval in msec | ||
75 | for periodic measurement. If the interval is not supported | ||
76 | by the sensor, the next faster interval is chosen | ||
diff --git a/Documentation/hwmon/submitting-patches b/Documentation/hwmon/submitting-patches index d201828d202f..57f60307accc 100644 --- a/Documentation/hwmon/submitting-patches +++ b/Documentation/hwmon/submitting-patches | |||
@@ -15,10 +15,15 @@ increase the chances of your change being accepted. | |||
15 | Documentation/SubmittingPatches | 15 | Documentation/SubmittingPatches |
16 | Documentation/CodingStyle | 16 | Documentation/CodingStyle |
17 | 17 | ||
18 | * If your patch generates checkpatch warnings, please refrain from explanations | 18 | * Please run your patch through 'checkpatch --strict'. There should be no |
19 | such as "I don't like that coding style". Keep in mind that each unnecessary | 19 | errors, no warnings, and few if any check messages. If there are any |
20 | warning helps hiding a real problem. If you don't like the kernel coding | 20 | messages, please be prepared to explain. |
21 | style, don't write kernel drivers. | 21 | |
22 | * If your patch generates checkpatch errors, warnings, or check messages, | ||
23 | please refrain from explanations such as "I prefer that coding style". | ||
24 | Keep in mind that each unnecessary message helps hiding a real problem, | ||
25 | and a consistent coding style makes it easier for others to understand | ||
26 | and review the code. | ||
22 | 27 | ||
23 | * Please test your patch thoroughly. We are not your test group. | 28 | * Please test your patch thoroughly. We are not your test group. |
24 | Sometimes a patch can not or not completely be tested because of missing | 29 | Sometimes a patch can not or not completely be tested because of missing |
@@ -61,15 +66,30 @@ increase the chances of your change being accepted. | |||
61 | 66 | ||
62 | * Make sure that all dependencies are listed in Kconfig. | 67 | * Make sure that all dependencies are listed in Kconfig. |
63 | 68 | ||
69 | * Please list include files in alphabetic order. | ||
70 | |||
71 | * Please align continuation lines with '(' on the previous line. | ||
72 | |||
64 | * Avoid forward declarations if you can. Rearrange the code if necessary. | 73 | * Avoid forward declarations if you can. Rearrange the code if necessary. |
65 | 74 | ||
75 | * Avoid macros to generate groups of sensor attributes. It not only confuses | ||
76 | checkpatch, but also makes it more difficult to review the code. | ||
77 | |||
66 | * Avoid calculations in macros and macro-generated functions. While such macros | 78 | * Avoid calculations in macros and macro-generated functions. While such macros |
67 | may save a line or so in the source, it obfuscates the code and makes code | 79 | may save a line or so in the source, it obfuscates the code and makes code |
68 | review more difficult. It may also result in code which is more complicated | 80 | review more difficult. It may also result in code which is more complicated |
69 | than necessary. Use inline functions or just regular functions instead. | 81 | than necessary. Use inline functions or just regular functions instead. |
70 | 82 | ||
83 | * Limit the number of kernel log messages. In general, your driver should not | ||
84 | generate an error message just because a runtime operation failed. Report | ||
85 | errors to user space instead, using an appropriate error code. Keep in mind | ||
86 | that kernel error log messages not only fill up the kernel log, but also are | ||
87 | printed synchronously, most likely with interrupt disabled, often to a serial | ||
88 | console. Excessive logging can seriously affect system performance. | ||
89 | |||
71 | * Use devres functions whenever possible to allocate resources. For rationale | 90 | * Use devres functions whenever possible to allocate resources. For rationale |
72 | and supported functions, please see Documentation/driver-model/devres.txt. | 91 | and supported functions, please see Documentation/driver-model/devres.txt. |
92 | If a function is not supported by devres, consider using devm_add_action(). | ||
73 | 93 | ||
74 | * If the driver has a detect function, make sure it is silent. Debug messages | 94 | * If the driver has a detect function, make sure it is silent. Debug messages |
75 | and messages printed after a successful detection are acceptable, but it | 95 | and messages printed after a successful detection are acceptable, but it |
@@ -96,8 +116,16 @@ increase the chances of your change being accepted. | |||
96 | writing to it might cause a bad misconfiguration. | 116 | writing to it might cause a bad misconfiguration. |
97 | 117 | ||
98 | * Make sure there are no race conditions in the probe function. Specifically, | 118 | * Make sure there are no race conditions in the probe function. Specifically, |
99 | completely initialize your chip first, then create sysfs entries and register | 119 | completely initialize your chip and your driver first, then register with |
100 | with the hwmon subsystem. | 120 | the hwmon subsystem. |
121 | |||
122 | * Use devm_hwmon_device_register_with_groups() or, if your driver needs a remove | ||
123 | function, hwmon_device_register_with_groups() to register your driver with the | ||
124 | hwmon subsystem. Try using devm_add_action() instead of a remove function if | ||
125 | possible. Do not use hwmon_device_register(). | ||
126 | |||
127 | * Your driver should be buildable as module. If not, please be prepared to | ||
128 | explain why it has to be built into the kernel. | ||
101 | 129 | ||
102 | * Do not provide support for deprecated sysfs attributes. | 130 | * Do not provide support for deprecated sysfs attributes. |
103 | 131 | ||
diff --git a/Documentation/hwmon/tmp401 b/Documentation/hwmon/tmp401 index 711f75e189eb..2d9ca42213cf 100644 --- a/Documentation/hwmon/tmp401 +++ b/Documentation/hwmon/tmp401 | |||
@@ -22,6 +22,9 @@ Supported chips: | |||
22 | Prefix: 'tmp435' | 22 | Prefix: 'tmp435' |
23 | Addresses scanned: I2C 0x48 - 0x4f | 23 | Addresses scanned: I2C 0x48 - 0x4f |
24 | Datasheet: http://focus.ti.com/docs/prod/folders/print/tmp435.html | 24 | Datasheet: http://focus.ti.com/docs/prod/folders/print/tmp435.html |
25 | * Texas Instruments TMP461 | ||
26 | Prefix: 'tmp461' | ||
27 | Datasheet: http://www.ti.com/product/tmp461 | ||
25 | 28 | ||
26 | Authors: | 29 | Authors: |
27 | Hans de Goede <hdegoede@redhat.com> | 30 | Hans de Goede <hdegoede@redhat.com> |
@@ -31,8 +34,8 @@ Description | |||
31 | ----------- | 34 | ----------- |
32 | 35 | ||
33 | This driver implements support for Texas Instruments TMP401, TMP411, | 36 | This driver implements support for Texas Instruments TMP401, TMP411, |
34 | TMP431, TMP432 and TMP435 chips. These chips implement one or two remote | 37 | TMP431, TMP432, TMP435, and TMP461 chips. These chips implement one or two |
35 | and one local temperature sensors. Temperature is measured in degrees | 38 | remote and one local temperature sensors. Temperature is measured in degrees |
36 | Celsius. Resolution of the remote sensor is 0.0625 degree. Local | 39 | Celsius. Resolution of the remote sensor is 0.0625 degree. Local |
37 | sensor resolution can be set to 0.5, 0.25, 0.125 or 0.0625 degree (not | 40 | sensor resolution can be set to 0.5, 0.25, 0.125 or 0.0625 degree (not |
38 | supported by the driver so far, so using the default resolution of 0.5 | 41 | supported by the driver so far, so using the default resolution of 0.5 |
@@ -55,3 +58,10 @@ some additional features. | |||
55 | 58 | ||
56 | TMP432 is compatible with TMP401 and TMP431. It supports two external | 59 | TMP432 is compatible with TMP401 and TMP431. It supports two external |
57 | temperature sensors. | 60 | temperature sensors. |
61 | |||
62 | TMP461 is compatible with TMP401. It supports offset correction | ||
63 | that is applied to the remote sensor. | ||
64 | |||
65 | * Sensor offset values are temperature values | ||
66 | |||
67 | Exported via sysfs attribute tempX_offset | ||
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index ff940075bb90..eaf2f916d48c 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig | |||
@@ -486,6 +486,18 @@ config SENSORS_FSCHMD | |||
486 | This driver can also be built as a module. If so, the module | 486 | This driver can also be built as a module. If so, the module |
487 | will be called fschmd. | 487 | will be called fschmd. |
488 | 488 | ||
489 | config SENSORS_FTSTEUTATES | ||
490 | tristate "Fujitsu Technology Solutions sensor chip Teutates" | ||
491 | depends on I2C && WATCHDOG | ||
492 | select WATCHDOG_CORE | ||
493 | help | ||
494 | If you say yes here you get support for the Fujitsu Technology | ||
495 | Solutions (FTS) sensor chip "Teutates" including support for | ||
496 | the integrated watchdog. | ||
497 | |||
498 | This driver can also be built as a module. If so, the module | ||
499 | will be called ftsteutates. | ||
500 | |||
489 | config SENSORS_GL518SM | 501 | config SENSORS_GL518SM |
490 | tristate "Genesys Logic GL518SM" | 502 | tristate "Genesys Logic GL518SM" |
491 | depends on I2C | 503 | depends on I2C |
@@ -645,8 +657,8 @@ config SENSORS_JC42 | |||
645 | temperature sensors, which are used on many DDR3 memory modules for | 657 | temperature sensors, which are used on many DDR3 memory modules for |
646 | mobile devices and servers. Support will include, but not be limited | 658 | mobile devices and servers. Support will include, but not be limited |
647 | to, ADT7408, AT30TS00, CAT34TS02, CAT6095, MAX6604, MCP9804, MCP9805, | 659 | to, ADT7408, AT30TS00, CAT34TS02, CAT6095, MAX6604, MCP9804, MCP9805, |
648 | MCP98242, MCP98243, MCP98244, MCP9843, SE97, SE98, STTS424(E), | 660 | MCP9808, MCP98242, MCP98243, MCP98244, MCP9843, SE97, SE98, |
649 | STTS2002, STTS3000, TSE2002, TSE2004, TS3000, and TS3001. | 661 | STTS424(E), STTS2002, STTS3000, TSE2002, TSE2004, TS3000, and TS3001. |
650 | 662 | ||
651 | This driver can also be built as a module. If so, the module | 663 | This driver can also be built as a module. If so, the module |
652 | will be called jc42. | 664 | will be called jc42. |
@@ -958,6 +970,7 @@ config SENSORS_LM75 | |||
958 | tristate "National Semiconductor LM75 and compatibles" | 970 | tristate "National Semiconductor LM75 and compatibles" |
959 | depends on I2C | 971 | depends on I2C |
960 | depends on THERMAL || !THERMAL_OF | 972 | depends on THERMAL || !THERMAL_OF |
973 | select REGMAP_I2C | ||
961 | help | 974 | help |
962 | If you say yes here you get support for one common type of | 975 | If you say yes here you get support for one common type of |
963 | temperature sensor chip, with models including: | 976 | temperature sensor chip, with models including: |
@@ -1265,6 +1278,17 @@ config SENSORS_SHT21 | |||
1265 | This driver can also be built as a module. If so, the module | 1278 | This driver can also be built as a module. If so, the module |
1266 | will be called sht21. | 1279 | will be called sht21. |
1267 | 1280 | ||
1281 | config SENSORS_SHT3x | ||
1282 | tristate "Sensiron humidity and temperature sensors. SHT3x and compat." | ||
1283 | depends on I2C | ||
1284 | select CRC8 | ||
1285 | help | ||
1286 | If you say yes here you get support for the Sensiron SHT30 and SHT31 | ||
1287 | humidity and temperature sensors. | ||
1288 | |||
1289 | This driver can also be built as a module. If so, the module | ||
1290 | will be called sht3x. | ||
1291 | |||
1268 | config SENSORS_SHTC1 | 1292 | config SENSORS_SHTC1 |
1269 | tristate "Sensiron humidity and temperature sensors. SHTC1 and compat." | 1293 | tristate "Sensiron humidity and temperature sensors. SHTC1 and compat." |
1270 | depends on I2C | 1294 | depends on I2C |
@@ -1514,6 +1538,17 @@ config SENSORS_INA2XX | |||
1514 | This driver can also be built as a module. If so, the module | 1538 | This driver can also be built as a module. If so, the module |
1515 | will be called ina2xx. | 1539 | will be called ina2xx. |
1516 | 1540 | ||
1541 | config SENSORS_INA3221 | ||
1542 | tristate "Texas Instruments INA3221 Triple Power Monitor" | ||
1543 | depends on I2C | ||
1544 | select REGMAP_I2C | ||
1545 | help | ||
1546 | If you say yes here you get support for the TI INA3221 Triple Power | ||
1547 | Monitor. | ||
1548 | |||
1549 | This driver can also be built as a module. If so, the module | ||
1550 | will be called ina3221. | ||
1551 | |||
1517 | config SENSORS_TC74 | 1552 | config SENSORS_TC74 |
1518 | tristate "Microchip TC74" | 1553 | tristate "Microchip TC74" |
1519 | depends on I2C | 1554 | depends on I2C |
@@ -1538,6 +1573,7 @@ config SENSORS_TMP102 | |||
1538 | tristate "Texas Instruments TMP102" | 1573 | tristate "Texas Instruments TMP102" |
1539 | depends on I2C | 1574 | depends on I2C |
1540 | depends on THERMAL || !THERMAL_OF | 1575 | depends on THERMAL || !THERMAL_OF |
1576 | select REGMAP_I2C | ||
1541 | help | 1577 | help |
1542 | If you say yes here you get support for Texas Instruments TMP102 | 1578 | If you say yes here you get support for Texas Instruments TMP102 |
1543 | sensor chips. | 1579 | sensor chips. |
@@ -1561,7 +1597,7 @@ config SENSORS_TMP401 | |||
1561 | depends on I2C | 1597 | depends on I2C |
1562 | help | 1598 | help |
1563 | If you say yes here you get support for Texas Instruments TMP401, | 1599 | If you say yes here you get support for Texas Instruments TMP401, |
1564 | TMP411, TMP431, TMP432 and TMP435 temperature sensor chips. | 1600 | TMP411, TMP431, TMP432, TMP435, and TMP461 temperature sensor chips. |
1565 | 1601 | ||
1566 | This driver can also be built as a module. If so, the module | 1602 | This driver can also be built as a module. If so, the module |
1567 | will be called tmp401. | 1603 | will be called tmp401. |
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index 2ef5b7c4c54f..fe87d2895a97 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile | |||
@@ -62,6 +62,7 @@ obj-$(CONFIG_SENSORS_F71882FG) += f71882fg.o | |||
62 | obj-$(CONFIG_SENSORS_F75375S) += f75375s.o | 62 | obj-$(CONFIG_SENSORS_F75375S) += f75375s.o |
63 | obj-$(CONFIG_SENSORS_FAM15H_POWER) += fam15h_power.o | 63 | obj-$(CONFIG_SENSORS_FAM15H_POWER) += fam15h_power.o |
64 | obj-$(CONFIG_SENSORS_FSCHMD) += fschmd.o | 64 | obj-$(CONFIG_SENSORS_FSCHMD) += fschmd.o |
65 | obj-$(CONFIG_SENSORS_FTSTEUTATES) += ftsteutates.o | ||
65 | obj-$(CONFIG_SENSORS_G760A) += g760a.o | 66 | obj-$(CONFIG_SENSORS_G760A) += g760a.o |
66 | obj-$(CONFIG_SENSORS_G762) += g762.o | 67 | obj-$(CONFIG_SENSORS_G762) += g762.o |
67 | obj-$(CONFIG_SENSORS_GL518SM) += gl518sm.o | 68 | obj-$(CONFIG_SENSORS_GL518SM) += gl518sm.o |
@@ -77,6 +78,7 @@ obj-$(CONFIG_SENSORS_IBMPOWERNV)+= ibmpowernv.o | |||
77 | obj-$(CONFIG_SENSORS_IIO_HWMON) += iio_hwmon.o | 78 | obj-$(CONFIG_SENSORS_IIO_HWMON) += iio_hwmon.o |
78 | obj-$(CONFIG_SENSORS_INA209) += ina209.o | 79 | obj-$(CONFIG_SENSORS_INA209) += ina209.o |
79 | obj-$(CONFIG_SENSORS_INA2XX) += ina2xx.o | 80 | obj-$(CONFIG_SENSORS_INA2XX) += ina2xx.o |
81 | obj-$(CONFIG_SENSORS_INA3221) += ina3221.o | ||
80 | obj-$(CONFIG_SENSORS_IT87) += it87.o | 82 | obj-$(CONFIG_SENSORS_IT87) += it87.o |
81 | obj-$(CONFIG_SENSORS_JC42) += jc42.o | 83 | obj-$(CONFIG_SENSORS_JC42) += jc42.o |
82 | obj-$(CONFIG_SENSORS_JZ4740) += jz4740-hwmon.o | 84 | obj-$(CONFIG_SENSORS_JZ4740) += jz4740-hwmon.o |
@@ -138,6 +140,7 @@ obj-$(CONFIG_SENSORS_SCH5627) += sch5627.o | |||
138 | obj-$(CONFIG_SENSORS_SCH5636) += sch5636.o | 140 | obj-$(CONFIG_SENSORS_SCH5636) += sch5636.o |
139 | obj-$(CONFIG_SENSORS_SHT15) += sht15.o | 141 | obj-$(CONFIG_SENSORS_SHT15) += sht15.o |
140 | obj-$(CONFIG_SENSORS_SHT21) += sht21.o | 142 | obj-$(CONFIG_SENSORS_SHT21) += sht21.o |
143 | obj-$(CONFIG_SENSORS_SHT3x) += sht3x.o | ||
141 | obj-$(CONFIG_SENSORS_SHTC1) += shtc1.o | 144 | obj-$(CONFIG_SENSORS_SHTC1) += shtc1.o |
142 | obj-$(CONFIG_SENSORS_SIS5595) += sis5595.o | 145 | obj-$(CONFIG_SENSORS_SIS5595) += sis5595.o |
143 | obj-$(CONFIG_SENSORS_SMM665) += smm665.o | 146 | obj-$(CONFIG_SENSORS_SMM665) += smm665.o |
diff --git a/drivers/hwmon/ad7314.c b/drivers/hwmon/ad7314.c index 202c1fbb3407..8ea35932fbaa 100644 --- a/drivers/hwmon/ad7314.c +++ b/drivers/hwmon/ad7314.c | |||
@@ -37,7 +37,6 @@ enum ad7314_variant { | |||
37 | 37 | ||
38 | struct ad7314_data { | 38 | struct ad7314_data { |
39 | struct spi_device *spi_dev; | 39 | struct spi_device *spi_dev; |
40 | struct device *hwmon_dev; | ||
41 | u16 rx ____cacheline_aligned; | 40 | u16 rx ____cacheline_aligned; |
42 | }; | 41 | }; |
43 | 42 | ||
@@ -88,62 +87,30 @@ static ssize_t ad7314_show_temperature(struct device *dev, | |||
88 | } | 87 | } |
89 | } | 88 | } |
90 | 89 | ||
91 | static ssize_t ad7314_show_name(struct device *dev, | ||
92 | struct device_attribute *devattr, char *buf) | ||
93 | { | ||
94 | return sprintf(buf, "%s\n", to_spi_device(dev)->modalias); | ||
95 | } | ||
96 | |||
97 | static DEVICE_ATTR(name, S_IRUGO, ad7314_show_name, NULL); | ||
98 | static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, | 90 | static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, |
99 | ad7314_show_temperature, NULL, 0); | 91 | ad7314_show_temperature, NULL, 0); |
100 | 92 | ||
101 | static struct attribute *ad7314_attributes[] = { | 93 | static struct attribute *ad7314_attrs[] = { |
102 | &dev_attr_name.attr, | ||
103 | &sensor_dev_attr_temp1_input.dev_attr.attr, | 94 | &sensor_dev_attr_temp1_input.dev_attr.attr, |
104 | NULL, | 95 | NULL, |
105 | }; | 96 | }; |
106 | 97 | ||
107 | static const struct attribute_group ad7314_group = { | 98 | ATTRIBUTE_GROUPS(ad7314); |
108 | .attrs = ad7314_attributes, | ||
109 | }; | ||
110 | 99 | ||
111 | static int ad7314_probe(struct spi_device *spi_dev) | 100 | static int ad7314_probe(struct spi_device *spi_dev) |
112 | { | 101 | { |
113 | int ret; | ||
114 | struct ad7314_data *chip; | 102 | struct ad7314_data *chip; |
103 | struct device *hwmon_dev; | ||
115 | 104 | ||
116 | chip = devm_kzalloc(&spi_dev->dev, sizeof(*chip), GFP_KERNEL); | 105 | chip = devm_kzalloc(&spi_dev->dev, sizeof(*chip), GFP_KERNEL); |
117 | if (chip == NULL) | 106 | if (chip == NULL) |
118 | return -ENOMEM; | 107 | return -ENOMEM; |
119 | 108 | ||
120 | spi_set_drvdata(spi_dev, chip); | ||
121 | |||
122 | ret = sysfs_create_group(&spi_dev->dev.kobj, &ad7314_group); | ||
123 | if (ret < 0) | ||
124 | return ret; | ||
125 | |||
126 | chip->hwmon_dev = hwmon_device_register(&spi_dev->dev); | ||
127 | if (IS_ERR(chip->hwmon_dev)) { | ||
128 | ret = PTR_ERR(chip->hwmon_dev); | ||
129 | goto error_remove_group; | ||
130 | } | ||
131 | chip->spi_dev = spi_dev; | 109 | chip->spi_dev = spi_dev; |
132 | 110 | hwmon_dev = devm_hwmon_device_register_with_groups(&spi_dev->dev, | |
133 | return 0; | 111 | spi_dev->modalias, |
134 | error_remove_group: | 112 | chip, ad7314_groups); |
135 | sysfs_remove_group(&spi_dev->dev.kobj, &ad7314_group); | 113 | return PTR_ERR_OR_ZERO(hwmon_dev); |
136 | return ret; | ||
137 | } | ||
138 | |||
139 | static int ad7314_remove(struct spi_device *spi_dev) | ||
140 | { | ||
141 | struct ad7314_data *chip = spi_get_drvdata(spi_dev); | ||
142 | |||
143 | hwmon_device_unregister(chip->hwmon_dev); | ||
144 | sysfs_remove_group(&spi_dev->dev.kobj, &ad7314_group); | ||
145 | |||
146 | return 0; | ||
147 | } | 114 | } |
148 | 115 | ||
149 | static const struct spi_device_id ad7314_id[] = { | 116 | static const struct spi_device_id ad7314_id[] = { |
@@ -159,7 +126,6 @@ static struct spi_driver ad7314_driver = { | |||
159 | .name = "ad7314", | 126 | .name = "ad7314", |
160 | }, | 127 | }, |
161 | .probe = ad7314_probe, | 128 | .probe = ad7314_probe, |
162 | .remove = ad7314_remove, | ||
163 | .id_table = ad7314_id, | 129 | .id_table = ad7314_id, |
164 | }; | 130 | }; |
165 | 131 | ||
diff --git a/drivers/hwmon/ads7871.c b/drivers/hwmon/ads7871.c index 4fd9e4de1972..59bd7b9e1772 100644 --- a/drivers/hwmon/ads7871.c +++ b/drivers/hwmon/ads7871.c | |||
@@ -66,14 +66,12 @@ | |||
66 | #include <linux/hwmon.h> | 66 | #include <linux/hwmon.h> |
67 | #include <linux/hwmon-sysfs.h> | 67 | #include <linux/hwmon-sysfs.h> |
68 | #include <linux/err.h> | 68 | #include <linux/err.h> |
69 | #include <linux/mutex.h> | ||
70 | #include <linux/delay.h> | 69 | #include <linux/delay.h> |
71 | 70 | ||
72 | #define DEVICE_NAME "ads7871" | 71 | #define DEVICE_NAME "ads7871" |
73 | 72 | ||
74 | struct ads7871_data { | 73 | struct ads7871_data { |
75 | struct device *hwmon_dev; | 74 | struct spi_device *spi; |
76 | struct mutex update_lock; | ||
77 | }; | 75 | }; |
78 | 76 | ||
79 | static int ads7871_read_reg8(struct spi_device *spi, int reg) | 77 | static int ads7871_read_reg8(struct spi_device *spi, int reg) |
@@ -101,7 +99,8 @@ static int ads7871_write_reg8(struct spi_device *spi, int reg, u8 val) | |||
101 | static ssize_t show_voltage(struct device *dev, | 99 | static ssize_t show_voltage(struct device *dev, |
102 | struct device_attribute *da, char *buf) | 100 | struct device_attribute *da, char *buf) |
103 | { | 101 | { |
104 | struct spi_device *spi = to_spi_device(dev); | 102 | struct ads7871_data *pdata = dev_get_drvdata(dev); |
103 | struct spi_device *spi = pdata->spi; | ||
105 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); | 104 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); |
106 | int ret, val, i = 0; | 105 | int ret, val, i = 0; |
107 | uint8_t channel, mux_cnv; | 106 | uint8_t channel, mux_cnv; |
@@ -139,12 +138,6 @@ static ssize_t show_voltage(struct device *dev, | |||
139 | } | 138 | } |
140 | } | 139 | } |
141 | 140 | ||
142 | static ssize_t ads7871_show_name(struct device *dev, | ||
143 | struct device_attribute *devattr, char *buf) | ||
144 | { | ||
145 | return sprintf(buf, "%s\n", to_spi_device(dev)->modalias); | ||
146 | } | ||
147 | |||
148 | static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, show_voltage, NULL, 0); | 141 | static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, show_voltage, NULL, 0); |
149 | static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, show_voltage, NULL, 1); | 142 | static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, show_voltage, NULL, 1); |
150 | static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, show_voltage, NULL, 2); | 143 | static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, show_voltage, NULL, 2); |
@@ -154,9 +147,7 @@ static SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, show_voltage, NULL, 5); | |||
154 | static SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, show_voltage, NULL, 6); | 147 | static SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, show_voltage, NULL, 6); |
155 | static SENSOR_DEVICE_ATTR(in7_input, S_IRUGO, show_voltage, NULL, 7); | 148 | static SENSOR_DEVICE_ATTR(in7_input, S_IRUGO, show_voltage, NULL, 7); |
156 | 149 | ||
157 | static DEVICE_ATTR(name, S_IRUGO, ads7871_show_name, NULL); | 150 | static struct attribute *ads7871_attrs[] = { |
158 | |||
159 | static struct attribute *ads7871_attributes[] = { | ||
160 | &sensor_dev_attr_in0_input.dev_attr.attr, | 151 | &sensor_dev_attr_in0_input.dev_attr.attr, |
161 | &sensor_dev_attr_in1_input.dev_attr.attr, | 152 | &sensor_dev_attr_in1_input.dev_attr.attr, |
162 | &sensor_dev_attr_in2_input.dev_attr.attr, | 153 | &sensor_dev_attr_in2_input.dev_attr.attr, |
@@ -165,21 +156,18 @@ static struct attribute *ads7871_attributes[] = { | |||
165 | &sensor_dev_attr_in5_input.dev_attr.attr, | 156 | &sensor_dev_attr_in5_input.dev_attr.attr, |
166 | &sensor_dev_attr_in6_input.dev_attr.attr, | 157 | &sensor_dev_attr_in6_input.dev_attr.attr, |
167 | &sensor_dev_attr_in7_input.dev_attr.attr, | 158 | &sensor_dev_attr_in7_input.dev_attr.attr, |
168 | &dev_attr_name.attr, | ||
169 | NULL | 159 | NULL |
170 | }; | 160 | }; |
171 | 161 | ||
172 | static const struct attribute_group ads7871_group = { | 162 | ATTRIBUTE_GROUPS(ads7871); |
173 | .attrs = ads7871_attributes, | ||
174 | }; | ||
175 | 163 | ||
176 | static int ads7871_probe(struct spi_device *spi) | 164 | static int ads7871_probe(struct spi_device *spi) |
177 | { | 165 | { |
178 | int ret, err; | 166 | struct device *dev = &spi->dev; |
167 | int ret; | ||
179 | uint8_t val; | 168 | uint8_t val; |
180 | struct ads7871_data *pdata; | 169 | struct ads7871_data *pdata; |
181 | 170 | struct device *hwmon_dev; | |
182 | dev_dbg(&spi->dev, "probe\n"); | ||
183 | 171 | ||
184 | /* Configure the SPI bus */ | 172 | /* Configure the SPI bus */ |
185 | spi->mode = (SPI_MODE_0); | 173 | spi->mode = (SPI_MODE_0); |
@@ -193,7 +181,7 @@ static int ads7871_probe(struct spi_device *spi) | |||
193 | ads7871_write_reg8(spi, REG_OSC_CONTROL, val); | 181 | ads7871_write_reg8(spi, REG_OSC_CONTROL, val); |
194 | ret = ads7871_read_reg8(spi, REG_OSC_CONTROL); | 182 | ret = ads7871_read_reg8(spi, REG_OSC_CONTROL); |
195 | 183 | ||
196 | dev_dbg(&spi->dev, "REG_OSC_CONTROL write:%x, read:%x\n", val, ret); | 184 | dev_dbg(dev, "REG_OSC_CONTROL write:%x, read:%x\n", val, ret); |
197 | /* | 185 | /* |
198 | * because there is no other error checking on an SPI bus | 186 | * because there is no other error checking on an SPI bus |
199 | * we need to make sure we really have a chip | 187 | * we need to make sure we really have a chip |
@@ -201,46 +189,23 @@ static int ads7871_probe(struct spi_device *spi) | |||
201 | if (val != ret) | 189 | if (val != ret) |
202 | return -ENODEV; | 190 | return -ENODEV; |
203 | 191 | ||
204 | pdata = devm_kzalloc(&spi->dev, sizeof(struct ads7871_data), | 192 | pdata = devm_kzalloc(dev, sizeof(struct ads7871_data), GFP_KERNEL); |
205 | GFP_KERNEL); | ||
206 | if (!pdata) | 193 | if (!pdata) |
207 | return -ENOMEM; | 194 | return -ENOMEM; |
208 | 195 | ||
209 | err = sysfs_create_group(&spi->dev.kobj, &ads7871_group); | 196 | pdata->spi = spi; |
210 | if (err < 0) | ||
211 | return err; | ||
212 | |||
213 | spi_set_drvdata(spi, pdata); | ||
214 | 197 | ||
215 | pdata->hwmon_dev = hwmon_device_register(&spi->dev); | 198 | hwmon_dev = devm_hwmon_device_register_with_groups(dev, spi->modalias, |
216 | if (IS_ERR(pdata->hwmon_dev)) { | 199 | pdata, |
217 | err = PTR_ERR(pdata->hwmon_dev); | 200 | ads7871_groups); |
218 | goto error_remove; | 201 | return PTR_ERR_OR_ZERO(hwmon_dev); |
219 | } | ||
220 | |||
221 | return 0; | ||
222 | |||
223 | error_remove: | ||
224 | sysfs_remove_group(&spi->dev.kobj, &ads7871_group); | ||
225 | return err; | ||
226 | } | ||
227 | |||
228 | static int ads7871_remove(struct spi_device *spi) | ||
229 | { | ||
230 | struct ads7871_data *pdata = spi_get_drvdata(spi); | ||
231 | |||
232 | hwmon_device_unregister(pdata->hwmon_dev); | ||
233 | sysfs_remove_group(&spi->dev.kobj, &ads7871_group); | ||
234 | return 0; | ||
235 | } | 202 | } |
236 | 203 | ||
237 | static struct spi_driver ads7871_driver = { | 204 | static struct spi_driver ads7871_driver = { |
238 | .driver = { | 205 | .driver = { |
239 | .name = DEVICE_NAME, | 206 | .name = DEVICE_NAME, |
240 | }, | 207 | }, |
241 | |||
242 | .probe = ads7871_probe, | 208 | .probe = ads7871_probe, |
243 | .remove = ads7871_remove, | ||
244 | }; | 209 | }; |
245 | 210 | ||
246 | module_spi_driver(ads7871_driver); | 211 | module_spi_driver(ads7871_driver); |
diff --git a/drivers/hwmon/adt7411.c b/drivers/hwmon/adt7411.c index 827c03703128..a7f886961830 100644 --- a/drivers/hwmon/adt7411.c +++ b/drivers/hwmon/adt7411.c | |||
@@ -30,6 +30,7 @@ | |||
30 | 30 | ||
31 | #define ADT7411_REG_CFG1 0x18 | 31 | #define ADT7411_REG_CFG1 0x18 |
32 | #define ADT7411_CFG1_START_MONITOR (1 << 0) | 32 | #define ADT7411_CFG1_START_MONITOR (1 << 0) |
33 | #define ADT7411_CFG1_RESERVED_BIT3 (1 << 3) | ||
33 | 34 | ||
34 | #define ADT7411_REG_CFG2 0x19 | 35 | #define ADT7411_REG_CFG2 0x19 |
35 | #define ADT7411_CFG2_DISABLE_AVG (1 << 5) | 36 | #define ADT7411_CFG2_DISABLE_AVG (1 << 5) |
@@ -296,8 +297,10 @@ static int adt7411_probe(struct i2c_client *client, | |||
296 | mutex_init(&data->device_lock); | 297 | mutex_init(&data->device_lock); |
297 | mutex_init(&data->update_lock); | 298 | mutex_init(&data->update_lock); |
298 | 299 | ||
300 | /* According to the datasheet, we must only write 1 to bit 3 */ | ||
299 | ret = adt7411_modify_bit(client, ADT7411_REG_CFG1, | 301 | ret = adt7411_modify_bit(client, ADT7411_REG_CFG1, |
300 | ADT7411_CFG1_START_MONITOR, 1); | 302 | ADT7411_CFG1_RESERVED_BIT3 |
303 | | ADT7411_CFG1_START_MONITOR, 1); | ||
301 | if (ret < 0) | 304 | if (ret < 0) |
302 | return ret; | 305 | return ret; |
303 | 306 | ||
diff --git a/drivers/hwmon/dell-smm-hwmon.c b/drivers/hwmon/dell-smm-hwmon.c index 2ac87d553e22..acf9c0361d9f 100644 --- a/drivers/hwmon/dell-smm-hwmon.c +++ b/drivers/hwmon/dell-smm-hwmon.c | |||
@@ -81,6 +81,7 @@ static bool disallow_fan_type_call; | |||
81 | #define I8K_HWMON_HAVE_TEMP4 (1 << 3) | 81 | #define I8K_HWMON_HAVE_TEMP4 (1 << 3) |
82 | #define I8K_HWMON_HAVE_FAN1 (1 << 4) | 82 | #define I8K_HWMON_HAVE_FAN1 (1 << 4) |
83 | #define I8K_HWMON_HAVE_FAN2 (1 << 5) | 83 | #define I8K_HWMON_HAVE_FAN2 (1 << 5) |
84 | #define I8K_HWMON_HAVE_FAN3 (1 << 6) | ||
84 | 85 | ||
85 | MODULE_AUTHOR("Massimo Dal Zotto (dz@debian.org)"); | 86 | MODULE_AUTHOR("Massimo Dal Zotto (dz@debian.org)"); |
86 | MODULE_AUTHOR("Pali Rohár <pali.rohar@gmail.com>"); | 87 | MODULE_AUTHOR("Pali Rohár <pali.rohar@gmail.com>"); |
@@ -139,6 +140,14 @@ static int i8k_smm(struct smm_regs *regs) | |||
139 | int eax = regs->eax; | 140 | int eax = regs->eax; |
140 | cpumask_var_t old_mask; | 141 | cpumask_var_t old_mask; |
141 | 142 | ||
143 | #ifdef DEBUG | ||
144 | int ebx = regs->ebx; | ||
145 | unsigned long duration; | ||
146 | ktime_t calltime, delta, rettime; | ||
147 | |||
148 | calltime = ktime_get(); | ||
149 | #endif | ||
150 | |||
142 | /* SMM requires CPU 0 */ | 151 | /* SMM requires CPU 0 */ |
143 | if (!alloc_cpumask_var(&old_mask, GFP_KERNEL)) | 152 | if (!alloc_cpumask_var(&old_mask, GFP_KERNEL)) |
144 | return -ENOMEM; | 153 | return -ENOMEM; |
@@ -210,6 +219,15 @@ static int i8k_smm(struct smm_regs *regs) | |||
210 | out: | 219 | out: |
211 | set_cpus_allowed_ptr(current, old_mask); | 220 | set_cpus_allowed_ptr(current, old_mask); |
212 | free_cpumask_var(old_mask); | 221 | free_cpumask_var(old_mask); |
222 | |||
223 | #ifdef DEBUG | ||
224 | rettime = ktime_get(); | ||
225 | delta = ktime_sub(rettime, calltime); | ||
226 | duration = ktime_to_ns(delta) >> 10; | ||
227 | pr_debug("smm(0x%.4x 0x%.4x) = 0x%.4x (took %7lu usecs)\n", eax, ebx, | ||
228 | (rc ? 0xffff : regs->eax & 0xffff), duration); | ||
229 | #endif | ||
230 | |||
213 | return rc; | 231 | return rc; |
214 | } | 232 | } |
215 | 233 | ||
@@ -252,7 +270,7 @@ static int _i8k_get_fan_type(int fan) | |||
252 | static int i8k_get_fan_type(int fan) | 270 | static int i8k_get_fan_type(int fan) |
253 | { | 271 | { |
254 | /* I8K_SMM_GET_FAN_TYPE SMM call is expensive, so cache values */ | 272 | /* I8K_SMM_GET_FAN_TYPE SMM call is expensive, so cache values */ |
255 | static int types[2] = { INT_MIN, INT_MIN }; | 273 | static int types[3] = { INT_MIN, INT_MIN, INT_MIN }; |
256 | 274 | ||
257 | if (types[fan] == INT_MIN) | 275 | if (types[fan] == INT_MIN) |
258 | types[fan] = _i8k_get_fan_type(fan); | 276 | types[fan] = _i8k_get_fan_type(fan); |
@@ -719,6 +737,12 @@ static SENSOR_DEVICE_ATTR(fan2_label, S_IRUGO, i8k_hwmon_show_fan_label, NULL, | |||
719 | 1); | 737 | 1); |
720 | static SENSOR_DEVICE_ATTR(pwm2, S_IRUGO | S_IWUSR, i8k_hwmon_show_pwm, | 738 | static SENSOR_DEVICE_ATTR(pwm2, S_IRUGO | S_IWUSR, i8k_hwmon_show_pwm, |
721 | i8k_hwmon_set_pwm, 1); | 739 | i8k_hwmon_set_pwm, 1); |
740 | static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, i8k_hwmon_show_fan, NULL, | ||
741 | 2); | ||
742 | static SENSOR_DEVICE_ATTR(fan3_label, S_IRUGO, i8k_hwmon_show_fan_label, NULL, | ||
743 | 2); | ||
744 | static SENSOR_DEVICE_ATTR(pwm3, S_IRUGO | S_IWUSR, i8k_hwmon_show_pwm, | ||
745 | i8k_hwmon_set_pwm, 2); | ||
722 | 746 | ||
723 | static struct attribute *i8k_attrs[] = { | 747 | static struct attribute *i8k_attrs[] = { |
724 | &sensor_dev_attr_temp1_input.dev_attr.attr, /* 0 */ | 748 | &sensor_dev_attr_temp1_input.dev_attr.attr, /* 0 */ |
@@ -735,6 +759,9 @@ static struct attribute *i8k_attrs[] = { | |||
735 | &sensor_dev_attr_fan2_input.dev_attr.attr, /* 11 */ | 759 | &sensor_dev_attr_fan2_input.dev_attr.attr, /* 11 */ |
736 | &sensor_dev_attr_fan2_label.dev_attr.attr, /* 12 */ | 760 | &sensor_dev_attr_fan2_label.dev_attr.attr, /* 12 */ |
737 | &sensor_dev_attr_pwm2.dev_attr.attr, /* 13 */ | 761 | &sensor_dev_attr_pwm2.dev_attr.attr, /* 13 */ |
762 | &sensor_dev_attr_fan3_input.dev_attr.attr, /* 14 */ | ||
763 | &sensor_dev_attr_fan3_label.dev_attr.attr, /* 15 */ | ||
764 | &sensor_dev_attr_pwm3.dev_attr.attr, /* 16 */ | ||
738 | NULL | 765 | NULL |
739 | }; | 766 | }; |
740 | 767 | ||
@@ -742,7 +769,7 @@ static umode_t i8k_is_visible(struct kobject *kobj, struct attribute *attr, | |||
742 | int index) | 769 | int index) |
743 | { | 770 | { |
744 | if (disallow_fan_type_call && | 771 | if (disallow_fan_type_call && |
745 | (index == 9 || index == 12)) | 772 | (index == 9 || index == 12 || index == 15)) |
746 | return 0; | 773 | return 0; |
747 | if (index >= 0 && index <= 1 && | 774 | if (index >= 0 && index <= 1 && |
748 | !(i8k_hwmon_flags & I8K_HWMON_HAVE_TEMP1)) | 775 | !(i8k_hwmon_flags & I8K_HWMON_HAVE_TEMP1)) |
@@ -762,6 +789,9 @@ static umode_t i8k_is_visible(struct kobject *kobj, struct attribute *attr, | |||
762 | if (index >= 11 && index <= 13 && | 789 | if (index >= 11 && index <= 13 && |
763 | !(i8k_hwmon_flags & I8K_HWMON_HAVE_FAN2)) | 790 | !(i8k_hwmon_flags & I8K_HWMON_HAVE_FAN2)) |
764 | return 0; | 791 | return 0; |
792 | if (index >= 14 && index <= 16 && | ||
793 | !(i8k_hwmon_flags & I8K_HWMON_HAVE_FAN3)) | ||
794 | return 0; | ||
765 | 795 | ||
766 | return attr->mode; | 796 | return attr->mode; |
767 | } | 797 | } |
@@ -807,6 +837,13 @@ static int __init i8k_init_hwmon(void) | |||
807 | if (err >= 0) | 837 | if (err >= 0) |
808 | i8k_hwmon_flags |= I8K_HWMON_HAVE_FAN2; | 838 | i8k_hwmon_flags |= I8K_HWMON_HAVE_FAN2; |
809 | 839 | ||
840 | /* Third fan attributes, if fan status or type is OK */ | ||
841 | err = i8k_get_fan_status(2); | ||
842 | if (err < 0) | ||
843 | err = i8k_get_fan_type(2); | ||
844 | if (err >= 0) | ||
845 | i8k_hwmon_flags |= I8K_HWMON_HAVE_FAN3; | ||
846 | |||
810 | i8k_hwmon_dev = hwmon_device_register_with_groups(NULL, "dell_smm", | 847 | i8k_hwmon_dev = hwmon_device_register_with_groups(NULL, "dell_smm", |
811 | NULL, i8k_groups); | 848 | NULL, i8k_groups); |
812 | if (IS_ERR(i8k_hwmon_dev)) { | 849 | if (IS_ERR(i8k_hwmon_dev)) { |
diff --git a/drivers/hwmon/emc6w201.c b/drivers/hwmon/emc6w201.c index ada90716448d..f37fe2011640 100644 --- a/drivers/hwmon/emc6w201.c +++ b/drivers/hwmon/emc6w201.c | |||
@@ -464,7 +464,7 @@ static int emc6w201_detect(struct i2c_client *client, | |||
464 | if (verstep < 0 || (verstep & 0xF0) != 0xB0) | 464 | if (verstep < 0 || (verstep & 0xF0) != 0xB0) |
465 | return -ENODEV; | 465 | return -ENODEV; |
466 | if ((verstep & 0x0F) > 2) { | 466 | if ((verstep & 0x0F) > 2) { |
467 | dev_dbg(&client->dev, "Unknwown EMC6W201 stepping %d\n", | 467 | dev_dbg(&client->dev, "Unknown EMC6W201 stepping %d\n", |
468 | verstep & 0x0F); | 468 | verstep & 0x0F); |
469 | return -ENODEV; | 469 | return -ENODEV; |
470 | } | 470 | } |
diff --git a/drivers/hwmon/ftsteutates.c b/drivers/hwmon/ftsteutates.c new file mode 100644 index 000000000000..2b2ff67026be --- /dev/null +++ b/drivers/hwmon/ftsteutates.c | |||
@@ -0,0 +1,819 @@ | |||
1 | /* | ||
2 | * Support for the FTS Systemmonitoring Chip "Teutates" | ||
3 | * | ||
4 | * Copyright (C) 2016 Fujitsu Technology Solutions GmbH, | ||
5 | * Thilo Cestonaro <thilo.cestonaro@ts.fujitsu.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | */ | ||
18 | #include <linux/err.h> | ||
19 | #include <linux/fs.h> | ||
20 | #include <linux/hwmon.h> | ||
21 | #include <linux/hwmon-sysfs.h> | ||
22 | #include <linux/i2c.h> | ||
23 | #include <linux/init.h> | ||
24 | #include <linux/jiffies.h> | ||
25 | #include <linux/module.h> | ||
26 | #include <linux/mutex.h> | ||
27 | #include <linux/slab.h> | ||
28 | #include <linux/sysfs.h> | ||
29 | #include <linux/uaccess.h> | ||
30 | #include <linux/watchdog.h> | ||
31 | |||
32 | #define FTS_DEVICE_ID_REG 0x0000 | ||
33 | #define FTS_DEVICE_REVISION_REG 0x0001 | ||
34 | #define FTS_DEVICE_STATUS_REG 0x0004 | ||
35 | #define FTS_SATELLITE_STATUS_REG 0x0005 | ||
36 | #define FTS_EVENT_STATUS_REG 0x0006 | ||
37 | #define FTS_GLOBAL_CONTROL_REG 0x0007 | ||
38 | |||
39 | #define FTS_SENSOR_EVENT_REG 0x0010 | ||
40 | |||
41 | #define FTS_FAN_EVENT_REG 0x0014 | ||
42 | #define FTS_FAN_PRESENT_REG 0x0015 | ||
43 | |||
44 | #define FTS_POWER_ON_TIME_COUNTER_A 0x007A | ||
45 | #define FTS_POWER_ON_TIME_COUNTER_B 0x007B | ||
46 | #define FTS_POWER_ON_TIME_COUNTER_C 0x007C | ||
47 | |||
48 | #define FTS_PAGE_SELECT_REG 0x007F | ||
49 | |||
50 | #define FTS_WATCHDOG_TIME_PRESET 0x000B | ||
51 | #define FTS_WATCHDOG_CONTROL 0x5081 | ||
52 | |||
53 | #define FTS_NO_FAN_SENSORS 0x08 | ||
54 | #define FTS_NO_TEMP_SENSORS 0x10 | ||
55 | #define FTS_NO_VOLT_SENSORS 0x04 | ||
56 | |||
57 | static struct i2c_device_id fts_id[] = { | ||
58 | { "ftsteutates", 0 }, | ||
59 | { } | ||
60 | }; | ||
61 | MODULE_DEVICE_TABLE(i2c, fts_id); | ||
62 | |||
63 | enum WATCHDOG_RESOLUTION { | ||
64 | seconds = 1, | ||
65 | minutes = 60 | ||
66 | }; | ||
67 | |||
68 | struct fts_data { | ||
69 | struct i2c_client *client; | ||
70 | /* update sensor data lock */ | ||
71 | struct mutex update_lock; | ||
72 | /* read/write register lock */ | ||
73 | struct mutex access_lock; | ||
74 | unsigned long last_updated; /* in jiffies */ | ||
75 | struct watchdog_device wdd; | ||
76 | enum WATCHDOG_RESOLUTION resolution; | ||
77 | bool valid; /* false until following fields are valid */ | ||
78 | |||
79 | u8 volt[FTS_NO_VOLT_SENSORS]; | ||
80 | |||
81 | u8 temp_input[FTS_NO_TEMP_SENSORS]; | ||
82 | u8 temp_alarm; | ||
83 | |||
84 | u8 fan_present; | ||
85 | u8 fan_input[FTS_NO_FAN_SENSORS]; /* in rps */ | ||
86 | u8 fan_source[FTS_NO_FAN_SENSORS]; | ||
87 | u8 fan_alarm; | ||
88 | }; | ||
89 | |||
90 | #define FTS_REG_FAN_INPUT(idx) ((idx) + 0x20) | ||
91 | #define FTS_REG_FAN_SOURCE(idx) ((idx) + 0x30) | ||
92 | #define FTS_REG_FAN_CONTROL(idx) (((idx) << 16) + 0x4881) | ||
93 | |||
94 | #define FTS_REG_TEMP_INPUT(idx) ((idx) + 0x40) | ||
95 | #define FTS_REG_TEMP_CONTROL(idx) (((idx) << 16) + 0x0681) | ||
96 | |||
97 | #define FTS_REG_VOLT(idx) ((idx) + 0x18) | ||
98 | |||
99 | /*****************************************************************************/ | ||
100 | /* I2C Helper functions */ | ||
101 | /*****************************************************************************/ | ||
102 | static int fts_read_byte(struct i2c_client *client, unsigned short reg) | ||
103 | { | ||
104 | int ret; | ||
105 | unsigned char page = reg >> 8; | ||
106 | struct fts_data *data = dev_get_drvdata(&client->dev); | ||
107 | |||
108 | mutex_lock(&data->access_lock); | ||
109 | |||
110 | dev_dbg(&client->dev, "page select - page: 0x%.02x\n", page); | ||
111 | ret = i2c_smbus_write_byte_data(client, FTS_PAGE_SELECT_REG, page); | ||
112 | if (ret < 0) | ||
113 | goto error; | ||
114 | |||
115 | reg &= 0xFF; | ||
116 | ret = i2c_smbus_read_byte_data(client, reg); | ||
117 | dev_dbg(&client->dev, "read - reg: 0x%.02x: val: 0x%.02x\n", reg, ret); | ||
118 | |||
119 | error: | ||
120 | mutex_unlock(&data->access_lock); | ||
121 | return ret; | ||
122 | } | ||
123 | |||
124 | static int fts_write_byte(struct i2c_client *client, unsigned short reg, | ||
125 | unsigned char value) | ||
126 | { | ||
127 | int ret; | ||
128 | unsigned char page = reg >> 8; | ||
129 | struct fts_data *data = dev_get_drvdata(&client->dev); | ||
130 | |||
131 | mutex_lock(&data->access_lock); | ||
132 | |||
133 | dev_dbg(&client->dev, "page select - page: 0x%.02x\n", page); | ||
134 | ret = i2c_smbus_write_byte_data(client, FTS_PAGE_SELECT_REG, page); | ||
135 | if (ret < 0) | ||
136 | goto error; | ||
137 | |||
138 | reg &= 0xFF; | ||
139 | dev_dbg(&client->dev, | ||
140 | "write - reg: 0x%.02x: val: 0x%.02x\n", reg, value); | ||
141 | ret = i2c_smbus_write_byte_data(client, reg, value); | ||
142 | |||
143 | error: | ||
144 | mutex_unlock(&data->access_lock); | ||
145 | return ret; | ||
146 | } | ||
147 | |||
148 | /*****************************************************************************/ | ||
149 | /* Data Updater Helper function */ | ||
150 | /*****************************************************************************/ | ||
151 | static int fts_update_device(struct fts_data *data) | ||
152 | { | ||
153 | int i; | ||
154 | int err = 0; | ||
155 | |||
156 | mutex_lock(&data->update_lock); | ||
157 | if (!time_after(jiffies, data->last_updated + 2 * HZ) && data->valid) | ||
158 | goto exit; | ||
159 | |||
160 | err = fts_read_byte(data->client, FTS_DEVICE_STATUS_REG); | ||
161 | if (err < 0) | ||
162 | goto exit; | ||
163 | |||
164 | data->valid = !!(err & 0x02); /* Data not ready yet */ | ||
165 | if (unlikely(!data->valid)) { | ||
166 | err = -EAGAIN; | ||
167 | goto exit; | ||
168 | } | ||
169 | |||
170 | err = fts_read_byte(data->client, FTS_FAN_PRESENT_REG); | ||
171 | if (err < 0) | ||
172 | goto exit; | ||
173 | data->fan_present = err; | ||
174 | |||
175 | err = fts_read_byte(data->client, FTS_FAN_EVENT_REG); | ||
176 | if (err < 0) | ||
177 | goto exit; | ||
178 | data->fan_alarm = err; | ||
179 | |||
180 | for (i = 0; i < FTS_NO_FAN_SENSORS; i++) { | ||
181 | if (data->fan_present & BIT(i)) { | ||
182 | err = fts_read_byte(data->client, FTS_REG_FAN_INPUT(i)); | ||
183 | if (err < 0) | ||
184 | goto exit; | ||
185 | data->fan_input[i] = err; | ||
186 | |||
187 | err = fts_read_byte(data->client, | ||
188 | FTS_REG_FAN_SOURCE(i)); | ||
189 | if (err < 0) | ||
190 | goto exit; | ||
191 | data->fan_source[i] = err; | ||
192 | } else { | ||
193 | data->fan_input[i] = 0; | ||
194 | data->fan_source[i] = 0; | ||
195 | } | ||
196 | } | ||
197 | |||
198 | err = fts_read_byte(data->client, FTS_SENSOR_EVENT_REG); | ||
199 | if (err < 0) | ||
200 | goto exit; | ||
201 | data->temp_alarm = err; | ||
202 | |||
203 | for (i = 0; i < FTS_NO_TEMP_SENSORS; i++) { | ||
204 | err = fts_read_byte(data->client, FTS_REG_TEMP_INPUT(i)); | ||
205 | if (err < 0) | ||
206 | goto exit; | ||
207 | data->temp_input[i] = err; | ||
208 | } | ||
209 | |||
210 | for (i = 0; i < FTS_NO_VOLT_SENSORS; i++) { | ||
211 | err = fts_read_byte(data->client, FTS_REG_VOLT(i)); | ||
212 | if (err < 0) | ||
213 | goto exit; | ||
214 | data->volt[i] = err; | ||
215 | } | ||
216 | data->last_updated = jiffies; | ||
217 | err = 0; | ||
218 | exit: | ||
219 | mutex_unlock(&data->update_lock); | ||
220 | return err; | ||
221 | } | ||
222 | |||
223 | /*****************************************************************************/ | ||
224 | /* Watchdog functions */ | ||
225 | /*****************************************************************************/ | ||
226 | static int fts_wd_set_resolution(struct fts_data *data, | ||
227 | enum WATCHDOG_RESOLUTION resolution) | ||
228 | { | ||
229 | int ret; | ||
230 | |||
231 | if (data->resolution == resolution) | ||
232 | return 0; | ||
233 | |||
234 | ret = fts_read_byte(data->client, FTS_WATCHDOG_CONTROL); | ||
235 | if (ret < 0) | ||
236 | return ret; | ||
237 | |||
238 | if ((resolution == seconds && ret & BIT(1)) || | ||
239 | (resolution == minutes && (ret & BIT(1)) == 0)) { | ||
240 | data->resolution = resolution; | ||
241 | return 0; | ||
242 | } | ||
243 | |||
244 | if (resolution == seconds) | ||
245 | set_bit(1, (unsigned long *)&ret); | ||
246 | else | ||
247 | ret &= ~BIT(1); | ||
248 | |||
249 | ret = fts_write_byte(data->client, FTS_WATCHDOG_CONTROL, ret); | ||
250 | if (ret < 0) | ||
251 | return ret; | ||
252 | |||
253 | data->resolution = resolution; | ||
254 | return ret; | ||
255 | } | ||
256 | |||
257 | static int fts_wd_set_timeout(struct watchdog_device *wdd, unsigned int timeout) | ||
258 | { | ||
259 | struct fts_data *data; | ||
260 | enum WATCHDOG_RESOLUTION resolution = seconds; | ||
261 | int ret; | ||
262 | |||
263 | data = watchdog_get_drvdata(wdd); | ||
264 | /* switch watchdog resolution to minutes if timeout does not fit | ||
265 | * into a byte | ||
266 | */ | ||
267 | if (timeout > 0xFF) { | ||
268 | timeout = DIV_ROUND_UP(timeout, 60) * 60; | ||
269 | resolution = minutes; | ||
270 | } | ||
271 | |||
272 | ret = fts_wd_set_resolution(data, resolution); | ||
273 | if (ret < 0) | ||
274 | return ret; | ||
275 | |||
276 | wdd->timeout = timeout; | ||
277 | return 0; | ||
278 | } | ||
279 | |||
280 | static int fts_wd_start(struct watchdog_device *wdd) | ||
281 | { | ||
282 | struct fts_data *data = watchdog_get_drvdata(wdd); | ||
283 | |||
284 | return fts_write_byte(data->client, FTS_WATCHDOG_TIME_PRESET, | ||
285 | wdd->timeout / (u8)data->resolution); | ||
286 | } | ||
287 | |||
288 | static int fts_wd_stop(struct watchdog_device *wdd) | ||
289 | { | ||
290 | struct fts_data *data; | ||
291 | |||
292 | data = watchdog_get_drvdata(wdd); | ||
293 | return fts_write_byte(data->client, FTS_WATCHDOG_TIME_PRESET, 0); | ||
294 | } | ||
295 | |||
296 | static const struct watchdog_info fts_wd_info = { | ||
297 | .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, | ||
298 | .identity = "FTS Teutates Hardware Watchdog", | ||
299 | }; | ||
300 | |||
301 | static const struct watchdog_ops fts_wd_ops = { | ||
302 | .owner = THIS_MODULE, | ||
303 | .start = fts_wd_start, | ||
304 | .stop = fts_wd_stop, | ||
305 | .set_timeout = fts_wd_set_timeout, | ||
306 | }; | ||
307 | |||
308 | static int fts_watchdog_init(struct fts_data *data) | ||
309 | { | ||
310 | int timeout, ret; | ||
311 | |||
312 | watchdog_set_drvdata(&data->wdd, data); | ||
313 | |||
314 | timeout = fts_read_byte(data->client, FTS_WATCHDOG_TIME_PRESET); | ||
315 | if (timeout < 0) | ||
316 | return timeout; | ||
317 | |||
318 | /* watchdog not running, set timeout to a default of 60 sec. */ | ||
319 | if (timeout == 0) { | ||
320 | ret = fts_wd_set_resolution(data, seconds); | ||
321 | if (ret < 0) | ||
322 | return ret; | ||
323 | data->wdd.timeout = 60; | ||
324 | } else { | ||
325 | ret = fts_read_byte(data->client, FTS_WATCHDOG_CONTROL); | ||
326 | if (ret < 0) | ||
327 | return ret; | ||
328 | |||
329 | data->resolution = ret & BIT(1) ? seconds : minutes; | ||
330 | data->wdd.timeout = timeout * (u8)data->resolution; | ||
331 | set_bit(WDOG_HW_RUNNING, &data->wdd.status); | ||
332 | } | ||
333 | |||
334 | /* Register our watchdog part */ | ||
335 | data->wdd.info = &fts_wd_info; | ||
336 | data->wdd.ops = &fts_wd_ops; | ||
337 | data->wdd.parent = &data->client->dev; | ||
338 | data->wdd.min_timeout = 1; | ||
339 | |||
340 | /* max timeout 255 minutes. */ | ||
341 | data->wdd.max_hw_heartbeat_ms = 0xFF * 60 * MSEC_PER_SEC; | ||
342 | |||
343 | return watchdog_register_device(&data->wdd); | ||
344 | } | ||
345 | |||
346 | /*****************************************************************************/ | ||
347 | /* SysFS handler functions */ | ||
348 | /*****************************************************************************/ | ||
349 | static ssize_t show_in_value(struct device *dev, | ||
350 | struct device_attribute *devattr, char *buf) | ||
351 | { | ||
352 | struct fts_data *data = dev_get_drvdata(dev); | ||
353 | int index = to_sensor_dev_attr(devattr)->index; | ||
354 | int err; | ||
355 | |||
356 | err = fts_update_device(data); | ||
357 | if (err < 0) | ||
358 | return err; | ||
359 | |||
360 | return sprintf(buf, "%u\n", data->volt[index]); | ||
361 | } | ||
362 | |||
363 | static ssize_t show_temp_value(struct device *dev, | ||
364 | struct device_attribute *devattr, char *buf) | ||
365 | { | ||
366 | struct fts_data *data = dev_get_drvdata(dev); | ||
367 | int index = to_sensor_dev_attr(devattr)->index; | ||
368 | int err; | ||
369 | |||
370 | err = fts_update_device(data); | ||
371 | if (err < 0) | ||
372 | return err; | ||
373 | |||
374 | return sprintf(buf, "%u\n", data->temp_input[index]); | ||
375 | } | ||
376 | |||
377 | static ssize_t show_temp_fault(struct device *dev, | ||
378 | struct device_attribute *devattr, char *buf) | ||
379 | { | ||
380 | struct fts_data *data = dev_get_drvdata(dev); | ||
381 | int index = to_sensor_dev_attr(devattr)->index; | ||
382 | int err; | ||
383 | |||
384 | err = fts_update_device(data); | ||
385 | if (err < 0) | ||
386 | return err; | ||
387 | |||
388 | /* 00h Temperature = Sensor Error */ | ||
389 | return sprintf(buf, "%d\n", data->temp_input[index] == 0); | ||
390 | } | ||
391 | |||
392 | static ssize_t show_temp_alarm(struct device *dev, | ||
393 | struct device_attribute *devattr, char *buf) | ||
394 | { | ||
395 | struct fts_data *data = dev_get_drvdata(dev); | ||
396 | int index = to_sensor_dev_attr(devattr)->index; | ||
397 | int err; | ||
398 | |||
399 | err = fts_update_device(data); | ||
400 | if (err < 0) | ||
401 | return err; | ||
402 | |||
403 | return sprintf(buf, "%u\n", !!(data->temp_alarm & BIT(index))); | ||
404 | } | ||
405 | |||
406 | static ssize_t | ||
407 | clear_temp_alarm(struct device *dev, struct device_attribute *devattr, | ||
408 | const char *buf, size_t count) | ||
409 | { | ||
410 | struct fts_data *data = dev_get_drvdata(dev); | ||
411 | int index = to_sensor_dev_attr(devattr)->index; | ||
412 | long ret; | ||
413 | |||
414 | ret = fts_update_device(data); | ||
415 | if (ret < 0) | ||
416 | return ret; | ||
417 | |||
418 | if (kstrtoul(buf, 10, &ret) || ret != 0) | ||
419 | return -EINVAL; | ||
420 | |||
421 | mutex_lock(&data->update_lock); | ||
422 | ret = fts_read_byte(data->client, FTS_REG_TEMP_CONTROL(index)); | ||
423 | if (ret < 0) | ||
424 | goto error; | ||
425 | |||
426 | ret = fts_write_byte(data->client, FTS_REG_TEMP_CONTROL(index), | ||
427 | ret | 0x1); | ||
428 | if (ret < 0) | ||
429 | goto error; | ||
430 | |||
431 | data->valid = false; | ||
432 | error: | ||
433 | mutex_unlock(&data->update_lock); | ||
434 | return ret; | ||
435 | } | ||
436 | |||
437 | static ssize_t show_fan_value(struct device *dev, | ||
438 | struct device_attribute *devattr, char *buf) | ||
439 | { | ||
440 | struct fts_data *data = dev_get_drvdata(dev); | ||
441 | int index = to_sensor_dev_attr(devattr)->index; | ||
442 | int err; | ||
443 | |||
444 | err = fts_update_device(data); | ||
445 | if (err < 0) | ||
446 | return err; | ||
447 | |||
448 | return sprintf(buf, "%u\n", data->fan_input[index]); | ||
449 | } | ||
450 | |||
451 | static ssize_t show_fan_source(struct device *dev, | ||
452 | struct device_attribute *devattr, char *buf) | ||
453 | { | ||
454 | struct fts_data *data = dev_get_drvdata(dev); | ||
455 | int index = to_sensor_dev_attr(devattr)->index; | ||
456 | int err; | ||
457 | |||
458 | err = fts_update_device(data); | ||
459 | if (err < 0) | ||
460 | return err; | ||
461 | |||
462 | return sprintf(buf, "%u\n", data->fan_source[index]); | ||
463 | } | ||
464 | |||
465 | static ssize_t show_fan_alarm(struct device *dev, | ||
466 | struct device_attribute *devattr, char *buf) | ||
467 | { | ||
468 | struct fts_data *data = dev_get_drvdata(dev); | ||
469 | int index = to_sensor_dev_attr(devattr)->index; | ||
470 | int err; | ||
471 | |||
472 | err = fts_update_device(data); | ||
473 | if (err < 0) | ||
474 | return err; | ||
475 | |||
476 | return sprintf(buf, "%d\n", !!(data->fan_alarm & BIT(index))); | ||
477 | } | ||
478 | |||
479 | static ssize_t | ||
480 | clear_fan_alarm(struct device *dev, struct device_attribute *devattr, | ||
481 | const char *buf, size_t count) | ||
482 | { | ||
483 | struct fts_data *data = dev_get_drvdata(dev); | ||
484 | int index = to_sensor_dev_attr(devattr)->index; | ||
485 | long ret; | ||
486 | |||
487 | ret = fts_update_device(data); | ||
488 | if (ret < 0) | ||
489 | return ret; | ||
490 | |||
491 | if (kstrtoul(buf, 10, &ret) || ret != 0) | ||
492 | return -EINVAL; | ||
493 | |||
494 | mutex_lock(&data->update_lock); | ||
495 | ret = fts_read_byte(data->client, FTS_REG_FAN_CONTROL(index)); | ||
496 | if (ret < 0) | ||
497 | goto error; | ||
498 | |||
499 | ret = fts_write_byte(data->client, FTS_REG_FAN_CONTROL(index), | ||
500 | ret | 0x1); | ||
501 | if (ret < 0) | ||
502 | goto error; | ||
503 | |||
504 | data->valid = false; | ||
505 | error: | ||
506 | mutex_unlock(&data->update_lock); | ||
507 | return ret; | ||
508 | } | ||
509 | |||
510 | /*****************************************************************************/ | ||
511 | /* SysFS structs */ | ||
512 | /*****************************************************************************/ | ||
513 | |||
514 | /* Temprature sensors */ | ||
515 | static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp_value, NULL, 0); | ||
516 | static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp_value, NULL, 1); | ||
517 | static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp_value, NULL, 2); | ||
518 | static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_temp_value, NULL, 3); | ||
519 | static SENSOR_DEVICE_ATTR(temp5_input, S_IRUGO, show_temp_value, NULL, 4); | ||
520 | static SENSOR_DEVICE_ATTR(temp6_input, S_IRUGO, show_temp_value, NULL, 5); | ||
521 | static SENSOR_DEVICE_ATTR(temp7_input, S_IRUGO, show_temp_value, NULL, 6); | ||
522 | static SENSOR_DEVICE_ATTR(temp8_input, S_IRUGO, show_temp_value, NULL, 7); | ||
523 | static SENSOR_DEVICE_ATTR(temp9_input, S_IRUGO, show_temp_value, NULL, 8); | ||
524 | static SENSOR_DEVICE_ATTR(temp10_input, S_IRUGO, show_temp_value, NULL, 9); | ||
525 | static SENSOR_DEVICE_ATTR(temp11_input, S_IRUGO, show_temp_value, NULL, 10); | ||
526 | static SENSOR_DEVICE_ATTR(temp12_input, S_IRUGO, show_temp_value, NULL, 11); | ||
527 | static SENSOR_DEVICE_ATTR(temp13_input, S_IRUGO, show_temp_value, NULL, 12); | ||
528 | static SENSOR_DEVICE_ATTR(temp14_input, S_IRUGO, show_temp_value, NULL, 13); | ||
529 | static SENSOR_DEVICE_ATTR(temp15_input, S_IRUGO, show_temp_value, NULL, 14); | ||
530 | static SENSOR_DEVICE_ATTR(temp16_input, S_IRUGO, show_temp_value, NULL, 15); | ||
531 | |||
532 | static SENSOR_DEVICE_ATTR(temp1_fault, S_IRUGO, show_temp_fault, NULL, 0); | ||
533 | static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_temp_fault, NULL, 1); | ||
534 | static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_temp_fault, NULL, 2); | ||
535 | static SENSOR_DEVICE_ATTR(temp4_fault, S_IRUGO, show_temp_fault, NULL, 3); | ||
536 | static SENSOR_DEVICE_ATTR(temp5_fault, S_IRUGO, show_temp_fault, NULL, 4); | ||
537 | static SENSOR_DEVICE_ATTR(temp6_fault, S_IRUGO, show_temp_fault, NULL, 5); | ||
538 | static SENSOR_DEVICE_ATTR(temp7_fault, S_IRUGO, show_temp_fault, NULL, 6); | ||
539 | static SENSOR_DEVICE_ATTR(temp8_fault, S_IRUGO, show_temp_fault, NULL, 7); | ||
540 | static SENSOR_DEVICE_ATTR(temp9_fault, S_IRUGO, show_temp_fault, NULL, 8); | ||
541 | static SENSOR_DEVICE_ATTR(temp10_fault, S_IRUGO, show_temp_fault, NULL, 9); | ||
542 | static SENSOR_DEVICE_ATTR(temp11_fault, S_IRUGO, show_temp_fault, NULL, 10); | ||
543 | static SENSOR_DEVICE_ATTR(temp12_fault, S_IRUGO, show_temp_fault, NULL, 11); | ||
544 | static SENSOR_DEVICE_ATTR(temp13_fault, S_IRUGO, show_temp_fault, NULL, 12); | ||
545 | static SENSOR_DEVICE_ATTR(temp14_fault, S_IRUGO, show_temp_fault, NULL, 13); | ||
546 | static SENSOR_DEVICE_ATTR(temp15_fault, S_IRUGO, show_temp_fault, NULL, 14); | ||
547 | static SENSOR_DEVICE_ATTR(temp16_fault, S_IRUGO, show_temp_fault, NULL, 15); | ||
548 | |||
549 | static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO | S_IWUSR, show_temp_alarm, | ||
550 | clear_temp_alarm, 0); | ||
551 | static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO | S_IWUSR, show_temp_alarm, | ||
552 | clear_temp_alarm, 1); | ||
553 | static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO | S_IWUSR, show_temp_alarm, | ||
554 | clear_temp_alarm, 2); | ||
555 | static SENSOR_DEVICE_ATTR(temp4_alarm, S_IRUGO | S_IWUSR, show_temp_alarm, | ||
556 | clear_temp_alarm, 3); | ||
557 | static SENSOR_DEVICE_ATTR(temp5_alarm, S_IRUGO | S_IWUSR, show_temp_alarm, | ||
558 | clear_temp_alarm, 4); | ||
559 | static SENSOR_DEVICE_ATTR(temp6_alarm, S_IRUGO | S_IWUSR, show_temp_alarm, | ||
560 | clear_temp_alarm, 5); | ||
561 | static SENSOR_DEVICE_ATTR(temp7_alarm, S_IRUGO | S_IWUSR, show_temp_alarm, | ||
562 | clear_temp_alarm, 6); | ||
563 | static SENSOR_DEVICE_ATTR(temp8_alarm, S_IRUGO | S_IWUSR, show_temp_alarm, | ||
564 | clear_temp_alarm, 7); | ||
565 | static SENSOR_DEVICE_ATTR(temp9_alarm, S_IRUGO | S_IWUSR, show_temp_alarm, | ||
566 | clear_temp_alarm, 8); | ||
567 | static SENSOR_DEVICE_ATTR(temp10_alarm, S_IRUGO | S_IWUSR, show_temp_alarm, | ||
568 | clear_temp_alarm, 9); | ||
569 | static SENSOR_DEVICE_ATTR(temp11_alarm, S_IRUGO | S_IWUSR, show_temp_alarm, | ||
570 | clear_temp_alarm, 10); | ||
571 | static SENSOR_DEVICE_ATTR(temp12_alarm, S_IRUGO | S_IWUSR, show_temp_alarm, | ||
572 | clear_temp_alarm, 11); | ||
573 | static SENSOR_DEVICE_ATTR(temp13_alarm, S_IRUGO | S_IWUSR, show_temp_alarm, | ||
574 | clear_temp_alarm, 12); | ||
575 | static SENSOR_DEVICE_ATTR(temp14_alarm, S_IRUGO | S_IWUSR, show_temp_alarm, | ||
576 | clear_temp_alarm, 13); | ||
577 | static SENSOR_DEVICE_ATTR(temp15_alarm, S_IRUGO | S_IWUSR, show_temp_alarm, | ||
578 | clear_temp_alarm, 14); | ||
579 | static SENSOR_DEVICE_ATTR(temp16_alarm, S_IRUGO | S_IWUSR, show_temp_alarm, | ||
580 | clear_temp_alarm, 15); | ||
581 | |||
582 | static struct attribute *fts_temp_attrs[] = { | ||
583 | &sensor_dev_attr_temp1_input.dev_attr.attr, | ||
584 | &sensor_dev_attr_temp2_input.dev_attr.attr, | ||
585 | &sensor_dev_attr_temp3_input.dev_attr.attr, | ||
586 | &sensor_dev_attr_temp4_input.dev_attr.attr, | ||
587 | &sensor_dev_attr_temp5_input.dev_attr.attr, | ||
588 | &sensor_dev_attr_temp6_input.dev_attr.attr, | ||
589 | &sensor_dev_attr_temp7_input.dev_attr.attr, | ||
590 | &sensor_dev_attr_temp8_input.dev_attr.attr, | ||
591 | &sensor_dev_attr_temp9_input.dev_attr.attr, | ||
592 | &sensor_dev_attr_temp10_input.dev_attr.attr, | ||
593 | &sensor_dev_attr_temp11_input.dev_attr.attr, | ||
594 | &sensor_dev_attr_temp12_input.dev_attr.attr, | ||
595 | &sensor_dev_attr_temp13_input.dev_attr.attr, | ||
596 | &sensor_dev_attr_temp14_input.dev_attr.attr, | ||
597 | &sensor_dev_attr_temp15_input.dev_attr.attr, | ||
598 | &sensor_dev_attr_temp16_input.dev_attr.attr, | ||
599 | |||
600 | &sensor_dev_attr_temp1_fault.dev_attr.attr, | ||
601 | &sensor_dev_attr_temp2_fault.dev_attr.attr, | ||
602 | &sensor_dev_attr_temp3_fault.dev_attr.attr, | ||
603 | &sensor_dev_attr_temp4_fault.dev_attr.attr, | ||
604 | &sensor_dev_attr_temp5_fault.dev_attr.attr, | ||
605 | &sensor_dev_attr_temp6_fault.dev_attr.attr, | ||
606 | &sensor_dev_attr_temp7_fault.dev_attr.attr, | ||
607 | &sensor_dev_attr_temp8_fault.dev_attr.attr, | ||
608 | &sensor_dev_attr_temp9_fault.dev_attr.attr, | ||
609 | &sensor_dev_attr_temp10_fault.dev_attr.attr, | ||
610 | &sensor_dev_attr_temp11_fault.dev_attr.attr, | ||
611 | &sensor_dev_attr_temp12_fault.dev_attr.attr, | ||
612 | &sensor_dev_attr_temp13_fault.dev_attr.attr, | ||
613 | &sensor_dev_attr_temp14_fault.dev_attr.attr, | ||
614 | &sensor_dev_attr_temp15_fault.dev_attr.attr, | ||
615 | &sensor_dev_attr_temp16_fault.dev_attr.attr, | ||
616 | |||
617 | &sensor_dev_attr_temp1_alarm.dev_attr.attr, | ||
618 | &sensor_dev_attr_temp2_alarm.dev_attr.attr, | ||
619 | &sensor_dev_attr_temp3_alarm.dev_attr.attr, | ||
620 | &sensor_dev_attr_temp4_alarm.dev_attr.attr, | ||
621 | &sensor_dev_attr_temp5_alarm.dev_attr.attr, | ||
622 | &sensor_dev_attr_temp6_alarm.dev_attr.attr, | ||
623 | &sensor_dev_attr_temp7_alarm.dev_attr.attr, | ||
624 | &sensor_dev_attr_temp8_alarm.dev_attr.attr, | ||
625 | &sensor_dev_attr_temp9_alarm.dev_attr.attr, | ||
626 | &sensor_dev_attr_temp10_alarm.dev_attr.attr, | ||
627 | &sensor_dev_attr_temp11_alarm.dev_attr.attr, | ||
628 | &sensor_dev_attr_temp12_alarm.dev_attr.attr, | ||
629 | &sensor_dev_attr_temp13_alarm.dev_attr.attr, | ||
630 | &sensor_dev_attr_temp14_alarm.dev_attr.attr, | ||
631 | &sensor_dev_attr_temp15_alarm.dev_attr.attr, | ||
632 | &sensor_dev_attr_temp16_alarm.dev_attr.attr, | ||
633 | NULL | ||
634 | }; | ||
635 | |||
636 | /* Fans */ | ||
637 | static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan_value, NULL, 0); | ||
638 | static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan_value, NULL, 1); | ||
639 | static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_fan_value, NULL, 2); | ||
640 | static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, show_fan_value, NULL, 3); | ||
641 | static SENSOR_DEVICE_ATTR(fan5_input, S_IRUGO, show_fan_value, NULL, 4); | ||
642 | static SENSOR_DEVICE_ATTR(fan6_input, S_IRUGO, show_fan_value, NULL, 5); | ||
643 | static SENSOR_DEVICE_ATTR(fan7_input, S_IRUGO, show_fan_value, NULL, 6); | ||
644 | static SENSOR_DEVICE_ATTR(fan8_input, S_IRUGO, show_fan_value, NULL, 7); | ||
645 | |||
646 | static SENSOR_DEVICE_ATTR(fan1_source, S_IRUGO, show_fan_source, NULL, 0); | ||
647 | static SENSOR_DEVICE_ATTR(fan2_source, S_IRUGO, show_fan_source, NULL, 1); | ||
648 | static SENSOR_DEVICE_ATTR(fan3_source, S_IRUGO, show_fan_source, NULL, 2); | ||
649 | static SENSOR_DEVICE_ATTR(fan4_source, S_IRUGO, show_fan_source, NULL, 3); | ||
650 | static SENSOR_DEVICE_ATTR(fan5_source, S_IRUGO, show_fan_source, NULL, 4); | ||
651 | static SENSOR_DEVICE_ATTR(fan6_source, S_IRUGO, show_fan_source, NULL, 5); | ||
652 | static SENSOR_DEVICE_ATTR(fan7_source, S_IRUGO, show_fan_source, NULL, 6); | ||
653 | static SENSOR_DEVICE_ATTR(fan8_source, S_IRUGO, show_fan_source, NULL, 7); | ||
654 | |||
655 | static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO | S_IWUSR, | ||
656 | show_fan_alarm, clear_fan_alarm, 0); | ||
657 | static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO | S_IWUSR, | ||
658 | show_fan_alarm, clear_fan_alarm, 1); | ||
659 | static SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO | S_IWUSR, | ||
660 | show_fan_alarm, clear_fan_alarm, 2); | ||
661 | static SENSOR_DEVICE_ATTR(fan4_alarm, S_IRUGO | S_IWUSR, | ||
662 | show_fan_alarm, clear_fan_alarm, 3); | ||
663 | static SENSOR_DEVICE_ATTR(fan5_alarm, S_IRUGO | S_IWUSR, | ||
664 | show_fan_alarm, clear_fan_alarm, 4); | ||
665 | static SENSOR_DEVICE_ATTR(fan6_alarm, S_IRUGO | S_IWUSR, | ||
666 | show_fan_alarm, clear_fan_alarm, 5); | ||
667 | static SENSOR_DEVICE_ATTR(fan7_alarm, S_IRUGO | S_IWUSR, | ||
668 | show_fan_alarm, clear_fan_alarm, 6); | ||
669 | static SENSOR_DEVICE_ATTR(fan8_alarm, S_IRUGO | S_IWUSR, | ||
670 | show_fan_alarm, clear_fan_alarm, 7); | ||
671 | |||
672 | static struct attribute *fts_fan_attrs[] = { | ||
673 | &sensor_dev_attr_fan1_input.dev_attr.attr, | ||
674 | &sensor_dev_attr_fan2_input.dev_attr.attr, | ||
675 | &sensor_dev_attr_fan3_input.dev_attr.attr, | ||
676 | &sensor_dev_attr_fan4_input.dev_attr.attr, | ||
677 | &sensor_dev_attr_fan5_input.dev_attr.attr, | ||
678 | &sensor_dev_attr_fan6_input.dev_attr.attr, | ||
679 | &sensor_dev_attr_fan7_input.dev_attr.attr, | ||
680 | &sensor_dev_attr_fan8_input.dev_attr.attr, | ||
681 | |||
682 | &sensor_dev_attr_fan1_source.dev_attr.attr, | ||
683 | &sensor_dev_attr_fan2_source.dev_attr.attr, | ||
684 | &sensor_dev_attr_fan3_source.dev_attr.attr, | ||
685 | &sensor_dev_attr_fan4_source.dev_attr.attr, | ||
686 | &sensor_dev_attr_fan5_source.dev_attr.attr, | ||
687 | &sensor_dev_attr_fan6_source.dev_attr.attr, | ||
688 | &sensor_dev_attr_fan7_source.dev_attr.attr, | ||
689 | &sensor_dev_attr_fan8_source.dev_attr.attr, | ||
690 | |||
691 | &sensor_dev_attr_fan1_alarm.dev_attr.attr, | ||
692 | &sensor_dev_attr_fan2_alarm.dev_attr.attr, | ||
693 | &sensor_dev_attr_fan3_alarm.dev_attr.attr, | ||
694 | &sensor_dev_attr_fan4_alarm.dev_attr.attr, | ||
695 | &sensor_dev_attr_fan5_alarm.dev_attr.attr, | ||
696 | &sensor_dev_attr_fan6_alarm.dev_attr.attr, | ||
697 | &sensor_dev_attr_fan7_alarm.dev_attr.attr, | ||
698 | &sensor_dev_attr_fan8_alarm.dev_attr.attr, | ||
699 | NULL | ||
700 | }; | ||
701 | |||
702 | /* Voltages */ | ||
703 | static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, show_in_value, NULL, 0); | ||
704 | static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, show_in_value, NULL, 1); | ||
705 | static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, show_in_value, NULL, 2); | ||
706 | static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, show_in_value, NULL, 3); | ||
707 | static struct attribute *fts_voltage_attrs[] = { | ||
708 | &sensor_dev_attr_in1_input.dev_attr.attr, | ||
709 | &sensor_dev_attr_in2_input.dev_attr.attr, | ||
710 | &sensor_dev_attr_in3_input.dev_attr.attr, | ||
711 | &sensor_dev_attr_in4_input.dev_attr.attr, | ||
712 | NULL | ||
713 | }; | ||
714 | |||
715 | static const struct attribute_group fts_voltage_attr_group = { | ||
716 | .attrs = fts_voltage_attrs | ||
717 | }; | ||
718 | |||
719 | static const struct attribute_group fts_temp_attr_group = { | ||
720 | .attrs = fts_temp_attrs | ||
721 | }; | ||
722 | |||
723 | static const struct attribute_group fts_fan_attr_group = { | ||
724 | .attrs = fts_fan_attrs | ||
725 | }; | ||
726 | |||
727 | static const struct attribute_group *fts_attr_groups[] = { | ||
728 | &fts_voltage_attr_group, | ||
729 | &fts_temp_attr_group, | ||
730 | &fts_fan_attr_group, | ||
731 | NULL | ||
732 | }; | ||
733 | |||
734 | /*****************************************************************************/ | ||
735 | /* Module initialization / remove functions */ | ||
736 | /*****************************************************************************/ | ||
737 | static int fts_remove(struct i2c_client *client) | ||
738 | { | ||
739 | struct fts_data *data = dev_get_drvdata(&client->dev); | ||
740 | |||
741 | watchdog_unregister_device(&data->wdd); | ||
742 | return 0; | ||
743 | } | ||
744 | |||
745 | static int fts_probe(struct i2c_client *client, const struct i2c_device_id *id) | ||
746 | { | ||
747 | u8 revision; | ||
748 | struct fts_data *data; | ||
749 | int err; | ||
750 | s8 deviceid; | ||
751 | struct device *hwmon_dev; | ||
752 | |||
753 | if (client->addr != 0x73) | ||
754 | return -ENODEV; | ||
755 | |||
756 | /* Baseboard Management Controller check */ | ||
757 | deviceid = i2c_smbus_read_byte_data(client, FTS_DEVICE_ID_REG); | ||
758 | if (deviceid > 0 && (deviceid & 0xF0) == 0x10) { | ||
759 | switch (deviceid & 0x0F) { | ||
760 | case 0x01: | ||
761 | break; | ||
762 | default: | ||
763 | dev_dbg(&client->dev, | ||
764 | "No Baseboard Management Controller\n"); | ||
765 | return -ENODEV; | ||
766 | } | ||
767 | } else { | ||
768 | dev_dbg(&client->dev, "No fujitsu board\n"); | ||
769 | return -ENODEV; | ||
770 | } | ||
771 | |||
772 | data = devm_kzalloc(&client->dev, sizeof(struct fts_data), | ||
773 | GFP_KERNEL); | ||
774 | if (!data) | ||
775 | return -ENOMEM; | ||
776 | |||
777 | mutex_init(&data->update_lock); | ||
778 | mutex_init(&data->access_lock); | ||
779 | data->client = client; | ||
780 | dev_set_drvdata(&client->dev, data); | ||
781 | |||
782 | err = i2c_smbus_read_byte_data(client, FTS_DEVICE_REVISION_REG); | ||
783 | if (err < 0) | ||
784 | return err; | ||
785 | revision = err; | ||
786 | |||
787 | hwmon_dev = devm_hwmon_device_register_with_groups(&client->dev, | ||
788 | "ftsteutates", | ||
789 | data, | ||
790 | fts_attr_groups); | ||
791 | if (IS_ERR(hwmon_dev)) | ||
792 | return PTR_ERR(hwmon_dev); | ||
793 | |||
794 | err = fts_watchdog_init(data); | ||
795 | if (err) | ||
796 | return err; | ||
797 | |||
798 | dev_info(&client->dev, "Detected FTS Teutates chip, revision: %d.%d\n", | ||
799 | (revision & 0xF0) >> 4, revision & 0x0F); | ||
800 | return 0; | ||
801 | } | ||
802 | |||
803 | /*****************************************************************************/ | ||
804 | /* Module Details */ | ||
805 | /*****************************************************************************/ | ||
806 | static struct i2c_driver fts_driver = { | ||
807 | .driver = { | ||
808 | .name = "ftsteutates", | ||
809 | }, | ||
810 | .id_table = fts_id, | ||
811 | .probe = fts_probe, | ||
812 | .remove = fts_remove, | ||
813 | }; | ||
814 | |||
815 | module_i2c_driver(fts_driver); | ||
816 | |||
817 | MODULE_AUTHOR("Thilo Cestonaro <thilo.cestonaro@ts.fujitsu.com>"); | ||
818 | MODULE_DESCRIPTION("FTS Teutates driver"); | ||
819 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/hwmon/ina3221.c b/drivers/hwmon/ina3221.c new file mode 100644 index 000000000000..e6b49500c52a --- /dev/null +++ b/drivers/hwmon/ina3221.c | |||
@@ -0,0 +1,445 @@ | |||
1 | /* | ||
2 | * INA3221 Triple Current/Voltage Monitor | ||
3 | * | ||
4 | * Copyright (C) 2016 Texas Instruments Incorporated - http://www.ti.com/ | ||
5 | * Andrew F. Davis <afd@ti.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, but | ||
12 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | * General Public License for more details. | ||
15 | */ | ||
16 | |||
17 | #include <linux/hwmon.h> | ||
18 | #include <linux/hwmon-sysfs.h> | ||
19 | #include <linux/i2c.h> | ||
20 | #include <linux/module.h> | ||
21 | #include <linux/of.h> | ||
22 | #include <linux/regmap.h> | ||
23 | |||
24 | #define INA3221_DRIVER_NAME "ina3221" | ||
25 | |||
26 | #define INA3221_CONFIG 0x00 | ||
27 | #define INA3221_SHUNT1 0x01 | ||
28 | #define INA3221_BUS1 0x02 | ||
29 | #define INA3221_SHUNT2 0x03 | ||
30 | #define INA3221_BUS2 0x04 | ||
31 | #define INA3221_SHUNT3 0x05 | ||
32 | #define INA3221_BUS3 0x06 | ||
33 | #define INA3221_CRIT1 0x07 | ||
34 | #define INA3221_WARN1 0x08 | ||
35 | #define INA3221_CRIT2 0x09 | ||
36 | #define INA3221_WARN2 0x0a | ||
37 | #define INA3221_CRIT3 0x0b | ||
38 | #define INA3221_WARN3 0x0c | ||
39 | #define INA3221_MASK_ENABLE 0x0f | ||
40 | |||
41 | #define INA3221_CONFIG_MODE_SHUNT BIT(1) | ||
42 | #define INA3221_CONFIG_MODE_BUS BIT(2) | ||
43 | #define INA3221_CONFIG_MODE_CONTINUOUS BIT(3) | ||
44 | |||
45 | #define INA3221_RSHUNT_DEFAULT 10000 | ||
46 | |||
47 | enum ina3221_fields { | ||
48 | /* Configuration */ | ||
49 | F_RST, | ||
50 | |||
51 | /* Alert Flags */ | ||
52 | F_WF3, F_WF2, F_WF1, | ||
53 | F_CF3, F_CF2, F_CF1, | ||
54 | |||
55 | /* sentinel */ | ||
56 | F_MAX_FIELDS | ||
57 | }; | ||
58 | |||
59 | static const struct reg_field ina3221_reg_fields[] = { | ||
60 | [F_RST] = REG_FIELD(INA3221_CONFIG, 15, 15), | ||
61 | |||
62 | [F_WF3] = REG_FIELD(INA3221_MASK_ENABLE, 3, 3), | ||
63 | [F_WF2] = REG_FIELD(INA3221_MASK_ENABLE, 4, 4), | ||
64 | [F_WF1] = REG_FIELD(INA3221_MASK_ENABLE, 5, 5), | ||
65 | [F_CF3] = REG_FIELD(INA3221_MASK_ENABLE, 7, 7), | ||
66 | [F_CF2] = REG_FIELD(INA3221_MASK_ENABLE, 8, 8), | ||
67 | [F_CF1] = REG_FIELD(INA3221_MASK_ENABLE, 9, 9), | ||
68 | }; | ||
69 | |||
70 | enum ina3221_channels { | ||
71 | INA3221_CHANNEL1, | ||
72 | INA3221_CHANNEL2, | ||
73 | INA3221_CHANNEL3, | ||
74 | INA3221_NUM_CHANNELS | ||
75 | }; | ||
76 | |||
77 | static const unsigned int register_channel[] = { | ||
78 | [INA3221_SHUNT1] = INA3221_CHANNEL1, | ||
79 | [INA3221_SHUNT2] = INA3221_CHANNEL2, | ||
80 | [INA3221_SHUNT3] = INA3221_CHANNEL3, | ||
81 | [INA3221_CRIT1] = INA3221_CHANNEL1, | ||
82 | [INA3221_CRIT2] = INA3221_CHANNEL2, | ||
83 | [INA3221_CRIT3] = INA3221_CHANNEL3, | ||
84 | [INA3221_WARN1] = INA3221_CHANNEL1, | ||
85 | [INA3221_WARN2] = INA3221_CHANNEL2, | ||
86 | [INA3221_WARN3] = INA3221_CHANNEL3, | ||
87 | }; | ||
88 | |||
89 | /** | ||
90 | * struct ina3221_data - device specific information | ||
91 | * @regmap: Register map of the device | ||
92 | * @fields: Register fields of the device | ||
93 | * @shunt_resistors: Array of resistor values per channel | ||
94 | */ | ||
95 | struct ina3221_data { | ||
96 | struct regmap *regmap; | ||
97 | struct regmap_field *fields[F_MAX_FIELDS]; | ||
98 | int shunt_resistors[INA3221_NUM_CHANNELS]; | ||
99 | }; | ||
100 | |||
101 | static int ina3221_read_value(struct ina3221_data *ina, unsigned int reg, | ||
102 | int *val) | ||
103 | { | ||
104 | unsigned int regval; | ||
105 | int ret; | ||
106 | |||
107 | ret = regmap_read(ina->regmap, reg, ®val); | ||
108 | if (ret) | ||
109 | return ret; | ||
110 | |||
111 | *val = sign_extend32(regval >> 3, 12); | ||
112 | |||
113 | return 0; | ||
114 | } | ||
115 | |||
116 | static ssize_t ina3221_show_bus_voltage(struct device *dev, | ||
117 | struct device_attribute *attr, | ||
118 | char *buf) | ||
119 | { | ||
120 | struct sensor_device_attribute *sd_attr = to_sensor_dev_attr(attr); | ||
121 | struct ina3221_data *ina = dev_get_drvdata(dev); | ||
122 | unsigned int reg = sd_attr->index; | ||
123 | int val, voltage_mv, ret; | ||
124 | |||
125 | ret = ina3221_read_value(ina, reg, &val); | ||
126 | if (ret) | ||
127 | return ret; | ||
128 | |||
129 | voltage_mv = val * 8; | ||
130 | |||
131 | return snprintf(buf, PAGE_SIZE, "%d\n", voltage_mv); | ||
132 | } | ||
133 | |||
134 | static ssize_t ina3221_show_shunt_voltage(struct device *dev, | ||
135 | struct device_attribute *attr, | ||
136 | char *buf) | ||
137 | { | ||
138 | struct sensor_device_attribute *sd_attr = to_sensor_dev_attr(attr); | ||
139 | struct ina3221_data *ina = dev_get_drvdata(dev); | ||
140 | unsigned int reg = sd_attr->index; | ||
141 | int val, voltage_uv, ret; | ||
142 | |||
143 | ret = ina3221_read_value(ina, reg, &val); | ||
144 | if (ret) | ||
145 | return ret; | ||
146 | voltage_uv = val * 40; | ||
147 | |||
148 | return snprintf(buf, PAGE_SIZE, "%d\n", voltage_uv); | ||
149 | } | ||
150 | |||
151 | static ssize_t ina3221_show_current(struct device *dev, | ||
152 | struct device_attribute *attr, char *buf) | ||
153 | { | ||
154 | struct sensor_device_attribute *sd_attr = to_sensor_dev_attr(attr); | ||
155 | struct ina3221_data *ina = dev_get_drvdata(dev); | ||
156 | unsigned int reg = sd_attr->index; | ||
157 | unsigned int channel = register_channel[reg]; | ||
158 | int resistance_uo = ina->shunt_resistors[channel]; | ||
159 | int val, current_ma, voltage_nv, ret; | ||
160 | |||
161 | ret = ina3221_read_value(ina, reg, &val); | ||
162 | if (ret) | ||
163 | return ret; | ||
164 | voltage_nv = val * 40000; | ||
165 | |||
166 | current_ma = DIV_ROUND_CLOSEST(voltage_nv, resistance_uo); | ||
167 | |||
168 | return snprintf(buf, PAGE_SIZE, "%d\n", current_ma); | ||
169 | } | ||
170 | |||
171 | static ssize_t ina3221_set_current(struct device *dev, | ||
172 | struct device_attribute *attr, | ||
173 | const char *buf, size_t count) | ||
174 | { | ||
175 | struct sensor_device_attribute *sd_attr = to_sensor_dev_attr(attr); | ||
176 | struct ina3221_data *ina = dev_get_drvdata(dev); | ||
177 | unsigned int reg = sd_attr->index; | ||
178 | unsigned int channel = register_channel[reg]; | ||
179 | int resistance_uo = ina->shunt_resistors[channel]; | ||
180 | int val, current_ma, voltage_uv, ret; | ||
181 | |||
182 | ret = kstrtoint(buf, 0, ¤t_ma); | ||
183 | if (ret) | ||
184 | return ret; | ||
185 | |||
186 | /* clamp current */ | ||
187 | current_ma = clamp_val(current_ma, | ||
188 | INT_MIN / resistance_uo, | ||
189 | INT_MAX / resistance_uo); | ||
190 | |||
191 | voltage_uv = DIV_ROUND_CLOSEST(current_ma * resistance_uo, 1000); | ||
192 | |||
193 | /* clamp voltage */ | ||
194 | voltage_uv = clamp_val(voltage_uv, -163800, 163800); | ||
195 | |||
196 | /* 1 / 40uV(scale) << 3(register shift) = 5 */ | ||
197 | val = DIV_ROUND_CLOSEST(voltage_uv, 5) & 0xfff8; | ||
198 | |||
199 | ret = regmap_write(ina->regmap, reg, val); | ||
200 | if (ret) | ||
201 | return ret; | ||
202 | |||
203 | return count; | ||
204 | } | ||
205 | |||
206 | static ssize_t ina3221_show_shunt(struct device *dev, | ||
207 | struct device_attribute *attr, char *buf) | ||
208 | { | ||
209 | struct sensor_device_attribute *sd_attr = to_sensor_dev_attr(attr); | ||
210 | struct ina3221_data *ina = dev_get_drvdata(dev); | ||
211 | unsigned int channel = sd_attr->index; | ||
212 | unsigned int resistance_uo; | ||
213 | |||
214 | resistance_uo = ina->shunt_resistors[channel]; | ||
215 | |||
216 | return snprintf(buf, PAGE_SIZE, "%d\n", resistance_uo); | ||
217 | } | ||
218 | |||
219 | static ssize_t ina3221_set_shunt(struct device *dev, | ||
220 | struct device_attribute *attr, | ||
221 | const char *buf, size_t count) | ||
222 | { | ||
223 | struct sensor_device_attribute *sd_attr = to_sensor_dev_attr(attr); | ||
224 | struct ina3221_data *ina = dev_get_drvdata(dev); | ||
225 | unsigned int channel = sd_attr->index; | ||
226 | int val; | ||
227 | int ret; | ||
228 | |||
229 | ret = kstrtoint(buf, 0, &val); | ||
230 | if (ret) | ||
231 | return ret; | ||
232 | |||
233 | val = clamp_val(val, 1, INT_MAX); | ||
234 | |||
235 | ina->shunt_resistors[channel] = val; | ||
236 | |||
237 | return count; | ||
238 | } | ||
239 | |||
240 | static ssize_t ina3221_show_alert(struct device *dev, | ||
241 | struct device_attribute *attr, char *buf) | ||
242 | { | ||
243 | struct sensor_device_attribute *sd_attr = to_sensor_dev_attr(attr); | ||
244 | struct ina3221_data *ina = dev_get_drvdata(dev); | ||
245 | unsigned int field = sd_attr->index; | ||
246 | unsigned int regval; | ||
247 | int ret; | ||
248 | |||
249 | ret = regmap_field_read(ina->fields[field], ®val); | ||
250 | if (ret) | ||
251 | return ret; | ||
252 | |||
253 | return snprintf(buf, PAGE_SIZE, "%d\n", regval); | ||
254 | } | ||
255 | |||
256 | /* bus voltage */ | ||
257 | static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, | ||
258 | ina3221_show_bus_voltage, NULL, INA3221_BUS1); | ||
259 | static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, | ||
260 | ina3221_show_bus_voltage, NULL, INA3221_BUS2); | ||
261 | static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, | ||
262 | ina3221_show_bus_voltage, NULL, INA3221_BUS3); | ||
263 | |||
264 | /* calculated current */ | ||
265 | static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, | ||
266 | ina3221_show_current, NULL, INA3221_SHUNT1); | ||
267 | static SENSOR_DEVICE_ATTR(curr2_input, S_IRUGO, | ||
268 | ina3221_show_current, NULL, INA3221_SHUNT2); | ||
269 | static SENSOR_DEVICE_ATTR(curr3_input, S_IRUGO, | ||
270 | ina3221_show_current, NULL, INA3221_SHUNT3); | ||
271 | |||
272 | /* shunt resistance */ | ||
273 | static SENSOR_DEVICE_ATTR(shunt1_resistor, S_IRUGO | S_IWUSR, | ||
274 | ina3221_show_shunt, ina3221_set_shunt, INA3221_CHANNEL1); | ||
275 | static SENSOR_DEVICE_ATTR(shunt2_resistor, S_IRUGO | S_IWUSR, | ||
276 | ina3221_show_shunt, ina3221_set_shunt, INA3221_CHANNEL2); | ||
277 | static SENSOR_DEVICE_ATTR(shunt3_resistor, S_IRUGO | S_IWUSR, | ||
278 | ina3221_show_shunt, ina3221_set_shunt, INA3221_CHANNEL3); | ||
279 | |||
280 | /* critical current */ | ||
281 | static SENSOR_DEVICE_ATTR(curr1_crit, S_IRUGO | S_IWUSR, | ||
282 | ina3221_show_current, ina3221_set_current, INA3221_CRIT1); | ||
283 | static SENSOR_DEVICE_ATTR(curr2_crit, S_IRUGO | S_IWUSR, | ||
284 | ina3221_show_current, ina3221_set_current, INA3221_CRIT2); | ||
285 | static SENSOR_DEVICE_ATTR(curr3_crit, S_IRUGO | S_IWUSR, | ||
286 | ina3221_show_current, ina3221_set_current, INA3221_CRIT3); | ||
287 | |||
288 | /* critical current alert */ | ||
289 | static SENSOR_DEVICE_ATTR(curr1_crit_alarm, S_IRUGO, | ||
290 | ina3221_show_alert, NULL, F_CF1); | ||
291 | static SENSOR_DEVICE_ATTR(curr2_crit_alarm, S_IRUGO, | ||
292 | ina3221_show_alert, NULL, F_CF2); | ||
293 | static SENSOR_DEVICE_ATTR(curr3_crit_alarm, S_IRUGO, | ||
294 | ina3221_show_alert, NULL, F_CF3); | ||
295 | |||
296 | /* warning current */ | ||
297 | static SENSOR_DEVICE_ATTR(curr1_max, S_IRUGO | S_IWUSR, | ||
298 | ina3221_show_current, ina3221_set_current, INA3221_WARN1); | ||
299 | static SENSOR_DEVICE_ATTR(curr2_max, S_IRUGO | S_IWUSR, | ||
300 | ina3221_show_current, ina3221_set_current, INA3221_WARN2); | ||
301 | static SENSOR_DEVICE_ATTR(curr3_max, S_IRUGO | S_IWUSR, | ||
302 | ina3221_show_current, ina3221_set_current, INA3221_WARN3); | ||
303 | |||
304 | /* warning current alert */ | ||
305 | static SENSOR_DEVICE_ATTR(curr1_max_alarm, S_IRUGO, | ||
306 | ina3221_show_alert, NULL, F_WF1); | ||
307 | static SENSOR_DEVICE_ATTR(curr2_max_alarm, S_IRUGO, | ||
308 | ina3221_show_alert, NULL, F_WF2); | ||
309 | static SENSOR_DEVICE_ATTR(curr3_max_alarm, S_IRUGO, | ||
310 | ina3221_show_alert, NULL, F_WF3); | ||
311 | |||
312 | /* shunt voltage */ | ||
313 | static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, | ||
314 | ina3221_show_shunt_voltage, NULL, INA3221_SHUNT1); | ||
315 | static SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, | ||
316 | ina3221_show_shunt_voltage, NULL, INA3221_SHUNT2); | ||
317 | static SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, | ||
318 | ina3221_show_shunt_voltage, NULL, INA3221_SHUNT3); | ||
319 | |||
320 | static struct attribute *ina3221_attrs[] = { | ||
321 | /* channel 1 */ | ||
322 | &sensor_dev_attr_in1_input.dev_attr.attr, | ||
323 | &sensor_dev_attr_curr1_input.dev_attr.attr, | ||
324 | &sensor_dev_attr_shunt1_resistor.dev_attr.attr, | ||
325 | &sensor_dev_attr_curr1_crit.dev_attr.attr, | ||
326 | &sensor_dev_attr_curr1_crit_alarm.dev_attr.attr, | ||
327 | &sensor_dev_attr_curr1_max.dev_attr.attr, | ||
328 | &sensor_dev_attr_curr1_max_alarm.dev_attr.attr, | ||
329 | &sensor_dev_attr_in4_input.dev_attr.attr, | ||
330 | |||
331 | /* channel 2 */ | ||
332 | &sensor_dev_attr_in2_input.dev_attr.attr, | ||
333 | &sensor_dev_attr_curr2_input.dev_attr.attr, | ||
334 | &sensor_dev_attr_shunt2_resistor.dev_attr.attr, | ||
335 | &sensor_dev_attr_curr2_crit.dev_attr.attr, | ||
336 | &sensor_dev_attr_curr2_crit_alarm.dev_attr.attr, | ||
337 | &sensor_dev_attr_curr2_max.dev_attr.attr, | ||
338 | &sensor_dev_attr_curr2_max_alarm.dev_attr.attr, | ||
339 | &sensor_dev_attr_in5_input.dev_attr.attr, | ||
340 | |||
341 | /* channel 3 */ | ||
342 | &sensor_dev_attr_in3_input.dev_attr.attr, | ||
343 | &sensor_dev_attr_curr3_input.dev_attr.attr, | ||
344 | &sensor_dev_attr_shunt3_resistor.dev_attr.attr, | ||
345 | &sensor_dev_attr_curr3_crit.dev_attr.attr, | ||
346 | &sensor_dev_attr_curr3_crit_alarm.dev_attr.attr, | ||
347 | &sensor_dev_attr_curr3_max.dev_attr.attr, | ||
348 | &sensor_dev_attr_curr3_max_alarm.dev_attr.attr, | ||
349 | &sensor_dev_attr_in6_input.dev_attr.attr, | ||
350 | |||
351 | NULL, | ||
352 | }; | ||
353 | ATTRIBUTE_GROUPS(ina3221); | ||
354 | |||
355 | static const struct regmap_range ina3221_yes_ranges[] = { | ||
356 | regmap_reg_range(INA3221_SHUNT1, INA3221_BUS3), | ||
357 | regmap_reg_range(INA3221_MASK_ENABLE, INA3221_MASK_ENABLE), | ||
358 | }; | ||
359 | |||
360 | static const struct regmap_access_table ina3221_volatile_table = { | ||
361 | .yes_ranges = ina3221_yes_ranges, | ||
362 | .n_yes_ranges = ARRAY_SIZE(ina3221_yes_ranges), | ||
363 | }; | ||
364 | |||
365 | static const struct regmap_config ina3221_regmap_config = { | ||
366 | .reg_bits = 8, | ||
367 | .val_bits = 16, | ||
368 | |||
369 | .cache_type = REGCACHE_RBTREE, | ||
370 | .volatile_table = &ina3221_volatile_table, | ||
371 | }; | ||
372 | |||
373 | static int ina3221_probe(struct i2c_client *client, | ||
374 | const struct i2c_device_id *id) | ||
375 | { | ||
376 | struct device *dev = &client->dev; | ||
377 | struct ina3221_data *ina; | ||
378 | struct device *hwmon_dev; | ||
379 | int i, ret; | ||
380 | |||
381 | ina = devm_kzalloc(dev, sizeof(*ina), GFP_KERNEL); | ||
382 | if (!ina) | ||
383 | return -ENOMEM; | ||
384 | |||
385 | ina->regmap = devm_regmap_init_i2c(client, &ina3221_regmap_config); | ||
386 | if (IS_ERR(ina->regmap)) { | ||
387 | dev_err(dev, "Unable to allocate register map\n"); | ||
388 | return PTR_ERR(ina->regmap); | ||
389 | } | ||
390 | |||
391 | for (i = 0; i < F_MAX_FIELDS; i++) { | ||
392 | ina->fields[i] = devm_regmap_field_alloc(dev, | ||
393 | ina->regmap, | ||
394 | ina3221_reg_fields[i]); | ||
395 | if (IS_ERR(ina->fields[i])) { | ||
396 | dev_err(dev, "Unable to allocate regmap fields\n"); | ||
397 | return PTR_ERR(ina->fields[i]); | ||
398 | } | ||
399 | } | ||
400 | |||
401 | for (i = 0; i < INA3221_NUM_CHANNELS; i++) | ||
402 | ina->shunt_resistors[i] = INA3221_RSHUNT_DEFAULT; | ||
403 | |||
404 | ret = regmap_field_write(ina->fields[F_RST], true); | ||
405 | if (ret) { | ||
406 | dev_err(dev, "Unable to reset device\n"); | ||
407 | return ret; | ||
408 | } | ||
409 | |||
410 | hwmon_dev = devm_hwmon_device_register_with_groups(dev, | ||
411 | client->name, | ||
412 | ina, ina3221_groups); | ||
413 | if (IS_ERR(hwmon_dev)) { | ||
414 | dev_err(dev, "Unable to register hwmon device\n"); | ||
415 | return PTR_ERR(hwmon_dev); | ||
416 | } | ||
417 | |||
418 | return 0; | ||
419 | } | ||
420 | |||
421 | static const struct of_device_id ina3221_of_match_table[] = { | ||
422 | { .compatible = "ti,ina3221", }, | ||
423 | { /* sentinel */ } | ||
424 | }; | ||
425 | MODULE_DEVICE_TABLE(of, ina3221_of_match_table); | ||
426 | |||
427 | static const struct i2c_device_id ina3221_ids[] = { | ||
428 | { "ina3221", 0 }, | ||
429 | { /* sentinel */ } | ||
430 | }; | ||
431 | MODULE_DEVICE_TABLE(i2c, ina3221_ids); | ||
432 | |||
433 | static struct i2c_driver ina3221_i2c_driver = { | ||
434 | .probe = ina3221_probe, | ||
435 | .driver = { | ||
436 | .name = INA3221_DRIVER_NAME, | ||
437 | .of_match_table = ina3221_of_match_table, | ||
438 | }, | ||
439 | .id_table = ina3221_ids, | ||
440 | }; | ||
441 | module_i2c_driver(ina3221_i2c_driver); | ||
442 | |||
443 | MODULE_AUTHOR("Andrew F. Davis <afd@ti.com>"); | ||
444 | MODULE_DESCRIPTION("Texas Instruments INA3221 HWMon Driver"); | ||
445 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/hwmon/jc42.c b/drivers/hwmon/jc42.c index 9887d3224a86..9d5f85f3384f 100644 --- a/drivers/hwmon/jc42.c +++ b/drivers/hwmon/jc42.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <linux/hwmon-sysfs.h> | 31 | #include <linux/hwmon-sysfs.h> |
32 | #include <linux/err.h> | 32 | #include <linux/err.h> |
33 | #include <linux/mutex.h> | 33 | #include <linux/mutex.h> |
34 | #include <linux/of.h> | ||
34 | 35 | ||
35 | /* Addresses to scan */ | 36 | /* Addresses to scan */ |
36 | static const unsigned short normal_i2c[] = { | 37 | static const unsigned short normal_i2c[] = { |
@@ -104,6 +105,9 @@ static const unsigned short normal_i2c[] = { | |||
104 | #define MCP9804_DEVID 0x0200 | 105 | #define MCP9804_DEVID 0x0200 |
105 | #define MCP9804_DEVID_MASK 0xfffc | 106 | #define MCP9804_DEVID_MASK 0xfffc |
106 | 107 | ||
108 | #define MCP9808_DEVID 0x0400 | ||
109 | #define MCP9808_DEVID_MASK 0xfffc | ||
110 | |||
107 | #define MCP98242_DEVID 0x2000 | 111 | #define MCP98242_DEVID 0x2000 |
108 | #define MCP98242_DEVID_MASK 0xfffc | 112 | #define MCP98242_DEVID_MASK 0xfffc |
109 | 113 | ||
@@ -160,6 +164,7 @@ static struct jc42_chips jc42_chips[] = { | |||
160 | { IDT_MANID, TS3001_DEVID, TS3001_DEVID_MASK }, | 164 | { IDT_MANID, TS3001_DEVID, TS3001_DEVID_MASK }, |
161 | { MAX_MANID, MAX6604_DEVID, MAX6604_DEVID_MASK }, | 165 | { MAX_MANID, MAX6604_DEVID, MAX6604_DEVID_MASK }, |
162 | { MCP_MANID, MCP9804_DEVID, MCP9804_DEVID_MASK }, | 166 | { MCP_MANID, MCP9804_DEVID, MCP9804_DEVID_MASK }, |
167 | { MCP_MANID, MCP9808_DEVID, MCP9808_DEVID_MASK }, | ||
163 | { MCP_MANID, MCP98242_DEVID, MCP98242_DEVID_MASK }, | 168 | { MCP_MANID, MCP98242_DEVID, MCP98242_DEVID_MASK }, |
164 | { MCP_MANID, MCP98243_DEVID, MCP98243_DEVID_MASK }, | 169 | { MCP_MANID, MCP98243_DEVID, MCP98243_DEVID_MASK }, |
165 | { MCP_MANID, MCP98244_DEVID, MCP98244_DEVID_MASK }, | 170 | { MCP_MANID, MCP98244_DEVID, MCP98244_DEVID_MASK }, |
@@ -537,11 +542,20 @@ static const struct i2c_device_id jc42_id[] = { | |||
537 | }; | 542 | }; |
538 | MODULE_DEVICE_TABLE(i2c, jc42_id); | 543 | MODULE_DEVICE_TABLE(i2c, jc42_id); |
539 | 544 | ||
545 | #ifdef CONFIG_OF | ||
546 | static const struct of_device_id jc42_of_ids[] = { | ||
547 | { .compatible = "jedec,jc-42.4-temp", }, | ||
548 | { } | ||
549 | }; | ||
550 | MODULE_DEVICE_TABLE(of, jc42_of_ids); | ||
551 | #endif | ||
552 | |||
540 | static struct i2c_driver jc42_driver = { | 553 | static struct i2c_driver jc42_driver = { |
541 | .class = I2C_CLASS_SPD, | 554 | .class = I2C_CLASS_SPD | I2C_CLASS_HWMON, |
542 | .driver = { | 555 | .driver = { |
543 | .name = "jc42", | 556 | .name = "jc42", |
544 | .pm = JC42_DEV_PM_OPS, | 557 | .pm = JC42_DEV_PM_OPS, |
558 | .of_match_table = of_match_ptr(jc42_of_ids), | ||
545 | }, | 559 | }, |
546 | .probe = jc42_probe, | 560 | .probe = jc42_probe, |
547 | .remove = jc42_remove, | 561 | .remove = jc42_remove, |
diff --git a/drivers/hwmon/jz4740-hwmon.c b/drivers/hwmon/jz4740-hwmon.c index df9b3447f2a8..0621ee1b3c98 100644 --- a/drivers/hwmon/jz4740-hwmon.c +++ b/drivers/hwmon/jz4740-hwmon.c | |||
@@ -29,23 +29,13 @@ | |||
29 | 29 | ||
30 | struct jz4740_hwmon { | 30 | struct jz4740_hwmon { |
31 | void __iomem *base; | 31 | void __iomem *base; |
32 | |||
33 | int irq; | 32 | int irq; |
34 | |||
35 | const struct mfd_cell *cell; | 33 | const struct mfd_cell *cell; |
36 | struct device *hwmon; | 34 | struct platform_device *pdev; |
37 | |||
38 | struct completion read_completion; | 35 | struct completion read_completion; |
39 | |||
40 | struct mutex lock; | 36 | struct mutex lock; |
41 | }; | 37 | }; |
42 | 38 | ||
43 | static ssize_t jz4740_hwmon_show_name(struct device *dev, | ||
44 | struct device_attribute *dev_attr, char *buf) | ||
45 | { | ||
46 | return sprintf(buf, "jz4740\n"); | ||
47 | } | ||
48 | |||
49 | static irqreturn_t jz4740_hwmon_irq(int irq, void *data) | 39 | static irqreturn_t jz4740_hwmon_irq(int irq, void *data) |
50 | { | 40 | { |
51 | struct jz4740_hwmon *hwmon = data; | 41 | struct jz4740_hwmon *hwmon = data; |
@@ -58,6 +48,7 @@ static ssize_t jz4740_hwmon_read_adcin(struct device *dev, | |||
58 | struct device_attribute *dev_attr, char *buf) | 48 | struct device_attribute *dev_attr, char *buf) |
59 | { | 49 | { |
60 | struct jz4740_hwmon *hwmon = dev_get_drvdata(dev); | 50 | struct jz4740_hwmon *hwmon = dev_get_drvdata(dev); |
51 | struct platform_device *pdev = hwmon->pdev; | ||
61 | struct completion *completion = &hwmon->read_completion; | 52 | struct completion *completion = &hwmon->read_completion; |
62 | long t; | 53 | long t; |
63 | unsigned long val; | 54 | unsigned long val; |
@@ -68,7 +59,7 @@ static ssize_t jz4740_hwmon_read_adcin(struct device *dev, | |||
68 | reinit_completion(completion); | 59 | reinit_completion(completion); |
69 | 60 | ||
70 | enable_irq(hwmon->irq); | 61 | enable_irq(hwmon->irq); |
71 | hwmon->cell->enable(to_platform_device(dev)); | 62 | hwmon->cell->enable(pdev); |
72 | 63 | ||
73 | t = wait_for_completion_interruptible_timeout(completion, HZ); | 64 | t = wait_for_completion_interruptible_timeout(completion, HZ); |
74 | 65 | ||
@@ -80,7 +71,7 @@ static ssize_t jz4740_hwmon_read_adcin(struct device *dev, | |||
80 | ret = t ? t : -ETIMEDOUT; | 71 | ret = t ? t : -ETIMEDOUT; |
81 | } | 72 | } |
82 | 73 | ||
83 | hwmon->cell->disable(to_platform_device(dev)); | 74 | hwmon->cell->disable(pdev); |
84 | disable_irq(hwmon->irq); | 75 | disable_irq(hwmon->irq); |
85 | 76 | ||
86 | mutex_unlock(&hwmon->lock); | 77 | mutex_unlock(&hwmon->lock); |
@@ -88,26 +79,24 @@ static ssize_t jz4740_hwmon_read_adcin(struct device *dev, | |||
88 | return ret; | 79 | return ret; |
89 | } | 80 | } |
90 | 81 | ||
91 | static DEVICE_ATTR(name, S_IRUGO, jz4740_hwmon_show_name, NULL); | ||
92 | static DEVICE_ATTR(in0_input, S_IRUGO, jz4740_hwmon_read_adcin, NULL); | 82 | static DEVICE_ATTR(in0_input, S_IRUGO, jz4740_hwmon_read_adcin, NULL); |
93 | 83 | ||
94 | static struct attribute *jz4740_hwmon_attributes[] = { | 84 | static struct attribute *jz4740_attrs[] = { |
95 | &dev_attr_name.attr, | ||
96 | &dev_attr_in0_input.attr, | 85 | &dev_attr_in0_input.attr, |
97 | NULL | 86 | NULL |
98 | }; | 87 | }; |
99 | 88 | ||
100 | static const struct attribute_group jz4740_hwmon_attr_group = { | 89 | ATTRIBUTE_GROUPS(jz4740); |
101 | .attrs = jz4740_hwmon_attributes, | ||
102 | }; | ||
103 | 90 | ||
104 | static int jz4740_hwmon_probe(struct platform_device *pdev) | 91 | static int jz4740_hwmon_probe(struct platform_device *pdev) |
105 | { | 92 | { |
106 | int ret; | 93 | int ret; |
94 | struct device *dev = &pdev->dev; | ||
107 | struct jz4740_hwmon *hwmon; | 95 | struct jz4740_hwmon *hwmon; |
96 | struct device *hwmon_dev; | ||
108 | struct resource *mem; | 97 | struct resource *mem; |
109 | 98 | ||
110 | hwmon = devm_kzalloc(&pdev->dev, sizeof(*hwmon), GFP_KERNEL); | 99 | hwmon = devm_kzalloc(dev, sizeof(*hwmon), GFP_KERNEL); |
111 | if (!hwmon) | 100 | if (!hwmon) |
112 | return -ENOMEM; | 101 | return -ENOMEM; |
113 | 102 | ||
@@ -125,12 +114,11 @@ static int jz4740_hwmon_probe(struct platform_device *pdev) | |||
125 | if (IS_ERR(hwmon->base)) | 114 | if (IS_ERR(hwmon->base)) |
126 | return PTR_ERR(hwmon->base); | 115 | return PTR_ERR(hwmon->base); |
127 | 116 | ||
117 | hwmon->pdev = pdev; | ||
128 | init_completion(&hwmon->read_completion); | 118 | init_completion(&hwmon->read_completion); |
129 | mutex_init(&hwmon->lock); | 119 | mutex_init(&hwmon->lock); |
130 | 120 | ||
131 | platform_set_drvdata(pdev, hwmon); | 121 | ret = devm_request_irq(dev, hwmon->irq, jz4740_hwmon_irq, 0, |
132 | |||
133 | ret = devm_request_irq(&pdev->dev, hwmon->irq, jz4740_hwmon_irq, 0, | ||
134 | pdev->name, hwmon); | 122 | pdev->name, hwmon); |
135 | if (ret) { | 123 | if (ret) { |
136 | dev_err(&pdev->dev, "Failed to request irq: %d\n", ret); | 124 | dev_err(&pdev->dev, "Failed to request irq: %d\n", ret); |
@@ -138,38 +126,13 @@ static int jz4740_hwmon_probe(struct platform_device *pdev) | |||
138 | } | 126 | } |
139 | disable_irq(hwmon->irq); | 127 | disable_irq(hwmon->irq); |
140 | 128 | ||
141 | ret = sysfs_create_group(&pdev->dev.kobj, &jz4740_hwmon_attr_group); | 129 | hwmon_dev = devm_hwmon_device_register_with_groups(dev, "jz4740", hwmon, |
142 | if (ret) { | 130 | jz4740_groups); |
143 | dev_err(&pdev->dev, "Failed to create sysfs group: %d\n", ret); | 131 | return PTR_ERR_OR_ZERO(hwmon_dev); |
144 | return ret; | ||
145 | } | ||
146 | |||
147 | hwmon->hwmon = hwmon_device_register(&pdev->dev); | ||
148 | if (IS_ERR(hwmon->hwmon)) { | ||
149 | ret = PTR_ERR(hwmon->hwmon); | ||
150 | goto err_remove_file; | ||
151 | } | ||
152 | |||
153 | return 0; | ||
154 | |||
155 | err_remove_file: | ||
156 | sysfs_remove_group(&pdev->dev.kobj, &jz4740_hwmon_attr_group); | ||
157 | return ret; | ||
158 | } | ||
159 | |||
160 | static int jz4740_hwmon_remove(struct platform_device *pdev) | ||
161 | { | ||
162 | struct jz4740_hwmon *hwmon = platform_get_drvdata(pdev); | ||
163 | |||
164 | hwmon_device_unregister(hwmon->hwmon); | ||
165 | sysfs_remove_group(&pdev->dev.kobj, &jz4740_hwmon_attr_group); | ||
166 | |||
167 | return 0; | ||
168 | } | 132 | } |
169 | 133 | ||
170 | static struct platform_driver jz4740_hwmon_driver = { | 134 | static struct platform_driver jz4740_hwmon_driver = { |
171 | .probe = jz4740_hwmon_probe, | 135 | .probe = jz4740_hwmon_probe, |
172 | .remove = jz4740_hwmon_remove, | ||
173 | .driver = { | 136 | .driver = { |
174 | .name = "jz4740-hwmon", | 137 | .name = "jz4740-hwmon", |
175 | }, | 138 | }, |
diff --git a/drivers/hwmon/lm75.c b/drivers/hwmon/lm75.c index 69166ab3151d..547a9c87c68c 100644 --- a/drivers/hwmon/lm75.c +++ b/drivers/hwmon/lm75.c | |||
@@ -26,8 +26,8 @@ | |||
26 | #include <linux/hwmon.h> | 26 | #include <linux/hwmon.h> |
27 | #include <linux/hwmon-sysfs.h> | 27 | #include <linux/hwmon-sysfs.h> |
28 | #include <linux/err.h> | 28 | #include <linux/err.h> |
29 | #include <linux/mutex.h> | ||
30 | #include <linux/of.h> | 29 | #include <linux/of.h> |
30 | #include <linux/regmap.h> | ||
31 | #include <linux/thermal.h> | 31 | #include <linux/thermal.h> |
32 | #include "lm75.h" | 32 | #include "lm75.h" |
33 | 33 | ||
@@ -66,35 +66,21 @@ static const unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, 0x4c, | |||
66 | 66 | ||
67 | 67 | ||
68 | /* The LM75 registers */ | 68 | /* The LM75 registers */ |
69 | #define LM75_REG_TEMP 0x00 | ||
69 | #define LM75_REG_CONF 0x01 | 70 | #define LM75_REG_CONF 0x01 |
70 | static const u8 LM75_REG_TEMP[3] = { | 71 | #define LM75_REG_HYST 0x02 |
71 | 0x00, /* input */ | 72 | #define LM75_REG_MAX 0x03 |
72 | 0x03, /* max */ | ||
73 | 0x02, /* hyst */ | ||
74 | }; | ||
75 | 73 | ||
76 | /* Each client has this additional data */ | 74 | /* Each client has this additional data */ |
77 | struct lm75_data { | 75 | struct lm75_data { |
78 | struct i2c_client *client; | 76 | struct i2c_client *client; |
79 | struct device *hwmon_dev; | 77 | struct regmap *regmap; |
80 | struct mutex update_lock; | ||
81 | u8 orig_conf; | 78 | u8 orig_conf; |
82 | u8 resolution; /* In bits, between 9 and 12 */ | 79 | u8 resolution; /* In bits, between 9 and 12 */ |
83 | u8 resolution_limits; | 80 | u8 resolution_limits; |
84 | char valid; /* !=0 if registers are valid */ | 81 | unsigned int sample_time; /* In ms */ |
85 | unsigned long last_updated; /* In jiffies */ | ||
86 | unsigned long sample_time; /* In jiffies */ | ||
87 | s16 temp[3]; /* Register values, | ||
88 | 0 = input | ||
89 | 1 = max | ||
90 | 2 = hyst */ | ||
91 | }; | 82 | }; |
92 | 83 | ||
93 | static int lm75_read_value(struct i2c_client *client, u8 reg); | ||
94 | static int lm75_write_value(struct i2c_client *client, u8 reg, u16 value); | ||
95 | static struct lm75_data *lm75_update_device(struct device *dev); | ||
96 | |||
97 | |||
98 | /*-----------------------------------------------------------------------*/ | 84 | /*-----------------------------------------------------------------------*/ |
99 | 85 | ||
100 | static inline long lm75_reg_to_mc(s16 temp, u8 resolution) | 86 | static inline long lm75_reg_to_mc(s16 temp, u8 resolution) |
@@ -106,12 +92,15 @@ static inline long lm75_reg_to_mc(s16 temp, u8 resolution) | |||
106 | 92 | ||
107 | static int lm75_read_temp(void *dev, int *temp) | 93 | static int lm75_read_temp(void *dev, int *temp) |
108 | { | 94 | { |
109 | struct lm75_data *data = lm75_update_device(dev); | 95 | struct lm75_data *data = dev_get_drvdata(dev); |
96 | unsigned int _temp; | ||
97 | int err; | ||
110 | 98 | ||
111 | if (IS_ERR(data)) | 99 | err = regmap_read(data->regmap, LM75_REG_TEMP, &_temp); |
112 | return PTR_ERR(data); | 100 | if (err < 0) |
101 | return err; | ||
113 | 102 | ||
114 | *temp = lm75_reg_to_mc(data->temp[0], data->resolution); | 103 | *temp = lm75_reg_to_mc(_temp, data->resolution); |
115 | 104 | ||
116 | return 0; | 105 | return 0; |
117 | } | 106 | } |
@@ -120,13 +109,15 @@ static ssize_t show_temp(struct device *dev, struct device_attribute *da, | |||
120 | char *buf) | 109 | char *buf) |
121 | { | 110 | { |
122 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); | 111 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); |
123 | struct lm75_data *data = lm75_update_device(dev); | 112 | struct lm75_data *data = dev_get_drvdata(dev); |
113 | unsigned int temp = 0; | ||
114 | int err; | ||
124 | 115 | ||
125 | if (IS_ERR(data)) | 116 | err = regmap_read(data->regmap, attr->index, &temp); |
126 | return PTR_ERR(data); | 117 | if (err < 0) |
118 | return err; | ||
127 | 119 | ||
128 | return sprintf(buf, "%ld\n", lm75_reg_to_mc(data->temp[attr->index], | 120 | return sprintf(buf, "%ld\n", lm75_reg_to_mc(temp, data->resolution)); |
129 | data->resolution)); | ||
130 | } | 121 | } |
131 | 122 | ||
132 | static ssize_t set_temp(struct device *dev, struct device_attribute *da, | 123 | static ssize_t set_temp(struct device *dev, struct device_attribute *da, |
@@ -134,8 +125,6 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *da, | |||
134 | { | 125 | { |
135 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); | 126 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); |
136 | struct lm75_data *data = dev_get_drvdata(dev); | 127 | struct lm75_data *data = dev_get_drvdata(dev); |
137 | struct i2c_client *client = data->client; | ||
138 | int nr = attr->index; | ||
139 | long temp; | 128 | long temp; |
140 | int error; | 129 | int error; |
141 | u8 resolution; | 130 | u8 resolution; |
@@ -153,25 +142,36 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *da, | |||
153 | else | 142 | else |
154 | resolution = data->resolution; | 143 | resolution = data->resolution; |
155 | 144 | ||
156 | mutex_lock(&data->update_lock); | ||
157 | temp = clamp_val(temp, LM75_TEMP_MIN, LM75_TEMP_MAX); | 145 | temp = clamp_val(temp, LM75_TEMP_MIN, LM75_TEMP_MAX); |
158 | data->temp[nr] = DIV_ROUND_CLOSEST(temp << (resolution - 8), | 146 | temp = DIV_ROUND_CLOSEST(temp << (resolution - 8), |
159 | 1000) << (16 - resolution); | 147 | 1000) << (16 - resolution); |
160 | lm75_write_value(client, LM75_REG_TEMP[nr], data->temp[nr]); | 148 | error = regmap_write(data->regmap, attr->index, temp); |
161 | mutex_unlock(&data->update_lock); | 149 | if (error < 0) |
150 | return error; | ||
151 | |||
162 | return count; | 152 | return count; |
163 | } | 153 | } |
164 | 154 | ||
155 | static ssize_t show_update_interval(struct device *dev, | ||
156 | struct device_attribute *da, char *buf) | ||
157 | { | ||
158 | struct lm75_data *data = dev_get_drvdata(dev); | ||
159 | |||
160 | return sprintf(buf, "%u\n", data->sample_time); | ||
161 | } | ||
162 | |||
165 | static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, | 163 | static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, |
166 | show_temp, set_temp, 1); | 164 | show_temp, set_temp, LM75_REG_MAX); |
167 | static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO, | 165 | static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO, |
168 | show_temp, set_temp, 2); | 166 | show_temp, set_temp, LM75_REG_HYST); |
169 | static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0); | 167 | static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, LM75_REG_TEMP); |
168 | static DEVICE_ATTR(update_interval, S_IRUGO, show_update_interval, NULL); | ||
170 | 169 | ||
171 | static struct attribute *lm75_attrs[] = { | 170 | static struct attribute *lm75_attrs[] = { |
172 | &sensor_dev_attr_temp1_input.dev_attr.attr, | 171 | &sensor_dev_attr_temp1_input.dev_attr.attr, |
173 | &sensor_dev_attr_temp1_max.dev_attr.attr, | 172 | &sensor_dev_attr_temp1_max.dev_attr.attr, |
174 | &sensor_dev_attr_temp1_max_hyst.dev_attr.attr, | 173 | &sensor_dev_attr_temp1_max_hyst.dev_attr.attr, |
174 | &dev_attr_update_interval.attr, | ||
175 | 175 | ||
176 | NULL | 176 | NULL |
177 | }; | 177 | }; |
@@ -185,10 +185,40 @@ static const struct thermal_zone_of_device_ops lm75_of_thermal_ops = { | |||
185 | 185 | ||
186 | /* device probe and removal */ | 186 | /* device probe and removal */ |
187 | 187 | ||
188 | static bool lm75_is_writeable_reg(struct device *dev, unsigned int reg) | ||
189 | { | ||
190 | return reg != LM75_REG_TEMP; | ||
191 | } | ||
192 | |||
193 | static bool lm75_is_volatile_reg(struct device *dev, unsigned int reg) | ||
194 | { | ||
195 | return reg == LM75_REG_TEMP; | ||
196 | } | ||
197 | |||
198 | static const struct regmap_config lm75_regmap_config = { | ||
199 | .reg_bits = 8, | ||
200 | .val_bits = 16, | ||
201 | .max_register = LM75_REG_MAX, | ||
202 | .writeable_reg = lm75_is_writeable_reg, | ||
203 | .volatile_reg = lm75_is_volatile_reg, | ||
204 | .val_format_endian = REGMAP_ENDIAN_BIG, | ||
205 | .cache_type = REGCACHE_RBTREE, | ||
206 | .use_single_rw = true, | ||
207 | }; | ||
208 | |||
209 | static void lm75_remove(void *data) | ||
210 | { | ||
211 | struct lm75_data *lm75 = data; | ||
212 | struct i2c_client *client = lm75->client; | ||
213 | |||
214 | i2c_smbus_write_byte_data(client, LM75_REG_CONF, lm75->orig_conf); | ||
215 | } | ||
216 | |||
188 | static int | 217 | static int |
189 | lm75_probe(struct i2c_client *client, const struct i2c_device_id *id) | 218 | lm75_probe(struct i2c_client *client, const struct i2c_device_id *id) |
190 | { | 219 | { |
191 | struct device *dev = &client->dev; | 220 | struct device *dev = &client->dev; |
221 | struct device *hwmon_dev; | ||
192 | struct lm75_data *data; | 222 | struct lm75_data *data; |
193 | int status; | 223 | int status; |
194 | u8 set_mask, clr_mask; | 224 | u8 set_mask, clr_mask; |
@@ -204,8 +234,10 @@ lm75_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
204 | return -ENOMEM; | 234 | return -ENOMEM; |
205 | 235 | ||
206 | data->client = client; | 236 | data->client = client; |
207 | i2c_set_clientdata(client, data); | 237 | |
208 | mutex_init(&data->update_lock); | 238 | data->regmap = devm_regmap_init_i2c(client, &lm75_regmap_config); |
239 | if (IS_ERR(data->regmap)) | ||
240 | return PTR_ERR(data->regmap); | ||
209 | 241 | ||
210 | /* Set to LM75 resolution (9 bits, 1/2 degree C) and range. | 242 | /* Set to LM75 resolution (9 bits, 1/2 degree C) and range. |
211 | * Then tweak to be more precise when appropriate. | 243 | * Then tweak to be more precise when appropriate. |
@@ -217,7 +249,7 @@ lm75_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
217 | case adt75: | 249 | case adt75: |
218 | clr_mask |= 1 << 5; /* not one-shot mode */ | 250 | clr_mask |= 1 << 5; /* not one-shot mode */ |
219 | data->resolution = 12; | 251 | data->resolution = 12; |
220 | data->sample_time = HZ / 8; | 252 | data->sample_time = MSEC_PER_SEC / 8; |
221 | break; | 253 | break; |
222 | case ds1775: | 254 | case ds1775: |
223 | case ds75: | 255 | case ds75: |
@@ -225,35 +257,35 @@ lm75_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
225 | clr_mask |= 3 << 5; | 257 | clr_mask |= 3 << 5; |
226 | set_mask |= 2 << 5; /* 11-bit mode */ | 258 | set_mask |= 2 << 5; /* 11-bit mode */ |
227 | data->resolution = 11; | 259 | data->resolution = 11; |
228 | data->sample_time = HZ; | 260 | data->sample_time = MSEC_PER_SEC; |
229 | break; | 261 | break; |
230 | case ds7505: | 262 | case ds7505: |
231 | set_mask |= 3 << 5; /* 12-bit mode */ | 263 | set_mask |= 3 << 5; /* 12-bit mode */ |
232 | data->resolution = 12; | 264 | data->resolution = 12; |
233 | data->sample_time = HZ / 4; | 265 | data->sample_time = MSEC_PER_SEC / 4; |
234 | break; | 266 | break; |
235 | case g751: | 267 | case g751: |
236 | case lm75: | 268 | case lm75: |
237 | case lm75a: | 269 | case lm75a: |
238 | data->resolution = 9; | 270 | data->resolution = 9; |
239 | data->sample_time = HZ / 2; | 271 | data->sample_time = MSEC_PER_SEC / 2; |
240 | break; | 272 | break; |
241 | case lm75b: | 273 | case lm75b: |
242 | data->resolution = 11; | 274 | data->resolution = 11; |
243 | data->sample_time = HZ / 4; | 275 | data->sample_time = MSEC_PER_SEC / 4; |
244 | break; | 276 | break; |
245 | case max6625: | 277 | case max6625: |
246 | data->resolution = 9; | 278 | data->resolution = 9; |
247 | data->sample_time = HZ / 4; | 279 | data->sample_time = MSEC_PER_SEC / 4; |
248 | break; | 280 | break; |
249 | case max6626: | 281 | case max6626: |
250 | data->resolution = 12; | 282 | data->resolution = 12; |
251 | data->resolution_limits = 9; | 283 | data->resolution_limits = 9; |
252 | data->sample_time = HZ / 4; | 284 | data->sample_time = MSEC_PER_SEC / 4; |
253 | break; | 285 | break; |
254 | case tcn75: | 286 | case tcn75: |
255 | data->resolution = 9; | 287 | data->resolution = 9; |
256 | data->sample_time = HZ / 8; | 288 | data->sample_time = MSEC_PER_SEC / 8; |
257 | break; | 289 | break; |
258 | case mcp980x: | 290 | case mcp980x: |
259 | data->resolution_limits = 9; | 291 | data->resolution_limits = 9; |
@@ -262,14 +294,14 @@ lm75_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
262 | case tmp101: | 294 | case tmp101: |
263 | set_mask |= 3 << 5; /* 12-bit mode */ | 295 | set_mask |= 3 << 5; /* 12-bit mode */ |
264 | data->resolution = 12; | 296 | data->resolution = 12; |
265 | data->sample_time = HZ; | 297 | data->sample_time = MSEC_PER_SEC; |
266 | clr_mask |= 1 << 7; /* not one-shot mode */ | 298 | clr_mask |= 1 << 7; /* not one-shot mode */ |
267 | break; | 299 | break; |
268 | case tmp112: | 300 | case tmp112: |
269 | set_mask |= 3 << 5; /* 12-bit mode */ | 301 | set_mask |= 3 << 5; /* 12-bit mode */ |
270 | clr_mask |= 1 << 7; /* not one-shot mode */ | 302 | clr_mask |= 1 << 7; /* not one-shot mode */ |
271 | data->resolution = 12; | 303 | data->resolution = 12; |
272 | data->sample_time = HZ / 4; | 304 | data->sample_time = MSEC_PER_SEC / 4; |
273 | break; | 305 | break; |
274 | case tmp105: | 306 | case tmp105: |
275 | case tmp175: | 307 | case tmp175: |
@@ -278,17 +310,17 @@ lm75_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
278 | set_mask |= 3 << 5; /* 12-bit mode */ | 310 | set_mask |= 3 << 5; /* 12-bit mode */ |
279 | clr_mask |= 1 << 7; /* not one-shot mode */ | 311 | clr_mask |= 1 << 7; /* not one-shot mode */ |
280 | data->resolution = 12; | 312 | data->resolution = 12; |
281 | data->sample_time = HZ / 2; | 313 | data->sample_time = MSEC_PER_SEC / 2; |
282 | break; | 314 | break; |
283 | case tmp75c: | 315 | case tmp75c: |
284 | clr_mask |= 1 << 5; /* not one-shot mode */ | 316 | clr_mask |= 1 << 5; /* not one-shot mode */ |
285 | data->resolution = 12; | 317 | data->resolution = 12; |
286 | data->sample_time = HZ / 4; | 318 | data->sample_time = MSEC_PER_SEC / 4; |
287 | break; | 319 | break; |
288 | } | 320 | } |
289 | 321 | ||
290 | /* configure as specified */ | 322 | /* configure as specified */ |
291 | status = lm75_read_value(client, LM75_REG_CONF); | 323 | status = i2c_smbus_read_byte_data(client, LM75_REG_CONF); |
292 | if (status < 0) { | 324 | if (status < 0) { |
293 | dev_dbg(dev, "Can't read config? %d\n", status); | 325 | dev_dbg(dev, "Can't read config? %d\n", status); |
294 | return status; | 326 | return status; |
@@ -297,30 +329,23 @@ lm75_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
297 | new = status & ~clr_mask; | 329 | new = status & ~clr_mask; |
298 | new |= set_mask; | 330 | new |= set_mask; |
299 | if (status != new) | 331 | if (status != new) |
300 | lm75_write_value(client, LM75_REG_CONF, new); | 332 | i2c_smbus_write_byte_data(client, LM75_REG_CONF, new); |
301 | dev_dbg(dev, "Config %02x\n", new); | ||
302 | 333 | ||
303 | data->hwmon_dev = hwmon_device_register_with_groups(dev, client->name, | 334 | devm_add_action(dev, lm75_remove, data); |
304 | data, lm75_groups); | ||
305 | if (IS_ERR(data->hwmon_dev)) | ||
306 | return PTR_ERR(data->hwmon_dev); | ||
307 | 335 | ||
308 | devm_thermal_zone_of_sensor_register(data->hwmon_dev, 0, | 336 | dev_dbg(dev, "Config %02x\n", new); |
309 | data->hwmon_dev, | ||
310 | &lm75_of_thermal_ops); | ||
311 | 337 | ||
312 | dev_info(dev, "%s: sensor '%s'\n", | 338 | hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name, |
313 | dev_name(data->hwmon_dev), client->name); | 339 | data, lm75_groups); |
340 | if (IS_ERR(hwmon_dev)) | ||
341 | return PTR_ERR(hwmon_dev); | ||
314 | 342 | ||
315 | return 0; | 343 | devm_thermal_zone_of_sensor_register(hwmon_dev, 0, |
316 | } | 344 | hwmon_dev, |
345 | &lm75_of_thermal_ops); | ||
317 | 346 | ||
318 | static int lm75_remove(struct i2c_client *client) | 347 | dev_info(dev, "%s: sensor '%s'\n", dev_name(hwmon_dev), client->name); |
319 | { | ||
320 | struct lm75_data *data = i2c_get_clientdata(client); | ||
321 | 348 | ||
322 | hwmon_device_unregister(data->hwmon_dev); | ||
323 | lm75_write_value(client, LM75_REG_CONF, data->orig_conf); | ||
324 | return 0; | 349 | return 0; |
325 | } | 350 | } |
326 | 351 | ||
@@ -449,13 +474,13 @@ static int lm75_suspend(struct device *dev) | |||
449 | { | 474 | { |
450 | int status; | 475 | int status; |
451 | struct i2c_client *client = to_i2c_client(dev); | 476 | struct i2c_client *client = to_i2c_client(dev); |
452 | status = lm75_read_value(client, LM75_REG_CONF); | 477 | status = i2c_smbus_read_byte_data(client, LM75_REG_CONF); |
453 | if (status < 0) { | 478 | if (status < 0) { |
454 | dev_dbg(&client->dev, "Can't read config? %d\n", status); | 479 | dev_dbg(&client->dev, "Can't read config? %d\n", status); |
455 | return status; | 480 | return status; |
456 | } | 481 | } |
457 | status = status | LM75_SHUTDOWN; | 482 | status = status | LM75_SHUTDOWN; |
458 | lm75_write_value(client, LM75_REG_CONF, status); | 483 | i2c_smbus_write_byte_data(client, LM75_REG_CONF, status); |
459 | return 0; | 484 | return 0; |
460 | } | 485 | } |
461 | 486 | ||
@@ -463,13 +488,13 @@ static int lm75_resume(struct device *dev) | |||
463 | { | 488 | { |
464 | int status; | 489 | int status; |
465 | struct i2c_client *client = to_i2c_client(dev); | 490 | struct i2c_client *client = to_i2c_client(dev); |
466 | status = lm75_read_value(client, LM75_REG_CONF); | 491 | status = i2c_smbus_read_byte_data(client, LM75_REG_CONF); |
467 | if (status < 0) { | 492 | if (status < 0) { |
468 | dev_dbg(&client->dev, "Can't read config? %d\n", status); | 493 | dev_dbg(&client->dev, "Can't read config? %d\n", status); |
469 | return status; | 494 | return status; |
470 | } | 495 | } |
471 | status = status & ~LM75_SHUTDOWN; | 496 | status = status & ~LM75_SHUTDOWN; |
472 | lm75_write_value(client, LM75_REG_CONF, status); | 497 | i2c_smbus_write_byte_data(client, LM75_REG_CONF, status); |
473 | return 0; | 498 | return 0; |
474 | } | 499 | } |
475 | 500 | ||
@@ -489,73 +514,11 @@ static struct i2c_driver lm75_driver = { | |||
489 | .pm = LM75_DEV_PM_OPS, | 514 | .pm = LM75_DEV_PM_OPS, |
490 | }, | 515 | }, |
491 | .probe = lm75_probe, | 516 | .probe = lm75_probe, |
492 | .remove = lm75_remove, | ||
493 | .id_table = lm75_ids, | 517 | .id_table = lm75_ids, |
494 | .detect = lm75_detect, | 518 | .detect = lm75_detect, |
495 | .address_list = normal_i2c, | 519 | .address_list = normal_i2c, |
496 | }; | 520 | }; |
497 | 521 | ||
498 | /*-----------------------------------------------------------------------*/ | ||
499 | |||
500 | /* register access */ | ||
501 | |||
502 | /* | ||
503 | * All registers are word-sized, except for the configuration register. | ||
504 | * LM75 uses a high-byte first convention, which is exactly opposite to | ||
505 | * the SMBus standard. | ||
506 | */ | ||
507 | static int lm75_read_value(struct i2c_client *client, u8 reg) | ||
508 | { | ||
509 | if (reg == LM75_REG_CONF) | ||
510 | return i2c_smbus_read_byte_data(client, reg); | ||
511 | else | ||
512 | return i2c_smbus_read_word_swapped(client, reg); | ||
513 | } | ||
514 | |||
515 | static int lm75_write_value(struct i2c_client *client, u8 reg, u16 value) | ||
516 | { | ||
517 | if (reg == LM75_REG_CONF) | ||
518 | return i2c_smbus_write_byte_data(client, reg, value); | ||
519 | else | ||
520 | return i2c_smbus_write_word_swapped(client, reg, value); | ||
521 | } | ||
522 | |||
523 | static struct lm75_data *lm75_update_device(struct device *dev) | ||
524 | { | ||
525 | struct lm75_data *data = dev_get_drvdata(dev); | ||
526 | struct i2c_client *client = data->client; | ||
527 | struct lm75_data *ret = data; | ||
528 | |||
529 | mutex_lock(&data->update_lock); | ||
530 | |||
531 | if (time_after(jiffies, data->last_updated + data->sample_time) | ||
532 | || !data->valid) { | ||
533 | int i; | ||
534 | dev_dbg(&client->dev, "Starting lm75 update\n"); | ||
535 | |||
536 | for (i = 0; i < ARRAY_SIZE(data->temp); i++) { | ||
537 | int status; | ||
538 | |||
539 | status = lm75_read_value(client, LM75_REG_TEMP[i]); | ||
540 | if (unlikely(status < 0)) { | ||
541 | dev_dbg(dev, | ||
542 | "LM75: Failed to read value: reg %d, error %d\n", | ||
543 | LM75_REG_TEMP[i], status); | ||
544 | ret = ERR_PTR(status); | ||
545 | data->valid = 0; | ||
546 | goto abort; | ||
547 | } | ||
548 | data->temp[i] = status; | ||
549 | } | ||
550 | data->last_updated = jiffies; | ||
551 | data->valid = 1; | ||
552 | } | ||
553 | |||
554 | abort: | ||
555 | mutex_unlock(&data->update_lock); | ||
556 | return ret; | ||
557 | } | ||
558 | |||
559 | module_i2c_driver(lm75_driver); | 522 | module_i2c_driver(lm75_driver); |
560 | 523 | ||
561 | MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>"); | 524 | MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>"); |
diff --git a/drivers/hwmon/lm90.c b/drivers/hwmon/lm90.c index e30a5939dc0d..f51e758ba529 100644 --- a/drivers/hwmon/lm90.c +++ b/drivers/hwmon/lm90.c | |||
@@ -171,7 +171,6 @@ enum chips { lm90, adm1032, lm99, lm86, max6657, max6659, adt7461, max6680, | |||
171 | 171 | ||
172 | #define SA56004_REG_R_LOCAL_TEMPL 0x22 | 172 | #define SA56004_REG_R_LOCAL_TEMPL 0x22 |
173 | 173 | ||
174 | #define LM90_DEF_CONVRATE_RVAL 6 /* Def conversion rate register value */ | ||
175 | #define LM90_MAX_CONVRATE_MS 16000 /* Maximum conversion rate in ms */ | 174 | #define LM90_MAX_CONVRATE_MS 16000 /* Maximum conversion rate in ms */ |
176 | 175 | ||
177 | /* TMP451 registers */ | 176 | /* TMP451 registers */ |
@@ -366,11 +365,9 @@ enum lm90_temp11_reg_index { | |||
366 | 365 | ||
367 | struct lm90_data { | 366 | struct lm90_data { |
368 | struct i2c_client *client; | 367 | struct i2c_client *client; |
369 | struct device *hwmon_dev; | ||
370 | const struct attribute_group *groups[6]; | 368 | const struct attribute_group *groups[6]; |
371 | struct mutex update_lock; | 369 | struct mutex update_lock; |
372 | struct regulator *regulator; | 370 | bool valid; /* true if register values are valid */ |
373 | char valid; /* zero until following fields are valid */ | ||
374 | unsigned long last_updated; /* in jiffies */ | 371 | unsigned long last_updated; /* in jiffies */ |
375 | int kind; | 372 | int kind; |
376 | u32 flags; | 373 | u32 flags; |
@@ -412,7 +409,7 @@ static inline s32 adm1032_write_byte(struct i2c_client *client, u8 value) | |||
412 | * because we don't want the address pointer to change between the write | 409 | * because we don't want the address pointer to change between the write |
413 | * byte and the read byte transactions. | 410 | * byte and the read byte transactions. |
414 | */ | 411 | */ |
415 | static int lm90_read_reg(struct i2c_client *client, u8 reg, u8 *value) | 412 | static int lm90_read_reg(struct i2c_client *client, u8 reg) |
416 | { | 413 | { |
417 | int err; | 414 | int err; |
418 | 415 | ||
@@ -423,20 +420,12 @@ static int lm90_read_reg(struct i2c_client *client, u8 reg, u8 *value) | |||
423 | } else | 420 | } else |
424 | err = i2c_smbus_read_byte_data(client, reg); | 421 | err = i2c_smbus_read_byte_data(client, reg); |
425 | 422 | ||
426 | if (err < 0) { | 423 | return err; |
427 | dev_warn(&client->dev, "Register %#02x read failed (%d)\n", | ||
428 | reg, err); | ||
429 | return err; | ||
430 | } | ||
431 | *value = err; | ||
432 | |||
433 | return 0; | ||
434 | } | 424 | } |
435 | 425 | ||
436 | static int lm90_read16(struct i2c_client *client, u8 regh, u8 regl, u16 *value) | 426 | static int lm90_read16(struct i2c_client *client, u8 regh, u8 regl) |
437 | { | 427 | { |
438 | int err; | 428 | int oldh, newh, l; |
439 | u8 oldh, newh, l; | ||
440 | 429 | ||
441 | /* | 430 | /* |
442 | * There is a trick here. We have to read two registers to have the | 431 | * There is a trick here. We have to read two registers to have the |
@@ -451,18 +440,21 @@ static int lm90_read16(struct i2c_client *client, u8 regh, u8 regl, u16 *value) | |||
451 | * we have to read the low byte again, and now we believe we have a | 440 | * we have to read the low byte again, and now we believe we have a |
452 | * correct reading. | 441 | * correct reading. |
453 | */ | 442 | */ |
454 | if ((err = lm90_read_reg(client, regh, &oldh)) | 443 | oldh = lm90_read_reg(client, regh); |
455 | || (err = lm90_read_reg(client, regl, &l)) | 444 | if (oldh < 0) |
456 | || (err = lm90_read_reg(client, regh, &newh))) | 445 | return oldh; |
457 | return err; | 446 | l = lm90_read_reg(client, regl); |
447 | if (l < 0) | ||
448 | return l; | ||
449 | newh = lm90_read_reg(client, regh); | ||
450 | if (newh < 0) | ||
451 | return newh; | ||
458 | if (oldh != newh) { | 452 | if (oldh != newh) { |
459 | err = lm90_read_reg(client, regl, &l); | 453 | l = lm90_read_reg(client, regl); |
460 | if (err) | 454 | if (l < 0) |
461 | return err; | 455 | return l; |
462 | } | 456 | } |
463 | *value = (newh << 8) | l; | 457 | return (newh << 8) | l; |
464 | |||
465 | return 0; | ||
466 | } | 458 | } |
467 | 459 | ||
468 | /* | 460 | /* |
@@ -473,20 +465,23 @@ static int lm90_read16(struct i2c_client *client, u8 regh, u8 regl, u16 *value) | |||
473 | * various registers have different meanings as a result of selecting a | 465 | * various registers have different meanings as a result of selecting a |
474 | * non-default remote channel. | 466 | * non-default remote channel. |
475 | */ | 467 | */ |
476 | static inline void lm90_select_remote_channel(struct i2c_client *client, | 468 | static inline int lm90_select_remote_channel(struct i2c_client *client, |
477 | struct lm90_data *data, | 469 | struct lm90_data *data, |
478 | int channel) | 470 | int channel) |
479 | { | 471 | { |
480 | u8 config; | 472 | int config; |
481 | 473 | ||
482 | if (data->kind == max6696) { | 474 | if (data->kind == max6696) { |
483 | lm90_read_reg(client, LM90_REG_R_CONFIG1, &config); | 475 | config = lm90_read_reg(client, LM90_REG_R_CONFIG1); |
476 | if (config < 0) | ||
477 | return config; | ||
484 | config &= ~0x08; | 478 | config &= ~0x08; |
485 | if (channel) | 479 | if (channel) |
486 | config |= 0x08; | 480 | config |= 0x08; |
487 | i2c_smbus_write_byte_data(client, LM90_REG_W_CONFIG1, | 481 | i2c_smbus_write_byte_data(client, LM90_REG_W_CONFIG1, |
488 | config); | 482 | config); |
489 | } | 483 | } |
484 | return 0; | ||
490 | } | 485 | } |
491 | 486 | ||
492 | /* | 487 | /* |
@@ -513,118 +508,204 @@ static void lm90_set_convrate(struct i2c_client *client, struct lm90_data *data, | |||
513 | data->update_interval = DIV_ROUND_CLOSEST(update_interval, 64); | 508 | data->update_interval = DIV_ROUND_CLOSEST(update_interval, 64); |
514 | } | 509 | } |
515 | 510 | ||
511 | static int lm90_update_limits(struct device *dev) | ||
512 | { | ||
513 | struct lm90_data *data = dev_get_drvdata(dev); | ||
514 | struct i2c_client *client = data->client; | ||
515 | int val; | ||
516 | |||
517 | val = lm90_read_reg(client, LM90_REG_R_LOCAL_CRIT); | ||
518 | if (val < 0) | ||
519 | return val; | ||
520 | data->temp8[LOCAL_CRIT] = val; | ||
521 | |||
522 | val = lm90_read_reg(client, LM90_REG_R_REMOTE_CRIT); | ||
523 | if (val < 0) | ||
524 | return val; | ||
525 | data->temp8[REMOTE_CRIT] = val; | ||
526 | |||
527 | val = lm90_read_reg(client, LM90_REG_R_TCRIT_HYST); | ||
528 | if (val < 0) | ||
529 | return val; | ||
530 | data->temp_hyst = val; | ||
531 | |||
532 | lm90_read_reg(client, LM90_REG_R_REMOTE_LOWH); | ||
533 | if (val < 0) | ||
534 | return val; | ||
535 | data->temp11[REMOTE_LOW] = val << 8; | ||
536 | |||
537 | if (data->flags & LM90_HAVE_REM_LIMIT_EXT) { | ||
538 | val = lm90_read_reg(client, LM90_REG_R_REMOTE_LOWL); | ||
539 | if (val < 0) | ||
540 | return val; | ||
541 | data->temp11[REMOTE_LOW] |= val; | ||
542 | } | ||
543 | |||
544 | val = lm90_read_reg(client, LM90_REG_R_REMOTE_HIGHH); | ||
545 | if (val < 0) | ||
546 | return val; | ||
547 | data->temp11[REMOTE_HIGH] = val << 8; | ||
548 | |||
549 | if (data->flags & LM90_HAVE_REM_LIMIT_EXT) { | ||
550 | val = lm90_read_reg(client, LM90_REG_R_REMOTE_HIGHL); | ||
551 | if (val < 0) | ||
552 | return val; | ||
553 | data->temp11[REMOTE_HIGH] |= val; | ||
554 | } | ||
555 | |||
556 | if (data->flags & LM90_HAVE_OFFSET) { | ||
557 | val = lm90_read16(client, LM90_REG_R_REMOTE_OFFSH, | ||
558 | LM90_REG_R_REMOTE_OFFSL); | ||
559 | if (val < 0) | ||
560 | return val; | ||
561 | data->temp11[REMOTE_OFFSET] = val; | ||
562 | } | ||
563 | |||
564 | if (data->flags & LM90_HAVE_EMERGENCY) { | ||
565 | val = lm90_read_reg(client, MAX6659_REG_R_LOCAL_EMERG); | ||
566 | if (val < 0) | ||
567 | return val; | ||
568 | data->temp8[LOCAL_EMERG] = val; | ||
569 | |||
570 | val = lm90_read_reg(client, MAX6659_REG_R_REMOTE_EMERG); | ||
571 | if (val < 0) | ||
572 | return val; | ||
573 | data->temp8[REMOTE_EMERG] = val; | ||
574 | } | ||
575 | |||
576 | if (data->kind == max6696) { | ||
577 | val = lm90_select_remote_channel(client, data, 1); | ||
578 | if (val < 0) | ||
579 | return val; | ||
580 | |||
581 | val = lm90_read_reg(client, LM90_REG_R_REMOTE_CRIT); | ||
582 | if (val < 0) | ||
583 | return val; | ||
584 | data->temp8[REMOTE2_CRIT] = val; | ||
585 | |||
586 | val = lm90_read_reg(client, MAX6659_REG_R_REMOTE_EMERG); | ||
587 | if (val < 0) | ||
588 | return val; | ||
589 | data->temp8[REMOTE2_EMERG] = val; | ||
590 | |||
591 | val = lm90_read_reg(client, LM90_REG_R_REMOTE_LOWH); | ||
592 | if (val < 0) | ||
593 | return val; | ||
594 | data->temp11[REMOTE2_LOW] = val << 8; | ||
595 | |||
596 | val = lm90_read_reg(client, LM90_REG_R_REMOTE_HIGHH); | ||
597 | if (val < 0) | ||
598 | return val; | ||
599 | data->temp11[REMOTE2_HIGH] = val << 8; | ||
600 | |||
601 | lm90_select_remote_channel(client, data, 0); | ||
602 | } | ||
603 | |||
604 | return 0; | ||
605 | } | ||
606 | |||
516 | static struct lm90_data *lm90_update_device(struct device *dev) | 607 | static struct lm90_data *lm90_update_device(struct device *dev) |
517 | { | 608 | { |
518 | struct lm90_data *data = dev_get_drvdata(dev); | 609 | struct lm90_data *data = dev_get_drvdata(dev); |
519 | struct i2c_client *client = data->client; | 610 | struct i2c_client *client = data->client; |
520 | unsigned long next_update; | 611 | unsigned long next_update; |
612 | int val = 0; | ||
521 | 613 | ||
522 | mutex_lock(&data->update_lock); | 614 | mutex_lock(&data->update_lock); |
523 | 615 | ||
616 | if (!data->valid) { | ||
617 | val = lm90_update_limits(dev); | ||
618 | if (val < 0) | ||
619 | goto error; | ||
620 | } | ||
621 | |||
524 | next_update = data->last_updated + | 622 | next_update = data->last_updated + |
525 | msecs_to_jiffies(data->update_interval); | 623 | msecs_to_jiffies(data->update_interval); |
526 | if (time_after(jiffies, next_update) || !data->valid) { | 624 | if (time_after(jiffies, next_update) || !data->valid) { |
527 | u8 h, l; | ||
528 | u8 alarms; | ||
529 | |||
530 | dev_dbg(&client->dev, "Updating lm90 data.\n"); | 625 | dev_dbg(&client->dev, "Updating lm90 data.\n"); |
531 | lm90_read_reg(client, LM90_REG_R_LOCAL_LOW, | 626 | |
532 | &data->temp8[LOCAL_LOW]); | 627 | data->valid = false; |
533 | lm90_read_reg(client, LM90_REG_R_LOCAL_HIGH, | 628 | |
534 | &data->temp8[LOCAL_HIGH]); | 629 | val = lm90_read_reg(client, LM90_REG_R_LOCAL_LOW); |
535 | lm90_read_reg(client, LM90_REG_R_LOCAL_CRIT, | 630 | if (val < 0) |
536 | &data->temp8[LOCAL_CRIT]); | 631 | goto error; |
537 | lm90_read_reg(client, LM90_REG_R_REMOTE_CRIT, | 632 | data->temp8[LOCAL_LOW] = val; |
538 | &data->temp8[REMOTE_CRIT]); | 633 | |
539 | lm90_read_reg(client, LM90_REG_R_TCRIT_HYST, &data->temp_hyst); | 634 | val = lm90_read_reg(client, LM90_REG_R_LOCAL_HIGH); |
635 | if (val < 0) | ||
636 | goto error; | ||
637 | data->temp8[LOCAL_HIGH] = val; | ||
540 | 638 | ||
541 | if (data->reg_local_ext) { | 639 | if (data->reg_local_ext) { |
542 | lm90_read16(client, LM90_REG_R_LOCAL_TEMP, | 640 | val = lm90_read16(client, LM90_REG_R_LOCAL_TEMP, |
543 | data->reg_local_ext, | 641 | data->reg_local_ext); |
544 | &data->temp11[LOCAL_TEMP]); | 642 | if (val < 0) |
643 | goto error; | ||
644 | data->temp11[LOCAL_TEMP] = val; | ||
545 | } else { | 645 | } else { |
546 | if (lm90_read_reg(client, LM90_REG_R_LOCAL_TEMP, | 646 | val = lm90_read_reg(client, LM90_REG_R_LOCAL_TEMP); |
547 | &h) == 0) | 647 | if (val < 0) |
548 | data->temp11[LOCAL_TEMP] = h << 8; | 648 | goto error; |
549 | } | 649 | data->temp11[LOCAL_TEMP] = val << 8; |
550 | lm90_read16(client, LM90_REG_R_REMOTE_TEMPH, | ||
551 | LM90_REG_R_REMOTE_TEMPL, | ||
552 | &data->temp11[REMOTE_TEMP]); | ||
553 | |||
554 | if (lm90_read_reg(client, LM90_REG_R_REMOTE_LOWH, &h) == 0) { | ||
555 | data->temp11[REMOTE_LOW] = h << 8; | ||
556 | if ((data->flags & LM90_HAVE_REM_LIMIT_EXT) | ||
557 | && lm90_read_reg(client, LM90_REG_R_REMOTE_LOWL, | ||
558 | &l) == 0) | ||
559 | data->temp11[REMOTE_LOW] |= l; | ||
560 | } | ||
561 | if (lm90_read_reg(client, LM90_REG_R_REMOTE_HIGHH, &h) == 0) { | ||
562 | data->temp11[REMOTE_HIGH] = h << 8; | ||
563 | if ((data->flags & LM90_HAVE_REM_LIMIT_EXT) | ||
564 | && lm90_read_reg(client, LM90_REG_R_REMOTE_HIGHL, | ||
565 | &l) == 0) | ||
566 | data->temp11[REMOTE_HIGH] |= l; | ||
567 | } | 650 | } |
651 | val = lm90_read16(client, LM90_REG_R_REMOTE_TEMPH, | ||
652 | LM90_REG_R_REMOTE_TEMPL); | ||
653 | if (val < 0) | ||
654 | goto error; | ||
655 | data->temp11[REMOTE_TEMP] = val; | ||
568 | 656 | ||
569 | if (data->flags & LM90_HAVE_OFFSET) { | 657 | val = lm90_read_reg(client, LM90_REG_R_STATUS); |
570 | if (lm90_read_reg(client, LM90_REG_R_REMOTE_OFFSH, | 658 | if (val < 0) |
571 | &h) == 0 | 659 | goto error; |
572 | && lm90_read_reg(client, LM90_REG_R_REMOTE_OFFSL, | 660 | data->alarms = val; /* lower 8 bit of alarms */ |
573 | &l) == 0) | ||
574 | data->temp11[REMOTE_OFFSET] = (h << 8) | l; | ||
575 | } | ||
576 | if (data->flags & LM90_HAVE_EMERGENCY) { | ||
577 | lm90_read_reg(client, MAX6659_REG_R_LOCAL_EMERG, | ||
578 | &data->temp8[LOCAL_EMERG]); | ||
579 | lm90_read_reg(client, MAX6659_REG_R_REMOTE_EMERG, | ||
580 | &data->temp8[REMOTE_EMERG]); | ||
581 | } | ||
582 | lm90_read_reg(client, LM90_REG_R_STATUS, &alarms); | ||
583 | data->alarms = alarms; /* save as 16 bit value */ | ||
584 | 661 | ||
585 | if (data->kind == max6696) { | 662 | if (data->kind == max6696) { |
586 | lm90_select_remote_channel(client, data, 1); | 663 | val = lm90_select_remote_channel(client, data, 1); |
587 | lm90_read_reg(client, LM90_REG_R_REMOTE_CRIT, | 664 | if (val < 0) |
588 | &data->temp8[REMOTE2_CRIT]); | 665 | goto error; |
589 | lm90_read_reg(client, MAX6659_REG_R_REMOTE_EMERG, | 666 | |
590 | &data->temp8[REMOTE2_EMERG]); | 667 | val = lm90_read16(client, LM90_REG_R_REMOTE_TEMPH, |
591 | lm90_read16(client, LM90_REG_R_REMOTE_TEMPH, | 668 | LM90_REG_R_REMOTE_TEMPL); |
592 | LM90_REG_R_REMOTE_TEMPL, | 669 | if (val < 0) |
593 | &data->temp11[REMOTE2_TEMP]); | 670 | goto error; |
594 | if (!lm90_read_reg(client, LM90_REG_R_REMOTE_LOWH, &h)) | 671 | data->temp11[REMOTE2_TEMP] = val; |
595 | data->temp11[REMOTE2_LOW] = h << 8; | 672 | |
596 | if (!lm90_read_reg(client, LM90_REG_R_REMOTE_HIGHH, &h)) | ||
597 | data->temp11[REMOTE2_HIGH] = h << 8; | ||
598 | lm90_select_remote_channel(client, data, 0); | 673 | lm90_select_remote_channel(client, data, 0); |
599 | 674 | ||
600 | if (!lm90_read_reg(client, MAX6696_REG_R_STATUS2, | 675 | val = lm90_read_reg(client, MAX6696_REG_R_STATUS2); |
601 | &alarms)) | 676 | if (val < 0) |
602 | data->alarms |= alarms << 8; | 677 | goto error; |
678 | data->alarms |= val << 8; | ||
603 | } | 679 | } |
604 | 680 | ||
605 | /* | 681 | /* |
606 | * Re-enable ALERT# output if it was originally enabled and | 682 | * Re-enable ALERT# output if it was originally enabled and |
607 | * relevant alarms are all clear | 683 | * relevant alarms are all clear |
608 | */ | 684 | */ |
609 | if ((data->config_orig & 0x80) == 0 | 685 | if (!(data->config_orig & 0x80) && |
610 | && (data->alarms & data->alert_alarms) == 0) { | 686 | !(data->alarms & data->alert_alarms)) { |
611 | u8 config; | 687 | val = lm90_read_reg(client, LM90_REG_R_CONFIG1); |
688 | if (val < 0) | ||
689 | goto error; | ||
612 | 690 | ||
613 | lm90_read_reg(client, LM90_REG_R_CONFIG1, &config); | 691 | if (val & 0x80) { |
614 | if (config & 0x80) { | ||
615 | dev_dbg(&client->dev, "Re-enabling ALERT#\n"); | 692 | dev_dbg(&client->dev, "Re-enabling ALERT#\n"); |
616 | i2c_smbus_write_byte_data(client, | 693 | i2c_smbus_write_byte_data(client, |
617 | LM90_REG_W_CONFIG1, | 694 | LM90_REG_W_CONFIG1, |
618 | config & ~0x80); | 695 | val & ~0x80); |
619 | } | 696 | } |
620 | } | 697 | } |
621 | 698 | ||
622 | data->last_updated = jiffies; | 699 | data->last_updated = jiffies; |
623 | data->valid = 1; | 700 | data->valid = true; |
624 | } | 701 | } |
625 | 702 | ||
703 | error: | ||
626 | mutex_unlock(&data->update_lock); | 704 | mutex_unlock(&data->update_lock); |
627 | 705 | ||
706 | if (val < 0) | ||
707 | return ERR_PTR(val); | ||
708 | |||
628 | return data; | 709 | return data; |
629 | } | 710 | } |
630 | 711 | ||
@@ -709,16 +790,14 @@ static inline int temp_from_u8_adt7461(struct lm90_data *data, u8 val) | |||
709 | { | 790 | { |
710 | if (data->flags & LM90_FLAG_ADT7461_EXT) | 791 | if (data->flags & LM90_FLAG_ADT7461_EXT) |
711 | return (val - 64) * 1000; | 792 | return (val - 64) * 1000; |
712 | else | 793 | return temp_from_s8(val); |
713 | return temp_from_s8(val); | ||
714 | } | 794 | } |
715 | 795 | ||
716 | static inline int temp_from_u16_adt7461(struct lm90_data *data, u16 val) | 796 | static inline int temp_from_u16_adt7461(struct lm90_data *data, u16 val) |
717 | { | 797 | { |
718 | if (data->flags & LM90_FLAG_ADT7461_EXT) | 798 | if (data->flags & LM90_FLAG_ADT7461_EXT) |
719 | return (val - 0x4000) / 64 * 250; | 799 | return (val - 0x4000) / 64 * 250; |
720 | else | 800 | return temp_from_s16(val); |
721 | return temp_from_s16(val); | ||
722 | } | 801 | } |
723 | 802 | ||
724 | static u8 temp_to_u8_adt7461(struct lm90_data *data, long val) | 803 | static u8 temp_to_u8_adt7461(struct lm90_data *data, long val) |
@@ -729,13 +808,12 @@ static u8 temp_to_u8_adt7461(struct lm90_data *data, long val) | |||
729 | if (val >= 191000) | 808 | if (val >= 191000) |
730 | return 0xFF; | 809 | return 0xFF; |
731 | return (val + 500 + 64000) / 1000; | 810 | return (val + 500 + 64000) / 1000; |
732 | } else { | ||
733 | if (val <= 0) | ||
734 | return 0; | ||
735 | if (val >= 127000) | ||
736 | return 127; | ||
737 | return (val + 500) / 1000; | ||
738 | } | 811 | } |
812 | if (val <= 0) | ||
813 | return 0; | ||
814 | if (val >= 127000) | ||
815 | return 127; | ||
816 | return (val + 500) / 1000; | ||
739 | } | 817 | } |
740 | 818 | ||
741 | static u16 temp_to_u16_adt7461(struct lm90_data *data, long val) | 819 | static u16 temp_to_u16_adt7461(struct lm90_data *data, long val) |
@@ -746,13 +824,12 @@ static u16 temp_to_u16_adt7461(struct lm90_data *data, long val) | |||
746 | if (val >= 191750) | 824 | if (val >= 191750) |
747 | return 0xFFC0; | 825 | return 0xFFC0; |
748 | return (val + 64000 + 125) / 250 * 64; | 826 | return (val + 64000 + 125) / 250 * 64; |
749 | } else { | ||
750 | if (val <= 0) | ||
751 | return 0; | ||
752 | if (val >= 127750) | ||
753 | return 0x7FC0; | ||
754 | return (val + 125) / 250 * 64; | ||
755 | } | 827 | } |
828 | if (val <= 0) | ||
829 | return 0; | ||
830 | if (val >= 127750) | ||
831 | return 0x7FC0; | ||
832 | return (val + 125) / 250 * 64; | ||
756 | } | 833 | } |
757 | 834 | ||
758 | /* | 835 | /* |
@@ -766,6 +843,9 @@ static ssize_t show_temp8(struct device *dev, struct device_attribute *devattr, | |||
766 | struct lm90_data *data = lm90_update_device(dev); | 843 | struct lm90_data *data = lm90_update_device(dev); |
767 | int temp; | 844 | int temp; |
768 | 845 | ||
846 | if (IS_ERR(data)) | ||
847 | return PTR_ERR(data); | ||
848 | |||
769 | if (data->kind == adt7461 || data->kind == tmp451) | 849 | if (data->kind == adt7461 || data->kind == tmp451) |
770 | temp = temp_from_u8_adt7461(data, data->temp8[attr->index]); | 850 | temp = temp_from_u8_adt7461(data, data->temp8[attr->index]); |
771 | else if (data->kind == max6646) | 851 | else if (data->kind == max6646) |
@@ -832,6 +912,9 @@ static ssize_t show_temp11(struct device *dev, struct device_attribute *devattr, | |||
832 | struct lm90_data *data = lm90_update_device(dev); | 912 | struct lm90_data *data = lm90_update_device(dev); |
833 | int temp; | 913 | int temp; |
834 | 914 | ||
915 | if (IS_ERR(data)) | ||
916 | return PTR_ERR(data); | ||
917 | |||
835 | if (data->kind == adt7461 || data->kind == tmp451) | 918 | if (data->kind == adt7461 || data->kind == tmp451) |
836 | temp = temp_from_u16_adt7461(data, data->temp11[attr->index]); | 919 | temp = temp_from_u16_adt7461(data, data->temp11[attr->index]); |
837 | else if (data->kind == max6646) | 920 | else if (data->kind == max6646) |
@@ -907,6 +990,9 @@ static ssize_t show_temphyst(struct device *dev, | |||
907 | struct lm90_data *data = lm90_update_device(dev); | 990 | struct lm90_data *data = lm90_update_device(dev); |
908 | int temp; | 991 | int temp; |
909 | 992 | ||
993 | if (IS_ERR(data)) | ||
994 | return PTR_ERR(data); | ||
995 | |||
910 | if (data->kind == adt7461 || data->kind == tmp451) | 996 | if (data->kind == adt7461 || data->kind == tmp451) |
911 | temp = temp_from_u8_adt7461(data, data->temp8[attr->index]); | 997 | temp = temp_from_u8_adt7461(data, data->temp8[attr->index]); |
912 | else if (data->kind == max6646) | 998 | else if (data->kind == max6646) |
@@ -953,6 +1039,10 @@ static ssize_t show_alarms(struct device *dev, struct device_attribute *dummy, | |||
953 | char *buf) | 1039 | char *buf) |
954 | { | 1040 | { |
955 | struct lm90_data *data = lm90_update_device(dev); | 1041 | struct lm90_data *data = lm90_update_device(dev); |
1042 | |||
1043 | if (IS_ERR(data)) | ||
1044 | return PTR_ERR(data); | ||
1045 | |||
956 | return sprintf(buf, "%d\n", data->alarms); | 1046 | return sprintf(buf, "%d\n", data->alarms); |
957 | } | 1047 | } |
958 | 1048 | ||
@@ -963,6 +1053,9 @@ static ssize_t show_alarm(struct device *dev, struct device_attribute | |||
963 | struct lm90_data *data = lm90_update_device(dev); | 1053 | struct lm90_data *data = lm90_update_device(dev); |
964 | int bitnr = attr->index; | 1054 | int bitnr = attr->index; |
965 | 1055 | ||
1056 | if (IS_ERR(data)) | ||
1057 | return PTR_ERR(data); | ||
1058 | |||
966 | return sprintf(buf, "%d\n", (data->alarms >> bitnr) & 1); | 1059 | return sprintf(buf, "%d\n", (data->alarms >> bitnr) & 1); |
967 | } | 1060 | } |
968 | 1061 | ||
@@ -1404,8 +1497,11 @@ static int lm90_detect(struct i2c_client *client, | |||
1404 | return 0; | 1497 | return 0; |
1405 | } | 1498 | } |
1406 | 1499 | ||
1407 | static void lm90_restore_conf(struct i2c_client *client, struct lm90_data *data) | 1500 | static void lm90_restore_conf(void *_data) |
1408 | { | 1501 | { |
1502 | struct lm90_data *data = _data; | ||
1503 | struct i2c_client *client = data->client; | ||
1504 | |||
1409 | /* Restore initial configuration */ | 1505 | /* Restore initial configuration */ |
1410 | i2c_smbus_write_byte_data(client, LM90_REG_W_CONVRATE, | 1506 | i2c_smbus_write_byte_data(client, LM90_REG_W_CONVRATE, |
1411 | data->convrate_orig); | 1507 | data->convrate_orig); |
@@ -1413,24 +1509,22 @@ static void lm90_restore_conf(struct i2c_client *client, struct lm90_data *data) | |||
1413 | data->config_orig); | 1509 | data->config_orig); |
1414 | } | 1510 | } |
1415 | 1511 | ||
1416 | static void lm90_init_client(struct i2c_client *client, struct lm90_data *data) | 1512 | static int lm90_init_client(struct i2c_client *client, struct lm90_data *data) |
1417 | { | 1513 | { |
1418 | u8 config, convrate; | 1514 | int config, convrate; |
1419 | 1515 | ||
1420 | if (lm90_read_reg(client, LM90_REG_R_CONVRATE, &convrate) < 0) { | 1516 | convrate = lm90_read_reg(client, LM90_REG_R_CONVRATE); |
1421 | dev_warn(&client->dev, "Failed to read convrate register!\n"); | 1517 | if (convrate < 0) |
1422 | convrate = LM90_DEF_CONVRATE_RVAL; | 1518 | return convrate; |
1423 | } | ||
1424 | data->convrate_orig = convrate; | 1519 | data->convrate_orig = convrate; |
1425 | 1520 | ||
1426 | /* | 1521 | /* |
1427 | * Start the conversions. | 1522 | * Start the conversions. |
1428 | */ | 1523 | */ |
1429 | lm90_set_convrate(client, data, 500); /* 500ms; 2Hz conversion rate */ | 1524 | lm90_set_convrate(client, data, 500); /* 500ms; 2Hz conversion rate */ |
1430 | if (lm90_read_reg(client, LM90_REG_R_CONFIG1, &config) < 0) { | 1525 | config = lm90_read_reg(client, LM90_REG_R_CONFIG1); |
1431 | dev_warn(&client->dev, "Initialization failed!\n"); | 1526 | if (config < 0) |
1432 | return; | 1527 | return config; |
1433 | } | ||
1434 | data->config_orig = config; | 1528 | data->config_orig = config; |
1435 | 1529 | ||
1436 | /* Check Temperature Range Select */ | 1530 | /* Check Temperature Range Select */ |
@@ -1456,17 +1550,26 @@ static void lm90_init_client(struct i2c_client *client, struct lm90_data *data) | |||
1456 | config &= 0xBF; /* run */ | 1550 | config &= 0xBF; /* run */ |
1457 | if (config != data->config_orig) /* Only write if changed */ | 1551 | if (config != data->config_orig) /* Only write if changed */ |
1458 | i2c_smbus_write_byte_data(client, LM90_REG_W_CONFIG1, config); | 1552 | i2c_smbus_write_byte_data(client, LM90_REG_W_CONFIG1, config); |
1553 | |||
1554 | devm_add_action(&client->dev, lm90_restore_conf, data); | ||
1555 | |||
1556 | return 0; | ||
1459 | } | 1557 | } |
1460 | 1558 | ||
1461 | static bool lm90_is_tripped(struct i2c_client *client, u16 *status) | 1559 | static bool lm90_is_tripped(struct i2c_client *client, u16 *status) |
1462 | { | 1560 | { |
1463 | struct lm90_data *data = i2c_get_clientdata(client); | 1561 | struct lm90_data *data = i2c_get_clientdata(client); |
1464 | u8 st, st2 = 0; | 1562 | int st, st2 = 0; |
1465 | 1563 | ||
1466 | lm90_read_reg(client, LM90_REG_R_STATUS, &st); | 1564 | st = lm90_read_reg(client, LM90_REG_R_STATUS); |
1565 | if (st < 0) | ||
1566 | return false; | ||
1467 | 1567 | ||
1468 | if (data->kind == max6696) | 1568 | if (data->kind == max6696) { |
1469 | lm90_read_reg(client, MAX6696_REG_R_STATUS2, &st2); | 1569 | st2 = lm90_read_reg(client, MAX6696_REG_R_STATUS2); |
1570 | if (st2 < 0) | ||
1571 | return false; | ||
1572 | } | ||
1470 | 1573 | ||
1471 | *status = st | (st2 << 8); | 1574 | *status = st | (st2 << 8); |
1472 | 1575 | ||
@@ -1506,6 +1609,16 @@ static irqreturn_t lm90_irq_thread(int irq, void *dev_id) | |||
1506 | return IRQ_NONE; | 1609 | return IRQ_NONE; |
1507 | } | 1610 | } |
1508 | 1611 | ||
1612 | static void lm90_remove_pec(void *dev) | ||
1613 | { | ||
1614 | device_remove_file(dev, &dev_attr_pec); | ||
1615 | } | ||
1616 | |||
1617 | static void lm90_regulator_disable(void *regulator) | ||
1618 | { | ||
1619 | regulator_disable(regulator); | ||
1620 | } | ||
1621 | |||
1509 | static int lm90_probe(struct i2c_client *client, | 1622 | static int lm90_probe(struct i2c_client *client, |
1510 | const struct i2c_device_id *id) | 1623 | const struct i2c_device_id *id) |
1511 | { | 1624 | { |
@@ -1513,6 +1626,7 @@ static int lm90_probe(struct i2c_client *client, | |||
1513 | struct i2c_adapter *adapter = to_i2c_adapter(dev->parent); | 1626 | struct i2c_adapter *adapter = to_i2c_adapter(dev->parent); |
1514 | struct lm90_data *data; | 1627 | struct lm90_data *data; |
1515 | struct regulator *regulator; | 1628 | struct regulator *regulator; |
1629 | struct device *hwmon_dev; | ||
1516 | int groups = 0; | 1630 | int groups = 0; |
1517 | int err; | 1631 | int err; |
1518 | 1632 | ||
@@ -1526,6 +1640,8 @@ static int lm90_probe(struct i2c_client *client, | |||
1526 | return err; | 1640 | return err; |
1527 | } | 1641 | } |
1528 | 1642 | ||
1643 | devm_add_action(dev, lm90_regulator_disable, regulator); | ||
1644 | |||
1529 | data = devm_kzalloc(dev, sizeof(struct lm90_data), GFP_KERNEL); | 1645 | data = devm_kzalloc(dev, sizeof(struct lm90_data), GFP_KERNEL); |
1530 | if (!data) | 1646 | if (!data) |
1531 | return -ENOMEM; | 1647 | return -ENOMEM; |
@@ -1534,8 +1650,6 @@ static int lm90_probe(struct i2c_client *client, | |||
1534 | i2c_set_clientdata(client, data); | 1650 | i2c_set_clientdata(client, data); |
1535 | mutex_init(&data->update_lock); | 1651 | mutex_init(&data->update_lock); |
1536 | 1652 | ||
1537 | data->regulator = regulator; | ||
1538 | |||
1539 | /* Set the device type */ | 1653 | /* Set the device type */ |
1540 | data->kind = id->driver_data; | 1654 | data->kind = id->driver_data; |
1541 | if (data->kind == adm1032) { | 1655 | if (data->kind == adm1032) { |
@@ -1557,7 +1671,11 @@ static int lm90_probe(struct i2c_client *client, | |||
1557 | data->max_convrate = lm90_params[data->kind].max_convrate; | 1671 | data->max_convrate = lm90_params[data->kind].max_convrate; |
1558 | 1672 | ||
1559 | /* Initialize the LM90 chip */ | 1673 | /* Initialize the LM90 chip */ |
1560 | lm90_init_client(client, data); | 1674 | err = lm90_init_client(client, data); |
1675 | if (err < 0) { | ||
1676 | dev_err(dev, "Failed to initialize device\n"); | ||
1677 | return err; | ||
1678 | } | ||
1561 | 1679 | ||
1562 | /* Register sysfs hooks */ | 1680 | /* Register sysfs hooks */ |
1563 | data->groups[groups++] = &lm90_group; | 1681 | data->groups[groups++] = &lm90_group; |
@@ -1577,15 +1695,14 @@ static int lm90_probe(struct i2c_client *client, | |||
1577 | if (client->flags & I2C_CLIENT_PEC) { | 1695 | if (client->flags & I2C_CLIENT_PEC) { |
1578 | err = device_create_file(dev, &dev_attr_pec); | 1696 | err = device_create_file(dev, &dev_attr_pec); |
1579 | if (err) | 1697 | if (err) |
1580 | goto exit_restore; | 1698 | return err; |
1699 | devm_add_action(dev, lm90_remove_pec, dev); | ||
1581 | } | 1700 | } |
1582 | 1701 | ||
1583 | data->hwmon_dev = hwmon_device_register_with_groups(dev, client->name, | 1702 | hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name, |
1584 | data, data->groups); | 1703 | data, data->groups); |
1585 | if (IS_ERR(data->hwmon_dev)) { | 1704 | if (IS_ERR(hwmon_dev)) |
1586 | err = PTR_ERR(data->hwmon_dev); | 1705 | return PTR_ERR(hwmon_dev); |
1587 | goto exit_remove_pec; | ||
1588 | } | ||
1589 | 1706 | ||
1590 | if (client->irq) { | 1707 | if (client->irq) { |
1591 | dev_dbg(dev, "IRQ: %d\n", client->irq); | 1708 | dev_dbg(dev, "IRQ: %d\n", client->irq); |
@@ -1595,33 +1712,11 @@ static int lm90_probe(struct i2c_client *client, | |||
1595 | "lm90", client); | 1712 | "lm90", client); |
1596 | if (err < 0) { | 1713 | if (err < 0) { |
1597 | dev_err(dev, "cannot request IRQ %d\n", client->irq); | 1714 | dev_err(dev, "cannot request IRQ %d\n", client->irq); |
1598 | goto exit_unregister; | 1715 | return err; |
1599 | } | 1716 | } |
1600 | } | 1717 | } |
1601 | 1718 | ||
1602 | return 0; | 1719 | return 0; |
1603 | |||
1604 | exit_unregister: | ||
1605 | hwmon_device_unregister(data->hwmon_dev); | ||
1606 | exit_remove_pec: | ||
1607 | device_remove_file(dev, &dev_attr_pec); | ||
1608 | exit_restore: | ||
1609 | lm90_restore_conf(client, data); | ||
1610 | regulator_disable(data->regulator); | ||
1611 | |||
1612 | return err; | ||
1613 | } | ||
1614 | |||
1615 | static int lm90_remove(struct i2c_client *client) | ||
1616 | { | ||
1617 | struct lm90_data *data = i2c_get_clientdata(client); | ||
1618 | |||
1619 | hwmon_device_unregister(data->hwmon_dev); | ||
1620 | device_remove_file(&client->dev, &dev_attr_pec); | ||
1621 | lm90_restore_conf(client, data); | ||
1622 | regulator_disable(data->regulator); | ||
1623 | |||
1624 | return 0; | ||
1625 | } | 1720 | } |
1626 | 1721 | ||
1627 | static void lm90_alert(struct i2c_client *client, unsigned int flag) | 1722 | static void lm90_alert(struct i2c_client *client, unsigned int flag) |
@@ -1636,13 +1731,16 @@ static void lm90_alert(struct i2c_client *client, unsigned int flag) | |||
1636 | */ | 1731 | */ |
1637 | struct lm90_data *data = i2c_get_clientdata(client); | 1732 | struct lm90_data *data = i2c_get_clientdata(client); |
1638 | 1733 | ||
1639 | if ((data->flags & LM90_HAVE_BROKEN_ALERT) | 1734 | if ((data->flags & LM90_HAVE_BROKEN_ALERT) && |
1640 | && (alarms & data->alert_alarms)) { | 1735 | (alarms & data->alert_alarms)) { |
1641 | u8 config; | 1736 | int config; |
1737 | |||
1642 | dev_dbg(&client->dev, "Disabling ALERT#\n"); | 1738 | dev_dbg(&client->dev, "Disabling ALERT#\n"); |
1643 | lm90_read_reg(client, LM90_REG_R_CONFIG1, &config); | 1739 | config = lm90_read_reg(client, LM90_REG_R_CONFIG1); |
1644 | i2c_smbus_write_byte_data(client, LM90_REG_W_CONFIG1, | 1740 | if (config >= 0) |
1645 | config | 0x80); | 1741 | i2c_smbus_write_byte_data(client, |
1742 | LM90_REG_W_CONFIG1, | ||
1743 | config | 0x80); | ||
1646 | } | 1744 | } |
1647 | } else { | 1745 | } else { |
1648 | dev_info(&client->dev, "Everything OK\n"); | 1746 | dev_info(&client->dev, "Everything OK\n"); |
@@ -1655,7 +1753,6 @@ static struct i2c_driver lm90_driver = { | |||
1655 | .name = "lm90", | 1753 | .name = "lm90", |
1656 | }, | 1754 | }, |
1657 | .probe = lm90_probe, | 1755 | .probe = lm90_probe, |
1658 | .remove = lm90_remove, | ||
1659 | .alert = lm90_alert, | 1756 | .alert = lm90_alert, |
1660 | .id_table = lm90_id, | 1757 | .id_table = lm90_id, |
1661 | .detect = lm90_detect, | 1758 | .detect = lm90_detect, |
diff --git a/drivers/hwmon/sht3x.c b/drivers/hwmon/sht3x.c new file mode 100644 index 000000000000..b73a48832732 --- /dev/null +++ b/drivers/hwmon/sht3x.c | |||
@@ -0,0 +1,775 @@ | |||
1 | /* Sensirion SHT3x-DIS humidity and temperature sensor driver. | ||
2 | * The SHT3x comes in many different versions, this driver is for the | ||
3 | * I2C version only. | ||
4 | * | ||
5 | * Copyright (C) 2016 Sensirion AG, Switzerland | ||
6 | * Author: David Frey <david.frey@sensirion.com> | ||
7 | * Author: Pascal Sachs <pascal.sachs@sensirion.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | */ | ||
20 | |||
21 | #include <asm/page.h> | ||
22 | #include <linux/crc8.h> | ||
23 | #include <linux/delay.h> | ||
24 | #include <linux/err.h> | ||
25 | #include <linux/hwmon.h> | ||
26 | #include <linux/hwmon-sysfs.h> | ||
27 | #include <linux/i2c.h> | ||
28 | #include <linux/init.h> | ||
29 | #include <linux/kernel.h> | ||
30 | #include <linux/module.h> | ||
31 | #include <linux/slab.h> | ||
32 | #include <linux/jiffies.h> | ||
33 | #include <linux/platform_data/sht3x.h> | ||
34 | |||
35 | /* commands (high precision mode) */ | ||
36 | static const unsigned char sht3x_cmd_measure_blocking_hpm[] = { 0x2c, 0x06 }; | ||
37 | static const unsigned char sht3x_cmd_measure_nonblocking_hpm[] = { 0x24, 0x00 }; | ||
38 | |||
39 | /* commands (low power mode) */ | ||
40 | static const unsigned char sht3x_cmd_measure_blocking_lpm[] = { 0x2c, 0x10 }; | ||
41 | static const unsigned char sht3x_cmd_measure_nonblocking_lpm[] = { 0x24, 0x16 }; | ||
42 | |||
43 | /* commands for periodic mode */ | ||
44 | static const unsigned char sht3x_cmd_measure_periodic_mode[] = { 0xe0, 0x00 }; | ||
45 | static const unsigned char sht3x_cmd_break[] = { 0x30, 0x93 }; | ||
46 | |||
47 | /* commands for heater control */ | ||
48 | static const unsigned char sht3x_cmd_heater_on[] = { 0x30, 0x6d }; | ||
49 | static const unsigned char sht3x_cmd_heater_off[] = { 0x30, 0x66 }; | ||
50 | |||
51 | /* other commands */ | ||
52 | static const unsigned char sht3x_cmd_read_status_reg[] = { 0xf3, 0x2d }; | ||
53 | static const unsigned char sht3x_cmd_clear_status_reg[] = { 0x30, 0x41 }; | ||
54 | |||
55 | /* delays for non-blocking i2c commands, both in us */ | ||
56 | #define SHT3X_NONBLOCKING_WAIT_TIME_HPM 15000 | ||
57 | #define SHT3X_NONBLOCKING_WAIT_TIME_LPM 4000 | ||
58 | |||
59 | #define SHT3X_WORD_LEN 2 | ||
60 | #define SHT3X_CMD_LENGTH 2 | ||
61 | #define SHT3X_CRC8_LEN 1 | ||
62 | #define SHT3X_RESPONSE_LENGTH 6 | ||
63 | #define SHT3X_CRC8_POLYNOMIAL 0x31 | ||
64 | #define SHT3X_CRC8_INIT 0xFF | ||
65 | #define SHT3X_MIN_TEMPERATURE -45000 | ||
66 | #define SHT3X_MAX_TEMPERATURE 130000 | ||
67 | #define SHT3X_MIN_HUMIDITY 0 | ||
68 | #define SHT3X_MAX_HUMIDITY 100000 | ||
69 | |||
70 | enum sht3x_chips { | ||
71 | sht3x, | ||
72 | sts3x, | ||
73 | }; | ||
74 | |||
75 | enum sht3x_limits { | ||
76 | limit_max = 0, | ||
77 | limit_max_hyst, | ||
78 | limit_min, | ||
79 | limit_min_hyst, | ||
80 | }; | ||
81 | |||
82 | DECLARE_CRC8_TABLE(sht3x_crc8_table); | ||
83 | |||
84 | /* periodic measure commands (high precision mode) */ | ||
85 | static const char periodic_measure_commands_hpm[][SHT3X_CMD_LENGTH] = { | ||
86 | /* 0.5 measurements per second */ | ||
87 | {0x20, 0x32}, | ||
88 | /* 1 measurements per second */ | ||
89 | {0x21, 0x30}, | ||
90 | /* 2 measurements per second */ | ||
91 | {0x22, 0x36}, | ||
92 | /* 4 measurements per second */ | ||
93 | {0x23, 0x34}, | ||
94 | /* 10 measurements per second */ | ||
95 | {0x27, 0x37}, | ||
96 | }; | ||
97 | |||
98 | /* periodic measure commands (low power mode) */ | ||
99 | static const char periodic_measure_commands_lpm[][SHT3X_CMD_LENGTH] = { | ||
100 | /* 0.5 measurements per second */ | ||
101 | {0x20, 0x2f}, | ||
102 | /* 1 measurements per second */ | ||
103 | {0x21, 0x2d}, | ||
104 | /* 2 measurements per second */ | ||
105 | {0x22, 0x2b}, | ||
106 | /* 4 measurements per second */ | ||
107 | {0x23, 0x29}, | ||
108 | /* 10 measurements per second */ | ||
109 | {0x27, 0x2a}, | ||
110 | }; | ||
111 | |||
112 | struct sht3x_limit_commands { | ||
113 | const char read_command[SHT3X_CMD_LENGTH]; | ||
114 | const char write_command[SHT3X_CMD_LENGTH]; | ||
115 | }; | ||
116 | |||
117 | static const struct sht3x_limit_commands limit_commands[] = { | ||
118 | /* temp1_max, humidity1_max */ | ||
119 | [limit_max] = { {0xe1, 0x1f}, {0x61, 0x1d} }, | ||
120 | /* temp_1_max_hyst, humidity1_max_hyst */ | ||
121 | [limit_max_hyst] = { {0xe1, 0x14}, {0x61, 0x16} }, | ||
122 | /* temp1_min, humidity1_min */ | ||
123 | [limit_min] = { {0xe1, 0x02}, {0x61, 0x00} }, | ||
124 | /* temp_1_min_hyst, humidity1_min_hyst */ | ||
125 | [limit_min_hyst] = { {0xe1, 0x09}, {0x61, 0x0B} }, | ||
126 | }; | ||
127 | |||
128 | #define SHT3X_NUM_LIMIT_CMD ARRAY_SIZE(limit_commands) | ||
129 | |||
130 | static const u16 mode_to_update_interval[] = { | ||
131 | 0, | ||
132 | 2000, | ||
133 | 1000, | ||
134 | 500, | ||
135 | 250, | ||
136 | 100, | ||
137 | }; | ||
138 | |||
139 | struct sht3x_data { | ||
140 | struct i2c_client *client; | ||
141 | struct mutex i2c_lock; /* lock for sending i2c commands */ | ||
142 | struct mutex data_lock; /* lock for updating driver data */ | ||
143 | |||
144 | u8 mode; | ||
145 | const unsigned char *command; | ||
146 | u32 wait_time; /* in us*/ | ||
147 | unsigned long last_update; /* last update in periodic mode*/ | ||
148 | |||
149 | struct sht3x_platform_data setup; | ||
150 | |||
151 | /* | ||
152 | * cached values for temperature and humidity and limits | ||
153 | * the limits arrays have the following order: | ||
154 | * max, max_hyst, min, min_hyst | ||
155 | */ | ||
156 | int temperature; | ||
157 | int temperature_limits[SHT3X_NUM_LIMIT_CMD]; | ||
158 | u32 humidity; | ||
159 | u32 humidity_limits[SHT3X_NUM_LIMIT_CMD]; | ||
160 | }; | ||
161 | |||
162 | static u8 get_mode_from_update_interval(u16 value) | ||
163 | { | ||
164 | size_t index; | ||
165 | u8 number_of_modes = ARRAY_SIZE(mode_to_update_interval); | ||
166 | |||
167 | if (value == 0) | ||
168 | return 0; | ||
169 | |||
170 | /* find next faster update interval */ | ||
171 | for (index = 1; index < number_of_modes; index++) { | ||
172 | if (mode_to_update_interval[index] <= value) | ||
173 | return index; | ||
174 | } | ||
175 | |||
176 | return number_of_modes - 1; | ||
177 | } | ||
178 | |||
179 | static int sht3x_read_from_command(struct i2c_client *client, | ||
180 | struct sht3x_data *data, | ||
181 | const char *command, | ||
182 | char *buf, int length, u32 wait_time) | ||
183 | { | ||
184 | int ret; | ||
185 | |||
186 | mutex_lock(&data->i2c_lock); | ||
187 | ret = i2c_master_send(client, command, SHT3X_CMD_LENGTH); | ||
188 | |||
189 | if (ret != SHT3X_CMD_LENGTH) { | ||
190 | ret = ret < 0 ? ret : -EIO; | ||
191 | goto out; | ||
192 | } | ||
193 | |||
194 | if (wait_time) | ||
195 | usleep_range(wait_time, wait_time + 1000); | ||
196 | |||
197 | ret = i2c_master_recv(client, buf, length); | ||
198 | if (ret != length) { | ||
199 | ret = ret < 0 ? ret : -EIO; | ||
200 | goto out; | ||
201 | } | ||
202 | |||
203 | ret = 0; | ||
204 | out: | ||
205 | mutex_unlock(&data->i2c_lock); | ||
206 | return ret; | ||
207 | } | ||
208 | |||
209 | static int sht3x_extract_temperature(u16 raw) | ||
210 | { | ||
211 | /* | ||
212 | * From datasheet: | ||
213 | * T = -45 + 175 * ST / 2^16 | ||
214 | * Adapted for integer fixed point (3 digit) arithmetic. | ||
215 | */ | ||
216 | return ((21875 * (int)raw) >> 13) - 45000; | ||
217 | } | ||
218 | |||
219 | static u32 sht3x_extract_humidity(u16 raw) | ||
220 | { | ||
221 | /* | ||
222 | * From datasheet: | ||
223 | * RH = 100 * SRH / 2^16 | ||
224 | * Adapted for integer fixed point (3 digit) arithmetic. | ||
225 | */ | ||
226 | return (12500 * (u32)raw) >> 13; | ||
227 | } | ||
228 | |||
229 | static struct sht3x_data *sht3x_update_client(struct device *dev) | ||
230 | { | ||
231 | struct sht3x_data *data = dev_get_drvdata(dev); | ||
232 | struct i2c_client *client = data->client; | ||
233 | u16 interval_ms = mode_to_update_interval[data->mode]; | ||
234 | unsigned long interval_jiffies = msecs_to_jiffies(interval_ms); | ||
235 | unsigned char buf[SHT3X_RESPONSE_LENGTH]; | ||
236 | u16 val; | ||
237 | int ret = 0; | ||
238 | |||
239 | mutex_lock(&data->data_lock); | ||
240 | /* | ||
241 | * Only update cached readings once per update interval in periodic | ||
242 | * mode. In single shot mode the sensor measures values on demand, so | ||
243 | * every time the sysfs interface is called, a measurement is triggered. | ||
244 | * In periodic mode however, the measurement process is handled | ||
245 | * internally by the sensor and reading out sensor values only makes | ||
246 | * sense if a new reading is available. | ||
247 | */ | ||
248 | if (time_after(jiffies, data->last_update + interval_jiffies)) { | ||
249 | ret = sht3x_read_from_command(client, data, data->command, buf, | ||
250 | sizeof(buf), data->wait_time); | ||
251 | if (ret) | ||
252 | goto out; | ||
253 | |||
254 | val = be16_to_cpup((__be16 *)buf); | ||
255 | data->temperature = sht3x_extract_temperature(val); | ||
256 | val = be16_to_cpup((__be16 *)(buf + 3)); | ||
257 | data->humidity = sht3x_extract_humidity(val); | ||
258 | data->last_update = jiffies; | ||
259 | } | ||
260 | |||
261 | out: | ||
262 | mutex_unlock(&data->data_lock); | ||
263 | if (ret) | ||
264 | return ERR_PTR(ret); | ||
265 | |||
266 | return data; | ||
267 | } | ||
268 | |||
269 | /* sysfs attributes */ | ||
270 | static ssize_t temp1_input_show(struct device *dev, | ||
271 | struct device_attribute *attr, char *buf) | ||
272 | { | ||
273 | struct sht3x_data *data = sht3x_update_client(dev); | ||
274 | |||
275 | if (IS_ERR(data)) | ||
276 | return PTR_ERR(data); | ||
277 | |||
278 | return sprintf(buf, "%d\n", data->temperature); | ||
279 | } | ||
280 | |||
281 | static ssize_t humidity1_input_show(struct device *dev, | ||
282 | struct device_attribute *attr, char *buf) | ||
283 | { | ||
284 | struct sht3x_data *data = sht3x_update_client(dev); | ||
285 | |||
286 | if (IS_ERR(data)) | ||
287 | return PTR_ERR(data); | ||
288 | |||
289 | return sprintf(buf, "%u\n", data->humidity); | ||
290 | } | ||
291 | |||
292 | /* | ||
293 | * limits_update must only be called from probe or with data_lock held | ||
294 | */ | ||
295 | static int limits_update(struct sht3x_data *data) | ||
296 | { | ||
297 | int ret; | ||
298 | u8 index; | ||
299 | int temperature; | ||
300 | u32 humidity; | ||
301 | u16 raw; | ||
302 | char buffer[SHT3X_RESPONSE_LENGTH]; | ||
303 | const struct sht3x_limit_commands *commands; | ||
304 | struct i2c_client *client = data->client; | ||
305 | |||
306 | for (index = 0; index < SHT3X_NUM_LIMIT_CMD; index++) { | ||
307 | commands = &limit_commands[index]; | ||
308 | ret = sht3x_read_from_command(client, data, | ||
309 | commands->read_command, buffer, | ||
310 | SHT3X_RESPONSE_LENGTH, 0); | ||
311 | |||
312 | if (ret) | ||
313 | return ret; | ||
314 | |||
315 | raw = be16_to_cpup((__be16 *)buffer); | ||
316 | temperature = sht3x_extract_temperature((raw & 0x01ff) << 7); | ||
317 | humidity = sht3x_extract_humidity(raw & 0xfe00); | ||
318 | data->temperature_limits[index] = temperature; | ||
319 | data->humidity_limits[index] = humidity; | ||
320 | } | ||
321 | |||
322 | return ret; | ||
323 | } | ||
324 | |||
325 | static ssize_t temp1_limit_show(struct device *dev, | ||
326 | struct device_attribute *attr, | ||
327 | char *buf) | ||
328 | { | ||
329 | struct sht3x_data *data = dev_get_drvdata(dev); | ||
330 | u8 index = to_sensor_dev_attr(attr)->index; | ||
331 | int temperature_limit = data->temperature_limits[index]; | ||
332 | |||
333 | return scnprintf(buf, PAGE_SIZE, "%d\n", temperature_limit); | ||
334 | } | ||
335 | |||
336 | static ssize_t humidity1_limit_show(struct device *dev, | ||
337 | struct device_attribute *attr, | ||
338 | char *buf) | ||
339 | { | ||
340 | struct sht3x_data *data = dev_get_drvdata(dev); | ||
341 | u8 index = to_sensor_dev_attr(attr)->index; | ||
342 | u32 humidity_limit = data->humidity_limits[index]; | ||
343 | |||
344 | return scnprintf(buf, PAGE_SIZE, "%u\n", humidity_limit); | ||
345 | } | ||
346 | |||
347 | /* | ||
348 | * limit_store must only be called with data_lock held | ||
349 | */ | ||
350 | static size_t limit_store(struct device *dev, | ||
351 | size_t count, | ||
352 | u8 index, | ||
353 | int temperature, | ||
354 | u32 humidity) | ||
355 | { | ||
356 | char buffer[SHT3X_CMD_LENGTH + SHT3X_WORD_LEN + SHT3X_CRC8_LEN]; | ||
357 | char *position = buffer; | ||
358 | int ret; | ||
359 | u16 raw; | ||
360 | struct sht3x_data *data = dev_get_drvdata(dev); | ||
361 | struct i2c_client *client = data->client; | ||
362 | const struct sht3x_limit_commands *commands; | ||
363 | |||
364 | commands = &limit_commands[index]; | ||
365 | |||
366 | memcpy(position, commands->write_command, SHT3X_CMD_LENGTH); | ||
367 | position += SHT3X_CMD_LENGTH; | ||
368 | /* | ||
369 | * ST = (T + 45) / 175 * 2^16 | ||
370 | * SRH = RH / 100 * 2^16 | ||
371 | * adapted for fixed point arithmetic and packed the same as | ||
372 | * in limit_show() | ||
373 | */ | ||
374 | raw = ((u32)(temperature + 45000) * 24543) >> (16 + 7); | ||
375 | raw |= ((humidity * 42950) >> 16) & 0xfe00; | ||
376 | |||
377 | *((__be16 *)position) = cpu_to_be16(raw); | ||
378 | position += SHT3X_WORD_LEN; | ||
379 | *position = crc8(sht3x_crc8_table, | ||
380 | position - SHT3X_WORD_LEN, | ||
381 | SHT3X_WORD_LEN, | ||
382 | SHT3X_CRC8_INIT); | ||
383 | |||
384 | mutex_lock(&data->i2c_lock); | ||
385 | ret = i2c_master_send(client, buffer, sizeof(buffer)); | ||
386 | mutex_unlock(&data->i2c_lock); | ||
387 | |||
388 | if (ret != sizeof(buffer)) | ||
389 | return ret < 0 ? ret : -EIO; | ||
390 | |||
391 | data->temperature_limits[index] = temperature; | ||
392 | data->humidity_limits[index] = humidity; | ||
393 | return count; | ||
394 | } | ||
395 | |||
396 | static ssize_t temp1_limit_store(struct device *dev, | ||
397 | struct device_attribute *attr, | ||
398 | const char *buf, | ||
399 | size_t count) | ||
400 | { | ||
401 | int temperature; | ||
402 | int ret; | ||
403 | struct sht3x_data *data = dev_get_drvdata(dev); | ||
404 | u8 index = to_sensor_dev_attr(attr)->index; | ||
405 | |||
406 | ret = kstrtoint(buf, 0, &temperature); | ||
407 | if (ret) | ||
408 | return ret; | ||
409 | |||
410 | temperature = clamp_val(temperature, SHT3X_MIN_TEMPERATURE, | ||
411 | SHT3X_MAX_TEMPERATURE); | ||
412 | mutex_lock(&data->data_lock); | ||
413 | ret = limit_store(dev, count, index, temperature, | ||
414 | data->humidity_limits[index]); | ||
415 | mutex_unlock(&data->data_lock); | ||
416 | |||
417 | return ret; | ||
418 | } | ||
419 | |||
420 | static ssize_t humidity1_limit_store(struct device *dev, | ||
421 | struct device_attribute *attr, | ||
422 | const char *buf, | ||
423 | size_t count) | ||
424 | { | ||
425 | u32 humidity; | ||
426 | int ret; | ||
427 | struct sht3x_data *data = dev_get_drvdata(dev); | ||
428 | u8 index = to_sensor_dev_attr(attr)->index; | ||
429 | |||
430 | ret = kstrtou32(buf, 0, &humidity); | ||
431 | if (ret) | ||
432 | return ret; | ||
433 | |||
434 | humidity = clamp_val(humidity, SHT3X_MIN_HUMIDITY, SHT3X_MAX_HUMIDITY); | ||
435 | mutex_lock(&data->data_lock); | ||
436 | ret = limit_store(dev, count, index, data->temperature_limits[index], | ||
437 | humidity); | ||
438 | mutex_unlock(&data->data_lock); | ||
439 | |||
440 | return ret; | ||
441 | } | ||
442 | |||
443 | static void sht3x_select_command(struct sht3x_data *data) | ||
444 | { | ||
445 | /* | ||
446 | * In blocking mode (clock stretching mode) the I2C bus | ||
447 | * is blocked for other traffic, thus the call to i2c_master_recv() | ||
448 | * will wait until the data is ready. For non blocking mode, we | ||
449 | * have to wait ourselves. | ||
450 | */ | ||
451 | if (data->mode > 0) { | ||
452 | data->command = sht3x_cmd_measure_periodic_mode; | ||
453 | data->wait_time = 0; | ||
454 | } else if (data->setup.blocking_io) { | ||
455 | data->command = data->setup.high_precision ? | ||
456 | sht3x_cmd_measure_blocking_hpm : | ||
457 | sht3x_cmd_measure_blocking_lpm; | ||
458 | data->wait_time = 0; | ||
459 | } else { | ||
460 | if (data->setup.high_precision) { | ||
461 | data->command = sht3x_cmd_measure_nonblocking_hpm; | ||
462 | data->wait_time = SHT3X_NONBLOCKING_WAIT_TIME_HPM; | ||
463 | } else { | ||
464 | data->command = sht3x_cmd_measure_nonblocking_lpm; | ||
465 | data->wait_time = SHT3X_NONBLOCKING_WAIT_TIME_LPM; | ||
466 | } | ||
467 | } | ||
468 | } | ||
469 | |||
470 | static int status_register_read(struct device *dev, | ||
471 | struct device_attribute *attr, | ||
472 | char *buffer, int length) | ||
473 | { | ||
474 | int ret; | ||
475 | struct sht3x_data *data = dev_get_drvdata(dev); | ||
476 | struct i2c_client *client = data->client; | ||
477 | |||
478 | ret = sht3x_read_from_command(client, data, sht3x_cmd_read_status_reg, | ||
479 | buffer, length, 0); | ||
480 | |||
481 | return ret; | ||
482 | } | ||
483 | |||
484 | static ssize_t temp1_alarm_show(struct device *dev, | ||
485 | struct device_attribute *attr, | ||
486 | char *buf) | ||
487 | { | ||
488 | char buffer[SHT3X_WORD_LEN + SHT3X_CRC8_LEN]; | ||
489 | int ret; | ||
490 | |||
491 | ret = status_register_read(dev, attr, buffer, | ||
492 | SHT3X_WORD_LEN + SHT3X_CRC8_LEN); | ||
493 | if (ret) | ||
494 | return ret; | ||
495 | |||
496 | return scnprintf(buf, PAGE_SIZE, "%d\n", !!(buffer[0] & 0x04)); | ||
497 | } | ||
498 | |||
499 | static ssize_t humidity1_alarm_show(struct device *dev, | ||
500 | struct device_attribute *attr, | ||
501 | char *buf) | ||
502 | { | ||
503 | char buffer[SHT3X_WORD_LEN + SHT3X_CRC8_LEN]; | ||
504 | int ret; | ||
505 | |||
506 | ret = status_register_read(dev, attr, buffer, | ||
507 | SHT3X_WORD_LEN + SHT3X_CRC8_LEN); | ||
508 | if (ret) | ||
509 | return ret; | ||
510 | |||
511 | return scnprintf(buf, PAGE_SIZE, "%d\n", !!(buffer[0] & 0x08)); | ||
512 | } | ||
513 | |||
514 | static ssize_t heater_enable_show(struct device *dev, | ||
515 | struct device_attribute *attr, | ||
516 | char *buf) | ||
517 | { | ||
518 | char buffer[SHT3X_WORD_LEN + SHT3X_CRC8_LEN]; | ||
519 | int ret; | ||
520 | |||
521 | ret = status_register_read(dev, attr, buffer, | ||
522 | SHT3X_WORD_LEN + SHT3X_CRC8_LEN); | ||
523 | if (ret) | ||
524 | return ret; | ||
525 | |||
526 | return scnprintf(buf, PAGE_SIZE, "%d\n", !!(buffer[0] & 0x20)); | ||
527 | } | ||
528 | |||
529 | static ssize_t heater_enable_store(struct device *dev, | ||
530 | struct device_attribute *attr, | ||
531 | const char *buf, | ||
532 | size_t count) | ||
533 | { | ||
534 | struct sht3x_data *data = dev_get_drvdata(dev); | ||
535 | struct i2c_client *client = data->client; | ||
536 | int ret; | ||
537 | bool status; | ||
538 | |||
539 | ret = kstrtobool(buf, &status); | ||
540 | if (ret) | ||
541 | return ret; | ||
542 | |||
543 | mutex_lock(&data->i2c_lock); | ||
544 | |||
545 | if (status) | ||
546 | ret = i2c_master_send(client, (char *)&sht3x_cmd_heater_on, | ||
547 | SHT3X_CMD_LENGTH); | ||
548 | else | ||
549 | ret = i2c_master_send(client, (char *)&sht3x_cmd_heater_off, | ||
550 | SHT3X_CMD_LENGTH); | ||
551 | |||
552 | mutex_unlock(&data->i2c_lock); | ||
553 | |||
554 | return ret; | ||
555 | } | ||
556 | |||
557 | static ssize_t update_interval_show(struct device *dev, | ||
558 | struct device_attribute *attr, | ||
559 | char *buf) | ||
560 | { | ||
561 | struct sht3x_data *data = dev_get_drvdata(dev); | ||
562 | |||
563 | return scnprintf(buf, PAGE_SIZE, "%u\n", | ||
564 | mode_to_update_interval[data->mode]); | ||
565 | } | ||
566 | |||
567 | static ssize_t update_interval_store(struct device *dev, | ||
568 | struct device_attribute *attr, | ||
569 | const char *buf, | ||
570 | size_t count) | ||
571 | { | ||
572 | u16 update_interval; | ||
573 | u8 mode; | ||
574 | int ret; | ||
575 | const char *command; | ||
576 | struct sht3x_data *data = dev_get_drvdata(dev); | ||
577 | struct i2c_client *client = data->client; | ||
578 | |||
579 | ret = kstrtou16(buf, 0, &update_interval); | ||
580 | if (ret) | ||
581 | return ret; | ||
582 | |||
583 | mode = get_mode_from_update_interval(update_interval); | ||
584 | |||
585 | mutex_lock(&data->data_lock); | ||
586 | /* mode did not change */ | ||
587 | if (mode == data->mode) { | ||
588 | mutex_unlock(&data->data_lock); | ||
589 | return count; | ||
590 | } | ||
591 | |||
592 | mutex_lock(&data->i2c_lock); | ||
593 | /* | ||
594 | * Abort periodic measure mode. | ||
595 | * To do any changes to the configuration while in periodic mode, we | ||
596 | * have to send a break command to the sensor, which then falls back | ||
597 | * to single shot (mode = 0). | ||
598 | */ | ||
599 | if (data->mode > 0) { | ||
600 | ret = i2c_master_send(client, sht3x_cmd_break, | ||
601 | SHT3X_CMD_LENGTH); | ||
602 | if (ret != SHT3X_CMD_LENGTH) | ||
603 | goto out; | ||
604 | data->mode = 0; | ||
605 | } | ||
606 | |||
607 | if (mode > 0) { | ||
608 | if (data->setup.high_precision) | ||
609 | command = periodic_measure_commands_hpm[mode - 1]; | ||
610 | else | ||
611 | command = periodic_measure_commands_lpm[mode - 1]; | ||
612 | |||
613 | /* select mode */ | ||
614 | ret = i2c_master_send(client, command, SHT3X_CMD_LENGTH); | ||
615 | if (ret != SHT3X_CMD_LENGTH) | ||
616 | goto out; | ||
617 | } | ||
618 | |||
619 | /* select mode and command */ | ||
620 | data->mode = mode; | ||
621 | sht3x_select_command(data); | ||
622 | |||
623 | out: | ||
624 | mutex_unlock(&data->i2c_lock); | ||
625 | mutex_unlock(&data->data_lock); | ||
626 | if (ret != SHT3X_CMD_LENGTH) | ||
627 | return ret < 0 ? ret : -EIO; | ||
628 | |||
629 | return count; | ||
630 | } | ||
631 | |||
632 | static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, temp1_input_show, NULL, 0); | ||
633 | static SENSOR_DEVICE_ATTR(humidity1_input, S_IRUGO, humidity1_input_show, | ||
634 | NULL, 0); | ||
635 | static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO | S_IWUSR, | ||
636 | temp1_limit_show, temp1_limit_store, | ||
637 | limit_max); | ||
638 | static SENSOR_DEVICE_ATTR(humidity1_max, S_IRUGO | S_IWUSR, | ||
639 | humidity1_limit_show, humidity1_limit_store, | ||
640 | limit_max); | ||
641 | static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IRUGO | S_IWUSR, | ||
642 | temp1_limit_show, temp1_limit_store, | ||
643 | limit_max_hyst); | ||
644 | static SENSOR_DEVICE_ATTR(humidity1_max_hyst, S_IRUGO | S_IWUSR, | ||
645 | humidity1_limit_show, humidity1_limit_store, | ||
646 | limit_max_hyst); | ||
647 | static SENSOR_DEVICE_ATTR(temp1_min, S_IRUGO | S_IWUSR, | ||
648 | temp1_limit_show, temp1_limit_store, | ||
649 | limit_min); | ||
650 | static SENSOR_DEVICE_ATTR(humidity1_min, S_IRUGO | S_IWUSR, | ||
651 | humidity1_limit_show, humidity1_limit_store, | ||
652 | limit_min); | ||
653 | static SENSOR_DEVICE_ATTR(temp1_min_hyst, S_IRUGO | S_IWUSR, | ||
654 | temp1_limit_show, temp1_limit_store, | ||
655 | limit_min_hyst); | ||
656 | static SENSOR_DEVICE_ATTR(humidity1_min_hyst, S_IRUGO | S_IWUSR, | ||
657 | humidity1_limit_show, humidity1_limit_store, | ||
658 | limit_min_hyst); | ||
659 | static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, temp1_alarm_show, NULL, 0); | ||
660 | static SENSOR_DEVICE_ATTR(humidity1_alarm, S_IRUGO, humidity1_alarm_show, | ||
661 | NULL, 0); | ||
662 | static SENSOR_DEVICE_ATTR(heater_enable, S_IRUGO | S_IWUSR, | ||
663 | heater_enable_show, heater_enable_store, 0); | ||
664 | static SENSOR_DEVICE_ATTR(update_interval, S_IRUGO | S_IWUSR, | ||
665 | update_interval_show, update_interval_store, 0); | ||
666 | |||
667 | static struct attribute *sht3x_attrs[] = { | ||
668 | &sensor_dev_attr_temp1_input.dev_attr.attr, | ||
669 | &sensor_dev_attr_humidity1_input.dev_attr.attr, | ||
670 | &sensor_dev_attr_temp1_max.dev_attr.attr, | ||
671 | &sensor_dev_attr_temp1_max_hyst.dev_attr.attr, | ||
672 | &sensor_dev_attr_humidity1_max.dev_attr.attr, | ||
673 | &sensor_dev_attr_humidity1_max_hyst.dev_attr.attr, | ||
674 | &sensor_dev_attr_temp1_min.dev_attr.attr, | ||
675 | &sensor_dev_attr_temp1_min_hyst.dev_attr.attr, | ||
676 | &sensor_dev_attr_humidity1_min.dev_attr.attr, | ||
677 | &sensor_dev_attr_humidity1_min_hyst.dev_attr.attr, | ||
678 | &sensor_dev_attr_temp1_alarm.dev_attr.attr, | ||
679 | &sensor_dev_attr_humidity1_alarm.dev_attr.attr, | ||
680 | &sensor_dev_attr_heater_enable.dev_attr.attr, | ||
681 | &sensor_dev_attr_update_interval.dev_attr.attr, | ||
682 | NULL | ||
683 | }; | ||
684 | |||
685 | static struct attribute *sts3x_attrs[] = { | ||
686 | &sensor_dev_attr_temp1_input.dev_attr.attr, | ||
687 | NULL | ||
688 | }; | ||
689 | |||
690 | ATTRIBUTE_GROUPS(sht3x); | ||
691 | ATTRIBUTE_GROUPS(sts3x); | ||
692 | |||
693 | static int sht3x_probe(struct i2c_client *client, | ||
694 | const struct i2c_device_id *id) | ||
695 | { | ||
696 | int ret; | ||
697 | struct sht3x_data *data; | ||
698 | struct device *hwmon_dev; | ||
699 | struct i2c_adapter *adap = client->adapter; | ||
700 | struct device *dev = &client->dev; | ||
701 | const struct attribute_group **attribute_groups; | ||
702 | |||
703 | /* | ||
704 | * we require full i2c support since the sht3x uses multi-byte read and | ||
705 | * writes as well as multi-byte commands which are not supported by | ||
706 | * the smbus protocol | ||
707 | */ | ||
708 | if (!i2c_check_functionality(adap, I2C_FUNC_I2C)) | ||
709 | return -ENODEV; | ||
710 | |||
711 | ret = i2c_master_send(client, sht3x_cmd_clear_status_reg, | ||
712 | SHT3X_CMD_LENGTH); | ||
713 | if (ret != SHT3X_CMD_LENGTH) | ||
714 | return ret < 0 ? ret : -ENODEV; | ||
715 | |||
716 | data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); | ||
717 | if (!data) | ||
718 | return -ENOMEM; | ||
719 | |||
720 | data->setup.blocking_io = false; | ||
721 | data->setup.high_precision = true; | ||
722 | data->mode = 0; | ||
723 | data->last_update = 0; | ||
724 | data->client = client; | ||
725 | crc8_populate_msb(sht3x_crc8_table, SHT3X_CRC8_POLYNOMIAL); | ||
726 | |||
727 | if (client->dev.platform_data) | ||
728 | data->setup = *(struct sht3x_platform_data *)dev->platform_data; | ||
729 | |||
730 | sht3x_select_command(data); | ||
731 | |||
732 | mutex_init(&data->i2c_lock); | ||
733 | mutex_init(&data->data_lock); | ||
734 | |||
735 | ret = limits_update(data); | ||
736 | if (ret) | ||
737 | return ret; | ||
738 | |||
739 | if (id->driver_data == sts3x) | ||
740 | attribute_groups = sts3x_groups; | ||
741 | else | ||
742 | attribute_groups = sht3x_groups; | ||
743 | |||
744 | hwmon_dev = devm_hwmon_device_register_with_groups(dev, | ||
745 | client->name, | ||
746 | data, | ||
747 | attribute_groups); | ||
748 | |||
749 | if (IS_ERR(hwmon_dev)) | ||
750 | dev_dbg(dev, "unable to register hwmon device\n"); | ||
751 | |||
752 | return PTR_ERR_OR_ZERO(hwmon_dev); | ||
753 | } | ||
754 | |||
755 | /* device ID table */ | ||
756 | static const struct i2c_device_id sht3x_ids[] = { | ||
757 | {"sht3x", sht3x}, | ||
758 | {"sts3x", sts3x}, | ||
759 | {} | ||
760 | }; | ||
761 | |||
762 | MODULE_DEVICE_TABLE(i2c, sht3x_ids); | ||
763 | |||
764 | static struct i2c_driver sht3x_i2c_driver = { | ||
765 | .driver.name = "sht3x", | ||
766 | .probe = sht3x_probe, | ||
767 | .id_table = sht3x_ids, | ||
768 | }; | ||
769 | |||
770 | module_i2c_driver(sht3x_i2c_driver); | ||
771 | |||
772 | MODULE_AUTHOR("David Frey <david.frey@sensirion.com>"); | ||
773 | MODULE_AUTHOR("Pascal Sachs <pascal.sachs@sensirion.com>"); | ||
774 | MODULE_DESCRIPTION("Sensirion SHT3x humidity and temperature sensor driver"); | ||
775 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/hwmon/tmp102.c b/drivers/hwmon/tmp102.c index f1e96fd7f445..a942a2574a4d 100644 --- a/drivers/hwmon/tmp102.c +++ b/drivers/hwmon/tmp102.c | |||
@@ -11,12 +11,9 @@ | |||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
13 | * GNU General Public License for more details. | 13 | * GNU General Public License for more details. |
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA | ||
18 | */ | 14 | */ |
19 | 15 | ||
16 | #include <linux/delay.h> | ||
20 | #include <linux/module.h> | 17 | #include <linux/module.h> |
21 | #include <linux/init.h> | 18 | #include <linux/init.h> |
22 | #include <linux/slab.h> | 19 | #include <linux/slab.h> |
@@ -27,6 +24,7 @@ | |||
27 | #include <linux/mutex.h> | 24 | #include <linux/mutex.h> |
28 | #include <linux/device.h> | 25 | #include <linux/device.h> |
29 | #include <linux/jiffies.h> | 26 | #include <linux/jiffies.h> |
27 | #include <linux/regmap.h> | ||
30 | #include <linux/thermal.h> | 28 | #include <linux/thermal.h> |
31 | #include <linux/of.h> | 29 | #include <linux/of.h> |
32 | 30 | ||
@@ -50,14 +48,23 @@ | |||
50 | #define TMP102_TLOW_REG 0x02 | 48 | #define TMP102_TLOW_REG 0x02 |
51 | #define TMP102_THIGH_REG 0x03 | 49 | #define TMP102_THIGH_REG 0x03 |
52 | 50 | ||
51 | #define TMP102_CONFREG_MASK (TMP102_CONF_SD | TMP102_CONF_TM | \ | ||
52 | TMP102_CONF_POL | TMP102_CONF_F0 | \ | ||
53 | TMP102_CONF_F1 | TMP102_CONF_OS | \ | ||
54 | TMP102_CONF_EM | TMP102_CONF_AL | \ | ||
55 | TMP102_CONF_CR0 | TMP102_CONF_CR1) | ||
56 | |||
57 | #define TMP102_CONFIG_CLEAR (TMP102_CONF_SD | TMP102_CONF_OS | \ | ||
58 | TMP102_CONF_CR0) | ||
59 | #define TMP102_CONFIG_SET (TMP102_CONF_TM | TMP102_CONF_EM | \ | ||
60 | TMP102_CONF_CR1) | ||
61 | |||
62 | #define CONVERSION_TIME_MS 35 /* in milli-seconds */ | ||
63 | |||
53 | struct tmp102 { | 64 | struct tmp102 { |
54 | struct i2c_client *client; | 65 | struct regmap *regmap; |
55 | struct device *hwmon_dev; | ||
56 | struct mutex lock; | ||
57 | u16 config_orig; | 66 | u16 config_orig; |
58 | unsigned long last_update; | 67 | unsigned long ready_time; |
59 | int temp[3]; | ||
60 | bool first_time; | ||
61 | }; | 68 | }; |
62 | 69 | ||
63 | /* convert left adjusted 13-bit TMP102 register value to milliCelsius */ | 70 | /* convert left adjusted 13-bit TMP102 register value to milliCelsius */ |
@@ -72,44 +79,22 @@ static inline u16 tmp102_mC_to_reg(int val) | |||
72 | return (val * 128) / 1000; | 79 | return (val * 128) / 1000; |
73 | } | 80 | } |
74 | 81 | ||
75 | static const u8 tmp102_reg[] = { | ||
76 | TMP102_TEMP_REG, | ||
77 | TMP102_TLOW_REG, | ||
78 | TMP102_THIGH_REG, | ||
79 | }; | ||
80 | |||
81 | static struct tmp102 *tmp102_update_device(struct device *dev) | ||
82 | { | ||
83 | struct tmp102 *tmp102 = dev_get_drvdata(dev); | ||
84 | struct i2c_client *client = tmp102->client; | ||
85 | |||
86 | mutex_lock(&tmp102->lock); | ||
87 | if (time_after(jiffies, tmp102->last_update + HZ / 3)) { | ||
88 | int i; | ||
89 | for (i = 0; i < ARRAY_SIZE(tmp102->temp); ++i) { | ||
90 | int status = i2c_smbus_read_word_swapped(client, | ||
91 | tmp102_reg[i]); | ||
92 | if (status > -1) | ||
93 | tmp102->temp[i] = tmp102_reg_to_mC(status); | ||
94 | } | ||
95 | tmp102->last_update = jiffies; | ||
96 | tmp102->first_time = false; | ||
97 | } | ||
98 | mutex_unlock(&tmp102->lock); | ||
99 | return tmp102; | ||
100 | } | ||
101 | |||
102 | static int tmp102_read_temp(void *dev, int *temp) | 82 | static int tmp102_read_temp(void *dev, int *temp) |
103 | { | 83 | { |
104 | struct tmp102 *tmp102 = tmp102_update_device(dev); | 84 | struct tmp102 *tmp102 = dev_get_drvdata(dev); |
85 | unsigned int reg; | ||
86 | int ret; | ||
105 | 87 | ||
106 | /* Is it too early even to return a conversion? */ | 88 | if (time_before(jiffies, tmp102->ready_time)) { |
107 | if (tmp102->first_time) { | ||
108 | dev_dbg(dev, "%s: Conversion not ready yet..\n", __func__); | 89 | dev_dbg(dev, "%s: Conversion not ready yet..\n", __func__); |
109 | return -EAGAIN; | 90 | return -EAGAIN; |
110 | } | 91 | } |
111 | 92 | ||
112 | *temp = tmp102->temp[0]; | 93 | ret = regmap_read(tmp102->regmap, TMP102_TEMP_REG, ®); |
94 | if (ret < 0) | ||
95 | return ret; | ||
96 | |||
97 | *temp = tmp102_reg_to_mC(reg); | ||
113 | 98 | ||
114 | return 0; | 99 | return 0; |
115 | } | 100 | } |
@@ -119,13 +104,20 @@ static ssize_t tmp102_show_temp(struct device *dev, | |||
119 | char *buf) | 104 | char *buf) |
120 | { | 105 | { |
121 | struct sensor_device_attribute *sda = to_sensor_dev_attr(attr); | 106 | struct sensor_device_attribute *sda = to_sensor_dev_attr(attr); |
122 | struct tmp102 *tmp102 = tmp102_update_device(dev); | 107 | struct tmp102 *tmp102 = dev_get_drvdata(dev); |
108 | int regaddr = sda->index; | ||
109 | unsigned int reg; | ||
110 | int err; | ||
123 | 111 | ||
124 | /* Is it too early even to return a read? */ | 112 | if (regaddr == TMP102_TEMP_REG && |
125 | if (tmp102->first_time) | 113 | time_before(jiffies, tmp102->ready_time)) |
126 | return -EAGAIN; | 114 | return -EAGAIN; |
127 | 115 | ||
128 | return sprintf(buf, "%d\n", tmp102->temp[sda->index]); | 116 | err = regmap_read(tmp102->regmap, regaddr, ®); |
117 | if (err < 0) | ||
118 | return err; | ||
119 | |||
120 | return sprintf(buf, "%d\n", tmp102_reg_to_mC(reg)); | ||
129 | } | 121 | } |
130 | 122 | ||
131 | static ssize_t tmp102_set_temp(struct device *dev, | 123 | static ssize_t tmp102_set_temp(struct device *dev, |
@@ -134,29 +126,26 @@ static ssize_t tmp102_set_temp(struct device *dev, | |||
134 | { | 126 | { |
135 | struct sensor_device_attribute *sda = to_sensor_dev_attr(attr); | 127 | struct sensor_device_attribute *sda = to_sensor_dev_attr(attr); |
136 | struct tmp102 *tmp102 = dev_get_drvdata(dev); | 128 | struct tmp102 *tmp102 = dev_get_drvdata(dev); |
137 | struct i2c_client *client = tmp102->client; | 129 | int reg = sda->index; |
138 | long val; | 130 | long val; |
139 | int status; | 131 | int err; |
140 | 132 | ||
141 | if (kstrtol(buf, 10, &val) < 0) | 133 | if (kstrtol(buf, 10, &val) < 0) |
142 | return -EINVAL; | 134 | return -EINVAL; |
143 | val = clamp_val(val, -256000, 255000); | 135 | val = clamp_val(val, -256000, 255000); |
144 | 136 | ||
145 | mutex_lock(&tmp102->lock); | 137 | err = regmap_write(tmp102->regmap, reg, tmp102_mC_to_reg(val)); |
146 | tmp102->temp[sda->index] = val; | 138 | return err ? : count; |
147 | status = i2c_smbus_write_word_swapped(client, tmp102_reg[sda->index], | ||
148 | tmp102_mC_to_reg(val)); | ||
149 | mutex_unlock(&tmp102->lock); | ||
150 | return status ? : count; | ||
151 | } | 139 | } |
152 | 140 | ||
153 | static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, tmp102_show_temp, NULL , 0); | 141 | static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, tmp102_show_temp, NULL, |
142 | TMP102_TEMP_REG); | ||
154 | 143 | ||
155 | static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO, tmp102_show_temp, | 144 | static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO, tmp102_show_temp, |
156 | tmp102_set_temp, 1); | 145 | tmp102_set_temp, TMP102_TLOW_REG); |
157 | 146 | ||
158 | static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, tmp102_show_temp, | 147 | static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, tmp102_show_temp, |
159 | tmp102_set_temp, 2); | 148 | tmp102_set_temp, TMP102_THIGH_REG); |
160 | 149 | ||
161 | static struct attribute *tmp102_attrs[] = { | 150 | static struct attribute *tmp102_attrs[] = { |
162 | &sensor_dev_attr_temp1_input.dev_attr.attr, | 151 | &sensor_dev_attr_temp1_input.dev_attr.attr, |
@@ -166,20 +155,46 @@ static struct attribute *tmp102_attrs[] = { | |||
166 | }; | 155 | }; |
167 | ATTRIBUTE_GROUPS(tmp102); | 156 | ATTRIBUTE_GROUPS(tmp102); |
168 | 157 | ||
169 | #define TMP102_CONFIG (TMP102_CONF_TM | TMP102_CONF_EM | TMP102_CONF_CR1) | ||
170 | #define TMP102_CONFIG_RD_ONLY (TMP102_CONF_R0 | TMP102_CONF_R1 | TMP102_CONF_AL) | ||
171 | |||
172 | static const struct thermal_zone_of_device_ops tmp102_of_thermal_ops = { | 158 | static const struct thermal_zone_of_device_ops tmp102_of_thermal_ops = { |
173 | .get_temp = tmp102_read_temp, | 159 | .get_temp = tmp102_read_temp, |
174 | }; | 160 | }; |
175 | 161 | ||
162 | static void tmp102_restore_config(void *data) | ||
163 | { | ||
164 | struct tmp102 *tmp102 = data; | ||
165 | |||
166 | regmap_write(tmp102->regmap, TMP102_CONF_REG, tmp102->config_orig); | ||
167 | } | ||
168 | |||
169 | static bool tmp102_is_writeable_reg(struct device *dev, unsigned int reg) | ||
170 | { | ||
171 | return reg != TMP102_TEMP_REG; | ||
172 | } | ||
173 | |||
174 | static bool tmp102_is_volatile_reg(struct device *dev, unsigned int reg) | ||
175 | { | ||
176 | return reg == TMP102_TEMP_REG; | ||
177 | } | ||
178 | |||
179 | static const struct regmap_config tmp102_regmap_config = { | ||
180 | .reg_bits = 8, | ||
181 | .val_bits = 16, | ||
182 | .max_register = TMP102_THIGH_REG, | ||
183 | .writeable_reg = tmp102_is_writeable_reg, | ||
184 | .volatile_reg = tmp102_is_volatile_reg, | ||
185 | .val_format_endian = REGMAP_ENDIAN_BIG, | ||
186 | .cache_type = REGCACHE_RBTREE, | ||
187 | .use_single_rw = true, | ||
188 | }; | ||
189 | |||
176 | static int tmp102_probe(struct i2c_client *client, | 190 | static int tmp102_probe(struct i2c_client *client, |
177 | const struct i2c_device_id *id) | 191 | const struct i2c_device_id *id) |
178 | { | 192 | { |
179 | struct device *dev = &client->dev; | 193 | struct device *dev = &client->dev; |
180 | struct device *hwmon_dev; | 194 | struct device *hwmon_dev; |
181 | struct tmp102 *tmp102; | 195 | struct tmp102 *tmp102; |
182 | int status; | 196 | unsigned int regval; |
197 | int err; | ||
183 | 198 | ||
184 | if (!i2c_check_functionality(client->adapter, | 199 | if (!i2c_check_functionality(client->adapter, |
185 | I2C_FUNC_SMBUS_WORD_DATA)) { | 200 | I2C_FUNC_SMBUS_WORD_DATA)) { |
@@ -193,101 +208,82 @@ static int tmp102_probe(struct i2c_client *client, | |||
193 | return -ENOMEM; | 208 | return -ENOMEM; |
194 | 209 | ||
195 | i2c_set_clientdata(client, tmp102); | 210 | i2c_set_clientdata(client, tmp102); |
196 | tmp102->client = client; | ||
197 | 211 | ||
198 | status = i2c_smbus_read_word_swapped(client, TMP102_CONF_REG); | 212 | tmp102->regmap = devm_regmap_init_i2c(client, &tmp102_regmap_config); |
199 | if (status < 0) { | 213 | if (IS_ERR(tmp102->regmap)) |
214 | return PTR_ERR(tmp102->regmap); | ||
215 | |||
216 | err = regmap_read(tmp102->regmap, TMP102_CONF_REG, ®val); | ||
217 | if (err < 0) { | ||
200 | dev_err(dev, "error reading config register\n"); | 218 | dev_err(dev, "error reading config register\n"); |
201 | return status; | 219 | return err; |
202 | } | 220 | } |
203 | tmp102->config_orig = status; | 221 | |
204 | status = i2c_smbus_write_word_swapped(client, TMP102_CONF_REG, | 222 | if ((regval & ~TMP102_CONFREG_MASK) != |
205 | TMP102_CONFIG); | 223 | (TMP102_CONF_R0 | TMP102_CONF_R1)) { |
206 | if (status < 0) { | 224 | dev_err(dev, "unexpected config register value\n"); |
207 | dev_err(dev, "error writing config register\n"); | 225 | return -ENODEV; |
208 | goto fail_restore_config; | ||
209 | } | 226 | } |
210 | status = i2c_smbus_read_word_swapped(client, TMP102_CONF_REG); | 227 | |
211 | if (status < 0) { | 228 | tmp102->config_orig = regval; |
212 | dev_err(dev, "error reading config register\n"); | 229 | |
213 | goto fail_restore_config; | 230 | devm_add_action(dev, tmp102_restore_config, tmp102); |
231 | |||
232 | regval &= ~TMP102_CONFIG_CLEAR; | ||
233 | regval |= TMP102_CONFIG_SET; | ||
234 | |||
235 | err = regmap_write(tmp102->regmap, TMP102_CONF_REG, regval); | ||
236 | if (err < 0) { | ||
237 | dev_err(dev, "error writing config register\n"); | ||
238 | return err; | ||
214 | } | 239 | } |
215 | status &= ~TMP102_CONFIG_RD_ONLY; | 240 | |
216 | if (status != TMP102_CONFIG) { | 241 | tmp102->ready_time = jiffies; |
217 | dev_err(dev, "config settings did not stick\n"); | 242 | if (tmp102->config_orig & TMP102_CONF_SD) { |
218 | status = -ENODEV; | 243 | /* |
219 | goto fail_restore_config; | 244 | * Mark that we are not ready with data until the first |
245 | * conversion is complete | ||
246 | */ | ||
247 | tmp102->ready_time += msecs_to_jiffies(CONVERSION_TIME_MS); | ||
220 | } | 248 | } |
221 | tmp102->last_update = jiffies; | ||
222 | /* Mark that we are not ready with data until conversion is complete */ | ||
223 | tmp102->first_time = true; | ||
224 | mutex_init(&tmp102->lock); | ||
225 | 249 | ||
226 | hwmon_dev = hwmon_device_register_with_groups(dev, client->name, | 250 | hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name, |
227 | tmp102, tmp102_groups); | 251 | tmp102, |
252 | tmp102_groups); | ||
228 | if (IS_ERR(hwmon_dev)) { | 253 | if (IS_ERR(hwmon_dev)) { |
229 | dev_dbg(dev, "unable to register hwmon device\n"); | 254 | dev_dbg(dev, "unable to register hwmon device\n"); |
230 | status = PTR_ERR(hwmon_dev); | 255 | return PTR_ERR(hwmon_dev); |
231 | goto fail_restore_config; | ||
232 | } | 256 | } |
233 | tmp102->hwmon_dev = hwmon_dev; | ||
234 | devm_thermal_zone_of_sensor_register(hwmon_dev, 0, hwmon_dev, | 257 | devm_thermal_zone_of_sensor_register(hwmon_dev, 0, hwmon_dev, |
235 | &tmp102_of_thermal_ops); | 258 | &tmp102_of_thermal_ops); |
236 | 259 | ||
237 | dev_info(dev, "initialized\n"); | 260 | dev_info(dev, "initialized\n"); |
238 | 261 | ||
239 | return 0; | 262 | return 0; |
240 | |||
241 | fail_restore_config: | ||
242 | i2c_smbus_write_word_swapped(client, TMP102_CONF_REG, | ||
243 | tmp102->config_orig); | ||
244 | return status; | ||
245 | } | ||
246 | |||
247 | static int tmp102_remove(struct i2c_client *client) | ||
248 | { | ||
249 | struct tmp102 *tmp102 = i2c_get_clientdata(client); | ||
250 | |||
251 | hwmon_device_unregister(tmp102->hwmon_dev); | ||
252 | |||
253 | /* Stop monitoring if device was stopped originally */ | ||
254 | if (tmp102->config_orig & TMP102_CONF_SD) { | ||
255 | int config; | ||
256 | |||
257 | config = i2c_smbus_read_word_swapped(client, TMP102_CONF_REG); | ||
258 | if (config >= 0) | ||
259 | i2c_smbus_write_word_swapped(client, TMP102_CONF_REG, | ||
260 | config | TMP102_CONF_SD); | ||
261 | } | ||
262 | |||
263 | return 0; | ||
264 | } | 263 | } |
265 | 264 | ||
266 | #ifdef CONFIG_PM_SLEEP | 265 | #ifdef CONFIG_PM_SLEEP |
267 | static int tmp102_suspend(struct device *dev) | 266 | static int tmp102_suspend(struct device *dev) |
268 | { | 267 | { |
269 | struct i2c_client *client = to_i2c_client(dev); | 268 | struct i2c_client *client = to_i2c_client(dev); |
270 | int config; | 269 | struct tmp102 *tmp102 = i2c_get_clientdata(client); |
271 | |||
272 | config = i2c_smbus_read_word_swapped(client, TMP102_CONF_REG); | ||
273 | if (config < 0) | ||
274 | return config; | ||
275 | 270 | ||
276 | config |= TMP102_CONF_SD; | 271 | return regmap_update_bits(tmp102->regmap, TMP102_CONF_REG, |
277 | return i2c_smbus_write_word_swapped(client, TMP102_CONF_REG, config); | 272 | TMP102_CONF_SD, TMP102_CONF_SD); |
278 | } | 273 | } |
279 | 274 | ||
280 | static int tmp102_resume(struct device *dev) | 275 | static int tmp102_resume(struct device *dev) |
281 | { | 276 | { |
282 | struct i2c_client *client = to_i2c_client(dev); | 277 | struct i2c_client *client = to_i2c_client(dev); |
283 | int config; | 278 | struct tmp102 *tmp102 = i2c_get_clientdata(client); |
279 | int err; | ||
280 | |||
281 | err = regmap_update_bits(tmp102->regmap, TMP102_CONF_REG, | ||
282 | TMP102_CONF_SD, 0); | ||
284 | 283 | ||
285 | config = i2c_smbus_read_word_swapped(client, TMP102_CONF_REG); | 284 | tmp102->ready_time = jiffies + msecs_to_jiffies(CONVERSION_TIME_MS); |
286 | if (config < 0) | ||
287 | return config; | ||
288 | 285 | ||
289 | config &= ~TMP102_CONF_SD; | 286 | return err; |
290 | return i2c_smbus_write_word_swapped(client, TMP102_CONF_REG, config); | ||
291 | } | 287 | } |
292 | #endif /* CONFIG_PM */ | 288 | #endif /* CONFIG_PM */ |
293 | 289 | ||
@@ -303,7 +299,6 @@ static struct i2c_driver tmp102_driver = { | |||
303 | .driver.name = DRIVER_NAME, | 299 | .driver.name = DRIVER_NAME, |
304 | .driver.pm = &tmp102_dev_pm_ops, | 300 | .driver.pm = &tmp102_dev_pm_ops, |
305 | .probe = tmp102_probe, | 301 | .probe = tmp102_probe, |
306 | .remove = tmp102_remove, | ||
307 | .id_table = tmp102_id, | 302 | .id_table = tmp102_id, |
308 | }; | 303 | }; |
309 | 304 | ||
diff --git a/drivers/hwmon/tmp401.c b/drivers/hwmon/tmp401.c index ccf4cffe0ee1..eeeed2c7d081 100644 --- a/drivers/hwmon/tmp401.c +++ b/drivers/hwmon/tmp401.c | |||
@@ -47,7 +47,7 @@ | |||
47 | static const unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4c, 0x4d, | 47 | static const unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4c, 0x4d, |
48 | 0x4e, 0x4f, I2C_CLIENT_END }; | 48 | 0x4e, 0x4f, I2C_CLIENT_END }; |
49 | 49 | ||
50 | enum chips { tmp401, tmp411, tmp431, tmp432, tmp435 }; | 50 | enum chips { tmp401, tmp411, tmp431, tmp432, tmp435, tmp461 }; |
51 | 51 | ||
52 | /* | 52 | /* |
53 | * The TMP401 registers, note some registers have different addresses for | 53 | * The TMP401 registers, note some registers have different addresses for |
@@ -62,31 +62,34 @@ enum chips { tmp401, tmp411, tmp431, tmp432, tmp435 }; | |||
62 | #define TMP401_MANUFACTURER_ID_REG 0xFE | 62 | #define TMP401_MANUFACTURER_ID_REG 0xFE |
63 | #define TMP401_DEVICE_ID_REG 0xFF | 63 | #define TMP401_DEVICE_ID_REG 0xFF |
64 | 64 | ||
65 | static const u8 TMP401_TEMP_MSB_READ[6][2] = { | 65 | static const u8 TMP401_TEMP_MSB_READ[7][2] = { |
66 | { 0x00, 0x01 }, /* temp */ | 66 | { 0x00, 0x01 }, /* temp */ |
67 | { 0x06, 0x08 }, /* low limit */ | 67 | { 0x06, 0x08 }, /* low limit */ |
68 | { 0x05, 0x07 }, /* high limit */ | 68 | { 0x05, 0x07 }, /* high limit */ |
69 | { 0x20, 0x19 }, /* therm (crit) limit */ | 69 | { 0x20, 0x19 }, /* therm (crit) limit */ |
70 | { 0x30, 0x34 }, /* lowest */ | 70 | { 0x30, 0x34 }, /* lowest */ |
71 | { 0x32, 0x36 }, /* highest */ | 71 | { 0x32, 0x36 }, /* highest */ |
72 | { 0, 0x11 }, /* offset */ | ||
72 | }; | 73 | }; |
73 | 74 | ||
74 | static const u8 TMP401_TEMP_MSB_WRITE[6][2] = { | 75 | static const u8 TMP401_TEMP_MSB_WRITE[7][2] = { |
75 | { 0, 0 }, /* temp (unused) */ | 76 | { 0, 0 }, /* temp (unused) */ |
76 | { 0x0C, 0x0E }, /* low limit */ | 77 | { 0x0C, 0x0E }, /* low limit */ |
77 | { 0x0B, 0x0D }, /* high limit */ | 78 | { 0x0B, 0x0D }, /* high limit */ |
78 | { 0x20, 0x19 }, /* therm (crit) limit */ | 79 | { 0x20, 0x19 }, /* therm (crit) limit */ |
79 | { 0x30, 0x34 }, /* lowest */ | 80 | { 0x30, 0x34 }, /* lowest */ |
80 | { 0x32, 0x36 }, /* highest */ | 81 | { 0x32, 0x36 }, /* highest */ |
82 | { 0, 0x11 }, /* offset */ | ||
81 | }; | 83 | }; |
82 | 84 | ||
83 | static const u8 TMP401_TEMP_LSB[6][2] = { | 85 | static const u8 TMP401_TEMP_LSB[7][2] = { |
84 | { 0x15, 0x10 }, /* temp */ | 86 | { 0x15, 0x10 }, /* temp */ |
85 | { 0x17, 0x14 }, /* low limit */ | 87 | { 0x17, 0x14 }, /* low limit */ |
86 | { 0x16, 0x13 }, /* high limit */ | 88 | { 0x16, 0x13 }, /* high limit */ |
87 | { 0, 0 }, /* therm (crit) limit (unused) */ | 89 | { 0, 0 }, /* therm (crit) limit (unused) */ |
88 | { 0x31, 0x35 }, /* lowest */ | 90 | { 0x31, 0x35 }, /* lowest */ |
89 | { 0x33, 0x37 }, /* highest */ | 91 | { 0x33, 0x37 }, /* highest */ |
92 | { 0, 0x12 }, /* offset */ | ||
90 | }; | 93 | }; |
91 | 94 | ||
92 | static const u8 TMP432_TEMP_MSB_READ[4][3] = { | 95 | static const u8 TMP432_TEMP_MSB_READ[4][3] = { |
@@ -149,6 +152,7 @@ static const struct i2c_device_id tmp401_id[] = { | |||
149 | { "tmp431", tmp431 }, | 152 | { "tmp431", tmp431 }, |
150 | { "tmp432", tmp432 }, | 153 | { "tmp432", tmp432 }, |
151 | { "tmp435", tmp435 }, | 154 | { "tmp435", tmp435 }, |
155 | { "tmp461", tmp461 }, | ||
152 | { } | 156 | { } |
153 | }; | 157 | }; |
154 | MODULE_DEVICE_TABLE(i2c, tmp401_id); | 158 | MODULE_DEVICE_TABLE(i2c, tmp401_id); |
@@ -170,7 +174,7 @@ struct tmp401_data { | |||
170 | /* register values */ | 174 | /* register values */ |
171 | u8 status[4]; | 175 | u8 status[4]; |
172 | u8 config; | 176 | u8 config; |
173 | u16 temp[6][3]; | 177 | u16 temp[7][3]; |
174 | u8 temp_crit_hyst; | 178 | u8 temp_crit_hyst; |
175 | }; | 179 | }; |
176 | 180 | ||
@@ -613,6 +617,22 @@ static const struct attribute_group tmp432_group = { | |||
613 | }; | 617 | }; |
614 | 618 | ||
615 | /* | 619 | /* |
620 | * Additional features of the TMP461 chip. | ||
621 | * The TMP461 temperature offset for the remote channel. | ||
622 | */ | ||
623 | static SENSOR_DEVICE_ATTR_2(temp2_offset, S_IWUSR | S_IRUGO, show_temp, | ||
624 | store_temp, 6, 1); | ||
625 | |||
626 | static struct attribute *tmp461_attributes[] = { | ||
627 | &sensor_dev_attr_temp2_offset.dev_attr.attr, | ||
628 | NULL | ||
629 | }; | ||
630 | |||
631 | static const struct attribute_group tmp461_group = { | ||
632 | .attrs = tmp461_attributes, | ||
633 | }; | ||
634 | |||
635 | /* | ||
616 | * Begin non sysfs callback code (aka Real code) | 636 | * Begin non sysfs callback code (aka Real code) |
617 | */ | 637 | */ |
618 | 638 | ||
@@ -714,7 +734,7 @@ static int tmp401_probe(struct i2c_client *client, | |||
714 | const struct i2c_device_id *id) | 734 | const struct i2c_device_id *id) |
715 | { | 735 | { |
716 | static const char * const names[] = { | 736 | static const char * const names[] = { |
717 | "TMP401", "TMP411", "TMP431", "TMP432", "TMP435" | 737 | "TMP401", "TMP411", "TMP431", "TMP432", "TMP435", "TMP461" |
718 | }; | 738 | }; |
719 | struct device *dev = &client->dev; | 739 | struct device *dev = &client->dev; |
720 | struct device *hwmon_dev; | 740 | struct device *hwmon_dev; |
@@ -745,6 +765,9 @@ static int tmp401_probe(struct i2c_client *client, | |||
745 | if (data->kind == tmp432) | 765 | if (data->kind == tmp432) |
746 | data->groups[groups++] = &tmp432_group; | 766 | data->groups[groups++] = &tmp432_group; |
747 | 767 | ||
768 | if (data->kind == tmp461) | ||
769 | data->groups[groups++] = &tmp461_group; | ||
770 | |||
748 | hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name, | 771 | hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name, |
749 | data, data->groups); | 772 | data, data->groups); |
750 | if (IS_ERR(hwmon_dev)) | 773 | if (IS_ERR(hwmon_dev)) |
diff --git a/include/linux/platform_data/sht3x.h b/include/linux/platform_data/sht3x.h new file mode 100644 index 000000000000..2e5eea358194 --- /dev/null +++ b/include/linux/platform_data/sht3x.h | |||
@@ -0,0 +1,25 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2016 Sensirion AG, Switzerland | ||
3 | * Author: David Frey <david.frey@sensirion.com> | ||
4 | * Author: Pascal Sachs <pascal.sachs@sensirion.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | */ | ||
17 | |||
18 | #ifndef __SHT3X_H_ | ||
19 | #define __SHT3X_H_ | ||
20 | |||
21 | struct sht3x_platform_data { | ||
22 | bool blocking_io; | ||
23 | bool high_precision; | ||
24 | }; | ||
25 | #endif /* __SHT3X_H_ */ | ||